diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5447eb3c6c7568f586bb23e8355e9e4d7c280677..d30863c0dbefeb059323ad755440a8740da764ad 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -142,7 +142,6 @@ lint_docs_markdown: optional: true variables: HELM_CHARTS: "${CI_PROJECT_DIR}/charts" - GITLAB_OPERATOR_ASSETS: "${CI_PROJECT_DIR}/hack/assets" KUBECONFIG: "" # to ensure that the CI cluster is not used USE_EXISTING_CLUSTER: "false" # to ensure we don't use the $KUBECONFIG value KUBEBUILDER_ASSETS: "/usr/local/kubebuilder/bin" diff --git a/Dockerfile b/Dockerfile index 9a4022e1584151bd9d16af571390d6fe4e9ad20c..cdefff2ab3a1d122816736e3c60915ac0bb86965 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,9 +36,6 @@ ENV USER_UID=1001 \ # ADD GITLAB LICENSE COPY LICENSE /licenses/GITLAB -# Copy config templates -COPY hack/assets / - # Add pre-packaged charts for the operator to deploy COPY charts ${CHART_DIR} diff --git a/controllers/gitlab/adapter.go b/controllers/gitlab/adapter.go index 4012671e4d52e513fde13986e9c2b02b1065fa70..e6e06fafa6969136d33b1060c1ac196ac5d526b6 100644 --- a/controllers/gitlab/adapter.go +++ b/controllers/gitlab/adapter.go @@ -3,7 +3,6 @@ package gitlab import ( "fmt" "hash/fnv" - "strconv" "strings" gitlabv1beta1 "gitlab.com/gitlab-org/cloud-native/gitlab-operator/api/v1beta1" @@ -112,11 +111,6 @@ gitlab: runAsUser: $LocalUser fsGroup: $LocalUser toolbox: - backups: - objectStorage: - config: - secret: $ToolboxConnectionSecretName - key: config common: labels: app.kubernetes.io/component: toolbox @@ -175,6 +169,11 @@ global: create: false name: $AppServiceAccount +minio: + securityContext: + runAsUser: $LocalUser + fsGroup: $LocalUser + redis: master: statefulset: @@ -211,42 +210,6 @@ nginx-ingress: name: $AppServiceAccount ` -var defaultValuesMinio string = ` -global: - minio: - enabled: false - appConfig: - object_store: - enabled: true - connection: - secret: $AppConfigConnectionSecretName - key: connection - artifacts: - bucket: gitlab-artifacts - backups: - bucket: gitlab-backups - tmpBucket: tmp - externalDiffs: - bucket: gitlab-mr-diffs - lfs: - bucket: git-lfs - packages: - bucket: gitlab-packages - pseudonymizer: - bucket: gitlab-pseudo - uploads: - bucket: gitlab-uploads - registry: - bucket: registry - -registry: - storage: - secret: $RegistryConnectionSecretName - key: config - redirect: - disable: $RegistryMinioRedirect -` - // NewCustomResourceAdapter returns a new adapter for the provided GitLab instance. func NewCustomResourceAdapter(gitlab *gitlabv1beta1.GitLab) CustomResourceAdapter { result := &populatingAdapter{ @@ -342,7 +305,6 @@ func (a *populatingAdapter) populateValues() { "$LocalUser", settings.LocalUser, "$AppServiceAccount", settings.AppServiceAccount, "$ManagerServiceAccount", settings.ManagerServiceAccount, - "$ToolboxConnectionSecretName", settings.ToolboxConnectionSecretName, "$GlobalIngressAnnotations", globalIngressAnnotations, "$NGINXServiceAccount", settings.NGINXServiceAccount, "$GlobalHostsExternalIP", globalHostsExternalIP, @@ -350,25 +312,6 @@ func (a *populatingAdapter) populateValues() { _ = a.values.AddFromYAML(valuesToUse) - // Need to pass a default value here as we don't yet have the coalesced values from GetTemplate(). - minioEnabled := a.values.GetBool(globalMinioEnabled, true) - if minioEnabled { - minioRedirect := a.values.GetBool("registry.minio.redirect") - valuesToUse := strings.NewReplacer( - "$AppConfigConnectionSecretName", settings.AppConfigConnectionSecretName, - "$RegistryConnectionSecretName", settings.RegistryConnectionSecretName, - "$RegistryMinioRedirect", strconv.FormatBool(!minioRedirect), - ).Replace(defaultValuesMinio) - - _ = a.values.AddFromYAML(valuesToUse) - } - - // This is a workaround to account for the fact that our "internal" MinIO is actually - // implemented as external object storage, meaning `global.minio.enabled` must be - // set to `false`. If `internalMinioEnabled=true`, then our "internal" MinIO objects - // will be reconciled, and vice versa. - _ = a.values.SetValue(internalMinioEnabled, minioEnabled) - email := a.values.GetString("certmanager-issuer.email") if email == "" { _ = a.values.SetValue("certmanager-issuer.email", "admin@example.com") diff --git a/controllers/gitlab/minio.go b/controllers/gitlab/minio.go index fc5f28d5fcfb08ef9b8fb1ac863bf0c0728db9d7..f4499d4da780b7b1e3a8d0cd1ee0b623311f5df2 100644 --- a/controllers/gitlab/minio.go +++ b/controllers/gitlab/minio.go @@ -1,11 +1,71 @@ package gitlab +import ( + appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/settings" + "gitlab.com/gitlab-org/cloud-native/gitlab-operator/helm" +) + const ( - globalMinioEnabled = "global.minio.enabled" - internalMinioEnabled = "internalMinioEnabled" + globalMinioEnabled = "global.minio.enabled" ) // MinioEnabled returns `true` if enabled, and `false` if not. func MinioEnabled(adapter CustomResourceAdapter) bool { - return adapter.Values().GetBool(internalMinioEnabled) + return adapter.Values().GetBool(globalMinioEnabled) +} + +// MinioJob returns the Job of the Minio component. +func MinioJob(adapter CustomResourceAdapter, template helm.Template) client.Object { + obj := template.Query().ObjectByKindAndComponent(JobKind, MinioComponentName) + + // Set ServiceAccountName and SecurityContext, as the Helm Chart does not currently + // support setting them. + // https://gitlab.com/gitlab-org/charts/gitlab/-/issues/3192 + var rootUser int64 + + job := obj.(*batchv1.Job) + job.Spec.Template.Spec.ServiceAccountName = settings.AppServiceAccount + job.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{ + RunAsUser: &rootUser, + FSGroup: &rootUser, + } + + return job +} + +// MinioDeployment returns the Deployment of the Minio component. +func MinioDeployment(adapter CustomResourceAdapter, template helm.Template) client.Object { + obj := template.Query().ObjectByKindAndComponent(DeploymentKind, MinioComponentName) + + // Set ServiceAccountName, as the Helm Chart does not currently support setting it. + // https://gitlab.com/gitlab-org/charts/gitlab/-/issues/3192 + deployment := obj.(*appsv1.Deployment) + deployment.Spec.Template.Spec.ServiceAccountName = settings.AppServiceAccount + + return deployment +} + +// MinioConfigMap returns the ConfigMap of the Minio component. +func MinioConfigMap(adapter CustomResourceAdapter, template helm.Template) client.Object { + return template.Query().ObjectByKindAndComponent(ConfigMapKind, MinioComponentName) +} + +// MinioIngress returns the Ingress of the Minio component. +func MinioIngress(adapter CustomResourceAdapter, template helm.Template) client.Object { + return template.Query().ObjectByKindAndComponent(IngressKind, MinioComponentName) +} + +// MinioService returns the Service of the Minio component. +func MinioService(adapter CustomResourceAdapter, template helm.Template) client.Object { + return template.Query().ObjectByKindAndComponent(ServiceKind, MinioComponentName) +} + +// MinioPersistentVolumeClaim returns the PersistentVolumeClaim of the Minio component. +func MinioPersistentVolumeClaim(adapter CustomResourceAdapter, template helm.Template) client.Object { + return template.Query().ObjectByKindAndComponent(PersistentVolumeClaimKind, MinioComponentName) } diff --git a/controllers/gitlab/utils.go b/controllers/gitlab/utils.go index 1ba1d3915ea3e5ff725e09dda51001569e6d8e4c..4fde1a012f5bf99fad586e536f21da6367836f45 100644 --- a/controllers/gitlab/utils.go +++ b/controllers/gitlab/utils.go @@ -71,6 +71,9 @@ const ( // ToolboxComponentName is the common name of Toolbox. ToolboxComponentName = "toolbox" + + // MinioComponentName is the common name of MinIO. + MinioComponentName = "minio" ) // RedisSubqueues is the array of possible Redis subqueues. diff --git a/controllers/gitlab_controller.go b/controllers/gitlab_controller.go index 3370c42b86241a3c9aca08e68802564a969872f4..a97cd19b8e37cbe48d655f87065540a1f389e5ad 100644 --- a/controllers/gitlab_controller.go +++ b/controllers/gitlab_controller.go @@ -185,7 +185,7 @@ func (r *GitLabReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr } if gitlabctl.MinioEnabled(adapter) { - if err := r.reconcileMinioInstance(ctx, adapter); err != nil { + if err := r.reconcileMinioInstance(ctx, adapter, template); err != nil { return ctrl.Result{}, err } } @@ -581,11 +581,6 @@ func (r *GitLabReconciler) createOrPatch(ctx context.Context, templateObject cli return true, nil } - // If Secret and related to MinIO, skip the patch. - if existing.GetObjectKind().GroupVersionKind().Kind == "Secret" && existing.GetLabels()["app.kubernetes.io/component"] == "minio" && gitlabctl.MinioEnabled(adapter) { - return false, nil - } - mutate := func() error { return mutateObject(templateObject, existing) } diff --git a/controllers/gitlab_controller_test.go b/controllers/gitlab_controller_test.go index 6f80a0cfb60eaa30feba85c5aa9f83933a8fce50..4265219128a61b88270ac0e3afcebd60123fd4f1 100644 --- a/controllers/gitlab_controller_test.go +++ b/controllers/gitlab_controller_test.go @@ -12,6 +12,7 @@ import ( appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gitlabv1beta1 "gitlab.com/gitlab-org/cloud-native/gitlab-operator/api/v1beta1" @@ -575,10 +576,12 @@ global: Context("MinIO", func() { When("Bundled MinIO is enabled", func() { releaseName := "minio-enabled" - cfgMapName := fmt.Sprintf("%s-minio-script", releaseName) - secretName := fmt.Sprintf("%s-minio-secret", releaseName) - serviceName := fmt.Sprintf("%s-minio", releaseName) - statefulSetName := fmt.Sprintf("%s-minio", releaseName) + cfgMapName := fmt.Sprintf("%s-minio-config-cm", releaseName) + serviceName := fmt.Sprintf("%s-minio-svc", releaseName) + jobName := fmt.Sprintf("%s-minio-create-buckets-1", releaseName) + ingressName := fmt.Sprintf("%s-minio", releaseName) + pvcName := fmt.Sprintf("%s-minio", releaseName) + deploymentName := fmt.Sprintf("%s-minio", releaseName) nextCfgMapName := fmt.Sprintf("%s-%s", releaseName, gitlabctl.SharedSecretsComponentName) chartValues := resource.Values{} @@ -591,16 +594,24 @@ global: }) It("Should create MinIO resources and continue the reconcile loop", func() { - By("Checking MinIO Secret exists") - Eventually(getObjectPromise(secretName, &corev1.Secret{}), - PollTimeout, PollInterval).Should(Succeed()) - By("Checking MinIO Service exists") Eventually(getObjectPromise(serviceName, &corev1.Service{}), PollTimeout, PollInterval).Should(Succeed()) - By("Checking MinIO StatefulSet exists") - Eventually(getObjectPromise(statefulSetName, &appsv1.StatefulSet{}), + By("Checking MinIO Job exists") + Eventually(getObjectPromise(jobName, &batchv1.Job{}), + PollTimeout, PollInterval).Should(Succeed()) + + By("Checking MinIO Ingress exists") + Eventually(getObjectPromise(ingressName, &networkingv1.Ingress{}), + PollTimeout, PollInterval).Should(Succeed()) + + By("Checking MinIO PersristenVolumeClaim exists") + Eventually(getObjectPromise(pvcName, &corev1.PersistentVolumeClaim{}), + PollTimeout, PollInterval).Should(Succeed()) + + By("Checking MinIO Deployment exists") + Eventually(getObjectPromise(deploymentName, &appsv1.Deployment{}), PollTimeout, PollInterval).Should(Succeed()) By("Checking MinIO ConfigMap exists") @@ -615,10 +626,12 @@ global: When("Bundled MinIO is disabled", func() { releaseName := "minio-disabled" - cfgMapName := fmt.Sprintf("%s-minio-script", releaseName) - secretName := fmt.Sprintf("%s-minio-secret", releaseName) - serviceName := fmt.Sprintf("%s-minio", releaseName) - statefulSetName := fmt.Sprintf("%s-minio", releaseName) + cfgMapName := fmt.Sprintf("%s-minio-config-cm", releaseName) + jobName := fmt.Sprintf("%s-minio-create-buckets-1", releaseName) + ingressName := fmt.Sprintf("%s-minio", releaseName) + pvcName := fmt.Sprintf("%s-minio", releaseName) + serviceName := fmt.Sprintf("%s-minio-svc", releaseName) + deploymentName := fmt.Sprintf("%s-minio", releaseName) nextCfgMapName := fmt.Sprintf("%s-%s", releaseName, gitlabctl.SharedSecretsComponentName) chartValues := resource.Values{} @@ -641,16 +654,24 @@ global: }) It("Should not create MinIO resources and continue the reconcile loop", func() { - By("Checking MinIO Secret does not exist") - Eventually(getObjectPromise(secretName, &corev1.Secret{}), - PollTimeout, PollInterval).ShouldNot(Succeed()) - By("Checking MinIO Service does not exist") Eventually(getObjectPromise(serviceName, &corev1.Service{}), PollTimeout, PollInterval).ShouldNot(Succeed()) - By("Checking MinIO StatefulSet does not exist") - Eventually(getObjectPromise(statefulSetName, &appsv1.StatefulSet{}), + By("Checking MinIO Job does not exist") + Eventually(getObjectPromise(jobName, &batchv1.Job{}), + PollTimeout, PollInterval).ShouldNot(Succeed()) + + By("Checking MinIO Ingress does not exist") + Eventually(getObjectPromise(ingressName, &networkingv1.Ingress{}), + PollTimeout, PollInterval).ShouldNot(Succeed()) + + By("Checking MinIO PersristenVolumeClaim does not exist") + Eventually(getObjectPromise(pvcName, &corev1.PersistentVolumeClaim{}), + PollTimeout, PollInterval).ShouldNot(Succeed()) + + By("Checking MinIO Deployment does not exist") + Eventually(getObjectPromise(deploymentName, &appsv1.StatefulSet{}), PollTimeout, PollInterval).ShouldNot(Succeed()) By("Checking MinIO ConfigMap does not exist") @@ -743,7 +764,7 @@ func processSharedSecretsJob(releaseName string) { } func processMinioBucketsJob(releaseName string) { - minioQuery := fmt.Sprintf("app.kubernetes.io/instance=%s-%s", releaseName, "bucket") + minioQuery := appLabels(releaseName, gitlabctl.MinioComponentName) By("Manipulating the MinIO buckets Job to succeed") Eventually(updateJobStatusPromise(minioQuery, true), diff --git a/controllers/internal/constants.go b/controllers/internal/constants.go new file mode 100644 index 0000000000000000000000000000000000000000..399672f768e2b17497fd6ef498bfbba0b3ddc1dc --- /dev/null +++ b/controllers/internal/constants.go @@ -0,0 +1,6 @@ +package internal + +const ( + // GitlabType represents resource of type Gitlab. + GitlabType = "gitlab" +) diff --git a/controllers/internal/job.go b/controllers/internal/job.go deleted file mode 100644 index 912a4bfe257b0f7ddb21bb5bc53b97c05a9e7eb2..0000000000000000000000000000000000000000 --- a/controllers/internal/job.go +++ /dev/null @@ -1,81 +0,0 @@ -package internal - -import ( - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - - "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/gitlab" - "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/settings" -) - -// BucketCreationJob creates the buckets used by GitLab. -func BucketCreationJob(adapter gitlab.CustomResourceAdapter) *batchv1.Job { - labels := Label(adapter.ReleaseName(), "bucket", GitlabType) - options := SystemBuildOptions(adapter) - - buckets := GenericJob(Component{ - Namespace: adapter.Namespace(), - Labels: labels, - Containers: []corev1.Container{ - { - Name: "mc", - Image: "minio/mc:RELEASE.2018-07-13T00-53-22Z", - ImagePullPolicy: corev1.PullIfNotPresent, - Command: []string{"/bin/sh", "/config/initialize"}, - Env: []corev1.EnvVar{ - { - Name: "MINIO_ENDPOINT", - Value: options.ObjectStore.Endpoint, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": ResourceQuantity("50m"), - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "minio-config", - MountPath: "/config", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "minio-config", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - DefaultMode: &ConfigMapDefaultMode, - Sources: []corev1.VolumeProjection{ - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: options.ObjectStore.Credentials, - }, - }, - }, - { - ConfigMap: &corev1.ConfigMapProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: adapter.ReleaseName() + "-minio-script", - }, - }, - }, - }, - }, - }, - }, - }, - }) - - var mcUser int64 - - buckets.Spec.Template.Spec.ServiceAccountName = settings.AppServiceAccount - buckets.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{ - RunAsUser: &mcUser, - FSGroup: &mcUser, - } - - return buckets -} diff --git a/controllers/internal/minio.go b/controllers/internal/minio.go deleted file mode 100644 index dd1b1f482407faa08177b307eb7d6883bc016794..0000000000000000000000000000000000000000 --- a/controllers/internal/minio.go +++ /dev/null @@ -1,453 +0,0 @@ -package internal - -import ( - "encoding/json" - "fmt" - "os" - - yaml "gopkg.in/yaml.v2" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - - "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/gitlab" - "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/settings" -) - -var ( - localUser int64 = 1000 -) - -// MinioSecret returns secret containing Minio accesskey and secretkey. -func MinioSecret(adapter gitlab.CustomResourceAdapter) *corev1.Secret { - labels := Label(adapter.ReleaseName(), "minio", GitlabType) - options := SystemBuildOptions(adapter) - - secretKey := Password(PasswordOptions{ - EnableSpecialChars: false, - Length: 48, - }) - - minio := GenericSecret(options.ObjectStore.Credentials, adapter.Namespace(), labels) - - minio.Data = map[string][]byte{ - "accesskey": []byte("gitlab"), - "secretkey": []byte(secretKey), - } - - return minio -} - -// MinioStatefulSet return Minio statefulset. -func MinioStatefulSet(adapter gitlab.CustomResourceAdapter) *appsv1.StatefulSet { - labels := Label(adapter.ReleaseName(), "minio", GitlabType) - options := SystemBuildOptions(adapter) - - var replicas int32 = 1 - - minio := GenericStatefulSet(Component{ - Namespace: adapter.Namespace(), - Labels: labels, - Replicas: replicas, - InitContainers: []corev1.Container{ - { - Name: "configure", - Image: "busybox:latest", - ImagePullPolicy: corev1.PullIfNotPresent, - Command: []string{"sh", "/config/configure"}, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": ResourceQuantity("50m"), - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "minio-configuration", - MountPath: "/config", - }, - { - Name: "minio-server-config", - MountPath: "/minio", - }, - }, - }, - }, - Containers: []corev1.Container{ - { - Name: "minio", - Image: "minio/minio:RELEASE.2017-12-28T01-21-00Z", - ImagePullPolicy: corev1.PullIfNotPresent, - Args: []string{"-C", "/tmp/.minio", "--quiet", "server", "/export"}, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": ResourceQuantity("100m"), - "memory": ResourceQuantity("128Mi"), - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "export", - MountPath: "/export", - }, - { - Name: "minio-server-config", - MountPath: "/tmp/.minio", - }, - { - Name: "podinfo", - MountPath: "/podinfo", - ReadOnly: false, - }, - }, - Ports: []corev1.ContainerPort{ - { - Name: "service", - Protocol: corev1.ProtocolTCP, - ContainerPort: 9000, - }, - }, - LivenessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - TCPSocket: &corev1.TCPSocketAction{ - Port: intstr.IntOrString{ - IntVal: 9000, - }, - }, - }, - TimeoutSeconds: 1, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "podinfo", - VolumeSource: corev1.VolumeSource{ - DownwardAPI: &corev1.DownwardAPIVolumeSource{ - Items: []corev1.DownwardAPIVolumeFile{ - { - Path: "labels", - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.labels", - }, - }, - }, - }, - }, - }, - { - Name: "minio-server-config", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{ - Medium: corev1.StorageMediumMemory, - }, - }, - }, - { - Name: "minio-configuration", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - Sources: []corev1.VolumeProjection{ - { - ConfigMap: &corev1.ConfigMapProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: adapter.ReleaseName() + "-minio-script", - }, - }, - }, - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: options.ObjectStore.Credentials, - }, - }, - }, - }, - }, - }, - }, - }, - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "export", - Namespace: adapter.Namespace(), - Labels: labels, - }, - Spec: corev1.PersistentVolumeClaimSpec{ - AccessModes: []corev1.PersistentVolumeAccessMode{ - corev1.ReadWriteOnce, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "storage": ResourceQuantity(options.ObjectStore.Capacity), - }, - }, - }, - }, - }, - }) - - minio.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{ - RunAsUser: &localUser, - FSGroup: &localUser, - } - - minio.Spec.Template.Spec.ServiceAccountName = settings.AppServiceAccount - - return minio -} - -// MinioScriptConfigMap returns scripts used to configure Minio. -func MinioScriptConfigMap(adapter gitlab.CustomResourceAdapter) *corev1.ConfigMap { - labels := Label(adapter.ReleaseName(), "minio", GitlabType) - - initScript := ReadConfig(os.Getenv("GITLAB_OPERATOR_ASSETS") + "/templates/minio/initialize-buckets.sh") - configureScript := ReadConfig(os.Getenv("GITLAB_OPERATOR_ASSETS") + "/templates/minio/configure.sh") - configJSON := ReadConfig(os.Getenv("GITLAB_OPERATOR_ASSETS") + "/templates/minio/config.json") - - init := GenericConfigMap(adapter.ReleaseName()+"-minio-script", adapter.Namespace(), labels) - init.Data = map[string]string{ - "initialize": initScript, - "configure": configureScript, - "config.json": configJSON, - } - - return init -} - -// MinioIngress returns the Ingress that exposes MinIO. -func MinioIngress(adapter gitlab.CustomResourceAdapter) *networkingv1.Ingress { - ingressClass := adapter.Values().GetString("global.ingress.class") - if ingressClass == "" { - ingressClass = fmt.Sprintf("%s-nginx", adapter.ReleaseName()) - } - - labels := Label(adapter.ReleaseName(), "minio", GitlabType) - annotations := make(map[string]string) - - if provider := adapter.Values().GetString("global.ingress.provider"); provider == "nginx" { - for k, v := range gitlab.NGINXAnnotations() { - annotations[k] = v - } - } - - configureCertmanager := CertManagerEnabled(adapter) - - if configureCertmanager { - annotations["cert-manager.io/issuer"] = fmt.Sprintf("%s-issuer", adapter.ReleaseName()) - annotations["acme.cert-manager.io/http01-edit-in-place"] = "true" - } - - minioIngressTLSSecretName := adapter.Values().GetString("minio.ingress.tls.secretName") - globalIngressTLSSecretName := adapter.Values().GetString("global.ingress.tls.secretName") - wildcardIngressTLSSecretName := fmt.Sprintf("%s-wildcard-tls", adapter.ReleaseName()) - certmanagerIngressTLSSecretName := fmt.Sprintf("%s-minio-tls", adapter.ReleaseName()) - - // To determine the secret name, copy the 'minio.tlsSecret' template logic until MinIO generated resources are removed. - // https://gitlab.com/gitlab-org/charts/gitlab/blob/8bc9d9e5f883e6d750cc957d4c1c67e65a9222df/charts/minio/templates/_helpers.tpl#L41-54 - var tlsSecretName string - if minioIngressTLSSecretName != "" { - tlsSecretName = minioIngressTLSSecretName - } else if globalIngressTLSSecretName != "" { - tlsSecretName = globalIngressTLSSecretName - } else if configureCertmanager { - tlsSecretName = certmanagerIngressTLSSecretName - } else { - tlsSecretName = wildcardIngressTLSSecretName - } - - url := getMinioURL(adapter) - pathType := networkingv1.PathTypePrefix - - return &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: labels["app.kubernetes.io/instance"], - Namespace: adapter.Namespace(), - Labels: labels, - Annotations: annotations, - }, - Spec: networkingv1.IngressSpec{ - IngressClassName: &ingressClass, - Rules: []networkingv1.IngressRule{ - { - Host: url, - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{ - Paths: []networkingv1.HTTPIngressPath{ - { - Path: "/", - PathType: &pathType, - Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{ - Name: MinioService(adapter).Name, - Port: networkingv1.ServiceBackendPort{ - Number: 9000, - }, - }, - }, - }, - }, - }, - }, - }, - }, - TLS: []networkingv1.IngressTLS{ - { - Hosts: []string{url}, - SecretName: tlsSecretName, - }, - }, - }, - } -} - -// MinioService returns service that exposes Minio. -func MinioService(adapter gitlab.CustomResourceAdapter) *corev1.Service { - labels := Label(adapter.ReleaseName(), "minio", GitlabType) - - return &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: labels["app.kubernetes.io/instance"], - Namespace: adapter.Namespace(), - Labels: labels, - }, - Spec: corev1.ServiceSpec{ - Selector: labels, - Ports: []corev1.ServicePort{ - { - Name: "minio", - Port: 9000, - TargetPort: intstr.FromInt(9000), - Protocol: corev1.ProtocolTCP, - }, - }, - Type: corev1.ServiceTypeClusterIP, - }, - } -} - -// AppConfigConnectionSecret returns secret containing MinIO connection config for `global.appConfig.object_store.connection.secret`. -func AppConfigConnectionSecret(adapter gitlab.CustomResourceAdapter, minioSecret corev1.Secret) (*corev1.Secret, error) { - labels := Label(adapter.ReleaseName(), "minio", GitlabType) - options := SystemBuildOptions(adapter) - secret := GenericSecret(settings.AppConfigConnectionSecretName, adapter.Namespace(), labels) - - data := minioSecret.Data - - connectionInfo := map[string]string{ - "provider": "AWS", - "region": settings.Region, - "host": options.ObjectStore.URL, - "endpoint": options.ObjectStore.Endpoint, - "aws_access_key_id": string(data["accesskey"]), - "aws_secret_access_key": string(data["secretkey"]), - "path_style": "true", - } - - connectionBytes, err := json.Marshal(connectionInfo) - if err != nil { - return &corev1.Secret{}, fmt.Errorf("unable to encode connection string for storage-config") - } - - secret.Data = map[string][]byte{ - "connection": connectionBytes, - } - - return secret, nil -} - -// RegistryConnectionSecret returns secret containing MinIO connection config for `registry.storage.secret`. -func RegistryConnectionSecret(adapter gitlab.CustomResourceAdapter, minioSecret corev1.Secret) (*corev1.Secret, error) { - labels := Label(adapter.ReleaseName(), "minio", GitlabType) - options := SystemBuildOptions(adapter) - secret := GenericSecret(settings.RegistryConnectionSecretName, adapter.Namespace(), labels) - - data := minioSecret.Data - - minioEndpoint := options.ObjectStore.Endpoint - minioRedirect := adapter.Values().GetBool("registry.minio.redirect") - - if minioRedirect { - // We can always assume it is HTTPS. - minioEndpoint = fmt.Sprintf("https://%s", getMinioURL(adapter)) - } - - connectionInfo := map[string]map[string]string{ - "s3": { - "bucket": settings.RegistryBucket, - "accesskey": string(data["accesskey"]), - "secretkey": string(data["secretkey"]), - "region": settings.Region, - "regionendpoint": minioEndpoint, - "v4auth": "true", - "path_style": "true", - }, - } - - connectionBytes, err := yaml.Marshal(connectionInfo) - if err != nil { - return &corev1.Secret{}, fmt.Errorf("unable to encode connection string for registry") - } - - secret.Data = map[string][]byte{ - "config": connectionBytes, - } - - return secret, nil -} - -// ToolboxConnectionSecret returns secret containing MinIO connection config for `global.toolbox.backups.objectStorage.config.secret`. -func ToolboxConnectionSecret(adapter gitlab.CustomResourceAdapter, minioSecret corev1.Secret) *corev1.Secret { - labels := Label(adapter.ReleaseName(), "minio", GitlabType) - secret := GenericSecret(settings.ToolboxConnectionSecretName, adapter.Namespace(), labels) - url := getMinioURL(adapter) - data := minioSecret.Data - - template := ` -[default] -access_key = %s -secret_key = %s -bucket_location = %s -host_base = %s -host_bucket = %s/%%(bucket) -default_mime_type = binary/octet-stream -enable_multipart = True -multipart_max_chunks = 10000 -multipart_chunk_size_mb = 128 -recursive = True -recv_chunk = 65536 -send_chunk = 65536 -server_side_encryption = False -signature_v2 = True -socket_timeout = 300 -use_mime_magic = False -verbosity = WARNING -website_endpoint = https://%s -` - - result := fmt.Sprintf(template, data["accesskey"], data["secretkey"], settings.Region, url, url, url) - - secret.Data = map[string][]byte{ - "config": []byte(result), - } - - return secret -} - -func getMinioURL(adapter gitlab.CustomResourceAdapter) string { - name := adapter.Values().GetString("global.hosts.minio.name") - if name != "" { - return name - } - - hostSuffix := adapter.Values().GetString("global.hosts.hostSuffix") - domain := adapter.Values().GetString("global.hosts.domain") - - if hostSuffix != "" { - return fmt.Sprintf("minio-%s.%s", hostSuffix, domain) - } - - return fmt.Sprintf("minio.%s", domain) -} diff --git a/controllers/internal/template.go b/controllers/internal/template.go index 412101a4d7f6143f4fc6328f3ca7cd43d36f047d..5325867058306809925de3c0f36142247c9be493 100644 --- a/controllers/internal/template.go +++ b/controllers/internal/template.go @@ -1,114 +1,10 @@ package internal import ( - "strings" - - "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/gitlab" - - appsv1 "k8s.io/api/apps/v1" - batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// Component represents an application / micro-service -// that makes part of a larger application. -type Component struct { - // Namespace of the component. - Namespace string - - // Defines the number of pods for the component to be created. - Replicas int32 - - // Labels for the component. - Labels map[string]string - - // InitContainers contains a list of containers that may - // need to run before the main application container starts up. - InitContainers []corev1.Container - - // Containers containers a list of containers that make up a pod. - Containers []corev1.Container - - // Contains a list of volumes used by the containers. - Volumes []corev1.Volume - - // Defines volume claims to be used by a statefulset. - VolumeClaimTemplates []corev1.PersistentVolumeClaim -} - -// GenericStatefulSet returns a generic k8s statefulset. -func GenericStatefulSet(component Component) *appsv1.StatefulSet { - labels := component.Labels - - return &appsv1.StatefulSet{ - TypeMeta: metav1.TypeMeta{ - Kind: gitlab.StatefulSetKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: labels["app.kubernetes.io/instance"], - Namespace: component.Namespace, - Labels: labels, - }, - Spec: appsv1.StatefulSetSpec{ - ServiceName: strings.Join([]string{labels["app.kubernetes.io/instance"], "headless"}, "-"), - VolumeClaimTemplates: component.VolumeClaimTemplates, - Selector: &metav1.LabelSelector{ - MatchLabels: labels, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: labels, - }, - Spec: corev1.PodSpec{ - InitContainers: component.InitContainers, - Containers: component.Containers, - Volumes: component.Volumes, - }, - }, - }, - } -} - -// GenericJob returns a Kubernetes Job. -func GenericJob(component Component) *batchv1.Job { - labels := component.Labels - - var ( - replicas int32 = 1 - backoffLimit int32 = 6 - activeDeadlineSec int64 = 3600 - ) - - return &batchv1.Job{ - TypeMeta: metav1.TypeMeta{ - Kind: gitlab.JobKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: labels["app.kubernetes.io/instance"], - Namespace: component.Namespace, - Labels: labels, - }, - Spec: batchv1.JobSpec{ - Parallelism: &replicas, - Completions: &replicas, - BackoffLimit: &backoffLimit, - ActiveDeadlineSeconds: &activeDeadlineSec, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: labels, - }, - Spec: corev1.PodSpec{ - InitContainers: component.InitContainers, - Containers: component.Containers, - Volumes: component.Volumes, - RestartPolicy: corev1.RestartPolicyOnFailure, - }, - }, - }, - } -} - // ServiceAccount returns service account to be used by pods. func ServiceAccount(name, namespace string) *corev1.ServiceAccount { return &corev1.ServiceAccount{ @@ -122,33 +18,3 @@ func ServiceAccount(name, namespace string) *corev1.ServiceAccount { }, } } - -// GenericSecret returns empty secret. -func GenericSecret(name, namespace string, labels map[string]string) *corev1.Secret { - return &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: gitlab.SecretKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: labels, - }, - StringData: map[string]string{}, - } -} - -// GenericConfigMap returns empty configmap. -func GenericConfigMap(name, namespace string, labels map[string]string) *corev1.ConfigMap { - return &corev1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - Kind: gitlab.ConfigMapKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: labels, - }, - Data: map[string]string{}, - } -} diff --git a/controllers/internal/tool.go b/controllers/internal/tool.go index 4541866c6b7548e29d78e5b622dbf9df2bf17ed4..f1070884fe5d95b62c136c7546b91fb973c9e1e6 100644 --- a/controllers/internal/tool.go +++ b/controllers/internal/tool.go @@ -1,29 +1,13 @@ package internal import ( - "context" - "encoding/hex" "fmt" - "io/ioutil" - "math/rand" "strings" - "time" - "crypto/sha256" - "encoding/json" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/discovery" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" ) @@ -38,11 +22,6 @@ func Label(resource, component, resourceType string) map[string]string { } } -// ResourceQuantity returns quantity requested for resource. -func ResourceQuantity(request string) resource.Quantity { - return resource.MustParse(request) -} - // IsOpenshift check if API has the API route.openshift.io/v1, // then it is considered an openshift environment. func IsOpenshift() bool { @@ -95,152 +74,3 @@ func (k KubeConfig) NewKubernetesClient() (*kubernetes.Clientset, error) { return kubernetes.NewForConfig(conf) } - -// GetSecretValue returns the value for a key from an existing secret. -func GetSecretValue(client client.Client, namespace, secret, key string) (string, error) { - target := &corev1.Secret{} - - err := client.Get(context.TODO(), types.NamespacedName{Name: secret, Namespace: namespace}, target) - if err != nil { - return "", err - } - - return string(target.Data[key]), err -} - -// ReadConfig returns contents of file as string. -func ReadConfig(filename string) string { - content, err := ioutil.ReadFile(filename) - if err != nil { - // log.Error(err, "Error reading %s", filename) - fmt.Printf("Error reading %s: %v", filename, err) - } - - return string(content) -} - -// Password creates an password string based on the password options provided. -func Password(options PasswordOptions) string { - password := make([]byte, options.Length) - charset := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890") - special := []byte("+,#?$()&%^*=/!+<>[]{}@-_") - - // add special characters if not database password - if options.EnableSpecialChars { - charset = append(charset, special...) - } - - //nolint:gosec // This will go away with #137, which will remove Minio objects from the controller. - seed := rand.New(rand.NewSource(time.Now().UnixNano())) - - for i := range password { - password[i] = charset[seed.Intn(len(charset))] - } - - return string(password) -} - -// SecretData gets a secret by name and returns its data. -func SecretData(name, namespace string) (map[string]string, error) { - client, err := KubernetesConfig().NewKubernetesClient() - if err != nil { - return map[string]string{}, err - } - - secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - return map[string]string{}, err - } - - return secret.StringData, nil -} - -// ConfigMapData returns data contained in a configmap. -func ConfigMapData(name, namespace string) (map[string]string, error) { - client, err := KubernetesConfig().NewKubernetesClient() - if err != nil { - return map[string]string{}, err - } - - cm, err := client.CoreV1().ConfigMaps(namespace).Get(context.Background(), name, metav1.GetOptions{}) - if err != nil { - return map[string]string{}, err - } - - return cm.Data, nil -} - -// GetDeploymentPods returns the pods that belong to a given deployment. -func GetDeploymentPods(kclient client.Client, name, namespace string) (result []corev1.Pod, err error) { - deployment := &appsv1.Deployment{} - - err = kclient.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, deployment) - if err != nil && errors.IsNotFound(err) { - return result, err - } - - deployLabels := deployment.Spec.Template.ObjectMeta.Labels - - pods := &corev1.PodList{} - options := &client.ListOptions{ - Namespace: namespace, - LabelSelector: labels.SelectorFromSet(deployLabels), - } - - err = kclient.List(context.TODO(), pods, options) - if err != nil { - return []corev1.Pod{}, err - } - - result = append(result, pods.Items...) - - return result, err -} - -// ConfigMapWithHash updates configmap with -// annotation containing a SHA256 hash of its data. -func ConfigMapWithHash(cm *corev1.ConfigMap) { - jdata, err := json.Marshal(cm.Data) - if err != nil { - return - } - - hash := sha256.Sum256(jdata) - - cm.Annotations = map[string]string{ - "checksum": hex.EncodeToString(hash[:]), - } -} - -// DeploymentConfigMaps returns a list of configmaps used in a deployment. -func DeploymentConfigMaps(deploy *appsv1.Deployment) []string { - cms := []string{} - - for _, container := range deploy.Spec.Template.Spec.Containers { - if len(container.Env) != 0 { - for _, env := range container.Env { - if env.ValueFrom != nil { - if env.ValueFrom.ConfigMapKeyRef != nil { - cms = append(cms, env.ValueFrom.ConfigMapKeyRef.LocalObjectReference.Name) - } - } - } - } - } - - for _, vol := range deploy.Spec.Template.Spec.Volumes { - if vol.VolumeSource.ConfigMap != nil { - cms = append(cms, vol.VolumeSource.ConfigMap.LocalObjectReference.Name) - } - - if vol.VolumeSource.Projected != nil { - for _, source := range vol.VolumeSource.Projected.Sources { - if source.ConfigMap != nil { - cms = append(cms, source.ConfigMap.LocalObjectReference.Name) - } - } - } - } - - return cms -} diff --git a/controllers/internal/types.go b/controllers/internal/types.go deleted file mode 100644 index 81aa58848ac0fec5cb50e33be7d946a5cd30470f..0000000000000000000000000000000000000000 --- a/controllers/internal/types.go +++ /dev/null @@ -1,114 +0,0 @@ -package internal - -import ( - "fmt" - "strings" - - "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/gitlab" -) - -const ( - // GitlabType represents resource of type Gitlab. - GitlabType = "gitlab" -) - -var ( - // ConfigMapDefaultMode for configmap projected volume. - ConfigMapDefaultMode int32 = 420 - - // ExecutableDefaultMode for configmap projected volume. - ExecutableDefaultMode int32 = 493 - - // ProjectedVolumeDefaultMode for projected volume. - ProjectedVolumeDefaultMode int32 = 256 - - // SecretDefaultMode for secret projected volume. - SecretDefaultMode int32 = 288 -) - -// PasswordOptions provides parameters to be -// used when generating passwords. -type PasswordOptions struct { - // Length defines desired password length. - Length int - - // EnableSpecialCharacters adds special characters - // to generated passwords. - EnableSpecialChars bool -} - -// ConfigurationOptions holds options used to configure the different -// GitLab components. -type ConfigurationOptions struct { - // ObjectStore defines object that describes values - // for the S3 compatible storage service. - ObjectStore ObjectStoreOptions -} - -// ObjectStoreOptions defines properties for -// the S3 storage used by GitLab. -type ObjectStoreOptions struct { - // URL defines address for development - // S3 storage service. - URL string - - // Endpoint defines the URL the API endpoint - // including the protocol. - Endpoint string - - // Credentials is the name of the secret - // that contains the 'accesskey' and 'secretkey'. - Credentials string - - // Capacity of the volume to be used by the development - // minio instance. - Capacity string -} - -// SystemBuildOptions retrieves options from the Gitlab custom resource -// and uses them to build configuration options used to deploy -// the Gitlab instance. -func SystemBuildOptions(adapter gitlab.CustomResourceAdapter) ConfigurationOptions { - objectStoreEnabled := adapter.Values().GetBool("global.appConfig.object_store.enabled") - objectStoreHost := adapter.Values().GetString("global.hosts.minio.name") - // This implies that we only support global object-store config. - objectStoreSecret := adapter.Values().GetString("global.appConfig.object_store.connection.secret") - - options := ConfigurationOptions{ - ObjectStore: ObjectStoreOptions{ - URL: objectStoreHost, - Credentials: strings.Join([]string{adapter.ReleaseName(), "minio-secret"}, "-"), - }, - } - - objectStoreCapacity := adapter.Values().GetString("minio.persistence.size") - if objectStoreCapacity == "" { - objectStoreCapacity = "5Gi" - } - - if objectStoreEnabled { - options.ObjectStore.URL = getName(adapter.ReleaseName(), "minio") - options.ObjectStore.Capacity = objectStoreCapacity - } - - if objectStoreHost == "" { - options.ObjectStore.Endpoint = "" - } - - if objectStoreEnabled { - minioSocket := []string{"http://", fmt.Sprintf("%s-minio", adapter.ReleaseName()), ":9000"} - options.ObjectStore.Endpoint = strings.Join(minioSocket, "") - } else { - options.ObjectStore.Endpoint = fmt.Sprintf("https://%s", objectStoreHost) - } - - if !objectStoreEnabled && options.ObjectStore.Credentials != "" { - options.ObjectStore.Credentials = objectStoreSecret - } - - return options -} - -func getName(cr, component string) string { - return strings.Join([]string{cr, component}, "-") -} diff --git a/controllers/minio.go b/controllers/minio.go index d6c723d0f93f2d46107b9d11845da620cb82aac8..ffe441b34a12f71f0a9eaaf7fa76522f85d3b6ae 100644 --- a/controllers/minio.go +++ b/controllers/minio.go @@ -3,68 +3,42 @@ package controllers import ( "context" - "k8s.io/apimachinery/pkg/api/errors" - gitlabctl "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/gitlab" - "gitlab.com/gitlab-org/cloud-native/gitlab-operator/controllers/internal" + "gitlab.com/gitlab-org/cloud-native/gitlab-operator/helm" ) -func (r *GitLabReconciler) reconcileMinioInstance(ctx context.Context, adapter gitlabctl.CustomResourceAdapter) error { - cm := internal.MinioScriptConfigMap(adapter) +func (r *GitLabReconciler) reconcileMinioInstance(ctx context.Context, adapter gitlabctl.CustomResourceAdapter, template helm.Template) error { + cm := gitlabctl.MinioConfigMap(adapter, template) if _, err := r.createOrPatch(ctx, cm, adapter); err != nil { return err } - secret := internal.MinioSecret(adapter) - if _, err := r.createOrPatch(ctx, secret, adapter); err != nil && errors.IsAlreadyExists(err) { - return err - } - - appConfigSecret, err := internal.AppConfigConnectionSecret(adapter, *secret) - if err != nil { - return err - } - - if _, err := r.createOrPatch(ctx, appConfigSecret, adapter); err != nil && errors.IsAlreadyExists(err) { - return err - } - - registryConnectionSecret, err := internal.RegistryConnectionSecret(adapter, *secret) - if err != nil { - return err - } - - if _, err := r.createOrPatch(ctx, registryConnectionSecret, adapter); err != nil && errors.IsAlreadyExists(err) { - return err - } - - toolboxConnectionSecret := internal.ToolboxConnectionSecret(adapter, *secret) - if _, err := r.createOrPatch(ctx, toolboxConnectionSecret, adapter); err != nil && errors.IsAlreadyExists(err) { + buckets := gitlabctl.MinioJob(adapter, template) + if _, err := r.createOrPatch(ctx, buckets, adapter); err != nil { return err } - svc := internal.MinioService(adapter) + svc := gitlabctl.MinioService(adapter, template) if _, err := r.createOrPatch(ctx, svc, adapter); err != nil { return err } - minio := internal.MinioStatefulSet(adapter) - if err := r.annotateSecretsChecksum(ctx, adapter, minio); err != nil { + pvc := gitlabctl.MinioPersistentVolumeClaim(adapter, template) + if _, err := r.createOrPatch(ctx, pvc, adapter); err != nil { return err } - _, err = r.createOrPatch(ctx, minio, adapter) - if err != nil { + minio := gitlabctl.MinioDeployment(adapter, template) + if err := r.annotateSecretsChecksum(ctx, adapter, minio); err != nil { return err } - buckets := internal.BucketCreationJob(adapter) - if _, err := r.createOrPatch(ctx, buckets, adapter); err != nil { + if _, err := r.createOrPatch(ctx, minio, adapter); err != nil { return err } - ingress := internal.MinioIngress(adapter) - if err = r.reconcileIngress(ctx, ingress, adapter); err != nil { + ingress := gitlabctl.MinioIngress(adapter, template) + if err := r.reconcileIngress(ctx, ingress, adapter); err != nil { return err } diff --git a/doc/index.md b/doc/index.md index b065fef5b98c9d09dfe18f8866a6768d9850e874..badb29df63eca223770f35fbc796f7e38dfc8864 100644 --- a/doc/index.md +++ b/doc/index.md @@ -43,7 +43,3 @@ Below is a list of components that are not yet recommended for production when deployed by the GitLab Operator: - KAS: [#353](https://gitlab.com/gitlab-org/cloud-native/gitlab-operator/-/issues/353) - -### Components not sourced from GitLab Helm Charts - -- MinIO: [#374](https://gitlab.com/gitlab-org/cloud-native/gitlab-operator/-/issues/374) diff --git a/hack/assets/templates/minio/config.json b/hack/assets/templates/minio/config.json deleted file mode 100644 index 75132121fc70990237be3f880e4aed23934b67d3..0000000000000000000000000000000000000000 --- a/hack/assets/templates/minio/config.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "version": "20", - "credential": { - "accessKey": "ACCESS_KEY", - "secretKey": "SECRET_KEY" - }, - "region": "us-east-1", - "browser": "on", - "domain": "", - "logger": { - "console": { - "enable": true - }, - "file": { - "enable": false, - "fileName": "" - } - }, - "notify": { - "amqp": { - "1": { - "enable": false, - "url": "", - "exchange": "", - "routingKey": "", - "exchangeType": "", - "deliveryMode": 0, - "mandatory": false, - "immediate": false, - "durable": false, - "internal": false, - "noWait": false, - "autoDeleted": false - } - }, - "nats": { - "1": { - "enable": false, - "address": "", - "subject": "", - "username": "", - "password": "", - "token": "", - "secure": false, - "pingInterval": 0, - "streaming": { - "enable": false, - "clusterID": "", - "clientID": "", - "async": false, - "maxPubAcksInflight": 0 - } - } - }, - "elasticsearch": { - "1": { - "enable": false, - "format": "namespace", - "url": "", - "index": "" - } - }, - "redis": { - "1": { - "enable": false, - "format": "namespace", - "address": "", - "password": "", - "key": "" - } - }, - "postgresql": { - "1": { - "enable": false, - "format": "namespace", - "connectionString": "", - "table": "", - "host": "", - "port": "", - "user": "", - "password": "", - "database": "" - } - }, - "kafka": { - "1": { - "enable": false, - "brokers": null, - "topic": "" - } - }, - "webhook": { - "1": { - "enable": false, - "endpoint": "" - } - }, - "mysql": { - "1": { - "enable": false, - "format": "namespace", - "dsnString": "", - "table": "", - "host": "", - "port": "", - "user": "", - "password": "", - "database": "" - } - }, - "mqtt": { - "1": { - "enable": false, - "broker": "", - "topic": "", - "qos": 0, - "clientId": "", - "username": "", - "password": "" - } - } - } -} diff --git a/hack/assets/templates/minio/configure.sh b/hack/assets/templates/minio/configure.sh deleted file mode 100644 index d7837853d8ad055cda61162663b30aca9857194f..0000000000000000000000000000000000000000 --- a/hack/assets/templates/minio/configure.sh +++ /dev/null @@ -1 +0,0 @@ -sed -e 's@ACCESS_KEY@'"$(cat /config/accesskey)"'@' -e 's@SECRET_KEY@'"$(cat /config/secretkey)"'@' /config/config.json > /minio/config.json diff --git a/hack/assets/templates/minio/initialize-buckets.sh b/hack/assets/templates/minio/initialize-buckets.sh deleted file mode 100644 index c4ec31f202c31089885c2792c35c91fd0ba2e90c..0000000000000000000000000000000000000000 --- a/hack/assets/templates/minio/initialize-buckets.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh -# minio/mc container has Busybox Ash, be sure to be POSIX compliant and avoid Bash-isms -set -e ; # Have script exit in the event of a failed command. - -# connectToMinio -# Use a check-sleep-check loop to wait for Minio service to be available -connectToMinio() { - set -e ; # fail if we can't read the keys. - ACCESS=$(cat /config/accesskey) ; SECRET=$(cat /config/secretkey) ; - set +e ; # The connections to minio are allowed to fail. - echo "Connecting to Minio server: $MINIO_ENDPOINT" ; - MC_COMMAND="mc config host add myminio $MINIO_ENDPOINT $ACCESS $SECRET" ; - $MC_COMMAND ; - STATUS=$? ; - until [ $STATUS -eq 0 ] ; - do - sleep 1 ; # 1 second intervals between attempts - $MC_COMMAND ; - STATUS=$? ; - done ; - set -e ; # reset `e` as active - return 0 -} - -# checkBucketExists ($bucket) -# Check if the bucket exists, by using the exit code of `mc ls` -checkBucketExists() { - BUCKET=$1 - CMD=$(/usr/bin/mc ls myminio/$BUCKET > /dev/null 2>&1) - return $? -} - -# createBucket ($bucket, $policy, $purge) -# Ensure bucket exists, purging if asked to -createBucket() { - BUCKET=$1 - POLICY=$2 - PURGE=$3 - - - # Purge the bucket, if set & exists - # Since PURGE is user input, check explicitly for `true` - if [ $PURGE = true ]; then - if checkBucketExists $BUCKET ; then - echo "Purging bucket '$BUCKET'." - set +e ; # don't exit if this fails - /usr/bin/mc rm -r --force myminio/$BUCKET - set -e ; # reset `e` as active - else - echo "Bucket '$BUCKET' does not exist, skipping purge." - fi - fi - - # Create the bucket if it does not exist - if ! checkBucketExists $BUCKET ; then - echo "Creating bucket '$BUCKET'" - /usr/bin/mc mb myminio/$BUCKET - else - echo "Bucket '$BUCKET' already exists." - fi - - # At this point, the bucket should exist, skip checking for existance - # Set policy on the bucket - echo "Setting policy of bucket '$BUCKET' to '$POLICY'." - /usr/bin/mc policy $POLICY myminio/$BUCKET -} - -connectToMinio -createBucket registry none false -createBucket git-lfs none false -createBucket runner-cache none false -createBucket gitlab-uploads none false -createBucket gitlab-artifacts none false -createBucket gitlab-backups none false -createBucket gitlab-packages none false -createBucket tmp none false -createBucket gitlab-pseudo none false -createBucket gitlab-mr-diffs none false -createBucket gitlab-terraform-state none false -createBucket gitlab-pages none false