From 1d00fee0c35328d2c1357e513d8a9c4a6b06fbc4 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 17 Jun 2019 12:07:15 +1000 Subject: [PATCH] Full support for configmaps --- README.md | 2 +- config-map.go | 33 +++++++++++++++++++++++++++++---- deployment.go | 8 ++++---- plugin.go | 6 +++--- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index ee9a0f1..1159485 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Deployment config files are first interpreted by **aymerick/raymond** ([handleba ## Config maps from files -In this case, you can create a template just like deployment.yaml but you can provide a file path (relative to the repo's root) in the plugin setting `configmap_file`. +In this case, you can create a template just like deployment.yaml but you can provide a file path (relative to the repo's root) in the plugin setting `configmap_file`. (Currently only accepts utf-8 encoded data). Like deployments, this will both create new or update existing configmaps (based on the configmap name). #### Adding a service account to Kubernetes that can manage deployments See [example/Role.yaml](example/Role.yaml), [example/ServiceAccount.yaml](example/ServiceAccount.yaml), [example/RoleBinding.yaml](example/RoleBinding.yaml). diff --git a/config-map.go b/config-map.go index 3253fa7..e682a03 100644 --- a/config-map.go +++ b/config-map.go @@ -3,21 +3,46 @@ package main import ( "io/ioutil" "log" + "path/filepath" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) // ApplyConfigMapFromFile -- Updates given deployment in Kubernetes func ApplyConfigMapFromFile(clientset *kubernetes.Clientset, namespace string, configmap *corev1.ConfigMap, path string) error { - log.Printf("Reading contents of %s", path) + log.Printf("📦 Reading contents of %s", path) + _, filename := filepath.Split(path) fileContents, err := ioutil.ReadFile(path) if err != nil { return err } - configMapData := make(map[string][]byte) - configMapData[path] = fileContents - configmap.BinaryData = configMapData + configMapData := make(map[string]string) + configMapData[filename] = string(fileContents) + configmap.Data = configMapData + // Check if deployment exists + deploymentExists, err := configMapExists(clientset, namespace, configmap.Name) + if deploymentExists { + log.Printf("📦 Found existing deployment. Updating %s.", configmap.Name) + _, err = clientset.CoreV1().ConfigMaps(namespace).Update(configmap) + return err + } _, err = clientset.CoreV1().ConfigMaps(namespace).Create(configmap) return err } + +// configMapExists -- Updates given deployment in Kubernetes +func configMapExists(clientset *kubernetes.Clientset, namespace string, name string) (bool, error) { + _, err := clientset.CoreV1().ConfigMaps(namespace).Get(name, meta.GetOptions{}) + if err != nil { + // TODO: Only conver to StatusError if the error is in fact a status error + statusError, ok := err.(*errors.StatusError) + if ok == true && statusError.Status().Code == 404 { + return false, nil + } + return false, err + } + return true, nil +} diff --git a/deployment.go b/deployment.go index a5e1ab8..c6eed47 100644 --- a/deployment.go +++ b/deployment.go @@ -9,7 +9,7 @@ import ( // CreateOrUpdateDeployment -- Checks if deployment already exists, updates if it does, creates if it doesn't func CreateOrUpdateDeployment(clientset *kubernetes.Clientset, namespace string, deployment *appv1.Deployment) error { - deploymentExists, err := DeploymentExists(clientset, namespace, deployment.Name) + deploymentExists, err := deploymentExists(clientset, namespace, deployment.Name) if deploymentExists { // log.Printf("📦 Found existing deployment. Updating.\n%s\n", depYaml) _, err = clientset.AppsV1().Deployments(namespace).Update(deployment) @@ -19,9 +19,9 @@ func CreateOrUpdateDeployment(clientset *kubernetes.Clientset, namespace string, return err } -// DeploymentExists -- Updates given deployment in Kubernetes -func DeploymentExists(clientset *kubernetes.Clientset, namespace string, deploymentName string) (bool, error) { - _, err := clientset.AppsV1().Deployments(namespace).Get(deploymentName, meta.GetOptions{}) +// deploymentExists -- Updates given deployment in Kubernetes +func deploymentExists(clientset *kubernetes.Clientset, namespace string, name string) (bool, error) { + _, err := clientset.AppsV1().Deployments(namespace).Get(name, meta.GetOptions{}) if err != nil { // TODO: Only conver to StatusError if the error is in fact a status error statusError, ok := err.(*errors.StatusError) diff --git a/plugin.go b/plugin.go index 9f187f4..05d7477 100644 --- a/plugin.go +++ b/plugin.go @@ -83,13 +83,13 @@ func (p Plugin) Exec() error { } switch o := kubernetesObject.(type) { case *appv1.Deployment: - log.Print("Found Deployment") + log.Print("📦 Resource type: Deployment") err = CreateOrUpdateDeployment(clientset, p.KubeConfig.Namespace, o) case *corev1.ConfigMap: - log.Print("Found ConfigMap") + log.Print("📦 Resource type: ConfigMap") err = ApplyConfigMapFromFile(clientset, p.KubeConfig.Namespace, o, p.ConfigMapFile) default: - err = errors.New("⛔️ This plugin doesn't support that kind of Kubernetes object") + err = errors.New("⛔️ This plugin doesn't support that resource type") return err } return err