1
0
mirror of https://github.com/openshift/installer.git synced 2026-02-05 15:47:14 +01:00

Merge pull request #9181 from barbacbd/OCPBUGS-44230-release-4.17

OCPBUGS-44230: Add C4A instance types
This commit is contained in:
openshift-merge-bot[bot]
2024-11-15 09:07:49 +00:00
committed by GitHub
31 changed files with 2075 additions and 1613 deletions

File diff suppressed because it is too large Load Diff

4
go.mod
View File

@@ -82,7 +82,7 @@ require (
github.com/openshift/cluster-api-provider-ovirt v0.1.1-0.20220323121149-e3f2850dd519
github.com/openshift/hive/apis v0.0.0-20220222213051-def9088fdb5a
github.com/openshift/library-go v0.0.0-20240207105404-126b47137408
github.com/openshift/machine-api-provider-gcp v0.0.1-0.20231014045125-6096cc86f3ba
github.com/openshift/machine-api-provider-gcp v0.0.1-0.20241024094404-0d6fbdb09401
github.com/openshift/machine-api-provider-ibmcloud v0.0.0-20231207164151-6b0b8ea7b16d
github.com/ovirt/go-ovirt v0.0.0-20210809163552-d4276e35d3db
github.com/pborman/uuid v1.2.0
@@ -128,7 +128,7 @@ require (
sigs.k8s.io/cluster-api-provider-openstack v0.10.3
sigs.k8s.io/cluster-api-provider-vsphere v1.9.3
sigs.k8s.io/controller-runtime v0.18.5
sigs.k8s.io/controller-tools v0.12.0
sigs.k8s.io/controller-tools v0.14.0
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd
sigs.k8s.io/yaml v1.4.0
)

8
go.sum
View File

@@ -802,8 +802,8 @@ github.com/openshift/library-go v0.0.0-20240207105404-126b47137408 h1:Evg6GEvEuy
github.com/openshift/library-go v0.0.0-20240207105404-126b47137408/go.mod h1:ePlaOqUiPplRc++6aYdMe+2FmXb2xTNS9Nz5laG2YmI=
github.com/openshift/machine-api-operator v0.2.1-0.20240722145313-3a817c78946a h1:0TwU3J28sQTGy/ZMVSvi3sUolH92BwlIWcf+wCJLWKE=
github.com/openshift/machine-api-operator v0.2.1-0.20240722145313-3a817c78946a/go.mod h1:2TUb0+EfkIj5fWhGy+oR3QiANCzHTWzkyNDEknxrQJI=
github.com/openshift/machine-api-provider-gcp v0.0.1-0.20231014045125-6096cc86f3ba h1:q9VMvYHgKq1v+3E57HIdbR9hJPNSmHDfZpOHsXC27Nk=
github.com/openshift/machine-api-provider-gcp v0.0.1-0.20231014045125-6096cc86f3ba/go.mod h1:G1BYMrC49dMOkCEjG+LPoe0rRXFRv8o/jqLuN4fgfGM=
github.com/openshift/machine-api-provider-gcp v0.0.1-0.20241024094404-0d6fbdb09401 h1:adlUJqvMzPbDPSUo/TIN8olPN5x0w/71plhxj6YIq9I=
github.com/openshift/machine-api-provider-gcp v0.0.1-0.20241024094404-0d6fbdb09401/go.mod h1:5peyDQD9BPqSVTlZeGpd8cP46M50G+JEjrhRWcGb7HA=
github.com/openshift/machine-api-provider-ibmcloud v0.0.0-20231207164151-6b0b8ea7b16d h1:ELypg5zkw9jXCbp2jZ6iwYWTCtSqZVrxcKBQqwIgd2Y=
github.com/openshift/machine-api-provider-ibmcloud v0.0.0-20231207164151-6b0b8ea7b16d/go.mod h1:cF2vIryKLoYmkUAFsvFHTlChMAtMEuRDVYMiH+uFe3E=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
@@ -1557,8 +1557,8 @@ sigs.k8s.io/cluster-api-provider-vsphere v1.9.3 h1:Kgo9XQYZyZVUYwzUWr351h1OJf8LY
sigs.k8s.io/cluster-api-provider-vsphere v1.9.3/go.mod h1:t0z1hU7lR5olxrwNv9C3j5UJsjQ2KLdnQ1RaZiPkQ2A=
sigs.k8s.io/controller-runtime v0.18.5 h1:nTHio/W+Q4aBlQMgbnC5hZb4IjIidyrizMai9P6n4Rk=
sigs.k8s.io/controller-runtime v0.18.5/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg=
sigs.k8s.io/controller-tools v0.12.0 h1:TY6CGE6+6hzO7hhJFte65ud3cFmmZW947jajXkuDfBw=
sigs.k8s.io/controller-tools v0.12.0/go.mod h1:rXlpTfFHZMpZA8aGq9ejArgZiieHd+fkk/fTatY8A2M=
sigs.k8s.io/controller-tools v0.14.0 h1:rnNoCC5wSXlrNoBKKzL70LNJKIQKEzT6lloG6/LF73A=
sigs.k8s.io/controller-tools v0.14.0/go.mod h1:TV7uOtNNnnR72SpzhStvPkoS/U5ir0nMudrkrC4M9Sc=
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=

View File

@@ -88,7 +88,7 @@ func validateInstanceAndDiskType(fldPath *field.Path, diskType, instanceType, ar
return field.NotFound(fldPath.Child("type"), family)
}
acceptedArmFamilies := sets.New("t2a")
acceptedArmFamilies := sets.New("c4a", "t2a")
if arch == types.ArchitectureARM64 && !acceptedArmFamilies.Has(family) {
return field.NotSupported(fldPath.Child("type"), family, sets.List(acceptedArmFamilies))
}

View File

@@ -19,13 +19,15 @@ func Test_lookup(t *testing.T) {
desc: `InstallConfig is the configuration for an OpenShift install.`,
}, {
path: []string{"publish"},
desc: `Publish controls how the user facing endpoints of the cluster like the Kubernetes API, OpenShift routes etc. are exposed. When no strategy is specified, the strategy is "External".`,
desc: `Publish controls how the user facing endpoints of the cluster like the Kubernetes API, OpenShift routes etc. are exposed.
When no strategy is specified, the strategy is "External".`,
}, {
path: []string{"publish", "unknown"},
err: `invalid field unknown, no such property found`,
}, {
path: []string{"platform"},
desc: `Platform is the configuration for the specific platform upon which to perform the installation.`,
desc: `Platform is the configuration for the specific platform upon which to
perform the installation.`,
}, {
path: []string{"platform", "aws"},
desc: `AWS is the configuration used when installing on AWS.`,
@@ -37,16 +39,24 @@ func Test_lookup(t *testing.T) {
desc: `Region specifies the AWS region where the cluster will be created.`,
}, {
path: []string{"platform", "aws", "subnets"},
desc: `Subnets specifies existing subnets (by ID) where cluster resources will be created. Leave unset to have the installer create subnets in a new VPC on your behalf.`,
desc: `Subnets specifies existing subnets (by ID) where cluster
resources will be created. Leave unset to have the installer
create subnets in a new VPC on your behalf.`,
}, {
path: []string{"platform", "aws", "userTags"},
desc: `UserTags additional keys and values that the installer will add as tags to all resources that it creates. Resources created by the cluster itself may not include these tags.`,
desc: `UserTags additional keys and values that the installer will add
as tags to all resources that it creates. Resources created by the
cluster itself may not include these tags.`,
}, {
path: []string{"platform", "aws", "serviceEndpoints"},
desc: `ServiceEndpoints list contains custom endpoints which will override default service endpoint of AWS Services. There must be only one ServiceEndpoint for a service.`,
desc: `ServiceEndpoints list contains custom endpoints which will override default
service endpoint of AWS Services.
There must be only one ServiceEndpoint for a service.`,
}, {
path: []string{"platform", "aws", "serviceEndpoints", "url"},
desc: `URL is fully qualified URI with scheme https, that overrides the default generated endpoint for a client. This must be provided and cannot be empty.`,
desc: `URL is fully qualified URI with scheme https, that overrides the default generated
endpoint for a client.
This must be provided and cannot be empty.`,
}}
for _, test := range cases {
t.Run("", func(t *testing.T) {

View File

@@ -20,83 +20,131 @@ func Test_PrintFields(t *testing.T) {
}{{
desc: `FIELDS:
additionalTrustBundle <string>
AdditionalTrustBundle is a PEM-encoded X.509 certificate bundle that will be added to the nodes' trusted certificate store.
AdditionalTrustBundle is a PEM-encoded X.509 certificate bundle
that will be added to the nodes' trusted certificate store.
additionalTrustBundlePolicy <string>
Valid Values: "","Proxyonly","Always"
AdditionalTrustBundlePolicy determines when to add the AdditionalTrustBundle to the nodes' trusted certificate store. "Proxyonly" is the default. The field can be set to following specified values. "Proxyonly" : adds the AdditionalTrustBundle to nodes when http/https proxy is configured. "Always" : always adds AdditionalTrustBundle.
AdditionalTrustBundlePolicy determines when to add the AdditionalTrustBundle
to the nodes' trusted certificate store. "Proxyonly" is the default.
The field can be set to following specified values.
"Proxyonly" : adds the AdditionalTrustBundle to nodes when http/https proxy is configured.
"Always" : always adds AdditionalTrustBundle.
apiVersion <string>
APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
baseDomain <string> -required-
BaseDomain is the base domain to which the cluster should belong.
bootstrapInPlace <object>
BootstrapInPlace is the configuration for installing a single node with bootstrap in place installation.
BootstrapInPlace is the configuration for installing a single node
with bootstrap in place installation.
capabilities <object>
Capabilities configures the installation of optional core cluster components.
compute <[]object>
Compute is the configuration for the machines that comprise the compute nodes.
Compute is the configuration for the machines that comprise the
compute nodes.
MachinePool is a pool of machines to be installed.
controlPlane <object>
ControlPlane is the configuration for the machines that comprise the control plane.
ControlPlane is the configuration for the machines that comprise the
control plane.
cpuPartitioningMode <string>
Default: "None"
Valid Values: "None","AllNodes"
CPUPartitioning determines if a cluster should be setup for CPU workload partitioning at install time. When this field is set the cluster will be flagged for CPU Partitioning allowing users to segregate workloads to specific CPU Sets. This does not make any decisions on workloads it only configures the nodes to allow CPU Partitioning. The "AllNodes" value will setup all nodes for CPU Partitioning, the default is "None".
CPUPartitioning determines if a cluster should be setup for CPU workload partitioning at install time.
When this field is set the cluster will be flagged for CPU Partitioning allowing users to segregate workloads to
specific CPU Sets. This does not make any decisions on workloads it only configures the nodes to allow CPU Partitioning.
The "AllNodes" value will setup all nodes for CPU Partitioning, the default is "None".
credentialsMode <string>
Valid Values: "","Mint","Passthrough","Manual"
CredentialsMode is used to explicitly set the mode with which CredentialRequests are satisfied.
If this field is set, then the installer will not attempt to query the cloud permissions before attempting installation. If the field is not set or empty, then the installer will perform its normal verification that the credentials provided are sufficient to perform an installation.
There are three possible values for this field, but the valid values are dependent upon the platform being used. "Mint": create new credentials with a subset of the overall permissions for each CredentialsRequest "Passthrough": copy the credentials with all of the overall permissions for each CredentialsRequest "Manual": CredentialsRequests must be handled manually by the user
For each of the following platforms, the field can set to the specified values. For all other platforms, the field must not be set. AWS: "Mint", "Passthrough", "Manual" Azure: "Passthrough", "Manual" AzureStack: "Manual" GCP: "Mint", "Passthrough", "Manual" IBMCloud: "Manual" PowerVS: "Manual" Nutanix: "Manual"
CredentialsMode is used to explicitly set the mode with which CredentialRequests are satisfied.
If this field is set, then the installer will not attempt to query the cloud permissions before attempting
installation. If the field is not set or empty, then the installer will perform its normal verification that the
credentials provided are sufficient to perform an installation.
There are three possible values for this field, but the valid values are dependent upon the platform being used.
"Mint": create new credentials with a subset of the overall permissions for each CredentialsRequest
"Passthrough": copy the credentials with all of the overall permissions for each CredentialsRequest
"Manual": CredentialsRequests must be handled manually by the user
For each of the following platforms, the field can set to the specified values. For all other platforms, the
field must not be set.
AWS: "Mint", "Passthrough", "Manual"
Azure: "Passthrough", "Manual"
AzureStack: "Manual"
GCP: "Mint", "Passthrough", "Manual"
IBMCloud: "Manual"
PowerVS: "Manual"
Nutanix: "Manual"
featureGates <[]string>
FeatureGates enables a set of custom feature gates. May only be used in conjunction with FeatureSet "CustomNoUpgrade". Features may be enabled or disabled by providing a true or false value for the feature gate. E.g. "featureGates": ["FeatureGate1=true", "FeatureGate2=false"].
FeatureGates enables a set of custom feature gates.
May only be used in conjunction with FeatureSet "CustomNoUpgrade".
Features may be enabled or disabled by providing a true or false value for the feature gate.
E.g. "featureGates": ["FeatureGate1=true", "FeatureGate2=false"].
featureSet <string>
FeatureSet enables features that are not part of the default feature set. Valid values are "Default", "TechPreviewNoUpgrade" and "CustomNoUpgrade". When omitted, the "Default" feature set is used.
FeatureSet enables features that are not part of the default feature set.
Valid values are "Default", "TechPreviewNoUpgrade" and "CustomNoUpgrade".
When omitted, the "Default" feature set is used.
fips <boolean>
Default: false
FIPS configures https://www.nist.gov/itl/fips-general-information
imageContentSources <[]object>
ImageContentSources lists sources/repositories for the release-image content. The field is deprecated. Please use imageDigestSources.
ImageContentSource defines a list of sources/repositories that can be used to pull content. The field is deprecated. Please use imageDigestSources.
ImageContentSources lists sources/repositories for the release-image content.
The field is deprecated. Please use imageDigestSources.
ImageContentSource defines a list of sources/repositories that can be used to pull content.
The field is deprecated. Please use imageDigestSources.
imageDigestSources <[]object>
ImageDigestSources lists sources/repositories for the release-image content.
ImageDigestSource defines a list of sources/repositories that can be used to pull content.
kind <string>
Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <object> -required-
<empty>
networking <object>
Networking is the configuration for the pod network provider in the cluster.
Networking is the configuration for the pod network provider in
the cluster.
operatorPublishingStrategy <object>
OperatorPublishingStrategy controls the visibility of ingress and apiserver. Defaults to public.
platform <object> -required-
Platform is the configuration for the specific platform upon which to perform the installation.
Platform is the configuration for the specific platform upon which to
perform the installation.
proxy <object>
Proxy defines the proxy settings for the cluster. If unset, the cluster will not be configured to use a proxy.
Proxy defines the proxy settings for the cluster.
If unset, the cluster will not be configured to use a proxy.
publish <string>
Default: "External"
Valid Values: "","External","Internal"
Publish controls how the user facing endpoints of the cluster like the Kubernetes API, OpenShift routes etc. are exposed. When no strategy is specified, the strategy is "External".
Publish controls how the user facing endpoints of the cluster like the Kubernetes API, OpenShift routes etc. are exposed.
When no strategy is specified, the strategy is "External".
pullSecret <string> -required-
PullSecret is the secret to use when pulling images.
@@ -119,7 +167,8 @@ func Test_PrintFields(t *testing.T) {
BareMetal is the configuration used when installing on bare metal.
external <object>
External is the configuration used when installing on an external cloud provider.
External is the configuration used when installing on
an external cloud provider.
gcp <object>
GCP is the configuration used when installing on Google Cloud Platform.
@@ -128,7 +177,8 @@ func Test_PrintFields(t *testing.T) {
IBMCloud is the configuration used when installing on IBM Cloud.
none <object>
None is the empty configuration used when installing on an unsupported platform.
None is the empty configuration used when installing on an unsupported
platform.
nutanix <object>
Nutanix is the configuration used when installing on Nutanix.
@@ -148,51 +198,95 @@ func Test_PrintFields(t *testing.T) {
path: []string{"platform", "aws"},
desc: `FIELDS:
amiID <string>
The field is deprecated. AMIID is the AMI that should be used to boot machines for the cluster. If set, the AMI should belong to the same region as the cluster.
The field is deprecated. AMIID is the AMI that should be used to boot
machines for the cluster. If set, the AMI should belong to the same
region as the cluster.
bestEffortDeleteIgnition <boolean>
BestEffortDeleteIgnition is an optional field that can be used to ignore errors from S3 deletion of ignition objects during cluster bootstrap. The default behavior is to fail the installation if ignition objects cannot be deleted. Enable this functionality when there are known reasons disallowing their deletion.
BestEffortDeleteIgnition is an optional field that can be used to ignore errors from S3 deletion of ignition
objects during cluster bootstrap. The default behavior is to fail the installation if ignition objects cannot be
deleted. Enable this functionality when there are known reasons disallowing their deletion.
defaultMachinePlatform <object>
DefaultMachinePlatform is the default configuration used when installing on AWS for machine pools which do not define their own platform configuration.
DefaultMachinePlatform is the default configuration used when
installing on AWS for machine pools which do not define their own
platform configuration.
experimentalPropagateUserTags <boolean>
The field is deprecated. ExperimentalPropagateUserTags is an experimental flag that directs in-cluster operators to include the specified user tags in the tags of the AWS resources that the operators create.
The field is deprecated. ExperimentalPropagateUserTags is an experimental
flag that directs in-cluster operators to include the specified
user tags in the tags of the AWS resources that the operators create.
hostedZone <string>
HostedZone is the ID of an existing hosted zone into which to add DNS records for the cluster's internal API. An existing hosted zone can only be used when also using existing subnets. The hosted zone must be associated with the VPC containing the subnets. Leave the hosted zone unset to have the installer create the hosted zone on your behalf.
HostedZone is the ID of an existing hosted zone into which to add DNS
records for the cluster's internal API. An existing hosted zone can
only be used when also using existing subnets. The hosted zone must be
associated with the VPC containing the subnets.
Leave the hosted zone unset to have the installer create the hosted zone
on your behalf.
hostedZoneRole <string>
HostedZoneRole is the ARN of an IAM role to be assumed when performing operations on the provided HostedZone. HostedZoneRole can be used in a shared VPC scenario when the private hosted zone belongs to a different account than the rest of the cluster resources. If HostedZoneRole is set, HostedZone must also be set.
HostedZoneRole is the ARN of an IAM role to be assumed when performing
operations on the provided HostedZone. HostedZoneRole can be used
in a shared VPC scenario when the private hosted zone belongs to a
different account than the rest of the cluster resources.
If HostedZoneRole is set, HostedZone must also be set.
lbType <string>
LBType is an optional field to specify a load balancer type. When this field is specified, all ingresscontrollers (including the default ingresscontroller) will be created using the specified load-balancer type by default.
Following are the accepted values:
* "Classic": A Classic Load Balancer that makes routing decisions at either the transport layer (TCP/SSL) or the application layer (HTTP/HTTPS). See the following for additional details: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#clb
* "NLB": A Network Load Balancer that makes routing decisions at the transport layer (TCP/SSL). See the following for additional details: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#nlb
If this field is not set explicitly, it defaults to "Classic". This default is subject to change over time.
LBType is an optional field to specify a load balancer type.
When this field is specified, all ingresscontrollers (including the
default ingresscontroller) will be created using the specified load-balancer
type by default.
Following are the accepted values:
* "Classic": A Classic Load Balancer that makes routing decisions at
either the transport layer (TCP/SSL) or the application layer
(HTTP/HTTPS). See the following for additional details:
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#clb
* "NLB": A Network Load Balancer that makes routing decisions at the
transport layer (TCP/SSL). See the following for additional details:
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#nlb
If this field is not set explicitly, it defaults to "Classic". This
default is subject to change over time.
preserveBootstrapIgnition <boolean>
PreserveBootstrapIgnition is deprecated. Use bestEffortDeleteIgnition instead.
propagateUserTags <boolean>
PropagateUserTags is a flag that directs in-cluster operators to include the specified user tags in the tags of the AWS resources that the operators create.
PropagateUserTags is a flag that directs in-cluster operators
to include the specified user tags in the tags of the
AWS resources that the operators create.
publicIpv4Pool <string>
PublicIpv4Pool is an optional field that can be used to tell the installation process to use Public IPv4 address that you bring to your AWS account with BYOIP.
PublicIpv4Pool is an optional field that can be used to tell the installation process to use
Public IPv4 address that you bring to your AWS account with BYOIP.
region <string> -required-
Region specifies the AWS region where the cluster will be created.
serviceEndpoints <[]object>
ServiceEndpoints list contains custom endpoints which will override default service endpoint of AWS Services. There must be only one ServiceEndpoint for a service.
ServiceEndpoint store the configuration for services to override existing defaults of AWS Services.
ServiceEndpoints list contains custom endpoints which will override default
service endpoint of AWS Services.
There must be only one ServiceEndpoint for a service.
ServiceEndpoint store the configuration for services to
override existing defaults of AWS Services.
subnets <[]string>
Subnets specifies existing subnets (by ID) where cluster resources will be created. Leave unset to have the installer create subnets in a new VPC on your behalf.
Subnets specifies existing subnets (by ID) where cluster
resources will be created. Leave unset to have the installer
create subnets in a new VPC on your behalf.
userTags <object>
UserTags additional keys and values that the installer will add as tags to all resources that it creates. Resources created by the cluster itself may not include these tags.`,
UserTags additional keys and values that the installer will add
as tags to all resources that it creates. Resources created by the
cluster itself may not include these tags.`,
}, {
path: []string{"platform", "azure"},
desc: `FIELDS:
@@ -204,7 +298,9 @@ func Test_PrintFields(t *testing.T) {
cloudName <string>
Valid Values: "","AzurePublicCloud","AzureUSGovernmentCloud","AzureChinaCloud","AzureGermanCloud","AzureStackCloud"
cloudName is the name of the Azure cloud environment which can be used to configure the Azure SDK with the appropriate Azure API endpoints. If empty, the value is equal to "AzurePublicCloud".
cloudName is the name of the Azure cloud environment which can be used to configure the Azure SDK
with the appropriate Azure API endpoints.
If empty, the value is equal to "AzurePublicCloud".
clusterOSImage <string>
ClusterOSImage is the url of a storage blob in the Azure Stack environment containing an RHCOS VHD. This field is required for Azure Stack and not applicable to Azure.
@@ -219,7 +315,9 @@ func Test_PrintFields(t *testing.T) {
CustomerManagedKey has the keys needed to encrypt the storage account.
defaultMachinePlatform <object>
DefaultMachinePlatform is the default configuration used when installing on Azure for machine pools which do not define their own platform configuration.
DefaultMachinePlatform is the default configuration used when
installing on Azure for machine pools which do not define their own
platform configuration.
networkResourceGroupName <string>
NetworkResourceGroupName specifies the network resource group that contains an existing VNet
@@ -227,16 +325,24 @@ func Test_PrintFields(t *testing.T) {
outboundType <string>
Default: "Loadbalancer"
Valid Values: "","Loadbalancer","NatGateway","UserDefinedRouting"
OutboundType is a strategy for how egress from cluster is achieved. When not specified default is "Loadbalancer". "NatGateway" is only available in TechPreview.
OutboundType is a strategy for how egress from cluster is achieved. When not specified default is "Loadbalancer".
"NatGateway" is only available in TechPreview.
region <string> -required-
Region specifies the Azure region where the cluster will be created.
resourceGroupName <string>
ResourceGroupName is the name of an already existing resource group where the cluster should be installed. This resource group should only be used for this specific cluster and the cluster components will assume ownership of all resources in the resource group. Destroying the cluster using installer will delete this resource group. This resource group must be empty with no other resources when trying to use it for creating a cluster. If empty, a new resource group will created for the cluster.
ResourceGroupName is the name of an already existing resource group where the cluster should be installed.
This resource group should only be used for this specific cluster and the cluster components will assume
ownership of all resources in the resource group. Destroying the cluster using installer will delete this
resource group.
This resource group must be empty with no other resources when trying to use it for creating a cluster.
If empty, a new resource group will created for the cluster.
userTags <object>
UserTags has additional keys and values that the installer will add as tags to all resources that it creates on AzurePublicCloud alone. Resources created by the cluster itself may not include these tags.
UserTags has additional keys and values that the installer will add
as tags to all resources that it creates on AzurePublicCloud alone.
Resources created by the cluster itself may not include these tags.
virtualNetwork <string>
VirtualNetwork specifies the name of an existing VNet for the installer to use`,
@@ -253,10 +359,13 @@ func Test_PrintFields(t *testing.T) {
path: []string{"platform", "aws", "serviceEndpoints"},
desc: `FIELDS:
name <string> -required-
Name is the name of the AWS service. This must be provided and cannot be empty.
Name is the name of the AWS service.
This must be provided and cannot be empty.
url <string> -required-
URL is fully qualified URI with scheme https, that overrides the default generated endpoint for a client. This must be provided and cannot be empty.`,
URL is fully qualified URI with scheme https, that overrides the default generated
endpoint for a client.
This must be provided and cannot be empty.`,
}, {
path: []string{"platform", "aws", "serviceEndpoints", "url"},
desc: ``,
@@ -298,7 +407,8 @@ VERSION: v1
RESOURCE: <string>
Default: "External"
Valid Values: "","External","Internal"
Publish controls how the user facing endpoints of the cluster like the Kubernetes API, OpenShift routes etc. are exposed. When no strategy is specified, the strategy is "External".
Publish controls how the user facing endpoints of the cluster like the Kubernetes API, OpenShift routes etc. are exposed.
When no strategy is specified, the strategy is "External".
`,
}, {
path: []string{"platform"},
@@ -307,7 +417,8 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <object>
Platform is the configuration for the specific platform upon which to perform the installation.
Platform is the configuration for the specific platform upon which to
perform the installation.
`,
}, {
path: []string{"platform", "aws"},
@@ -343,7 +454,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <[]string>
Subnets specifies existing subnets (by ID) where cluster resources will be created. Leave unset to have the installer create subnets in a new VPC on your behalf.
Subnets specifies existing subnets (by ID) where cluster
resources will be created. Leave unset to have the installer
create subnets in a new VPC on your behalf.
`,
}, {
path: []string{"platform", "aws", "userTags"},
@@ -352,7 +465,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <object>
UserTags additional keys and values that the installer will add as tags to all resources that it creates. Resources created by the cluster itself may not include these tags.
UserTags additional keys and values that the installer will add
as tags to all resources that it creates. Resources created by the
cluster itself may not include these tags.
`,
}, {
path: []string{"platform", "aws", "serviceEndpoints"},
@@ -361,7 +476,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <[]object>
ServiceEndpoints list contains custom endpoints which will override default service endpoint of AWS Services. There must be only one ServiceEndpoint for a service.
ServiceEndpoints list contains custom endpoints which will override default
service endpoint of AWS Services.
There must be only one ServiceEndpoint for a service.
`,
}, {
path: []string{"platform", "aws", "serviceEndpoints", "url"},
@@ -370,7 +487,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <string>
URL is fully qualified URI with scheme https, that overrides the default generated endpoint for a client. This must be provided and cannot be empty.
URL is fully qualified URI with scheme https, that overrides the default generated
endpoint for a client.
This must be provided and cannot be empty.
`,
}, {
path: []string{"compute", "platform", "aws", "iamRole"},
@@ -379,7 +498,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <string>
IAMRole is the name of the IAM Role to use for the instance profile of the machine. Leave unset to have the installer create the IAM Role on your behalf. Cannot be specified together with iamProfile.
IAMRole is the name of the IAM Role to use for the instance profile of the machine.
Leave unset to have the installer create the IAM Role on your behalf.
Cannot be specified together with iamProfile.
`,
}, {
path: []string{"controlPlane", "platform", "aws", "iamRole"},
@@ -388,7 +509,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <string>
IAMRole is the name of the IAM Role to use for the instance profile of the machine. Leave unset to have the installer create the IAM Role on your behalf. Cannot be specified together with iamProfile.
IAMRole is the name of the IAM Role to use for the instance profile of the machine.
Leave unset to have the installer create the IAM Role on your behalf.
Cannot be specified together with iamProfile.
`,
}, {
path: []string{"platform", "aws", "defaultMachinePlatform", "iamRole"},
@@ -397,7 +520,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <string>
IAMRole is the name of the IAM Role to use for the instance profile of the machine. Leave unset to have the installer create the IAM Role on your behalf. Cannot be specified together with iamProfile.
IAMRole is the name of the IAM Role to use for the instance profile of the machine.
Leave unset to have the installer create the IAM Role on your behalf.
Cannot be specified together with iamProfile.
`,
}, {
path: []string{"compute", "platform", "aws", "iamProfile"},
@@ -406,7 +531,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <string>
IAMProfile is the name of the IAM instance profile to use for the machine. Leave unset to have the installer create the IAM Profile on your behalf. Cannot be specified together with iamRole.
IAMProfile is the name of the IAM instance profile to use for the machine.
Leave unset to have the installer create the IAM Profile on your behalf.
Cannot be specified together with iamRole.
`,
}, {
path: []string{"controlPlane", "platform", "aws", "iamProfile"},
@@ -415,7 +542,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <string>
IAMProfile is the name of the IAM instance profile to use for the machine. Leave unset to have the installer create the IAM Profile on your behalf. Cannot be specified together with iamRole.
IAMProfile is the name of the IAM instance profile to use for the machine.
Leave unset to have the installer create the IAM Profile on your behalf.
Cannot be specified together with iamRole.
`,
}, {
path: []string{"platform", "aws", "defaultMachinePlatform", "iamProfile"},
@@ -424,7 +553,9 @@ KIND: InstallConfig
VERSION: v1
RESOURCE: <string>
IAMProfile is the name of the IAM instance profile to use for the machine. Leave unset to have the installer create the IAM Profile on your behalf. Cannot be specified together with iamRole.
IAMProfile is the name of the IAM instance profile to use for the machine.
Leave unset to have the installer create the IAM Profile on your behalf.
Cannot be specified together with iamRole.
`,
}}
for _, test := range cases {

View File

@@ -41,6 +41,7 @@ var (
"c3": {PDSSD, PDBalanced, HyperDiskBalanced},
"c3d": {PDSSD, PDBalanced, HyperDiskBalanced},
"c4": {HyperDiskBalanced},
"c4a": {HyperDiskBalanced},
"e2": {PDStandard, PDSSD, PDBalanced},
"m1": {PDSSD, PDBalanced, HyperDiskBalanced},
"n1": {PDStandard, PDSSD, PDBalanced},

View File

@@ -0,0 +1,43 @@
package tagservice
import (
"context"
"fmt"
tags "google.golang.org/api/cloudresourcemanager/v3"
"google.golang.org/api/option"
)
// TagService is a pass through wrapper for google.golang.org/api/cloudresourcemanager/v3
// to enable tests to mock this struct and control behavior.
type TagService interface {
GetNamespacedName(context.Context, string) (*tags.TagValue, error)
}
// tagService implements TagService interface.
type tagService struct {
tagValuesService *tags.TagValuesService
}
// BuilderFuncType is function type for building GCP tag client.
type BuilderFuncType func(ctx context.Context, serviceAccountJSON string) (TagService, error)
// NewTagService return a new tagService.
func NewTagService(ctx context.Context, serviceAccountJSON string) (TagService, error) {
service, err := tags.NewService(ctx, option.WithCredentialsJSON([]byte(serviceAccountJSON)))
if err != nil {
return nil, fmt.Errorf("could not create new tag service: %w", err)
}
return &tagService{
tagValuesService: tags.NewTagValuesService(service),
}, nil
}
// GetNamespacedName returns the tag's metadata fetched using its namespaced name.
func (t *tagService) GetNamespacedName(ctx context.Context, namespacedName string) (*tags.TagValue, error) {
return t.tagValuesService.GetNamespaced().
Context(ctx).
Name(namespacedName).
Do()
}

View File

@@ -0,0 +1,30 @@
package tagservice
import (
"context"
tags "google.golang.org/api/cloudresourcemanager/v3"
)
// MockTagService mocks TagService interface for tests.
type MockTagService struct {
MockGetNamespacedName func(context.Context, string) (*tags.TagValue, error)
}
// NewMockTagService returns new mock of tagService.
func NewMockTagService() *MockTagService {
return &MockTagService{}
}
// NewMockTagServiceBuilder returns new mock for creating GCP tag client.
func NewMockTagServiceBuilder(ctx context.Context, serviceAccountJSON string) (TagService, error) {
return NewMockTagService(), nil
}
// GetNamespacedName returns mock metadata of the requested tag.
func (m *MockTagService) GetNamespacedName(ctx context.Context, name string) (*tags.TagValue, error) {
if m.MockGetNamespacedName == nil {
return nil, nil
}
return m.MockGetNamespacedName(ctx, name)
}

View File

@@ -26,6 +26,7 @@ const (
// machineTypePrefixArchitectureMap contains a map of (machineTypePrefix, architecture) tuples
var machineTypePrefixArchitectureMap = map[string]NormalizedArch{
"c4a": ArchitectureArm64,
"t2a": ArchitectureArm64,
}

View File

@@ -15,13 +15,27 @@ package util
import (
"context"
"errors"
"fmt"
"net/http"
machinecontroller "github.com/openshift/machine-api-operator/pkg/controller/machine"
tagservice "github.com/openshift/machine-api-provider-gcp/pkg/cloud/gcp/actuators/services/tags"
configv1 "github.com/openshift/api/config/v1"
machinev1 "github.com/openshift/api/machine/v1beta1"
"github.com/googleapis/gax-go/v2/apierror"
"k8s.io/klog/v2"
controllerclient "sigs.k8s.io/controller-runtime/pkg/client"
)
const (
// maxUserTagLimit is the maximum userTags that can be configured as defined in openshift/api.
// https://github.com/openshift/api/blob/master/machine/v1beta1/types_gcpprovider.go#L153-L160
maxUserTagLimit = 50
// globalInfrastructureName is the default name of the Infrastructure object
globalInfrastructureName = "cluster"
@@ -39,7 +53,6 @@ func GetInfrastructure(client controllerclient.Client) (*configv1.Infrastructure
if err := client.Get(context.Background(), infraName, infra); err != nil {
return nil, fmt.Errorf("failed to get infrastructure: %w", err)
}
return infra, nil
}
@@ -119,3 +132,115 @@ func GetLabelsList(userLabelsAllowed bool, client controllerclient.Client, machi
return labels, nil
}
// getInfraResourceTagsList returns the user-defined tags present in the
// status sub-resource of Infrastructure.
func getInfraResourceTagsList(platformStatus *configv1.PlatformStatus) []machinev1.ResourceManagerTag {
if platformStatus == nil || platformStatus.GCP == nil || platformStatus.GCP.ResourceTags == nil {
return nil
}
tags := make([]machinev1.ResourceManagerTag, len(platformStatus.GCP.ResourceTags))
for i, tag := range platformStatus.GCP.ResourceTags {
tags[i] = machinev1.ResourceManagerTag{
ParentID: tag.ParentID,
Key: tag.Key,
Value: tag.Value,
}
}
return tags
}
// getTagValuesNames returns the list of tags in Compute APIs required format, which
// is a map containing keys of the form Key(`tagKeys/{tag_key_id}`) and values in the
// form (`tagValues/{tag_value_id}`).
func getTagValuesNames(ctx context.Context, tagService tagservice.TagService, tagList []machinev1.ResourceManagerTag) (map[string]string, error) {
// identify tags which are inaccessible due to permissions issues
// or does not exist and report back to user to fix in one go.
inaccessibleTags := make([]string, 0)
tagValueList := make(map[string]string, len(tagList))
for _, tag := range tagList {
name := fmt.Sprintf("%s/%s/%s", tag.ParentID, tag.Key, tag.Value)
value, err := tagService.GetNamespacedName(ctx, name)
if err != nil {
var gErr *apierror.APIError
// google API returns StatusForbidden or StatusNotFound when the tag
// does not exist, since it could be because of permission issues
// or genuinely tag does not exist.
if errors.As(err, &gErr) && (gErr.HTTPCode() == http.StatusNotFound ||
gErr.HTTPCode() == http.StatusForbidden) {
klog.Errorf("does not have permission to access %s tag or tag does not exist", name)
inaccessibleTags = append(inaccessibleTags, name)
continue
}
// fetching tag's metadata could fail due to errors like timeout, server
// internal errors, permission issues among others. Since tag's key and
// value names are required for binding tag to compute resource, will
// return error and retry during next reconciliation.
return nil, fmt.Errorf("failed to fetch %s tag details: %w", name, err)
}
tagValueList[value.Parent] = value.Name
}
if len(inaccessibleTags) != 0 {
return nil, machinecontroller.InvalidMachineConfiguration("%v tag(s) do not exist or does not have required permission to access", inaccessibleTags)
}
return tagValueList, nil
}
// mergeInfraProviderSpecTags merges user-defined tags in Infrastructure.Status and
// GCPMachineProviderSpec, with precedence given to those in GCPMachineProviderSpec
// for new or updated tags.
func mergeInfraProviderSpecTags(infraTags []machinev1.ResourceManagerTag, providerSpecTags []machinev1.ResourceManagerTag) []machinev1.ResourceManagerTag {
mergedTags := make([]machinev1.ResourceManagerTag, 0, len(infraTags))
for _, tag := range providerSpecTags {
mergedTags = append(mergedTags, tag)
}
for _, iTag := range infraTags {
appendTag := true
for _, pTag := range providerSpecTags {
if iTag.ParentID == pTag.ParentID && iTag.Key == pTag.Key {
appendTag = false
break
}
}
if appendTag {
mergedTags = append(mergedTags, iTag)
}
}
return mergedTags
}
// GetResourceManagerTags returns the merged list of user-defined tags in Infrastructure.Status
// and GCPMachineProviderSpec to apply on the resources.
func GetResourceManagerTags(ctx context.Context,
client controllerclient.Client,
tagService tagservice.TagService,
providerSpecTags []machinev1.ResourceManagerTag) (map[string]string, error) {
infra, err := GetInfrastructure(client)
if err != nil {
return nil, fmt.Errorf("failed to get cluster infrastructure: %w", err)
}
userTags := getInfraResourceTagsList(infra.Status.PlatformStatus)
if len(userTags) == 0 && len(providerSpecTags) == 0 {
klog.V(3).Infof("user-defined tags in infrastructure and machineProviderSpec is empty")
return nil, nil
}
mergedTags := mergeInfraProviderSpecTags(userTags, providerSpecTags)
if len(mergedTags) > maxUserTagLimit {
return nil, fmt.Errorf("maximum of %d tags can be added to a compute instance, "+
"infrastructure.status.resourceTags and machines.spec.providerSpec.resourceManagerTags "+
"combined tag count is %d", maxUserTagLimit, len(mergedTags))
}
return getTagValuesNames(ctx, tagService, mergedTags)
}

7
vendor/modules.txt vendored
View File

@@ -1159,8 +1159,9 @@ github.com/openshift/machine-api-operator/pkg/controller/machine
github.com/openshift/machine-api-operator/pkg/metrics
github.com/openshift/machine-api-operator/pkg/util
github.com/openshift/machine-api-operator/pkg/util/conditions
# github.com/openshift/machine-api-provider-gcp v0.0.1-0.20231014045125-6096cc86f3ba
## explicit; go 1.20
# github.com/openshift/machine-api-provider-gcp v0.0.1-0.20241024094404-0d6fbdb09401
## explicit; go 1.22.0
github.com/openshift/machine-api-provider-gcp/pkg/cloud/gcp/actuators/services/tags
github.com/openshift/machine-api-provider-gcp/pkg/cloud/gcp/actuators/util
# github.com/openshift/machine-api-provider-ibmcloud v0.0.0-20231207164151-6b0b8ea7b16d
## explicit; go 1.19
@@ -2267,7 +2268,7 @@ sigs.k8s.io/controller-runtime/pkg/webhook
sigs.k8s.io/controller-runtime/pkg/webhook/admission
sigs.k8s.io/controller-runtime/pkg/webhook/conversion
sigs.k8s.io/controller-runtime/pkg/webhook/internal/metrics
# sigs.k8s.io/controller-tools v0.12.0
# sigs.k8s.io/controller-tools v0.14.0
## explicit; go 1.20
sigs.k8s.io/controller-tools/cmd/controller-gen
sigs.k8s.io/controller-tools/pkg/crd

View File

@@ -477,6 +477,9 @@ func (m Default) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
if err != nil {
return err
}
if schema.Type == "array" && string(marshalledDefault) == "{}" {
marshalledDefault = []byte("[]")
}
schema.Default = &apiext.JSON{Raw: marshalledDefault}
return nil
}

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright2019 The Kubernetes Authors.

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright2019 The Kubernetes Authors.

View File

@@ -176,7 +176,6 @@ type ObjectGenCtx struct {
func writeHeader(pkg *loader.Package, out io.Writer, packageName string, imports *importsList, headerText string) {
// NB(directxman12): blank line after build tags to distinguish them from comments
_, err := fmt.Fprintf(out, `//go:build !ignore_autogenerated
// +build !ignore_autogenerated
%[3]s

View File

@@ -374,7 +374,8 @@ func (c *copyMethodMaker) genMapDeepCopy(actualName *namingInfo, mapType *types.
c.IfElse("val == nil", func() {
c.Line("(*out)[key] = nil")
}, func() {
c.Line("in, out := &val, &outVal")
c.Line("inVal := (*in)[key]")
c.Line("in, out := &inVal, &outVal")
c.genDeepCopyIntoBlock(&namingInfo{typeInfo: mapType.Elem()}, mapType.Elem())
})
c.Line("(*out)[key] = outVal")

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright2019 The Kubernetes Authors.

View File

@@ -20,7 +20,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"golang.org/x/tools/go/packages"
@@ -214,7 +213,7 @@ func (g GenerationContext) ReadFile(path string) ([]byte, error) {
return nil, err
}
defer file.Close()
return ioutil.ReadAll(file)
return io.ReadAll(file)
}
// ForRoots produces a Runtime to run the given generators against the

View File

@@ -136,6 +136,9 @@ func protoFromOptions(optionsRegistry *markers.Registry, options []string) (prot
switch val := val.(type) {
case Generator:
gens = append(gens, &val)
if _, alreadyExists := gensByName[defn.Name]; alreadyExists {
return protoRuntime{}, fmt.Errorf("multiple instances of '%s' generator specified", defn.Name)
}
gensByName[defn.Name] = &val
case OutputRule:
_, genName := splitOutputRuleOption(defn.Name)

View File

@@ -19,7 +19,6 @@ package genall
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
@@ -92,7 +91,7 @@ var OutputToNothing = outputToNothing{}
type outputToNothing struct{}
func (o outputToNothing) Open(_ *loader.Package, _ string) (io.WriteCloser, error) {
return nopCloser{ioutil.Discard}, nil
return nopCloser{io.Discard}, nil
}
// +controllertools:marker:generateHelp:category=""

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright2019 The Kubernetes Authors.

View File

@@ -23,7 +23,6 @@ import (
"go/scanner"
"go/token"
"go/types"
"io/ioutil"
"os"
"path/filepath"
"regexp"
@@ -111,7 +110,7 @@ func (p *Package) NeedSyntax() {
for i, filename := range p.CompiledGoFiles {
go func(i int, filename string) {
defer wg.Done()
src, err := ioutil.ReadFile(filename)
src, err := os.ReadFile(filename)
if err != nil {
p.AddError(err)
return

View File

@@ -31,7 +31,7 @@ import (
type Collector struct {
*Registry
byPackage map[string]map[ast.Node]MarkerValues
byPackage map[*loader.Package]map[ast.Node]MarkerValues
mu sync.Mutex
}
@@ -53,7 +53,7 @@ func (c *Collector) init() {
c.Registry = &Registry{}
}
if c.byPackage == nil {
c.byPackage = make(map[string]map[ast.Node]MarkerValues)
c.byPackage = make(map[*loader.Package]map[ast.Node]MarkerValues)
}
}
@@ -75,7 +75,7 @@ func (c *Collector) init() {
func (c *Collector) MarkersInPackage(pkg *loader.Package) (map[ast.Node]MarkerValues, error) {
c.mu.Lock()
c.init()
if markers, exist := c.byPackage[pkg.ID]; exist {
if markers, exist := c.byPackage[pkg]; exist {
c.mu.Unlock()
return markers, nil
}
@@ -91,8 +91,7 @@ func (c *Collector) MarkersInPackage(pkg *loader.Package) (map[ast.Node]MarkerVa
c.mu.Lock()
defer c.mu.Unlock()
c.byPackage[pkg.ID] = markers
c.byPackage[pkg] = markers
return markers, nil
}

View File

@@ -310,6 +310,7 @@ func guessType(scanner *sc.Scanner, raw string, allowSlice bool) *Argument {
// We'll cross that bridge when we get there.
// look ahead till we can figure out if this is a map or a slice
hint = peekNoSpace(subScanner)
firstElemType := guessType(subScanner, subRaw, false)
if firstElemType.Type == StringType {
// might be a map or slice, parse the string and check for colon
@@ -317,8 +318,9 @@ func guessType(scanner *sc.Scanner, raw string, allowSlice bool) *Argument {
var keyVal string // just ignore this
(&Argument{Type: StringType}).parseString(subScanner, raw, reflect.Indirect(reflect.ValueOf(&keyVal)))
if subScanner.Scan() == ':' {
if token := subScanner.Scan(); token == ':' || hint == '}' {
// it's got a string followed by a colon -- it's a map
// or an empty map in case of {}
return &Argument{
Type: MapType,
ItemType: &Argument{Type: AnyType},

View File

@@ -58,6 +58,13 @@ func extractDoc(node ast.Node, decl *ast.GenDecl) string {
}
outGroup.List = append(outGroup.List, comment)
}
isAsteriskComment := false
for _, l := range outGroup.List {
if strings.HasPrefix(l.Text, "/*") {
isAsteriskComment = true
break
}
}
// split lines, and re-join together as a single
// paragraph, respecting double-newlines as
@@ -69,10 +76,12 @@ func extractDoc(node ast.Node, decl *ast.GenDecl) string {
}
for i, line := range outLines {
// Trim any extranous whitespace,
// for handling /*…*/-style comments,
// which have whitespace preserved in go/ast:
line = strings.TrimSpace(line)
if isAsteriskComment {
// Trim any extranous whitespace,
// for handling /*…*/-style comments,
// which have whitespace preserved in go/ast:
line = strings.TrimSpace(line)
}
// Respect that double-newline means
// actual newline:
@@ -82,8 +91,7 @@ func extractDoc(node ast.Node, decl *ast.GenDecl) string {
outLines[i] = line
}
}
return strings.Join(outLines, " ")
return strings.Join(outLines, "\n")
}
// PackageMarkers collects all the package-level marker values for the given package.

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright2019 The Kubernetes Authors.

View File

@@ -18,7 +18,7 @@ package schemapatcher
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"gopkg.in/yaml.v3"
@@ -335,7 +335,7 @@ func (e *partialCRD) setVersionedSchemata(newSchemata map[string]apiext.JSONSche
// minimally invasive. Returned CRDs are mapped by group-kind.
func crdsFromDirectory(ctx *genall.GenerationContext, dir string) (map[schema.GroupKind]*partialCRDSet, error) {
res := map[schema.GroupKind]*partialCRDSet{}
dirEntries, err := ioutil.ReadDir(dir)
dirEntries, err := os.ReadDir(dir)
if err != nil {
return nil, err
}

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright2019 The Kubernetes Authors.

View File

@@ -19,7 +19,7 @@ limitations under the License.
//
// The markers take the form:
//
// +kubebuilder:webhook:webhookVersions=<[]string>,failurePolicy=<string>,matchPolicy=<string>,groups=<[]string>,resources=<[]string>,verbs=<[]string>,versions=<[]string>,name=<string>,path=<string>,mutating=<bool>,sideEffects=<string>,admissionReviewVersions=<[]string>,reinvocationPolicy=<string>
// +kubebuilder:webhook:webhookVersions=<[]string>,failurePolicy=<string>,matchPolicy=<string>,groups=<[]string>,resources=<[]string>,verbs=<[]string>,versions=<[]string>,name=<string>,path=<string>,mutating=<bool>,sideEffects=<string>,timeoutSeconds=<int>,admissionReviewVersions=<[]string>,reinvocationPolicy=<string>
package webhook
import (
@@ -81,6 +81,11 @@ type Config struct {
// If the value is "NoneOnDryRun", then the webhook is responsible for inspecting the "dryRun" property of the
// AdmissionReview sent in the request, and avoiding side effects if that value is "true."
SideEffects string `marker:",optional"`
// TimeoutSeconds allows configuring how long the API server should wait for a webhook to respond before treating the call as a failure.
// If the timeout expires before the webhook responds, the webhook call will be ignored or the API call will be rejected based on the failure policy.
// The timeout value must be between 1 and 30 seconds.
// The timeout for an admission webhook defaults to 10 seconds.
TimeoutSeconds int `marker:",optional"`
// Groups specifies the API groups that this webhook receives requests for.
Groups []string
@@ -103,7 +108,7 @@ type Config struct {
// are substituted for hyphens. For example, a validating webhook path for type
// batch.tutorial.kubebuilder.io/v1,Kind=CronJob would be
// /validate-batch-tutorial-kubebuilder-io-v1-cronjob
Path string
Path string `marker:"path,optional"`
// WebhookVersions specifies the target API versions of the {Mutating,Validating}WebhookConfiguration objects
// itself to generate. The only supported value is v1. Defaults to v1.
@@ -120,6 +125,14 @@ type Config struct {
// an object, and mutating webhooks can specify a reinvocationPolicy to control
// whether they are reinvoked as well.
ReinvocationPolicy string `marker:"reinvocationPolicy,optional"`
// URL allows mutating webhooks configuration to specify an external URL when generating
// the manifests, instead of using the internal service communication. Should be in format of
// https://address:port/path
// When this option is specified, the serviceConfig.Service is removed from webhook the manifest.
// The URL configuration should be between quotes.
// `url` cannot be specified when `path` is specified.
URL string `marker:"url,optional"`
}
// verbToAPIVariant converts a marker's verb to the proper value for the API.
@@ -152,13 +165,19 @@ func (c Config) ToMutatingWebhook() (admissionregv1.MutatingWebhook, error) {
return admissionregv1.MutatingWebhook{}, err
}
clientConfig, err := c.clientConfig()
if err != nil {
return admissionregv1.MutatingWebhook{}, err
}
return admissionregv1.MutatingWebhook{
Name: c.Name,
Rules: c.rules(),
FailurePolicy: c.failurePolicy(),
MatchPolicy: matchPolicy,
ClientConfig: c.clientConfig(),
ClientConfig: clientConfig,
SideEffects: c.sideEffects(),
TimeoutSeconds: c.timeoutSeconds(),
AdmissionReviewVersions: c.AdmissionReviewVersions,
ReinvocationPolicy: c.reinvocationPolicy(),
}, nil
@@ -175,13 +194,19 @@ func (c Config) ToValidatingWebhook() (admissionregv1.ValidatingWebhook, error)
return admissionregv1.ValidatingWebhook{}, err
}
clientConfig, err := c.clientConfig()
if err != nil {
return admissionregv1.ValidatingWebhook{}, err
}
return admissionregv1.ValidatingWebhook{
Name: c.Name,
Rules: c.rules(),
FailurePolicy: c.failurePolicy(),
MatchPolicy: matchPolicy,
ClientConfig: c.clientConfig(),
ClientConfig: clientConfig,
SideEffects: c.sideEffects(),
TimeoutSeconds: c.timeoutSeconds(),
AdmissionReviewVersions: c.AdmissionReviewVersions,
}, nil
}
@@ -244,15 +269,27 @@ func (c Config) matchPolicy() (*admissionregv1.MatchPolicyType, error) {
}
// clientConfig returns the client config for a webhook.
func (c Config) clientConfig() admissionregv1.WebhookClientConfig {
path := c.Path
return admissionregv1.WebhookClientConfig{
Service: &admissionregv1.ServiceReference{
Name: "webhook-service",
Namespace: "system",
Path: &path,
},
func (c Config) clientConfig() (admissionregv1.WebhookClientConfig, error) {
if (c.Path != "" && c.URL != "") || (c.Path == "" && c.URL == "") {
return admissionregv1.WebhookClientConfig{}, fmt.Errorf("`url` or `path` markers are required and mutually exclusive")
}
path := c.Path
if path != "" {
return admissionregv1.WebhookClientConfig{
Service: &admissionregv1.ServiceReference{
Name: "webhook-service",
Namespace: "system",
Path: &path,
},
}, nil
}
url := c.URL
return admissionregv1.WebhookClientConfig{
URL: &url,
}, nil
}
// sideEffects returns the sideEffects config for a webhook.
@@ -273,6 +310,15 @@ func (c Config) sideEffects() *admissionregv1.SideEffectClass {
return &sideEffects
}
// timeoutSeconds returns the timeoutSeconds config for a webhook.
func (c Config) timeoutSeconds() *int32 {
if c.TimeoutSeconds != 0 {
timeoutSeconds := int32(c.TimeoutSeconds)
return &timeoutSeconds
}
return nil
}
// reinvocationPolicy returns the reinvocationPolicy config for a mutating webhook.
func (c Config) reinvocationPolicy() *admissionregv1.ReinvocationPolicyType {
var reinvocationPolicy admissionregv1.ReinvocationPolicyType
@@ -381,6 +427,11 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
if err := checkSideEffectsForV1(objRaw.Webhooks[i].SideEffects); err != nil {
return err
}
// TimeoutSeconds must be nil or between 1 and 30 seconds, otherwise,
// return an error
if err := checkTimeoutSeconds(objRaw.Webhooks[i].TimeoutSeconds); err != nil {
return err
}
// AdmissionReviewVersions is required in admissionregistration/v1, if this is not set,
// return an error
if len(objRaw.Webhooks[i].AdmissionReviewVersions) == 0 {
@@ -407,6 +458,11 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
if err := checkSideEffectsForV1(objRaw.Webhooks[i].SideEffects); err != nil {
return err
}
// TimeoutSeconds must be nil or between 1 and 30 seconds, otherwise,
// return an error
if err := checkTimeoutSeconds(objRaw.Webhooks[i].TimeoutSeconds); err != nil {
return err
}
// AdmissionReviewVersions is required in admissionregistration/v1, if this is not set,
// return an error
if len(objRaw.Webhooks[i].AdmissionReviewVersions) == 0 {
@@ -451,3 +507,10 @@ func checkSideEffectsForV1(sideEffects *admissionregv1.SideEffectClass) error {
}
return nil
}
func checkTimeoutSeconds(timeoutSeconds *int32) error {
if timeoutSeconds != nil && (*timeoutSeconds < 1 || *timeoutSeconds > 30) {
return fmt.Errorf("TimeoutSeconds must be between 1 and 30 seconds")
}
return nil
}

View File

@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright2019 The Kubernetes Authors.
@@ -49,6 +48,10 @@ func (Config) Help() *markers.DefinitionHelp {
Summary: "specify whether calling the webhook will have side effects. This has an impact on dry runs and `kubectl diff`: if the sideEffect is \"Unknown\" (the default) or \"Some\", then the API server will not call the webhook on a dry-run request and fails instead. If the value is \"None\", then the webhook has no side effects and the API server will call it on dry-run. If the value is \"NoneOnDryRun\", then the webhook is responsible for inspecting the \"dryRun\" property of the AdmissionReview sent in the request, and avoiding side effects if that value is \"true.\"",
Details: "",
},
"TimeoutSeconds": {
Summary: "allows configuring how long the API server should wait for a webhook to respond before treating the call as a failure. If the timeout expires before the webhook responds, the webhook call will be ignored or the API call will be rejected based on the failure policy. The timeout value must be between 1 and 30 seconds. The timeout for an admission webhook defaults to 10 seconds.",
Details: "",
},
"Groups": {
Summary: "specifies the API groups that this webhook receives requests for.",
Details: "",