From 5a95fed35bee7f11160f56dff3ffe6afa73c9770 Mon Sep 17 00:00:00 2001 From: Cesar N Date: Wed, 19 Aug 2020 20:34:43 -0700 Subject: [PATCH] Add option to delete tenant's pvcs on tenant deletion (#251) --- k8s/console/base/kustomization.yaml | 2 +- k8s/console/base/minio-operator.yaml | 1852 ----------------- .../base/console-cluster-role.yaml | 6 + k8s/operator-console/base/kustomization.yaml | 2 +- k8s/operator-console/base/minio-operator.yaml | 1852 ----------------- models/delete_tenant_request.go | 60 + restapi/admin_tenants.go | 50 +- restapi/admin_tenants_test.go | 148 +- restapi/embedded_spec.go | 34 +- restapi/operations/admin_api/delete_tenant.go | 2 +- .../admin_api/delete_tenant_parameters.go | 23 + swagger.yml | 13 +- 12 files changed, 320 insertions(+), 3724 deletions(-) delete mode 100644 k8s/console/base/minio-operator.yaml delete mode 100644 k8s/operator-console/base/minio-operator.yaml create mode 100644 models/delete_tenant_request.go diff --git a/k8s/console/base/kustomization.yaml b/k8s/console/base/kustomization.yaml index 320c38eea..69cac85d8 100644 --- a/k8s/console/base/kustomization.yaml +++ b/k8s/console/base/kustomization.yaml @@ -8,4 +8,4 @@ resources: - console-configmap.yaml - console-service.yaml - console-deployment.yaml - - minio-operator.yaml + - https://github.com/minio/operator/?ref=v3.0.10 diff --git a/k8s/console/base/minio-operator.yaml b/k8s/console/base/minio-operator.yaml deleted file mode 100644 index e14ee6cb3..000000000 --- a/k8s/console/base/minio-operator.yaml +++ /dev/null @@ -1,1852 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: minio-operator ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: (devel) - creationTimestamp: null - name: tenants.minio.min.io -spec: - group: minio.min.io - names: - kind: Tenant - listKind: TenantList - plural: tenants - shortNames: - - tenant - singular: tenant - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - description: Tenant is a specification for a MinIO resource - properties: - apiVersion: - description: - "APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources" - type: string - kind: - description: - "Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" - type: string - metadata: - type: object - scheduler: - description: TenantScheduler is the spec for a Tenant scheduler - properties: - name: - description: - SchedulerName defines the name of scheduler to be used - to schedule Tenant pods - type: string - required: - - name - type: object - spec: - description: TenantSpec is the spec for a Tenant resource - properties: - certConfig: - description: - CertConfig allows users to set entries like CommonName, - Organization, etc for the certificate - properties: - commonName: - type: string - dnsNames: - items: - type: string - type: array - organizationName: - items: - type: string - type: array - type: object - console: - description: - ConsoleConfiguration is for setting up minio/console for - graphical user interface - properties: - consoleSecret: - description: - This secret provides all environment variables for - KES This is a mandatory field - properties: - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - type: object - env: - description: - If provided, use these environment variables for Console - resource - items: - description: - EnvVar represents an environment variable present - in a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: - 'Variable references $(VAR_NAME) are expanded - using the previous defined environment variables in the - container and any service environment variables. If a variable - cannot be resolved, the reference in the input string will - be unchanged. The $(VAR_NAME) syntax can be escaped with - a double $$, ie: $$(VAR_NAME). Escaped references will never - be expanded, regardless of whether the variable exists or - not. Defaults to "".' - type: string - valueFrom: - description: - Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?" - type: string - optional: - description: - Specify whether the ConfigMap or its - key must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: - "Selects a field of the pod: supports metadata.name, - metadata.namespace, metadata.labels, metadata.annotations, - spec.nodeName, spec.serviceAccountName, status.hostIP, - status.podIP, status.podIPs." - properties: - apiVersion: - description: - Version of the schema the FieldPath is - written in terms of, defaults to "v1". - type: string - fieldPath: - description: - Path of the field to select in the specified - API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: - "Selects a resource of the container: only - resources limits and requests (limits.cpu, limits.memory, - limits.ephemeral-storage, requests.cpu, requests.memory - and requests.ephemeral-storage) are currently supported." - properties: - containerName: - description: - "Container name: required for volumes, - optional for env vars" - type: string - divisor: - anyOf: - - type: integer - - type: string - description: - Specifies the output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: "Required: resource to select" - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: - The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?" - type: string - optional: - description: - Specify whether the Secret or its key - must be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - image: - description: Image defines the Tenant Console Docker image. - type: string - metadata: - type: object - replicas: - description: Replicas defines number of pods for KES StatefulSet. - format: int32 - type: integer - resources: - description: - If provided, use these requests and limit for cpu/memory - resource allocation - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - type: object - required: - - consoleSecret - type: object - credsSecret: - description: - If provided, use this secret as the credentials for Tenant - resource Otherwise MinIO server creates dynamic credentials printed - on MinIO server startup banner - properties: - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - type: object - env: - description: - If provided, use these environment variables for Tenant - resource - items: - description: - EnvVar represents an environment variable present in - a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: - 'Variable references $(VAR_NAME) are expanded using - the previous defined environment variables in the container - and any service environment variables. If a variable cannot - be resolved, the reference in the input string will be unchanged. - The $(VAR_NAME) syntax can be escaped with a double $$, ie: - $$(VAR_NAME). Escaped references will never be expanded, regardless - of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: - Source for the environment variable's value. Cannot - be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - optional: - description: - Specify whether the ConfigMap or its key - must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: - "Selects a field of the pod: supports metadata.name, - metadata.namespace, metadata.labels, metadata.annotations, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, - status.podIPs." - properties: - apiVersion: - description: - Version of the schema the FieldPath is written - in terms of, defaults to "v1". - type: string - fieldPath: - description: - Path of the field to select in the specified - API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: - "Selects a resource of the container: only resources - limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, - requests.cpu, requests.memory and requests.ephemeral-storage) - are currently supported." - properties: - containerName: - description: - "Container name: required for volumes, optional - for env vars" - type: string - divisor: - anyOf: - - type: integer - - type: string - description: - Specifies the output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: "Required: resource to select" - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: - The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - optional: - description: - Specify whether the Secret or its key must - be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - externalCertSecret: - description: - ExternalCertSecret allows a user to specify custom CA certificate, - and private key. This is used for enabling TLS support on MinIO Pods. - properties: - name: - type: string - type: - type: string - required: - - name - type: object - externalClientCertSecret: - description: - ExternalClientCertSecret allows a user to specify custom - CA client certificate, and private key. This is used for adding client - certificates on MinIO Pods --> used for KES authentication. - properties: - name: - type: string - type: - type: string - required: - - name - type: object - image: - description: Image defines the Tenant Docker image. - type: string - imagePullSecret: - description: - ImagePullSecret defines the secret to be used for pull - image from a private Docker image. - properties: - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - type: object - kes: - description: KES is for setting up minio/kes as MinIO KMS - properties: - externalCertSecret: - description: - ExternalCertSecret allows a user to specify custom - CA certificate, and private key for group replication TLS. - properties: - name: - type: string - type: - type: string - required: - - name - type: object - image: - description: Image defines the Tenant KES Docker image. - type: string - kesSecret: - description: - This kesSecret serves as the configuration for KES - This is a mandatory field - properties: - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - type: object - metadata: - type: object - replicas: - description: Replicas defines number of pods for KES StatefulSet. - format: int32 - type: integer - required: - - kesSecret - type: object - liveness: - description: - Liveness Probe for container liveness. Container will be - restarted if the probe fails. - properties: - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - timeoutSeconds: - format: int32 - type: integer - required: - - initialDelaySeconds - - periodSeconds - - timeoutSeconds - type: object - metadata: - description: - Metadata defines the object metadata passed to each pod - that is a part of this Tenant - type: object - mountPath: - description: Mount path for MinIO volume (PV). Defaults to /export - type: string - podManagementPolicy: - description: Pod Management Policy for pod created by StatefulSet - type: string - requestAutoCert: - description: - "RequestAutoCert allows user to enable Kubernetes based - TLS cert generation and signing as explained here: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/" - type: boolean - securityContext: - description: - Security Context allows user to set entries like runAsUser, - privilege escalation etc. - properties: - fsGroup: - description: - "A special supplemental group that applies to all containers - in a pod. Some volume types allow the Kubelet to change the ownership - of that volume to be owned by the pod: \n 1. The owning GID will - be the FSGroup 2. The setgid bit is set (new files created in - the volume will be owned by FSGroup) 3. The permission bits are - OR'd with rw-rw---- \n If unset, the Kubelet will not modify the - ownership and permissions of any volume." - format: int64 - type: integer - fsGroupChangePolicy: - description: - 'fsGroupChangePolicy defines behavior of changing ownership - and permission of the volume before being exposed inside Pod. - This field will only apply to volume types which support fsGroup - based ownership(and permissions). It will have no effect on ephemeral - volume types such as: secret, configmaps and emptydir. Valid values - are "OnRootMismatch" and "Always". If not specified defaults to - "Always".' - type: string - runAsGroup: - description: - The GID to run the entrypoint of the container process. - Uses runtime default if unset. May also be set in SecurityContext. If - set in both SecurityContext and PodSecurityContext, the value - specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - runAsNonRoot: - description: - Indicates that the container must run as a non-root - user. If true, the Kubelet will validate the image at runtime - to ensure that it does not run as UID 0 (root) and fail to start - the container if it does. If unset or false, no such validation - will be performed. May also be set in SecurityContext. If set - in both SecurityContext and PodSecurityContext, the value specified - in SecurityContext takes precedence. - type: boolean - runAsUser: - description: - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. May - also be set in SecurityContext. If set in both SecurityContext - and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - format: int64 - type: integer - seLinuxOptions: - description: - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux - context for each container. May also be set in SecurityContext. If - set in both SecurityContext and PodSecurityContext, the value - specified in SecurityContext takes precedence for that container. - properties: - level: - description: - Level is SELinux level label that applies to the - container. - type: string - role: - description: - Role is a SELinux role label that applies to the - container. - type: string - type: - description: - Type is a SELinux type label that applies to the - container. - type: string - user: - description: - User is a SELinux user label that applies to the - container. - type: string - type: object - supplementalGroups: - description: - A list of groups applied to the first process run in - each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. - items: - format: int64 - type: integer - type: array - sysctls: - description: - Sysctls hold a list of namespaced sysctls used for - the pod. Pods with unsupported sysctls (by the container runtime) - might fail to launch. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - description: - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext - will be used. If set in both SecurityContext and PodSecurityContext, - the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: - GMSACredentialSpec is where the GMSA admission - webhook (https://github.com/kubernetes-sigs/windows-gmsa) - inlines the contents of the GMSA credential spec named by - the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: - GMSACredentialSpecName is the name of the GMSA - credential spec to use. - type: string - runAsUserName: - description: - The UserName in Windows to run the entrypoint of - the container process. Defaults to the user specified in image - metadata if unspecified. May also be set in PodSecurityContext. - If set in both SecurityContext and PodSecurityContext, the - value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: - ServiceAccountName is the name of the ServiceAccount to - use to run pods of all MinIO Pods created as a part of this Tenant. - type: string - serviceName: - description: - ServiceName defines name of the Service that will be created - for this instance, if none is specified, it will default to the instance - name - type: string - subPath: - description: - Subpath inside mount path. This is the directory where - MinIO stores data. Default to "" (empty) - type: string - zones: - description: Definition for Cluster in given MinIO cluster - items: - description: Zone defines the spec for a MinIO Zone - properties: - affinity: - description: - If specified, affinity will define the pod's scheduling - constraints - properties: - nodeAffinity: - description: - Describes node affinity scheduling rules for - the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: - The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node matches the corresponding matchExpressions; - the node(s) with the highest sum are the most preferred. - items: - description: - An empty preferred scheduling term matches - all objects with implicit weight 0 (i.e. it's a no-op). - A null preferred scheduling term matches no objects - (i.e. is also a no-op). - properties: - preference: - description: - A node selector term, associated with - the corresponding weight. - properties: - matchExpressions: - description: - A list of node selector requirements - by node's labels. - items: - description: - A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - The label key that the selector - applies to. - type: string - operator: - description: - Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: - An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: - A list of node selector requirements - by node's fields. - items: - description: - A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - The label key that the selector - applies to. - type: string - operator: - description: - Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: - An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - description: - Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: - If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from - its node. - properties: - nodeSelectorTerms: - description: - Required. A list of node selector terms. - The terms are ORed. - items: - description: - A null or empty node selector term - matches no objects. The requirements of them are - ANDed. The TopologySelectorTerm type implements - a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: - A list of node selector requirements - by node's labels. - items: - description: - A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - The label key that the selector - applies to. - type: string - operator: - description: - Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: - An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: - A list of node selector requirements - by node's fields. - items: - description: - A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - The label key that the selector - applies to. - type: string - operator: - description: - Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: - An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - description: - Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: - The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: - The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: - Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: - A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: - matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: - A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: - key is the label key - that the selector applies to. - type: string - operator: - description: - operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: - values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - namespaces: - description: - namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: - This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: - weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: - If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to a pod label update), - the system may or may not try to eventually evict the - pod from its node. When there are multiple elements, - the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: - Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: - A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: - matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: - A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - key is the label key that - the selector applies to. - type: string - operator: - description: - operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: - values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - namespaces: - description: - namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: - This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: - Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: - The scheduler will prefer to schedule pods - to nodes that satisfy the anti-affinity expressions - specified by this field, but it may choose a node that - violates one or more of the expressions. The node that - is most preferred is the one with the greatest sum of - weights, i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - anti-affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: - The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: - Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: - A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: - matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: - A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: - key is the label key - that the selector applies to. - type: string - operator: - description: - operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: - values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - namespaces: - description: - namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: - This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: - weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: - If the anti-affinity requirements specified - by this field are not met at scheduling time, the pod - will not be scheduled onto the node. If the anti-affinity - requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod - label update), the system may or may not try to eventually - evict the pod from its node. When there are multiple - elements, the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: - Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: - A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: - matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: - A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - key is the label key that - the selector applies to. - type: string - operator: - description: - operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: - values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - namespaces: - description: - namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: - This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - name: - description: Name of the zone - type: string - nodeSelector: - additionalProperties: - type: string - description: - "NodeSelector is a selector which must be true for - the pod to fit on a node. Selector which must match a node's - labels for the pod to be scheduled on that node. More info: - https://kubernetes.io/docs/concepts/configuration/assign-pod-node/" - type: object - resources: - description: - If provided, use these requests and limit for cpu/memory - resource allocation - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - type: object - servers: - description: Number of Servers in the zone - format: int32 - type: integer - tolerations: - description: - Tolerations allows users to set entries like effect, - key, operator, value. - items: - description: - The pod this Toleration is attached to tolerates - any taint that matches the triple using - the matching operator . - properties: - effect: - description: - Effect indicates the taint effect to match. - Empty means match all taint effects. When specified, allowed - values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: - Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, - operator must be Exists; this combination means to match - all values and all keys. - type: string - operator: - description: - Operator represents a key's relationship to - the value. Valid operators are Exists and Equal. Defaults - to Equal. Exists is equivalent to wildcard for value, - so that a pod can tolerate all taints of a particular - category. - type: string - tolerationSeconds: - description: - TolerationSeconds represents the period of - time the toleration (which must be of effect NoExecute, - otherwise this field is ignored) tolerates the taint. - By default, it is not set, which means tolerate the taint - forever (do not evict). Zero and negative values will - be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: - Value is the taint value the toleration matches - to. If the operator is Exists, the value should be empty, - otherwise just a regular string. - type: string - type: object - type: array - volumeClaimTemplate: - description: - VolumeClaimTemplate allows a user to specify how - volumes inside a Tenant - properties: - apiVersion: - description: - "APIVersion defines the versioned schema of this - representation of an object. Servers should convert recognized - schemas to the latest internal value, and may reject unrecognized - values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources" - type: string - kind: - description: - "Kind is a string value representing the REST - resource this object represents. Servers may infer this - from the endpoint the client submits requests to. Cannot - be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" - type: string - metadata: - description: "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" - type: object - spec: - description: - "Spec defines the desired characteristics of - a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims" - properties: - accessModes: - description: - "AccessModes contains the desired access - modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1" - items: - type: string - type: array - dataSource: - description: - "This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot - - Beta) * An existing PVC (PersistentVolumeClaim) * - An existing custom resource/object that implements data - population (Alpha) In order to use VolumeSnapshot object - types, the appropriate feature gate must be enabled - (VolumeSnapshotDataSource or AnyVolumeDataSource) If - the provisioner or an external controller can support - the specified data source, it will create a new volume - based on the contents of the specified data source. - If the specified data source is not supported, the volume - will not be created and the failure will be reported - as an event. In the future, we plan to support more - data source types and the behavior of the provisioner - may change." - properties: - apiGroup: - description: - APIGroup is the group for the resource - being referenced. If APIGroup is not specified, - the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - resources: - description: - "Resources represents the minimum resources - the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources" - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Limits describes the maximum amount - of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Requests describes the minimum amount - of compute resources required. If Requests is omitted - for a container, it defaults to Limits if that is - explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - type: object - selector: - description: - A label query over volumes to consider for - binding. - properties: - matchExpressions: - description: - matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: - A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: - key is the label key that the selector - applies to. - type: string - operator: - description: - operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: - values is an array of string values. - If the operator is In or NotIn, the values - array must be non-empty. If the operator is - Exists or DoesNotExist, the values array must - be empty. This array is replaced during a - strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - type: object - storageClassName: - description: - "Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1" - type: string - volumeMode: - description: - volumeMode defines what type of volume is - required by the claim. Value of Filesystem is implied - when not included in claim spec. - type: string - volumeName: - description: - VolumeName is the binding reference to the - PersistentVolume backing this claim. - type: string - type: object - status: - description: - "Status represents the current information/status - of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims" - properties: - accessModes: - description: - "AccessModes contains the actual access modes - the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1" - items: - type: string - type: array - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - Represents the actual resources of the underlying - volume. - type: object - conditions: - description: - Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. - items: - description: - PersistentVolumeClaimCondition contails - details about state of pvc - properties: - lastProbeTime: - description: Last time we probed the condition. - format: date-time - type: string - lastTransitionTime: - description: - Last time the condition transitioned - from one status to another. - format: date-time - type: string - message: - description: - Human-readable message indicating details - about last transition. - type: string - reason: - description: - Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. - type: string - status: - type: string - type: - description: - PersistentVolumeClaimConditionType - is a valid value of PersistentVolumeClaimCondition.Type - type: string - required: - - status - - type - type: object - type: array - phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - type: object - type: object - volumesPerServer: - description: - Number of persistent volumes that will be attached - per server - format: int32 - type: integer - required: - - servers - - volumeClaimTemplate - - volumesPerServer - type: object - type: array - required: - - zones - type: object - status: - description: Status provides details of the state of the Tenant - properties: - availableReplicas: - format: int32 - type: integer - currentState: - type: string - required: - - availableReplicas - - currentState - type: object - required: - - spec - type: object - version: v1 - versions: - - name: v1 - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: minio-operator - namespace: minio-operator ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: minio-operator-role -rules: - - apiGroups: - - "" - resources: - - namespaces - - secrets - - pods - - services - - events - verbs: - - get - - watch - - create - - list - - delete - - apiGroups: - - apps - resources: - - statefulsets - - deployments - verbs: - - get - - create - - list - - patch - - watch - - update - - delete - - apiGroups: - - batch - resources: - - jobs - verbs: - - get - - create - - list - - patch - - watch - - update - - delete - - apiGroups: - - certificates.k8s.io - resources: - - certificatesigningrequests - - certificatesigningrequests/approval - - certificatesigningrequests/status - verbs: - - update - - create - - get - - delete - - apiGroups: - - certificates.k8s.io - resourceNames: - - kubernetes.io/legacy-unknown - resources: - - signers - verbs: - - approve - - sign - - apiGroups: - - minio.min.io - resources: - - "*" - verbs: - - "*" - - apiGroups: - - min.io - resources: - - "*" - verbs: - - "*" ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: minio-operator-binding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: minio-operator-role -subjects: - - kind: ServiceAccount - name: minio-operator - namespace: minio-operator ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: minio-operator - namespace: minio-operator -spec: - replicas: 1 - selector: - matchLabels: - name: minio-operator - template: - metadata: - labels: - name: minio-operator - spec: - containers: - - image: minio/k8s-operator:v3.0.5 - imagePullPolicy: IfNotPresent - name: minio-operator - securityContext: - readOnlyRootFilesystem: true - runAsNonRoot: true - runAsUser: 1000 - serviceAccountName: minio-operator diff --git a/k8s/operator-console/base/console-cluster-role.yaml b/k8s/operator-console/base/console-cluster-role.yaml index 8f4744b03..a17d594db 100644 --- a/k8s/operator-console/base/console-cluster-role.yaml +++ b/k8s/operator-console/base/console-cluster-role.yaml @@ -28,6 +28,12 @@ rules: - create - list - patch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - deletecollection - apiGroups: - "storage.k8s.io" resources: diff --git a/k8s/operator-console/base/kustomization.yaml b/k8s/operator-console/base/kustomization.yaml index 320c38eea..69cac85d8 100644 --- a/k8s/operator-console/base/kustomization.yaml +++ b/k8s/operator-console/base/kustomization.yaml @@ -8,4 +8,4 @@ resources: - console-configmap.yaml - console-service.yaml - console-deployment.yaml - - minio-operator.yaml + - https://github.com/minio/operator/?ref=v3.0.10 diff --git a/k8s/operator-console/base/minio-operator.yaml b/k8s/operator-console/base/minio-operator.yaml deleted file mode 100644 index 641e9a5b8..000000000 --- a/k8s/operator-console/base/minio-operator.yaml +++ /dev/null @@ -1,1852 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: minio-operator ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: (devel) - creationTimestamp: null - name: tenants.minio.min.io -spec: - group: minio.min.io - names: - kind: Tenant - listKind: TenantList - plural: tenants - shortNames: - - tenant - singular: tenant - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - description: Tenant is a specification for a MinIO resource - properties: - apiVersion: - description: - "APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources" - type: string - kind: - description: - "Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" - type: string - metadata: - type: object - scheduler: - description: TenantScheduler is the spec for a Tenant scheduler - properties: - name: - description: - SchedulerName defines the name of scheduler to be used - to schedule Tenant pods - type: string - required: - - name - type: object - spec: - description: TenantSpec is the spec for a Tenant resource - properties: - certConfig: - description: - CertConfig allows users to set entries like CommonName, - Organization, etc for the certificate - properties: - commonName: - type: string - dnsNames: - items: - type: string - type: array - organizationName: - items: - type: string - type: array - type: object - console: - description: - ConsoleConfiguration is for setting up minio/console for - graphical user interface - properties: - consoleSecret: - description: - This secret provides all environment variables for - KES This is a mandatory field - properties: - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - type: object - env: - description: - If provided, use these environment variables for Console - resource - items: - description: - EnvVar represents an environment variable present - in a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: - 'Variable references $(VAR_NAME) are expanded - using the previous defined environment variables in the - container and any service environment variables. If a variable - cannot be resolved, the reference in the input string will - be unchanged. The $(VAR_NAME) syntax can be escaped with - a double $$, ie: $$(VAR_NAME). Escaped references will never - be expanded, regardless of whether the variable exists or - not. Defaults to "".' - type: string - valueFrom: - description: - Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?" - type: string - optional: - description: - Specify whether the ConfigMap or its - key must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: - "Selects a field of the pod: supports metadata.name, - metadata.namespace, metadata.labels, metadata.annotations, - spec.nodeName, spec.serviceAccountName, status.hostIP, - status.podIP, status.podIPs." - properties: - apiVersion: - description: - Version of the schema the FieldPath is - written in terms of, defaults to "v1". - type: string - fieldPath: - description: - Path of the field to select in the specified - API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: - "Selects a resource of the container: only - resources limits and requests (limits.cpu, limits.memory, - limits.ephemeral-storage, requests.cpu, requests.memory - and requests.ephemeral-storage) are currently supported." - properties: - containerName: - description: - "Container name: required for volumes, - optional for env vars" - type: string - divisor: - anyOf: - - type: integer - - type: string - description: - Specifies the output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: "Required: resource to select" - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: - The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?" - type: string - optional: - description: - Specify whether the Secret or its key - must be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - image: - description: Image defines the Tenant Console Docker image. - type: string - metadata: - type: object - replicas: - description: Replicas defines number of pods for KES StatefulSet. - format: int32 - type: integer - resources: - description: - If provided, use these requests and limit for cpu/memory - resource allocation - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - type: object - required: - - consoleSecret - type: object - credsSecret: - description: - If provided, use this secret as the credentials for Tenant - resource Otherwise MinIO server creates dynamic credentials printed - on MinIO server startup banner - properties: - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - type: object - env: - description: - If provided, use these environment variables for Tenant - resource - items: - description: - EnvVar represents an environment variable present in - a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: - 'Variable references $(VAR_NAME) are expanded using - the previous defined environment variables in the container - and any service environment variables. If a variable cannot - be resolved, the reference in the input string will be unchanged. - The $(VAR_NAME) syntax can be escaped with a double $$, ie: - $$(VAR_NAME). Escaped references will never be expanded, regardless - of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: - Source for the environment variable's value. Cannot - be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - optional: - description: - Specify whether the ConfigMap or its key - must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: - "Selects a field of the pod: supports metadata.name, - metadata.namespace, metadata.labels, metadata.annotations, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, - status.podIPs." - properties: - apiVersion: - description: - Version of the schema the FieldPath is written - in terms of, defaults to "v1". - type: string - fieldPath: - description: - Path of the field to select in the specified - API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: - "Selects a resource of the container: only resources - limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, - requests.cpu, requests.memory and requests.ephemeral-storage) - are currently supported." - properties: - containerName: - description: - "Container name: required for volumes, optional - for env vars" - type: string - divisor: - anyOf: - - type: integer - - type: string - description: - Specifies the output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: "Required: resource to select" - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: - The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - optional: - description: - Specify whether the Secret or its key must - be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - externalCertSecret: - description: - ExternalCertSecret allows a user to specify custom CA certificate, - and private key. This is used for enabling TLS support on MinIO Pods. - properties: - name: - type: string - type: - type: string - required: - - name - type: object - externalClientCertSecret: - description: - ExternalClientCertSecret allows a user to specify custom - CA client certificate, and private key. This is used for adding client - certificates on MinIO Pods --> used for KES authentication. - properties: - name: - type: string - type: - type: string - required: - - name - type: object - image: - description: Image defines the Tenant Docker image. - type: string - imagePullSecret: - description: - ImagePullSecret defines the secret to be used for pull - image from a private Docker image. - properties: - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - type: object - kes: - description: KES is for setting up minio/kes as MinIO KMS - properties: - externalCertSecret: - description: - ExternalCertSecret allows a user to specify custom - CA certificate, and private key for group replication SSL. - properties: - name: - type: string - type: - type: string - required: - - name - type: object - image: - description: Image defines the Tenant KES Docker image. - type: string - kesSecret: - description: - This kesSecret serves as the configuration for KES - This is a mandatory field - properties: - name: - description: - "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?" - type: string - type: object - metadata: - type: object - replicas: - description: Replicas defines number of pods for KES StatefulSet. - format: int32 - type: integer - required: - - kesSecret - type: object - liveness: - description: - Liveness Probe for container liveness. Container will be - restarted if the probe fails. - properties: - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - timeoutSeconds: - format: int32 - type: integer - required: - - initialDelaySeconds - - periodSeconds - - timeoutSeconds - type: object - metadata: - description: - Metadata defines the object metadata passed to each pod - that is a part of this Tenant - type: object - mountPath: - description: Mount path for MinIO volume (PV). Defaults to /export - type: string - podManagementPolicy: - description: Pod Management Policy for pod created by StatefulSet - type: string - requestAutoCert: - description: - "RequestAutoCert allows user to enable Kubernetes based - TLS cert generation and signing as explained here: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/" - type: boolean - securityContext: - description: - Security Context allows user to set entries like runAsUser, - privilege escalation etc. - properties: - fsGroup: - description: - "A special supplemental group that applies to all containers - in a pod. Some volume types allow the Kubelet to change the ownership - of that volume to be owned by the pod: \n 1. The owning GID will - be the FSGroup 2. The setgid bit is set (new files created in - the volume will be owned by FSGroup) 3. The permission bits are - OR'd with rw-rw---- \n If unset, the Kubelet will not modify the - ownership and permissions of any volume." - format: int64 - type: integer - fsGroupChangePolicy: - description: - 'fsGroupChangePolicy defines behavior of changing ownership - and permission of the volume before being exposed inside Pod. - This field will only apply to volume types which support fsGroup - based ownership(and permissions). It will have no effect on ephemeral - volume types such as: secret, configmaps and emptydir. Valid values - are "OnRootMismatch" and "Always". If not specified defaults to - "Always".' - type: string - runAsGroup: - description: - The GID to run the entrypoint of the container process. - Uses runtime default if unset. May also be set in SecurityContext. If - set in both SecurityContext and PodSecurityContext, the value - specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - runAsNonRoot: - description: - Indicates that the container must run as a non-root - user. If true, the Kubelet will validate the image at runtime - to ensure that it does not run as UID 0 (root) and fail to start - the container if it does. If unset or false, no such validation - will be performed. May also be set in SecurityContext. If set - in both SecurityContext and PodSecurityContext, the value specified - in SecurityContext takes precedence. - type: boolean - runAsUser: - description: - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. May - also be set in SecurityContext. If set in both SecurityContext - and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - format: int64 - type: integer - seLinuxOptions: - description: - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux - context for each container. May also be set in SecurityContext. If - set in both SecurityContext and PodSecurityContext, the value - specified in SecurityContext takes precedence for that container. - properties: - level: - description: - Level is SELinux level label that applies to the - container. - type: string - role: - description: - Role is a SELinux role label that applies to the - container. - type: string - type: - description: - Type is a SELinux type label that applies to the - container. - type: string - user: - description: - User is a SELinux user label that applies to the - container. - type: string - type: object - supplementalGroups: - description: - A list of groups applied to the first process run in - each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. - items: - format: int64 - type: integer - type: array - sysctls: - description: - Sysctls hold a list of namespaced sysctls used for - the pod. Pods with unsupported sysctls (by the container runtime) - might fail to launch. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - description: - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext - will be used. If set in both SecurityContext and PodSecurityContext, - the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: - GMSACredentialSpec is where the GMSA admission - webhook (https://github.com/kubernetes-sigs/windows-gmsa) - inlines the contents of the GMSA credential spec named by - the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: - GMSACredentialSpecName is the name of the GMSA - credential spec to use. - type: string - runAsUserName: - description: - The UserName in Windows to run the entrypoint of - the container process. Defaults to the user specified in image - metadata if unspecified. May also be set in PodSecurityContext. - If set in both SecurityContext and PodSecurityContext, the - value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: - ServiceAccountName is the name of the ServiceAccount to - use to run pods of all MinIO Pods created as a part of this Tenant. - type: string - serviceName: - description: - ServiceName defines name of the Service that will be created - for this instance, if none is specified, it will default to the instance - name - type: string - subPath: - description: - Subpath inside mount path. This is the directory where - MinIO stores data. Default to "" (empty) - type: string - zones: - description: Definition for Cluster in given MinIO cluster - items: - description: Zone defines the spec for a MinIO Zone - properties: - affinity: - description: - If specified, affinity will define the pod's scheduling - constraints - properties: - nodeAffinity: - description: - Describes node affinity scheduling rules for - the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: - The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node matches the corresponding matchExpressions; - the node(s) with the highest sum are the most preferred. - items: - description: - An empty preferred scheduling term matches - all objects with implicit weight 0 (i.e. it's a no-op). - A null preferred scheduling term matches no objects - (i.e. is also a no-op). - properties: - preference: - description: - A node selector term, associated with - the corresponding weight. - properties: - matchExpressions: - description: - A list of node selector requirements - by node's labels. - items: - description: - A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - The label key that the selector - applies to. - type: string - operator: - description: - Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: - An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: - A list of node selector requirements - by node's fields. - items: - description: - A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - The label key that the selector - applies to. - type: string - operator: - description: - Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: - An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - description: - Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: - If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from - its node. - properties: - nodeSelectorTerms: - description: - Required. A list of node selector terms. - The terms are ORed. - items: - description: - A null or empty node selector term - matches no objects. The requirements of them are - ANDed. The TopologySelectorTerm type implements - a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: - A list of node selector requirements - by node's labels. - items: - description: - A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - The label key that the selector - applies to. - type: string - operator: - description: - Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: - An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: - A list of node selector requirements - by node's fields. - items: - description: - A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - The label key that the selector - applies to. - type: string - operator: - description: - Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: - An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - description: - Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: - The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: - The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: - Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: - A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: - matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: - A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: - key is the label key - that the selector applies to. - type: string - operator: - description: - operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: - values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - namespaces: - description: - namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: - This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: - weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: - If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to a pod label update), - the system may or may not try to eventually evict the - pod from its node. When there are multiple elements, - the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: - Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: - A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: - matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: - A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - key is the label key that - the selector applies to. - type: string - operator: - description: - operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: - values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - namespaces: - description: - namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: - This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: - Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: - The scheduler will prefer to schedule pods - to nodes that satisfy the anti-affinity expressions - specified by this field, but it may choose a node that - violates one or more of the expressions. The node that - is most preferred is the one with the greatest sum of - weights, i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - anti-affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: - The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: - Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: - A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: - matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: - A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: - key is the label key - that the selector applies to. - type: string - operator: - description: - operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: - values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - namespaces: - description: - namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: - This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: - weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: - If the anti-affinity requirements specified - by this field are not met at scheduling time, the pod - will not be scheduled onto the node. If the anti-affinity - requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod - label update), the system may or may not try to eventually - evict the pod from its node. When there are multiple - elements, the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: - Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: - A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: - matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: - A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: - key is the label key that - the selector applies to. - type: string - operator: - description: - operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: - values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - namespaces: - description: - namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: - This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - name: - description: Name of the zone - type: string - nodeSelector: - additionalProperties: - type: string - description: - "NodeSelector is a selector which must be true for - the pod to fit on a node. Selector which must match a node's - labels for the pod to be scheduled on that node. More info: - https://kubernetes.io/docs/concepts/configuration/assign-pod-node/" - type: object - resources: - description: - If provided, use these requests and limit for cpu/memory - resource allocation - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - type: object - servers: - description: Number of Servers in the zone - format: int32 - type: integer - tolerations: - description: - Tolerations allows users to set entries like effect, - key, operator, value. - items: - description: - The pod this Toleration is attached to tolerates - any taint that matches the triple using - the matching operator . - properties: - effect: - description: - Effect indicates the taint effect to match. - Empty means match all taint effects. When specified, allowed - values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: - Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, - operator must be Exists; this combination means to match - all values and all keys. - type: string - operator: - description: - Operator represents a key's relationship to - the value. Valid operators are Exists and Equal. Defaults - to Equal. Exists is equivalent to wildcard for value, - so that a pod can tolerate all taints of a particular - category. - type: string - tolerationSeconds: - description: - TolerationSeconds represents the period of - time the toleration (which must be of effect NoExecute, - otherwise this field is ignored) tolerates the taint. - By default, it is not set, which means tolerate the taint - forever (do not evict). Zero and negative values will - be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: - Value is the taint value the toleration matches - to. If the operator is Exists, the value should be empty, - otherwise just a regular string. - type: string - type: object - type: array - volumeClaimTemplate: - description: - VolumeClaimTemplate allows a user to specify how - volumes inside a Tenant - properties: - apiVersion: - description: - "APIVersion defines the versioned schema of this - representation of an object. Servers should convert recognized - schemas to the latest internal value, and may reject unrecognized - values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources" - type: string - kind: - description: - "Kind is a string value representing the REST - resource this object represents. Servers may infer this - from the endpoint the client submits requests to. Cannot - be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" - type: string - metadata: - description: "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" - type: object - spec: - description: - "Spec defines the desired characteristics of - a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims" - properties: - accessModes: - description: - "AccessModes contains the desired access - modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1" - items: - type: string - type: array - dataSource: - description: - "This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot - - Beta) * An existing PVC (PersistentVolumeClaim) * - An existing custom resource/object that implements data - population (Alpha) In order to use VolumeSnapshot object - types, the appropriate feature gate must be enabled - (VolumeSnapshotDataSource or AnyVolumeDataSource) If - the provisioner or an external controller can support - the specified data source, it will create a new volume - based on the contents of the specified data source. - If the specified data source is not supported, the volume - will not be created and the failure will be reported - as an event. In the future, we plan to support more - data source types and the behavior of the provisioner - may change." - properties: - apiGroup: - description: - APIGroup is the group for the resource - being referenced. If APIGroup is not specified, - the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - resources: - description: - "Resources represents the minimum resources - the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources" - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Limits describes the maximum amount - of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - "Requests describes the minimum amount - of compute resources required. If Requests is omitted - for a container, it defaults to Limits if that is - explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/" - type: object - type: object - selector: - description: - A label query over volumes to consider for - binding. - properties: - matchExpressions: - description: - matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: - A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: - key is the label key that the selector - applies to. - type: string - operator: - description: - operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: - values is an array of string values. - If the operator is In or NotIn, the values - array must be non-empty. If the operator is - Exists or DoesNotExist, the values array must - be empty. This array is replaced during a - strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: - matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - type: object - storageClassName: - description: - "Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1" - type: string - volumeMode: - description: - volumeMode defines what type of volume is - required by the claim. Value of Filesystem is implied - when not included in claim spec. - type: string - volumeName: - description: - VolumeName is the binding reference to the - PersistentVolume backing this claim. - type: string - type: object - status: - description: - "Status represents the current information/status - of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims" - properties: - accessModes: - description: - "AccessModes contains the actual access modes - the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1" - items: - type: string - type: array - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: - Represents the actual resources of the underlying - volume. - type: object - conditions: - description: - Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. - items: - description: - PersistentVolumeClaimCondition contails - details about state of pvc - properties: - lastProbeTime: - description: Last time we probed the condition. - format: date-time - type: string - lastTransitionTime: - description: - Last time the condition transitioned - from one status to another. - format: date-time - type: string - message: - description: - Human-readable message indicating details - about last transition. - type: string - reason: - description: - Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. - type: string - status: - type: string - type: - description: - PersistentVolumeClaimConditionType - is a valid value of PersistentVolumeClaimCondition.Type - type: string - required: - - status - - type - type: object - type: array - phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - type: object - type: object - volumesPerServer: - description: - Number of persistent volumes that will be attached - per server - format: int32 - type: integer - required: - - servers - - volumeClaimTemplate - - volumesPerServer - type: object - type: array - required: - - zones - type: object - status: - description: Status provides details of the state of the Tenant - properties: - availableReplicas: - format: int32 - type: integer - currentState: - type: string - required: - - availableReplicas - - currentState - type: object - required: - - spec - type: object - version: v1 - versions: - - name: v1 - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: minio-operator - namespace: minio-operator ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: minio-operator-role -rules: - - apiGroups: - - "" - resources: - - namespaces - - secrets - - pods - - services - - events - verbs: - - get - - watch - - create - - list - - delete - - apiGroups: - - apps - resources: - - statefulsets - - deployments - verbs: - - get - - create - - list - - patch - - watch - - update - - delete - - apiGroups: - - batch - resources: - - jobs - verbs: - - get - - create - - list - - patch - - watch - - update - - delete - - apiGroups: - - certificates.k8s.io - resources: - - certificatesigningrequests - - certificatesigningrequests/approval - - certificatesigningrequests/status - verbs: - - update - - create - - get - - delete - - apiGroups: - - certificates.k8s.io - resourceNames: - - kubernetes.io/legacy-unknown - resources: - - signers - verbs: - - approve - - sign - - apiGroups: - - minio.min.io - resources: - - "*" - verbs: - - "*" - - apiGroups: - - min.io - resources: - - "*" - verbs: - - "*" ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: minio-operator-binding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: minio-operator-role -subjects: - - kind: ServiceAccount - name: minio-operator - namespace: minio-operator ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: minio-operator - namespace: minio-operator -spec: - replicas: 1 - selector: - matchLabels: - name: minio-operator - template: - metadata: - labels: - name: minio-operator - spec: - containers: - - image: minio/k8s-operator:v3.0.5 - imagePullPolicy: IfNotPresent - name: minio-operator - securityContext: - readOnlyRootFilesystem: true - runAsNonRoot: true - runAsUser: 1000 - serviceAccountName: minio-operator diff --git a/models/delete_tenant_request.go b/models/delete_tenant_request.go new file mode 100644 index 000000000..457400e8e --- /dev/null +++ b/models/delete_tenant_request.go @@ -0,0 +1,60 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// 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 . +// + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// DeleteTenantRequest delete tenant request +// +// swagger:model deleteTenantRequest +type DeleteTenantRequest struct { + + // delete pvcs + DeletePvcs bool `json:"delete_pvcs,omitempty"` +} + +// Validate validates this delete tenant request +func (m *DeleteTenantRequest) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *DeleteTenantRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *DeleteTenantRequest) UnmarshalBinary(b []byte) error { + var res DeleteTenantRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/restapi/admin_tenants.go b/restapi/admin_tenants.go index 07321d9f9..047d402b1 100644 --- a/restapi/admin_tenants.go +++ b/restapi/admin_tenants.go @@ -110,7 +110,7 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { err := getDeleteTenantResponse(session, params) if err != nil { log.Println(err) - return admin_api.NewTenantInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String("Unable to delete tenant")}) + return admin_api.NewTenantInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())}) } return admin_api.NewTenantInfoOK() @@ -145,25 +145,53 @@ func registerTenantHandlers(api *operations.ConsoleAPI) { }) } -// deleteTenantAction performs the actions of deleting a tenant -func deleteTenantAction(ctx context.Context, operatorClient OperatorClient, nameSpace, instanceName string) error { - err := operatorClient.TenantDelete(ctx, nameSpace, instanceName, metav1.DeleteOptions{}) - if err != nil { - return err - } - return nil -} - // getDeleteTenantResponse gets the output of deleting a minio instance func getDeleteTenantResponse(session *models.Principal, params admin_api.DeleteTenantParams) error { opClientClientSet, err := cluster.OperatorClient(session.SessionToken) if err != nil { return err } + // get Kubernetes Client + clientset, err := cluster.K8sClient(session.SessionToken) + if err != nil { + return err + } opClient := &operatorClient{ client: opClientClientSet, } - return deleteTenantAction(context.Background(), opClient, params.Namespace, params.Tenant) + deleteTenantPVCs := false + if params.Body != nil { + deleteTenantPVCs = params.Body.DeletePvcs + } + return deleteTenantAction(context.Background(), opClient, clientset.CoreV1(), params.Namespace, params.Tenant, deleteTenantPVCs) +} + +// deleteTenantAction performs the actions of deleting a tenant +// +// It also adds the option of deleting the tenant's underlying pvcs if deletePvcs set +func deleteTenantAction( + ctx context.Context, + operatorClient OperatorClient, + clientset v1.CoreV1Interface, + namespace, tenantName string, + deletePvcs bool) error { + + err := operatorClient.TenantDelete(ctx, namespace, tenantName, metav1.DeleteOptions{}) + if err != nil { + // try to delete pvc even if the tenant doesn't exist anymore but only if deletePvcs is set to true, + // else, we return the error + if (deletePvcs && !k8sErrors.IsNotFound(err)) || !deletePvcs { + return err + } + } + + if deletePvcs { + opts := metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", operator.TenantLabel, tenantName), + } + return clientset.PersistentVolumeClaims(namespace).DeleteCollection(ctx, metav1.DeleteOptions{}, opts) + } + return nil } func getTenantScheme(mi *operator.Tenant) string { diff --git a/restapi/admin_tenants_test.go b/restapi/admin_tenants_test.go index 7e4043972..40731ca9d 100644 --- a/restapi/admin_tenants_test.go +++ b/restapi/admin_tenants_test.go @@ -33,9 +33,11 @@ import ( operator "github.com/minio/operator/pkg/apis/minio.min.io/v1" v1 "github.com/minio/operator/pkg/apis/minio.min.io/v1" corev1 "k8s.io/api/core/v1" + k8sErrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" types "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/fake" ) @@ -335,12 +337,13 @@ func Test_TenantInfo(t *testing.T) { func Test_deleteTenantAction(t *testing.T) { opClient := opClientMock{} - type args struct { ctx context.Context operatorClient OperatorClient nameSpace string tenantName string + deletePvcs bool + objs []runtime.Object mockTenantDelete func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error } tests := []struct { @@ -355,6 +358,7 @@ func Test_deleteTenantAction(t *testing.T) { operatorClient: opClient, nameSpace: "default", tenantName: "minio-tenant", + deletePvcs: false, mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error { return nil }, @@ -368,17 +372,155 @@ func Test_deleteTenantAction(t *testing.T) { operatorClient: opClient, nameSpace: "default", tenantName: "minio-tenant", + deletePvcs: false, mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error { return errors.New("something happened") }, }, wantErr: true, }, + { + // Delete only PVCs of the defined tenant on the specific namespace + name: "Delete PVCs on Tenant Deletion", + args: args{ + ctx: context.Background(), + operatorClient: opClient, + nameSpace: "minio-tenant", + tenantName: "tenant1", + deletePvcs: true, + objs: []runtime.Object{ + &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "PVC1", + Namespace: "minio-tenant", + Labels: map[string]string{ + operator.TenantLabel: "tenant1", + operator.ZoneLabel: "zone-1", + }, + }, + }, + }, + mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error { + return nil + }, + }, + wantErr: false, + }, + { + // Do not delete underlying pvcs + name: "Don't Delete PVCs on Tenant Deletion", + args: args{ + ctx: context.Background(), + operatorClient: opClient, + nameSpace: "minio-tenant", + tenantName: "tenant1", + deletePvcs: false, + objs: []runtime.Object{ + &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "PVC1", + Namespace: "minio-tenant", + Labels: map[string]string{ + operator.TenantLabel: "tenant1", + operator.ZoneLabel: "zone-1", + }, + }, + }, + }, + mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error { + return nil + }, + }, + wantErr: false, + }, + { + // If error is different than NotFound, PVC deletion should not continue + name: "Don't delete pvcs if error Deleting Tenant, return", + args: args{ + ctx: context.Background(), + operatorClient: opClient, + nameSpace: "minio-tenant", + tenantName: "tenant1", + deletePvcs: true, + objs: []runtime.Object{ + &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "PVC1", + Namespace: "minio-tenant", + Labels: map[string]string{ + operator.TenantLabel: "tenant1", + operator.ZoneLabel: "zone-1", + }, + }, + }, + }, + mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error { + return errors.New("error returned") + }, + }, + wantErr: true, + }, + { + // If error is NotFound while trying to Delete Tenant, PVC deletion should continue + name: "Delete pvcs if tenant not found", + args: args{ + ctx: context.Background(), + operatorClient: opClient, + nameSpace: "minio-tenant", + tenantName: "tenant1", + deletePvcs: true, + objs: []runtime.Object{ + &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "PVC1", + Namespace: "minio-tenant", + Labels: map[string]string{ + operator.TenantLabel: "tenant1", + operator.ZoneLabel: "zone-1", + }, + }, + }, + }, + mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error { + return k8sErrors.NewNotFound(schema.GroupResource{}, "tenant1") + }, + }, + wantErr: false, + }, + { + // If error is NotFound while trying to Delete Tenant and pvcdeletion=false, + // error should be returned + name: "Don't delete pvcs and return error if tenant not found", + args: args{ + ctx: context.Background(), + operatorClient: opClient, + nameSpace: "minio-tenant", + tenantName: "tenant1", + deletePvcs: false, + objs: []runtime.Object{ + &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "PVC1", + Namespace: "minio-tenant", + Labels: map[string]string{ + operator.TenantLabel: "tenant1", + operator.ZoneLabel: "zone-1", + }, + }, + }, + }, + mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error { + return k8sErrors.NewNotFound(schema.GroupResource{}, "tenant1") + }, + }, + wantErr: true, + }, } for _, tt := range tests { opClientTenantDeleteMock = tt.args.mockTenantDelete + kubeClient := fake.NewSimpleClientset(tt.args.objs...) t.Run(tt.name, func(t *testing.T) { - if err := deleteTenantAction(tt.args.ctx, tt.args.operatorClient, tt.args.nameSpace, tt.args.tenantName); (err != nil) != tt.wantErr { + if err := deleteTenantAction(tt.args.ctx, tt.args.operatorClient, kubeClient.CoreV1(), tt.args.nameSpace, tt.args.tenantName, tt.args.deletePvcs); (err != nil) != tt.wantErr { t.Errorf("deleteTenantAction() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -768,7 +910,7 @@ func Test_UpdateTenantAction(t *testing.T) { cnsClient := fake.NewSimpleClientset(tt.objs...) t.Run(tt.name, func(t *testing.T) { if err := updateTenantAction(tt.args.ctx, tt.args.operatorClient, cnsClient.CoreV1(), tt.args.httpCl, tt.args.nameSpace, tt.args.params); (err != nil) != tt.wantErr { - t.Errorf("deleteTenantAction() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("updateTenantAction() error = %v, wantErr %v", err, tt.wantErr) } }) } diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 64f6aa45e..7ae0c242f 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -1007,7 +1007,7 @@ func init() { "tags": [ "AdminAPI" ], - "summary": "Delete Tenant", + "summary": "Delete tenant and underlying pvcs", "operationId": "DeleteTenant", "parameters": [ { @@ -1021,6 +1021,13 @@ func init() { "name": "tenant", "in": "path", "required": true + }, + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/deleteTenantRequest" + } } ], "responses": { @@ -2105,6 +2112,14 @@ func init() { } } }, + "deleteTenantRequest": { + "type": "object", + "properties": { + "delete_pvcs": { + "type": "boolean" + } + } + }, "encryptionConfiguration": { "type": "object", "properties": { @@ -4423,7 +4438,7 @@ func init() { "tags": [ "AdminAPI" ], - "summary": "Delete Tenant", + "summary": "Delete tenant and underlying pvcs", "operationId": "DeleteTenant", "parameters": [ { @@ -4437,6 +4452,13 @@ func init() { "name": "tenant", "in": "path", "required": true + }, + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/deleteTenantRequest" + } } ], "responses": { @@ -6032,6 +6054,14 @@ func init() { } } }, + "deleteTenantRequest": { + "type": "object", + "properties": { + "delete_pvcs": { + "type": "boolean" + } + } + }, "encryptionConfiguration": { "type": "object", "properties": { diff --git a/restapi/operations/admin_api/delete_tenant.go b/restapi/operations/admin_api/delete_tenant.go index af352ae05..d292271b0 100644 --- a/restapi/operations/admin_api/delete_tenant.go +++ b/restapi/operations/admin_api/delete_tenant.go @@ -50,7 +50,7 @@ func NewDeleteTenant(ctx *middleware.Context, handler DeleteTenantHandler) *Dele /*DeleteTenant swagger:route DELETE /namespaces/{namespace}/tenants/{tenant} AdminAPI deleteTenant -Delete Tenant +Delete tenant and underlying pvcs */ type DeleteTenant struct { diff --git a/restapi/operations/admin_api/delete_tenant_parameters.go b/restapi/operations/admin_api/delete_tenant_parameters.go index 9d57048a7..f675f8e61 100644 --- a/restapi/operations/admin_api/delete_tenant_parameters.go +++ b/restapi/operations/admin_api/delete_tenant_parameters.go @@ -26,8 +26,11 @@ import ( "net/http" "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/strfmt" + + "github.com/minio/console/models" ) // NewDeleteTenantParams creates a new DeleteTenantParams object @@ -46,6 +49,10 @@ type DeleteTenantParams struct { // HTTP Request Object HTTPRequest *http.Request `json:"-"` + /* + In: body + */ + Body *models.DeleteTenantRequest /* Required: true In: path @@ -67,6 +74,22 @@ func (o *DeleteTenantParams) BindRequest(r *http.Request, route *middleware.Matc o.HTTPRequest = r + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.DeleteTenantRequest + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("body", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Body = &body + } + } + } rNamespace, rhkNamespace, _ := route.Params.GetOK("namespace") if err := o.bindNamespace(rNamespace, rhkNamespace, route.Formats); err != nil { res = append(res, err) diff --git a/swagger.yml b/swagger.yml index 251ccb9a0..b5e41cbfa 100644 --- a/swagger.yml +++ b/swagger.yml @@ -1069,7 +1069,7 @@ paths: tags: - AdminAPI delete: - summary: Delete Tenant + summary: Delete tenant and underlying pvcs operationId: DeleteTenant parameters: - name: namespace @@ -1080,6 +1080,11 @@ paths: in: path required: true type: string + - name: body + in: body + required: false + schema: + $ref: "#/definitions/deleteTenantRequest" responses: 204: description: A successful response. @@ -2516,3 +2521,9 @@ definitions: used: type: integer format: int64 + + deleteTenantRequest: + type: object + properties: + delete_pvcs: + type: boolean