From a23258f9d7e4cca91c560663ad9b64e049c1efa2 Mon Sep 17 00:00:00 2001 From: alexander-demicev Date: Fri, 25 Aug 2023 15:25:44 +0200 Subject: [PATCH 1/5] Add addon provider to API --- api/v1alpha2/addonprovider_types.go | 59 + api/v1alpha2/zz_generated.deepcopy.go | 91 + ...rator.cluster.x-k8s.io_addonproviders.yaml | 1539 +++++++++++++++++ config/crd/kustomization.yaml | 3 + .../cainjection_in_addonproviders.yaml | 8 + .../patches/webhook_in_addonproviders.yaml | 19 + config/webhook/manifests.yaml | 44 + internal/webhook/addonprovier_webhook.go | 75 + 8 files changed, 1838 insertions(+) create mode 100644 api/v1alpha2/addonprovider_types.go create mode 100644 config/crd/bases/operator.cluster.x-k8s.io_addonproviders.yaml create mode 100644 config/crd/patches/cainjection_in_addonproviders.yaml create mode 100644 config/crd/patches/webhook_in_addonproviders.yaml create mode 100644 internal/webhook/addonprovier_webhook.go diff --git a/api/v1alpha2/addonprovider_types.go b/api/v1alpha2/addonprovider_types.go new file mode 100644 index 000000000..9130b90e2 --- /dev/null +++ b/api/v1alpha2/addonprovider_types.go @@ -0,0 +1,59 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// AddonProviderSpec defines the desired state of AddonProvider. +type AddonProviderSpec struct { + ProviderSpec `json:",inline"` +} + +// AddonProviderStatus defines the observed state of AddonProvider. +type AddonProviderStatus struct { + ProviderStatus `json:",inline"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="InstalledVersion",type="string",JSONPath=".status.installedVersion" +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +// +kubebuilder:storageversion + +// AddonProvider is the Schema for the addonproviders API. +type AddonProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec AddonProviderSpec `json:"spec,omitempty"` + Status AddonProviderStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// AddonProviderList contains a list of AddonProvider. +type AddonProviderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []AddonProvider `json:"items"` +} + +func init() { + SchemeBuilder.Register(&AddonProvider{}, &AddonProviderList{}) +} diff --git a/api/v1alpha2/zz_generated.deepcopy.go b/api/v1alpha2/zz_generated.deepcopy.go index b43394e38..9e0681a02 100644 --- a/api/v1alpha2/zz_generated.deepcopy.go +++ b/api/v1alpha2/zz_generated.deepcopy.go @@ -30,6 +30,97 @@ import ( timex "time" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddonProvider) DeepCopyInto(out *AddonProvider) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonProvider. +func (in *AddonProvider) DeepCopy() *AddonProvider { + if in == nil { + return nil + } + out := new(AddonProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddonProvider) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddonProviderList) DeepCopyInto(out *AddonProviderList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AddonProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonProviderList. +func (in *AddonProviderList) DeepCopy() *AddonProviderList { + if in == nil { + return nil + } + out := new(AddonProviderList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddonProviderList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddonProviderSpec) DeepCopyInto(out *AddonProviderSpec) { + *out = *in + in.ProviderSpec.DeepCopyInto(&out.ProviderSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonProviderSpec. +func (in *AddonProviderSpec) DeepCopy() *AddonProviderSpec { + if in == nil { + return nil + } + out := new(AddonProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddonProviderStatus) DeepCopyInto(out *AddonProviderStatus) { + *out = *in + in.ProviderStatus.DeepCopyInto(&out.ProviderStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonProviderStatus. +func (in *AddonProviderStatus) DeepCopy() *AddonProviderStatus { + if in == nil { + return nil + } + out := new(AddonProviderStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BootstrapProvider) DeepCopyInto(out *BootstrapProvider) { *out = *in diff --git a/config/crd/bases/operator.cluster.x-k8s.io_addonproviders.yaml b/config/crd/bases/operator.cluster.x-k8s.io_addonproviders.yaml new file mode 100644 index 000000000..2b1cb8509 --- /dev/null +++ b/config/crd/bases/operator.cluster.x-k8s.io_addonproviders.yaml @@ -0,0 +1,1539 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.4 + name: addonproviders.operator.cluster.x-k8s.io +spec: + group: operator.cluster.x-k8s.io + names: + kind: AddonProvider + listKind: AddonProviderList + plural: addonproviders + singular: addonprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: AddonProvider is the Schema for the addonproviders API. + 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 + spec: + description: AddonProviderSpec defines the desired state of AddonProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + configSecret: + description: ConfigSecret is the object with name and namespace of + the Secret providing the configuration variables for the current + provider instance, like e.g. credentials. Such configurations will + be used when creating or upgrading provider components. The contents + of the secret will be treated as immutable. If changes need to be + made, a new object can be created and the name should be updated. + The contents should be in the form of key:value. This secret must + be in the same namespace as the provider. + properties: + name: + description: Name defines the name of the secret. + type: string + namespace: + description: Namespace defines the namespace of the secret. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector 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 + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector 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 + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector 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 + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector 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 + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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 previously 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. + Double $$ are reduced to a single $, which allows + for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" + will produce the string literal "$(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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + imageUrl: + description: Container Image URL + type: string + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n This field + is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in + PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where + this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + 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-resources-containers/' + 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. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + 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 + x-kubernetes-map-type: atomic + type: array + 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 + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + x-kubernetes-map-type: atomic + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains thw controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: AddonProviderStatus defines the observed state of AddonProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index a024e4822..fa4df33c9 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -6,6 +6,7 @@ resources: - bases/operator.cluster.x-k8s.io_bootstrapproviders.yaml - bases/operator.cluster.x-k8s.io_controlplaneproviders.yaml - bases/operator.cluster.x-k8s.io_infrastructureproviders.yaml +- bases/operator.cluster.x-k8s.io_addonproviders.yaml # +kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -15,6 +16,7 @@ patchesStrategicMerge: - patches/webhook_in_bootstrapproviders.yaml - patches/webhook_in_controlplaneproviders.yaml - patches/webhook_in_infrastructureproviders.yaml +- patches/webhook_in_addonproviders.yaml # +kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. @@ -23,6 +25,7 @@ patchesStrategicMerge: - patches/cainjection_in_bootstrapproviders.yaml - patches/cainjection_in_controlplaneproviders.yaml - patches/cainjection_in_infrastructureproviders.yaml +- patches/cainjection_in_addonproviders.yaml # +kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_addonproviders.yaml b/config/crd/patches/cainjection_in_addonproviders.yaml new file mode 100644 index 000000000..4c67ab630 --- /dev/null +++ b/config/crd/patches/cainjection_in_addonproviders.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: addonproviders.operator.cluster.x-k8s.io diff --git a/config/crd/patches/webhook_in_addonproviders.yaml b/config/crd/patches/webhook_in_addonproviders.yaml new file mode 100644 index 000000000..841af444c --- /dev/null +++ b/config/crd/patches/webhook_in_addonproviders.yaml @@ -0,0 +1,19 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: addonproviders.operator.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: [ "v1", "v1alpha1" ] + clientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 0cfcccbb6..8f8624d43 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -4,6 +4,28 @@ kind: MutatingWebhookConfiguration metadata: name: mutating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-operator-cluster-x-k8s-io-v1alpha2-addonprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vaddonprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - addonproviders + sideEffects: None - admissionReviewVersions: - v1 - v1beta1 @@ -98,6 +120,28 @@ kind: ValidatingWebhookConfiguration metadata: name: validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-operator-cluster-x-k8s-io-v1alpha2-addonprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vaddonprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - addonproviders + sideEffects: None - admissionReviewVersions: - v1 - v1beta1 diff --git a/internal/webhook/addonprovier_webhook.go b/internal/webhook/addonprovier_webhook.go new file mode 100644 index 000000000..eecb35553 --- /dev/null +++ b/internal/webhook/addonprovier_webhook.go @@ -0,0 +1,75 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package webhook + +import ( + "context" + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha2" +) + +type AddonProviderWebhook struct{} + +func (r *AddonProviderWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&operatorv1.AddonProvider{}). + WithValidator(r). + WithDefaulter(r). + Complete() +} + +//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha2-addonprovider,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=operator.cluster.x-k8s.io,resources=addonproviders,versions=v1alpha2,name=vaddonprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 +//+kubebuilder:webhook:verbs=create;update,path=/mutate-operator-cluster-x-k8s-io-v1alpha2-addonprovider,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,matchPolicy=Equivalent,groups=operator.cluster.x-k8s.io,resources=addonproviders,versions=v1alpha2,name=vaddonprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 + +var ( + _ webhook.CustomValidator = &AddonProviderWebhook{} + _ webhook.CustomDefaulter = &AddonProviderWebhook{} +) + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type. +func (r *AddonProviderWebhook) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. +func (r *AddonProviderWebhook) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type. +func (r *AddonProviderWebhook) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +// Default implements webhook.Default so a webhook will be registered for the type. +func (r *AddonProviderWebhook) Default(ctx context.Context, obj runtime.Object) error { + addonProvider, ok := obj.(*operatorv1.AddonProvider) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected a AddonProvider but got a %T", obj)) + } + + setDefaultProviderSpec(&addonProvider.Spec.ProviderSpec, addonProvider.Namespace) + + return nil +} From d22b5edafeca9826816d6860c04bf4400375266e Mon Sep 17 00:00:00 2001 From: alexander-demicev Date: Fri, 25 Aug 2023 15:26:03 +0200 Subject: [PATCH 2/5] Implement reconciliation of addon provider --- cmd/main.go | 15 ++++ .../genericprovider/addonprovider_wrapper.go | 77 +++++++++++++++++++ .../controller/genericprovider_controller.go | 4 + internal/controller/phases.go | 2 + util/util.go | 2 + 5 files changed, 100 insertions(+) create mode 100644 internal/controller/genericprovider/addonprovider_wrapper.go diff --git a/cmd/main.go b/cmd/main.go index dd3296a9e..2ee9e1d1b 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -223,6 +223,16 @@ func setupReconcilers(mgr ctrl.Manager) { setupLog.Error(err, "unable to create controller", "controller", "ControlPlaneProvider") os.Exit(1) } + + if err := (&providercontroller.GenericProviderReconciler{ + Provider: &operatorv1.AddonProvider{}, + ProviderList: &operatorv1.AddonProviderList{}, + Client: mgr.GetClient(), + Config: mgr.GetConfig(), + }).SetupWithManager(mgr, concurrency(concurrencyNumber)); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "AddonProvider") + os.Exit(1) + } } func setupWebhooks(mgr ctrl.Manager) { @@ -245,6 +255,11 @@ func setupWebhooks(mgr ctrl.Manager) { setupLog.Error(err, "unable to create webhook", "webhook", "InfrastructureProvider") os.Exit(1) } + + if err := (&webhook.AddonProviderWebhook{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "AddonProvider") + os.Exit(1) + } } func concurrency(c int) controller.Options { diff --git a/internal/controller/genericprovider/addonprovider_wrapper.go b/internal/controller/genericprovider/addonprovider_wrapper.go new file mode 100644 index 000000000..f99b155c1 --- /dev/null +++ b/internal/controller/genericprovider/addonprovider_wrapper.go @@ -0,0 +1,77 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericprovider + +import ( + operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha2" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type AddonProviderWrapper struct { + *operatorv1.AddonProvider +} + +func (b *AddonProviderWrapper) GetConditions() clusterv1.Conditions { + return b.Status.Conditions +} + +func (b *AddonProviderWrapper) SetConditions(conditions clusterv1.Conditions) { + b.Status.Conditions = conditions +} + +func (b *AddonProviderWrapper) GetSpec() operatorv1.ProviderSpec { + return b.Spec.ProviderSpec +} + +func (b *AddonProviderWrapper) SetSpec(in operatorv1.ProviderSpec) { + b.Spec.ProviderSpec = in +} + +func (b *AddonProviderWrapper) GetStatus() operatorv1.ProviderStatus { + return b.Status.ProviderStatus +} + +func (b *AddonProviderWrapper) SetStatus(in operatorv1.ProviderStatus) { + b.Status.ProviderStatus = in +} + +func (b *AddonProviderWrapper) GetObject() client.Object { + return b.AddonProvider +} + +func (b *AddonProviderWrapper) GetType() string { + return "addon" +} + +type AddonProviderListWrapper struct { + *operatorv1.AddonProviderList +} + +func (b *AddonProviderListWrapper) GetItems() []GenericProvider { + providers := []GenericProvider{} + + for index := range b.Items { + providers = append(providers, &AddonProviderWrapper{&b.Items[index]}) + } + + return providers +} + +func (b *AddonProviderListWrapper) GetObject() client.ObjectList { + return b.AddonProviderList +} diff --git a/internal/controller/genericprovider_controller.go b/internal/controller/genericprovider_controller.go index fc87c7c3c..04a179d1d 100644 --- a/internal/controller/genericprovider_controller.go +++ b/internal/controller/genericprovider_controller.go @@ -242,6 +242,8 @@ func (r *GenericProviderReconciler) newGenericProvider() (genericprovider.Generi return &genericprovider.ControlPlaneProviderWrapper{ControlPlaneProvider: &operatorv1.ControlPlaneProvider{}}, nil case *operatorv1.InfrastructureProvider: return &genericprovider.InfrastructureProviderWrapper{InfrastructureProvider: &operatorv1.InfrastructureProvider{}}, nil + case *operatorv1.AddonProvider: + return &genericprovider.AddonProviderWrapper{AddonProvider: &operatorv1.AddonProvider{}}, nil default: providerKind := reflect.Indirect(reflect.ValueOf(r.Provider)).Type().Name() failedToCastInterfaceErr := fmt.Errorf("failed to cast interface for type: %s", providerKind) @@ -260,6 +262,8 @@ func (r *GenericProviderReconciler) newGenericProviderList() (genericprovider.Ge return &genericprovider.ControlPlaneProviderListWrapper{ControlPlaneProviderList: &operatorv1.ControlPlaneProviderList{}}, nil case *operatorv1.InfrastructureProviderList: return &genericprovider.InfrastructureProviderListWrapper{InfrastructureProviderList: &operatorv1.InfrastructureProviderList{}}, nil + case *operatorv1.AddonProviderList: + return &genericprovider.AddonProviderListWrapper{AddonProviderList: &operatorv1.AddonProviderList{}}, nil default: providerKind := reflect.Indirect(reflect.ValueOf(r.ProviderList)).Type().Name() failedToCastInterfaceErr := fmt.Errorf("failed to cast interface for type: %s", providerKind) diff --git a/internal/controller/phases.go b/internal/controller/phases.go index dbf0371bf..f4b90ed91 100644 --- a/internal/controller/phases.go +++ b/internal/controller/phases.go @@ -509,6 +509,8 @@ func clusterctlProviderName(provider genericprovider.GenericProvider) client.Obj prefix = "control-plane-" case *operatorv1.InfrastructureProvider: prefix = "infrastructure-" + case *operatorv1.AddonProvider: + prefix = "addon-" } return client.ObjectKey{Name: prefix + provider.GetName(), Namespace: provider.GetNamespace()} diff --git a/util/util.go b/util/util.go index b5e340145..c9aac381b 100644 --- a/util/util.go +++ b/util/util.go @@ -38,6 +38,8 @@ func ClusterctlProviderType(genericProvider genericprovider.GenericProvider) clu return clusterctlv1.InfrastructureProviderType case *operatorv1.BootstrapProvider: return clusterctlv1.BootstrapProviderType + case *operatorv1.AddonProvider: + return clusterctlv1.AddonProviderType } return clusterctlv1.ProviderTypeUnknown From b0b2a893b18e1437d34641dfb6c587196ec01d24 Mon Sep 17 00:00:00 2001 From: alexander-demicev Date: Fri, 25 Aug 2023 15:26:20 +0200 Subject: [PATCH 3/5] Add addon provider to e2e suite --- test/e2e/helpers_test.go | 3 + test/e2e/minimal_configuration_test.go | 35 + test/e2e/resources/full-chart-install.yaml | 1602 ++++++++++++++++++++ 3 files changed, 1640 insertions(+) diff --git a/test/e2e/helpers_test.go b/test/e2e/helpers_test.go index 780a5feee..312899593 100644 --- a/test/e2e/helpers_test.go +++ b/test/e2e/helpers_test.go @@ -44,5 +44,8 @@ const ( infraProviderName = "docker" infraProviderDeploymentName = "capd-controller-manager" + addonProviderName = "helm" + addonProviderDeploymentName = "caaph-controller-manager" + customManifestsFolder = "resources/" ) diff --git a/test/e2e/minimal_configuration_test.go b/test/e2e/minimal_configuration_test.go index f50de93af..c42292ff6 100644 --- a/test/e2e/minimal_configuration_test.go +++ b/test/e2e/minimal_configuration_test.go @@ -210,6 +210,41 @@ data: e2eConfig.GetIntervals(bootstrapClusterProxy.GetName(), "wait-controllers")...) }) + It("should successfully create and delete an AddonProvider", func() { + bootstrapCluster := bootstrapClusterProxy.GetClient() + addonProvider := &operatorv1.AddonProvider{ObjectMeta: metav1.ObjectMeta{ + Name: addonProviderName, + Namespace: operatorNamespace, + }} + deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{ + Name: addonProviderDeploymentName, + Namespace: operatorNamespace, + }} + Expect(bootstrapCluster.Create(ctx, addonProvider)).To(Succeed()) + + By("Waiting for the addon provider deployment to be ready") + framework.WaitForDeploymentsAvailable(ctx, framework.WaitForDeploymentsAvailableInput{ + Getter: bootstrapCluster, + Deployment: deployment, + }, e2eConfig.GetIntervals(bootstrapClusterProxy.GetName(), "wait-controllers")...) + + By("Waiting for the addon provider to be ready") + WaitFor(ctx, For(addonProvider).In(bootstrapCluster).ToSatisfy( + HaveStatusCondition(&addonProvider.Status.Conditions, operatorv1.ProviderInstalledCondition)), + e2eConfig.GetIntervals(bootstrapClusterProxy.GetName(), "wait-controllers")...) + + By("Waiting for status.IntalledVersion to be set") + WaitFor(ctx, For(addonProvider).In(bootstrapCluster).ToSatisfy(func() bool { + return ptr.Equal(addonProvider.Status.InstalledVersion, &addonProvider.Spec.Version) + }), e2eConfig.GetIntervals(bootstrapClusterProxy.GetName(), "wait-controllers")...) + + Expect(bootstrapCluster.Delete(ctx, addonProvider)).To(Succeed()) + + By("Waiting for the addon provider deployment to be deleted") + WaitForDelete(ctx, For(deployment).In(bootstrapCluster), + e2eConfig.GetIntervals(bootstrapClusterProxy.GetName(), "wait-controllers")...) + }) + It("should successfully downgrade a CoreProvider (latest -> v1.4.2)", func() { bootstrapCluster := bootstrapClusterProxy.GetClient() coreProvider := &operatorv1.CoreProvider{} diff --git a/test/e2e/resources/full-chart-install.yaml b/test/e2e/resources/full-chart-install.yaml index 257e8c01b..f7813c48d 100644 --- a/test/e2e/resources/full-chart-install.yaml +++ b/test/e2e/resources/full-chart-install.yaml @@ -2,6 +2,1561 @@ # Source: cluster-api-operator/templates/operator-components.yaml apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: 'default/capi-operator-serving-cert' + controller-gen.kubebuilder.io/version: v0.11.4 + labels: + clusterctl.cluster.x-k8s.io/core: capi-operator + name: addonproviders.operator.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capi-operator-webhook-service + namespace: 'default' + path: /convert + conversionReviewVersions: + - v1 + - v1alpha1 + group: operator.cluster.x-k8s.io + names: + kind: AddonProvider + listKind: AddonProviderList + plural: addonproviders + singular: addonprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.installedVersion + name: InstalledVersion + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: AddonProvider is the Schema for the addonproviders API. + 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 + spec: + description: AddonProviderSpec defines the desired state of AddonProvider. + properties: + additionalManifests: + description: AdditionalManifests is reference to configmap that contains + additional manifests that will be applied together with the provider + components. The key for storing these manifests has to be `manifests`. + The manifests are applied only once when a certain release is installed/upgraded. + If namespace is not specified, the namespace of the provider will + be used. There is no validation of the yaml content inside the configmap. + properties: + name: + description: Name defines the name of the configmap. + type: string + namespace: + description: Namespace defines the namespace of the configmap. + type: string + required: + - name + type: object + configSecret: + description: ConfigSecret is the object with name and namespace of + the Secret providing the configuration variables for the current + provider instance, like e.g. credentials. Such configurations will + be used when creating or upgrading provider components. The contents + of the secret will be treated as immutable. If changes need to be + made, a new object can be created and the name should be updated. + The contents should be in the form of key:value. This secret must + be in the same namespace as the provider. + properties: + name: + description: Name defines the name of the secret. + type: string + namespace: + description: Namespace defines the namespace of the secret. + type: string + required: + - name + type: object + deployment: + description: Deployment defines the properties that can be enabled + on the deployment for the provider. + properties: + affinity: + description: If specified, 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector 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 + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector 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 + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector 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 + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector 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 + containers: + description: List of containers specified in the Deployment + items: + description: ContainerSpec defines the properties available + to override for each container in a provider deployment such + as Image and Args to the container’s entrypoint. + properties: + args: + additionalProperties: + type: string + description: Args represents extra provider specific flags + that are not encoded as fields in this API. Explicit controller + manager properties defined in the `Provider.ManagerSpec` + will have higher precedence than those defined in `ContainerSpec.Args`. + For example, `ManagerSpec.SyncPeriod` will be used instead + of the container arg `--sync-period` if both are defined. + The same holds for `ManagerSpec.FeatureGates` and `--feature-gates`. + type: object + command: + description: Command allows override container's entrypoint + array. + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. + 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 previously 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. + Double $$ are reduced to a single $, which allows + for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" + will produce the string literal "$(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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + imageUrl: + description: Container Image URL + type: string + name: + description: Name of the container. Cannot be updated. + type: string + resources: + description: Compute resources required by this container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n This field + is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in + PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where + this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + 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-resources-containers/' + 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. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + imagePullSecrets: + description: List of image pull secrets specified in the Deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + 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 + x-kubernetes-map-type: atomic + type: array + 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 + replicas: + description: Number of desired pods. This is a pointer to distinguish + between explicit zero and not specified. Defaults to 1. + minimum: 0 + type: integer + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + 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 + type: object + fetchConfig: + description: FetchConfig determines how the operator will fetch the + components and metadata for the provider. If nil, the operator will + try to fetch components according to default embedded fetch configuration + for the given kind and `ObjectMeta.Name`. For example, the infrastructure + name `aws` will fetch artifacts from https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases. + properties: + selector: + description: 'Selector to be used for fetching provider’s components + and metadata from ConfigMaps stored inside the cluster. Each + ConfigMap is expected to contain components and metadata for + a specific version only. Note: the name of the ConfigMap should + be set to the version or to override this add a label like the + following: provider.cluster.x-k8s.io/version=v1.4.3' + 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 + x-kubernetes-map-type: atomic + url: + description: URL to be used for fetching the provider’s components + and metadata from a remote Github repository. For example, https://github.com/{owner}/{repository}/releases + You must set `providerSpec.Version` field for operator to pick + up desired version of the release from GitHub. + type: string + type: object + manager: + description: Manager defines the properties that can be enabled on + the controller manager for the provider. + properties: + cacheNamespace: + description: "CacheNamespace if specified restricts the manager's + cache to watch objects in the desired namespace Defaults to + all namespaces \n Note: If a namespace is specified, controllers + can still Watch for a cluster-scoped resource (e.g Node). For + namespaced resources the cache will only hold objects from the + desired namespace." + type: string + controller: + description: Controller contains global configuration options + for controllers registered within this manager. + properties: + cacheSyncTimeout: + description: CacheSyncTimeout refers to the time limit set + to wait for syncing caches. Defaults to 2 minutes if not + set. + format: int64 + type: integer + groupKindConcurrency: + additionalProperties: + type: integer + description: "GroupKindConcurrency is a map from a Kind to + the number of concurrent reconciliation allowed for that + controller. \n When a controller is registered within this + manager using the builder utilities, users have to specify + the type the controller reconciles in the For(...) call. + If the object's kind passed matches one of the keys in this + map, the concurrency for that controller is set to the number + specified. \n The key is expected to be consistent in form + with GroupKind.String(), e.g. ReplicaSet in apps group (regardless + of version) would be `ReplicaSet.apps`." + type: object + recoverPanic: + description: RecoverPanic indicates if panics should be recovered. + type: boolean + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates define provider specific feature flags + that will be passed in as container args to the provider's controller + manager. Controller Manager flag is --feature-gates. + type: object + gracefulShutDown: + description: GracefulShutdownTimeout is the duration given to + runnable to stop before the manager actually returns on stop. + To disable graceful shutdown, set to time.Duration(0) To use + graceful shutdown without timeout, set to a negative duration, + e.G. time.Duration(-1) The graceful shutdown is skipped for + safety reasons in case the leader election lease is lost. + type: string + health: + description: Health contains the controller health configuration + properties: + healthProbeBindAddress: + description: HealthProbeBindAddress is the TCP address that + the controller should bind to for serving health probes + It can be set to "0" or "" to disable serving the health + probe. + type: string + livenessEndpointName: + description: LivenessEndpointName, defaults to "healthz" + type: string + readinessEndpointName: + description: ReadinessEndpointName, defaults to "readyz" + type: string + type: object + leaderElection: + description: LeaderElection is the LeaderElection config to be + used when configuring the manager.Manager leader election + properties: + leaderElect: + description: leaderElect enables a leader election client + to gain leadership before executing the main loop. Enable + this when running replicated components for high availability. + type: boolean + leaseDuration: + description: leaseDuration is the duration that non-leader + candidates will wait after observing a leadership renewal + until attempting to acquire leadership of a led but unrenewed + leader slot. This is effectively the maximum duration that + a leader can be stopped before it is replaced by another + candidate. This is only applicable if leader election is + enabled. + type: string + renewDeadline: + description: renewDeadline is the interval between attempts + by the acting master to renew a leadership slot before it + stops leading. This must be less than or equal to the lease + duration. This is only applicable if leader election is + enabled. + type: string + resourceLock: + description: resourceLock indicates the resource object type + that will be used to lock during leader election cycles. + type: string + resourceName: + description: resourceName indicates the name of resource object + that will be used to lock during leader election cycles. + type: string + resourceNamespace: + description: resourceName indicates the namespace of resource + object that will be used to lock during leader election + cycles. + type: string + retryPeriod: + description: retryPeriod is the duration the clients should + wait between attempting acquisition and renewal of a leadership. + This is only applicable if leader election is enabled. + type: string + required: + - leaderElect + - leaseDuration + - renewDeadline + - resourceLock + - resourceName + - resourceNamespace + - retryPeriod + type: object + maxConcurrentReconciles: + description: MaxConcurrentReconciles is the maximum number of + concurrent Reconciles which can be run. + minimum: 1 + type: integer + metrics: + description: Metrics contains thw controller metrics configuration + properties: + bindAddress: + description: BindAddress is the TCP address that the controller + should bind to for serving prometheus metrics. It can be + set to "0" to disable the metrics serving. + type: string + type: object + profilerAddress: + description: ProfilerAddress defines the bind address to expose + the pprof profiler (e.g. localhost:6060). Default empty, meaning + the profiler is disabled. Controller Manager flag is --profiler-address. + type: string + syncPeriod: + description: SyncPeriod determines the minimum frequency at which + watched resources are reconciled. A lower period will correct + entropy more quickly, but reduce responsiveness to change if + there are many watched resources. Change this value only if + you know what you are doing. Defaults to 10 hours if unset. + there will a 10 percent jitter between the SyncPeriod of all + controllers so that all controllers will not send list requests + simultaneously. + type: string + verbosity: + default: 1 + description: Verbosity set the logs verbosity. Defaults to 1. + Controller Manager flag is --verbosity. + minimum: 0 + type: integer + webhook: + description: Webhook contains the controllers webhook configuration + properties: + certDir: + description: CertDir is the directory that contains the server + key and certificate. if not set, webhook server would look + up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs. + The server key and certificate must be named tls.key and + tls.crt, respectively. + type: string + host: + description: Host is the hostname that the webhook server + binds to. It is used to set webhook.Server.Host. + type: string + port: + description: Port is the port that the webhook server serves + at. It is used to set webhook.Server.Port. + type: integer + type: object + type: object + version: + description: Version indicates the provider version. + type: string + type: object + status: + description: AddonProviderStatus defines the observed state of AddonProvider. + properties: + conditions: + description: Conditions define the current service state of the provider. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + contract: + description: Contract will contain the core provider contract that + the provider is abiding by, like e.g. v1alpha4. + type: string + installedVersion: + description: InstalledVersion is the version of the provider that + is installed. + type: string + observedGeneration: + description: ObservedGeneration is the latest generation observed + by the controller. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +# Source: cluster-api-operator/templates/operator-components.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from: 'default/capi-operator-serving-cert' @@ -12632,6 +14187,9 @@ spec: - effect: NoSchedule key: node-role.kubernetes.io/control-plane --- +# Source: cluster-api-operator/templates/addon.yaml +# Addon provider +--- # Source: cluster-api-operator/templates/bootstrap.yaml # Bootstrap provider --- @@ -12682,6 +14240,28 @@ metadata: clusterctl.cluster.x-k8s.io/core: capi-operator name: capi-operator-mutating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: 'default' + path: /mutate-operator-cluster-x-k8s-io-v1alpha2-addonprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vaddonprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - addonproviders + sideEffects: None - admissionReviewVersions: - v1 - v1beta1 @@ -12781,6 +14361,28 @@ metadata: clusterctl.cluster.x-k8s.io/core: capi-operator name: capi-operator-validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: capi-operator-webhook-service + namespace: 'default' + path: /validate-operator-cluster-x-k8s-io-v1alpha2-addonprovider + failurePolicy: Fail + matchPolicy: Equivalent + name: vaddonprovider.kb.io + rules: + - apiGroups: + - operator.cluster.x-k8s.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - addonproviders + sideEffects: None - admissionReviewVersions: - v1 - v1beta1 From c03f518c5fb5e5dbd6352fc497fcc9f78f5f00e0 Mon Sep 17 00:00:00 2001 From: alexander-demicev Date: Fri, 25 Aug 2023 15:26:57 +0200 Subject: [PATCH 4/5] Update docs with addon provider --- docs/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index d64887993..714aa6fbb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -165,12 +165,13 @@ docker run -it --rm registry.k8s.io/capi-operator/cluster-api-operator:${CAPI_OP ## Basic Cluster API Provider Installation -In this section, we will walk you through the basic process of installing Cluster API providers using the operator. The Cluster API operator manages four types of objects: +In this section, we will walk you through the basic process of installing Cluster API providers using the operator. The Cluster API operator manages five types of objects: - CoreProvider - BootstrapProvider - ControlPlaneProvider - InfrastructureProvider +- AddonProvider Please note that this example provides a basic configuration of Azure Infrastructure provider for getting started. More detailed examples and CRD descriptions will be provided in subsequent sections of this document. From a3e346ee7853649085bafcc4eb19d20ee82b65c4 Mon Sep 17 00:00:00 2001 From: alexander-demicev Date: Fri, 25 Aug 2023 15:27:15 +0200 Subject: [PATCH 5/5] Add addon provider to helm chart --- .../templates/addon-conditions.yaml | 29 ++++++++++ .../cluster-api-operator/templates/addon.yaml | 54 +++++++++++++++++++ hack/charts/cluster-api-operator/values.yaml | 1 + 3 files changed, 84 insertions(+) create mode 100644 hack/charts/cluster-api-operator/templates/addon-conditions.yaml create mode 100644 hack/charts/cluster-api-operator/templates/addon.yaml diff --git a/hack/charts/cluster-api-operator/templates/addon-conditions.yaml b/hack/charts/cluster-api-operator/templates/addon-conditions.yaml new file mode 100644 index 000000000..fcfd9a699 --- /dev/null +++ b/hack/charts/cluster-api-operator/templates/addon-conditions.yaml @@ -0,0 +1,29 @@ +{{- if .Values.addon }} +# Deploy core components if not specified +{{- if not .Values.core }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: capi-system +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: CoreProvider +metadata: + name: cluster-api + namespace: capi-system + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- if .Values.secretName }} +spec: + secretName: {{ .Values.secretName }} +{{- if .Values.secretNamespace }} + secretNamespace: {{ .Values.secretNamespace }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/hack/charts/cluster-api-operator/templates/addon.yaml b/hack/charts/cluster-api-operator/templates/addon.yaml new file mode 100644 index 000000000..a4acb740c --- /dev/null +++ b/hack/charts/cluster-api-operator/templates/addon.yaml @@ -0,0 +1,54 @@ +# Addon provider +{{- if .Values.addon }} +{{- $addons := split ";" .Values.addon }} +{{- $addonNamespace := "" }} +{{- $addonName := "" }} +{{- $addonVersion := "" }} +{{- range $addon := $addons }} +{{- $addonArgs := split ":" $addon }} +{{- $addonArgsLen := len $addonArgs }} +{{- if eq $addonArgsLen 3 }} + {{- $addonNamespace = $addonArgs._0 }} + {{- $addonName = $addonArgs._1 }} + {{- $addonVersion = $addonArgs._2 }} +{{- else if eq $addonArgsLen 2 }} + {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} + {{- $addonName = $addonArgs._0 }} + {{- $addonVersion = $addonArgs._1 }} +{{- else if eq $addonArgsLen 1 }} + {{- $addonNamespace = print $addonArgs._0 "-addon-system" }} + {{- $addonName = $addonArgs._0 }} +{{- else }} + {{- fail "addon provider argument should have the following format helm:v1.0.0 or mynamespace:helm:v1.0.0" }} +{{- end }} +--- +apiVersion: v1 +kind: Namespace +metadata: + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "1" + name: {{ $addonNamespace }} +--- +apiVersion: operator.cluster.x-k8s.io/v1alpha2 +kind: AddonProvider +metadata: + name: {{ $addonName }} + namespace: {{ $addonNamespace }} + annotations: + "helm.sh/hook": "post-install" + "helm.sh/hook-weight": "2" +{{- if or $addonVersion $.Values.secretName }} +spec: +{{- end}} +{{- if $addonVersion }} + version: {{ $addonVersion }} +{{- end }} +{{- if $.Values.secretName }} + secretName: {{ $.Values.secretName }} +{{- end }} +{{- if $.Values.secretNamespace }} + secretNamespace: {{ $.Values.secretNamespace }} +{{- end }} +{{- end }} +{{- end }} diff --git a/hack/charts/cluster-api-operator/values.yaml b/hack/charts/cluster-api-operator/values.yaml index e8bc411e6..8df1ddee6 100644 --- a/hack/charts/cluster-api-operator/values.yaml +++ b/hack/charts/cluster-api-operator/values.yaml @@ -11,6 +11,7 @@ core: "" bootstrap: "" controlPlane: "" infrastructure: "" +addon: "" # --- # Common configuration secret options configSecret: {}