init
This commit is contained in:
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
*.abcl
|
||||
*.fasl
|
||||
*.dx32fsl
|
||||
*.dx64fsl
|
||||
*.lx32fsl
|
||||
*.lx64fsl
|
||||
*.x86f
|
||||
*~
|
||||
.#*
|
||||
12
README.org
Normal file
12
README.org
Normal file
@@ -0,0 +1,12 @@
|
||||
* K8splayground
|
||||
|
||||
Playing around with using CLOG to set up kind clusters for teaching
|
||||
different techniques for canarying.
|
||||
|
||||
** Author
|
||||
|
||||
+ Adam Mohammed (adam@fixergrid.net)
|
||||
|
||||
** Copyright
|
||||
|
||||
Copyright (c) 2023 Adam Mohammed (adam@fixergrid.net)
|
||||
21
k8splayground.asd
Normal file
21
k8splayground.asd
Normal file
@@ -0,0 +1,21 @@
|
||||
(defsystem "k8splayground"
|
||||
:version "0.1.0"
|
||||
:author "Adam Mohammed"
|
||||
:license ""
|
||||
:depends-on ("yason")
|
||||
:components ((:module "src"
|
||||
:components
|
||||
((:file "main"))))
|
||||
:description ""
|
||||
:in-order-to ((test-op (test-op "k8splayground/tests"))))
|
||||
|
||||
(defsystem "k8splayground/tests"
|
||||
:author "Adam Mohammed"
|
||||
:license ""
|
||||
:depends-on ("k8splayground"
|
||||
"rove")
|
||||
:components ((:module "tests"
|
||||
:components
|
||||
((:file "main"))))
|
||||
:description "Test system for k8splayground"
|
||||
:perform (test-op (op c) (symbol-call :rove :run c)))
|
||||
116
src/main.lisp
Normal file
116
src/main.lisp
Normal file
@@ -0,0 +1,116 @@
|
||||
(defpackage k8splayground
|
||||
(:use :cl)
|
||||
(:export :create-kube-cluster)
|
||||
(:import-from #:yason
|
||||
#:parse)
|
||||
(:import-from #:uiop
|
||||
#:run-program))
|
||||
|
||||
|
||||
(in-package :k8splayground)
|
||||
|
||||
(defclass demo-cluster ()
|
||||
((name :accessor cluster-name
|
||||
:documentation "name of the k8s cluster.")
|
||||
(deployments :accessor k8s-deployments
|
||||
:initform '()
|
||||
:documentation "currently active deployments")
|
||||
(services :accessor k8s-services
|
||||
:initform '()
|
||||
:documentation "currently active services")))
|
||||
|
||||
(defun kind-executable ()
|
||||
"Determine the location of the `kind` executable"
|
||||
"/home/adammo/go/bin/kind")
|
||||
|
||||
(defun kubectl-executable ()
|
||||
"Location for kubectl"
|
||||
"/usr/local/bin/kubectl")
|
||||
|
||||
(defun initial-deployment-files ()
|
||||
"Files to deploy when the cluster first starts."
|
||||
"/home/adammo/repos/k8splayground/src/tutorial0/deployment.yaml")
|
||||
|
||||
(defun create-kube-cluster (name)
|
||||
(let ((result (nth-value 2 (run-program (create-kube-cluster-command name) :output *STANDARD-OUTPUT*))))
|
||||
(= 0 result)))
|
||||
|
||||
(defun delete-kube-cluster (cluster)
|
||||
(let ((result (nth-value 2 (run-program (delete-kube-cluster-command cluster) :output *STANDARD-OUTPUT*))))
|
||||
(= 0 result)))
|
||||
|
||||
(defun create-kube-cluster-command (name)
|
||||
"Create the command to create the cluster."
|
||||
(list (kind-executable) "create" "cluster" "--name" name))
|
||||
|
||||
(defun delete-kube-cluster-command (cluster)
|
||||
"Lists the existing kube clusters."
|
||||
(list (kind-executable) "delete" "cluster" "--name" (cluster-name cluster)))
|
||||
|
||||
|
||||
(defun update-cluster (cluster)
|
||||
"Fetches the latest state for the cluster."
|
||||
(progn
|
||||
(update-cluster-deployments cluster)
|
||||
(update-cluster-services cluster)
|
||||
cluster))
|
||||
|
||||
|
||||
(defun fetch-resources (resource)
|
||||
(let* ((api-response (run-program (list "/usr/local/bin/kubectl" "get" resource "-o" "json") :output :string))
|
||||
(json-resp (parse api-response))
|
||||
(resources (gethash "items" json-resp)))
|
||||
(loop for r in resources
|
||||
collect (gethash "name" (gethash "metadata" r)))))
|
||||
|
||||
(defun update-cluster-deployments (cluster)
|
||||
(let ((active-deployments (fetch-resources "deployments")))
|
||||
(setf (k8s-deployments cluster) active-deployments)))
|
||||
|
||||
(defun update-cluster-services (cluster)
|
||||
(let ((active-services (fetch-resources "services")))
|
||||
(setf (k8s-services cluster) active-services)))
|
||||
|
||||
(defun bring-up-environment (name)
|
||||
"Starts a kind cluster and applies yaml and updates the cluster-state"
|
||||
(let ((cluster (make-instance 'demo-cluster))
|
||||
(kcname (format nil "kind-~A" name))
|
||||
(output *STANDARD-OUTPUT*))
|
||||
(format output "Creating cluster ~A... This may take a few seconds.~%" name)
|
||||
(setf (cluster-name cluster) name)
|
||||
(create-kube-cluster name)
|
||||
(format output "Switching Kube context.~%")
|
||||
(run-program `(,(kubectl-executable) "config" "use-context" ,kcname) :output output)
|
||||
(format output "Creating K8s resources.~%")
|
||||
(run-program `(,(kubectl-executable) "apply" "-f" ,(initial-deployment-files)) :ouptut output)
|
||||
(format output "Refreshing cluster state.~%")
|
||||
(update-cluster cluster)))
|
||||
|
||||
(defun update-drop-list (drop-list items)
|
||||
(loop for i in items
|
||||
do (clog:create-list-item (clog-drop-list:drop-root drop-list) :content i)))
|
||||
|
||||
(defun update-cluster-ui (dep-drop svc-drop cluster)
|
||||
(progn
|
||||
(update-cluster cluster)
|
||||
(update-drop-list dep-drop (k8s-deployments cluster))
|
||||
(update-drop-list svc-drop (k8s-services cluster))))
|
||||
|
||||
(defun on-new-window (body)
|
||||
(let ((active-name (clog:create-child body (format nil "<h1>Cluster Name: kind-~A</h1>" (cluster-name *ACTIVE-CLUSTER*))))
|
||||
(dep-drop (clog-drop-list:create-drop-list body :content "Deployments"))
|
||||
(svc-drop (clog-drop-list:create-drop-list body :content "Services"))
|
||||
(refresh-btn (clog:create-button body :content "⟳ Refresh")))
|
||||
(declare (ignore active-name))
|
||||
(setf (clog:background-color body) "#3B4252")
|
||||
(setf (clog:color body) "#ECEFF4")
|
||||
(update-cluster-ui dep-drop svc-drop *ACTIVE-CLUSTER*)
|
||||
(clog:set-on-click refresh-btn (lambda (obj)
|
||||
(declare (ignore obj))
|
||||
(let ((new-dep-drop (clog-drop-list:create-drop-list body :auto-place nil :content "Deployments"))
|
||||
(new-svc-drop (clog-drop-list:create-drop-list body :auto-place nil :content "Services")))
|
||||
(update-cluster-ui new-dep-drop new-svc-drop *ACTIVE-CLUSTER*)
|
||||
(clog:replace-element dep-drop new-dep-drop)
|
||||
(setf dep-drop new-dep-drop)
|
||||
(clog:replace-element svc-drop new-svc-drop)
|
||||
(setf svc-drop new-svc-drop))))))
|
||||
41
src/tutorial0/deployment.yaml
Normal file
41
src/tutorial0/deployment.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: demo-echo-server
|
||||
name: demo-echo-server
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: demo-echo-server
|
||||
strategy: {}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: demo-echo-server
|
||||
spec:
|
||||
containers:
|
||||
- image: docker.io/hashicorp/http-echo
|
||||
name: echo-server
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
command:
|
||||
- /http-echo
|
||||
- -text=$(POD_NAME)
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: demo-echo-service
|
||||
spec:
|
||||
selector:
|
||||
app: demo-echo-server
|
||||
ports:
|
||||
- name: web
|
||||
port: 8080
|
||||
targetPort: 5678
|
||||
12
tests/main.lisp
Normal file
12
tests/main.lisp
Normal file
@@ -0,0 +1,12 @@
|
||||
(defpackage k8splayground/tests/main
|
||||
(:use :cl
|
||||
:k8splayground
|
||||
:rove))
|
||||
(in-package :k8splayground/tests/main)
|
||||
|
||||
;; NOTE: To run this test file, execute `(asdf:test-system :k8splayground)' in your Lisp.
|
||||
|
||||
(deftest make-k8s-cluster
|
||||
(testing "should create a k8s-cluster"
|
||||
(let ((cluster (k8smake-k8s-cluster)))
|
||||
(ok (= "test" (k8splayground:cluster-name cluster))))))
|
||||
Reference in New Issue
Block a user