From 07fd0afabbcc17c5212b831fb90a63e5c5358097 Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Thu, 14 May 2020 23:16:59 +0530 Subject: [PATCH] feat: Add support for KES (#95) This PR also cleans up few helper methods. --- README.md | 33 ++- docs/kes.md | 58 +++++ docs/mcs.md | 41 +++ docs/mirror.md | 44 ++++ docs/operator-fields.md | 8 +- examples/kes-config-secret.yaml | 60 +++++ examples/minioinstance-kes.yaml | 176 +++++++++++++ examples/minioinstance-mcs.yaml | 162 ++++++++++++ examples/minioinstance.yaml | 7 +- examples/mirrorinstance.yaml | 2 +- go.mod | 2 + go.sum | 5 + main.go | 1 + .../operator.min.io/v1}/constants.go | 167 ++++++------ pkg/apis/operator.min.io/v1/globals.go | 54 ++++ pkg/apis/operator.min.io/v1/helper.go | 246 +++++++++++------- pkg/apis/operator.min.io/v1/helper_test.go | 7 +- pkg/apis/operator.min.io/v1/labels.go | 39 +++ pkg/apis/operator.min.io/v1/names.go | 131 ++++++++++ pkg/apis/operator.min.io/v1/types.go | 40 ++- .../v1/zz_generated.deepcopy.go | 84 ++++-- pkg/client/clientset/versioned/clientset.go | 30 +-- pkg/client/clientset/versioned/doc.go | 30 +-- .../versioned/fake/clientset_generated.go | 30 +-- pkg/client/clientset/versioned/fake/doc.go | 30 +-- .../clientset/versioned/fake/register.go | 32 +-- pkg/client/clientset/versioned/scheme/doc.go | 30 +-- .../clientset/versioned/scheme/register.go | 30 +-- .../versioned/typed/operator.min.io/v1/doc.go | 30 +-- .../typed/operator.min.io/v1/fake/doc.go | 30 +-- .../v1/fake/fake_minioinstance.go | 30 +-- .../v1/fake/fake_mirrorinstance.go | 30 +-- .../v1/fake/fake_operator.min.io_client.go | 30 +-- .../operator.min.io/v1/generated_expansion.go | 30 +-- .../typed/operator.min.io/v1/minioinstance.go | 30 +-- .../operator.min.io/v1/mirrorinstance.go | 30 +-- .../v1/operator.min.io_client.go | 30 +-- .../informers/externalversions/factory.go | 30 +-- .../informers/externalversions/generic.go | 30 +-- .../internalinterfaces/factory_interfaces.go | 30 +-- .../operator.min.io/interface.go | 30 +-- .../operator.min.io/v1/interface.go | 30 +-- .../operator.min.io/v1/minioinstance.go | 30 +-- .../operator.min.io/v1/mirrorinstance.go | 30 +-- .../operator.min.io/v1/expansion_generated.go | 30 +-- .../operator.min.io/v1/minioinstance.go | 30 +-- .../operator.min.io/v1/mirrorinstance.go | 30 +-- pkg/controller/cluster/csr.go | 92 ++++--- pkg/controller/cluster/kes-csr.go | 152 +++++++++++ ...{main_controller.go => main-controller.go} | 138 ++++++++-- ...ror_controller.go => mirror-controller.go} | 2 +- .../{deployment.go => mcs-deployment.go} | 73 +++--- pkg/resources/jobs/kes-job.go | 146 +++++++++++ pkg/resources/jobs/{job.go => mirror-job.go} | 27 +- pkg/resources/services/service.go | 111 ++++---- pkg/resources/statefulsets/kes-statefulset.go | 167 ++++++++++++ .../{statefulset.go => minio-statefulset.go} | 132 ++++++---- 57 files changed, 2345 insertions(+), 844 deletions(-) create mode 100644 docs/kes.md create mode 100644 docs/mcs.md create mode 100644 docs/mirror.md create mode 100644 examples/kes-config-secret.yaml create mode 100644 examples/minioinstance-kes.yaml create mode 100644 examples/minioinstance-mcs.yaml rename pkg/{constants => apis/operator.min.io/v1}/constants.go (65%) create mode 100644 pkg/apis/operator.min.io/v1/globals.go create mode 100644 pkg/apis/operator.min.io/v1/labels.go create mode 100644 pkg/apis/operator.min.io/v1/names.go create mode 100644 pkg/controller/cluster/kes-csr.go rename pkg/controller/cluster/{main_controller.go => main-controller.go} (82%) rename pkg/controller/mirror/{mirror_controller.go => mirror-controller.go} (99%) rename pkg/resources/deployments/{deployment.go => mcs-deployment.go} (62%) create mode 100644 pkg/resources/jobs/kes-job.go rename pkg/resources/jobs/{job.go => mirror-job.go} (76%) create mode 100644 pkg/resources/statefulsets/kes-statefulset.go rename pkg/resources/statefulsets/{statefulset.go => minio-statefulset.go} (70%) diff --git a/README.md b/README.md index 5c51448c4b8..a2184fc2150 100644 --- a/README.md +++ b/README.md @@ -32,15 +32,6 @@ This will create all relevant resources required for the Operator to work. Here - `ClusterRoleBinding`: This cluster wide binding binds the service account `minio-operator-sa` to cluster role `minio-operator-role`. - `Deployment`: Deployment creates a pod using the MinIO-Operator Docker image. This is where the custom controller runs and looks after any changes in custom resource. -### Environment variables - -These variables may be passed to operator Deployment in order to modify some of its parameters - -| Name | Default | Description | -| --- | --- | --- | -| `WATCHED_NAMESPACE` | | If set, the operator will watch only MinIO resources deployed in the specified namespace. All namespaces are watched if empty | -| `CLUSTER_DOMAIN` | cluster.local | Cluster Domain of the Kubernetes cluster | - ### Create a MinIO instance Once MinIO-Operator deployment is running, you can create MinIO instances using the below command @@ -77,19 +68,27 @@ For example, to expose the created headless Service `minio-hl-svc` on http://min kubectl apply -f https://raw.githubusercontent.com/minio/minio-operator/master/examples/expose-via-istio.yaml ``` -## Features +### Environment variables -MinIO-Operator currently supports following features: +These variables may be passed to operator Deployment in order to modify some of its parameters -- Create and delete highly available distributed MinIO clusters. -- Expand an existing MinIO cluster. -- Upgrading existing distributed MinIO clusters. +| Name | Default | Description | +| --- | --- | --- | +| `WATCHED_NAMESPACE` | | If set, the operator will watch only MinIO resources deployed in the specified namespace. All namespaces are watched if empty | +| `CLUSTER_DOMAIN` | cluster.local | Cluster Domain of the Kubernetes cluster | -Refer [`minioinstance.yaml`](https://raw.githubusercontent.com/minio/minio-operator/master/examples/minioinstance.yaml) for details on how to pass supported fields to the operator. +## Features -## Upcoming features +MinIO-Operator currently supports following features: -- Continuous remote site mirroring with [`mc mirror`](https://docs.minio.io/docs/minio-client-complete-guide.html#mirror) +| Feature | Reference Document | +|-------------------------|--------------------| +| Create and delete highly available distributed MinIO clusters | [Create a MinIO Instance](https://github.com/minio/minio-operator#create-a-minio-instance). | +| Expand an existing MinIO cluster | [Expand a MinIO Cluster](https://github.com/minio/minio-operator#expand-a-minio-cluster). | +| Automatic TLS for MinIO | [Automatic TLS for MinIO Instance](https://github.com/minio/minio-operator/blob/master/docs/tls.md#automatic-csr-generation). | +| Deploy [MCS](https://github.com/minio/mcs) with MinIO cluster | [Deploy MinIO Instance with MCS](https://github.com/minio/minio-operator/blob/master/docs/mcs.md). | +| Deploy [KES](https://github.com/minio/kes) with MinIO cluster | [Deploy MinIO Instance with KES](https://github.com/minio/minio-operator/blob/master/docs/kes.md). | +| Deploy [mc mirror](https://docs.minio.io/docs/minio-client-complete-guide.html#mirror) | [Deploy Mirror Instance](https://github.com/minio/minio-operator/blob/master/docs/mirror.md). | ## Explore Further diff --git a/docs/kes.md b/docs/kes.md new file mode 100644 index 00000000000..f8ffa43b20a --- /dev/null +++ b/docs/kes.md @@ -0,0 +1,58 @@ +# MinIO Operator KES Configuration + +[![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io) +[![Docker Pulls](https://img.shields.io/docker/pulls/minio/k8s-operator.svg?maxAge=604800)](https://hub.docker.com/r/minio/k8s-operator) + +This document explains how to enable KES with MinIO Operator. + +## Getting Started + +### Prerequisites + +- MinIO Operator up and running as explained in the [document here](https://github.com/minio/minio-operator#create-operator-and-related-resources). +- KES requires TLS enabled for MinIO. Make sure TLS is enabled as explained in the [document here](https://github.com/minio/minio-operator/blob/master/docs/tls.md). +- KES requires a KMS backend in [configuration](https://raw.githubusercontent.com/minio/minio-operator/master/examples/kes-config-secret.yaml). Currently KES supports [AWS Secrets Manager](https://github.com/minio/kes/wiki/AWS-SecretsManager) and [Hashicorp Vault](https://github.com/minio/kes/wiki/Hashicorp-Vault-Keystore) as KMS backend for production. We recommend setting up one of these as the KMS backend before setting up KES. + +### Enable KES Configuration + +KES Configuration is a part of MinIOInstance yaml file. Check the sample file [available here](https://raw.githubusercontent.com/minio/minio-operator/master/examples/minioinstance-kes.yaml). The config offers below options + +#### KES Fields + +| Field | Description | +|-----------------------|-------------| +| spec.kes | Defines the KES configuration. Refer [this](https://github.com/minio/kes) | +| spec.kes.replicas | Number of KES pods to be created. | +| spec.kes.image | Defines the KES image. | +| spec.kes.configSecret | Secret to specify KES Configuration. This is a mandatory field. | +| spec.kes.selector | Add a selector for the KES. Which will be used by the KES pods for grouping. (Note: Should not match the labels provided in `spec.selector`) | +| spec.kes.metadata | This allows a way to map metadata to the KES pods. Internally `metadata` is a struct type as [explained here](https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#ObjectMeta). [Note: Should match the labels in `spec.kes.selector`] | + +### Create MinIO Instance + +Once you have updated the yaml file per your requirement, use `kubectl` to create the MinIO instance like + +``` +kubectl create -f examples/minioinstance-kes.yaml +``` + +Alternatively, you can deploy the example like this + +``` +kubectl create -f https://raw.githubusercontent.com/minio/minio-operator/master/examples/minioinstance-kes.yaml +``` + +KES uses CSR for self signed certificate generation. KES requires three certificates/key pairs for working + +- X.509 certificate for the KES server and the corresponding private key. +- X.509 certificate for the MinIO server and the corresponding private key. +- X.509 certificate for the KES client (MinIO is the KES client in this case) and the corresponding private key. + +Accordingly, you'll need to approve three CSR requests, using below approach + +``` +kubectl get csr +kubectl certificate approve +``` + +Once all the CSRs are approved, MinIO Operator will deploy KES Pods and start MinIO Server with KES integration. diff --git a/docs/mcs.md b/docs/mcs.md new file mode 100644 index 00000000000..91df066f72a --- /dev/null +++ b/docs/mcs.md @@ -0,0 +1,41 @@ +# MinIO Operator MCS Configuration + +[![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io) +[![Docker Pulls](https://img.shields.io/docker/pulls/minio/k8s-operator.svg?maxAge=604800)](https://hub.docker.com/r/minio/k8s-operator) + +This document explains how to enable MCS with MinIO Operator. + +## Getting Started + +### Prerequisites + +- MinIO Operator up and running as explained in the [document here](https://github.com/minio/minio-operator#create-operator-and-related-resources). + +### Enable MCS Configuration + +MCS Configuration is a part of MinIOInstance yaml file. Check the sample file [available here](https://raw.githubusercontent.com/minio/minio-operator/master/examples/minioinstance-mcs.yaml). The config offers below options + +#### MCS Fields + +| Field | Description | +|-----------------------|-------------| +| spec.mcs | Defines the mcs configuration. mcs is a graphical user interface for MinIO. Refer [this](https://github.com/minio/mcs) | +| spec.mcs.image | Defines the mcs image | +| spec.mcs.mcsAccessKey | Specify the access key to be used by mcs | +| spec.mcs.mcsSecret | Use this secret to assign mcs credentials to MinIOInstance. | +| spec.mcs.selector | Add a selector for the mcs. Which will be used by the mcs container for grouping. (Note: Should not match the labels provided in `spec.selector`) | +| spec.mcs.metadata | This allows a way to map metadata to the mcs container. Internally `metadata` is a struct type as [explained here](https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#ObjectMeta). [Note: Should match the labels in `spec.mcs.selector`] | + +### Create MinIO Instance + +Once you have updated the yaml file per your requirement, use `kubectl` to create the MinIO instance like + +``` +kubectl create -f examples/minioinstance-mcs.yaml +``` + +Alternatively, you can deploy the example like this + +``` +kubectl create -f https://raw.githubusercontent.com/minio/minio-operator/master/examples/minioinstance-mcs.yaml +``` diff --git a/docs/mirror.md b/docs/mirror.md new file mode 100644 index 00000000000..fb434d74d6a --- /dev/null +++ b/docs/mirror.md @@ -0,0 +1,44 @@ +# MinIO Operator Mirror Configuration + +[![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io) +[![Docker Pulls](https://img.shields.io/docker/pulls/minio/k8s-operator.svg?maxAge=604800)](https://hub.docker.com/r/minio/k8s-operator) + +This document explains how to enable Mirror with MinIO Operator. + +## Getting Started + +### Prerequisites + +- MinIO Operator up and running as explained in the [document here](https://github.com/minio/minio-operator#create-operator-and-related-resources). + +### Enable MCS Configuration + +Mirror Configuration is a part of MirrorInstance yaml file. Check the sample file [available here](https://raw.githubusercontent.com/minio/minio-operator/master/examples/mirrorinstance.yaml). The config offers below options + +#### Mirror Fields + +| Field | Description | +|-----------------------|-------------| +| kind | This defines the resource type to be created. MinIO Operator CRD defines the `kind` for Mirror Operation as `MirrorInstance`.| +| metadata | This field allows a way to assign metadata to a MirrorInstance. Internally `metadata` is a struct type as [explained here](https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#ObjectMeta).| +| spec.metadata | Define the object metadata to be passed to all the members pods of this MirrorInstance. This allows adding annotations and labels.| +| spec.image | Set the container registry and image tag for MinIO Client to be used in the MirrorInstance.| +| spec.env | Add Mirror specific environment variables. There are two mandatory fields required for Mirror to work. `MC_HOST_source` is the environment variable to specify the source MinIO cluster for mirror operation. `MC_HOST_target` is the environment variable to specify the target MinIO cluster for mirror operation. The value of these environment variables in the format `https://:@`. Refer [the document](https://github.com/minio/mc/blob/master/docs/minio-client-complete-guide.md#specify-host-configuration-through-environment-variable) for further details. | +| spec.args.source | Specify the source location for mirror operation. This can be a top level alias (e.g `source`), a bucket (e.g `source/bucket`), or a prefix (e.g `source/bucket/prefix`.) | +| spec.args.target | Specify the target location for mirror operation. This can be a top level alias (e.g `target`), a bucket (e.g `target/bucket`), or a prefix (e.g `target/bucket/prefix`.) | +| spec.args.flags | Specify the flags to fine tune the mirror operation. Refer the [mc mirror documentation](https://github.com/minio/mc/blob/master/docs/minio-client-complete-guide.md#mirror) for possible values for flags. | +| spec.resources | Specify CPU and Memory resources for each MirrorInstance Job container. Refer [this document](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-types) for details. | + +### Create Mirror Instance + +Once you have updated the yaml file per your requirement, use `kubectl` to create the Mirror instance like + +``` +kubectl create -f examples/mirrorinstance.yaml +``` + +Alternatively, you can deploy the example like this + +``` +kubectl create -f https://raw.githubusercontent.com/minio/minio-operator/master/examples/mirrorinstance.yaml +``` diff --git a/docs/operator-fields.md b/docs/operator-fields.md index 0403e56e53a..03fe3e0399c 100644 --- a/docs/operator-fields.md +++ b/docs/operator-fields.md @@ -44,11 +44,17 @@ If the MirrorInstance is named as `mirrorinstance`, resources and their names as | spec.tolerations | Define a toleration for the MinIOInstance pod to match on a taint. Refer [this document](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) for details. | | spec.securityContext | Define a security context for the MinIOInstance pod. Refer [this document](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for details. | | spec.mcs | Defines the mcs configuration. mcs is a graphical user interface for MinIO. Refer [this](https://github.com/minio/mcs) | -| spec.mcs.image | Defines the mcs image (If unspecified, It will be set to the default: `minio/mcs:v0.0.2`) | +| spec.mcs.image | Defines the mcs image. | | spec.mcs.mcsAccessKey | Specify the access key to be used by mcs | | spec.mcs.mcsSecret | Use this secret to assign mcs credentials to MinIOInstance. | | spec.mcs.selector | Add a selector for the mcs. Which will be used by the mcs container for grouping. (Note: Should not match the labels provided in `spec.selector`) | | spec.mcs.metadata | This allows a way to map metadata to the mcs container. Internally `metadata` is a struct type as [explained here](https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#ObjectMeta). [Note: Should match the labels in `spec.mcs.selector`] | +| spec.kes | Defines the KES configuration. Refer [this](https://github.com/minio/kes) | +| spec.kes.replicas | Number of KES pods to be created. | +| spec.kes.image | Defines the KES image. | +| spec.kes.configSecret | Secret to specify KES Configuration. This is a mandatory field. | +| spec.kes.selector | Add a selector for the KES. Which will be used by the KES pods for grouping. (Note: Should not match the labels provided in `spec.selector`) | +| spec.kes.metadata | This allows a way to map metadata to the KES pods. Internally `metadata` is a struct type as [explained here](https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#ObjectMeta). [Note: Should match the labels in `spec.kes.selector`] | ## MirrorInstance Fields diff --git a/examples/kes-config-secret.yaml b/examples/kes-config-secret.yaml new file mode 100644 index 00000000000..7aab850e36d --- /dev/null +++ b/examples/kes-config-secret.yaml @@ -0,0 +1,60 @@ +apiVersion: v1 +kind: Secret +metadata: + name: kes-config +type: Opaque +stringData: + server-config.yaml: |- + address: 0.0.0.0:7373 + root: _ # Effectively disabled since no root identity necessary. + tls: + key: /home/server.key # Path to the TLS private key + cert: /home/server.crt # Path to the TLS certificate + proxy: + identities: [] + header: + cert: X-Tls-Client-Cert + policy: + my-policy: + paths: + - /v1/key/create/* + - /v1/key/generate/* + - /v1/key/decrypt/* + identities: + - ${MINIO_ID} + cache: + expiry: + any: 5m0s + unused: 20s + log: + error: on + audit: off + keys: + fs: + path: "/kes" # Path to directory. Keys will be stored as files. Not Recommended for Production. + # vault: + # endpoint: "" # The Vault endpoint - e.g. https://127.0.0.1:8200 + # namespace: "" # An optional Vault namespace. See: https://www.vaultproject.io/docs/enterprise/namespaces/index.html + # prefix: "" # An optional K/V prefix. The server will store keys under this prefix. + # approle: # AppRole credentials. See: https://www.vaultproject.io/docs/auth/approle.html + # id: "" # Your AppRole Role ID + # secret: "" # Your AppRole Secret ID + # retry: 15s # Duration until the server tries to re-authenticate after connection loss. + # tls: # The Vault client TLS configuration for mTLS authentication and certificate verification + # key: "" # Path to the TLS client private key for mTLS authentication to Vault + # cert: "" # Path to the TLS client certificate for mTLS authentication to Vailt + # ca: "" # Path to one or multiple PEM root CA certificates + # status: # Vault status configuration. The server will periodically reach out to Vault to check its status. + # ping: 10s # Duration until the server checks Vault's status again. + # aws: + # # The AWS SecretsManager key store. The server will store + # # secret keys at the AWS SecretsManager encrypted with + # # AWS-KMS. See: https://aws.amazon.com/secrets-manager + # secretsmanager: + # endpoint: "" # The AWS SecretsManager endpoint - e.g.: secretsmanager.us-east-2.amazonaws.com + # region: "" # The AWS region of the SecretsManager - e.g.: us-east-2 + # kmskey: "" # The AWS-KMS key ID used to en/decrypt secrets at the SecretsManager. By default (if not set) the default AWS-KMS key will be used. + # credentials: # The AWS credentials for accessing secrets at the AWS SecretsManager. + # accesskey: "" # Your AWS Access Key + # secretkey: "" # Your AWS Secret Key + # token: "" # Your AWS session token (usually optional) \ No newline at end of file diff --git a/examples/minioinstance-kes.yaml b/examples/minioinstance-kes.yaml new file mode 100644 index 00000000000..15399801fbc --- /dev/null +++ b/examples/minioinstance-kes.yaml @@ -0,0 +1,176 @@ +apiVersion: v1 +kind: Secret +metadata: + name: minio-creds-secret +type: Opaque +data: + accesskey: bWluaW8= # base 64 encoded "minio" (echo -n 'minio' | base64) + secretkey: bWluaW8xMjM= # based 64 encoded "minio123" (echo -n 'minio123' | base64) +--- +apiVersion: v1 +kind: Secret +metadata: + name: minio-mcs-secret +type: Opaque +data: + mcshmacjwt: WU9VUkpXVFNJR05JTkdTRUNSRVQ= # base 64 encoded "YOURJWTSIGNINGSECRET" (echo -n 'YOURJWTSIGNINGSECRET' | base64) + mcspbkdfpassphrase: U0VDUkVU # base 64 encoded "SECRET" (echo -n 'SECRET' | base64) + mcspbkdfsalt: U0VDUkVU # base 64 encoded "SECRET" (echo -n 'SECRET' | base64) + mcssecretkey: WU9VUk1DU1NFQ1JFVA== # base 64 encoded "YOURMCSSECRET" (echo -n 'YOURMCSSECRET' | base64) +--- +apiVersion: v1 +kind: Service +metadata: + name: minio-service +spec: + type: ClusterIP + ports: + - port: 9000 + targetPort: 9000 + protocol: TCP + selector: + app: minio +--- +apiVersion: operator.min.io/v1 +kind: MinIOInstance +metadata: + name: minio +## If specified, MinIOInstance pods will be dispatched by specified scheduler. +## If not specified, the pod will be dispatched by default scheduler. +# scheduler: +# name: my-custom-scheduler +spec: + selector: + matchLabels: + app: minio # Should match spec.metadata.labels + ## Add metadata to the all pods created by the StatefulSet + metadata: + labels: + app: minio # Should match spec.selector.matchLabels + annotations: + prometheus.io/path: /minio/prometheus/metrics + prometheus.io/port: "9000" + prometheus.io/scrape: "true" + ## Registry location and Tag to download MinIO Server image + image: minio/minio:RELEASE.2020-05-08T02-40-49Z + ## A ClusterIP Service will be created with the given name + serviceName: minio-internal-service + ## Secret with credentials to be used by MinIO instance. + credsSecret: + name: minio-creds-secret + zones: + - name: "zone-0" + ## Number of MinIO servers/pods in this zone. + ## For standalone mode, supply 1. For distributed mode, supply 4 or more. + ## Note that the operator does not support upgrading from standalone to distributed mode. + servers: 4 + ## Supply number of volumes to be mounted per MinIO server instance. + volumesPerServer: 1 + ## Mount path where PV will be mounted inside container(s). Defaults to "/export". + mountPath: /export + ## Sub path inside Mount path where MinIO starts. Defaults to "". + # subPath: /data + ## This VolumeClaimTemplate is used across all the volumes provisioned for MinIO cluster. + ## Please do not change the volumeClaimTemplate field while expanding the cluster, this may + ## lead to unbound PVCs and missing data + volumeClaimTemplate: + metadata: + name: data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + ## Define configuration for MCS (Graphical user interface for MinIO) + mcs: + image: minio/mcs:v0.0.3 + mcsAccessKey: "mcs" + mcsSecret: + name: minio-mcs-secret + metadata: + labels: + app: mcs # Should match spec.mcs.selector.matchLabels + selector: + matchLabels: + app: mcs # Should match spec.mcs.metadata.labels + ## Define configuration for KES (stateless and distributed key-management system) + kes: + image: minio/kes:v0.9.0 + replicas: 2 + configSecret: + name: kes-config + metadata: + labels: + app: kes # Should match spec.kes.selector.matchLabels + selector: + matchLabels: + app: kes # Should match spec.kes.metadata.labels + ## Secret with certificates to configure TLS for MinIO certs. Create secrets as explained + ## here: https://github.com/minio/minio/tree/master/docs/tls/kubernetes#2-create-kubernetes-secret + # externalCertSecret: + # name: tls-ssl-minio + ## Enable Kubernetes based certificate generation and signing as explained in + ## https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster + requestAutoCert: true + ## PodManagement policy for pods created by StatefulSet. Can be "OrderedReady" or "Parallel" + ## Refer https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy + ## for details. Defaults to "Parallel" + ## If set to "OrderedReady", then disable Readiness checks below. Readiness check will only + ## work if PodManagementPolicy is set to "Parallel". + podManagementPolicy: Parallel + ## Used when "requestAutoCert" is set to true. Set CommonName for the auto-generated certificate. + ## Internal DNS name for the pod will be used if CommonName is not provided. + ## DNS name format is minio-{0...3}.minio.default.svc.cluster.local + certConfig: + commonName: "" + organizationName: [] + dnsNames: [] + ## Used to specify a toleration for a pod + # tolerations: + # - effect: NoSchedule + # key: dedicated + # operator: Equal + # value: storage + ## Add environment variables to be set in MinIO container (https://github.com/minio/minio/tree/master/docs/config) + env: + - name: MINIO_BROWSER + value: "on" + # - name: MINIO_STORAGE_CLASS_RRS + # value: "EC:2" + ## Configure resource requests and limits for MinIO containers + resources: + requests: + memory: 512Mi + cpu: 250m + ## Liveness probe detects situations where MinIO server instance + ## is not working properly and needs restart. Kubernetes automatically + ## restarts the pods if liveness checks fail. + liveness: + httpGet: + scheme: HTTPS + path: /minio/health/live + port: 9000 + initialDelaySeconds: 120 + periodSeconds: 60 + ## Readiness probe detects situations when MinIO server instance + ## is not ready to accept traffic. Kubernetes doesn't forward + ## traffic to the pod while readiness checks fail. + ## Readiness check will only work if PodManagementPolicy is set to "Parallel". + ## Disable this check if you're setting PodManagementPolicy to "OrderedReady". + readiness: + httpGet: + scheme: HTTPS + path: /minio/health/ready + port: 9000 + initialDelaySeconds: 120 + periodSeconds: 60 + ## nodeSelector parameters for MinIO Pods. It specifies a map of key-value pairs. For the pod to be + ## eligible to run on a node, the node must have each of the + ## indicated key-value pairs as labels. + ## Read more here: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + # nodeSelector: + # disktype: ssd + ## Affinity settings for MinIO pods. Read more about affinity + ## here: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity. + # affinity: diff --git a/examples/minioinstance-mcs.yaml b/examples/minioinstance-mcs.yaml new file mode 100644 index 00000000000..aab8cfbf252 --- /dev/null +++ b/examples/minioinstance-mcs.yaml @@ -0,0 +1,162 @@ +apiVersion: v1 +kind: Secret +metadata: + name: minio-creds-secret +type: Opaque +data: + accesskey: bWluaW8= # base 64 encoded "minio" (echo -n 'minio' | base64) + secretkey: bWluaW8xMjM= # based 64 encoded "minio123" (echo -n 'minio123' | base64) +--- +apiVersion: v1 +kind: Secret +metadata: + name: minio-mcs-secret +type: Opaque +data: + mcshmacjwt: WU9VUkpXVFNJR05JTkdTRUNSRVQ= # base 64 encoded "YOURJWTSIGNINGSECRET" (echo -n 'YOURJWTSIGNINGSECRET' | base64) + mcspbkdfpassphrase: U0VDUkVU # base 64 encoded "SECRET" (echo -n 'SECRET' | base64) + mcspbkdfsalt: U0VDUkVU # base 64 encoded "SECRET" (echo -n 'SECRET' | base64) + mcssecretkey: WU9VUk1DU1NFQ1JFVA== # base 64 encoded "YOURMCSSECRET" (echo -n 'YOURMCSSECRET' | base64) +--- +apiVersion: v1 +kind: Service +metadata: + name: minio-service +spec: + type: ClusterIP + ports: + - port: 9000 + targetPort: 9000 + protocol: TCP + selector: + app: minio +--- +apiVersion: operator.min.io/v1 +kind: MinIOInstance +metadata: + name: minio +## If specified, MinIOInstance pods will be dispatched by specified scheduler. +## If not specified, the pod will be dispatched by default scheduler. +# scheduler: +# name: my-custom-scheduler +spec: + selector: + matchLabels: + app: minio # Should match spec.metadata.labels + ## Add metadata to the all pods created by the StatefulSet + metadata: + labels: + app: minio # Should match spec.selector.matchLabels + annotations: + prometheus.io/path: /minio/prometheus/metrics + prometheus.io/port: "9000" + prometheus.io/scrape: "true" + ## Registry location and Tag to download MinIO Server image + image: minio/minio:RELEASE.2020-05-08T02-40-49Z + ## A ClusterIP Service will be created with the given name + serviceName: minio-internal-service + ## Secret with credentials to be used by MinIO instance. + credsSecret: + name: minio-creds-secret + zones: + - name: "zone-0" + ## Number of MinIO servers/pods in this zone. + ## For standalone mode, supply 1. For distributed mode, supply 4 or more. + ## Note that the operator does not support upgrading from standalone to distributed mode. + servers: 4 + ## Supply number of volumes to be mounted per MinIO server instance. + volumesPerServer: 1 + ## Mount path where PV will be mounted inside container(s). Defaults to "/export". + mountPath: /export + ## Sub path inside Mount path where MinIO starts. Defaults to "". + # subPath: /data + ## This VolumeClaimTemplate is used across all the volumes provisioned for MinIO cluster. + ## Please do not change the volumeClaimTemplate field while expanding the cluster, this may + ## lead to unbound PVCs and missing data + volumeClaimTemplate: + metadata: + name: data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + ## Define configuration for MCS (Graphical user interface for MinIO) + mcs: + image: minio/mcs:v0.0.3 + mcsAccessKey: "mcs" + mcsSecret: + name: minio-mcs-secret + metadata: + labels: + app: mcs # Should match spec.mcs.selector.matchLabels + selector: + matchLabels: + app: mcs # Should match spec.mcs.metadata.labels + ## Secret with certificates to configure TLS for MinIO certs. Create secrets as explained + ## here: https://github.com/minio/minio/tree/master/docs/tls/kubernetes#2-create-kubernetes-secret + # externalCertSecret: + # name: tls-ssl-minio + ## Enable Kubernetes based certificate generation and signing as explained in + ## https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster + requestAutoCert: false + ## PodManagement policy for pods created by StatefulSet. Can be "OrderedReady" or "Parallel" + ## Refer https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy + ## for details. Defaults to "Parallel" + ## If set to "OrderedReady", then disable Readiness checks below. Readiness check will only + ## work if PodManagementPolicy is set to "Parallel". + podManagementPolicy: Parallel + ## Used when "requestAutoCert" is set to true. Set CommonName for the auto-generated certificate. + ## Internal DNS name for the pod will be used if CommonName is not provided. + ## DNS name format is minio-{0...3}.minio.default.svc.cluster.local + certConfig: + commonName: "" + organizationName: [] + dnsNames: [] + ## Used to specify a toleration for a pod + # tolerations: + # - effect: NoSchedule + # key: dedicated + # operator: Equal + # value: storage + ## Add environment variables to be set in MinIO container (https://github.com/minio/minio/tree/master/docs/config) + env: + - name: MINIO_BROWSER + value: "on" + # - name: MINIO_STORAGE_CLASS_RRS + # value: "EC:2" + ## Configure resource requests and limits for MinIO containers + resources: + requests: + memory: 512Mi + cpu: 250m + ## Liveness probe detects situations where MinIO server instance + ## is not working properly and needs restart. Kubernetes automatically + ## restarts the pods if liveness checks fail. + liveness: + httpGet: + path: /minio/health/live + port: 9000 + initialDelaySeconds: 120 + periodSeconds: 60 + ## Readiness probe detects situations when MinIO server instance + ## is not ready to accept traffic. Kubernetes doesn't forward + ## traffic to the pod while readiness checks fail. + ## Readiness check will only work if PodManagementPolicy is set to "Parallel". + ## Disable this check if you're setting PodManagementPolicy to "OrderedReady". + readiness: + httpGet: + path: /minio/health/ready + port: 9000 + initialDelaySeconds: 120 + periodSeconds: 60 + ## nodeSelector parameters for MinIO Pods. It specifies a map of key-value pairs. For the pod to be + ## eligible to run on a node, the node must have each of the + ## indicated key-value pairs as labels. + ## Read more here: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + # nodeSelector: + # disktype: ssd + ## Affinity settings for MinIO pods. Read more about affinity + ## here: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity. + # affinity: diff --git a/examples/minioinstance.yaml b/examples/minioinstance.yaml index a4cc597e516..12a6d641f72 100644 --- a/examples/minioinstance.yaml +++ b/examples/minioinstance.yaml @@ -6,7 +6,6 @@ type: Opaque data: accesskey: bWluaW8= # base 64 encoded "minio" (echo -n 'minio' | base64) secretkey: bWluaW8xMjM= # based 64 encoded "minio123" (echo -n 'minio123' | base64) -## Secrets defined for mcs --- apiVersion: v1 kind: Secret @@ -40,9 +39,9 @@ spec: prometheus.io/port: "9000" prometheus.io/scrape: "true" ## Registry location and Tag to download MinIO Server image - image: minio/minio:RELEASE.2020-05-01T22-19-14Z + image: minio/minio:RELEASE.2020-05-08T02-40-49Z ## A ClusterIP Service will be created with the given name - serviceName: minio + serviceName: minio-internal-service zones: - name: "zone-0" ## Number of MinIO servers/pods in this zone. @@ -98,7 +97,7 @@ spec: # value: storage ## Define configuration for mcs (A graphical user interface for MinIO) mcs: - image: minio/mcs:v0.0.2 + image: minio/mcs:v0.0.3 mcsAccessKey: "mcs" mcsSecret: name: minio-mcs-secret diff --git a/examples/mirrorinstance.yaml b/examples/mirrorinstance.yaml index 167e8757ad0..b34a72ed039 100644 --- a/examples/mirrorinstance.yaml +++ b/examples/mirrorinstance.yaml @@ -15,7 +15,7 @@ spec: labels: app: mc # Should match spec.selector.matchLabels ## Registry location and Tag to download MC image - image: minio/mc:RELEASE.2020-04-25T00-43-23Z + image: minio/mc:RELEASE.2020-05-06T18-00-07Z ## This is used to set configuration ## Format name: MC_HOST_ ## Format value: https://:@ diff --git a/go.mod b/go.mod index fd967acf50e..068ef73bf9f 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.14 require ( github.com/evanphx/json-patch v4.5.0+incompatible // indirect + github.com/golang/protobuf v1.3.3 // indirect + github.com/imdario/mergo v0.3.6 // indirect github.com/minio/minio v0.0.0-20200501124117-09571d03a531 github.com/stretchr/testify v1.4.0 golang.org/x/net v0.0.0-20200505041828-1ed23360d12c // indirect diff --git a/go.sum b/go.sum index a2b4043ecd3..918b5b9b790 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,7 @@ github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXH github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coredns/coredns v1.4.0 h1:RubBkYmkByUqZWWkjRHvNLnUHgkRVqAWgSMmRFvpE1A= github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -110,6 +111,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -178,6 +181,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg= github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= diff --git a/main.go b/main.go index 2475477a5a3..fdfe284f3ea 100644 --- a/main.go +++ b/main.go @@ -115,6 +115,7 @@ func main() { mainController := cluster.NewController(kubeClient, controllerClient, *certClient, kubeInformerFactory.Apps().V1().StatefulSets(), kubeInformerFactory.Apps().V1().Deployments(), + kubeInformerFactory.Batch().V1().Jobs(), minioInformerFactory.Operator().V1().MinIOInstances(), kubeInformerFactory.Core().V1().Services()) diff --git a/pkg/constants/constants.go b/pkg/apis/operator.min.io/v1/constants.go similarity index 65% rename from pkg/constants/constants.go rename to pkg/apis/operator.min.io/v1/constants.go index ff5d16fdb09..8e372442942 100644 --- a/pkg/constants/constants.go +++ b/pkg/apis/operator.min.io/v1/constants.go @@ -15,42 +15,48 @@ * */ -package constants +package v1 import ( "crypto/elliptic" - "os" "time" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" ) -// InstanceLabel is applied to all components of a MinIOInstance cluster -const InstanceLabel = "v1.min.io/instance" - -// McsInstanceLabel is applied to the MCS pods of a MinIOInstance cluster -const McsInstanceLabel = "v1.min.io/mcs" - // MinIOOperatorVersionLabel denotes the version of the MinIOInstance operator // running in the cluster. const MinIOOperatorVersionLabel = "v1.min.io/version" +// MinIOCRDResourceKind is the Kind of a Cluster. +const MinIOCRDResourceKind = "MinIOInstance" + +// DefaultPodManagementPolicy specifies default pod management policy as expllained here +// https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies +const DefaultPodManagementPolicy = appsv1.ParallelPodManagement + +// DefaultUpdateStrategy specifies default pod update policy as explained here +// https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +const DefaultUpdateStrategy = "RollingUpdate" + +// DefaultImagePullPolicy specifies the policy to image pulls +const DefaultImagePullPolicy = "Always" + +// CSRNameSuffix specifies the suffix added to MinIOInstance name to create a CSR +const CSRNameSuffix = "-csr" + +// MinIO Related Constants + +// InstanceLabel is applied to all components of a MinIOInstance cluster +const InstanceLabel = "v1.min.io/instance" + // MinIOPort specifies the default MinIOInstance port number. const MinIOPort = 9000 // MinIOServicePortName specifies the default Service's port name, e.g. for automatic protocol selection in Istio const MinIOServicePortName = "http-minio" -// MinIOServicePortNumber specifies the default Service's port number. -const MinIOServicePortNumber = 9000 - -// McsPort specifies the default Mcs port number. -const McsPort = 9090 - -// McsServicePortName specifies the default Service's port name, e.g. for automatic protocol selection in Istio -const McsServicePortName = "http-mcs" - // MinIOVolumeName specifies the default volume name for MinIO volumes const MinIOVolumeName = "export" @@ -61,19 +67,30 @@ const MinIOVolumeMountPath = "/export" const MinIOVolumeSubPath = "" // DefaultMinIOImage specifies the default MinIO Docker hub image -const DefaultMinIOImage = "minio/minio:RELEASE.2020-05-01T22-19-14Z" +const DefaultMinIOImage = "minio/minio:RELEASE.2020-05-08T02-40-49Z" -// DefaultMCImage specifies the default mc Docker hub image -const DefaultMCImage = "minio/mc:RELEASE.2020-04-25T00-43-23Z" +// DefaultMinIOAccessKey specifies default access key for MinIOInstance +const DefaultMinIOAccessKey = "AKIAIOSFODNN7EXAMPLE" -// DefaultMcsImage specifies the latest Mcs Docker hub image -const DefaultMcsImage = "minio/mcs:v0.0.2" +// DefaultMinIOSecretKey specifies default secret key for MinIOInstance +const DefaultMinIOSecretKey = "wJalrXUtnFEMIK7MDENGbPxRfiCYEXAMPLEKEY" -// MinIOServerName specifies the default container name for MinIOInstance -const MinIOServerName = "minio" +// MinIOHLSvcNameSuffix specifies the suffix added to MinIOInstance name to create a headless service +const MinIOHLSvcNameSuffix = "-hl-svc" -// MirorContainerName specifies the default container name for MirrorInstance -const MirorContainerName = "mirror" +// DefaultServers specifies the default MinIO replicas to use for distributed deployment if not specified explicitly by user +const DefaultServers = 1 + +// DefaultVolumesPerServer specifies the default number of volumes per MinIO instance +const DefaultVolumesPerServer = 1 + +// DefaultZoneName specifies the default zone name +const DefaultZoneName = "zone-0" + +// MC Mirror Related Constants + +// DefaultMCImage specifies the default mc Docker hub image +const DefaultMCImage = "minio/mc:RELEASE.2020-05-06T18-00-07Z" // MirrorJobRestartPolicy specifies the restart policy for the job created for mirroring const MirrorJobRestartPolicy = corev1.RestartPolicyOnFailure @@ -81,37 +98,66 @@ const MirrorJobRestartPolicy = corev1.RestartPolicyOnFailure // DefaultMirrorFlags specifies the restart policy for the job created for mirroring var DefaultMirrorFlags = []string{"--no-color", "--json"} -// DefaultMinIOAccessKey specifies default access key for MinIOInstance -const DefaultMinIOAccessKey = "AKIAIOSFODNN7EXAMPLE" +// MirrorCRDResourceKind is the Kind of a Cluster. +const MirrorCRDResourceKind = "MirrorInstance" -// DefaultMinIOSecretKey specifies default secret key for MinIOInstance -const DefaultMinIOSecretKey = "wJalrXUtnFEMIK7MDENGbPxRfiCYEXAMPLEKEY" +// MCS Related Constants -// DefaultPodManagementPolicy specifies default pod management policy as expllained here -// https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies -const DefaultPodManagementPolicy = appsv1.ParallelPodManagement +// DefaultMCSImage specifies the latest MCS Docker hub image +const DefaultMCSImage = "minio/mcs:v0.0.3" -// DefaultUpdateStrategy specifies default pod update policy as explained here -// https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies -const DefaultUpdateStrategy = "RollingUpdate" +// MCSInstanceLabel is applied to the MCS pods of a MinIOInstance cluster +const MCSInstanceLabel = "v1.min.io/mcs" -// DefaultImagePullPolicy specifies the policy to image pulls -const DefaultImagePullPolicy = "Always" +// MCSPort specifies the default MCS port number. +const MCSPort = 9090 -// HeadlessServiceNameSuffix specifies the suffix added to MinIOInstance name to create a headless service -const HeadlessServiceNameSuffix = "-hl-svc" +// MCSServicePortName specifies the default MCS Service's port name. +const MCSServicePortName = "http-mcs" -// McsServiceNameSuffix specifies the suffix added to MinIOInstance servce name to create a service for mcs -const McsServiceNameSuffix = "-ui" +// MCSServiceNameSuffix specifies the suffix added to MinIOInstance service name to create a service for mcs +const MCSServiceNameSuffix = "-ui" -// CSRNameSuffix specifies the suffix added to MinIOInstance name to create a CSR -const CSRNameSuffix = "-csr" +// MCSName specifies the default container name for MCS +const MCSName = "-mcs" -// MinIOCRDResourceKind is the Kind of a Cluster. -const MinIOCRDResourceKind = "MinIOInstance" +// MCSAdminPolicyName denotes the policy name for MCS user +const MCSAdminPolicyName = "mcsAdmin" -// MirrorCRDResourceKind is the Kind of a Cluster. -const MirrorCRDResourceKind = "MirrorInstance" +// MCSRestartPolicy defines the default restart policy for MCS Containers +const MCSRestartPolicy = corev1.RestartPolicyAlways + +// KES Related Constants + +// DefaultKESImage specifies the latest KES Docker hub image +const DefaultKESImage = "minio/kes:v0.9.0" + +// KESInstanceLabel is applied to the KES pods of a MinIOInstance cluster +const KESInstanceLabel = "v1.min.io/kes" + +// KESPort specifies the default KES Service's port number. +const KESPort = 7373 + +// KESServicePortName specifies the default KES Service's port name. +const KESServicePortName = "http-kes" + +// KESMinIOKey is the name of key that KES creates on the KMS backend +const KESMinIOKey = "my-minio-key" + +// KESJobRestartPolicy specifies the restart policy for the job created for mirroring +const KESJobRestartPolicy = corev1.RestartPolicyOnFailure + +// KESHLSvcNameSuffix specifies the suffix added to MinIOInstance name to create a headless service for KES +const KESHLSvcNameSuffix = "-kes-hl-svc" + +// KESName specifies the default container name for KES +const KESName = "-kes" + +// KESConfigMountPath specifies the path where KES config file and all secrets are mounted +const KESConfigMountPath = "/home" + +// DefaultKESReplicas specifies the default number of KES pods to be created if not specified +const DefaultKESReplicas = 2 // Auto TLS related constants @@ -129,28 +175,3 @@ var DefaultQueryTimeout = time.Minute * 20 // TLSSecretSuffix is the suffix applied to MinIOInstance name to create the TLS secret var TLSSecretSuffix = "-tls" - -// DefaultServers specifies the default MinIO replicas to use for distributed deployment if not specified explicitly by user -const DefaultServers = 1 - -// DefaultVolumesPerServer specifies the default number of volumes per MinIO instance -const DefaultVolumesPerServer = 1 - -// DefaultZoneName specifies the default zone name -const DefaultZoneName = "zone-0" - -// McsName specifies the default container name for Mcs -const McsName = "mcs" - -// MCSAdminPolicyName denotes the policy name for MCS user -const MCSAdminPolicyName = "mcsAdmin" - -func getEnv(key, defaultValue string) string { - value := os.Getenv(key) - if len(value) == 0 { - return defaultValue - } - return value -} - -var ClusterDomain = getEnv("CLUSTER_DOMAIN", "cluster.local") diff --git a/pkg/apis/operator.min.io/v1/globals.go b/pkg/apis/operator.min.io/v1/globals.go new file mode 100644 index 00000000000..6746f6a0695 --- /dev/null +++ b/pkg/apis/operator.min.io/v1/globals.go @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020, MinIO, Inc. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +package v1 + +import ( + "os" +) + +// ClusterDomain is used to store the Kubernetes cluster domain +var ClusterDomain string + +// Scheme indicates communication over http or https +var Scheme string + +// Identity is the public identity generated for MinIO Server based on +// Used only during KES Deployments +var Identity string + +func getEnv(key string) string { + value, ok := os.LookupEnv(key) + if !ok { + return "cluster.local" + } + return value +} + +func identifyScheme(mi *MinIOInstance) string { + scheme := "http" + if mi.RequiresAutoCertSetup() || mi.RequiresExternalCertSetup() { + scheme = "https" + } + return scheme +} + +// InitGlobals initiates the global variables while Operator starts +func InitGlobals(mi *MinIOInstance) { + ClusterDomain = getEnv("CLUSTER_DOMAIN") + Scheme = identifyScheme(mi) +} diff --git a/pkg/apis/operator.min.io/v1/helper.go b/pkg/apis/operator.min.io/v1/helper.go index 59f4289ebc3..68447bf02ee 100644 --- a/pkg/apis/operator.min.io/v1/helper.go +++ b/pkg/apis/operator.min.io/v1/helper.go @@ -26,11 +26,10 @@ import ( "strconv" "time" - "k8s.io/klog" - - constants "github.com/minio/minio-operator/pkg/constants" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/klog" "github.com/minio/minio/pkg/bucket/policy" "github.com/minio/minio/pkg/bucket/policy/condition" @@ -76,25 +75,18 @@ func (mi *MinIOInstance) RequiresAutoCertSetup() bool { return mi.Spec.RequestAutoCert == true } -// PodLabels returns the default labels -func (mi *MinIOInstance) PodLabels() map[string]string { - m := make(map[string]string, 1) - m[constants.InstanceLabel] = mi.Name - return m -} - -// GetVolumesPath returns the paths for MinIO mounts based on +// VolumePath returns the paths for MinIO mounts based on // total number of volumes per MinIO server -func (mi *MinIOInstance) GetVolumesPath() string { +func (mi *MinIOInstance) VolumePath() string { if mi.Spec.VolumesPerServer == 1 { return path.Join(mi.Spec.Mountpath, mi.Spec.Subpath) } return path.Join(mi.Spec.Mountpath+"{0..."+strconv.Itoa((mi.Spec.VolumesPerServer)-1)+"}", mi.Spec.Subpath) } -// GetReplicas returns the number of total replicas +// MinIOReplicas returns the number of total replicas // required for this cluster -func (mi *MinIOInstance) GetReplicas() int32 { +func (mi *MinIOInstance) MinIOReplicas() int32 { var replicas int32 for _, z := range mi.Spec.Zones { replicas = replicas + z.Servers @@ -102,6 +94,16 @@ func (mi *MinIOInstance) GetReplicas() int32 { return replicas } +// KESReplicas returns the number of total KES replicas +// required for this cluster +func (mi *MinIOInstance) KESReplicas() int32 { + var replicas int32 + if mi.Spec.KES != nil && mi.Spec.KES.Replicas != 0 { + replicas = mi.Spec.KES.Replicas + } + return replicas +} + // EnsureDefaults will ensure that if a user omits and fields in the // spec that are required, we set some sensible defaults. // For example a user can choose to omit the version @@ -109,11 +111,11 @@ func (mi *MinIOInstance) GetReplicas() int32 { func (mi *MinIOInstance) EnsureDefaults() *MinIOInstance { if mi.Spec.PodManagementPolicy == "" || (mi.Spec.PodManagementPolicy != appsv1.OrderedReadyPodManagement && mi.Spec.PodManagementPolicy != appsv1.ParallelPodManagement) { - mi.Spec.PodManagementPolicy = constants.DefaultPodManagementPolicy + mi.Spec.PodManagementPolicy = DefaultPodManagementPolicy } if mi.Spec.Image == "" { - mi.Spec.Image = constants.DefaultMinIOImage + mi.Spec.Image = DefaultMinIOImage } // Default an empty service name to the instance name @@ -123,167 +125,177 @@ func (mi *MinIOInstance) EnsureDefaults() *MinIOInstance { for _, z := range mi.Spec.Zones { if z.Servers == 0 { - z.Servers = constants.DefaultServers + z.Servers = DefaultServers } } if mi.Spec.VolumesPerServer == 0 { - mi.Spec.VolumesPerServer = constants.DefaultVolumesPerServer + mi.Spec.VolumesPerServer = DefaultVolumesPerServer } if mi.Spec.Mountpath == "" { - mi.Spec.Mountpath = constants.MinIOVolumeMountPath + mi.Spec.Mountpath = MinIOVolumeMountPath } if mi.Spec.Subpath == "" { - mi.Spec.Subpath = constants.MinIOVolumeSubPath + mi.Spec.Subpath = MinIOVolumeSubPath } if mi.RequiresAutoCertSetup() == true { if mi.Spec.CertConfig != nil { if mi.Spec.CertConfig.CommonName == "" { - mi.Spec.CertConfig.CommonName = mi.GetWildCardName() + mi.Spec.CertConfig.CommonName = mi.MinIOWildCardName() } if mi.Spec.CertConfig.DNSNames == nil { - mi.Spec.CertConfig.DNSNames = mi.GetHosts() + mi.Spec.CertConfig.DNSNames = mi.MinIOHosts() } if mi.Spec.CertConfig.OrganizationName == nil { - mi.Spec.CertConfig.OrganizationName = constants.DefaultOrgName + mi.Spec.CertConfig.OrganizationName = DefaultOrgName } } else { mi.Spec.CertConfig = &CertificateConfig{ - CommonName: mi.GetWildCardName(), - DNSNames: mi.GetHosts(), - OrganizationName: constants.DefaultOrgName, + CommonName: mi.MinIOWildCardName(), + DNSNames: mi.MinIOHosts(), + OrganizationName: DefaultOrgName, } } } if !mi.HasSelector() { mi.Spec.Selector = &metav1.LabelSelector{ - MatchLabels: mi.PodLabels(), + MatchLabels: mi.MinIOPodLabels(), } } - if mi.HasMcsEnabled() && mi.Spec.Mcs.Image == "" { - mi.Spec.Mcs.Image = constants.DefaultMcsImage + if mi.HasMCSEnabled() && mi.Spec.MCS.Image == "" { + mi.Spec.MCS.Image = DefaultMCSImage + } + + if mi.HasKESEnabled() { + if mi.Spec.KES.Image == "" { + mi.Spec.KES.Image = DefaultKESImage + } + if mi.Spec.KES.Replicas == 0 { + mi.Spec.KES.Replicas = DefaultKESReplicas + } } return mi } -// GetHosts returns the domain names managed by headless service created for -// current MinIOInstance -func (mi *MinIOInstance) GetHosts() []string { +// MinIOHosts returns the domain names in ellipses format created for current MinIOInstance +func (mi *MinIOInstance) MinIOHosts() []string { hosts := make([]string, 0) var max, index int32 // Create the ellipses style URL - // mi.Name is the headless service name for _, z := range mi.Spec.Zones { max = max + z.Servers - hosts = append(hosts, fmt.Sprintf("%s-{"+strconv.Itoa(int(index))+"..."+strconv.Itoa(int(max)-1)+"}.%s.%s.svc."+constants.ClusterDomain, mi.Name, mi.GetHeadlessServiceName(), mi.Namespace)) + hosts = append(hosts, fmt.Sprintf("%s-{"+strconv.Itoa(int(index))+"..."+strconv.Itoa(int(max)-1)+"}.%s.%s.svc.%s", mi.MinIOStatefulSetName(), mi.MinIOHLServiceName(), mi.Namespace, ClusterDomain)) index = max } return hosts } -// GetServiceHost returns headless service Host. -// current MinIOInstance -func (mi *MinIOInstance) GetServiceHost() string { +// AllMinIOHosts returns the all the individual domain names relevant for current MinIOInstance +func (mi *MinIOInstance) AllMinIOHosts() []string { + hosts := make([]string, 0) + var max, index int32 + for _, z := range mi.Spec.Zones { + max = max + z.Servers + for index < max { + hosts = append(hosts, fmt.Sprintf("%s-"+strconv.Itoa(int(index))+".%s.%s.svc.%s", mi.MinIOStatefulSetName(), mi.MinIOHLServiceName(), mi.Namespace, ClusterDomain)) + index++ + } + } + hosts = append(hosts, mi.MinIOCIServiceHost()) + hosts = append(hosts, mi.MinIOHeadlessServiceHost()) + return hosts +} + +// MinIOCIServiceHost returns ClusterIP service Host for current MinIOInstance +func (mi *MinIOInstance) MinIOCIServiceHost() string { if mi.Spec.Zones[0].Servers == 1 { msg := "Please set the server count > 1" klog.V(2).Infof(msg) return "" } - hostStr := fmt.Sprintf("%s.%s.svc."+constants.ClusterDomain, mi.GetServiceName(), mi.Namespace) - return net.JoinHostPort(hostStr, strconv.Itoa(constants.MinIOServicePortNumber)) + return fmt.Sprintf("%s.%s.svc.%s", mi.MinIOCIServiceName(), mi.Namespace, ClusterDomain) } -// GetWildCardName returns the wild card name managed by headless service created for -// current MinIOInstance -func (mi *MinIOInstance) GetWildCardName() string { - // mi.Name is the headless service name - return fmt.Sprintf("*.%s.%s.svc."+constants.ClusterDomain, mi.GetHeadlessServiceName(), mi.Namespace) -} - -// GetTLSSecretName returns the name of Secret that has TLS related Info (Cert & Prviate Key) -func (mi *MinIOInstance) GetTLSSecretName() string { - return mi.Name + constants.TLSSecretSuffix -} - -// GetServiceName returns the name of service that is exposes the MinIO Instance -func (mi *MinIOInstance) GetServiceName() string { - return mi.Spec.ServiceName +// MinIOHeadlessServiceHost returns headless service Host for current MinIOInstance +func (mi *MinIOInstance) MinIOHeadlessServiceHost() string { + if mi.Spec.Zones[0].Servers == 1 { + msg := "Please set the server count > 1" + klog.V(2).Infof(msg) + return "" + } + return fmt.Sprintf("%s.%s.svc.%s", mi.MinIOHLServiceName(), mi.Namespace, ClusterDomain) } -// GetHeadlessServiceName returns the name of headless service that is created to manage the -// StatefulSet of this MinIOInstance -func (mi *MinIOInstance) GetHeadlessServiceName() string { - return mi.Name + constants.HeadlessServiceNameSuffix +// KESHosts returns the host names created for current KES StatefulSet +func (mi *MinIOInstance) KESHosts() []string { + hosts := make([]string, 0) + var i int32 = 0 + for i < mi.Spec.KES.Replicas { + hosts = append(hosts, fmt.Sprintf("%s-"+strconv.Itoa(int(i))+".%s.%s.svc.%s", mi.KESStatefulSetName(), mi.KESHLServiceName(), mi.Namespace, ClusterDomain)) + i++ + } + hosts = append(hosts, mi.KESServiceHost()) + return hosts } -// GetMcsServiceName returns the name of the service that is created to access the mcs for the -// MinIOInstance -func (mi *MinIOInstance) GetMcsServiceName() string { - return mi.GetServiceName() + constants.McsServiceNameSuffix +// KESServiceHost returns headless service Host for KES in current MinIOInstance +func (mi *MinIOInstance) KESServiceHost() string { + return fmt.Sprintf("%s.%s.svc.%s", mi.KESHLServiceName(), mi.Namespace, ClusterDomain) } -// GetCSRName returns the name of CSR that generated if AutoTLS is enabled -func (mi *MinIOInstance) GetCSRName() string { - return mi.Name + constants.CSRNameSuffix +// HasKESEnabled checks if kes configuration is provided by user +func (mi *MinIOInstance) HasKESEnabled() bool { + return mi.Spec.KES != nil } -// EnsureDefaults will ensure that if a user omits and fields in the -// spec that are required, we set some sensible defaults. -func (mi *MirrorInstance) EnsureDefaults() *MirrorInstance { - if mi.Spec.Image == "" { - mi.Spec.Image = constants.DefaultMCImage - } - return mi +// HasMCSEnabled checks if the mcs has been enabled by the user +func (mi *MinIOInstance) HasMCSEnabled() bool { + return mi.Spec.MCS != nil } -// HasMetadata returns true if the user has provided a pod metadata +// HasMCSSecret returns true if the user has provided an mcs secret // for a MinIOInstance else false -func (mi *MirrorInstance) HasMetadata() bool { - return mi.Spec.Metadata != nil +func (mi *MinIOInstance) HasMCSSecret() bool { + return mi.Spec.MCS != nil && mi.Spec.MCS.MCSSecret != nil } -// HasSelector returns true if the user has provided a pod selector -// field (ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-selector) -func (mi *MirrorInstance) HasSelector() bool { - return mi.Spec.Selector != nil -} - -// HasMcsEnabled checks if the mcs has been enabled by the user -func (mi *MinIOInstance) HasMcsEnabled() bool { - return mi.Spec.Mcs != nil +// HasMCSMetadata returns true if the user has provided a mcs metadata +// for a MinIOInstance else false +func (mi *MinIOInstance) HasMCSMetadata() bool { + return mi.Spec.MCS != nil && mi.Spec.MCS.Metadata != nil } -// HasMcsSecret returns true if the user has provided an mcs secret +// HasMCSSelector returns true if the user has provided a mcs selector // for a MinIOInstance else false -func (mi *MinIOInstance) HasMcsSecret() bool { - return mi.Spec.Mcs != nil && mi.Spec.Mcs.McsSecret != nil +func (mi *MinIOInstance) HasMCSSelector() bool { + return mi.Spec.MCS != nil && mi.Spec.MCS.Selector != nil } -// HasMcsMetadata returns true if the user has provided a mcs metadata +// HasKESMetadata returns true if the user has provided KES metadata // for a MinIOInstance else false -func (mi *MinIOInstance) HasMcsMetadata() bool { - return mi.Spec.Mcs != nil && mi.Spec.Mcs.Metadata != nil +func (mi *MinIOInstance) HasKESMetadata() bool { + return mi.Spec.KES != nil && mi.Spec.KES.Metadata != nil } -// HasMcsSelector returns true if the user has provided a mcs selector +// HasKESSelector returns true if the user has provided a KES selector // for a MinIOInstance else false -func (mi *MinIOInstance) HasMcsSelector() bool { - return mi.Spec.Mcs != nil && mi.Spec.Mcs.Selector != nil +func (mi *MinIOInstance) HasKESSelector() bool { + return mi.Spec.KES != nil && mi.Spec.KES.Selector != nil } -// CreateMcsUser function creates an admin user -func (mi *MinIOInstance) CreateMcsUser(minioSecret, mcsSecret map[string][]byte) error { +// CreateMCSUser function creates an admin user +func (mi *MinIOInstance) CreateMCSUser(minioSecret, mcsSecret map[string][]byte) error { var accessKey, secretKey, mcsSecretKey []byte var ok bool - host := mi.GetServiceHost() + host := net.JoinHostPort(mi.MinIOCIServiceHost(), strconv.Itoa(MinIOPort)) if host == "" { return errors.New("MCS MINIO SERVER is empty") } @@ -302,15 +314,15 @@ func (mi *MinIOInstance) CreateMcsUser(minioSecret, mcsSecret map[string][]byte) if !ok { return errors.New("mcssecretkey not provided") } - //TODO: Set Secure=true if the instance was setup like so - madmClnt, err := madmin.New(host, string(accessKey), string(secretKey), false) + + madmClnt, err := madmin.New(host, string(accessKey), string(secretKey), Scheme == "https") if err != nil { return err } // try to add user with a 20 seconds timeout ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) defer cancel() - if err = madmClnt.AddUser(ctx, mi.Spec.Mcs.McsAccessKey, string(mcsSecretKey)); err != nil { + if err = madmClnt.AddUser(ctx, mi.Spec.MCS.MCSAccessKey, string(mcsSecretKey)); err != nil { return err } @@ -335,13 +347,45 @@ func (mi *MinIOInstance) CreateMcsUser(minioSecret, mcsSecret map[string][]byte) }, } - if err = madmClnt.AddCannedPolicy(context.Background(), constants.MCSAdminPolicyName, &p); err != nil { + if err = madmClnt.AddCannedPolicy(context.Background(), MCSAdminPolicyName, &p); err != nil { return err } - if err = madmClnt.SetPolicy(context.Background(), constants.MCSAdminPolicyName, string(mi.Spec.Mcs.McsAccessKey), false); err != nil { + if err = madmClnt.SetPolicy(context.Background(), MCSAdminPolicyName, string(mi.Spec.MCS.MCSAccessKey), false); err != nil { return err } return nil } + +// OwnerRef returns the OwnerReference to be added to all resources created by MinIOInstance +func (mi *MinIOInstance) OwnerRef() []metav1.OwnerReference { + return []metav1.OwnerReference{ + *metav1.NewControllerRef(mi, schema.GroupVersionKind{ + Group: SchemeGroupVersion.Group, + Version: SchemeGroupVersion.Version, + Kind: MinIOCRDResourceKind, + }), + } +} + +// EnsureDefaults will ensure that if a user omits and fields in the +// spec that are required, we set some sensible defaults. +func (mi *MirrorInstance) EnsureDefaults() *MirrorInstance { + if mi.Spec.Image == "" { + mi.Spec.Image = DefaultMCImage + } + return mi +} + +// HasMetadata returns true if the user has provided a pod metadata +// for a MinIOInstance else false +func (mi *MirrorInstance) HasMetadata() bool { + return mi.Spec.Metadata != nil +} + +// HasSelector returns true if the user has provided a pod selector +// field (ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-selector) +func (mi *MirrorInstance) HasSelector() bool { + return mi.Spec.Selector != nil +} diff --git a/pkg/apis/operator.min.io/v1/helper_test.go b/pkg/apis/operator.min.io/v1/helper_test.go index c4a9b2c876e..47e90473186 100644 --- a/pkg/apis/operator.min.io/v1/helper_test.go +++ b/pkg/apis/operator.min.io/v1/helper_test.go @@ -3,7 +3,6 @@ package v1 import ( "testing" - constants "github.com/minio/minio-operator/pkg/constants" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -13,9 +12,9 @@ func TestEnsureDefaults(t *testing.T) { mi.EnsureDefaults() t.Run("defaults", func(t *testing.T) { - assert.Equal(t, mi.Spec.Image, constants.DefaultMinIOImage) - assert.Equal(t, mi.Spec.Mountpath, constants.MinIOVolumeMountPath) - assert.Equal(t, mi.Spec.Subpath, constants.MinIOVolumeSubPath) + assert.Equal(t, mi.Spec.Image, DefaultMinIOImage) + assert.Equal(t, mi.Spec.Mountpath, MinIOVolumeMountPath) + assert.Equal(t, mi.Spec.Subpath, MinIOVolumeSubPath) assert.False(t, mi.RequiresAutoCertSetup()) }) diff --git a/pkg/apis/operator.min.io/v1/labels.go b/pkg/apis/operator.min.io/v1/labels.go new file mode 100644 index 00000000000..24ce86e795a --- /dev/null +++ b/pkg/apis/operator.min.io/v1/labels.go @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020, MinIO, Inc. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +package v1 + +// MinIOPodLabels returns the default labels for MinIO Pod +func (mi *MinIOInstance) MinIOPodLabels() map[string]string { + m := make(map[string]string, 1) + m[InstanceLabel] = mi.MinIOStatefulSetName() + return m +} + +// KESPodLabels returns the default labels for KES Pod +func (mi *MinIOInstance) KESPodLabels() map[string]string { + m := make(map[string]string, 1) + m[KESInstanceLabel] = mi.KESStatefulSetName() + return m +} + +// MCSPodLabels returns the default labels for MCS Pod +func (mi *MinIOInstance) MCSPodLabels() map[string]string { + m := make(map[string]string, 1) + m[MCSInstanceLabel] = mi.MCSDeploymentName() + return m +} diff --git a/pkg/apis/operator.min.io/v1/names.go b/pkg/apis/operator.min.io/v1/names.go new file mode 100644 index 00000000000..92d54ded0e8 --- /dev/null +++ b/pkg/apis/operator.min.io/v1/names.go @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2020, MinIO, Inc. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +package v1 + +import ( + "fmt" +) + +// MinIOServerName specifies the default container name for MinIOInstance +const MinIOServerName = "minio" + +// MirrorContainerName specifies the default container name for MirrorInstance +const MirrorContainerName = "mirror" + +// KESContainerName specifies the default container name for KES +const KESContainerName = "kes" + +// MCSContainerName specifies the default container name for MCS +const MCSContainerName = "mcs" + +// MinIO Related Names + +// MinIOStatefulSetName returns the name for MinIO StatefulSet +func (mi *MinIOInstance) MinIOStatefulSetName() string { + return mi.Name +} + +// MinIOWildCardName returns the wild card name for all MinIO Pods in current StatefulSet +func (mi *MinIOInstance) MinIOWildCardName() string { + return fmt.Sprintf("*.%s.%s.svc.%s", mi.MinIOHLServiceName(), mi.Namespace, ClusterDomain) +} + +// MinIOTLSSecretName returns the name of Secret that has TLS related Info (Cert & Private Key) +func (mi *MinIOInstance) MinIOTLSSecretName() string { + return mi.Name + TLSSecretSuffix +} + +// MinIOClientTLSSecretName returns the name of Secret that has TLS related Info (Cert & Private Key) +// for MinIO <-> KES client side authentication. +func (mi *MinIOInstance) MinIOClientTLSSecretName() string { + return mi.Name + "-client" + TLSSecretSuffix +} + +// MinIOHLServiceName returns the name of headless service that is created to manage the +// StatefulSet of this MinIOInstance +func (mi *MinIOInstance) MinIOHLServiceName() string { + return mi.Name + MinIOHLSvcNameSuffix +} + +// MinIOCIServiceName returns the name of Cluster IP service that is created to communicate +// with current MinIO StatefulSet pods +func (mi *MinIOInstance) MinIOCIServiceName() string { + return mi.Spec.ServiceName +} + +// MinIOCSRName returns the name of CSR that is generated if AutoTLS is enabled +func (mi *MinIOInstance) MinIOCSRName() string { + return mi.Name + CSRNameSuffix +} + +// MinIOClientCSRName returns the name of CSR that is generated for Client side authentication +// Used by KES Pods +func (mi *MinIOInstance) MinIOClientCSRName() string { + return mi.Name + "-client" + CSRNameSuffix +} + +// KES Related Names + +// KESJobName returns the name for KES Key Job +func (mi *MinIOInstance) KESJobName() string { + return mi.Name + KESName +} + +// KESStatefulSetName returns the name for KES StatefulSet +func (mi *MinIOInstance) KESStatefulSetName() string { + return mi.Name + KESName +} + +// KESHLServiceName returns the name of headless service that is created to manage the +// StatefulSet of this MinIOInstance +func (mi *MinIOInstance) KESHLServiceName() string { + return mi.Name + KESHLSvcNameSuffix +} + +// KESVolMountName returns the name of Secret that has TLS related Info (Cert & Private Key) +func (mi *MinIOInstance) KESVolMountName() string { + return mi.Name + KESName +} + +// KESWildCardName returns the wild card name managed by headless service created for +// KES StatefulSet in current MinIOInstance +func (mi *MinIOInstance) KESWildCardName() string { + return fmt.Sprintf("*.%s.%s.svc.%s", mi.KESHLServiceName(), mi.Namespace, ClusterDomain) +} + +// KESTLSSecretName returns the name of Secret that has KES TLS related Info (Cert & Private Key) +func (mi *MinIOInstance) KESTLSSecretName() string { + return mi.KESStatefulSetName() + TLSSecretSuffix +} + +// KESCSRName returns the name of CSR that generated if AutoTLS is enabled for KES +func (mi *MinIOInstance) KESCSRName() string { + return mi.KESStatefulSetName() + CSRNameSuffix +} + +// MCS Related Names + +// MCSDeploymentName returns the name for MCS Deployment +func (mi *MinIOInstance) MCSDeploymentName() string { + return mi.Name + MCSName +} + +// MCSCIServiceName returns the name for MCS Cluster IP Service +func (mi *MinIOInstance) MCSCIServiceName() string { + return mi.Name + MCSName + "-service" +} diff --git a/pkg/apis/operator.min.io/v1/types.go b/pkg/apis/operator.min.io/v1/types.go index 6c19bb16d8e..b9c4d8613f8 100644 --- a/pkg/apis/operator.min.io/v1/types.go +++ b/pkg/apis/operator.min.io/v1/types.go @@ -120,9 +120,12 @@ type MinIOInstanceSpec struct { // Definition for Cluster in given MinIO cluster // +optional Zones []Zone `json:"zones"` - // McsConfig is for setting up minio/mcs for graphical user interface + // MCSConfig is for setting up minio/mcs for graphical user interface //+optional - Mcs *McsConfig `json:"mcs,omitempty"` + MCS *MCSConfig `json:"mcs,omitempty"` + // KES is for setting up minio/kes as MinIO KMS + //+optional + KES *KESConfig `json:"kes,omitempty"` } // MinIOInstanceStatus is the status for a MinIOInstance resource @@ -149,6 +152,30 @@ type Zone struct { Servers int32 `json:"servers"` } +// MCSConfig defines the credentials for mcs +type MCSConfig struct { + Image string `json:"image,omitempty"` + MCSAccessKey string `json:"mcsAccessKey"` + MCSSecret *corev1.LocalObjectReference `json:"mcsSecret,omitempty"` + Selector *metav1.LabelSelector `json:"selector,omitempty"` + Metadata *metav1.ObjectMeta `json:"metadata,omitempty"` +} + +// KESConfig defines the specifications for KES StatefulSet +type KESConfig struct { + // Replicas defines number of pods for KES StatefulSet. + // +optional + Replicas int32 `json:"replicas,omitempty"` + // Image defines the MinIOInstance Docker image. + // +optional + Image string `json:"image,omitempty"` + // This configSecret serves as the configuration for KES + // This is a mandatory field + Configuration *corev1.LocalObjectReference `json:"configSecret"` + Selector *metav1.LabelSelector `json:"selector,omitempty"` + Metadata *metav1.ObjectMeta `json:"metadata,omitempty"` +} + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // MinIOInstanceList is a list of MinIOInstance resources @@ -214,12 +241,3 @@ type Args struct { Target string `json:"target"` Flags []string `json:"flags"` } - -// McsConfig defines the credentials for mcs -type McsConfig struct { - Image string `json:"image,omitempty"` - McsAccessKey string `json:"mcsAccessKey"` - McsSecret *corev1.LocalObjectReference `json:"mcsSecret,omitempty"` - Selector *metav1.LabelSelector `json:"selector,omitempty"` - Metadata *metav1.ObjectMeta `json:"metadata,omitempty"` -} diff --git a/pkg/apis/operator.min.io/v1/zz_generated.deepcopy.go b/pkg/apis/operator.min.io/v1/zz_generated.deepcopy.go index 721bf8839fc..043e942cece 100644 --- a/pkg/apis/operator.min.io/v1/zz_generated.deepcopy.go +++ b/pkg/apis/operator.min.io/v1/zz_generated.deepcopy.go @@ -1,20 +1,20 @@ // +build !ignore_autogenerated -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by deepcopy-gen. DO NOT EDIT. @@ -73,6 +73,37 @@ func (in *CertificateConfig) DeepCopy() *CertificateConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KESConfig) DeepCopyInto(out *KESConfig) { + *out = *in + if in.Configuration != nil { + in, out := &in.Configuration, &out.Configuration + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(metav1.ObjectMeta) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KESConfig. +func (in *KESConfig) DeepCopy() *KESConfig { + if in == nil { + return nil + } + out := new(KESConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalCertificateReference) DeepCopyInto(out *LocalCertificateReference) { *out = *in @@ -90,10 +121,10 @@ func (in *LocalCertificateReference) DeepCopy() *LocalCertificateReference { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *McsConfig) DeepCopyInto(out *McsConfig) { +func (in *MCSConfig) DeepCopyInto(out *MCSConfig) { *out = *in - if in.McsSecret != nil { - in, out := &in.McsSecret, &out.McsSecret + if in.MCSSecret != nil { + in, out := &in.MCSSecret, &out.MCSSecret *out = new(corev1.LocalObjectReference) **out = **in } @@ -110,12 +141,12 @@ func (in *McsConfig) DeepCopyInto(out *McsConfig) { return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new McsConfig. -func (in *McsConfig) DeepCopy() *McsConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MCSConfig. +func (in *MCSConfig) DeepCopy() *MCSConfig { if in == nil { return nil } - out := new(McsConfig) + out := new(MCSConfig) in.DeepCopyInto(out) return out } @@ -279,9 +310,14 @@ func (in *MinIOInstanceSpec) DeepCopyInto(out *MinIOInstanceSpec) { *out = make([]Zone, len(*in)) copy(*out, *in) } - if in.Mcs != nil { - in, out := &in.Mcs, &out.Mcs - *out = new(McsConfig) + if in.MCS != nil { + in, out := &in.MCS, &out.MCS + *out = new(MCSConfig) + (*in).DeepCopyInto(*out) + } + if in.KES != nil { + in, out := &in.KES, &out.KES + *out = new(KESConfig) (*in).DeepCopyInto(*out) } return diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index b5057b8b4ee..70df44e1620 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/doc.go b/pkg/client/clientset/versioned/doc.go index 1391cffc921..41721ca52d4 100644 --- a/pkg/client/clientset/versioned/doc.go +++ b/pkg/client/clientset/versioned/doc.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index 63b6e531b79..0ee2948fcfd 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/fake/doc.go b/pkg/client/clientset/versioned/fake/doc.go index ac005f16d0b..9b99e716709 100644 --- a/pkg/client/clientset/versioned/fake/doc.go +++ b/pkg/client/clientset/versioned/fake/doc.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 5429ee87e34..2262b4dab7b 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. @@ -29,7 +29,7 @@ import ( var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) - +var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ operatorv1.AddToScheme, } diff --git a/pkg/client/clientset/versioned/scheme/doc.go b/pkg/client/clientset/versioned/scheme/doc.go index 7218a52ae6c..7dc3756168f 100644 --- a/pkg/client/clientset/versioned/scheme/doc.go +++ b/pkg/client/clientset/versioned/scheme/doc.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index ae99af7e4ce..eb124b22721 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/doc.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/doc.go index 045f9080d46..3af5d054f10 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/doc.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/doc.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/doc.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/doc.go index 3867d2033eb..16f44399065 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/doc.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/doc.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_minioinstance.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_minioinstance.go index ab3c1237784..ca6f30ed73f 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_minioinstance.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_minioinstance.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_mirrorinstance.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_mirrorinstance.go index 8efb1f373c6..3e855ce7121 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_mirrorinstance.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_mirrorinstance.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_operator.min.io_client.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_operator.min.io_client.go index 77b78e4b715..4e2db48e794 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_operator.min.io_client.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/fake/fake_operator.min.io_client.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/generated_expansion.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/generated_expansion.go index 7be3bf74d32..9af6bd73205 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/generated_expansion.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/minioinstance.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/minioinstance.go index 67cf755375f..95d08b54a7c 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/minioinstance.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/minioinstance.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/mirrorinstance.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/mirrorinstance.go index 073fe805ef9..22cd5cd82a7 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/mirrorinstance.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/mirrorinstance.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/clientset/versioned/typed/operator.min.io/v1/operator.min.io_client.go b/pkg/client/clientset/versioned/typed/operator.min.io/v1/operator.min.io_client.go index a6e9533cfd5..7e1bf7f88b3 100644 --- a/pkg/client/clientset/versioned/typed/operator.min.io/v1/operator.min.io_client.go +++ b/pkg/client/clientset/versioned/typed/operator.min.io/v1/operator.min.io_client.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by client-gen. DO NOT EDIT. diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 62b14c1ef7c..daca4716619 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by informer-gen. DO NOT EDIT. diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 5aecb393fb4..9696b47e954 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by informer-gen. DO NOT EDIT. diff --git a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index 34889f49265..592250e6dd3 100644 --- a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by informer-gen. DO NOT EDIT. diff --git a/pkg/client/informers/externalversions/operator.min.io/interface.go b/pkg/client/informers/externalversions/operator.min.io/interface.go index 602eefff084..d10185c8da8 100644 --- a/pkg/client/informers/externalversions/operator.min.io/interface.go +++ b/pkg/client/informers/externalversions/operator.min.io/interface.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by informer-gen. DO NOT EDIT. diff --git a/pkg/client/informers/externalversions/operator.min.io/v1/interface.go b/pkg/client/informers/externalversions/operator.min.io/v1/interface.go index 7ad29fc4884..70e7fb154fc 100644 --- a/pkg/client/informers/externalversions/operator.min.io/v1/interface.go +++ b/pkg/client/informers/externalversions/operator.min.io/v1/interface.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by informer-gen. DO NOT EDIT. diff --git a/pkg/client/informers/externalversions/operator.min.io/v1/minioinstance.go b/pkg/client/informers/externalversions/operator.min.io/v1/minioinstance.go index d7a6a9ae040..b08da8a5242 100644 --- a/pkg/client/informers/externalversions/operator.min.io/v1/minioinstance.go +++ b/pkg/client/informers/externalversions/operator.min.io/v1/minioinstance.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by informer-gen. DO NOT EDIT. diff --git a/pkg/client/informers/externalversions/operator.min.io/v1/mirrorinstance.go b/pkg/client/informers/externalversions/operator.min.io/v1/mirrorinstance.go index 9dda49073ed..63b373468cb 100644 --- a/pkg/client/informers/externalversions/operator.min.io/v1/mirrorinstance.go +++ b/pkg/client/informers/externalversions/operator.min.io/v1/mirrorinstance.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by informer-gen. DO NOT EDIT. diff --git a/pkg/client/listers/operator.min.io/v1/expansion_generated.go b/pkg/client/listers/operator.min.io/v1/expansion_generated.go index 8642fe1ac12..29639246843 100644 --- a/pkg/client/listers/operator.min.io/v1/expansion_generated.go +++ b/pkg/client/listers/operator.min.io/v1/expansion_generated.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by lister-gen. DO NOT EDIT. diff --git a/pkg/client/listers/operator.min.io/v1/minioinstance.go b/pkg/client/listers/operator.min.io/v1/minioinstance.go index 443d8cb0d7a..721bec67a3e 100644 --- a/pkg/client/listers/operator.min.io/v1/minioinstance.go +++ b/pkg/client/listers/operator.min.io/v1/minioinstance.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by lister-gen. DO NOT EDIT. diff --git a/pkg/client/listers/operator.min.io/v1/mirrorinstance.go b/pkg/client/listers/operator.min.io/v1/mirrorinstance.go index 85889fb649b..ad53e116ba5 100644 --- a/pkg/client/listers/operator.min.io/v1/mirrorinstance.go +++ b/pkg/client/listers/operator.min.io/v1/mirrorinstance.go @@ -1,18 +1,18 @@ -// This file is part of MinIO Operator -// Copyright (c) 2020 MinIO, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ // Code generated by lister-gen. DO NOT EDIT. diff --git a/pkg/controller/cluster/csr.go b/pkg/controller/cluster/csr.go index d23a2499cb8..c4f304b1900 100644 --- a/pkg/controller/cluster/csr.go +++ b/pkg/controller/cluster/csr.go @@ -25,7 +25,10 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" + "errors" "fmt" + "io" + "io/ioutil" "os" "os/signal" "syscall" @@ -33,8 +36,7 @@ import ( "k8s.io/klog" - miniov1beta1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" - "github.com/minio/minio-operator/pkg/constants" + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" certificates "k8s.io/api/certificates/v1beta1" corev1 "k8s.io/api/core/v1" @@ -65,10 +67,10 @@ func isEqual(a, b []string) bool { return true } -func generateCryptoData(mi *miniov1beta1.MinIOInstance) ([]byte, []byte, error) { +func generateCryptoData(mi *miniov1.MinIOInstance) ([]byte, []byte, error) { dnsNames := make([]string, 0) klog.V(0).Infof("Generating private key") - privateKey, err := newPrivateKey(constants.DefaultEllipticCurve) + privateKey, err := newPrivateKey(miniov1.DefaultEllipticCurve) if err != nil { klog.Errorf("Unexpected error during the ECDSA Key generation: %v", err) return nil, nil, err @@ -82,10 +84,12 @@ func generateCryptoData(mi *miniov1beta1.MinIOInstance) ([]byte, []byte, error) klog.V(0).Infof("Generating CSR with CN=%s", mi.Spec.CertConfig.CommonName) - if isEqual(mi.Spec.CertConfig.DNSNames, mi.GetHosts()) { + hosts := mi.AllMinIOHosts() + + if isEqual(mi.Spec.CertConfig.DNSNames, hosts) { dnsNames = mi.Spec.CertConfig.DNSNames } else { - dnsNames = append(mi.Spec.CertConfig.DNSNames, mi.GetHosts()...) + dnsNames = append(mi.Spec.CertConfig.DNSNames, hosts...) } csrTemplate := x509.CertificateRequest{ @@ -107,40 +111,42 @@ func generateCryptoData(mi *miniov1beta1.MinIOInstance) ([]byte, []byte, error) // createCSR handles all the steps required to create the CSR: from creation of keys, submitting CSR and // finally creating a secret that MinIO statefulset will use to mount private key and certificate for TLS -func (c *Controller) createCSR(ctx context.Context, mi *miniov1beta1.MinIOInstance) error { +// This Method Blocks till the CSR Request is approved via kubectl approve +func (c *Controller) createCSR(ctx context.Context, mi *miniov1.MinIOInstance) error { privKeysBytes, csrBytes, err := generateCryptoData(mi) if err != nil { klog.Errorf("Private Key and CSR generation failed with error: %v", err) return err } - klog.V(2).Infof("Creating csr/%s", mi.GetCSRName()) - err = c.submitCSR(ctx, mi, csrBytes) + err = c.submitCSR(ctx, mi.MinIOPodLabels(), mi.MinIOCSRName(), mi.Namespace, csrBytes, mi) if err != nil { - klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.GetCSRName(), err) + klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.MinIOCSRName(), err) return err } - klog.V(0).Infof("Successfully created csr/%s", mi.GetCSRName()) // fetch certificate from CSR - certbytes, err := c.fetchCertificate(ctx, mi.GetCSRName()) + certbytes, err := c.fetchCertificate(ctx, mi.MinIOCSRName()) if err != nil { - klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.GetCSRName(), err) + klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.MinIOCSRName(), err) return err } + // PEM encode private ECDSA key encodedPrivKey := pem.EncodeToMemory(&pem.Block{Type: privateKeyType, Bytes: privKeysBytes}) + // Create secret for MinIO Statefulset to use - err = c.createSecret(ctx, mi, encodedPrivKey, certbytes) + err = c.createSecret(ctx, mi, mi.MinIOPodLabels(), mi.MinIOTLSSecretName(), mi.Namespace, encodedPrivKey, certbytes) if err != nil { - klog.Errorf("Unexpected error during the creation of the secret/%s: %v", mi.GetTLSSecretName(), err) + klog.Errorf("Unexpected error during the creation of the secret/%s: %v", mi.MinIOTLSSecretName(), err) return err } + return nil } // SubmitCSR is equivalent to kubectl create ${CSR}, if the override is configured, it becomes kubectl apply ${CSR} -func (c *Controller) submitCSR(ctx context.Context, mi *miniov1beta1.MinIOInstance, csrBytes []byte) error { +func (c *Controller) submitCSR(ctx context.Context, labels map[string]string, name, namespace string, csrBytes []byte, mi *miniov1.MinIOInstance) error { encodedBytes := pem.EncodeToMemory(&pem.Block{Type: csrType, Bytes: csrBytes}) kubeCSR := &certificates.CertificateSigningRequest{ @@ -149,14 +155,14 @@ func (c *Controller) submitCSR(ctx context.Context, mi *miniov1beta1.MinIOInstan Kind: "CertificateSigningRequest", }, ObjectMeta: v1.ObjectMeta{ - Name: mi.GetCSRName(), - Labels: map[string]string{constants.InstanceLabel: mi.Name}, - Namespace: mi.Namespace, + Name: name, + Labels: labels, + Namespace: namespace, OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(mi, schema.GroupVersionKind{ - Group: miniov1beta1.SchemeGroupVersion.Group, - Version: miniov1beta1.SchemeGroupVersion.Version, - Kind: constants.MinIOCRDResourceKind, + Group: miniov1.SchemeGroupVersion.Group, + Version: miniov1.SchemeGroupVersion.Version, + Kind: miniov1.MinIOCRDResourceKind, }), }, }, @@ -181,12 +187,12 @@ func (c *Controller) submitCSR(ctx context.Context, mi *miniov1beta1.MinIOInstan // FetchCertificate fetches the generated certificate from the CSR func (c *Controller) fetchCertificate(ctx context.Context, csrName string) ([]byte, error) { klog.V(0).Infof("Start polling for certificate of csr/%s, every %s, timeout after %s", csrName, - constants.DefaultQueryInterval, constants.DefaultQueryTimeout) + miniov1.DefaultQueryInterval, miniov1.DefaultQueryTimeout) - tick := time.NewTicker(constants.DefaultQueryInterval) + tick := time.NewTicker(miniov1.DefaultQueryInterval) defer tick.Stop() - timeout := time.NewTimer(constants.DefaultQueryTimeout) + timeout := time.NewTimer(miniov1.DefaultQueryTimeout) defer tick.Stop() ch := make(chan os.Signal) @@ -216,7 +222,7 @@ func (c *Controller) fetchCertificate(ctx context.Context, csrName string) ([]by return nil, err } } - klog.V(1).Infof("Certificate of csr/%s still not available, next try in %d", csrName, constants.DefaultQueryInterval) + klog.V(1).Infof("Certificate of csr/%s still not available, next try in %d", csrName, miniov1.DefaultQueryInterval) case <-timeout.C: return nil, fmt.Errorf("timeout during certificate fetching of csr/%s", csrName) @@ -224,7 +230,7 @@ func (c *Controller) fetchCertificate(ctx context.Context, csrName string) ([]by } } -func (c *Controller) createSecret(ctx context.Context, mi *miniov1beta1.MinIOInstance, pkBytes, certBytes []byte) error { +func (c *Controller) createSecret(ctx context.Context, mi *miniov1.MinIOInstance, labels map[string]string, name, namespace string, pkBytes, certBytes []byte) error { secret := &corev1.Secret{ Type: "Opaque", TypeMeta: metav1.TypeMeta{ @@ -232,14 +238,14 @@ func (c *Controller) createSecret(ctx context.Context, mi *miniov1beta1.MinIOIns APIVersion: "apps/v1beta1", }, ObjectMeta: metav1.ObjectMeta{ - Name: mi.GetTLSSecretName(), - Namespace: mi.Namespace, - Labels: map[string]string{constants.InstanceLabel: mi.Name}, + Name: name, + Namespace: namespace, + Labels: labels, OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(mi, schema.GroupVersionKind{ - Group: miniov1beta1.SchemeGroupVersion.Group, - Version: miniov1beta1.SchemeGroupVersion.Version, - Kind: constants.MinIOCRDResourceKind, + Group: miniov1.SchemeGroupVersion.Group, + Version: miniov1.SchemeGroupVersion.Version, + Kind: miniov1.MinIOCRDResourceKind, }), }, }, @@ -255,3 +261,23 @@ func (c *Controller) createSecret(ctx context.Context, mi *miniov1beta1.MinIOIns } return nil } + +func parseCertificate(r io.Reader) (*x509.Certificate, error) { + certPEMBlock, err := ioutil.ReadAll(r) + if err != nil { + return nil, err + } + + for { + var certDERBlock *pem.Block + certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) + if certDERBlock == nil { + break + } + + if certDERBlock.Type == "CERTIFICATE" { + return x509.ParseCertificate(certDERBlock.Bytes) + } + } + return nil, errors.New("found no (non-CA) certificate in any PEM block") +} diff --git a/pkg/controller/cluster/kes-csr.go b/pkg/controller/cluster/kes-csr.go new file mode 100644 index 00000000000..f5582d63458 --- /dev/null +++ b/pkg/controller/cluster/kes-csr.go @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2019, 2020, MinIO, Inc. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +package cluster + +import ( + "bytes" + "context" + "crypto/rand" + "crypto/sha256" + "crypto/x509" + "crypto/x509/pkix" + "encoding/hex" + "encoding/pem" + + "k8s.io/klog" + + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" +) + +func generateKESCryptoData(mi *miniov1.MinIOInstance) ([]byte, []byte, error) { + privateKey, err := newPrivateKey(miniov1.DefaultEllipticCurve) + if err != nil { + klog.Errorf("Unexpected error during the ECDSA Key generation: %v", err) + return nil, nil, err + } + + privKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey) + if err != nil { + klog.Errorf("Unexpected error during encoding the ECDSA Private Key: %v", err) + return nil, nil, err + } + + csrTemplate := x509.CertificateRequest{ + Subject: pkix.Name{ + CommonName: mi.KESWildCardName(), + Organization: miniov1.DefaultOrgName, + }, + SignatureAlgorithm: x509.ECDSAWithSHA512, + DNSNames: mi.KESHosts(), + } + + csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, privateKey) + if err != nil { + klog.Errorf("Unexpected error during creating the CSR: %v", err) + return nil, nil, err + } + return privKeyBytes, csrBytes, nil +} + +// createKESTLSCSR handles all the steps required to create the CSR: from creation of keys, submitting CSR and +// finally creating a secret that KES Statefulset will use to mount private key and certificate for TLS +// This Method Blocks till the CSR Request is approved via kubectl approve +func (c *Controller) createKESTLSCSR(ctx context.Context, mi *miniov1.MinIOInstance) error { + privKeysBytes, csrBytes, err := generateKESCryptoData(mi) + if err != nil { + klog.Errorf("Private Key and CSR generation failed with error: %v", err) + return err + } + + err = c.submitCSR(ctx, mi.KESPodLabels(), mi.KESCSRName(), mi.Namespace, csrBytes, mi) + if err != nil { + klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.KESCSRName(), err) + return err + } + + // fetch certificate from CSR + certbytes, err := c.fetchCertificate(ctx, mi.KESCSRName()) + if err != nil { + klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.KESCSRName(), err) + return err + } + + // PEM encode private ECDSA key + encodedPrivKey := pem.EncodeToMemory(&pem.Block{Type: privateKeyType, Bytes: privKeysBytes}) + + // Create secret for KES Statefulset to use + err = c.createSecret(ctx, mi, mi.KESPodLabels(), mi.KESTLSSecretName(), mi.Namespace, encodedPrivKey, certbytes) + if err != nil { + klog.Errorf("Unexpected error during the creation of the secret/%s: %v", mi.MinIOTLSSecretName(), err) + return err + } + + return nil +} + +// createMinIOClientTLSCSR handles all the steps required to create the CSR: from creation of keys, submitting CSR and +// finally creating a secret that KES Statefulset will use for MinIO Client Auth +func (c *Controller) createMinIOClientTLSCSR(ctx context.Context, mi *miniov1.MinIOInstance) error { + privKeysBytes, csrBytes, err := generateCryptoData(mi) + if err != nil { + klog.Errorf("Private Key and CSR generation failed with error: %v", err) + return err + } + + err = c.submitCSR(ctx, mi.MinIOPodLabels(), mi.MinIOClientCSRName(), mi.Namespace, csrBytes, mi) + if err != nil { + klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.MinIOClientCSRName(), err) + return err + } + + // fetch certificate from CSR + certbytes, err := c.fetchCertificate(ctx, mi.MinIOClientCSRName()) + if err != nil { + klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.MinIOClientCSRName(), err) + return err + } + + // parse the certificate here to generate the identity for this certifcate. + // This is later used to update the identity in KES Server Config File + h := sha256.New() + cert, err := parseCertificate(bytes.NewReader(certbytes)) + if err != nil { + klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.MinIOClientCSRName(), err) + return err + } + + _, err = h.Write(cert.RawSubjectPublicKeyInfo) + if err != nil { + klog.Errorf("Unexpected error during the creation of the csr/%s: %v", mi.MinIOClientCSRName(), err) + return err + } + + // Store the Identity to be used later during KES container creation + miniov1.Identity = hex.EncodeToString(h.Sum(nil)) + + // PEM encode private ECDSA key + encodedPrivKey := pem.EncodeToMemory(&pem.Block{Type: privateKeyType, Bytes: privKeysBytes}) + + // Create secret for KES Statefulset to use + err = c.createSecret(ctx, mi, mi.MinIOPodLabels(), mi.MinIOClientTLSSecretName(), mi.Namespace, encodedPrivKey, certbytes) + if err != nil { + klog.Errorf("Unexpected error during the creation of the secret/%s: %v", mi.MinIOClientTLSSecretName(), err) + return err + } + + return nil +} diff --git a/pkg/controller/cluster/main_controller.go b/pkg/controller/cluster/main-controller.go similarity index 82% rename from pkg/controller/cluster/main_controller.go rename to pkg/controller/cluster/main-controller.go index efd676b53bd..43ebe7c06ce 100644 --- a/pkg/controller/cluster/main_controller.go +++ b/pkg/controller/cluster/main-controller.go @@ -33,23 +33,26 @@ import ( "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" appsinformers "k8s.io/client-go/informers/apps/v1" + batchinformers "k8s.io/client-go/informers/batch/v1" coreinformers "k8s.io/client-go/informers/core/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" certapi "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" appslisters "k8s.io/client-go/listers/apps/v1" + batchlisters "k8s.io/client-go/listers/batch/v1" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" queue "k8s.io/client-go/util/workqueue" - miniov1beta1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" clientset "github.com/minio/minio-operator/pkg/client/clientset/versioned" minioscheme "github.com/minio/minio-operator/pkg/client/clientset/versioned/scheme" informers "github.com/minio/minio-operator/pkg/client/informers/externalversions/operator.min.io/v1" listers "github.com/minio/minio-operator/pkg/client/listers/operator.min.io/v1" "github.com/minio/minio-operator/pkg/resources/deployments" + "github.com/minio/minio-operator/pkg/resources/jobs" "github.com/minio/minio-operator/pkg/resources/services" "github.com/minio/minio-operator/pkg/resources/statefulsets" ) @@ -92,6 +95,13 @@ type Controller struct { // has synced at least once. deploymentListerSynced cache.InformerSynced + // jobLister is able to list/get Deployments from a shared + // informer's store. + jobLister batchlisters.JobLister + // jobListerSynced returns true if the Deployment shared informer + // has synced at least once. + jobListerSynced cache.InformerSynced + // minioInstancesLister lists MinIOInstance from a shared informer's // store. minioInstancesLister listers.MinIOInstanceLister @@ -124,6 +134,7 @@ func NewController( certClient certapi.CertificatesV1beta1Client, statefulSetInformer appsinformers.StatefulSetInformer, deploymentInformer appsinformers.DeploymentInformer, + jobInformer batchinformers.JobInformer, minioInstanceInformer informers.MinIOInstanceInformer, serviceInformer coreinformers.ServiceInformer) *Controller { @@ -145,6 +156,8 @@ func NewController( statefulSetListerSynced: statefulSetInformer.Informer().HasSynced, deploymentLister: deploymentInformer.Lister(), deploymentListerSynced: statefulSetInformer.Informer().HasSynced, + jobLister: jobInformer.Lister(), + jobListerSynced: jobInformer.Informer().HasSynced, minioInstancesLister: minioInstanceInformer.Lister(), minioInstancesSynced: minioInstanceInformer.Informer().HasSynced, serviceLister: serviceInformer.Lister(), @@ -323,21 +336,22 @@ func (c *Controller) syncHandler(key string) error { } mi.EnsureDefaults() + miniov1.InitGlobals(mi) - svc, err := c.serviceLister.Services(mi.Namespace).Get(mi.GetServiceName()) + svc, err := c.serviceLister.Services(mi.Namespace).Get(mi.MinIOCIServiceName()) // If the service doesn't exist, we'll create it if apierrors.IsNotFound(err) { - klog.V(2).Infof("Creating a new Service for cluster %q", nsName) - svc = services.NewServiceForCluster(mi) - _, err = c.kubeClientSet.CoreV1().Services(svc.Namespace).Create(ctx, svc, cOpts) + klog.V(2).Infof("Creating a new Cluster IP Service for cluster %q", nsName) + svc = services.NewClusterIPForMinIO(mi) + _, err = c.kubeClientSet.CoreV1().Services(mi.Namespace).Create(ctx, svc, cOpts) } - hlSvc, err := c.serviceLister.Services(mi.Namespace).Get(mi.GetHeadlessServiceName()) + hlSvc, err := c.serviceLister.Services(mi.Namespace).Get(mi.MinIOHLServiceName()) // If the headless service doesn't exist, we'll create it if apierrors.IsNotFound(err) { klog.V(2).Infof("Creating a new Headless Service for cluster %q", nsName) - hlSvc = services.NewHeadlessServiceForCluster(mi) - _, err = c.kubeClientSet.CoreV1().Services(hlSvc.Namespace).Create(ctx, hlSvc, cOpts) + hlSvc = services.NewHeadlessForMinIO(mi) + _, err = c.kubeClientSet.CoreV1().Services(mi.Namespace).Create(ctx, hlSvc, cOpts) } // If an error occurs during Get/Create, we'll requeue the item so we can @@ -356,7 +370,7 @@ func (c *Controller) syncHandler(key string) error { } if mi.RequiresAutoCertSetup() { - _, err := c.certClient.CertificateSigningRequests().Get(ctx, mi.GetCSRName(), metav1.GetOptions{}) + _, err := c.certClient.CertificateSigningRequests().Get(ctx, mi.MinIOCSRName(), metav1.GetOptions{}) if err != nil { // If the CSR doesn't exist, we'll create it if apierrors.IsNotFound(err) { @@ -367,13 +381,41 @@ func (c *Controller) syncHandler(key string) error { return err } } + if mi.HasKESEnabled() { + _, err := c.certClient.CertificateSigningRequests().Get(ctx, mi.KESCSRName(), metav1.GetOptions{}) + if err != nil { + // If the CSR doesn't exist, we'll create it + if apierrors.IsNotFound(err) { + klog.V(2).Infof("Creating a new Certificate Signing Request for cluster %q", nsName) + err = c.createKESTLSCSR(ctx, mi) + if err != nil { + return err + } + } else { + return err + } + } + _, err = c.certClient.CertificateSigningRequests().Get(ctx, mi.MinIOClientCSRName(), metav1.GetOptions{}) + if err != nil { + // If the CSR doesn't exist, we'll create it + if apierrors.IsNotFound(err) { + klog.V(2).Infof("Creating a new Certificate Signing Request for cluster %q", nsName) + err = c.createMinIOClientTLSCSR(ctx, mi) + if err != nil { + return err + } + } else { + return err + } + } + } } // Get the StatefulSet with the name specified in MinIOInstance.spec ss, err := c.statefulSetLister.StatefulSets(mi.Namespace).Get(mi.Name) // If the resource doesn't exist, we'll create it if apierrors.IsNotFound(err) { - ss = statefulsets.NewForCluster(mi, hlSvc.Name) + ss = statefulsets.NewForMinIO(mi, hlSvc.Name) ss, err = c.kubeClientSet.AppsV1().StatefulSets(mi.Namespace).Create(ctx, ss, cOpts) } @@ -384,12 +426,12 @@ func (c *Controller) syncHandler(key string) error { return err } - if mi.HasMcsEnabled() { - // Get the Deployment with the name specified in MinIOInstance.spec - d, err := c.deploymentLister.Deployments(mi.Namespace).Get(mi.Name) + if mi.HasMCSEnabled() { + // Get the Deployment with the name specified in MirrorInstace.spec + d, err := c.deploymentLister.Deployments(mi.Namespace).Get(mi.MCSDeploymentName()) // If the resource doesn't exist, we'll create it if apierrors.IsNotFound(err) { - if !mi.HasCredsSecret() || !mi.HasMcsSecret() { + if !mi.HasCredsSecret() || !mi.HasMCSSecret() { msg := "Please set the credentials" klog.V(2).Infof(msg) return fmt.Errorf(msg) @@ -401,26 +443,26 @@ func (c *Controller) syncHandler(key string) error { return sErr } - mcsSecretName := mi.Spec.Mcs.McsSecret.Name + mcsSecretName := mi.Spec.MCS.MCSSecret.Name mcsSecret, sErr := c.kubeClientSet.CoreV1().Secrets(mi.Namespace).Get(ctx, mcsSecretName, gOpts) if sErr != nil { return sErr } // Check if any one replica is READY if ss.Status.ReadyReplicas > 0 { - if pErr := mi.CreateMcsUser(minioSecret.Data, mcsSecret.Data); pErr != nil { + if pErr := mi.CreateMCSUser(minioSecret.Data, mcsSecret.Data); pErr != nil { klog.V(2).Infof(pErr.Error()) return pErr } // Create MCS Deployment - d = deployments.NewMcsDeployment(mi) + d = deployments.NewForMCS(mi) d, err = c.kubeClientSet.AppsV1().Deployments(mi.Namespace).Create(ctx, d, cOpts) if err != nil { klog.V(2).Infof(err.Error()) return err } // Create MCS service - mcsSvc := services.NewMcsServiceForCluster(mi) + mcsSvc := services.NewClusterIPForMCS(mi) _, err = c.kubeClientSet.CoreV1().Services(svc.Namespace).Create(ctx, mcsSvc, cOpts) if err != nil { klog.V(2).Infof(err.Error()) @@ -432,6 +474,50 @@ func (c *Controller) syncHandler(key string) error { } } + if mi.HasKESEnabled() && !(mi.RequiresAutoCertSetup() || mi.RequiresExternalCertSetup()) { + msg := "KES Setup Requires MinIO to be configured with TLS" + klog.V(2).Infof(msg) + return fmt.Errorf(msg) + } + + if mi.HasKESEnabled() && (mi.RequiresAutoCertSetup() || mi.RequiresExternalCertSetup()) { + svc, err := c.serviceLister.Services(mi.Namespace).Get(mi.KESHLServiceName()) + // If the headless service doesn't exist, we'll create it + if apierrors.IsNotFound(err) { + klog.V(2).Infof("Creating a new Headless Service for cluster %q", nsName) + svc = services.NewHeadlessForKES(mi) + _, err = c.kubeClientSet.CoreV1().Services(svc.Namespace).Create(ctx, svc, cOpts) + } else { + return err + } + // Get the StatefulSet with the name specified in spec + ks, err := c.statefulSetLister.StatefulSets(mi.Namespace).Get(mi.KESStatefulSetName()) + if apierrors.IsNotFound(err) { + ks = statefulsets.NewForKES(mi, svc.Name) + klog.V(2).Infof("Creating a new StatefulSet for cluster %q", nsName) + ks, err = c.kubeClientSet.AppsV1().StatefulSets(mi.Namespace).Create(ctx, ks, cOpts) + if err != nil { + klog.V(2).Infof(err.Error()) + return err + } + } else { + return err + } + // After KES and MinIO are deployed successfully, create the MinIO Key on KES KMS Backend + j, err := c.jobLister.Jobs(mi.Namespace).Get(mi.Name) + if apierrors.IsNotFound(err) { + j = jobs.NewForKES(mi) + klog.V(2).Infof("Creating a new Job for cluster %q", nsName) + j, err = c.kubeClientSet.BatchV1().Jobs(mi.Namespace).Create(ctx, j, cOpts) + if err != nil { + klog.V(2).Infof(err.Error()) + return err + } + } else { + return err + } + } + // If the StatefulSet is not controlled by this MinIOInstance resource, we should log // a warning to the event recorder and ret if !metav1.IsControlledBy(ss, mi) { @@ -443,9 +529,9 @@ func (c *Controller) syncHandler(key string) error { // If this number of the replicas on the MinIOInstance resource is specified, and the // number does not equal the current desired replicas on the StatefulSet, we // should update the StatefulSet resource. - if mi.GetReplicas() != *ss.Spec.Replicas { - klog.V(4).Infof("MinIOInstance %s replicas: %d, StatefulSet replicas: %d", name, mi.GetReplicas(), *ss.Spec.Replicas) - ss = statefulsets.NewForCluster(mi, hlSvc.Name) + if mi.MinIOReplicas() != *ss.Spec.Replicas { + klog.V(4).Infof("MinIOInstance %s replicas: %d, StatefulSet replicas: %d", name, mi.MinIOReplicas(), *ss.Spec.Replicas) + ss = statefulsets.NewForMinIO(mi, hlSvc.Name) err = c.kubeClientSet.AppsV1().StatefulSets(mi.Namespace).Delete(ctx, ss.Name, metav1.DeleteOptions{}) if err != nil { return err @@ -461,7 +547,7 @@ func (c *Controller) syncHandler(key string) error { // should update the StatefulSet resource. if mi.Spec.Image != ss.Spec.Template.Spec.Containers[0].Image { klog.V(4).Infof("Updating MinIOInstance %s MinIO server version %s, to: %s", name, mi.Spec.Image, ss.Spec.Template.Spec.Containers[0].Image) - ss = statefulsets.NewForCluster(mi, hlSvc.Name) + ss = statefulsets.NewForMinIO(mi, hlSvc.Name) _, err = c.kubeClientSet.AppsV1().StatefulSets(mi.Namespace).Update(ctx, ss, uOpts) } @@ -472,9 +558,9 @@ func (c *Controller) syncHandler(key string) error { return err } - if mi.HasMcsEnabled() && d != nil && mi.Spec.Mcs.Image != d.Spec.Template.Spec.Containers[0].Image { - klog.V(4).Infof("Updating MinIOInstance %s mcs version %s, to: %s", name, mi.Spec.Mcs.Image, d.Spec.Template.Spec.Containers[0].Image) - d = deployments.NewMcsDeployment(mi) + if mi.HasMCSEnabled() && d != nil && mi.Spec.MCS.Image != d.Spec.Template.Spec.Containers[0].Image { + klog.V(4).Infof("Updating MinIOInstance %s mcs version %s, to: %s", name, mi.Spec.MCS.Image, d.Spec.Template.Spec.Containers[0].Image) + d = deployments.NewForMCS(mi) _, err = c.kubeClientSet.AppsV1().Deployments(mi.Namespace).Update(ctx, d, uOpts) // If an error occurs during Update, we'll requeue the item so we can // attempt processing again later. This could have been caused by a @@ -493,7 +579,7 @@ func (c *Controller) syncHandler(key string) error { return nil } -func (c *Controller) updateMinIOInstanceStatus(ctx context.Context, minioInstance *miniov1beta1.MinIOInstance, statefulSet *appsv1.StatefulSet) error { +func (c *Controller) updateMinIOInstanceStatus(ctx context.Context, minioInstance *miniov1.MinIOInstance, statefulSet *appsv1.StatefulSet) error { opts := metav1.UpdateOptions{} // NEVER modify objects from the store. It's a read-only, local cache. // You can use DeepCopy() to make a deep copy of original object and modify this copy diff --git a/pkg/controller/mirror/mirror_controller.go b/pkg/controller/mirror/mirror-controller.go similarity index 99% rename from pkg/controller/mirror/mirror_controller.go rename to pkg/controller/mirror/mirror-controller.go index 48c8b2328c3..0efa8a11dca 100644 --- a/pkg/controller/mirror/mirror_controller.go +++ b/pkg/controller/mirror/mirror-controller.go @@ -274,7 +274,7 @@ func (c *Controller) syncHandler(key string) error { j, err := c.jobLister.Jobs(mi.Namespace).Get(mi.Name) // If the resource doesn't exist, we'll create it if errors.IsNotFound(err) { - j = jobs.NewForCluster(mi) + j = jobs.NewForMirror(mi) _, err = c.kubeClientSet.BatchV1().Jobs(mi.Namespace).Create(ctx, j, cOpts) } diff --git a/pkg/resources/deployments/deployment.go b/pkg/resources/deployments/mcs-deployment.go similarity index 62% rename from pkg/resources/deployments/deployment.go rename to pkg/resources/deployments/mcs-deployment.go index 7d5c09622b7..8651c1fc20a 100644 --- a/pkg/resources/deployments/deployment.go +++ b/pkg/resources/deployments/mcs-deployment.go @@ -18,21 +18,21 @@ package deployments import ( - miniov1beta1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" - "github.com/minio/minio-operator/pkg/constants" + "net" + "strconv" + + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" ) -// Returns the Mcs environment variables set in configuration. -// If a user specifies a set of secrets for the MCS Environment -func mcsEnvironmentVars(mi *miniov1beta1.MinIOInstance) []corev1.EnvVar { +// Returns the MCS environment variables set in configuration. +func mcsEnvironmentVars(mi *miniov1.MinIOInstance) []corev1.EnvVar { envVars := make([]corev1.EnvVar, 0) - if mi.HasMcsSecret() { + if mi.HasMCSSecret() { var secretName string - secretName = mi.Spec.Mcs.McsSecret.Name + secretName = mi.Spec.MCS.MCSSecret.Name envVars = append(envVars, corev1.EnvVar{ Name: "MCS_HMAC_JWT_SECRET", ValueFrom: &corev1.EnvVarSource{ @@ -65,7 +65,7 @@ func mcsEnvironmentVars(mi *miniov1beta1.MinIOInstance) []corev1.EnvVar { }, }, corev1.EnvVar{ Name: "MCS_MINIO_SERVER", - Value: "http://" + mi.GetServiceHost(), + Value: miniov1.Scheme + "://" + net.JoinHostPort(mi.MinIOCIServiceHost(), strconv.Itoa(miniov1.MinIOPort)), }, corev1.EnvVar{ Name: "MCS_SECRET_KEY", ValueFrom: &corev1.EnvVarSource{ @@ -78,18 +78,14 @@ func mcsEnvironmentVars(mi *miniov1beta1.MinIOInstance) []corev1.EnvVar { }, }, corev1.EnvVar{ Name: "MCS_ACCESS_KEY", - Value: mi.Spec.Mcs.McsAccessKey, + Value: mi.Spec.MCS.MCSAccessKey, }) } - // Return environment variables return envVars } -func mcsMetadata(mi *miniov1beta1.MinIOInstance) metav1.ObjectMeta { +func mcsMetadata(mi *miniov1.MinIOInstance) metav1.ObjectMeta { meta := metav1.ObjectMeta{} - if mi.HasMcsMetadata() { - meta = *mi.Spec.Mcs.Metadata - } // Initialize empty fields if meta.Labels == nil { meta.Labels = make(map[string]string) @@ -97,63 +93,60 @@ func mcsMetadata(mi *miniov1beta1.MinIOInstance) metav1.ObjectMeta { if meta.Annotations == nil { meta.Annotations = make(map[string]string) } + + if mi.HasMCSMetadata() { + meta = *mi.Spec.MCS.Metadata + } + for k, v := range mi.MCSPodLabels() { + meta.Labels[k] = v + } // Add the Selector labels set by user - if mi.HasMcsSelector() { - for k, v := range mi.Spec.Mcs.Selector.MatchLabels { + if mi.HasMCSSelector() { + for k, v := range mi.Spec.MCS.Selector.MatchLabels { meta.Labels[k] = v } } - - // attach McsInstanceLabel to be able to target this from the MCS service - meta.Labels[constants.McsInstanceLabel] = mi.Name + constants.McsServiceNameSuffix - return meta } -// Builds the Mcs container for a MinIOInstance. -func mcsContainer(mi *miniov1beta1.MinIOInstance) corev1.Container { +// Builds the MCS container for a MinIOInstance. +func mcsContainer(mi *miniov1.MinIOInstance) corev1.Container { args := []string{"server"} return corev1.Container{ - Name: constants.McsName, - Image: mi.Spec.Mcs.Image, + Name: miniov1.MCSContainerName, + Image: mi.Spec.MCS.Image, Ports: []corev1.ContainerPort{ { - ContainerPort: constants.McsPort, + ContainerPort: miniov1.MCSPort, }, }, - ImagePullPolicy: constants.DefaultImagePullPolicy, + ImagePullPolicy: miniov1.DefaultImagePullPolicy, Args: args, Env: mcsEnvironmentVars(mi), Resources: mi.Spec.Resources, } } -// NewMcsDeployment creates a new Deployment for the given MinIO instance. -func NewMcsDeployment(mi *miniov1beta1.MinIOInstance) *appsv1.Deployment { +// NewForMCS creates a new Deployment for the given MinIO instance. +func NewForMCS(mi *miniov1.MinIOInstance) *appsv1.Deployment { var replicas int32 = 1 d := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Namespace: mi.Namespace, - Name: mi.Name, - OwnerReferences: []metav1.OwnerReference{ - *metav1.NewControllerRef(mi, schema.GroupVersionKind{ - Group: miniov1beta1.SchemeGroupVersion.Group, - Version: miniov1beta1.SchemeGroupVersion.Version, - Kind: constants.MinIOCRDResourceKind, - }), - }, + Namespace: mi.Namespace, + Name: mi.MCSDeploymentName(), + OwnerReferences: mi.OwnerRef(), }, Spec: appsv1.DeploymentSpec{ Replicas: &replicas, - Selector: mi.Spec.Mcs.Selector, + Selector: mi.Spec.MCS.Selector, Template: corev1.PodTemplateSpec{ ObjectMeta: mcsMetadata(mi), Spec: corev1.PodSpec{ Containers: []corev1.Container{mcsContainer(mi)}, - RestartPolicy: corev1.RestartPolicyAlways, + RestartPolicy: miniov1.MCSRestartPolicy, }, }, }, diff --git a/pkg/resources/jobs/kes-job.go b/pkg/resources/jobs/kes-job.go new file mode 100644 index 00000000000..686cfb83ce8 --- /dev/null +++ b/pkg/resources/jobs/kes-job.go @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2020, MinIO, Inc. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +package jobs + +import ( + "net" + "strconv" + + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// NewForKES creates a new Job to create KES Key +func NewForKES(mi *miniov1.MinIOInstance) *batchv1.Job { + + containers := []corev1.Container{kesJobContainer(mi)} + + var MinIOCertKeyPaths = []corev1.KeyToPath{ + {Key: "public.crt", Path: "minio.crt"}, + {Key: "private.key", Path: "minio.key"}, + } + + podVolumes := []corev1.Volume{ + { + Name: mi.KESVolMountName(), + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: mi.MinIOClientTLSSecretName(), + }, + Items: MinIOCertKeyPaths, + }, + }, + }, + }, + }, + }, + } + + d := &batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: mi.Namespace, + Name: mi.KESJobName(), + OwnerReferences: mi.OwnerRef(), + }, + Spec: batchv1.JobSpec{ + Template: corev1.PodTemplateSpec{ + ObjectMeta: kesMetadata(mi), + Spec: corev1.PodSpec{ + RestartPolicy: miniov1.KESJobRestartPolicy, + Containers: containers, + ImagePullSecrets: []corev1.LocalObjectReference{mi.Spec.ImagePullSecret}, + Volumes: podVolumes, + }, + }, + }, + } + + return d +} + +// returns the KES job container +func kesJobContainer(mi *miniov1.MinIOInstance) corev1.Container { + args := []string{"key", "create", miniov1.KESMinIOKey, "-k"} + + return corev1.Container{ + Name: miniov1.KESContainerName, + Image: mi.Spec.KES.Image, + ImagePullPolicy: miniov1.DefaultImagePullPolicy, + Args: args, + Env: kesEnvironmentVars(mi), + VolumeMounts: kesVolumeMounts(mi), + } +} + +// Returns the KES environment variables required for the Job. +func kesEnvironmentVars(mi *miniov1.MinIOInstance) []corev1.EnvVar { + return []corev1.EnvVar{ + { + Name: "KES_SERVER", + Value: "https://" + net.JoinHostPort(mi.KESServiceHost(), strconv.Itoa(miniov1.KESPort)), + }, + { + Name: "KES_CLIENT_CERT", + Value: miniov1.KESConfigMountPath + "/minio.crt", + }, + { + Name: "KES_CLIENT_KEY", + Value: miniov1.KESConfigMountPath + "/minio.key", + }, + } +} + +// KESMetadata Returns the KES pods metadata set in configuration. +// If a user specifies metadata in the spec we return that +// metadata. +func kesMetadata(mi *miniov1.MinIOInstance) metav1.ObjectMeta { + meta := metav1.ObjectMeta{} + + if mi.HasKESMetadata() { + meta = *mi.Spec.KES.Metadata + } + + // Add the additional label from spec + for k, v := range mi.KESPodLabels() { + meta.Labels[k] = v + } + + // Add the Selector labels set by user + if mi.HasKESSelector() { + for k, v := range mi.Spec.KES.Selector.MatchLabels { + meta.Labels[k] = v + } + } + return meta +} + +// kesVolumeMounts builds the volume mounts for KES container. +func kesVolumeMounts(mi *miniov1.MinIOInstance) []corev1.VolumeMount { + return []corev1.VolumeMount{ + { + Name: mi.KESVolMountName(), + MountPath: miniov1.KESConfigMountPath, + }, + } +} diff --git a/pkg/resources/jobs/job.go b/pkg/resources/jobs/mirror-job.go similarity index 76% rename from pkg/resources/jobs/job.go rename to pkg/resources/jobs/mirror-job.go index 0d40194a465..1f86654334e 100644 --- a/pkg/resources/jobs/job.go +++ b/pkg/resources/jobs/mirror-job.go @@ -20,16 +20,15 @@ package jobs import ( "strings" - miniov1beta1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" - "github.com/minio/minio-operator/pkg/constants" + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" ) -// NewForCluster creates a new Job for the given mirror instance. -func NewForCluster(mi *miniov1beta1.MirrorInstance) *batchv1.Job { +// NewForMirror creates a new Job for the given mirror instance. +func NewForMirror(mi *miniov1.MirrorInstance) *batchv1.Job { containers := []corev1.Container{mirrorJobContainer(mi)} @@ -39,9 +38,9 @@ func NewForCluster(mi *miniov1beta1.MirrorInstance) *batchv1.Job { Name: mi.Name, OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(mi, schema.GroupVersionKind{ - Group: miniov1beta1.SchemeGroupVersion.Group, - Version: miniov1beta1.SchemeGroupVersion.Version, - Kind: constants.MirrorCRDResourceKind, + Group: miniov1.SchemeGroupVersion.Group, + Version: miniov1.SchemeGroupVersion.Version, + Kind: miniov1.MirrorCRDResourceKind, }), }, }, @@ -49,7 +48,7 @@ func NewForCluster(mi *miniov1beta1.MirrorInstance) *batchv1.Job { Template: corev1.PodTemplateSpec{ ObjectMeta: mirrorMetadata(mi), Spec: corev1.PodSpec{ - RestartPolicy: constants.MirrorJobRestartPolicy, + RestartPolicy: miniov1.MirrorJobRestartPolicy, Containers: containers, ImagePullSecrets: []corev1.LocalObjectReference{mi.Spec.ImagePullSecret}, }, @@ -61,11 +60,11 @@ func NewForCluster(mi *miniov1beta1.MirrorInstance) *batchv1.Job { } // Builds the mc container for a MirrorInstance. -func mirrorJobContainer(mi *miniov1beta1.MirrorInstance) corev1.Container { +func mirrorJobContainer(mi *miniov1.MirrorInstance) corev1.Container { args := []string{"mirror"} // Add default flags - args = append(args, constants.DefaultMirrorFlags...) + args = append(args, miniov1.DefaultMirrorFlags...) for _, f := range mi.Spec.Args.Flags { arg := strings.Split(f, " ") @@ -81,16 +80,16 @@ func mirrorJobContainer(mi *miniov1beta1.MirrorInstance) corev1.Container { } return corev1.Container{ - Name: constants.MirorContainerName, + Name: miniov1.MirrorContainerName, Image: mi.Spec.Image, - ImagePullPolicy: constants.DefaultImagePullPolicy, + ImagePullPolicy: miniov1.DefaultImagePullPolicy, Args: args, Env: mirrorEnvironmentVars(mi), } } // Returns the mc mirror environment variables set in configuration. -func mirrorEnvironmentVars(mi *miniov1beta1.MirrorInstance) []corev1.EnvVar { +func mirrorEnvironmentVars(mi *miniov1.MirrorInstance) []corev1.EnvVar { envVars := make([]corev1.EnvVar, 0) // Add all the environment variables for _, e := range mi.Spec.Env { @@ -103,7 +102,7 @@ func mirrorEnvironmentVars(mi *miniov1beta1.MirrorInstance) []corev1.EnvVar { // Returns the MC pods metadata set in configuration. // If a user specifies metadata in the spec we return that // metadata. -func mirrorMetadata(mi *miniov1beta1.MirrorInstance) metav1.ObjectMeta { +func mirrorMetadata(mi *miniov1.MirrorInstance) metav1.ObjectMeta { meta := metav1.ObjectMeta{} if mi.HasMetadata() { meta = *mi.Spec.Metadata diff --git a/pkg/resources/services/service.go b/pkg/resources/services/service.go index 4f36d149a01..4a1ee78af22 100644 --- a/pkg/resources/services/service.go +++ b/pkg/resources/services/service.go @@ -20,96 +20,89 @@ package services import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - miniov1beta1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" - constants "github.com/minio/minio-operator/pkg/constants" + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" ) -// NewServiceForCluster will return a new headless Kubernetes service for a MinIOInstance -func NewServiceForCluster(mi *miniov1beta1.MinIOInstance) *corev1.Service { - minioPort := corev1.ServicePort{Port: constants.MinIOServicePortNumber, Name: constants.MinIOServicePortName} +// NewClusterIPForMinIO will return a new headless Kubernetes service for a MinIOInstance +func NewClusterIPForMinIO(mi *miniov1.MinIOInstance) *corev1.Service { + minioPort := corev1.ServicePort{Port: miniov1.MinIOPort, Name: miniov1.MinIOServicePortName} svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{constants.InstanceLabel: mi.Name}, - Name: mi.GetServiceName(), - Namespace: mi.Namespace, - OwnerReferences: []metav1.OwnerReference{ - *metav1.NewControllerRef(mi, schema.GroupVersionKind{ - Group: miniov1beta1.SchemeGroupVersion.Group, - Version: miniov1beta1.SchemeGroupVersion.Version, - Kind: constants.MinIOCRDResourceKind, - }), - }, - Annotations: map[string]string{ - "service.alpha.kubernetes.io/tolerate-unready-endpoints": "true", - }, + Labels: mi.MinIOPodLabels(), + Name: mi.MinIOCIServiceName(), + Namespace: mi.Namespace, + OwnerReferences: mi.OwnerRef(), }, Spec: corev1.ServiceSpec{ PublishNotReadyAddresses: true, Ports: []corev1.ServicePort{minioPort}, - Selector: map[string]string{ - constants.InstanceLabel: mi.Name, - }, + Selector: mi.MinIOPodLabels(), + Type: corev1.ServiceTypeClusterIP, }, } return svc } -// NewHeadlessServiceForCluster will return a new headless Kubernetes service for a MinIOInstance -func NewHeadlessServiceForCluster(mi *miniov1beta1.MinIOInstance) *corev1.Service { - minioPort := corev1.ServicePort{Port: constants.MinIOServicePortNumber, Name: constants.MinIOServicePortName} +// NewHeadlessForMinIO will return a new headless Kubernetes service for a MinIOInstance +func NewHeadlessForMinIO(mi *miniov1.MinIOInstance) *corev1.Service { + minioPort := corev1.ServicePort{Port: miniov1.MinIOPort, Name: miniov1.MinIOServicePortName} svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{constants.InstanceLabel: mi.Name}, - Name: mi.GetHeadlessServiceName(), - Namespace: mi.Namespace, - OwnerReferences: []metav1.OwnerReference{ - *metav1.NewControllerRef(mi, schema.GroupVersionKind{ - Group: miniov1beta1.SchemeGroupVersion.Group, - Version: miniov1beta1.SchemeGroupVersion.Version, - Kind: constants.MinIOCRDResourceKind, - }), - }, - Annotations: map[string]string{ - "service.alpha.kubernetes.io/tolerate-unready-endpoints": "true", - }, + Labels: mi.MinIOPodLabels(), + Name: mi.MinIOHLServiceName(), + Namespace: mi.Namespace, + OwnerReferences: mi.OwnerRef(), }, Spec: corev1.ServiceSpec{ PublishNotReadyAddresses: true, Ports: []corev1.ServicePort{minioPort}, - Selector: map[string]string{ - constants.InstanceLabel: mi.Name, - }, - ClusterIP: corev1.ClusterIPNone, + Selector: mi.MinIOPodLabels(), + Type: corev1.ServiceTypeClusterIP, + ClusterIP: corev1.ClusterIPNone, }, } return svc } -// NewMcsServiceForCluster will return a new service for a MinIOInstance's MCS -func NewMcsServiceForCluster(mi *miniov1beta1.MinIOInstance) *corev1.Service { - minioPort := corev1.ServicePort{Port: constants.McsPort, Name: constants.McsServicePortName} +// NewHeadlessForKES will return a new headless Kubernetes service for a KES StatefulSet +func NewHeadlessForKES(mi *miniov1.MinIOInstance) *corev1.Service { + kesPort := corev1.ServicePort{Port: miniov1.KESPort, Name: miniov1.KESServicePortName} svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{constants.InstanceLabel: mi.Name}, - Name: mi.GetMcsServiceName(), - Namespace: mi.Namespace, - OwnerReferences: []metav1.OwnerReference{ - *metav1.NewControllerRef(mi, schema.GroupVersionKind{ - Group: miniov1beta1.SchemeGroupVersion.Group, - Version: miniov1beta1.SchemeGroupVersion.Version, - Kind: constants.MinIOCRDResourceKind, - }), - }, + Labels: mi.KESPodLabels(), + Name: mi.KESHLServiceName(), + Namespace: mi.Namespace, + OwnerReferences: mi.OwnerRef(), }, Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{minioPort}, - Selector: map[string]string{ - constants.McsInstanceLabel: mi.Name + constants.McsServiceNameSuffix, - }, + PublishNotReadyAddresses: true, + Ports: []corev1.ServicePort{kesPort}, + Selector: mi.KESPodLabels(), + Type: corev1.ServiceTypeClusterIP, + ClusterIP: corev1.ClusterIPNone, + }, + } + + return svc +} + +// NewClusterIPForMCS will return a new cluster IP service for MCS Deployment +func NewClusterIPForMCS(mi *miniov1.MinIOInstance) *corev1.Service { + minioPort := corev1.ServicePort{Port: miniov1.MCSPort, Name: miniov1.MCSServicePortName} + svc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Labels: mi.MCSPodLabels(), + Name: mi.MCSCIServiceName(), + Namespace: mi.Namespace, + OwnerReferences: mi.OwnerRef(), + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{minioPort}, + Selector: mi.MCSPodLabels(), + Type: corev1.ServiceTypeClusterIP, }, } diff --git a/pkg/resources/statefulsets/kes-statefulset.go b/pkg/resources/statefulsets/kes-statefulset.go new file mode 100644 index 00000000000..aa1d071f909 --- /dev/null +++ b/pkg/resources/statefulsets/kes-statefulset.go @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2020, MinIO, Inc. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +package statefulsets + +import ( + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KESMetadata Returns the KES pods metadata set in configuration. +// If a user specifies metadata in the spec we return that +// metadata. +func KESMetadata(mi *miniov1.MinIOInstance) metav1.ObjectMeta { + meta := metav1.ObjectMeta{} + + if mi.HasKESMetadata() { + meta = *mi.Spec.KES.Metadata + } + + // Add the additional label used by StatefulSet spec + for k, v := range mi.KESPodLabels() { + meta.Labels[k] = v + } + // Add the Selector labels set by user + if mi.HasKESSelector() { + for k, v := range mi.Spec.KES.Selector.MatchLabels { + meta.Labels[k] = v + } + } + return meta +} + +// KESVolumeMounts builds the volume mounts for MinIO container. +func KESVolumeMounts(mi *miniov1.MinIOInstance) []corev1.VolumeMount { + var mounts []corev1.VolumeMount + + if mi.RequiresAutoCertSetup() || mi.RequiresExternalCertSetup() { + mounts = append(mounts, corev1.VolumeMount{ + Name: mi.KESVolMountName(), + MountPath: miniov1.KESConfigMountPath, + }) + } + + return mounts +} + +// KESEnvironmentVars returns the KES environment variables set in configuration. +func KESEnvironmentVars(mi *miniov1.MinIOInstance) []corev1.EnvVar { + // pass the identity created while generating the MinIO client cert + return []corev1.EnvVar{ + { + Name: "MINIO_ID", + Value: miniov1.Identity, + }, + } +} + +// KESServerContainer returns the KES container for a KES StatefulSet. +func KESServerContainer(mi *miniov1.MinIOInstance) corev1.Container { + + // Args to start KES with config mounted at miniov1.KESConfigMountPath and require but don't verify mTLS authentication + args := []string{"server", "--config=" + miniov1.KESConfigMountPath + "/server-config.yaml", "--auth=off"} + + return corev1.Container{ + Name: miniov1.KESContainerName, + Image: mi.Spec.KES.Image, + Ports: []corev1.ContainerPort{ + { + ContainerPort: miniov1.KESPort, + }, + }, + ImagePullPolicy: miniov1.DefaultImagePullPolicy, + VolumeMounts: KESVolumeMounts(mi), + Args: args, + Env: KESEnvironmentVars(mi), + } +} + +// NewForKES creates a new KES StatefulSet for the given Cluster. +func NewForKES(mi *miniov1.MinIOInstance, serviceName string) *appsv1.StatefulSet { + var replicas = mi.KESReplicas() + + var KEScertKeyPaths = []corev1.KeyToPath{ + {Key: "public.crt", Path: "server.crt"}, + {Key: "private.key", Path: "server.key"}, + } + + var configPath = []corev1.KeyToPath{ + {Key: "server-config.yaml", Path: "server-config.yaml"}, + } + + podVolumes := []corev1.Volume{ + { + Name: mi.KESVolMountName(), + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: mi.KESTLSSecretName(), + }, + Items: KEScertKeyPaths, + }, + }, + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: mi.Spec.KES.Configuration.Name, + }, + Items: configPath, + }, + }, + }, + }, + }, + }, + } + + containers := []corev1.Container{KESServerContainer(mi)} + + ss := &appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: mi.Namespace, + Name: mi.KESStatefulSetName(), + OwnerReferences: mi.OwnerRef(), + }, + Spec: appsv1.StatefulSetSpec{ + UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ + Type: miniov1.DefaultUpdateStrategy, + }, + PodManagementPolicy: mi.Spec.PodManagementPolicy, + Selector: mi.Spec.KES.Selector, + ServiceName: serviceName, + Replicas: &replicas, + Template: corev1.PodTemplateSpec{ + ObjectMeta: KESMetadata(mi), + Spec: corev1.PodSpec{ + Containers: containers, + Volumes: podVolumes, + ImagePullSecrets: []corev1.LocalObjectReference{mi.Spec.ImagePullSecret}, + RestartPolicy: corev1.RestartPolicyAlways, + SchedulerName: mi.Scheduler.Name, + }, + }, + }, + } + + return ss +} diff --git a/pkg/resources/statefulsets/statefulset.go b/pkg/resources/statefulsets/minio-statefulset.go similarity index 70% rename from pkg/resources/statefulsets/statefulset.go rename to pkg/resources/statefulsets/minio-statefulset.go index 777e10e5ada..3ea582f4dc1 100644 --- a/pkg/resources/statefulsets/statefulset.go +++ b/pkg/resources/statefulsets/minio-statefulset.go @@ -19,10 +19,10 @@ package statefulsets import ( "fmt" + "net" "strconv" - miniov1beta1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" - constants "github.com/minio/minio-operator/pkg/constants" + miniov1 "github.com/minio/minio-operator/pkg/apis/operator.min.io/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -32,7 +32,7 @@ import ( // Returns the MinIO environment variables set in configuration. // If a user specifies a secret in the spec (for MinIO credentials) we use // that to set MINIO_ACCESS_KEY & MINIO_SECRET_KEY. -func minioEnvironmentVars(mi *miniov1beta1.MinIOInstance) []corev1.EnvVar { +func minioEnvironmentVars(mi *miniov1.MinIOInstance) []corev1.EnvVar { envVars := make([]corev1.EnvVar, 0) // Add all the environment variables for _, e := range mi.Spec.Env { @@ -65,6 +65,25 @@ func minioEnvironmentVars(mi *miniov1beta1.MinIOInstance) []corev1.EnvVar { }, }) } + if mi.HasKESEnabled() { + envVars = append(envVars, corev1.EnvVar{ + Name: "MINIO_KMS_KES_ENDPOINT", + Value: "https://" + net.JoinHostPort(mi.KESServiceHost(), strconv.Itoa(miniov1.KESPort)), + }, corev1.EnvVar{ + Name: "MINIO_KMS_KES_CERT_FILE", + Value: "/root/.minio/certs/client.crt", + }, corev1.EnvVar{ + Name: "MINIO_KMS_KES_KEY_FILE", + Value: "/root/.minio/certs/client.key", + }, corev1.EnvVar{ + Name: "MINIO_KMS_KES_CA_PATH", + Value: "/root/.minio/certs/CAs/server.crt", + }, corev1.EnvVar{ + Name: "MINIO_KMS_KES_KEY_NAME", + Value: miniov1.KESMinIOKey, + }) + } + // Return environment variables return envVars } @@ -72,7 +91,7 @@ func minioEnvironmentVars(mi *miniov1beta1.MinIOInstance) []corev1.EnvVar { // Returns the MinIO pods metadata set in configuration. // If a user specifies metadata in the spec we return that // metadata. -func minioMetadata(mi *miniov1beta1.MinIOInstance) metav1.ObjectMeta { +func minioMetadata(mi *miniov1.MinIOInstance) metav1.ObjectMeta { meta := metav1.ObjectMeta{} if mi.HasMetadata() { meta = *mi.Spec.Metadata @@ -85,7 +104,7 @@ func minioMetadata(mi *miniov1beta1.MinIOInstance) metav1.ObjectMeta { meta.Annotations = make(map[string]string) } // Add the additional label used by StatefulSet spec - for k, v := range mi.PodLabels() { + for k, v := range mi.MinIOPodLabels() { meta.Labels[k] = v } // Add the Selector labels set by user @@ -98,12 +117,12 @@ func minioMetadata(mi *miniov1beta1.MinIOInstance) metav1.ObjectMeta { } // Builds the volume mounts for MinIO container. -func volumeMounts(mi *miniov1beta1.MinIOInstance) []corev1.VolumeMount { +func volumeMounts(mi *miniov1.MinIOInstance) []corev1.VolumeMount { var mounts []corev1.VolumeMount // This is the case where user didn't provide a zone and we deploy a EmptyDir based // single node single drive (FS) MinIO deployment - name := constants.MinIOVolumeName + name := miniov1.MinIOVolumeName if mi.Spec.VolumeClaimTemplate != nil { name = mi.Spec.VolumeClaimTemplate.Name } @@ -111,20 +130,20 @@ func volumeMounts(mi *miniov1beta1.MinIOInstance) []corev1.VolumeMount { if mi.Spec.VolumesPerServer == 1 { mounts = append(mounts, corev1.VolumeMount{ Name: name + strconv.Itoa(0), - MountPath: constants.MinIOVolumeMountPath, + MountPath: miniov1.MinIOVolumeMountPath, }) } else { for i := 0; i < mi.Spec.VolumesPerServer; i++ { mounts = append(mounts, corev1.VolumeMount{ Name: name + strconv.Itoa(i), - MountPath: constants.MinIOVolumeMountPath + strconv.Itoa(i), + MountPath: miniov1.MinIOVolumeMountPath + strconv.Itoa(i), }) } } if mi.RequiresAutoCertSetup() || mi.RequiresExternalCertSetup() { mounts = append(mounts, corev1.VolumeMount{ - Name: mi.GetTLSSecretName(), + Name: mi.MinIOTLSSecretName(), MountPath: "/root/.minio/certs", }) } @@ -133,34 +152,29 @@ func volumeMounts(mi *miniov1beta1.MinIOInstance) []corev1.VolumeMount { } // Builds the MinIO container for a MinIOInstance. -func minioServerContainer(mi *miniov1beta1.MinIOInstance, serviceName string) corev1.Container { - scheme := "http" - if mi.RequiresAutoCertSetup() || mi.RequiresExternalCertSetup() { - scheme = "https" - } - +func minioServerContainer(mi *miniov1.MinIOInstance, serviceName string) corev1.Container { args := []string{"server"} if mi.Spec.Zones[0].Servers == 1 { // to run in standalone mode we must pass the path - args = append(args, constants.MinIOVolumeMountPath) + args = append(args, miniov1.MinIOVolumeMountPath) } else { // append all the MinIOInstance replica URLs - hosts := mi.GetHosts() + hosts := mi.MinIOHosts() for _, h := range hosts { - args = append(args, fmt.Sprintf("%s://"+h+"%s", scheme, mi.GetVolumesPath())) + args = append(args, fmt.Sprintf("%s://"+h+"%s", miniov1.Scheme, mi.VolumePath())) } } return corev1.Container{ - Name: constants.MinIOServerName, + Name: miniov1.MinIOServerName, Image: mi.Spec.Image, Ports: []corev1.ContainerPort{ { - ContainerPort: constants.MinIOPort, + ContainerPort: miniov1.MinIOPort, }, }, - ImagePullPolicy: constants.DefaultImagePullPolicy, + ImagePullPolicy: miniov1.DefaultImagePullPolicy, VolumeMounts: volumeMounts(mi), Args: args, Env: minioEnvironmentVars(mi), @@ -171,7 +185,7 @@ func minioServerContainer(mi *miniov1beta1.MinIOInstance, serviceName string) co } // Builds the tolerations for a MinIOInstance. -func minioTolerations(mi *miniov1beta1.MinIOInstance) []corev1.Toleration { +func minioTolerations(mi *miniov1.MinIOInstance) []corev1.Toleration { tolerations := make([]corev1.Toleration, 0) // Add all the tolerations for _, t := range mi.Spec.Tolerations { @@ -182,7 +196,7 @@ func minioTolerations(mi *miniov1beta1.MinIOInstance) []corev1.Toleration { } // Builds the security contexts for a MinIOInstance -func minioSecurityContext(mi *miniov1beta1.MinIOInstance) *corev1.PodSecurityContext { +func minioSecurityContext(mi *miniov1.MinIOInstance) *corev1.PodSecurityContext { var securityContext = corev1.PodSecurityContext{} if mi.Spec.SecurityContext != nil { securityContext = *mi.Spec.SecurityContext @@ -190,7 +204,7 @@ func minioSecurityContext(mi *miniov1beta1.MinIOInstance) *corev1.PodSecurityCon return &securityContext } -func getVolumesForContainer(mi *miniov1beta1.MinIOInstance) []corev1.Volume { +func getVolumesForContainer(mi *miniov1.MinIOInstance) []corev1.Volume { var podVolumes = []corev1.Volume{} // This is the case where user didn't provide a volume claim template and we deploy a // EmptyDir based MinIO deployment @@ -203,13 +217,13 @@ func getVolumesForContainer(mi *miniov1beta1.MinIOInstance) []corev1.Volume { return podVolumes } -// NewForCluster creates a new StatefulSet for the given Cluster. -func NewForCluster(mi *miniov1beta1.MinIOInstance, serviceName string) *appsv1.StatefulSet { +// NewForMinIO creates a new StatefulSet for the given Cluster. +func NewForMinIO(mi *miniov1.MinIOInstance, serviceName string) *appsv1.StatefulSet { var secretName string // If a PV isn't specified just use a EmptyDir volume var podVolumes = getVolumesForContainer(mi) - var replicas = mi.GetReplicas() + var replicas = mi.MinIOReplicas() var keyPaths = []corev1.KeyToPath{ {Key: "public.crt", Path: "public.crt"}, @@ -217,8 +231,17 @@ func NewForCluster(mi *miniov1beta1.MinIOInstance, serviceName string) *appsv1.S {Key: "public.crt", Path: "CAs/public.crt"}, } + var MinIOCertKeyPaths = []corev1.KeyToPath{ + {Key: "public.crt", Path: "client.crt"}, + {Key: "private.key", Path: "client.key"}, + } + + var KESCertKeyPaths = []corev1.KeyToPath{ + {Key: "public.crt", Path: "CAs/server.crt"}, + } + if mi.RequiresAutoCertSetup() { - secretName = mi.GetTLSSecretName() + secretName = mi.MinIOTLSSecretName() } else if mi.RequiresExternalCertSetup() { secretName = mi.Spec.ExternalCertSecret.Name if mi.Spec.ExternalCertSecret.Type == "kubernetes.io/tls" { @@ -238,20 +261,41 @@ func NewForCluster(mi *miniov1beta1.MinIOInstance, serviceName string) *appsv1.S // Add SSL volume from SSL secret to the podVolumes if mi.RequiresAutoCertSetup() || mi.RequiresExternalCertSetup() { + sources := []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: secretName, + }, + Items: keyPaths, + }, + }, + } + if mi.HasKESEnabled() { + sources = append(sources, []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: mi.MinIOClientTLSSecretName(), + }, + Items: MinIOCertKeyPaths, + }, + }, + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: mi.KESTLSSecretName(), + }, + Items: KESCertKeyPaths, + }, + }, + }...) + } podVolumes = append(podVolumes, corev1.Volume{ - Name: mi.GetTLSSecretName(), + Name: mi.MinIOTLSSecretName(), VolumeSource: corev1.VolumeSource{ Projected: &corev1.ProjectedVolumeSource{ - Sources: []corev1.VolumeProjection{ - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: secretName, - }, - Items: keyPaths, - }, - }, - }, + Sources: sources, }, }, }) @@ -265,15 +309,15 @@ func NewForCluster(mi *miniov1beta1.MinIOInstance, serviceName string) *appsv1.S Name: mi.Name, OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(mi, schema.GroupVersionKind{ - Group: miniov1beta1.SchemeGroupVersion.Group, - Version: miniov1beta1.SchemeGroupVersion.Version, - Kind: constants.MinIOCRDResourceKind, + Group: miniov1.SchemeGroupVersion.Group, + Version: miniov1.SchemeGroupVersion.Version, + Kind: miniov1.MinIOCRDResourceKind, }), }, }, Spec: appsv1.StatefulSetSpec{ UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ - Type: constants.DefaultUpdateStrategy, + Type: miniov1.DefaultUpdateStrategy, }, PodManagementPolicy: mi.Spec.PodManagementPolicy, Selector: mi.Spec.Selector,