github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/caas/kubernetes/provider/daemonset.go (about) 1 // Copyright 2020 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 apps "k8s.io/api/apps/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 ) 18 19 func (k *kubernetesClient) ensureDaemonSet(spec *apps.DaemonSet) (func(), error) { 20 cleanUp := func() {} 21 out, err := k.createDaemonSet(spec) 22 if err == nil { 23 logger.Debugf("daemon set %q created", out.GetName()) 24 cleanUp = func() { _ = k.deleteDaemonSet(out.GetName(), out.GetUID()) } 25 return cleanUp, nil 26 } 27 if !errors.IsAlreadyExists(err) { 28 return cleanUp, errors.Trace(err) 29 } 30 _, err = k.listDaemonSets(spec.GetLabels()) 31 if err != nil { 32 if errors.IsNotFound(err) { 33 // spec.Name is already used for an existing daemon set. 34 return cleanUp, errors.AlreadyExistsf("daemon set %q", spec.GetName()) 35 } 36 return cleanUp, errors.Trace(err) 37 } 38 _, err = k.updateDaemonSet(spec) 39 logger.Debugf("updating daemon set %q", spec.GetName()) 40 return cleanUp, errors.Trace(err) 41 } 42 43 func (k *kubernetesClient) createDaemonSet(spec *apps.DaemonSet) (*apps.DaemonSet, error) { 44 if k.namespace == "" { 45 return nil, errNoNamespace 46 } 47 utils.PurifyResource(spec) 48 out, err := k.client().AppsV1().DaemonSets(k.namespace).Create(context.TODO(), spec, v1.CreateOptions{}) 49 if k8serrors.IsAlreadyExists(err) { 50 return nil, errors.AlreadyExistsf("daemon set %q", spec.GetName()) 51 } 52 return out, errors.Trace(err) 53 } 54 55 func (k *kubernetesClient) getDaemonSet(name string) (*apps.DaemonSet, error) { 56 if k.namespace == "" { 57 return nil, errNoNamespace 58 } 59 out, err := k.client().AppsV1().DaemonSets(k.namespace).Get(context.TODO(), name, v1.GetOptions{}) 60 if k8serrors.IsNotFound(err) { 61 return nil, errors.NotFoundf("daemon set %q", name) 62 } 63 return out, errors.Trace(err) 64 } 65 66 func (k *kubernetesClient) updateDaemonSet(spec *apps.DaemonSet) (*apps.DaemonSet, error) { 67 if k.namespace == "" { 68 return nil, errNoNamespace 69 } 70 out, err := k.client().AppsV1().DaemonSets(k.namespace).Update(context.TODO(), spec, v1.UpdateOptions{}) 71 if k8serrors.IsNotFound(err) { 72 return nil, errors.NotFoundf("daemon set %q", spec.GetName()) 73 } 74 return out, errors.Trace(err) 75 } 76 77 func (k *kubernetesClient) deleteDaemonSet(name string, uid types.UID) error { 78 if k.namespace == "" { 79 return errNoNamespace 80 } 81 err := k.client().AppsV1().DaemonSets(k.namespace).Delete(context.TODO(), name, utils.NewPreconditionDeleteOptions(uid)) 82 if k8serrors.IsNotFound(err) { 83 return nil 84 } 85 return errors.Trace(err) 86 } 87 88 func (k *kubernetesClient) listDaemonSets(labels map[string]string) ([]apps.DaemonSet, error) { 89 if k.namespace == "" { 90 return nil, errNoNamespace 91 } 92 listOps := v1.ListOptions{ 93 LabelSelector: utils.LabelsToSelector(labels).String(), 94 } 95 out, err := k.client().AppsV1().DaemonSets(k.namespace).List(context.TODO(), listOps) 96 if err != nil { 97 return nil, errors.Trace(err) 98 } 99 if len(out.Items) == 0 { 100 return nil, errors.NotFoundf("daemon set with labels %v", labels) 101 } 102 return out.Items, nil 103 } 104 105 func (k *kubernetesClient) deleteDaemonSets(appName string) error { 106 if k.namespace == "" { 107 return errNoNamespace 108 } 109 labels := utils.LabelsForApp(appName, k.IsLegacyLabels()) 110 err := k.client().AppsV1().DaemonSets(k.namespace).DeleteCollection(context.TODO(), v1.DeleteOptions{ 111 PropagationPolicy: constants.DefaultPropagationPolicy(), 112 }, v1.ListOptions{ 113 LabelSelector: utils.LabelsToSelector(labels).String(), 114 }) 115 if k8serrors.IsNotFound(err) { 116 return nil 117 } 118 return errors.Trace(err) 119 }