diff --git a/Dockerfile b/Dockerfile index c389c09..a414ef1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,13 +21,16 @@ COPY internal/controller/ internal/controller/ # was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO # the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, # by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. -RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go +RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o gobackup-operator cmd/main.go -# Use distroless as minimal base image to package the manager binary -# Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot +# Use BusyBox as minimal base image to package the manager binary +FROM busybox WORKDIR / -COPY --from=builder /workspace/manager . -USER 65532:65532 -ENTRYPOINT ["/manager"] +# Copy the binary from the builder stage +COPY --from=builder /workspace/gobackup-operator . + +# Set permissions +USER root + +ENTRYPOINT ["/gobackup-operator"] diff --git a/example/gobackup-opetator-clusterrole.yaml b/example/gobackup-opetator-clusterrole.yaml new file mode 100644 index 0000000..37f01ce --- /dev/null +++ b/example/gobackup-opetator-clusterrole.yaml @@ -0,0 +1,9 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: gobackup-operator-cluster-role + namespace: gobackup-operator-test +rules: +- apiGroups: [""] + resources: ["*"] + verbs: ["*"] diff --git a/example/gobackup-opetator-rolebinding.yaml b/example/gobackup-opetator-clusterrolebinding.yaml similarity index 77% rename from example/gobackup-opetator-rolebinding.yaml rename to example/gobackup-opetator-clusterrolebinding.yaml index 9fc28d4..d57a6a0 100644 --- a/example/gobackup-opetator-rolebinding.yaml +++ b/example/gobackup-opetator-clusterrolebinding.yaml @@ -1,5 +1,5 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding +kind: ClusterRoleBinding metadata: name: gobackup-operator-role-binding namespace: gobackup-operator-test @@ -8,6 +8,6 @@ subjects: name: gobackup-operator-service-account namespace: gobackup-operator-test roleRef: - kind: Role - name: gobackup-operator-role + kind: ClusterRole + name: gobackup-operator-cluster-role apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/example/gobackup-opetator-deployment.yaml b/example/gobackup-opetator-deployment.yaml index 0da80fa..d271971 100644 --- a/example/gobackup-opetator-deployment.yaml +++ b/example/gobackup-opetator-deployment.yaml @@ -1,31 +1,26 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: postgres-deployment + name: gobackup-operator + labels: + app: gobackup-operator spec: + replicas: 1 selector: matchLabels: - app: postgres - replicas: 1 + app: gobackup-operator template: metadata: labels: - app: postgres + app: gobackup-operator spec: + serviceAccountName: gobackup-operator-service-account containers: - - name: postgres - image: docker.arvancloud.ir/postgres:latest + - name: gobackup-operator + image: payamqorbanpour/gobackup-operator:v0.1.0 + imagePullPolicy: IfNotPresent env: - - name: POSTGRES_USER - value: "" - - name: POSTGRES_PASSWORD - value: "" - - name: PGDATA - value: "/var/lib/postgresql/data/pgdata" - volumeMounts: - - mountPath: /var/lib/postgresql/data - name: postgredb - volumes: - - name: postgredb - persistentVolumeClaim: - claimName: postgres-pvc \ No newline at end of file + - name: gobackup-operator-test + valueFrom: + fieldRef: + fieldPath: metadata.namespace diff --git a/example/gobackup-opetator-postgres-deployment.yaml b/example/gobackup-opetator-postgres-deployment.yaml new file mode 100644 index 0000000..b3f21a7 --- /dev/null +++ b/example/gobackup-opetator-postgres-deployment.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres-deployment +spec: + selector: + matchLabels: + app: postgres + replicas: 1 + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:14.11 + env: + - name: POSTGRES_USER + value: "" + - name: POSTGRES_PASSWORD + value: "" + - name: PGDATA + value: "/var/lib/postgresql/data/pgdata" + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgredb + volumes: + - name: postgredb + persistentVolumeClaim: + claimName: postgres-pvc \ No newline at end of file diff --git a/example/gobackup-opetator-role.yaml b/example/gobackup-opetator-role.yaml deleted file mode 100644 index a573a4f..0000000 --- a/example/gobackup-opetator-role.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - namespace: gobackup-operator-test - name: gobackup-operator-role -rules: -- apiGroups: [""] - resources: ["serviceaccounts"] - verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] \ No newline at end of file diff --git a/internal/controller/cronbackup_controller.go b/internal/controller/cronbackup_controller.go index a1f97ad..1c72ecb 100644 --- a/internal/controller/cronbackup_controller.go +++ b/internal/controller/cronbackup_controller.go @@ -19,23 +19,22 @@ package controller import ( "context" "fmt" - "os" "gopkg.in/yaml.v2" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" backupv1 "github.com/gobackup/gobackup-operator/api/v1" - "github.com/gobackup/gobackup-operator/pkg/utils" ) // CronBackupReconciler reconciles a CronBackup object @@ -101,7 +100,8 @@ func (r *CronBackupReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{}, client.IgnoreNotFound(nil) } - config, err := clientcmd.BuildConfigFromFlags("", "/Users/payam/.kube/config") + // Create config to use the ServiceAccount's token, CA cert, and API server address + config, err := rest.InClusterConfig() if err != nil { return ctrl.Result{}, err } @@ -111,12 +111,12 @@ func (r *CronBackupReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{}, err } - examplepsql, err := utils.GetCRD(ctx, dynamicClient, "database.gobackup.io", "v1", "postgresqls", "gobackup-operator-test", "example-postgresql") + examplepsql, err := GetCRD(ctx, dynamicClient, "database.gobackup.io", "v1", "postgresqls", "gobackup-operator-test", "example-postgresql") if err != nil { return ctrl.Result{}, err } - examples3, err := utils.GetCRD(ctx, dynamicClient, "storage.gobackup.io", "v1", "s3s", "gobackup-operator-test", "example-s3") + examples3, err := GetCRD(ctx, dynamicClient, "storage.gobackup.io", "v1", "s3s", "gobackup-operator-test", "example-s3") if err != nil { return ctrl.Result{}, err } @@ -152,12 +152,6 @@ func (r *CronBackupReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{}, err } - // Write to gobackup.yaml - err = os.WriteFile("gobackup.yaml", yamlData, 0644) - if err != nil { - return ctrl.Result{}, err - } - secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "gobackup-secret", @@ -277,7 +271,7 @@ func (r *CronBackupReconciler) createBackupJob(ctx context.Context, config *rest // nolint // createBackupCronJob creates a cronjob to run the 'gobackup perform' -func (r *CronBackupReconciler) createBackupCronJob(ctx context.Context, namespace string) (*batchv1.CronJob, error) { +func (r *CronBackupReconciler) createBackupCronJob(ctx context.Context, config *rest.Config, namespace string) (*batchv1.CronJob, error) { _ = log.FromContext(ctx) cronJob := &batchv1.CronJob{ @@ -323,11 +317,6 @@ func (r *CronBackupReconciler) createBackupCronJob(ctx context.Context, namespac }, } - config, err := clientcmd.BuildConfigFromFlags("", "/Users/payam/.kube/config") - if err != nil { - return nil, err - } - // Create a clientset from the configuration clientset, err := kubernetes.NewForConfig(config) if err != nil { @@ -342,3 +331,17 @@ func (r *CronBackupReconciler) createBackupCronJob(ctx context.Context, namespac return cronJob, nil } + +// nolint +// GetCRD fetches a CRD instance. +func GetCRD(ctx context.Context, dynamicClient dynamic.Interface, group, version, resource, namespace, name string) (*unstructured.Unstructured, error) { + gvr := schema.GroupVersionResource{Group: group, Version: version, Resource: resource} + + // Fetch the instance + crdObj, err := dynamicClient.Resource(gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to fetch CRD %s in namespace %s: %w", name, namespace, err) + } + + return crdObj, nil +} diff --git a/pkg/utils/config.go b/pkg/utils/config.go deleted file mode 100644 index af7fc41..0000000 --- a/pkg/utils/config.go +++ /dev/null @@ -1,25 +0,0 @@ -package utils - -import ( - "context" - "fmt" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/dynamic" -) - -// nolint -// GetCRD fetches a CRD instance. -func GetCRD(ctx context.Context, dynamicClient dynamic.Interface, group, version, resource, namespace, name string) (*unstructured.Unstructured, error) { - gvr := schema.GroupVersionResource{Group: group, Version: version, Resource: resource} - - // Fetch the instance - crdObj, err := dynamicClient.Resource(gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return nil, fmt.Errorf("failed to fetch CRD %s in namespace %s: %w", name, namespace, err) - } - - return crdObj, nil -}