diff --git a/config/v1/0000_10_config-operator_01_dns.crd.yaml b/config/v1/0000_10_config-operator_01_dns.crd.yaml index e4fa56eeeab..493656f17c0 100644 --- a/config/v1/0000_10_config-operator_01_dns.crd.yaml +++ b/config/v1/0000_10_config-operator_01_dns.crd.yaml @@ -39,6 +39,46 @@ spec: baseDomain: description: "baseDomain is the base domain of the cluster. All managed DNS records will be sub-domains of this base. \n For example, given the base domain `openshift.example.com`, an API server DNS record may be created for `cluster-api.openshift.example.com`. \n Once set, this field cannot be changed." type: string + platform: + description: platform holds configuration specific to the underlying infrastructure provider for DNS. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. + type: object + required: + - type + properties: + aws: + description: aws contains DNS configuration specific to the Amazon Web Services cloud provider. + type: object + properties: + privateZoneIAMRole: + description: privateZoneIAMRole contains the ARN of an IAM role that should be assumed when performing operations on the cluster's private hosted zone specified in the cluster DNS config. When left empty, no role should be assumed. + type: string + pattern: ^arn:(aws|aws-cn|aws-us-gov):iam::[0-9]{12}:role\/.*$ + type: + description: "type is the underlying infrastructure provider for the cluster. Allowed values: \"\", \"AWS\". \n Individual components may not support all platforms, and must handle unrecognized platforms with best-effort defaults." + type: string + enum: + - "" + - AWS + - Azure + - BareMetal + - GCP + - Libvirt + - OpenStack + - None + - VSphere + - oVirt + - IBMCloud + - KubeVirt + - EquinixMetal + - PowerVS + - AlibabaCloud + - Nutanix + x-kubernetes-validations: + - rule: self in ['','AWS'] + message: allowed values are '' and 'AWS' + x-kubernetes-validations: + - rule: 'has(self.type) && self.type == ''AWS'' ? has(self.aws) : !has(self.aws)' + message: aws configuration is required when platform is AWS, and forbidden otherwise privateZone: description: "privateZone is the location where all the DNS records that are only available internally to the cluster exist. \n If this field is nil, no private records should be created. \n Once set, this field cannot be changed." type: object diff --git a/config/v1/stable.dns.testsuite.yaml b/config/v1/stable.dns.testsuite.yaml index c69f50050a4..b8535da7991 100644 --- a/config/v1/stable.dns.testsuite.yaml +++ b/config/v1/stable.dns.testsuite.yaml @@ -12,3 +12,94 @@ tests: apiVersion: config.openshift.io/v1 kind: DNS spec: {} + - name: Should be able to specify an AWS role ARN for a private hosted zone + initial: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: AWS + aws: + privateZoneIAMRole: arn:aws:iam::123456789012:role/foo + expected: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: AWS + aws: + privateZoneIAMRole: arn:aws:iam::123456789012:role/foo + - name: Should not be able to specify unsupported platform + initial: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: Azure + azure: + privateZoneIAMRole: arn:aws:iam::123456789012:role/foo + expectedError: "Invalid value: \"string\": allowed values are '' and 'AWS'" + - name: Should not be able to specify invalid AWS role ARN + initial: | + apiVersion: config.openshift.io/v1 + kind: DNS + metadata: + name: cluster + spec: + platform: + type: AWS + aws: + privateZoneIAMRole: arn:aws:iam:bad:123456789012:role/foo + expectedError: "DNS.config.openshift.io \"cluster\" is invalid: spec.platform.aws.privateZoneIAMRole: Invalid value: \"arn:aws:iam:bad:123456789012:role/foo\": spec.platform.aws.privateZoneIAMRole in body should match '^arn:(aws|aws-cn|aws-us-gov):iam::[0-9]{12}:role\\/.*$'" + - name: Should not be able to specify different type and platform + initial: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: "" + aws: + privateZoneIAMRole: arn:aws:iam::123456789012:role/foo + expectedError: "Invalid value: \"object\": aws configuration is required when platform is AWS, and forbidden otherwise" + onUpdate: + - name: Can switch from empty (default), to AWS + initial: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: "" + updated: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: AWS + aws: + privateZoneIAMRole: arn:aws:iam::123456789012:role/foo + expected: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: AWS + aws: + privateZoneIAMRole: arn:aws:iam::123456789012:role/foo + - name: Upgrade case is valid + initial: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: {} # No spec is required for a DNS + updated: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: "" + expected: | + apiVersion: config.openshift.io/v1 + kind: DNS + spec: + platform: + type: "" + diff --git a/config/v1/types_dns.go b/config/v1/types_dns.go index c223f828e1f..efca4d01548 100644 --- a/config/v1/types_dns.go +++ b/config/v1/types_dns.go @@ -50,6 +50,12 @@ type DNSSpec struct { // // +optional PrivateZone *DNSZone `json:"privateZone,omitempty"` + // platform holds configuration specific to the underlying + // infrastructure provider for DNS. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // +optional + Platform DNSPlatformSpec `json:"platform,omitempty"` } // DNSZone is used to define a DNS hosted zone. @@ -90,3 +96,34 @@ type DNSList struct { Items []DNS `json:"items"` } + +// DNSPlatformSpec holds cloud-provider-specific configuration +// for DNS administration. +// +union +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'AWS' ? has(self.aws) : !has(self.aws)",message="aws configuration is required when platform is AWS, and forbidden otherwise" +type DNSPlatformSpec struct { + // type is the underlying infrastructure provider for the cluster. + // Allowed values: "", "AWS". + // + // Individual components may not support all platforms, + // and must handle unrecognized platforms with best-effort defaults. + // + // +unionDiscriminator + // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self in ['','AWS']",message="allowed values are '' and 'AWS'" + Type PlatformType `json:"type"` + + // aws contains DNS configuration specific to the Amazon Web Services cloud provider. + // +optional + AWS *AWSDNSSpec `json:"aws"` +} + +// AWSDNSSpec contains DNS configuration specific to the Amazon Web Services cloud provider. +type AWSDNSSpec struct { + // privateZoneIAMRole contains the ARN of an IAM role that should be assumed when performing + // operations on the cluster's private hosted zone specified in the cluster DNS config. + // When left empty, no role should be assumed. + // +kubebuilder:validation:Pattern:=`^arn:(aws|aws-cn|aws-us-gov):iam::[0-9]{12}:role\/.*$` + // +optional + PrivateZoneIAMRole string `json:"privateZoneIAMRole"` +} diff --git a/config/v1/zz_generated.deepcopy.go b/config/v1/zz_generated.deepcopy.go index 59e92ad7a11..69c12e80b72 100644 --- a/config/v1/zz_generated.deepcopy.go +++ b/config/v1/zz_generated.deepcopy.go @@ -179,6 +179,22 @@ func (in *APIServerStatus) DeepCopy() *APIServerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSDNSSpec) DeepCopyInto(out *AWSDNSSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSDNSSpec. +func (in *AWSDNSSpec) DeepCopy() *AWSDNSSpec { + if in == nil { + return nil + } + out := new(AWSDNSSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AWSIngressSpec) DeepCopyInto(out *AWSIngressSpec) { *out = *in @@ -1538,6 +1554,27 @@ func (in *DNSList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSPlatformSpec) DeepCopyInto(out *DNSPlatformSpec) { + *out = *in + if in.AWS != nil { + in, out := &in.AWS, &out.AWS + *out = new(AWSDNSSpec) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSPlatformSpec. +func (in *DNSPlatformSpec) DeepCopy() *DNSPlatformSpec { + if in == nil { + return nil + } + out := new(DNSPlatformSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DNSSpec) DeepCopyInto(out *DNSSpec) { *out = *in @@ -1551,6 +1588,7 @@ func (in *DNSSpec) DeepCopyInto(out *DNSSpec) { *out = new(DNSZone) (*in).DeepCopyInto(*out) } + in.Platform.DeepCopyInto(&out.Platform) return } diff --git a/config/v1/zz_generated.swagger_doc_generated.go b/config/v1/zz_generated.swagger_doc_generated.go index c5a5ae79c7b..e82ad53feea 100644 --- a/config/v1/zz_generated.swagger_doc_generated.go +++ b/config/v1/zz_generated.swagger_doc_generated.go @@ -733,6 +733,15 @@ func (ConsoleStatus) SwaggerDoc() map[string]string { return map_ConsoleStatus } +var map_AWSDNSSpec = map[string]string{ + "": "AWSDNSSpec contains DNS configuration specific to the Amazon Web Services cloud provider.", + "privateZoneIAMRole": "privateZoneIAMRole contains the ARN of an IAM role that should be assumed when performing operations on the cluster's private hosted zone specified in the cluster DNS config. When left empty, no role should be assumed.", +} + +func (AWSDNSSpec) SwaggerDoc() map[string]string { + return map_AWSDNSSpec +} + var map_DNS = map[string]string{ "": "DNS holds cluster-wide information about DNS. The canonical name is `cluster`\n\nCompatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", "spec": "spec holds user settable values for configuration", @@ -751,10 +760,21 @@ func (DNSList) SwaggerDoc() map[string]string { return map_DNSList } +var map_DNSPlatformSpec = map[string]string{ + "": "DNSPlatformSpec holds cloud-provider-specific configuration for DNS administration.", + "type": "type is the underlying infrastructure provider for the cluster. Allowed values: \"\", \"AWS\".\n\nIndividual components may not support all platforms, and must handle unrecognized platforms with best-effort defaults.", + "aws": "aws contains DNS configuration specific to the Amazon Web Services cloud provider.", +} + +func (DNSPlatformSpec) SwaggerDoc() map[string]string { + return map_DNSPlatformSpec +} + var map_DNSSpec = map[string]string{ "baseDomain": "baseDomain is the base domain of the cluster. All managed DNS records will be sub-domains of this base.\n\nFor example, given the base domain `openshift.example.com`, an API server DNS record may be created for `cluster-api.openshift.example.com`.\n\nOnce set, this field cannot be changed.", "publicZone": "publicZone is the location where all the DNS records that are publicly accessible to the internet exist.\n\nIf this field is nil, no public records should be created.\n\nOnce set, this field cannot be changed.", "privateZone": "privateZone is the location where all the DNS records that are only available internally to the cluster exist.\n\nIf this field is nil, no private records should be created.\n\nOnce set, this field cannot be changed.", + "platform": "platform holds configuration specific to the underlying infrastructure provider for DNS. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time.", } func (DNSSpec) SwaggerDoc() map[string]string { diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go index 45a25c5c80f..4902837d1e4 100644 --- a/openapi/generated_openapi/zz_generated.openapi.go +++ b/openapi/generated_openapi/zz_generated.openapi.go @@ -149,6 +149,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/openshift/api/config/v1.APIServerServingCerts": schema_openshift_api_config_v1_APIServerServingCerts(ref), "github.com/openshift/api/config/v1.APIServerSpec": schema_openshift_api_config_v1_APIServerSpec(ref), "github.com/openshift/api/config/v1.APIServerStatus": schema_openshift_api_config_v1_APIServerStatus(ref), + "github.com/openshift/api/config/v1.AWSDNSSpec": schema_openshift_api_config_v1_AWSDNSSpec(ref), "github.com/openshift/api/config/v1.AWSIngressSpec": schema_openshift_api_config_v1_AWSIngressSpec(ref), "github.com/openshift/api/config/v1.AWSPlatformSpec": schema_openshift_api_config_v1_AWSPlatformSpec(ref), "github.com/openshift/api/config/v1.AWSPlatformStatus": schema_openshift_api_config_v1_AWSPlatformStatus(ref), @@ -207,6 +208,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/openshift/api/config/v1.CustomTLSProfile": schema_openshift_api_config_v1_CustomTLSProfile(ref), "github.com/openshift/api/config/v1.DNS": schema_openshift_api_config_v1_DNS(ref), "github.com/openshift/api/config/v1.DNSList": schema_openshift_api_config_v1_DNSList(ref), + "github.com/openshift/api/config/v1.DNSPlatformSpec": schema_openshift_api_config_v1_DNSPlatformSpec(ref), "github.com/openshift/api/config/v1.DNSSpec": schema_openshift_api_config_v1_DNSSpec(ref), "github.com/openshift/api/config/v1.DNSStatus": schema_openshift_api_config_v1_DNSStatus(ref), "github.com/openshift/api/config/v1.DNSZone": schema_openshift_api_config_v1_DNSZone(ref), @@ -8193,6 +8195,27 @@ func schema_openshift_api_config_v1_APIServerStatus(ref common.ReferenceCallback } } +func schema_openshift_api_config_v1_AWSDNSSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "AWSDNSSpec contains DNS configuration specific to the Amazon Web Services cloud provider.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "privateZoneIAMRole": { + SchemaProps: spec.SchemaProps{ + Description: "privateZoneIAMRole contains the ARN of an IAM role that should be assumed when performing operations on the cluster's private hosted zone specified in the cluster DNS config. When left empty, no role should be assumed.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + func schema_openshift_api_config_v1_AWSIngressSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -10777,6 +10800,48 @@ func schema_openshift_api_config_v1_DNSList(ref common.ReferenceCallback) common } } +func schema_openshift_api_config_v1_DNSPlatformSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DNSPlatformSpec holds cloud-provider-specific configuration for DNS administration.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "type is the underlying infrastructure provider for the cluster. Allowed values: \"\", \"AWS\".\n\nIndividual components may not support all platforms, and must handle unrecognized platforms with best-effort defaults.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "aws": { + SchemaProps: spec.SchemaProps{ + Description: "aws contains DNS configuration specific to the Amazon Web Services cloud provider.", + Ref: ref("github.com/openshift/api/config/v1.AWSDNSSpec"), + }, + }, + }, + Required: []string{"type"}, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-unions": []interface{}{ + map[string]interface{}{ + "discriminator": "type", + "fields-to-discriminateBy": map[string]interface{}{ + "aws": "AWS", + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/openshift/api/config/v1.AWSDNSSpec"}, + } +} + func schema_openshift_api_config_v1_DNSSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -10803,12 +10868,19 @@ func schema_openshift_api_config_v1_DNSSpec(ref common.ReferenceCallback) common Ref: ref("github.com/openshift/api/config/v1.DNSZone"), }, }, + "platform": { + SchemaProps: spec.SchemaProps{ + Description: "platform holds configuration specific to the underlying infrastructure provider for DNS. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time.", + Default: map[string]interface{}{}, + Ref: ref("github.com/openshift/api/config/v1.DNSPlatformSpec"), + }, + }, }, Required: []string{"baseDomain"}, }, }, Dependencies: []string{ - "github.com/openshift/api/config/v1.DNSZone"}, + "github.com/openshift/api/config/v1.DNSPlatformSpec", "github.com/openshift/api/config/v1.DNSZone"}, } } diff --git a/openapi/openapi.json b/openapi/openapi.json index 3a2a426c643..7419fb6c792 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -4099,6 +4099,17 @@ "com.github.openshift.api.config.v1.APIServerStatus": { "type": "object" }, + "com.github.openshift.api.config.v1.AWSDNSSpec": { + "description": "AWSDNSSpec contains DNS configuration specific to the Amazon Web Services cloud provider.", + "type": "object", + "properties": { + "privateZoneIAMRole": { + "description": "privateZoneIAMRole contains the ARN of an IAM role that should be assumed when performing operations on the cluster's private hosted zone specified in the cluster DNS config. When left empty, no role should be assumed.", + "type": "string", + "default": "" + } + } + }, "com.github.openshift.api.config.v1.AWSIngressSpec": { "description": "AWSIngressSpec holds the desired state of the Ingress for Amazon Web Services infrastructure provider. This only includes fields that can be modified in the cluster.", "type": "object", @@ -5633,6 +5644,32 @@ } } }, + "com.github.openshift.api.config.v1.DNSPlatformSpec": { + "description": "DNSPlatformSpec holds cloud-provider-specific configuration for DNS administration.", + "type": "object", + "required": [ + "type" + ], + "properties": { + "aws": { + "description": "aws contains DNS configuration specific to the Amazon Web Services cloud provider.", + "$ref": "#/definitions/com.github.openshift.api.config.v1.AWSDNSSpec" + }, + "type": { + "description": "type is the underlying infrastructure provider for the cluster. Allowed values: \"\", \"AWS\".\n\nIndividual components may not support all platforms, and must handle unrecognized platforms with best-effort defaults.", + "type": "string", + "default": "" + } + }, + "x-kubernetes-unions": [ + { + "discriminator": "type", + "fields-to-discriminateBy": { + "aws": "AWS" + } + } + ] + }, "com.github.openshift.api.config.v1.DNSSpec": { "type": "object", "required": [ @@ -5644,6 +5681,11 @@ "type": "string", "default": "" }, + "platform": { + "description": "platform holds configuration specific to the underlying infrastructure provider for DNS. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time.", + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.config.v1.DNSPlatformSpec" + }, "privateZone": { "description": "privateZone is the location where all the DNS records that are only available internally to the cluster exist.\n\nIf this field is nil, no private records should be created.\n\nOnce set, this field cannot be changed.", "$ref": "#/definitions/com.github.openshift.api.config.v1.DNSZone"