(ns kube-deploy.blocks (:require [clojure.java.io :as io] [kube-deploy.helpers :as lkh] [lambdakube.core :as lk])) (def resources-mini {:requests {:cpu "100m" :memory "64Mi"} :limits {:cpu "200m" :memory "256Mi"}}) (def resources-small {:requests {:cpu "100m" :memory "100Mi"} :limits {:cpu "200m" :memory "400Mi"}}) (def resources-medium {:requests {:cpu "100m" :memory "500Mi"} :limits {:cpu "200m" :memory "1Gi"}}) (defn mosquitto-mqtt [kube-injector] (-> kube-injector (lk/rule :mosquitto-master-rule [] (fn [] (-> (lk/pod :mosquitto-master {:app :footprint :role :master :env :production :tier :database}) (lk/add-container :mosquitto "eclipse-mosquitto" (-> {} (lkh/add-to-spec :resources resources-mini) (lkh/add-readiness-probe-cmd ["pg_isready"]) (lkh/add-liveness-probe-cmd ["pg_isready"]) (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]))) (lk/deployment 1) (lk/expose-cluster-ip :mosquitto-master (lk/port :mosquitto :mosquitto 1883 1883))))))) (defn test-block [kube-injector] (-> kube-injector (lk/rule :test-rule [] (fn [] (-> (lk/pod :test-pod {:app :test}) (lk/add-container :busybox "busybox" (-> {} (lkh/add-to-spec :resources resources-mini) (lkh/add-to-spec :command ["sleep 3600"]) (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]))) (lk/deployment 1)))))) (defn ldap ([kube-injector] (ldap kube-injector {})) ([kube-injector settings] (let [app-name (get settings :app-name "ldap") app-pod-name (str app-name "-pod") app-rule-name (keyword (str app-name "-rule")) app-container-name (keyword (str app-name "-container")) app-service-name (keyword (str app-name "-service")) app-labels (get settings :labels {:app "ldap"}) app-image (get settings :image "osixia/openldap:1.2.0") app-resources (get settings :resources resources-small)] (-> kube-injector (lk/rule app-rule-name [] (fn [] (-> (lk/pod app-pod-name app-labels) (lk/add-container app-container-name app-image (-> {} (lkh/add-to-spec :resources app-resources))) (lk/deployment 1) (lk/expose-cluster-ip app-service-name (lk/port app-container-name :ldap 389 389))))))))) #_(defn aq-schedular ([kube-injector] (aq-schedular kube-injector {})) ([kube-injector settings]) (let [app-name (get settings :app-name "aq-schedular") app-pod-name (str app-name "-pod") app-rule-name (keyword (str app-name "-rule")) app-container-name (keyword (str app-name "-container")) app-service-name (keyword (str app-name "-service")) app-labels (get settings :labels {:app "aq-schedular"}) app-image (get settings :image "aq-schedular") app-resources (get settings :resources resources-small)] (lk/rule :footprint-aqscheduler-master [] (fn [] (-> (lk/pod :footprint-scheduler {:app :footprint :env :production :tier :scheduler} {:imagePullSecrets [{:name "docker-registry"}]}) (lk/add-container :scheduler app-image (-> {} (lkh/add-to-spec :imagePullPolicy "Always") (lkh/add-to-spec :resources resources-mini) (lkh/add-to-spec :command ["/usr/local/bin/dramatiq_apscheduler" "/app/tasks.yml" "--debug"]) (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]))) (add-volume "scheduler-config" {:configMap {:name "scheduler-tasks"}} {:scheduler {:name "scheduler-config" :mountPath "/app/tasks.yml" :subPath "tasks.yml"}}) (lk/deployment 1)))))) (defn redis ([kube-injector] (redis kube-injector {})) ([kube-injector settings] (let [app-name (get settings :app-name "redis") app-pod-name (str app-name "-pod") app-rule-name (keyword (str app-name "-rule")) app-container-name (keyword (str app-name "-container")) app-service-name (keyword (str app-name "-service")) app-labels (get settings :labels {:app "redis"}) app-image (get settings :image "redis") app-resources (get settings :resources resources-small)] (-> kube-injector (lk/rule app-rule-name [] (fn [] (-> (lk/pod app-pod-name app-labels) (lk/add-container app-container-name app-image (-> {} (lkh/add-to-spec :resources app-resources) (lkh/add-readiness-probe-cmd ["redis-cli" "--version"]) (lkh/add-liveness-probe-cmd ["redis-cli" "--version"]))) (lk/deployment 1) (lk/expose-cluster-ip app-service-name (lk/port app-container-name :redis 6379 6379))))))))) (defn rabbitmq ([kube-injector] (rabbitmq kube-injector {})) ([kube-injector settings] (let [app-name (get settings :app-name "postgres") app-pod-name (str app-name "-pod") app-rule-name (keyword (str app-name "-rule")) app-container-name (keyword (str app-name "-container")) app-service-name (keyword (str app-name "-service")) app-dependencies (get settings :dependencies []) app-containers 1 app-labels (get settings :labels {:app "postgres"}) app-image (get settings :image "postgres") app-resources (get settings :resources resources-small)] (-> kube-injector (lk/rule app-rule-name [] (fn [] (-> (lk/pod app-pod-name app-labels) (lk/add-container app-container-name app-image (-> {} (lkh/add-to-spec :resources app-resources) (lkh/add-liveness-probe-cmd ["rabbitmq-diagnostics" "ping" "-q"]))) (lk/deployment app-containers) (lk/expose-cluster-ip app-service-name (lk/port app-container-name :rabbit 5672 5672))))))))) (defn postgres ([kube-injector] (postgres kube-injector {})) ([kube-injector settings] (let [app-name (get settings :app-name "postgres") app-pod-name (str app-name "-pod") app-rule-name (keyword (str app-name "-rule")) app-container-name (keyword (str app-name "-container")) app-service-name (keyword (str app-name "-service")) app-dependencies (get settings :dependencies []) app-containers 1 app-labels (get settings :labels {:app "postgres"}) app-image (get settings :image "postgres") app-resources (get settings :resources resources-small)] (-> kube-injector (lk/rule app-rule-name [] (fn [] (-> (lk/pod app-pod-name app-labels) (lk/add-container app-container-name app-image (-> {} (lkh/add-to-spec :resources app-resources) (lkh/add-readiness-probe-cmd ["pg_isready"]) (lkh/add-liveness-probe-cmd ["pg_isready"]) (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]))) (lk/stateful-set 1) (lk/add-volume-claim-template :postgres-volume {:accessModes ["ReadWriteOnce"] :resources {:requests {:storage "1Gi"}}} {:bar "/var/lib/postgresql/data"}) (lk/expose-cluster-ip app-service-name (lk/port app-container-name :postgres 5432 5432))))))))) (defn gunicorn ([kube-injector] (gunicorn kube-injector {})) ([kube-injector settings] (let [app-name (get settings :app-name "gunicorn") app-pod-name (keyword (str app-name "-pod")) app-rule-name (str app-name "-rule") app-gunicorn-container-name (keyword (str app-name "-container")) app-nginx-container-name (keyword (str app-name "-nginx-container")) app-nginx-pod-name (str app-name "-pod") app-annotations (get settings :annotations {}) app-dependencies [] ;(get settings :dependencies []) app-containers 1 app-labels (get settings :labels {:app app-name}) app-image (get settings :image "python:3") app-resources (get settings :resources resources-small) app-service-name "gunicorn-service" app-nginx-service-name "nginx-service" app-serve-static (get settings :serve-static true)] (-> kube-injector (lk/rule (keyword (str app-name "-rule")) app-dependencies (fn [] (as-> (lk/pod app-pod-name app-labels {:imagePullSecrets [{:name "docker-registry"}]}) pod ; Add containers to the pod, one for frontend assets and one for backend (lk/add-annotation pod :linkerd.io/inject "enabled") (lk/add-container pod app-gunicorn-container-name app-image {:resources app-resources :imagePullPolicy "Always" :command (get settings :command ["/usr/bin/gunicorn" "wsgi" "--workers" "2" "-k" "gevent" "--worker-connections" "100" "--max-requests" "300" "--keep-alive" "1000" "-b" "0.0.0.0:5000" "--chdir=/app"]) ;:ports [{:containerPort 5000 :name "gunicorn-port"}] :envFrom [{:secretRef {:name "environment"}}] #_(lkh/add-readiness-probe-cmd ["wget" "127.0.0.1:5000"]) #_(lkh/add-liveness-probe-cmd ["wget" "127.0.0.1:5000"])}) #_(lk/add-init-container pod (keyword (str app-name "-init-migrations")) app-image (-> {} (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]) (lkh/add-to-spec :command ["./manage.py" "migrate"]))) (if (nil? app-serve-static) pod (-> pod (lk/add-container app-nginx-container-name "nginx:alpine" (-> {} (lkh/add-to-spec :resources resources-mini) (lkh/add-to-spec :imagePullPolicy "Always") ;(lkh/add-to-spec :ports [{:containerPort 80 :name "nginx-port"}]) #_(lkh/add-readiness-probe-get "127.0.0.1/static/images/favicon.ico" 80) (lkh/add-liveness-probe-get "http://127.0.0.1/static/admin/css/responsive.css" 80))) (lk/add-init-container (keyword (str app-name "-init-static-files")) app-image (-> {} (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]) (lkh/add-to-spec :command ["./manage.py" "collectstatic" "--no-input"]))) (lk/add-volume :static-files {:emptyDir {}} {app-nginx-container-name "/usr/share/nginx/html/static/" app-gunicorn-container-name "/app/staticfiles"}))) ; order does matter here, deployment after initcontainers ;(lku/wait-for-service-port postgres :postgres) ;(lku/wait-for-service-port redis :redis) ; wrap in a deployment (lk/deployment pod 1) (if (nil? app-serve-static) pod (lk/expose-cluster-ip pod app-nginx-service-name (lk/port app-nginx-container-name :nginx-port 80 80))) (lk/expose-cluster-ip pod app-service-name (lk/port app-gunicorn-container-name :gunicorn-port 5000 5000))))) ; inject the ingress required to serve to gunicorn app (lk/rule (keyword (str app-name "-ingress-rule")) [] (fn [] (let [ingress-name (str app-name "-ingress") paths []] (-> (lkh/ingress ingress-name {:app :nginx-ingress :env :production :tier :ingress}) (lkh/add-spec :tls [{:hosts [(:ingress-host settings)] :secretName (str app-name "-tls")}]) (lkh/add-spec :rules [{:host (:ingress-host settings) :http {:paths (remove nil? [{:path "/" :backend {:serviceName app-service-name :servicePort 5000}} (when app-serve-static {:path "/static/" :backend {:serviceName app-nginx-service-name :servicePort 80}})])}}]) (lk/add-annotation :kubernetes.io/tls-acme "true") ; (lk/add-annotation :certmanager.k8s.io/cluster-issuer "letsencrypt-production") (lk/add-annotation :kubernetes.io/ingress.class "nginx"))))))))) (defn django-huey ([kube-injector] (gunicorn kube-injector {})) ([kube-injector settings] (let [app-name (get settings :app-name "huey") app-pod-name (keyword (str app-name "-pod")) app-rule-name (keyword (str app-name "-rule")) app-container-name (keyword (str app-name "-container")) app-dependencies [] ;(get settings :dependencies []) app-containers 1 app-labels (get settings :labels {:app app-name}) app-image (get settings :image "python:3") app-resources (get settings :resources resources-small)] (-> kube-injector (lk/rule app-rule-name [] (fn [] (-> (lk/pod app-pod-name {:app :hackspace :env :stage :role :master :tier :queue} {:imagePullSecrets [{:name "docker-registry"}]}) (lk/add-container app-container-name app-image (-> {} (lkh/add-to-spec :resources resources-small) (lkh/add-to-spec :command ["/app/manage.py" "run_huey"]) (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]))) (lk/deployment 2)))))))) ;; (into [] (flatten ["c" [:b 2]] )) ;; ;; (bulk-add ) ;; ;; (apply lk/add-annotation (list ["a"] (first {:a 1 :b 2}))) ;; ;; (defn bulk-add [func obj values] ;; ;; (println (first func)) ;; ;; (if (= 0 (count values)) ;; ;; (recur ;; ;; func ;; ;; (apply func (into [] (flatten [obj (first values)]))) ;; ;; (rest values)) ;; ;; obj)) ;; ;; (as-> (lk/pod :foo {}) ;; ;; pod ;; ;; (bulk-add lk/add-annotation pod {:a 1 :b 2})) ;; ;(apply lk/add-annotation pod (first {:a 1 :b 2}))