From cfbfd38ae4e1916f3fd0b0c3443d6cd9e79a30f0 Mon Sep 17 00:00:00 2001 From: Jean-Marc ANDRE Date: Wed, 9 Dec 2020 23:15:15 +0100 Subject: [PATCH] Create/Delete RBAC. Restore deployment to original state when BackupConfiguration is deleted --- api/v1alpha1/backupconfiguration_types.go | 5 +- api/v1alpha1/zz_generated.deepcopy.go | 5 - controllers/backupconfiguration_controller.go | 204 ++++++++++------ go.mod | 14 +- main.go | 16 +- pkg/rbac/backupconfiguration.go | 231 ++++++++++++++++++ pkg/utils/root.go | 20 ++ test/00-setup.yaml | 80 ------ 8 files changed, 398 insertions(+), 177 deletions(-) create mode 100644 pkg/rbac/backupconfiguration.go create mode 100644 pkg/utils/root.go diff --git a/api/v1alpha1/backupconfiguration_types.go b/api/v1alpha1/backupconfiguration_types.go index fae0698..f1ef09b 100644 --- a/api/v1alpha1/backupconfiguration_types.go +++ b/api/v1alpha1/backupconfiguration_types.go @@ -48,8 +48,6 @@ type BackupConfigurationSpec struct { // +optional VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"` Paths []string `json:"paths"` - // +optional - Suspend *bool `json:"suspend,omitempty"` } // BackupConfigurationStatus defines the observed state of BackupConfiguration @@ -62,10 +60,9 @@ type BackupConfigurationStatus struct { ActiveSidecar bool `json:"activeSidecar"` } +// BackupConfiguration is the Schema for the backupconfigurations API // +kubebuilder:object:root=true // +kubebuilder:subresource:status - -// BackupConfiguration is the Schema for the backupconfigurations API type BackupConfiguration struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 175d7b0..1e87d85 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -118,11 +118,6 @@ func (in *BackupConfigurationSpec) DeepCopyInto(out *BackupConfigurationSpec) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.Suspend != nil { - in, out := &in.Suspend, &out.Suspend - *out = new(bool) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupConfigurationSpec. diff --git a/controllers/backupconfiguration_controller.go b/controllers/backupconfiguration_controller.go index 53560d5..369e61f 100644 --- a/controllers/backupconfiguration_controller.go +++ b/controllers/backupconfiguration_controller.go @@ -19,17 +19,20 @@ package controllers import ( "context" + formolrbac "github.com/desmo999r/formol/pkg/rbac" + formolutils "github.com/desmo999r/formol/pkg/utils" "github.com/go-logr/logr" appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" kbatch_beta1 "k8s.io/api/batch/v1beta1" corev1 "k8s.io/api/core/v1" - // rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/predicate" formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1" ) @@ -41,6 +44,16 @@ type BackupConfigurationReconciler struct { Scheme *runtime.Scheme } +func (r *BackupConfigurationReconciler) getDeployment(namespace string, name string) (*appsv1.Deployment, error) { + + deployment := &appsv1.Deployment{} + err := r.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: name, + }, deployment) + return deployment, err +} + // +kubebuilder:rbac:groups=formol.desmojim.fr,resources=backupconfigurations,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=formol.desmojim.fr,resources=backupconfigurations/status,verbs=get;update;patch // +kubebuilder:rbac:groups=formol.desmojim.fr,resources=repoes,verbs=get;list;watch @@ -49,23 +62,65 @@ type BackupConfigurationReconciler struct { // +kubebuilder:rbac:groups=batch,resources=cronjobs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=batch,resources=cronjobs/status,verbs=get -func (r *BackupConfigurationReconciler) addSidecarContainer(backupConf *formolv1alpha1.BackupConfiguration) error { - log := r.Log.WithValues("backupconf", backupConf.Name) - getDeployment := func() (*appsv1.Deployment, error) { - deployment := &appsv1.Deployment{} - err := r.Get(context.Background(), client.ObjectKey{ - Namespace: backupConf.Namespace, - Name: backupConf.Spec.Target.Name, - }, deployment) - return deployment, err +func (r *BackupConfigurationReconciler) deleteSidecarContainer(backupConf *formolv1alpha1.BackupConfiguration) error { + deployment, err := r.getDeployment(backupConf.Namespace, backupConf.Spec.Target.Name) + if err != nil { + return err + } + restorecontainers := []corev1.Container{} + for _, container := range deployment.Spec.Template.Spec.Containers { + if container.Name == "backup" { + continue + } + restorecontainers = append(restorecontainers, container) + } + deployment.Spec.Template.Spec.Containers = restorecontainers + if err := r.Update(context.Background(), deployment); err != nil { + return err + } + selector, err := metav1.LabelSelectorAsMap(deployment.Spec.Selector) + if err != nil { + return nil + } + pods := &corev1.PodList{} + err = r.List(context.Background(), pods, client.MatchingLabels(selector)) + if err != nil { + return nil + } + replicasToDelete := []appsv1.ReplicaSet{} + for _, pod := range pods.Items { + for _, podRef := range pod.OwnerReferences { + rs := &appsv1.ReplicaSet{} + if err := r.Get(context.Background(), client.ObjectKey{ + Name: podRef.Name, + Namespace: pod.Namespace, + }, rs); err != nil { + return nil + } + for _, rsRef := range rs.OwnerReferences { + if rsRef.Kind == deployment.Kind && rsRef.Name == deployment.Name { + replicasToDelete = append(replicasToDelete, *rs) + } + } + } } - deployment, err := getDeployment() + for _, replica := range replicasToDelete { + if err := r.Delete(context.TODO(), &replica); err != nil { + return nil + } + } + return nil +} + +func (r *BackupConfigurationReconciler) addSidecarContainer(backupConf *formolv1alpha1.BackupConfiguration) error { + log := r.Log.WithValues("backupconf", backupConf.Name) + deployment, err := r.getDeployment(backupConf.Namespace, backupConf.Spec.Target.Name) if err != nil { log.Error(err, "unable to get Deployment") return err } - log.WithValues("Deployment", backupConf.Spec.Target.Name) + log.V(1).Info("got deployment", "Deployment", deployment) for _, container := range deployment.Spec.Template.Spec.Containers { if container.Name == "backup" { log.V(0).Info("There is already a backup sidecar container. Skipping", "container", container) @@ -155,7 +210,7 @@ func (r *BackupConfigurationReconciler) addSidecarContainer(backupConf *formolv1 log.Error(err, "unable to get deployment pods") return nil } - podsToDelete := []appsv1.ReplicaSet{} + replicasToDelete := []appsv1.ReplicaSet{} log.V(1).Info("got that list of pods", "pods", len(pods.Items)) for _, pod := range pods.Items { log.V(1).Info("checking pod", "pod", pod) @@ -172,78 +227,35 @@ func (r *BackupConfigurationReconciler) addSidecarContainer(backupConf *formolv1 for _, rsRef := range rs.OwnerReferences { if rsRef.Kind == deployment.Kind && rsRef.Name == deployment.Name { log.V(0).Info("Adding pod to the list of pods to be restarted", "pod", pod.Name) - podsToDelete = append(podsToDelete, *rs) + replicasToDelete = append(replicasToDelete, *rs) } } } } deployment.Spec.Template.Spec.Containers = append(deployment.Spec.Template.Spec.Containers, sidecar) + + if err := formolrbac.CreateBackupSessionListenerRBAC(r.Client, deployment.Spec.Template.Spec.ServiceAccountName, deployment.Namespace); err != nil { + log.Error(err, "unable to create backupsessionlistener RBAC") + return nil + } + log.V(0).Info("Adding a sicar container") if err := r.Update(context.Background(), deployment); err != nil { log.Error(err, "unable to update the Deployment") return err } - for _, pod := range podsToDelete { - if err := r.Delete(context.TODO(), &pod); err != nil { - log.Error(err, "unable to delete pod", "pod", pod.Name) + for _, replica := range replicasToDelete { + if err := r.Delete(context.TODO(), &replica); err != nil { + log.Error(err, "unable to delete replica", "replica", replica.Name) return nil } } - deployment, err = getDeployment() - if err != nil { - log.Error(err, "unable to get Deployment") - return err - } return nil } func (r *BackupConfigurationReconciler) addCronJob(backupConf *formolv1alpha1.BackupConfiguration) error { log := r.Log.WithName("addCronJob") - // serviceaccount := &corev1.ServiceAccount{ - // ObjectMeta: metav1.ObjectMeta{ - // Namespace: backupConf.Namespace, - // Name: "backupsession-creator", - // }, - // } - // if err := r.Get(context.Background(), client.ObjectKey{ - // Namespace: backupConf.Namespace, - // Name: "backupsession-creator", - // }, serviceaccount); err != nil && errors.IsNotFound(err) { - // log.V(0).Info("creating service account", "service account", serviceaccount) - // if err = r.Create(context.Background(), serviceaccount); err != nil { - // log.Error(err, "unable to create serviceaccount", "serviceaccount", serviceaccount) - // return nil - // } - // } - // rolebinding := &rbacv1.RoleBinding{ - // ObjectMeta: metav1.ObjectMeta{ - // Namespace: backupConf.Namespace, - // Name: "backupsession-creator-rolebinding", - // }, - // Subjects: []rbacv1.Subject{ - // rbacv1.Subject{ - // Kind: "ServiceAccount", - // Name: "backupsession-creator", - // }, - // }, - // RoleRef: rbacv1.RoleRef{ - // APIGroup: "rbac.authorization.k8s.io", - // Kind: "ClusterRole", - // Name: "backupsession-creator", - // }, - // } - // if err := r.Get(context.Background(), client.ObjectKey{ - // Namespace: backupConf.Namespace, - // Name: "backupsession-creator-rolebinding", - // }, rolebinding); err != nil && errors.IsNotFound(err) { - // log.V(0).Info("creating role binding for service account", "rolebinding", rolebinding, "service account", serviceaccount) - // if err = r.Create(context.Background(), rolebinding); err != nil { - // log.Error(err, "unable to create rolebinding", "rolebinding", rolebinding) - // return nil - // } - // } - cronjob := &kbatch_beta1.CronJob{} if err := r.Get(context.Background(), client.ObjectKey{ Namespace: backupConf.Namespace, @@ -256,6 +268,11 @@ func (r *BackupConfigurationReconciler) addCronJob(backupConf *formolv1alpha1.Ba return err } + if err := formolrbac.CreateBackupSessionCreatorRBAC(r.Client, backupConf.Namespace); err != nil { + log.Error(err, "unable to create backupsession-creator RBAC") + return nil + } + cronjob = &kbatch_beta1.CronJob{ ObjectMeta: metav1.ObjectMeta{ Name: "backup-" + backupConf.Name, @@ -310,10 +327,35 @@ func (r *BackupConfigurationReconciler) Reconcile(req ctrl.Request) (ctrl.Result // your logic here backupConf := &formolv1alpha1.BackupConfiguration{} if err := r.Get(ctx, req.NamespacedName, backupConf); err != nil { - log.Error(err, "unable to fetch BackupConfiguration") return ctrl.Result{}, client.IgnoreNotFound(err) } + finalizerName := "finalizer.backupconfiguration.formol.desmojim.fr" + + if backupConf.ObjectMeta.DeletionTimestamp.IsZero() { + if !formolutils.ContainsString(backupConf.ObjectMeta.Finalizers, finalizerName) { + backupConf.ObjectMeta.Finalizers = append(backupConf.ObjectMeta.Finalizers, finalizerName) + if err := r.Update(context.Background(), backupConf); err != nil { + log.Error(err, "unable to append finalizer") + return ctrl.Result{}, err + } + } + } else { + log.V(0).Info("backupconf being deleted", "backupconf", backupConf.Name) + if formolutils.ContainsString(backupConf.ObjectMeta.Finalizers, finalizerName) { + if err := r.deleteExternelResources(backupConf); err != nil { + return ctrl.Result{}, err + } + } + backupConf.ObjectMeta.Finalizers = formolutils.RemoveString(backupConf.ObjectMeta.Finalizers, finalizerName) + if err := r.Update(context.Background(), backupConf); err != nil { + log.Error(err, "unable to remove finalizer") + return ctrl.Result{}, err + } + // We have been deleted. Return here + return ctrl.Result{}, nil + } + if err := r.addCronJob(backupConf); err != nil { return ctrl.Result{}, nil } @@ -330,12 +372,7 @@ func (r *BackupConfigurationReconciler) Reconcile(req ctrl.Request) (ctrl.Result return ctrl.Result{}, nil } - if backupConf.Spec.Suspend != nil && *backupConf.Spec.Suspend == true { - log.V(0).Info("We are suspended return and wait for the next event") - // TODO Suspend the CronJob - return ctrl.Result{}, nil - } - + backupConf.Status.Suspended = false log.V(1).Info("updating backupconf") if err := r.Status().Update(ctx, backupConf); err != nil { log.Error(err, "unable to update backupconf", "backupconf", backupConf) @@ -345,9 +382,28 @@ func (r *BackupConfigurationReconciler) Reconcile(req ctrl.Request) (ctrl.Result return ctrl.Result{}, nil } +func (r *BackupConfigurationReconciler) deleteExternelResources(backupConf *formolv1alpha1.BackupConfiguration) error { + deployment, err := r.getDeployment(backupConf.Namespace, backupConf.Spec.Target.Name) + if err != nil { + return err + } + if err := formolrbac.DeleteBackupSessionListenerRBAC(r.Client, deployment.Spec.Template.Spec.ServiceAccountName, deployment.Namespace); err != nil { + return err + } + if err := formolrbac.DeleteBackupSessionCreatorRBAC(r.Client, backupConf.Namespace); err != nil { + return err + } + if err := r.deleteSidecarContainer(backupConf); err != nil { + return err + } + return nil +} + func (r *BackupConfigurationReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&formolv1alpha1.BackupConfiguration{}). - Owns(&kbatch_beta1.CronJob{}). + WithOptions(controller.Options{MaxConcurrentReconciles: 3}). + WithEventFilter(predicate.GenerationChangedPredicate{}). + // Owns(&kbatch_beta1.CronJob{}). Complete(r) } diff --git a/go.mod b/go.mod index a56993e..9113c58 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,12 @@ go 1.13 require ( github.com/go-logr/logr v0.1.0 - github.com/onsi/ginkgo v1.11.0 - github.com/onsi/gomega v1.8.1 - k8s.io/api v0.17.2 - k8s.io/apimachinery v0.17.2 - k8s.io/client-go v0.17.2 - sigs.k8s.io/controller-runtime v0.5.0 + github.com/onsi/ginkgo v1.12.1 + github.com/onsi/gomega v1.10.1 + gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e // indirect + k8s.io/api v0.18.6 + k8s.io/apimachinery v0.18.6 + k8s.io/client-go v0.18.6 + sigs.k8s.io/controller-runtime v0.6.4 + sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 // indirect ) diff --git a/main.go b/main.go index a907994..619ebf0 100644 --- a/main.go +++ b/main.go @@ -74,14 +74,14 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "BackupConfiguration") os.Exit(1) } - if err = (&controllers.BackupSessionReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("BackupSession"), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "BackupSession") - os.Exit(1) - } + // if err = (&controllers.BackupSessionReconciler{ + // Client: mgr.GetClient(), + // Log: ctrl.Log.WithName("controllers").WithName("BackupSession"), + // Scheme: mgr.GetScheme(), + // }).SetupWithManager(mgr); err != nil { + // setupLog.Error(err, "unable to create controller", "controller", "BackupSession") + // os.Exit(1) + // } if os.Getenv("ENABLE_WEBHOOKS") != "false" { if err = (&formolv1alpha1.BackupSession{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "BackupSession") diff --git a/pkg/rbac/backupconfiguration.go b/pkg/rbac/backupconfiguration.go new file mode 100644 index 0000000..e2d2733 --- /dev/null +++ b/pkg/rbac/backupconfiguration.go @@ -0,0 +1,231 @@ +package rbac + +import ( + "context" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + backupListenerRole = "backup-listener-role" + backupListenerRoleBinding = "backup-listener-rolebinding" + backupSessionCreatorSA = "backupsession-creator" + backupSessionCreatorRole = "backupsession-creator-role" + backupSessionCreatorRoleBinding = "backupsession-creator-rolebinding" +) + +func DeleteBackupSessionCreatorRBAC(cl client.Client, namespace string) error { + serviceaccount := &corev1.ServiceAccount{} + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupSessionCreatorSA, + }, serviceaccount); err == nil { + if err = cl.Delete(context.Background(), serviceaccount); err != nil { + return err + } + } + role := &rbacv1.Role{} + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupSessionCreatorRole, + }, role); err == nil { + if err = cl.Delete(context.Background(), role); err != nil { + return err + } + } + + rolebinding := &rbacv1.RoleBinding{} + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupSessionCreatorRoleBinding, + }, rolebinding); err == nil { + if err = cl.Delete(context.Background(), rolebinding); err != nil { + return err + } + } + + return nil +} + +func CreateBackupSessionCreatorRBAC(cl client.Client, namespace string) error { + serviceaccount := &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: backupSessionCreatorSA, + }, + } + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupSessionCreatorSA, + }, serviceaccount); err != nil && errors.IsNotFound(err) { + if err = cl.Create(context.Background(), serviceaccount); err != nil { + return err + } + } + role := &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: backupSessionCreatorRole, + }, + Rules: []rbacv1.PolicyRule{ + rbacv1.PolicyRule{ + Verbs: []string{"get", "list", "watch", "create", "update", "patch", "delete"}, + APIGroups: []string{"formol.desmojim.fr"}, + Resources: []string{"backupsessions"}, + }, + rbacv1.PolicyRule{ + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{"formol.desmojim.fr"}, + Resources: []string{"backupconfigurations"}, + }, + }, + } + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupSessionCreatorRole, + }, role); err != nil && errors.IsNotFound(err) { + if err = cl.Create(context.Background(), role); err != nil { + return err + } + } + rolebinding := &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: backupSessionCreatorRoleBinding, + }, + Subjects: []rbacv1.Subject{ + rbacv1.Subject{ + Kind: "ServiceAccount", + Name: backupSessionCreatorSA, + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + Name: backupSessionCreatorRole, + }, + } + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupSessionCreatorRoleBinding, + }, rolebinding); err != nil && errors.IsNotFound(err) { + if err = cl.Create(context.Background(), rolebinding); err != nil { + return err + } + } + + return nil +} + +func DeleteBackupSessionListenerRBAC(cl client.Client, saName string, namespace string) error { + if saName == "" { + saName = "default" + } + sa := &corev1.ServiceAccount{} + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: saName, + }, sa); err != nil { + return err + } + + role := &rbacv1.Role{} + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupListenerRole, + }, role); err == nil { + if err = cl.Delete(context.Background(), role); err != nil { + return err + } + } + + rolebinding := &rbacv1.RoleBinding{} + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupListenerRoleBinding, + }, rolebinding); err == nil { + if err = cl.Delete(context.Background(), rolebinding); err != nil { + return err + } + } + + return nil +} + +func CreateBackupSessionListenerRBAC(cl client.Client, saName string, namespace string) error { + if saName == "" { + saName = "default" + } + sa := &corev1.ServiceAccount{} + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: saName, + }, sa); err != nil { + return err + } + role := &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: backupListenerRole, + }, + Rules: []rbacv1.PolicyRule{ + rbacv1.PolicyRule{ + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{""}, + Resources: []string{"pods"}, + }, + rbacv1.PolicyRule{ + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{"apps"}, + Resources: []string{"deployments", "replicasets"}, + }, + rbacv1.PolicyRule{ + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{"formol.desmojim.fr"}, + Resources: []string{"backupsessions", "backupconfigurations"}, + }, + rbacv1.PolicyRule{ + Verbs: []string{"get", "list", "watch", "patch", "update"}, + APIGroups: []string{"formol.desmojim.fr"}, + Resources: []string{"backupsessions/status"}, + }, + }, + } + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupListenerRole, + }, role); err != nil && errors.IsNotFound(err) { + if err = cl.Create(context.Background(), role); err != nil { + return err + } + } + rolebinding := &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: backupListenerRoleBinding, + }, + Subjects: []rbacv1.Subject{ + rbacv1.Subject{ + Kind: "ServiceAccount", + Name: saName, + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + Name: backupListenerRole, + }, + } + if err := cl.Get(context.Background(), client.ObjectKey{ + Namespace: namespace, + Name: backupListenerRoleBinding, + }, rolebinding); err != nil && errors.IsNotFound(err) { + if err = cl.Create(context.Background(), rolebinding); err != nil { + return err + } + } + return nil +} diff --git a/pkg/utils/root.go b/pkg/utils/root.go new file mode 100644 index 0000000..09862e6 --- /dev/null +++ b/pkg/utils/root.go @@ -0,0 +1,20 @@ +package utils + +func ContainsString(slice []string, s string) bool { + for _, item := range slice { + if item == s { + return true + } + } + return false +} + +func RemoveString(slice []string, s string) (result []string) { + for _, item := range slice { + if item == s { + continue + } + result = append(result, item) + } + return +} diff --git a/test/00-setup.yaml b/test/00-setup.yaml index 3e55292..2698446 100644 --- a/test/00-setup.yaml +++ b/test/00-setup.yaml @@ -52,86 +52,6 @@ spec: storage: 50Mi --- apiVersion: v1 -kind: ServiceAccount -metadata: - name: backupsession-creator - namespace: demo - labels: - app: backupsession-creator ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRole -metadata: - name: backup-listener - labels: - app: backup-listener -rules: - - apiGroups: ["formol.desmojim.fr"] - resources: ["backupsessions", "backupconfigurations"] - verbs: ["get", "list", "watch"] - - apiGroups: ["formol.desmojim.fr"] - resources: ["backupsessions/status"] - verbs: ["update"] ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: Role -metadata: - name: backupsession-creator - namespace: demo - labels: - app: backupsession-creator -rules: - - apiGroups: ["formol.desmojim.fr"] - resources: ["backupsessions"] - verbs: ["get", "list", "create", "delete"] - - apiGroups: ["formol.desmojim.fr"] - resources: ["backupconfigurations"] - verbs: ["get", "list", "watch"] ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: backupsession-creator - namespace: demo - labels: - app: backupsession-creator -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: backupsession-creator -subjects: - - name: backupsession-creator - kind: ServiceAccount ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding -metadata: - name: backup-listener - labels: - app: backup-listener -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: backup-listener -subjects: - - name: default - namespace: demo - kind: ServiceAccount ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: demo-viewer - namespace: demo -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: view -subjects: - - name: default - kind: ServiceAccount ---- -apiVersion: v1 kind: Secret metadata: name: secret-minio