diff --git a/manifests/claudie/crd/claudie.io_inputmanifests.yaml b/manifests/claudie/crd/claudie.io_inputmanifests.yaml index cb88826db..d0057e3eb 100644 --- a/manifests/claudie/crd/claudie.io_inputmanifests.yaml +++ b/manifests/claudie/crd/claudie.io_inputmanifests.yaml @@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null name: inputmanifests.claudie.io spec: group: claudie.io @@ -22,25 +23,19 @@ spec: name: v1beta1 schema: openAPIV3Schema: - description: |- - InputManifest is a definition of the user's infrastructure. - It contains cloud provider specification, - nodepool specification, Kubernetes and loadbalancer clusters. + description: InputManifest is a definition of the user's infrastructure. It + contains cloud provider specification, nodepool specification, Kubernetes + and loadbalancer clusters. 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 + 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 + 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 @@ -86,11 +81,11 @@ spec: - control type: object version: - description: |- - Version should be defined in format vX.Y. In terms of supported versions of Kubernetes, - Claudie follows kubeone releases and their supported versions. - The current kubeone version used in Claudie is 1.5. - To see the list of supported versions, please refer to kubeone documentation. + description: Version should be defined in format vX.Y. In + terms of supported versions of Kubernetes, Claudie follows + kubeone releases and their supported versions. The current + kubeone version used in Claudie is 1.5. To see the list + of supported versions, please refer to kubeone documentation. https://docs.kubermatic.com/kubeone/v1.5/architecture/compatibility/supported-versions/#supported-kubernetes-versions type: string required: @@ -135,9 +130,10 @@ spec: description: Name of the loadbalancer. type: string pools: - description: |- - List of nodepool names this loadbalancer will use. Remember, that nodepools defined - in nodepools are only "blueprints". The actual nodepool will be created once referenced here. + description: List of nodepool names this loadbalancer will + use. Remember, that nodepools defined in nodepools are + only "blueprints". The actual nodepool will be created + once referenced here. items: type: string type: array @@ -198,22 +194,22 @@ spec: type: array type: object nodePools: - description: |- - NodePool is a map of dynamic nodepools and static nodepools which will be used to - form kubernetes or loadbalancer clusters. + description: NodePool is a map of dynamic nodepools and static nodepools + which will be used to form kubernetes or loadbalancer clusters. properties: dynamic: description: Dynamic nodepools define nodepools dynamically created by Claudie. items: - description: |- - DynamicNodePool List of dynamically to-be-created nodepools of not yet existing machines, used for Kubernetes or loadbalancer clusters. - These are only blueprints, and will only be created per reference in kubernetes or loadBalancer clusters. - - - E.g. if the nodepool isn't used, it won't even be created. Or if the same nodepool is used in two different clusters, - it will be created twice. In OOP analogy, a dynamic nodepool would be a class - that would get instantiated N >= 0 times depending on which clusters reference it. + description: "DynamicNodePool List of dynamically to-be-created + nodepools of not yet existing machines, used for Kubernetes + or loadbalancer clusters. These are only blueprints, and will + only be created per reference in kubernetes or loadBalancer + clusters. \n E.g. if the nodepool isn't used, it won't even + be created. Or if the same nodepool is used in two different + clusters, it will be created twice. In OOP analogy, a dynamic + nodepool would be a class that would get instantiated N >= + 0 times depending on which clusters reference it." properties: annotations: additionalProperties: @@ -285,37 +281,37 @@ spec: - region type: object serverType: - description: "\tType of the machines in the nodepool. Currently, - only AMD64 machines are supported." + description: Type of the machines in the nodepool. Currently, + only AMD64 machines are supported. type: string storageDiskSize: - description: |- - Size of the storage disk on the nodes in the nodepool in GB. The OS disk is created automatically - with predefined size of 100GB for kubernetes nodes and 50GB for Loadbalancer nodes. - The value must be either -1 (no disk is created), or >= 50. If no value is specified, 50 is used. + description: Size of the storage disk on the nodes in the + nodepool in GB. The OS disk is created automatically with + predefined size of 100GB for kubernetes nodes and 50GB + for Loadbalancer nodes. The value must be either -1 (no + disk is created), or >= 50. If no value is specified, + 50 is used. format: int32 type: integer taints: description: User defined taints for this nodepool. items: - description: |- - The node this Taint is attached to has the "effect" on - any pod that does not tolerate the Taint. + description: The node this Taint is attached to has the + "effect" on any pod that does not tolerate the Taint. properties: effect: - description: |- - Required. The effect of the taint on pods - that do not tolerate the taint. - Valid effects are NoSchedule, PreferNoSchedule and NoExecute. + description: Required. The effect of the taint on + pods that do not tolerate the taint. Valid effects + are NoSchedule, PreferNoSchedule and NoExecute. type: string key: description: Required. The taint key to be applied to a node. type: string timeAdded: - description: |- - TimeAdded represents the time at which the taint was added. - It is only written for NoExecute taints. + description: TimeAdded represents the time at which + the taint was added. It is only written for NoExecute + taints. format: date-time type: string value: @@ -388,24 +384,22 @@ spec: type: array taints: items: - description: |- - The node this Taint is attached to has the "effect" on - any pod that does not tolerate the Taint. + description: The node this Taint is attached to has the + "effect" on any pod that does not tolerate the Taint. properties: effect: - description: |- - Required. The effect of the taint on pods - that do not tolerate the taint. - Valid effects are NoSchedule, PreferNoSchedule and NoExecute. + description: Required. The effect of the taint on + pods that do not tolerate the taint. Valid effects + are NoSchedule, PreferNoSchedule and NoExecute. type: string key: description: Required. The taint key to be applied to a node. type: string timeAdded: - description: |- - TimeAdded represents the time at which the taint was added. - It is only written for NoExecute taints. + description: TimeAdded represents the time at which + the taint was added. It is only written for NoExecute + taints. format: date-time type: string value: @@ -424,12 +418,10 @@ spec: type: array type: object providers: - description: |- - Providers list of defined cloud provider configuration + description: Providers list of defined cloud provider configuration that will be used while infrastructure provisioning. items: - description: |- - Providers list of defined cloud provider configuration + description: Providers list of defined cloud provider configuration that will be used while infrastructure provisioning. properties: name: @@ -439,9 +431,8 @@ spec: minLength: 1 type: string providerType: - description: |- - ProviderType type of a provider. - A list of available providers can be found at https://docs.claudie.io/v0.3.2/input-manifest/providers/aws/ + description: ProviderType type of a provider. A list of available + providers can be found at https://docs.claudie.io/v0.3.2/input-manifest/providers/aws/ enum: - gcp - hetzner @@ -453,9 +444,8 @@ spec: - genesiscloud type: string secretRef: - description: |- - SecretReference represents a Secret Reference. It has enough information to retrieve secret - in any namespace + description: SecretReference represents a Secret Reference. + It has enough information to retrieve secret in any namespace properties: name: description: name is unique within a namespace to reference diff --git a/manifests/claudie/kustomization.yaml b/manifests/claudie/kustomization.yaml index b5e5967d9..28aef4f3c 100644 --- a/manifests/claudie/kustomization.yaml +++ b/manifests/claudie/kustomization.yaml @@ -64,7 +64,7 @@ images: - name: ghcr.io/berops/claudie/builder newTag: 1eac122-2739 - name: ghcr.io/berops/claudie/claudie-operator - newTag: 1eac122-2739 + newTag: 684a010-2740 - name: ghcr.io/berops/claudie/context-box newTag: 1eac122-2739 - name: ghcr.io/berops/claudie/kube-eleven diff --git a/services/claudie-operator/pkg/controller/validator.go b/services/claudie-operator/pkg/controller/validator.go index b519538fe..4d0c5bb2d 100644 --- a/services/claudie-operator/pkg/controller/validator.go +++ b/services/claudie-operator/pkg/controller/validator.go @@ -69,8 +69,13 @@ func (v *InputManifestValidator) ValidateDelete(ctx context.Context, obj runtime // It doesn't validate .spec.Providers field. func validateInputManifest(im *v1beta.InputManifest) error { var rawManifest manifest.Manifest + validateUniqueProviders := make(map[string]bool) // Fill providers only with names, to check if they are defined for _, p := range im.Spec.Providers { + if _, exists := validateUniqueProviders[p.ProviderName]; exists { + return fmt.Errorf("spec.providers.name has to be unique") + } + validateUniqueProviders[p.ProviderName] = true switch p.ProviderType { case v1beta.GCP: rawManifest.Providers.GCP = append(rawManifest.Providers.GCP, manifest.GCP{Name: p.ProviderName})