(in-package :cl) (require :asdf) (asdf:operate 'asdf:load-op 'drakma) (defpackage :dns-admin (:use :cl :asdf)) (in-package :dns-admin) (defparameter *conf-file* "/etc/dns-admin/options.lisp") ;;(defparameter *endpoint* "https://dns-admin.vcpfe.vzwops.com") (defparameter *endpoint* "http://localhost:3000") (defparameter *records* '( (:name "www.meter.vzwops.com" :ref "record:cname/ZG5zLmJpbmRfY25hbWUkLl9kZWZhdWx0LmNvbS52endvcHMubWV0ZXIud3d3:www.meter.vzwops.com/default") (:name "core.meter.vzwops.com" :ref "record:cname/ZG5zLmJpbmRfY25hbWUkLl9kZWZhdWx0LmNvbS52endvcHMubWV0ZXIuY29yZQ:core.meter.vzwops.com/default") (:name "edn.meter.vzwops.com" :ref "record:cname/ZG5zLmJpbmRfY25hbWUkLl9kZWZhdWx0LmNvbS52endvcHMubWV0ZXIuZWRu:edn.meter.vzwops.com/default") (:name "capacity.meter.vzwops.com" :ref "record:cname/ZG5zLmJpbmRfY25hbWUkLl9kZWZhdWx0LmNvbS52endvcHMubWV0ZXIuY2FwYWNpdHk:capacity.meter.vzwops.com/default") (:name "capacity-edn.meter.vzwops.com" :ref "record:cname/ZG5zLmJpbmRfY25hbWUkLl9kZWZhdWx0LmNvbS52endvcHMubWV0ZXIuY2FwYWNpdHktZWRu:capacity-edn.meter.vzwops.com/default") )) (defmacro with-cookie-jar (&body body) `(let ((cookie-jar (make-instance 'drakma:cookie-jar))) ,@body)) (defun drakma-request (url cookie-jar &key (protocol :HTTP/1.1) (method :get) (content-type "application/x-www-form-urlencoded") (user-agent :firefox) (content nil) (parameters nil) (redirect t) (auto-referer t) (additional-headers nil) (connection-timeout 120) (verify nil) (proxy nil) (proxy-basic-authorization nil) (basic-authorization nil)) (drakma:http-request url :cookie-jar cookie-jar :protocol protocol :method method :content-type content-type :parameters parameters :content content :user-agent user-agent :redirect redirect :auto-referer auto-referer :connection-timeout connection-timeout :additional-headers additional-headers :verify verify :proxy proxy :proxy-basic-authorization proxy-basic-authorization :basic-authorization basic-authorization :close t)) (defun read-conf-file () "Reads the data stored in the config file at location `*conf-file*'." (when (probe-file *conf-file*) (with-open-file (input *conf-file* :direction :input) (read input)))) (defun read-creds () (let ((conf (read-conf-file)) username password) (setf username (getf conf :username)) (setf password (getf conf :password)) (values username password))) (defun do-failover (target) (let ((retcode 0) (retmsg "OK")) (handler-case (multiple-value-bind (username password) (read-creds) (with-cookie-jar (loop for record in *records* do (format t "Setting ~a to ~a~%" (getf record :name) target) (multiple-value-bind (body status-code headers uri stream must-close reason) (drakma-request (format nil "~a/dns/api/modify/post" *endpoint*) cookie-jar :method :post :basic-authorization `(,username ,password) :parameters `(("recordtype" . "cname") ("ref" . ,(getf record :ref)) ("name" . ,(getf record :name)) ("canonical" . ,(format nil "openbook-lb-vip-master-~a.meter.vzwops.com" target)))) (declare (ignore headers uri stream must-close reason)) (cond ((>= status-code 300) (setf retcode 1) (setf retmsg (format nil "Error response from dns-admin.~%Endpoint = [~a]~%Response = [~a]" (format nil "~a/dns/modify/submit" *endpoint*) body))) (t (format t "~a~%" body))))))) (error (e) (progn (setf retcode 1) (setf retmsg (format nil "An error occurred. Error: ~a" e))))) (values retcode retmsg))) (defun run (&optional target-override) (let ((target (or target-override (car (last sb-ext:*posix-argv*)))) (retcode 0) (retmsg "OK")) (cond ((not (find target '("rocklin" "twinsburg") :test 'string=)) (setf retcode 1) (setf retmsg "Invalid target specified. Must be 'rocklin' or 'twinsburg'.")) (t (multiple-value-bind (code msg) (do-failover target) (setf retcode code) (setf retmsg msg)))) (format t "~a" retmsg) (sb-ext:exit :code retcode)))