github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/caas/kubernetes/provider/configmap.go (about) 1 // Copyright 2019 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provider 5 6 import ( 7 "context" 8 9 "github.com/juju/errors" 10 core "k8s.io/api/core/v1" 11 k8serrors "k8s.io/apimachinery/pkg/api/errors" 12 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 "k8s.io/apimachinery/pkg/types" 14 15 "github.com/juju/juju/caas/kubernetes/provider/constants" 16 "github.com/juju/juju/caas/kubernetes/provider/utils" 17 "github.com/juju/juju/caas/specs" 18 ) 19 20 func (k *kubernetesClient) getConfigMapLabels(appName string) map[string]string { 21 return utils.LabelsForApp(appName, k.IsLegacyLabels()) 22 } 23 24 func (k *kubernetesClient) ensureConfigMaps( 25 appName string, 26 annotations map[string]string, 27 cms map[string]specs.ConfigMap, 28 ) (cleanUps []func(), _ error) { 29 if k.namespace == "" { 30 return nil, errNoNamespace 31 } 32 for name, v := range cms { 33 spec := &core.ConfigMap{ 34 ObjectMeta: v1.ObjectMeta{ 35 Name: name, 36 Namespace: k.namespace, 37 Labels: k.getConfigMapLabels(appName), 38 Annotations: annotations, 39 }, 40 Data: v, 41 } 42 cmCleanup, err := k.ensureConfigMap(spec) 43 cleanUps = append(cleanUps, cmCleanup) 44 if err != nil { 45 return cleanUps, errors.Trace(err) 46 } 47 } 48 return cleanUps, nil 49 } 50 51 // ensureConfigMapLegacy is a tmp fix for upgrading configmap(no proper labels) created in 2.6. 52 // TODO(caas): remove this and use "updateConfigMap" once `environupgrader` supports CaaS models. 53 func (k *kubernetesClient) ensureConfigMapLegacy(cm *core.ConfigMap) (cleanUp func(), err error) { 54 cleanUp = func() {} 55 if k.namespace == "" { 56 return cleanUp, errNoNamespace 57 } 58 api := k.client().CoreV1().ConfigMaps(k.namespace) 59 _, err = api.Update(context.TODO(), cm, v1.UpdateOptions{}) 60 if k8serrors.IsNotFound(err) { 61 var out *core.ConfigMap 62 if out, err = api.Create(context.TODO(), cm, v1.CreateOptions{}); err == nil { 63 logger.Debugf("configmap %q created", out.GetName()) 64 cleanUp = func() { _ = k.deleteConfigMap(out.GetName(), out.GetUID()) } 65 return cleanUp, nil 66 } 67 } 68 return cleanUp, errors.Trace(err) 69 } 70 71 // ensureConfigMap ensures a ConfigMap resource. 72 func (k *kubernetesClient) ensureConfigMap(cm *core.ConfigMap) (func(), error) { 73 cleanUp := func() {} 74 out, err := k.createConfigMap(cm) 75 if err == nil { 76 logger.Debugf("configmap %q created", out.GetName()) 77 cleanUp = func() { _ = k.deleteConfigMap(out.GetName(), out.GetUID()) } 78 return cleanUp, nil 79 } 80 if !errors.IsAlreadyExists(err) { 81 return cleanUp, errors.Trace(err) 82 } 83 err = k.updateConfigMap(cm) 84 logger.Debugf("updating configmap %q", cm.GetName()) 85 return cleanUp, errors.Trace(err) 86 } 87 88 func (k *kubernetesClient) updateConfigMap(cm *core.ConfigMap) error { 89 if k.namespace == "" { 90 return errNoNamespace 91 } 92 _, err := k.client().CoreV1().ConfigMaps(k.namespace).Update(context.TODO(), cm, v1.UpdateOptions{}) 93 if k8serrors.IsNotFound(err) { 94 return errors.NotFoundf("configmap %q", cm.GetName()) 95 } 96 return errors.Trace(err) 97 } 98 99 // getConfigMap returns a ConfigMap resource. 100 func (k *kubernetesClient) getConfigMap(name string) (*core.ConfigMap, error) { 101 if k.namespace == "" { 102 return nil, errNoNamespace 103 } 104 cm, err := k.client().CoreV1().ConfigMaps(k.namespace).Get(context.TODO(), name, v1.GetOptions{}) 105 if err != nil { 106 if k8serrors.IsNotFound(err) { 107 return nil, errors.NotFoundf("configmap %q", name) 108 } 109 return nil, errors.Trace(err) 110 } 111 return cm, nil 112 } 113 114 // createConfigMap creates a ConfigMap resource. 115 func (k *kubernetesClient) createConfigMap(cm *core.ConfigMap) (*core.ConfigMap, error) { 116 if k.namespace == "" { 117 return nil, errNoNamespace 118 } 119 utils.PurifyResource(cm) 120 out, err := k.client().CoreV1().ConfigMaps(k.namespace).Create(context.TODO(), cm, v1.CreateOptions{}) 121 if k8serrors.IsAlreadyExists(err) { 122 return nil, errors.AlreadyExistsf("configmap %q", cm.GetName()) 123 } 124 return out, errors.Trace(err) 125 } 126 127 // deleteConfigMap deletes a ConfigMap resource. 128 func (k *kubernetesClient) deleteConfigMap(name string, uid types.UID) error { 129 if k.namespace == "" { 130 return errNoNamespace 131 } 132 err := k.client().CoreV1().ConfigMaps(k.namespace).Delete(context.TODO(), name, utils.NewPreconditionDeleteOptions(uid)) 133 if k8serrors.IsNotFound(err) { 134 return nil 135 } 136 return errors.Trace(err) 137 } 138 139 func (k *kubernetesClient) deleteConfigMaps(appName string) error { 140 if k.namespace == "" { 141 return errNoNamespace 142 } 143 err := k.client().CoreV1().ConfigMaps(k.namespace).DeleteCollection(context.TODO(), v1.DeleteOptions{ 144 PropagationPolicy: constants.DefaultPropagationPolicy(), 145 }, v1.ListOptions{ 146 LabelSelector: utils.LabelsToSelector(k.getConfigMapLabels(appName)).String(), 147 }) 148 if k8serrors.IsNotFound(err) { 149 return nil 150 } 151 return errors.Trace(err) 152 }