github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/caas/kubernetes/provider/resources/role.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package resources 5 6 import ( 7 "context" 8 "time" 9 10 "github.com/juju/errors" 11 corev1 "k8s.io/api/core/v1" 12 rbacv1 "k8s.io/api/rbac/v1" 13 k8serrors "k8s.io/apimachinery/pkg/api/errors" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 16 "k8s.io/apimachinery/pkg/runtime" 17 "k8s.io/apimachinery/pkg/types" 18 "k8s.io/client-go/kubernetes" 19 20 k8sconstants "github.com/juju/juju/caas/kubernetes/provider/constants" 21 "github.com/juju/juju/core/status" 22 ) 23 24 // Role extends the k8s role. 25 type Role struct { 26 rbacv1.Role 27 } 28 29 // NewRole creates a new role resource. 30 func NewRole(name string, namespace string, in *rbacv1.Role) *Role { 31 if in == nil { 32 in = &rbacv1.Role{} 33 } 34 in.SetName(name) 35 in.SetNamespace(namespace) 36 return &Role{*in} 37 } 38 39 // Clone returns a copy of the resource. 40 func (r *Role) Clone() Resource { 41 clone := *r 42 return &clone 43 } 44 45 // ID returns a comparable ID for the Resource 46 func (r *Role) ID() ID { 47 return ID{"Role", r.Name, r.Namespace} 48 } 49 50 // Apply patches the resource change. 51 func (r *Role) Apply(ctx context.Context, client kubernetes.Interface) error { 52 api := client.RbacV1().Roles(r.Namespace) 53 data, err := runtime.Encode(unstructured.UnstructuredJSONScheme, &r.Role) 54 if err != nil { 55 return errors.Trace(err) 56 } 57 res, err := api.Patch(ctx, r.Name, types.StrategicMergePatchType, data, metav1.PatchOptions{ 58 FieldManager: JujuFieldManager, 59 }) 60 if k8serrors.IsNotFound(err) { 61 res, err = api.Create(ctx, &r.Role, metav1.CreateOptions{ 62 FieldManager: JujuFieldManager, 63 }) 64 } 65 if k8serrors.IsConflict(err) { 66 return errors.Annotatef(errConflict, "role %q", r.Name) 67 } 68 if err != nil { 69 return errors.Trace(err) 70 } 71 r.Role = *res 72 return nil 73 } 74 75 // Get refreshes the resource. 76 func (r *Role) Get(ctx context.Context, client kubernetes.Interface) error { 77 api := client.RbacV1().Roles(r.Namespace) 78 res, err := api.Get(ctx, r.Name, metav1.GetOptions{}) 79 if k8serrors.IsNotFound(err) { 80 return errors.NewNotFound(err, "k8s") 81 } else if err != nil { 82 return errors.Trace(err) 83 } 84 r.Role = *res 85 return nil 86 } 87 88 // Delete removes the resource. 89 func (r *Role) Delete(ctx context.Context, client kubernetes.Interface) error { 90 api := client.RbacV1().Roles(r.Namespace) 91 err := api.Delete(ctx, r.Name, metav1.DeleteOptions{ 92 PropagationPolicy: k8sconstants.DefaultPropagationPolicy(), 93 }) 94 if k8serrors.IsNotFound(err) { 95 return nil 96 } else if err != nil { 97 return errors.Trace(err) 98 } 99 return nil 100 } 101 102 // Events emitted by the resource. 103 func (r *Role) Events(ctx context.Context, client kubernetes.Interface) ([]corev1.Event, error) { 104 return ListEventsForObject(ctx, client, r.Namespace, r.Name, "Role") 105 } 106 107 // ComputeStatus returns a juju status for the resource. 108 func (r *Role) ComputeStatus(_ context.Context, _ kubernetes.Interface, now time.Time) (string, status.Status, time.Time, error) { 109 if r.DeletionTimestamp != nil { 110 return "", status.Terminated, r.DeletionTimestamp.Time, nil 111 } 112 return "", status.Active, now, nil 113 }