diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index de2ee7de9..1b6530b75 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -132,21 +132,16 @@ jobs: with: enable-cache: true - - name: Export golang and golangci-lint versions - id: versions - run: | - echo "golangci-lint=$(devbox run -- golangci-lint version --short)" >>"${GITHUB_OUTPUT}" - echo "golang=$(devbox run -- go version | grep -o "[[:digit:]]\+.[[:digit:]]\+\(.[[:digit:]]\+\)\?")" >>"${GITHUB_OUTPUT}" + - name: Install custom golangci-lint + run: devbox run -- make hack/tools/golangci-lint-kube-api-linter - name: golangci-lint - uses: reviewdog/action-golangci-lint@v2 - with: - fail_level: error - reporter: github-pr-review - golangci_lint_version: v${{ steps.versions.outputs.golangci-lint }} - go_version: v${{ steps.versions.outputs.golang }} - workdir: ${{ matrix.module }} - golangci_lint_flags: "--config=${{ github.workspace }}/.golangci.yml" + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ${{ github.workspace }}/hack/tools/golangci-lint-kube-api-linter run --config=${{ github.workspace }}/.golangci.yml --output.text.path=stdout ./... | \ + devbox run -- reviewdog -f=golangci-lint -reporter=github-pr-review --fail-level=any + working-directory: ${{ matrix.module }} lint-gha: runs-on: ubuntu-24.04 diff --git a/.gitignore b/.gitignore index 177e3755b..845415da9 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ test/e2e/config/caren-envsubst.yaml hack/tools/fetch-images/fetch-images caren-images.txt hack/examples/release/*-cluster-class.yaml +golangci-lint-kube-api-linter diff --git a/.golangci.yml b/.golangci.yml index ff8d3bc05..d8e8e858a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,6 +23,7 @@ linters: - govet - importas - ineffassign + - kubeapilinter - lll - misspell - nolintlint @@ -74,8 +75,55 @@ linters: - github.com/onsi/gomega testifylint: enable-all: true + custom: + kubeapilinter: + type: module + description: KAL is the Kube-API-Linter and lints Kube like APIs based on API conventions and best practices. + settings: + linters: + enable: + # - "commentstart" # Ensure comments start with the serialized version of the field name. + # - "conditions" # Ensure conditions have the correct json tags and markers. + - "duplicatemarkers" # Ensure there are no exact duplicate markers. for types and fields. + - "integers" # Ensure only int32 and int64 are used for integers. + - "jsontags" # Ensure every field has a json tag. + - "maxlength" # Ensure all strings and arrays have maximum lengths/maximum items. + - "nobools" # Bools do not evolve over time, should use enums instead. + - "nofloats" # Ensure floats are not used. + # - "nomaps" # Ensure maps are not used. + # - "nophase" # Ensure phases are not used, as they are not extensible. + - "optionalfields" # Ensure that all fields marked as optional adhere to being pointers and + # having the `omitempty` value in their `json` tag where appropriate. + - "optionalorrequired" # Every field should be marked as `+optional` or `+required`. + - "requiredfields" # Required fields should not be pointers, and should not have `omitempty`. + # - "ssatags" # Ensure array fields have the appropriate listType markers + # - "statusoptional" # Ensure all first children within status should be optional. + # - "statussubresource" # All root objects that have a `status` field should have a status subresource. + - "uniquemarkers" # Ensure that types and fields do not contain more than a single definition of a marker that should only be present once. + + # Linters below this line are disabled, pending conversation on how and when to enable them. + disable: + - "*" # We will manually enable new linters after understanding the impact. Disable all by default. + lintersConfig: + optionalfields: + pointers: + preference: WhenRequired # Always | WhenRequired # Whether to always require pointers, or only when required. Defaults to `Always`. + jsontags: + jsonTagRegex: "^[a-z][a-z0-9-]*(?:[A-Z][a-z0-9]*)*$" # The default regex is appropriate for our use case. + optionalorrequired: + preferredOptionalMarker: kubebuilder:validation:Optional # The preferred optional marker to use, fixes will suggest to use this marker. Defaults to `optional`. + preferredRequiredMarker: kubebuilder:validation:Required # The preferred required marker to use, fixes will suggest to use this marker. Defaults to `required`. exclusions: - generated: lax + generated: strict + paths: + # Ignore generated files. + - zz_generated.*\.go$ + # Ignore external API packages. + - external/ + # Ignore test files. + - '.+_test\.go$' + # Ignore aggregate types. + - 'aggregate_types\.go$' presets: - comments - common-false-positives @@ -103,11 +151,36 @@ linters: - gocritic path: internal/test/envtest text: 'hugeParam: input is heavy' - paths: - - external - - third_party$ - - builtin$ - - examples$ + + # START kube-api-linter rules + - path: ".*" + text: "optionalorrequired: embedded field must be marked as kubebuilder:validation:Optional or kubebuilder:validation:Required" + linters: + - kubeapilinter + + # kube-api-linter does not handle formats correctly yet. + - path: '/addon_types\.go$' + text: "maxlength: field (Start|End) must have a maximum length, add kubebuilder:validation:MaxLength marker" + linters: + - kubeapilinter + - path: '/common_types\.go$' + text: "maxlength: field Address must have a maximum length, add kubebuilder:validation:MaxLength marker" + linters: + - kubeapilinter + + # kube-api-linter does not handle patterns correctly yet. + - path: '/aws_(clusterconfig|node)_types\.go$' + text: "maxlength: field (ID|IAMInstanceProfile|InstanceType|Org) must have a maximum length, add kubebuilder:validation:MaxLength marker" + linters: + - kubeapilinter + - path: '/(nutanix_)?(clusterconfig)_types\.go$' + text: "maxlength: field (URL|Tag) must have a maximum length, add kubebuilder:validation:MaxLength marker" + linters: + - kubeapilinter + - path-except: "^/api/" + linters: + - kubeapilinter + # END kube-api-linter rules formatters: enable: - gci diff --git a/api/v1alpha1/addon_types.go b/api/v1alpha1/addon_types.go index 229195881..1d32e8905 100644 --- a/api/v1alpha1/addon_types.go +++ b/api/v1alpha1/addon_types.go @@ -118,8 +118,9 @@ type CNI struct { // Addon strategy used to deploy the CNI provider to the workload cluster. // +kubebuilder:default=HelmAddon + // +kubebuilder:validation:Optional // +kubebuilder:validation:Enum=ClusterResourceSet;HelmAddon - Strategy *AddonStrategy `json:"strategy,omitempty"` + Strategy AddonStrategy `json:"strategy,omitzero"` // AddonConfig contains the configuration for the CNI provider. // +kubebuilder:validation:Optional @@ -153,6 +154,7 @@ type ValuesReference struct { // Name is the name of resource being referenced. // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 Name string `json:"name"` } @@ -160,8 +162,9 @@ type ValuesReference struct { type NFD struct { // Addon strategy used to deploy Node Feature Discovery (NFD) to the workload cluster. // +kubebuilder:default=HelmAddon + // +kubebuilder:validation:Optional // +kubebuilder:validation:Enum=ClusterResourceSet;HelmAddon - Strategy *AddonStrategy `json:"strategy,omitempty"` + Strategy AddonStrategy `json:"strategy,omitzero"` } // ClusterAutoscaler tells us to enable or disable the cluster-autoscaler addon. @@ -169,8 +172,9 @@ type ClusterAutoscaler struct { // Addon strategy used to deploy cluster-autoscaler to the management cluster // targeting the workload cluster. // +kubebuilder:default=HelmAddon + // +kubebuilder:validation:Optional // +kubebuilder:validation:Enum=ClusterResourceSet;HelmAddon - Strategy *AddonStrategy `json:"strategy,omitempty"` + Strategy AddonStrategy `json:"strategy,omitzero"` } type GenericCSI struct { @@ -185,15 +189,17 @@ type GenericCSI struct { type GenericCOSI struct { // Addon strategy used to deploy the COSI controller to the workload cluster. // +kubebuilder:default=HelmAddon + // +kubebuilder:validation:Optional // +kubebuilder:validation:Enum=HelmAddon - Strategy *AddonStrategy `json:"strategy,omitempty"` + Strategy AddonStrategy `json:"strategy,omitzero"` } type SnapshotController struct { // Addon strategy used to deploy the snapshot controller to the workload cluster. // +kubebuilder:default=HelmAddon + // +kubebuilder:validation:Optional // +kubebuilder:validation:Enum=ClusterResourceSet;HelmAddon - Strategy *AddonStrategy `json:"strategy,omitempty"` + Strategy AddonStrategy `json:"strategy,omitzero"` } type DefaultStorage struct { @@ -205,6 +211,7 @@ type DefaultStorage struct { // Name of the default storage class config the specified default provider. // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=242 StorageClassConfig string `json:"storageClassConfig"` } @@ -251,8 +258,9 @@ type CSIProvider struct { // Addon strategy used to deploy the CSI provider to the workload cluster. // +kubebuilder:default=HelmAddon + // +kubebuilder:validation:Optional // +kubebuilder:validation:Enum=ClusterResourceSet;HelmAddon - Strategy *AddonStrategy `json:"strategy,omitempty"` + Strategy AddonStrategy `json:"strategy,omitzero"` // The reference to any secret used by the CSI Provider. // +kubebuilder:validation:Optional @@ -276,7 +284,6 @@ type StorageClassConfig struct { // If the storage class should allow volume expanding // +kubebuilder:validation:Optional - // +kubebuilder:default=false AllowExpansion bool `json:"allowExpansion,omitempty"` } @@ -302,8 +309,9 @@ type CCM struct { // Addon strategy used to deploy the CCM to the workload cluster. // +kubebuilder:default=HelmAddon + // +kubebuilder:validation:Optional // +kubebuilder:validation:Enum=ClusterResourceSet;HelmAddon - Strategy *AddonStrategy `json:"strategy,omitempty"` + Strategy AddonStrategy `json:"strategy,omitzero"` } type CCMCredentials struct { @@ -329,21 +337,25 @@ type ServiceLoadBalancerConfiguration struct { // provider uses to choose an address for a load balancer. // +kubebuilder:validation:Required // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=10 AddressRanges []AddressRange `json:"addressRanges"` } // AddressRange defines an IPv4 range. type AddressRange struct { // +kubebuilder:validation:Format=ipv4 + // +kubebuilder:validation:Required Start string `json:"start"` // +kubebuilder:validation:Format=ipv4 + // +kubebuilder:validation:Required End string `json:"end"` } type RegistryAddon struct { // The OCI registry provider to deploy. // +kubebuilder:default="CNCF Distribution" + // +kubebuilder:validation:Required // +kubebuilder:validation:Enum="CNCF Distribution" Provider string `json:"provider"` } diff --git a/api/v1alpha1/aws_clusterconfig_types.go b/api/v1alpha1/aws_clusterconfig_types.go index 2fe21a340..94617767b 100644 --- a/api/v1alpha1/aws_clusterconfig_types.go +++ b/api/v1alpha1/aws_clusterconfig_types.go @@ -20,6 +20,8 @@ type AWSSpec struct { ControlPlaneLoadBalancer *AWSLoadBalancerSpec `json:"controlPlaneLoadBalancer,omitempty"` } +// +kubebuilder:validation:MinLength=4 +// +kubebuilder:validation:MaxLength=16 type Region string type AWSNetwork struct { @@ -34,17 +36,18 @@ type AWSNetwork struct { type VPC struct { // Existing VPC ID to use for the cluster. // +kubebuilder:validation:Required - // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:Format=`^vpc-[0-9a-f]{8}(?:[0-9a-f]{9})?$` ID string `json:"id"` } +// +kubebuilder:validation:MaxItems=10 type Subnets []SubnetSpec // SubnetSpec configures an AWS Subnet. type SubnetSpec struct { // Existing Subnet ID to use for the cluster. // +kubebuilder:validation:Required - // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:Format=`^subnet-[0-9a-f]{8}(?:[0-9a-f]{9})?$` ID string `json:"id"` } diff --git a/api/v1alpha1/aws_node_types.go b/api/v1alpha1/aws_node_types.go index b8b65220f..03774adc5 100644 --- a/api/v1alpha1/aws_node_types.go +++ b/api/v1alpha1/aws_node_types.go @@ -7,10 +7,14 @@ type AWSControlPlaneNodeSpec struct { // The IAM instance profile to use for the cluster Machines. // +kubebuilder:validation:Optional // +kubebuilder:default=control-plane.cluster-api-provider-aws.sigs.k8s.io + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=128 IAMInstanceProfile string `json:"iamInstanceProfile,omitempty"` // +kubebuilder:validation:Optional // +kubebuilder:default=m5.xlarge + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=32 InstanceType string `json:"instanceType,omitempty"` AWSGenericNodeSpec `json:",inline"` @@ -20,11 +24,15 @@ type AWSWorkerNodeSpec struct { // The IAM instance profile to use for the cluster Machines. // +kubebuilder:validation:Optional // +kubebuilder:default=nodes.cluster-api-provider-aws.sigs.k8s.io + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=128 IAMInstanceProfile string `json:"iamInstanceProfile,omitempty"` // The AWS instance type to use for the cluster Machines. // +kubebuilder:validation:Optional // +kubebuilder:default=m5.2xlarge + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=32 InstanceType string `json:"instanceType,omitempty"` AWSGenericNodeSpec `json:",inline"` @@ -44,6 +52,7 @@ type AWSGenericNodeSpec struct { PlacementGroup *PlacementGroup `json:"placementGroup,omitempty"` } +// +kubebuilder:validation:MaxItems=32 type AdditionalSecurityGroup []SecurityGroup type PlacementGroup struct { @@ -57,12 +66,16 @@ type PlacementGroup struct { type SecurityGroup struct { // ID is the id of the security group // +kubebuilder:validation:Optional + // +kubebuilder:validation:Format=`^sg-[0-9a-f]{8}(?:[0-9a-f]{9})?$` + // +kubebuilder:validation:MinLength=1 ID string `json:"id,omitempty"` } type AMISpec struct { // AMI ID is the reference to the AMI from which to create the machine instance. // +kubebuilder:validation:Optional + // +kubebuilder:validation:Format=`^ami-[0-9a-f]{8}(?:[0-9a-f]{9})?$` + // +kubebuilder:validation:MinLength=1 ID string `json:"id,omitempty"` // Lookup is the lookup arguments for the AMI. @@ -75,13 +88,20 @@ type AMILookup struct { // base OS and kubernetes version. // +kubebuilder:validation:Optional // +kubebuilder:example=`capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-*` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=128 Format string `json:"format,omitempty"` // The AWS Organization ID to use for image lookup. // +kubebuilder:validation:Optional + // +kubebuilder:validation:Format=`^o-[0-9a-z]{10,32}$` + // +kubebuilder:validation:MinLength=12 + // +kubebuilder:validation:MaxLength=34 Org string `json:"org,omitempty"` // The name of the base os for image lookup // +kubebuilder:validation:Optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=32 BaseOS string `json:"baseOS,omitempty"` } diff --git a/api/v1alpha1/clusterconfig_types.go b/api/v1alpha1/clusterconfig_types.go index 9b995cadd..4bcea9c65 100644 --- a/api/v1alpha1/clusterconfig_types.go +++ b/api/v1alpha1/clusterconfig_types.go @@ -57,7 +57,7 @@ type AWSClusterConfig struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +kubebuilder:validation:Optional - Spec AWSClusterConfigSpec `json:"spec,omitempty"` + Spec *AWSClusterConfigSpec `json:"spec,omitempty"` } func (s AWSClusterConfig) VariableSchema() clusterv1.VariableSchema { //nolint:gocritic,lll // Passed by value for no potential side-effect. @@ -82,6 +82,8 @@ type AWSClusterConfigSpec struct { // +kubebuilder:validation:Optional // +kubebuilder:validation:UniqueItems=true // +kubebuilder:validation:items:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + // +kubebuilder:validation:MaxItems=100 + // +kubebuilder:validation:items:MaxLength=253 ExtraAPIServerCertSANs []string `json:"extraAPIServerCertSANs,omitempty"` } @@ -93,7 +95,7 @@ type DockerClusterConfig struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +kubebuilder:validation:Optional - Spec DockerClusterConfigSpec `json:"spec,omitempty"` + Spec *DockerClusterConfigSpec `json:"spec,omitempty"` } func (s DockerClusterConfig) VariableSchema() clusterv1.VariableSchema { //nolint:gocritic,lll // Passed by value for no potential side-effect. @@ -122,6 +124,8 @@ type DockerClusterConfigSpec struct { // +kubebuilder:validation:Optional // +kubebuilder:validation:UniqueItems=true // +kubebuilder:validation:items:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + // +kubebuilder:validation:MaxItems=100 + // +kubebuilder:validation:items:MaxLength=253 ExtraAPIServerCertSANs []string `json:"extraAPIServerCertSANs,omitempty"` } @@ -133,7 +137,7 @@ type NutanixClusterConfig struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +kubebuilder:validation:Optional - Spec NutanixClusterConfigSpec `json:"spec,omitempty"` + Spec *NutanixClusterConfigSpec `json:"spec,omitempty"` } func (s NutanixClusterConfig) VariableSchema() clusterv1.VariableSchema { //nolint:gocritic,lll // Passed by value for no potential side-effect. @@ -161,6 +165,8 @@ type NutanixClusterConfigSpec struct { // +kubebuilder:validation:Optional // +kubebuilder:validation:UniqueItems=true // +kubebuilder:validation:items:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + // +kubebuilder:validation:MaxItems=100 + // +kubebuilder:validation:items:MaxLength=253 ExtraAPIServerCertSANs []string `json:"extraAPIServerCertSANs,omitempty"` } @@ -171,13 +177,15 @@ type GenericClusterConfig struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - // +optional - Spec GenericClusterConfigSpec `json:"spec,omitempty"` + // +kubebuilder:validation:Optional + Spec *GenericClusterConfigSpec `json:"spec,omitempty"` // Extra Subject Alternative Names for the API Server signing cert. // +kubebuilder:validation:UniqueItems=true // +kubebuilder:validation:items:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` - // +optional + // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=100 + // +kubebuilder:validation:items:MaxLength=253 ExtraAPIServerCertSANs []string `json:"extraAPIServerCertSANs,omitempty"` } @@ -190,7 +198,9 @@ type GenericClusterConfigSpec struct { // Sets the Kubernetes image repository used for the KubeadmControlPlane. // +kubebuilder:validation:Optional // +kubebuilder:validation:Pattern=`^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$` - KubernetesImageRepository *string `json:"kubernetesImageRepository,omitempty"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=2048 + KubernetesImageRepository string `json:"kubernetesImageRepository,omitempty"` // +kubebuilder:validation:Optional Etcd *Etcd `json:"etcd,omitempty"` @@ -199,12 +209,14 @@ type GenericClusterConfigSpec struct { Proxy *HTTPProxy `json:"proxy,omitempty"` // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=32 ImageRegistries []ImageRegistry `json:"imageRegistries,omitempty"` // +kubebuilder:validation:Optional GlobalImageRegistryMirror *GlobalImageRegistryMirror `json:"globalImageRegistryMirror,omitempty"` // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=32 Users []User `json:"users,omitempty"` // +kubebuilder:validation:Optional @@ -226,11 +238,15 @@ type Image struct { // Repository is used to override the image repository to pull from. // +kubebuilder:validation:Optional // +kubebuilder:validation:Pattern=`^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=2048 Repository string `json:"repository,omitempty"` // Tag is used to override the default image tag. // +kubebuilder:validation:Optional // +kubebuilder:validation:Pattern=`^[\w][\w.-]{0,127}$` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=128 Tag string `json:"tag,omitempty"` } @@ -277,6 +293,7 @@ type ImageRegistry struct { type User struct { // Name specifies the user name. // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength=256 Name string `json:"name"` // HashedPassword is a hashed password for the user, formatted as described @@ -284,18 +301,24 @@ type User struct { // instructions to create a hashed password. // An empty string is not marshalled, because it is not a valid value. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=106 HashedPassword string `json:"hashedPassword,omitempty"` // SSHAuthorizedKeys is a list of public SSH keys to write to the // machine. Use the corresponding private SSH keys to authenticate. See SSH // documentation for instructions to create a key pair. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=32 + // +kubebuilder:validation:items:MaxLength=256 SSHAuthorizedKeys []string `json:"sshAuthorizedKeys,omitempty"` // Sudo is a sudo user specification, formatted as described in the sudo // documentation. // An empty string is not marshalled, because it is not a valid value. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 Sudo string `json:"sudo,omitempty"` } @@ -362,6 +385,8 @@ type NTP struct { // Servers is a list of NTP servers to use for time synchronization. // +kubebuilder:validation:Required // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:items:MaxLength=253 Servers []string `json:"servers"` } diff --git a/api/v1alpha1/common_types.go b/api/v1alpha1/common_types.go index b09fdd27f..dbb762f81 100644 --- a/api/v1alpha1/common_types.go +++ b/api/v1alpha1/common_types.go @@ -28,6 +28,7 @@ type ControlPlaneEndpointSpec struct { // The hostname on which the API server is serving. // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 Host string `json:"host"` // The port on which the API server is serving. @@ -58,6 +59,7 @@ type ControlPlaneVirtualIPConfiguration struct { // If left empty, the value from controlPlaneEndpoint.host will be used. // +kubebuilder:validation:Optional // +kubebuilder:validation:Format=ipv4 + // +kubebuilder:validation:MinLength=1 Address string `json:"address,omitempty"` // The port on which the API server is serving. @@ -75,6 +77,7 @@ type LocalObjectReference struct { // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 Name string `json:"name"` } diff --git a/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml index d11c860d7..44ebccb4a 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml @@ -56,6 +56,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -116,6 +117,7 @@ spec: type: string name: description: Name is the name of resource being referenced. + maxLength: 253 minLength: 1 type: string required: @@ -137,6 +139,7 @@ spec: type: string storageClassConfig: description: Name of the default storage class config the specified default provider. + maxLength: 242 minLength: 1 type: string required: @@ -157,6 +160,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -169,7 +173,6 @@ spec: additionalProperties: properties: allowExpansion: - default: false description: If the storage class should allow volume expanding type: boolean parameters: @@ -267,6 +270,7 @@ spec: - end - start type: object + maxItems: 10 minItems: 1 type: array required: @@ -307,17 +311,18 @@ spec: properties: id: description: Existing Subnet ID to use for the cluster. - minLength: 1 + format: ^subnet-[0-9a-f]{8}(?:[0-9a-f]{9})?$ type: string required: - id type: object + maxItems: 10 type: array vpc: properties: id: description: Existing VPC ID to use for the cluster. - minLength: 1 + format: ^vpc-[0-9a-f]{8}(?:[0-9a-f]{9})?$ type: string required: - id @@ -325,6 +330,8 @@ spec: type: object region: description: AWS region to create cluster in. + maxLength: 16 + minLength: 4 type: string type: object controlPlane: @@ -355,8 +362,11 @@ spec: properties: id: description: ID is the id of the security group + format: ^sg-[0-9a-f]{8}(?:[0-9a-f]{9})?$ + minLength: 1 type: string type: object + maxItems: 32 type: array ami: description: |- @@ -365,30 +375,43 @@ spec: properties: id: description: AMI ID is the reference to the AMI from which to create the machine instance. + format: ^ami-[0-9a-f]{8}(?:[0-9a-f]{9})?$ + minLength: 1 type: string lookup: description: Lookup is the lookup arguments for the AMI. properties: baseOS: description: The name of the base os for image lookup + maxLength: 32 + minLength: 1 type: string format: description: |- AMI naming format. Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base OS and kubernetes version. example: capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* + maxLength: 128 + minLength: 1 type: string org: description: The AWS Organization ID to use for image lookup. + format: ^o-[0-9a-z]{10,32}$ + maxLength: 34 + minLength: 12 type: string type: object type: object iamInstanceProfile: default: control-plane.cluster-api-provider-aws.sigs.k8s.io description: The IAM instance profile to use for the cluster Machines. + maxLength: 128 + minLength: 1 type: string instanceType: default: m5.xlarge + maxLength: 32 + minLength: 1 type: string placementGroup: description: PlacementGroup specifies the placement group in which to launch the instance. @@ -438,14 +461,18 @@ spec: type: string key: description: The taint key to be applied to a node. + maxLength: 253 type: string value: description: The taint value corresponding to the taint key. + maxLength: 63 + minLength: 1 type: string required: - effect - key type: object + maxItems: 32 type: array type: object dns: @@ -462,10 +489,14 @@ spec: properties: repository: description: Repository is used to override the image repository to pull from. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string tag: description: Tag is used to override the default image tag. + maxLength: 128 + minLength: 1 pattern: ^[\w][\w.-]{0,127}$ type: string type: object @@ -498,10 +529,14 @@ spec: properties: repository: description: Repository is used to override the image repository to pull from. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string tag: description: Tag is used to override the default image tag. + maxLength: 128 + minLength: 1 pattern: ^[\w][\w.-]{0,127}$ type: string type: object @@ -509,8 +544,10 @@ spec: extraAPIServerCertSANs: description: Extra Subject Alternative Names for the API Server signing cert. items: + maxLength: 253 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + maxItems: 100 type: array uniqueItems: true globalImageRegistryMirror: @@ -529,6 +566,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -559,6 +597,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -573,6 +612,7 @@ spec: required: - url type: object + maxItems: 32 type: array kubeProxy: description: KubeProxy defines the configuration for kube-proxy. @@ -592,6 +632,8 @@ spec: type: object kubernetesImageRepository: description: Sets the Kubernetes image repository used for the KubeadmControlPlane. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string ntp: @@ -600,7 +642,9 @@ spec: servers: description: Servers is a list of NTP servers to use for time synchronization. items: + maxLength: 253 type: string + maxItems: 16 minItems: 1 type: array required: @@ -616,13 +660,20 @@ spec: Default values: localhost,127.0.0.1,,,kubernetes ,kubernetes.default,.svc,.svc. items: + maxLength: 253 + minLength: 1 type: string + maxItems: 128 type: array http: description: HTTP proxy value. + maxLength: 2048 + minLength: 1 type: string https: description: HTTPS proxy value. + maxLength: 2048 + minLength: 1 type: string type: object users: @@ -635,9 +686,12 @@ spec: by the crypt(5) man page. See your distribution's documentation for instructions to create a hashed password. An empty string is not marshalled, because it is not a valid value. + maxLength: 106 + minLength: 1 type: string name: description: Name specifies the user name. + maxLength: 256 type: string sshAuthorizedKeys: description: |- @@ -645,17 +699,22 @@ spec: machine. Use the corresponding private SSH keys to authenticate. See SSH documentation for instructions to create a key pair. items: + maxLength: 256 type: string + maxItems: 32 type: array sudo: description: |- Sudo is a sudo user specification, formatted as described in the sudo documentation. An empty string is not marshalled, because it is not a valid value. + maxLength: 1024 + minLength: 1 type: string required: - name type: object + maxItems: 32 type: array type: object type: object diff --git a/api/v1alpha1/crds/caren.nutanix.com_awsworkernodeconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_awsworkernodeconfigs.yaml index e0f74a647..3bc0a2484 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_awsworkernodeconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_awsworkernodeconfigs.yaml @@ -51,8 +51,11 @@ spec: properties: id: description: ID is the id of the security group + format: ^sg-[0-9a-f]{8}(?:[0-9a-f]{9})?$ + minLength: 1 type: string type: object + maxItems: 32 type: array ami: description: |- @@ -62,32 +65,45 @@ spec: id: description: AMI ID is the reference to the AMI from which to create the machine instance. + format: ^ami-[0-9a-f]{8}(?:[0-9a-f]{9})?$ + minLength: 1 type: string lookup: description: Lookup is the lookup arguments for the AMI. properties: baseOS: description: The name of the base os for image lookup + maxLength: 32 + minLength: 1 type: string format: description: |- AMI naming format. Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base OS and kubernetes version. example: capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* + maxLength: 128 + minLength: 1 type: string org: description: The AWS Organization ID to use for image lookup. + format: ^o-[0-9a-z]{10,32}$ + maxLength: 34 + minLength: 12 type: string type: object type: object iamInstanceProfile: default: nodes.cluster-api-provider-aws.sigs.k8s.io description: The IAM instance profile to use for the cluster Machines. + maxLength: 128 + minLength: 1 type: string instanceType: default: m5.2xlarge description: The AWS instance type to use for the cluster Machines. + maxLength: 32 + minLength: 1 type: string placementGroup: description: PlacementGroup specifies the placement group in which @@ -140,14 +156,18 @@ spec: type: string key: description: The taint key to be applied to a node. + maxLength: 253 type: string value: description: The taint value corresponding to the taint key. + maxLength: 63 + minLength: 1 type: string required: - effect - key type: object + maxItems: 32 type: array type: object type: object diff --git a/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml index 92c74546e..5c39de5c1 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml @@ -56,6 +56,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -116,6 +117,7 @@ spec: type: string name: description: Name is the name of resource being referenced. + maxLength: 253 minLength: 1 type: string required: @@ -146,6 +148,7 @@ spec: type: string storageClassConfig: description: Name of the default storage class config the specified default provider. + maxLength: 242 minLength: 1 type: string required: @@ -166,6 +169,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -178,7 +182,6 @@ spec: additionalProperties: properties: allowExpansion: - default: false description: If the storage class should allow volume expanding type: boolean parameters: @@ -276,6 +279,7 @@ spec: - end - start type: object + maxItems: 10 minItems: 1 type: array required: @@ -317,6 +321,8 @@ spec: properties: customImage: description: Custom OCI image for control plane and worker Nodes. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*(:[\w][\w.-]{0,127})?(@[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][0-9A-Fa-f]{32,})?$ type: string type: object @@ -356,14 +362,18 @@ spec: type: string key: description: The taint key to be applied to a node. + maxLength: 253 type: string value: description: The taint value corresponding to the taint key. + maxLength: 63 + minLength: 1 type: string required: - effect - key type: object + maxItems: 32 type: array type: object dns: @@ -380,10 +390,14 @@ spec: properties: repository: description: Repository is used to override the image repository to pull from. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string tag: description: Tag is used to override the default image tag. + maxLength: 128 + minLength: 1 pattern: ^[\w][\w.-]{0,127}$ type: string type: object @@ -418,10 +432,14 @@ spec: properties: repository: description: Repository is used to override the image repository to pull from. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string tag: description: Tag is used to override the default image tag. + maxLength: 128 + minLength: 1 pattern: ^[\w][\w.-]{0,127}$ type: string type: object @@ -435,8 +453,10 @@ spec: - 0.0.0.0 - host.docker.internal items: + maxLength: 253 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + maxItems: 100 type: array uniqueItems: true globalImageRegistryMirror: @@ -455,6 +475,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -485,6 +506,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -499,6 +521,7 @@ spec: required: - url type: object + maxItems: 32 type: array kubeProxy: description: KubeProxy defines the configuration for kube-proxy. @@ -518,6 +541,8 @@ spec: type: object kubernetesImageRepository: description: Sets the Kubernetes image repository used for the KubeadmControlPlane. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string ntp: @@ -526,7 +551,9 @@ spec: servers: description: Servers is a list of NTP servers to use for time synchronization. items: + maxLength: 253 type: string + maxItems: 16 minItems: 1 type: array required: @@ -542,13 +569,20 @@ spec: Default values: localhost,127.0.0.1,,,kubernetes ,kubernetes.default,.svc,.svc. items: + maxLength: 253 + minLength: 1 type: string + maxItems: 128 type: array http: description: HTTP proxy value. + maxLength: 2048 + minLength: 1 type: string https: description: HTTPS proxy value. + maxLength: 2048 + minLength: 1 type: string type: object users: @@ -561,9 +595,12 @@ spec: by the crypt(5) man page. See your distribution's documentation for instructions to create a hashed password. An empty string is not marshalled, because it is not a valid value. + maxLength: 106 + minLength: 1 type: string name: description: Name specifies the user name. + maxLength: 256 type: string sshAuthorizedKeys: description: |- @@ -571,17 +608,22 @@ spec: machine. Use the corresponding private SSH keys to authenticate. See SSH documentation for instructions to create a key pair. items: + maxLength: 256 type: string + maxItems: 32 type: array sudo: description: |- Sudo is a sudo user specification, formatted as described in the sudo documentation. An empty string is not marshalled, because it is not a valid value. + maxLength: 1024 + minLength: 1 type: string required: - name type: object + maxItems: 32 type: array type: object type: object diff --git a/api/v1alpha1/crds/caren.nutanix.com_dockerworkernodeconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_dockerworkernodeconfigs.yaml index f409ed335..fa6e775a6 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_dockerworkernodeconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_dockerworkernodeconfigs.yaml @@ -65,6 +65,8 @@ spec: properties: customImage: description: Custom OCI image for control plane and worker Nodes. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*(:[\w][\w.-]{0,127})?(@[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][0-9A-Fa-f]{32,})?$ type: string type: object @@ -106,14 +108,18 @@ spec: type: string key: description: The taint key to be applied to a node. + maxLength: 253 type: string value: description: The taint value corresponding to the taint key. + maxLength: 63 + minLength: 1 type: string required: - effect - key type: object + maxItems: 32 type: array type: object type: object diff --git a/api/v1alpha1/crds/caren.nutanix.com_genericclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_genericclusterconfigs.yaml index 93abf1486..6829b2684 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_genericclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_genericclusterconfigs.yaml @@ -33,8 +33,10 @@ spec: description: Extra Subject Alternative Names for the API Server signing cert. items: + maxLength: 253 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + maxItems: 100 type: array uniqueItems: true kind: @@ -66,11 +68,15 @@ spec: repository: description: Repository is used to override the image repository to pull from. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string tag: description: Tag is used to override the default image tag. + maxLength: 128 + minLength: 1 pattern: ^[\w][\w.-]{0,127}$ type: string type: object @@ -104,10 +110,14 @@ spec: repository: description: Repository is used to override the image repository to pull from. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string tag: description: Tag is used to override the default image tag. + maxLength: 128 + minLength: 1 pattern: ^[\w][\w.-]{0,127}$ type: string type: object @@ -130,6 +140,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -160,6 +171,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -174,6 +186,7 @@ spec: required: - url type: object + maxItems: 32 type: array kubeProxy: description: KubeProxy defines the configuration for kube-proxy. @@ -193,6 +206,8 @@ spec: type: object kubernetesImageRepository: description: Sets the Kubernetes image repository used for the KubeadmControlPlane. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string ntp: @@ -202,7 +217,9 @@ spec: description: Servers is a list of NTP servers to use for time synchronization. items: + maxLength: 253 type: string + maxItems: 16 minItems: 1 type: array required: @@ -218,13 +235,20 @@ spec: Default values: localhost,127.0.0.1,,,kubernetes ,kubernetes.default,.svc,.svc. items: + maxLength: 253 + minLength: 1 type: string + maxItems: 128 type: array http: description: HTTP proxy value. + maxLength: 2048 + minLength: 1 type: string https: description: HTTPS proxy value. + maxLength: 2048 + minLength: 1 type: string type: object users: @@ -237,9 +261,12 @@ spec: by the crypt(5) man page. See your distribution's documentation for instructions to create a hashed password. An empty string is not marshalled, because it is not a valid value. + maxLength: 106 + minLength: 1 type: string name: description: Name specifies the user name. + maxLength: 256 type: string sshAuthorizedKeys: description: |- @@ -247,17 +274,22 @@ spec: machine. Use the corresponding private SSH keys to authenticate. See SSH documentation for instructions to create a key pair. items: + maxLength: 256 type: string + maxItems: 32 type: array sudo: description: |- Sudo is a sudo user specification, formatted as described in the sudo documentation. An empty string is not marshalled, because it is not a valid value. + maxLength: 1024 + minLength: 1 type: string required: - name type: object + maxItems: 32 type: array type: object type: object diff --git a/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml index 3160bdcfd..a019c9a40 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml @@ -56,6 +56,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -116,6 +117,7 @@ spec: type: string name: description: Name is the name of resource being referenced. + maxLength: 253 minLength: 1 type: string required: @@ -146,6 +148,7 @@ spec: type: string storageClassConfig: description: Name of the default storage class config the specified default provider. + maxLength: 242 minLength: 1 type: string required: @@ -166,6 +169,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -178,7 +182,6 @@ spec: additionalProperties: properties: allowExpansion: - default: false description: If the storage class should allow volume expanding type: boolean parameters: @@ -276,6 +279,7 @@ spec: - end - start type: object + maxItems: 10 minItems: 1 type: array required: @@ -337,7 +341,9 @@ spec: failureDomains specifies a list of NutanixFailureDomains (by names) that the cluster uses to deploy its control-plane machines. items: + maxLength: 253 type: string + maxItems: 5 type: array x-kubernetes-list-type: set machineDetails: @@ -355,6 +361,7 @@ spec: description: value is the category value linked to the category key in PC type: string type: object + maxItems: 32 type: array bootType: description: Defines the boot type of the virtual machine. Only supports UEFI and Legacy @@ -402,6 +409,7 @@ spec: required: - type type: object + maxItems: 32 type: array image: description: |- @@ -497,6 +505,7 @@ spec: required: - type type: object + maxItems: 16 type: array systemDiskSize: description: |- @@ -544,14 +553,18 @@ spec: type: string key: description: The taint key to be applied to a node. + maxLength: 253 type: string value: description: The taint value corresponding to the taint key. + maxLength: 63 + minLength: 1 type: string required: - effect - key type: object + maxItems: 32 type: array type: object dns: @@ -568,10 +581,14 @@ spec: properties: repository: description: Repository is used to override the image repository to pull from. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string tag: description: Tag is used to override the default image tag. + maxLength: 128 + minLength: 1 pattern: ^[\w][\w.-]{0,127}$ type: string type: object @@ -604,10 +621,14 @@ spec: properties: repository: description: Repository is used to override the image repository to pull from. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string tag: description: Tag is used to override the default image tag. + maxLength: 128 + minLength: 1 pattern: ^[\w][\w.-]{0,127}$ type: string type: object @@ -620,8 +641,10 @@ spec: - 127.0.0.1 - 0.0.0.0 items: + maxLength: 253 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + maxItems: 100 type: array uniqueItems: true globalImageRegistryMirror: @@ -640,6 +663,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -670,6 +694,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -684,6 +709,7 @@ spec: required: - url type: object + maxItems: 32 type: array kubeProxy: description: KubeProxy defines the configuration for kube-proxy. @@ -703,6 +729,8 @@ spec: type: object kubernetesImageRepository: description: Sets the Kubernetes image repository used for the KubeadmControlPlane. + maxLength: 2048 + minLength: 1 pattern: ^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*$ type: string ntp: @@ -711,7 +739,9 @@ spec: servers: description: Servers is a list of NTP servers to use for time synchronization. items: + maxLength: 253 type: string + maxItems: 16 minItems: 1 type: array required: @@ -727,6 +757,7 @@ spec: properties: host: description: The hostname on which the API server is serving. + maxLength: 253 minLength: 1 type: string port: @@ -746,6 +777,7 @@ spec: The virtual IP on which the API server is serving. If left empty, the value from controlPlaneEndpoint.host will be used. format: ipv4 + minLength: 1 type: string port: description: |- @@ -776,6 +808,8 @@ spec: the certificate for a Prism Central that uses certificates that were issued by a non-publicly trusted RootCA. The trust bundle is added to the cert pool used to authenticate the TLS connection to the Prism Central. format: byte + maxLength: 1048576 + minLength: 1 type: string credentials: description: A reference to the Secret for credential information for the target Prism Central instance. @@ -787,6 +821,7 @@ spec: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + maxLength: 253 minLength: 1 type: string required: @@ -821,13 +856,20 @@ spec: Default values: localhost,127.0.0.1,,,kubernetes ,kubernetes.default,.svc,.svc. items: + maxLength: 253 + minLength: 1 type: string + maxItems: 128 type: array http: description: HTTP proxy value. + maxLength: 2048 + minLength: 1 type: string https: description: HTTPS proxy value. + maxLength: 2048 + minLength: 1 type: string type: object users: @@ -840,9 +882,12 @@ spec: by the crypt(5) man page. See your distribution's documentation for instructions to create a hashed password. An empty string is not marshalled, because it is not a valid value. + maxLength: 106 + minLength: 1 type: string name: description: Name specifies the user name. + maxLength: 256 type: string sshAuthorizedKeys: description: |- @@ -850,17 +895,22 @@ spec: machine. Use the corresponding private SSH keys to authenticate. See SSH documentation for instructions to create a key pair. items: + maxLength: 256 type: string + maxItems: 32 type: array sudo: description: |- Sudo is a sudo user specification, formatted as described in the sudo documentation. An empty string is not marshalled, because it is not a valid value. + maxLength: 1024 + minLength: 1 type: string required: - name type: object + maxItems: 32 type: array type: object type: object diff --git a/api/v1alpha1/crds/caren.nutanix.com_nutanixworkernodeconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_nutanixworkernodeconfigs.yaml index 77a0acab3..d7093c561 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_nutanixworkernodeconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_nutanixworkernodeconfigs.yaml @@ -75,6 +75,7 @@ spec: description: value is the category value linked to the category key in PC type: string type: object + maxItems: 32 type: array bootType: description: Defines the boot type of the virtual machine. Only supports UEFI and Legacy @@ -122,6 +123,7 @@ spec: required: - type type: object + maxItems: 32 type: array image: description: |- @@ -217,6 +219,7 @@ spec: required: - type type: object + maxItems: 16 type: array systemDiskSize: description: |- @@ -264,14 +267,18 @@ spec: type: string key: description: The taint key to be applied to a node. + maxLength: 253 type: string value: description: The taint value corresponding to the taint key. + maxLength: 63 + minLength: 1 type: string required: - effect - key type: object + maxItems: 32 type: array type: object type: object diff --git a/api/v1alpha1/docker_node_types.go b/api/v1alpha1/docker_node_types.go index d34e3f81b..8c4bef90d 100644 --- a/api/v1alpha1/docker_node_types.go +++ b/api/v1alpha1/docker_node_types.go @@ -7,5 +7,7 @@ type DockerNodeSpec struct { // Custom OCI image for control plane and worker Nodes. // +kubebuilder:validation:Optional // +kubebuilder:validation:Pattern=`^((?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*|\[(?:[a-fA-F0-9:]+)\])(:[0-9]+)?/)?[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*(/[a-z0-9]+((?:[._]|__|[-]+)[a-z0-9]+)*)*(:[\w][\w.-]{0,127})?(@[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][0-9A-Fa-f]{32,})?$` - CustomImage *string `json:"customImage,omitempty"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=2048 + CustomImage string `json:"customImage,omitempty"` } diff --git a/api/v1alpha1/http_proxy.go b/api/v1alpha1/http_proxy.go index 3c910dc64..6a5b5f1a0 100644 --- a/api/v1alpha1/http_proxy.go +++ b/api/v1alpha1/http_proxy.go @@ -20,10 +20,14 @@ const ( type HTTPProxy struct { // HTTP proxy value. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=2048 HTTP string `json:"http,omitempty"` // HTTPS proxy value. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=2048 HTTPS string `json:"https,omitempty"` // AdditionalNo Proxy list that will be added to the automatically calculated @@ -31,6 +35,9 @@ type HTTPProxy struct { // Default values: localhost,127.0.0.1,,,kubernetes // ,kubernetes.default,.svc,.svc. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=128 + // +kubebuilder:validation:items:MinLength=1 + // +kubebuilder:validation:items:MaxLength=253 AdditionalNo []string `json:"additionalNo,omitempty"` } diff --git a/api/v1alpha1/nodeconfig_types.go b/api/v1alpha1/nodeconfig_types.go index 8fff34b84..f7235eb29 100644 --- a/api/v1alpha1/nodeconfig_types.go +++ b/api/v1alpha1/nodeconfig_types.go @@ -37,7 +37,7 @@ type AWSWorkerNodeConfig struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +kubebuilder:validation:Optional - Spec AWSWorkerNodeConfigSpec `json:"spec,omitempty"` + Spec *AWSWorkerNodeConfigSpec `json:"spec,omitempty"` } func (s AWSWorkerNodeConfig) VariableSchema() clusterv1.VariableSchema { //nolint:gocritic,lll // Passed by value for no potential side-effect. @@ -62,7 +62,7 @@ type DockerWorkerNodeConfig struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +kubebuilder:validation:Optional - Spec DockerControlPlaneSpec `json:"spec,omitempty"` + Spec *DockerControlPlaneSpec `json:"spec,omitempty"` } func (s DockerWorkerNodeConfig) VariableSchema() clusterv1.VariableSchema { //nolint:gocritic,lll // Passed by value for no potential side-effect. @@ -87,7 +87,7 @@ type NutanixWorkerNodeConfig struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +kubebuilder:validation:Optional - Spec NutanixWorkerNodeConfigSpec `json:"spec,omitempty"` + Spec *NutanixWorkerNodeConfigSpec `json:"spec,omitempty"` } func (s NutanixWorkerNodeConfig) VariableSchema() clusterv1.VariableSchema { //nolint:gocritic,lll // Passed by value for no potential side-effect. @@ -105,6 +105,7 @@ type NutanixWorkerNodeConfigSpec struct { type GenericNodeSpec struct { // Taints specifies the taints the Node API object should be registered with. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=32 Taints []Taint `json:"taints,omitempty"` // NodeRegistration holds fields that relate to registering the new control-plane node to the cluster. @@ -118,10 +119,13 @@ type GenericNodeSpec struct { type Taint struct { // The taint key to be applied to a node. // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength=253 Key string `json:"key"` // The taint value corresponding to the taint key. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 Value string `json:"value,omitempty"` // The effect of the taint on pods that do not tolerate the taint. diff --git a/api/v1alpha1/nutanix_clusterconfig_types.go b/api/v1alpha1/nutanix_clusterconfig_types.go index 83f0cd325..56350c328 100644 --- a/api/v1alpha1/nutanix_clusterconfig_types.go +++ b/api/v1alpha1/nutanix_clusterconfig_types.go @@ -35,13 +35,15 @@ type NutanixPrismCentralEndpointSpec struct { // use insecure connection to Prism Central endpoint // +kubebuilder:validation:Optional - Insecure bool `json:"insecure"` + Insecure bool `json:"insecure,omitempty"` // A base64 PEM encoded x509 cert for the RootCA that was used to create // the certificate for a Prism Central that uses certificates that were issued by a non-publicly trusted RootCA. // The trust bundle is added to the cert pool used to authenticate the TLS connection to the Prism Central. // +kubebuilder:validation:Optional // +kubebuilder:validation:Format=`byte` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1048576 AdditionalTrustBundle string `json:"additionalTrustBundle,omitempty"` // A reference to the Secret for credential information for the target Prism Central instance. diff --git a/api/v1alpha1/nutanix_node_types.go b/api/v1alpha1/nutanix_node_types.go index c26e243fb..e1b0d43bd 100644 --- a/api/v1alpha1/nutanix_node_types.go +++ b/api/v1alpha1/nutanix_node_types.go @@ -10,16 +10,20 @@ import ( ) type NutanixControlPlaneNodeSpec struct { + // +kubebuilder:validation:Required MachineDetails NutanixMachineDetails `json:"machineDetails"` // failureDomains specifies a list of NutanixFailureDomains (by names) // that the cluster uses to deploy its control-plane machines. // +listType=set - // +optional + // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=5 + // +kubebuilder:validation:items:MaxLength=253 FailureDomains []string `json:"failureDomains,omitempty"` } type NutanixWorkerNodeSpec struct { + // +kubebuilder:validation:Required MachineDetails NutanixMachineDetails `json:"machineDetails"` } @@ -40,35 +44,33 @@ type NutanixMachineDetails struct { // image identifies the image uploaded to Prism Central (PC). The identifier // (uuid or name) can be obtained from the console or API. // +kubebuilder:validation:Optional - // +optional Image *capxv1.NutanixResourceIdentifier `json:"image,omitempty"` // imageLookup is a container that holds how to look up vm images for the cluster. // +kubebuilder:validation:Optional - // +optional ImageLookup *capxv1.NutanixImageLookup `json:"imageLookup,omitempty"` // cluster identifies the Prism Element in which the machine will be created. // The identifier (uuid or name) can be obtained from the console or API. // +kubebuilder:validation:Optional - // +optional Cluster *capxv1.NutanixResourceIdentifier `json:"cluster,omitempty"` // subnet identifies the network subnet to use for the machine. // The identifier (uuid or name) can be obtained from the console or API. // +kubebuilder:validation:Optional - // +optional + // +kubebuilder:validation:MaxItems=16 Subnets []capxv1.NutanixResourceIdentifier `json:"subnets,omitempty"` // List of categories that need to be added to the machines. Categories must already // exist in Prism Central. One category key can have more than one value. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=32 AdditionalCategories []capxv1.NutanixCategoryIdentifier `json:"additionalCategories,omitempty"` // Defines the boot type of the virtual machine. Only supports UEFI and Legacy // +kubebuilder:validation:Optional // +kubebuilder:validation:Enum:=legacy;uefi - BootType capxv1.NutanixBootType `json:"bootType"` + BootType capxv1.NutanixBootType `json:"bootType,omitempty"` // systemDiskSize is size (in Quantity format) of the system disk of the VM // The minimum systemDiskSize is 20Gi bytes @@ -82,6 +84,7 @@ type NutanixMachineDetails struct { // List of GPU devices that need to be added to the machines. // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=32 GPUs []capxv1.NutanixGPU `json:"gpus,omitempty"` } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 94fe6de30..a038f0a11 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -124,7 +124,11 @@ func (in *AWSClusterConfig) DeepCopyInto(out *AWSClusterConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(AWSClusterConfigSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSClusterConfig. @@ -329,7 +333,11 @@ func (in *AWSWorkerNodeConfig) DeepCopyInto(out *AWSWorkerNodeConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(AWSWorkerNodeConfigSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSWorkerNodeConfig. @@ -484,11 +492,6 @@ func (in *CCM) DeepCopyInto(out *CCM) { *out = new(CCMCredentials) **out = **in } - if in.Strategy != nil { - in, out := &in.Strategy, &out.Strategy - *out = new(AddonStrategy) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CCM. @@ -520,11 +523,6 @@ func (in *CCMCredentials) DeepCopy() *CCMCredentials { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CNI) DeepCopyInto(out *CNI) { *out = *in - if in.Strategy != nil { - in, out := &in.Strategy, &out.Strategy - *out = new(AddonStrategy) - **out = **in - } in.AddonConfig.DeepCopyInto(&out.AddonConfig) } @@ -564,11 +562,6 @@ func (in *CSIProvider) DeepCopyInto(out *CSIProvider) { (*out)[key] = *val.DeepCopy() } } - if in.Strategy != nil { - in, out := &in.Strategy, &out.Strategy - *out = new(AddonStrategy) - **out = **in - } if in.Credentials != nil { in, out := &in.Credentials, &out.Credentials *out = new(CSICredentials) @@ -589,11 +582,6 @@ func (in *CSIProvider) DeepCopy() *CSIProvider { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterAutoscaler) DeepCopyInto(out *ClusterAutoscaler) { *out = *in - if in.Strategy != nil { - in, out := &in.Strategy, &out.Strategy - *out = new(AddonStrategy) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterAutoscaler. @@ -728,7 +716,7 @@ func (in *DockerAddons) DeepCopyInto(out *DockerAddons) { if in.COSI != nil { in, out := &in.COSI, &out.COSI *out = new(DockerCOSI) - (*in).DeepCopyInto(*out) + **out = **in } } @@ -745,7 +733,7 @@ func (in *DockerAddons) DeepCopy() *DockerAddons { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DockerCOSI) DeepCopyInto(out *DockerCOSI) { *out = *in - in.GenericCOSI.DeepCopyInto(&out.GenericCOSI) + out.GenericCOSI = in.GenericCOSI } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DockerCOSI. @@ -796,7 +784,11 @@ func (in *DockerClusterConfig) DeepCopyInto(out *DockerClusterConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(DockerClusterConfigSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DockerClusterConfig. @@ -859,7 +851,7 @@ func (in *DockerControlPlaneSpec) DeepCopyInto(out *DockerControlPlaneSpec) { if in.Docker != nil { in, out := &in.Docker, &out.Docker *out = new(DockerNodeSpec) - (*in).DeepCopyInto(*out) + **out = **in } in.GenericControlPlaneSpec.DeepCopyInto(&out.GenericControlPlaneSpec) in.GenericNodeSpec.DeepCopyInto(&out.GenericNodeSpec) @@ -878,11 +870,6 @@ func (in *DockerControlPlaneSpec) DeepCopy() *DockerControlPlaneSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DockerNodeSpec) DeepCopyInto(out *DockerNodeSpec) { *out = *in - if in.CustomImage != nil { - in, out := &in.CustomImage, &out.CustomImage - *out = new(string) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DockerNodeSpec. @@ -915,7 +902,11 @@ func (in *DockerWorkerNodeConfig) DeepCopyInto(out *DockerWorkerNodeConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(DockerControlPlaneSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DockerWorkerNodeConfig. @@ -942,7 +933,7 @@ func (in *DockerWorkerNodeConfigSpec) DeepCopyInto(out *DockerWorkerNodeConfigSp if in.Docker != nil { in, out := &in.Docker, &out.Docker *out = new(DockerNodeSpec) - (*in).DeepCopyInto(*out) + **out = **in } in.GenericNodeSpec.DeepCopyInto(&out.GenericNodeSpec) } @@ -1035,12 +1026,12 @@ func (in *GenericAddons) DeepCopyInto(out *GenericAddons) { if in.NFD != nil { in, out := &in.NFD, &out.NFD *out = new(NFD) - (*in).DeepCopyInto(*out) + **out = **in } if in.ClusterAutoscaler != nil { in, out := &in.ClusterAutoscaler, &out.ClusterAutoscaler *out = new(ClusterAutoscaler) - (*in).DeepCopyInto(*out) + **out = **in } if in.CCM != nil { in, out := &in.CCM, &out.CCM @@ -1072,11 +1063,6 @@ func (in *GenericAddons) DeepCopy() *GenericAddons { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GenericCOSI) DeepCopyInto(out *GenericCOSI) { *out = *in - if in.Strategy != nil { - in, out := &in.Strategy, &out.Strategy - *out = new(AddonStrategy) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericCOSI. @@ -1096,7 +1082,7 @@ func (in *GenericCSI) DeepCopyInto(out *GenericCSI) { if in.SnapshotController != nil { in, out := &in.SnapshotController, &out.SnapshotController *out = new(SnapshotController) - (*in).DeepCopyInto(*out) + **out = **in } } @@ -1115,7 +1101,11 @@ func (in *GenericClusterConfig) DeepCopyInto(out *GenericClusterConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(GenericClusterConfigSpec) + (*in).DeepCopyInto(*out) + } if in.ExtraAPIServerCertSANs != nil { in, out := &in.ExtraAPIServerCertSANs, &out.ExtraAPIServerCertSANs *out = make([]string, len(*in)) @@ -1144,11 +1134,6 @@ func (in *GenericClusterConfig) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GenericClusterConfigSpec) DeepCopyInto(out *GenericClusterConfigSpec) { *out = *in - if in.KubernetesImageRepository != nil { - in, out := &in.KubernetesImageRepository, &out.KubernetesImageRepository - *out = new(string) - **out = **in - } if in.Etcd != nil { in, out := &in.Etcd, &out.Etcd *out = new(Etcd) @@ -1363,11 +1348,6 @@ func (in *LocalObjectReference) DeepCopy() *LocalObjectReference { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NFD) DeepCopyInto(out *NFD) { *out = *in - if in.Strategy != nil { - in, out := &in.Strategy, &out.Strategy - *out = new(AddonStrategy) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NFD. @@ -1432,7 +1412,7 @@ func (in *NutanixAddons) DeepCopyInto(out *NutanixAddons) { if in.COSI != nil { in, out := &in.COSI, &out.COSI *out = new(NutanixCOSI) - (*in).DeepCopyInto(*out) + **out = **in } } @@ -1449,7 +1429,7 @@ func (in *NutanixAddons) DeepCopy() *NutanixAddons { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NutanixCOSI) DeepCopyInto(out *NutanixCOSI) { *out = *in - in.GenericCOSI.DeepCopyInto(&out.GenericCOSI) + out.GenericCOSI = in.GenericCOSI } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixCOSI. @@ -1500,7 +1480,11 @@ func (in *NutanixClusterConfig) DeepCopyInto(out *NutanixClusterConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(NutanixClusterConfigSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixClusterConfig. @@ -1710,7 +1694,11 @@ func (in *NutanixWorkerNodeConfig) DeepCopyInto(out *NutanixWorkerNodeConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(NutanixWorkerNodeConfigSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixWorkerNodeConfig. @@ -1920,11 +1908,6 @@ func (in *ServiceLoadBalancerConfiguration) DeepCopy() *ServiceLoadBalancerConfi // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SnapshotController) DeepCopyInto(out *SnapshotController) { *out = *in - if in.Strategy != nil { - in, out := &in.Strategy, &out.Strategy - *out = new(AddonStrategy) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotController. diff --git a/devbox.json b/devbox.json index 32c5c3add..39bda4c1b 100644 --- a/devbox.json +++ b/devbox.json @@ -28,6 +28,7 @@ "kubernetes-controller-tools@latest", "kustomize@latest", "pre-commit@latest", + "reviewdog@latest", "rsync@latest", "setup-envtest@latest", "shfmt@latest", diff --git a/devbox.lock b/devbox.lock index cba1fd3dc..8d1a05e09 100644 --- a/devbox.lock +++ b/devbox.lock @@ -1577,6 +1577,54 @@ } } }, + "reviewdog@latest": { + "last_modified": "2025-06-20T02:24:11Z", + "resolved": "github:NixOS/nixpkgs/076e8c6678d8c54204abcb4b1b14c366835a58bb#reviewdog", + "source": "devbox-search", + "version": "0.20.3", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/3yyxphpj15k63glrjhks2gkpj0ni9snf-reviewdog-0.20.3", + "default": true + } + ], + "store_path": "/nix/store/3yyxphpj15k63glrjhks2gkpj0ni9snf-reviewdog-0.20.3" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/drhvxi0lcpa5drqvh3asqll3kak7g2ja-reviewdog-0.20.3", + "default": true + } + ], + "store_path": "/nix/store/drhvxi0lcpa5drqvh3asqll3kak7g2ja-reviewdog-0.20.3" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/i6cknyqzrvzzpzjh9n267y4b15zdxc6n-reviewdog-0.20.3", + "default": true + } + ], + "store_path": "/nix/store/i6cknyqzrvzzpzjh9n267y4b15zdxc6n-reviewdog-0.20.3" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/15vfbrwqpi0z4d97790vs7cr5ysz6srd-reviewdog-0.20.3", + "default": true + } + ], + "store_path": "/nix/store/15vfbrwqpi0z4d97790vs7cr5ysz6srd-reviewdog-0.20.3" + } + } + }, "rsync@latest": { "last_modified": "2025-07-13T22:45:35Z", "resolved": "github:NixOS/nixpkgs/a421ac6595024edcfbb1ef950a3712b89161c359#rsync", diff --git a/docs/content/contributing/linting.md b/docs/content/contributing/linting.md new file mode 100644 index 000000000..99058df1f --- /dev/null +++ b/docs/content/contributing/linting.md @@ -0,0 +1,36 @@ ++++ +title = "Linting" +icon = "fa-solid fa-magnifying-glass" ++++ + +This project uses [`golangci-lint`][golangci-lint] to both lint and format the CAREN sourcecode. `golangci-lint` is +installed via devbox, just as every other development tool that this project uses. The `golangci-lint` configuration +includes a custom linter, [`kube-api-linter`][kube-api-linter], integrated as a `golangci-lint` [module plugin]. + +## Installing `golangci-lint` with KAL + +To install the customized linter binary into `hack/tools/golangci-lint-kube-api-linter`, run: + +```bash +make hack/tools/golangci-lint-kube-api-linter +``` + +## Integrating with vscode + +One the customized linter has been installed above, `vscode` can be configured to run this linter. Add the followin +configuration to `.vscode/settings.json`: + +```json + "go.lintTool": "golangci-lint", + "go.lintFlags": ["--path-mode=abs"], + "go.formatTool": "custom", + "go.alternateTools": { + "customFormatter": "golangci-lint", + "golangci-lint": "${workspaceFolder}/hack/tools/golangci-lint-kube-api-linter" + }, + "go.formatFlags": ["fmt", "--stdin"] +``` + +[golangci-lint]: https://golangci-lint.run/ +[kube-api-linter]: https://github.com/kubernetes-sigs/kube-api-linter/ +[module plugin]: https://golangci-lint.run/plugins/module-plugins/ diff --git a/hack/tools/.custom-gcl.yml b/hack/tools/.custom-gcl.yml new file mode 100644 index 000000000..d0d7b951e --- /dev/null +++ b/hack/tools/.custom-gcl.yml @@ -0,0 +1,8 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +version: v2.2.2 +name: golangci-lint-kube-api-linter +plugins: +- module: 'sigs.k8s.io/kube-api-linter' + version: v0.0.0-20250710131328-b566fe88b732 diff --git a/make/go.mk b/make/go.mk index 9b25cf30c..6183d374e 100644 --- a/make/go.mk +++ b/make/go.mk @@ -125,6 +125,7 @@ endif endif GOLANGCI_CONFIG_FILE ?= $(wildcard $(REPO_ROOT)/.golangci.y*ml) +GOLANGCI_KAL_CONFIG_FILE ?= $(wildcard $(REPO_ROOT)/.golangci-kal.y*ml) .PHONY:fmt fmt: ## Runs golangci-lint fmt for all modules in repository @@ -152,8 +153,12 @@ endif .PHONY: lint.% lint.%: ## Runs golangci-lint run for a specific module -lint.%: fmt.% ; $(info $(M) linting $* module) - $(if $(filter-out root,$*),cd $* && )golangci-lint run --fix --config=$(GOLANGCI_CONFIG_FILE) +lint.%: hack/tools/golangci-lint-kube-api-linter fmt.% ; $(info $(M) linting $* module) + $(if $(filter-out root,$*),cd $* && )$(PWD)/hack/tools/golangci-lint-kube-api-linter run --fix --config=$(GOLANGCI_CONFIG_FILE) + +hack/tools/golangci-lint-kube-api-linter: hack/tools/.custom-gcl.yml +hack/tools/golangci-lint-kube-api-linter: ; $(info $(M) installing golangci-lint-kube-api-linter tool) + cd hack/tools && golangci-lint custom .PHONY: mod-tidy mod-tidy: ## Run go mod tidy for all modules diff --git a/pkg/handlers/aws/mutation/ami/variables_test.go b/pkg/handlers/aws/mutation/ami/variables_test.go index 58769fef3..4e63d146d 100644 --- a/pkg/handlers/aws/mutation/ami/variables_test.go +++ b/pkg/handlers/aws/mutation/ami/variables_test.go @@ -31,7 +31,7 @@ func TestVariableValidation(t *testing.T) { Lookup: &v1alpha1.AMILookup{ Format: "capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-*", BaseOS: "rhel-8.4", - Org: "12345678", + Org: "o-0o-0123456789", }, }, }, diff --git a/pkg/handlers/aws/mutation/iaminstanceprofile/variables_test.go b/pkg/handlers/aws/mutation/iaminstanceprofile/variables_test.go index 48db69506..383626830 100644 --- a/pkg/handlers/aws/mutation/iaminstanceprofile/variables_test.go +++ b/pkg/handlers/aws/mutation/iaminstanceprofile/variables_test.go @@ -31,7 +31,7 @@ func TestVariableValidation(t *testing.T) { Lookup: &v1alpha1.AMILookup{ Format: "capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-*", BaseOS: "rhel-8.4", - Org: "12345678", + Org: "o-0123456789", }, }, }, diff --git a/pkg/handlers/aws/mutation/region/variables_test.go b/pkg/handlers/aws/mutation/region/variables_test.go index 24e597808..8b4991cf0 100644 --- a/pkg/handlers/aws/mutation/region/variables_test.go +++ b/pkg/handlers/aws/mutation/region/variables_test.go @@ -24,7 +24,7 @@ func TestVariableValidation(t *testing.T) { Name: "specified region", Vals: v1alpha1.AWSClusterConfigSpec{ AWS: &v1alpha1.AWSSpec{ - Region: ptr.To(v1alpha1.Region("a-specified-region")), + Region: ptr.To(v1alpha1.Region("specified")), }, }, }, diff --git a/pkg/handlers/docker/mutation/customimage/variables_test.go b/pkg/handlers/docker/mutation/customimage/variables_test.go index 41d34d9de..917f8ca14 100644 --- a/pkg/handlers/docker/mutation/customimage/variables_test.go +++ b/pkg/handlers/docker/mutation/customimage/variables_test.go @@ -25,7 +25,7 @@ func TestVariableValidation(t *testing.T) { Vals: v1alpha1.DockerClusterConfigSpec{ ControlPlane: &v1alpha1.DockerControlPlaneSpec{ Docker: &v1alpha1.DockerNodeSpec{ - CustomImage: ptr.To("docker.io/some/image:v2.3.4"), + CustomImage: "docker.io/some/image:v2.3.4", }, }, }, @@ -35,7 +35,7 @@ func TestVariableValidation(t *testing.T) { Vals: v1alpha1.DockerClusterConfigSpec{ ControlPlane: &v1alpha1.DockerControlPlaneSpec{ Docker: &v1alpha1.DockerNodeSpec{ - CustomImage: ptr.To("this.is.not.valid?"), + CustomImage: "this.is.not.valid?", }, }, }, diff --git a/pkg/handlers/generic/lifecycle/ccm/aws/handler.go b/pkg/handlers/generic/lifecycle/ccm/aws/handler.go index 128cef7e0..6c51c2c1f 100644 --- a/pkg/handlers/generic/lifecycle/ccm/aws/handler.go +++ b/pkg/handlers/generic/lifecycle/ccm/aws/handler.go @@ -10,7 +10,6 @@ import ( "github.com/go-logr/logr" "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -93,7 +92,7 @@ func (a *AWSCCM) Apply( } var strategy addons.Applier - switch ptr.Deref(clusterConfig.Addons.CCM.Strategy, "") { + switch clusterConfig.Addons.CCM.Strategy { case v1alpha1.AddonStrategyHelmAddon: helmChart, err := a.helmChartInfoGetter.For(ctx, log, config.AWSCCM) if err != nil { @@ -114,7 +113,7 @@ func (a *AWSCCM) Apply( case "": return fmt.Errorf("strategy not specified for AWS CCM") default: - return fmt.Errorf("strategy %s not implemented", *clusterConfig.Addons.CCM.Strategy) + return fmt.Errorf("strategy %s not implemented", clusterConfig.Addons.CCM.Strategy) } if err := strategy.Apply(ctx, cluster, a.config.DefaultsNamespace(), log); err != nil { diff --git a/pkg/handlers/generic/lifecycle/clusterautoscaler/handler.go b/pkg/handlers/generic/lifecycle/clusterautoscaler/handler.go index d9c558464..7dfd1e86d 100644 --- a/pkg/handlers/generic/lifecycle/clusterautoscaler/handler.go +++ b/pkg/handlers/generic/lifecycle/clusterautoscaler/handler.go @@ -9,7 +9,6 @@ import ( "github.com/go-logr/logr" "github.com/spf13/pflag" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" ctrl "sigs.k8s.io/controller-runtime" @@ -136,7 +135,7 @@ func (n *DefaultClusterAutoscaler) apply( } var strategy addonStrategy - switch ptr.Deref(caVar.Strategy, "") { + switch caVar.Strategy { case v1alpha1.AddonStrategyClusterResourceSet: strategy = crsStrategy{ config: n.config.crsConfig, @@ -172,7 +171,7 @@ func (n *DefaultClusterAutoscaler) apply( default: resp.SetStatus(runtimehooksv1.ResponseStatusFailure) resp.SetMessage( - fmt.Sprintf("unknown cluster-autoscaler addon deployment strategy %q", *caVar.Strategy), + fmt.Sprintf("unknown cluster-autoscaler addon deployment strategy %q", caVar.Strategy), ) return } @@ -217,7 +216,7 @@ func (n *DefaultClusterAutoscaler) BeforeClusterDelete( } var strategy addonStrategy - switch ptr.Deref(caVar.Strategy, "") { + switch caVar.Strategy { case v1alpha1.AddonStrategyClusterResourceSet: strategy = crsStrategy{ config: n.config.crsConfig, @@ -235,7 +234,7 @@ func (n *DefaultClusterAutoscaler) BeforeClusterDelete( default: resp.SetStatus(runtimehooksv1.ResponseStatusFailure) resp.SetMessage( - fmt.Sprintf("unknown cluster-autoscaler addon deployment strategy %q", *caVar.Strategy), + fmt.Sprintf("unknown cluster-autoscaler addon deployment strategy %q", caVar.Strategy), ) return } diff --git a/pkg/handlers/generic/lifecycle/clusterautoscaler/variables_test.go b/pkg/handlers/generic/lifecycle/clusterautoscaler/variables_test.go index e570cfd24..0a694ac4f 100644 --- a/pkg/handlers/generic/lifecycle/clusterautoscaler/variables_test.go +++ b/pkg/handlers/generic/lifecycle/clusterautoscaler/variables_test.go @@ -29,7 +29,7 @@ func TestVariableValidation_AWS(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To(v1alpha1.AddonStrategyClusterResourceSet), + Strategy: v1alpha1.AddonStrategyClusterResourceSet, }, }, }, @@ -41,7 +41,7 @@ func TestVariableValidation_AWS(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, }, }, }, @@ -53,7 +53,7 @@ func TestVariableValidation_AWS(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To[v1alpha1.AddonStrategy]("invalid-strategy"), + Strategy: v1alpha1.AddonStrategy("invalid-strategy"), }, }, }, @@ -76,7 +76,7 @@ func TestVariableValidation_Nutanix(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To(v1alpha1.AddonStrategyClusterResourceSet), + Strategy: v1alpha1.AddonStrategyClusterResourceSet, }, }, }, @@ -88,7 +88,7 @@ func TestVariableValidation_Nutanix(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, }, }, }, @@ -100,7 +100,7 @@ func TestVariableValidation_Nutanix(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To[v1alpha1.AddonStrategy]("invalid-strategy"), + Strategy: v1alpha1.AddonStrategy("invalid-strategy"), }, }, }, @@ -123,7 +123,7 @@ func TestVariableValidation_Docker(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To(v1alpha1.AddonStrategyClusterResourceSet), + Strategy: v1alpha1.AddonStrategyClusterResourceSet, }, }, }, @@ -135,7 +135,7 @@ func TestVariableValidation_Docker(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, }, }, }, @@ -147,7 +147,7 @@ func TestVariableValidation_Docker(t *testing.T) { Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ ClusterAutoscaler: &v1alpha1.ClusterAutoscaler{ - Strategy: ptr.To[v1alpha1.AddonStrategy]("invalid-strategy"), + Strategy: v1alpha1.AddonStrategy("invalid-strategy"), }, }, }, diff --git a/pkg/handlers/generic/lifecycle/cni/calico/handler.go b/pkg/handlers/generic/lifecycle/cni/calico/handler.go index 2ca181dce..3ee409088 100644 --- a/pkg/handlers/generic/lifecycle/cni/calico/handler.go +++ b/pkg/handlers/generic/lifecycle/cni/calico/handler.go @@ -9,7 +9,6 @@ import ( "github.com/go-logr/logr" "github.com/spf13/pflag" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" ctrl "sigs.k8s.io/controller-runtime" @@ -145,7 +144,7 @@ func (c *CalicoCNI) apply( } var strategy addonStrategy - switch ptr.Deref(cniVar.Strategy, "") { + switch cniVar.Strategy { case v1alpha1.AddonStrategyClusterResourceSet: strategy = crsStrategy{ config: c.config.crsConfig, @@ -179,7 +178,7 @@ func (c *CalicoCNI) apply( resp.SetMessage("strategy not specified for CNI addon") default: resp.SetStatus(runtimehooksv1.ResponseStatusFailure) - resp.SetMessage(fmt.Sprintf("unknown CNI addon deployment strategy %q", *cniVar.Strategy)) + resp.SetMessage(fmt.Sprintf("unknown CNI addon deployment strategy %q", cniVar.Strategy)) return } diff --git a/pkg/handlers/generic/lifecycle/cni/cilium/handler.go b/pkg/handlers/generic/lifecycle/cni/cilium/handler.go index 9a19ad971..ff9d14cc2 100644 --- a/pkg/handlers/generic/lifecycle/cni/cilium/handler.go +++ b/pkg/handlers/generic/lifecycle/cni/cilium/handler.go @@ -10,7 +10,6 @@ import ( "github.com/spf13/pflag" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" ctrl "sigs.k8s.io/controller-runtime" @@ -158,7 +157,7 @@ func (c *CiliumCNI) apply( targetNamespace := c.config.DefaultsNamespace() var strategy addons.Applier - switch ptr.Deref(cniVar.Strategy, "") { + switch cniVar.Strategy { case v1alpha1.AddonStrategyClusterResourceSet: strategy = crsStrategy{ config: c.config.crsConfig, @@ -228,7 +227,7 @@ func (c *CiliumCNI) apply( resp.SetMessage("strategy not specified for Cilium CNI addon") default: resp.SetStatus(runtimehooksv1.ResponseStatusFailure) - resp.SetMessage(fmt.Sprintf("unknown CNI addon deployment strategy %q", *cniVar.Strategy)) + resp.SetMessage(fmt.Sprintf("unknown CNI addon deployment strategy %q", cniVar.Strategy)) return } diff --git a/pkg/handlers/generic/lifecycle/cni/variables_test.go b/pkg/handlers/generic/lifecycle/cni/variables_test.go index c7c13b0cf..2a6feceb0 100644 --- a/pkg/handlers/generic/lifecycle/cni/variables_test.go +++ b/pkg/handlers/generic/lifecycle/cni/variables_test.go @@ -23,7 +23,7 @@ var testDefs = []capitest.VariableTestDef{{ GenericAddons: v1alpha1.GenericAddons{ CNI: &v1alpha1.CNI{ Provider: v1alpha1.CNIProviderCalico, - Strategy: ptr.To(v1alpha1.AddonStrategyClusterResourceSet), + Strategy: v1alpha1.AddonStrategyClusterResourceSet, }, }, }, @@ -35,7 +35,7 @@ var testDefs = []capitest.VariableTestDef{{ GenericAddons: v1alpha1.GenericAddons{ CNI: &v1alpha1.CNI{ Provider: v1alpha1.CNIProviderCalico, - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, }, }, }, @@ -47,7 +47,7 @@ var testDefs = []capitest.VariableTestDef{{ GenericAddons: v1alpha1.GenericAddons{ CNI: &v1alpha1.CNI{ Provider: v1alpha1.CNIProviderCilium, - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, AddonConfig: v1alpha1.AddonConfig{ Values: &v1alpha1.AddonValues{ SourceRef: &v1alpha1.ValuesReference{ @@ -67,7 +67,7 @@ var testDefs = []capitest.VariableTestDef{{ GenericAddons: v1alpha1.GenericAddons{ CNI: &v1alpha1.CNI{ Provider: "invalid-provider", - Strategy: ptr.To(v1alpha1.AddonStrategyClusterResourceSet), + Strategy: v1alpha1.AddonStrategyClusterResourceSet, }, }, }, @@ -80,7 +80,7 @@ var testDefs = []capitest.VariableTestDef{{ GenericAddons: v1alpha1.GenericAddons{ CNI: &v1alpha1.CNI{ Provider: v1alpha1.CNIProviderCalico, - Strategy: ptr.To[v1alpha1.AddonStrategy]("invalid-strategy"), + Strategy: v1alpha1.AddonStrategy("invalid-strategy"), }, }, }, diff --git a/pkg/handlers/generic/lifecycle/cosi/handler.go b/pkg/handlers/generic/lifecycle/cosi/handler.go index e186dd3c4..7713dcca1 100644 --- a/pkg/handlers/generic/lifecycle/cosi/handler.go +++ b/pkg/handlers/generic/lifecycle/cosi/handler.go @@ -8,7 +8,6 @@ import ( "fmt" "github.com/spf13/pflag" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" ctrl "sigs.k8s.io/controller-runtime" @@ -142,7 +141,7 @@ func (n *DefaultCOSIController) apply( } var strategy addons.Applier - switch ptr.Deref(cosiVar.Strategy, "") { + switch cosiVar.Strategy { case v1alpha1.AddonStrategyHelmAddon: helmChart, err := n.helmChartInfoGetter.For(ctx, log, config.COSIController) if err != nil { @@ -177,7 +176,7 @@ func (n *DefaultCOSIController) apply( return default: resp.SetStatus(runtimehooksv1.ResponseStatusFailure) - resp.SetMessage(fmt.Sprintf("unknown COSI addon deployment strategy %q", *cosiVar.Strategy)) + resp.SetMessage(fmt.Sprintf("unknown COSI addon deployment strategy %q", cosiVar.Strategy)) return } diff --git a/pkg/handlers/generic/lifecycle/cosi/variables_test.go b/pkg/handlers/generic/lifecycle/cosi/variables_test.go index c88c3a2d7..064787931 100644 --- a/pkg/handlers/generic/lifecycle/cosi/variables_test.go +++ b/pkg/handlers/generic/lifecycle/cosi/variables_test.go @@ -21,7 +21,7 @@ var testDefs = []capitest.VariableTestDef{{ Addons: &apivariables.Addons{ COSI: &apivariables.COSI{ GenericCOSI: v1alpha1.GenericCOSI{ - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, }, }, }, @@ -32,7 +32,7 @@ var testDefs = []capitest.VariableTestDef{{ Addons: &apivariables.Addons{ COSI: &apivariables.COSI{ GenericCOSI: v1alpha1.GenericCOSI{ - Strategy: ptr.To(v1alpha1.AddonStrategyClusterResourceSet), + Strategy: v1alpha1.AddonStrategyClusterResourceSet, }, }, }, @@ -44,7 +44,7 @@ var testDefs = []capitest.VariableTestDef{{ Addons: &apivariables.Addons{ COSI: &apivariables.COSI{ GenericCOSI: v1alpha1.GenericCOSI{ - Strategy: ptr.To[v1alpha1.AddonStrategy]("invalid-strategy"), + Strategy: v1alpha1.AddonStrategy("invalid-strategy"), }, }, }, diff --git a/pkg/handlers/generic/lifecycle/csi/awsebs/handler.go b/pkg/handlers/generic/lifecycle/csi/awsebs/handler.go index ffe182e7b..10abee8b1 100644 --- a/pkg/handlers/generic/lifecycle/csi/awsebs/handler.go +++ b/pkg/handlers/generic/lifecycle/csi/awsebs/handler.go @@ -10,7 +10,6 @@ import ( "github.com/go-logr/logr" "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -80,7 +79,7 @@ func (a *AWSEBS) Apply( log logr.Logger, ) error { var strategy addons.Applier - switch ptr.Deref(provider.Strategy, "") { + switch provider.Strategy { case v1alpha1.AddonStrategyHelmAddon: helmChart, err := a.helmChartInfoGetter.For(ctx, log, config.AWSEBSCSI) if err != nil { @@ -99,7 +98,7 @@ func (a *AWSEBS) Apply( case "": return fmt.Errorf("strategy not specified for AWS EBS CSI driver") default: - return fmt.Errorf("strategy %s not implemented", *provider.Strategy) + return fmt.Errorf("strategy %s not implemented", provider.Strategy) } if err := strategy.Apply(ctx, cluster, a.config.DefaultsNamespace(), log); err != nil { diff --git a/pkg/handlers/generic/lifecycle/csi/localpath/handler.go b/pkg/handlers/generic/lifecycle/csi/localpath/handler.go index 91212315a..75cbb928d 100644 --- a/pkg/handlers/generic/lifecycle/csi/localpath/handler.go +++ b/pkg/handlers/generic/lifecycle/csi/localpath/handler.go @@ -10,7 +10,6 @@ import ( "github.com/go-logr/logr" "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -76,7 +75,7 @@ func (l *LocalPathProvisionerCSI) Apply( log logr.Logger, ) error { var strategy addons.Applier - switch ptr.Deref(provider.Strategy, "") { + switch provider.Strategy { case v1alpha1.AddonStrategyHelmAddon: helmChart, err := l.helmChartInfoGetter.For(ctx, log, config.LocalPathProvisionerCSI) if err != nil { @@ -95,7 +94,7 @@ func (l *LocalPathProvisionerCSI) Apply( case "": return fmt.Errorf("strategy not provided for local-path CSI addon") default: - return fmt.Errorf("strategy %s not implemented", *provider.Strategy) + return fmt.Errorf("strategy %s not implemented", provider.Strategy) } if err := strategy.Apply(ctx, cluster, l.config.DefaultsNamespace(), log); err != nil { diff --git a/pkg/handlers/generic/lifecycle/csi/nutanix/handler.go b/pkg/handlers/generic/lifecycle/csi/nutanix/handler.go index 2a1752b22..8e9eed6de 100644 --- a/pkg/handlers/generic/lifecycle/csi/nutanix/handler.go +++ b/pkg/handlers/generic/lifecycle/csi/nutanix/handler.go @@ -10,7 +10,6 @@ import ( "github.com/go-logr/logr" "github.com/spf13/pflag" corev1 "k8s.io/api/core/v1" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -88,7 +87,7 @@ func (n *NutanixCSI) Apply( log logr.Logger, ) error { var strategy addons.Applier - switch ptr.Deref(provider.Strategy, "") { + switch provider.Strategy { case v1alpha1.AddonStrategyHelmAddon: helmChart, err := n.helmChartInfoGetter.For(ctx, log, config.NutanixStorageCSI) if err != nil { @@ -105,7 +104,7 @@ func (n *NutanixCSI) Apply( case "": return fmt.Errorf("strategy not provided for Nutanix CSI driver") default: - return fmt.Errorf("strategy %s not implemented", *provider.Strategy) + return fmt.Errorf("strategy %s not implemented", provider.Strategy) } if provider.Credentials != nil { diff --git a/pkg/handlers/generic/lifecycle/csi/snapshotcontroller/handler.go b/pkg/handlers/generic/lifecycle/csi/snapshotcontroller/handler.go index 56a92a71b..80afe8c60 100644 --- a/pkg/handlers/generic/lifecycle/csi/snapshotcontroller/handler.go +++ b/pkg/handlers/generic/lifecycle/csi/snapshotcontroller/handler.go @@ -9,7 +9,6 @@ import ( "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" ctrl "sigs.k8s.io/controller-runtime" @@ -138,7 +137,7 @@ func (s *SnapshotControllerHandler) apply( } var strategy addons.Applier - switch ptr.Deref(snapshotControllerVar.Strategy, "") { + switch snapshotControllerVar.Strategy { case v1alpha1.AddonStrategyHelmAddon: helmChart, err := s.helmChartInfoGetter.For(ctx, log, config.SnapshotController) if err != nil { @@ -166,7 +165,7 @@ func (s *SnapshotControllerHandler) apply( resp.SetMessage( fmt.Sprintf( "unknown snapshot-controller addon deployment strategy %q", - *snapshotControllerVar.Strategy, + snapshotControllerVar.Strategy, ), ) } diff --git a/pkg/handlers/generic/lifecycle/csi/variables_test.go b/pkg/handlers/generic/lifecycle/csi/variables_test.go index 8f17aceb3..6345a7e77 100644 --- a/pkg/handlers/generic/lifecycle/csi/variables_test.go +++ b/pkg/handlers/generic/lifecycle/csi/variables_test.go @@ -36,7 +36,7 @@ func TestVariableValidation_AWSCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderAWSEBS: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -59,7 +59,7 @@ func TestVariableValidation_AWSCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderNutanix: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -83,7 +83,7 @@ func TestVariableValidation_AWSCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderLocalPath: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -107,7 +107,7 @@ func TestVariableValidation_AWSCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ "unknown": { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -141,7 +141,7 @@ func TestVariableValidation_NutanixCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderNutanix: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -164,7 +164,7 @@ func TestVariableValidation_NutanixCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderAWSEBS: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -188,7 +188,7 @@ func TestVariableValidation_NutanixCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderLocalPath: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -212,7 +212,7 @@ func TestVariableValidation_NutanixCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ "unknown": { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -246,7 +246,7 @@ func TestVariableValidation_DockerCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderLocalPath: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -269,7 +269,7 @@ func TestVariableValidation_DockerCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderAWSEBS: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -293,7 +293,7 @@ func TestVariableValidation_DockerCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ v1alpha1.CSIProviderNutanix: { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, @@ -317,7 +317,7 @@ func TestVariableValidation_DockerCSI(t *testing.T) { }, Providers: map[string]v1alpha1.CSIProvider{ "unknown": { - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, StorageClassConfigs: map[string]v1alpha1.StorageClassConfig{ "test-1": {}, }, diff --git a/pkg/handlers/generic/lifecycle/nfd/handler.go b/pkg/handlers/generic/lifecycle/nfd/handler.go index f63ca1546..470b5136d 100644 --- a/pkg/handlers/generic/lifecycle/nfd/handler.go +++ b/pkg/handlers/generic/lifecycle/nfd/handler.go @@ -8,7 +8,6 @@ import ( "fmt" "github.com/spf13/pflag" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" ctrl "sigs.k8s.io/controller-runtime" @@ -141,7 +140,7 @@ func (n *DefaultNFD) apply( } var strategy addons.Applier - switch ptr.Deref(cniVar.Strategy, "") { + switch cniVar.Strategy { case v1alpha1.AddonStrategyClusterResourceSet: strategy = crsStrategy{ config: n.config.crsConfig, @@ -172,7 +171,7 @@ func (n *DefaultNFD) apply( resp.SetMessage("strategy not provided for NFD") default: resp.SetStatus(runtimehooksv1.ResponseStatusFailure) - resp.SetMessage(fmt.Sprintf("unknown NFD addon deployment strategy %q", *cniVar.Strategy)) + resp.SetMessage(fmt.Sprintf("unknown NFD addon deployment strategy %q", cniVar.Strategy)) return } diff --git a/pkg/handlers/generic/lifecycle/nfd/variables_test.go b/pkg/handlers/generic/lifecycle/nfd/variables_test.go index 84b0048db..166108c49 100644 --- a/pkg/handlers/generic/lifecycle/nfd/variables_test.go +++ b/pkg/handlers/generic/lifecycle/nfd/variables_test.go @@ -22,7 +22,7 @@ var testDefs = []capitest.VariableTestDef{{ Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ NFD: &v1alpha1.NFD{ - Strategy: ptr.To(v1alpha1.AddonStrategyClusterResourceSet), + Strategy: v1alpha1.AddonStrategyClusterResourceSet, }, }, }, @@ -33,7 +33,7 @@ var testDefs = []capitest.VariableTestDef{{ Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ NFD: &v1alpha1.NFD{ - Strategy: ptr.To(v1alpha1.AddonStrategyHelmAddon), + Strategy: v1alpha1.AddonStrategyHelmAddon, }, }, }, @@ -44,7 +44,7 @@ var testDefs = []capitest.VariableTestDef{{ Addons: &apivariables.Addons{ GenericAddons: v1alpha1.GenericAddons{ NFD: &v1alpha1.NFD{ - Strategy: ptr.To[v1alpha1.AddonStrategy]("invalid-strategy"), + Strategy: v1alpha1.AddonStrategy("invalid-strategy"), }, }, }, diff --git a/pkg/handlers/generic/mutation/externalcloudprovider/inject.go b/pkg/handlers/generic/mutation/externalcloudprovider/inject.go index 79586f2cf..2a50a587c 100644 --- a/pkg/handlers/generic/mutation/externalcloudprovider/inject.go +++ b/pkg/handlers/generic/mutation/externalcloudprovider/inject.go @@ -7,6 +7,7 @@ import ( "context" "fmt" + "github.com/blang/semver/v4" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" @@ -15,16 +16,13 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/blang/semver/v4" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers/mutation" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/patches" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/patches/selectors" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/variables" ) -var ( - versionGreaterOrEqualTo133Range = semver.MustParseRange(">=1.33.0-0") -) +var versionGreaterOrEqualTo133Range = semver.MustParseRange(">=1.33.0-0") type externalCloudProviderPatchHandler struct{} @@ -58,7 +56,8 @@ func (h *externalCloudProviderPatchHandler) Mutate( } // This is a fatal error, we can't proceed without the control plane version. - log.WithValues("variables", vars).Error(err, "failed to get control plane Kubernetes version from builtin variable") + log.WithValues("variables", vars). + Error(err, "failed to get control plane Kubernetes version from builtin variable") return fmt.Errorf("failed to get control plane Kubernetes version from builtin variable: %w", err) } @@ -87,7 +86,7 @@ func (h *externalCloudProviderPatchHandler) Mutate( if obj.Spec.Template.Spec.KubeadmConfigSpec.ClusterConfiguration.APIServer.ExtraArgs == nil { obj.Spec.Template.Spec.KubeadmConfigSpec.ClusterConfiguration.APIServer.ExtraArgs = make(map[string]string, 1) } - if _, ok := obj.Spec.Template.Spec.KubeadmConfigSpec.ClusterConfiguration.APIServer.ExtraArgs["cloud-provider"]; !ok { + if _, ok := obj.Spec.Template.Spec.KubeadmConfigSpec.ClusterConfiguration.APIServer.ExtraArgs["cloud-provider"]; !ok { //nolint:lll // Easier to read this way. obj.Spec.Template.Spec.KubeadmConfigSpec.ClusterConfiguration.APIServer.ExtraArgs["cloud-provider"] = "external" } diff --git a/pkg/handlers/generic/mutation/imageregistries/credentials/credentials_secret_test.go b/pkg/handlers/generic/mutation/imageregistries/credentials/credentials_secret_test.go index cc8170f9b..919a56699 100644 --- a/pkg/handlers/generic/mutation/imageregistries/credentials/credentials_secret_test.go +++ b/pkg/handlers/generic/mutation/imageregistries/credentials/credentials_secret_test.go @@ -31,7 +31,7 @@ func Test_generateCredentialsSecretFile(t *testing.T) { { name: "config with no static credentials, expect no file", configs: []providerConfig{ - {URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com"}, + {URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com"}, }, clusterName: "test-cluster", wantFile: nil, @@ -89,7 +89,7 @@ func Test_generateCredentialsSecret(t *testing.T) { { name: "config with no static credentials, expect no Secret", configs: []providerConfig{ - {URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com"}, + {URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com"}, }, clusterName: "test-cluster", namespace: "test-namespace", @@ -157,7 +157,7 @@ func Test_kubeletStaticCredentialProviderSecretContents(t *testing.T) { { name: "config with no static credentials, expect empty string", configs: []providerConfig{ - {URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com"}, + {URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com"}, }, wantContents: "", }, @@ -189,7 +189,7 @@ func Test_kubeletStaticCredentialProviderSecretContents(t *testing.T) { Username: "myuser", Password: "mypassword", }, - {URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com"}, + {URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com"}, { URL: "https://registry-1.docker.io", Username: "myuser", diff --git a/pkg/handlers/generic/mutation/imageregistries/credentials/inject_test.go b/pkg/handlers/generic/mutation/imageregistries/credentials/inject_test.go index f72a60bee..c25d103e1 100644 --- a/pkg/handlers/generic/mutation/imageregistries/credentials/inject_test.go +++ b/pkg/handlers/generic/mutation/imageregistries/credentials/inject_test.go @@ -45,10 +45,10 @@ func Test_providerConfigsThatNeedConfiguration(t *testing.T) { { name: "ECR registry with no credentials", configs: []providerConfig{ - {URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com"}, + {URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com"}, }, expected: []providerConfig{ - {URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com"}, + {URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com"}, }, }, { @@ -67,11 +67,11 @@ func Test_providerConfigsThatNeedConfiguration(t *testing.T) { { name: "ECR mirror with no credentials", configs: []providerConfig{{ - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", Mirror: true, }}, expected: []providerConfig{{ - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", Mirror: true, }}, }, @@ -203,7 +203,7 @@ var _ = Describe("Generate Image registry patches", func() { capitest.VariableWithValue( v1alpha1.ClusterConfigVariableName, []v1alpha1.ImageRegistry{{ - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", }}, v1alpha1.ImageRegistriesVariableName, ), @@ -338,7 +338,7 @@ var _ = Describe("Generate Image registry patches", func() { capitest.VariableWithValue( v1alpha1.ClusterConfigVariableName, []v1alpha1.ImageRegistry{{ - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", }}, v1alpha1.ImageRegistriesVariableName, ), diff --git a/pkg/handlers/generic/mutation/kubeproxymode/variables_test.go b/pkg/handlers/generic/mutation/kubeproxymode/variables_test.go index 9f82a7b4e..8595bd41b 100644 --- a/pkg/handlers/generic/mutation/kubeproxymode/variables_test.go +++ b/pkg/handlers/generic/mutation/kubeproxymode/variables_test.go @@ -133,7 +133,7 @@ func minimalDockerClusterConfigSpec() v1alpha1.DockerClusterConfigSpec { return v1alpha1.DockerClusterConfigSpec{ ControlPlane: &v1alpha1.DockerControlPlaneSpec{ Docker: &v1alpha1.DockerNodeSpec{ - CustomImage: ptr.To("fake-docker-image"), + CustomImage: "fake-docker-image", }, }, } diff --git a/pkg/handlers/generic/mutation/kubernetesimagerepository/variables_test.go b/pkg/handlers/generic/mutation/kubernetesimagerepository/variables_test.go index 46433ffba..0130bb724 100644 --- a/pkg/handlers/generic/mutation/kubernetesimagerepository/variables_test.go +++ b/pkg/handlers/generic/mutation/kubernetesimagerepository/variables_test.go @@ -18,9 +18,7 @@ import ( var testDefs = []capitest.VariableTestDef{{ Name: "set", Vals: v1alpha1.GenericClusterConfigSpec{ - KubernetesImageRepository: ptr.To( - "my-registry.io/my-org/my-repo", - ), + KubernetesImageRepository: "my-registry.io/my-org/my-repo", }, }} diff --git a/pkg/handlers/generic/mutation/mirrors/containerd_files_test.go b/pkg/handlers/generic/mutation/mirrors/containerd_files_test.go index 45c354a2a..23e3a38b6 100644 --- a/pkg/handlers/generic/mutation/mirrors/containerd_files_test.go +++ b/pkg/handlers/generic/mutation/mirrors/containerd_files_test.go @@ -23,7 +23,7 @@ func Test_generateContainerdDefaultHostsFile(t *testing.T) { name: "ECR mirror image registry and no CA certificate", configs: []containerdConfig{ { - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", Mirror: true, }, }, @@ -33,7 +33,7 @@ func Test_generateContainerdDefaultHostsFile(t *testing.T) { Permissions: "0600", Encoding: "", Append: false, - Content: `[host."https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2"] + Content: `[host."https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com/v2"] capabilities = ["pull", "resolve"] # don't rely on Containerd to add the v2/ suffix # there is a bug where it is added incorrectly for mirrors with a path @@ -45,7 +45,7 @@ func Test_generateContainerdDefaultHostsFile(t *testing.T) { name: "ECR mirror image registry with a path and no CA certificate", configs: []containerdConfig{ { - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com/myproject", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com/myproject", Mirror: true, }, }, @@ -55,7 +55,7 @@ func Test_generateContainerdDefaultHostsFile(t *testing.T) { Permissions: "0600", Encoding: "", Append: false, - Content: `[host."https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2/myproject"] + Content: `[host."https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com/v2/myproject"] capabilities = ["pull", "resolve"] # don't rely on Containerd to add the v2/ suffix # there is a bug where it is added incorrectly for mirrors with a path @@ -155,7 +155,7 @@ func Test_generateRegistryCACertFiles(t *testing.T) { name: "ECR mirror image registry with no CA certificate", configs: []containerdConfig{ { - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", Mirror: true, }, }, diff --git a/pkg/handlers/generic/mutation/mirrors/inject_test.go b/pkg/handlers/generic/mutation/mirrors/inject_test.go index c95feb527..1f4a8eea7 100644 --- a/pkg/handlers/generic/mutation/mirrors/inject_test.go +++ b/pkg/handlers/generic/mutation/mirrors/inject_test.go @@ -67,7 +67,7 @@ var _ = Describe("Generate Global mirror patches", func() { capitest.VariableWithValue( v1alpha1.ClusterConfigVariableName, v1alpha1.GlobalImageRegistryMirror{ - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", }, v1alpha1.GlobalMirrorVariableName, ), @@ -193,7 +193,7 @@ var _ = Describe("Generate Global mirror patches", func() { capitest.VariableWithValue( v1alpha1.ClusterConfigVariableName, v1alpha1.GlobalImageRegistryMirror{ - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", }, v1alpha1.GlobalMirrorVariableName, ), @@ -581,7 +581,7 @@ func Test_needContainerdConfiguration(t *testing.T) { name: "ECR mirror image registry with no CA certificate", configs: []containerdConfig{ { - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com", Mirror: true, }, }, @@ -591,7 +591,7 @@ func Test_needContainerdConfiguration(t *testing.T) { name: "ECR mirror image registry with a path and no CA certificate", configs: []containerdConfig{ { - URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com/myproject", + URL: "https://o-0123456789.dkr.ecr.us-east-1.amazonaws.com/myproject", Mirror: true, }, }, diff --git a/test/e2e/ccm_helpers.go b/test/e2e/ccm_helpers.go index 31a623a27..8a24bec6f 100644 --- a/test/e2e/ccm_helpers.go +++ b/test/e2e/ccm_helpers.go @@ -14,7 +14,6 @@ import ( appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" addonsv1 "sigs.k8s.io/cluster-api/api/addons/v1beta1" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/test/framework" @@ -74,7 +73,7 @@ func WaitForAWSCCMToBeReadyInWorkloadCluster( workloadClusterClient client.Client, input WaitForCCMToBeReadyInWorkloadClusterInput, //nolint:gocritic // This hugeParam is OK in tests. ) { - switch ptr.Deref(input.CCM.Strategy, "") { + switch input.CCM.Strategy { case v1alpha1.AddonStrategyClusterResourceSet: crs := &addonsv1.ClusterResourceSet{} Expect(input.ClusterProxy.GetClient().Get( @@ -111,7 +110,7 @@ func WaitForAWSCCMToBeReadyInWorkloadCluster( Fail( fmt.Sprintf( "Do not know how to wait for AWS CCM using strategy %s to be ready", - *input.CCM.Strategy, + input.CCM.Strategy, ), ) } @@ -132,7 +131,7 @@ func WaitForNutanixCCMToBeReadyInWorkloadCluster( workloadClusterClient client.Client, input WaitForCCMToBeReadyInWorkloadClusterInput, //nolint:gocritic // This hugeParam is OK in tests. ) { - switch ptr.Deref(input.CCM.Strategy, "") { + switch input.CCM.Strategy { case v1alpha1.AddonStrategyHelmAddon: WaitForHelmReleaseProxyReadyForCluster( ctx, @@ -149,7 +148,7 @@ func WaitForNutanixCCMToBeReadyInWorkloadCluster( Fail( fmt.Sprintf( "Do not know how to wait for Nutanix CCM using strategy %s to be ready", - *input.CCM.Strategy, + input.CCM.Strategy, ), ) } diff --git a/test/e2e/clusterautoscaler_helpers.go b/test/e2e/clusterautoscaler_helpers.go index 57138cd21..5c282a54c 100644 --- a/test/e2e/clusterautoscaler_helpers.go +++ b/test/e2e/clusterautoscaler_helpers.go @@ -17,7 +17,6 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" addonsv1 "sigs.k8s.io/cluster-api/api/addons/v1beta1" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/test/framework" @@ -58,7 +57,7 @@ func WaitForClusterAutoscalerToBeReadyForWorkloadCluster( return } - switch ptr.Deref(input.ClusterAutoscaler.Strategy, "") { + switch input.ClusterAutoscaler.Strategy { case v1alpha1.AddonStrategyClusterResourceSet: crs := &addonsv1.ClusterResourceSet{} Expect(input.ClusterProxy.GetClient().Get( @@ -99,7 +98,7 @@ func WaitForClusterAutoscalerToBeReadyForWorkloadCluster( Fail( fmt.Sprintf( "Do not know how to wait for cluster autoscaler using strategy %s to be ready", - *input.ClusterAutoscaler.Strategy, + input.ClusterAutoscaler.Strategy, ), ) } diff --git a/test/e2e/cni_helpers.go b/test/e2e/cni_helpers.go index 13d07c5ee..2d5628cc9 100644 --- a/test/e2e/cni_helpers.go +++ b/test/e2e/cni_helpers.go @@ -14,7 +14,6 @@ import ( appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" addonsv1 "sigs.k8s.io/cluster-api/api/addons/v1beta1" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/test/framework" @@ -45,7 +44,7 @@ func WaitForCNIToBeReadyInWorkloadCluster( waitForCalicoToBeReadyInWorkloadCluster( ctx, waitForCalicoToBeReadyInWorkloadClusterInput{ - strategy: ptr.Deref(input.CNI.Strategy, ""), + strategy: input.CNI.Strategy, workloadCluster: input.WorkloadCluster, clusterProxy: input.ClusterProxy, deploymentIntervals: input.DeploymentIntervals, @@ -58,7 +57,7 @@ func WaitForCNIToBeReadyInWorkloadCluster( waitForCiliumToBeReadyInWorkloadCluster( ctx, waitForCiliumToBeReadyInWorkloadClusterInput{ - strategy: ptr.Deref(input.CNI.Strategy, ""), + strategy: input.CNI.Strategy, workloadCluster: input.WorkloadCluster, clusterProxy: input.ClusterProxy, deploymentIntervals: input.DeploymentIntervals, diff --git a/test/e2e/cosi_helpers.go b/test/e2e/cosi_helpers.go index d76939385..a1c627a62 100644 --- a/test/e2e/cosi_helpers.go +++ b/test/e2e/cosi_helpers.go @@ -12,7 +12,6 @@ import ( . "github.com/onsi/ginkgo/v2" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/test/framework" @@ -36,7 +35,7 @@ func WaitForCOSIControllerToBeReadyInWorkloadCluster( return } - switch ptr.Deref(input.COSI.Strategy, "") { + switch input.COSI.Strategy { case v1alpha1.AddonStrategyHelmAddon: WaitForHelmReleaseProxyReadyForCluster( ctx, @@ -53,7 +52,7 @@ func WaitForCOSIControllerToBeReadyInWorkloadCluster( Fail( fmt.Sprintf( "Do not know how to wait for COSI using strategy %s to be ready", - *input.COSI.Strategy, + input.COSI.Strategy, ), ) } diff --git a/test/e2e/csi_helpers.go b/test/e2e/csi_helpers.go index 39ae5e998..9b072dbc2 100644 --- a/test/e2e/csi_helpers.go +++ b/test/e2e/csi_helpers.go @@ -18,7 +18,6 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" addonsv1 "sigs.k8s.io/cluster-api/api/addons/v1beta1" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" capie2e "sigs.k8s.io/cluster-api/test/e2e" @@ -57,7 +56,7 @@ func WaitForCSIToBeReadyInWorkloadCluster( waitForLocalPathCSIToBeReadyInWorkloadCluster( ctx, waitForLocalPathCSIToBeReadyInWorkloadClusterInput{ - strategy: ptr.Deref(providerConfig.Strategy, ""), + strategy: providerConfig.Strategy, workloadCluster: input.WorkloadCluster, clusterProxy: input.ClusterProxy, deploymentIntervals: input.DeploymentIntervals, @@ -70,7 +69,7 @@ func WaitForCSIToBeReadyInWorkloadCluster( waitForAWSEBSCSIToBeReadyInWorkloadCluster( ctx, waitForAWSEBSCSIToBeReadyInWorkloadClusterInput{ - strategy: ptr.Deref(providerConfig.Strategy, ""), + strategy: providerConfig.Strategy, workloadCluster: input.WorkloadCluster, clusterProxy: input.ClusterProxy, deploymentIntervals: input.DeploymentIntervals, @@ -84,7 +83,7 @@ func WaitForCSIToBeReadyInWorkloadCluster( waitForNutanixCSIToBeReadyInWorkloadCluster( ctx, waitForNutanixCSIToBeReadyInWorkloadClusterInput{ - strategy: ptr.Deref(providerConfig.Strategy, ""), + strategy: providerConfig.Strategy, workloadCluster: input.WorkloadCluster, clusterProxy: input.ClusterProxy, deploymentIntervals: input.DeploymentIntervals, @@ -119,7 +118,7 @@ func WaitForCSIToBeReadyInWorkloadCluster( waitForSnapshotControllerToBeReadyInWorkloadCluster( ctx, waitForSnapshotControllerToBeReadyInWorkloadClusterInput{ - strategy: ptr.Deref(input.CSI.SnapshotController.Strategy, ""), + strategy: input.CSI.SnapshotController.Strategy, workloadCluster: input.WorkloadCluster, clusterProxy: input.ClusterProxy, deploymentIntervals: input.DeploymentIntervals, diff --git a/test/e2e/nfd_helpers.go b/test/e2e/nfd_helpers.go index 3b5a93c9b..cf2b60e90 100644 --- a/test/e2e/nfd_helpers.go +++ b/test/e2e/nfd_helpers.go @@ -14,7 +14,6 @@ import ( appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" addonsv1 "sigs.k8s.io/cluster-api/api/addons/v1beta1" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/test/framework" @@ -40,7 +39,7 @@ func WaitForNFDToBeReadyInWorkloadCluster( return } - switch ptr.Deref(input.NFD.Strategy, "") { + switch input.NFD.Strategy { case v1alpha1.AddonStrategyClusterResourceSet: crs := &addonsv1.ClusterResourceSet{} Expect(input.ClusterProxy.GetClient().Get( @@ -77,7 +76,7 @@ func WaitForNFDToBeReadyInWorkloadCluster( Fail( fmt.Sprintf( "Do not know how to wait for NFD using strategy %s to be ready", - *input.NFD.Strategy, + input.NFD.Strategy, ), ) }