Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(crds): Migrate from a webhook to CEL validation for aws nodetemplates #4586

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions pkg/apis/crds/karpenter.k8s.aws_awsnodetemplates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ spec:
type: string
description: AMISelector discovers AMIs to be used by Amazon EC2 tags.
type: object
x-kubernetes-validations:
- message: Only one of UserData and AMISelector can be provided
rule: '!has(self.AMISelector) || has(self.AMISelector) != has(self.UserData)'
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
Expand Down Expand Up @@ -215,7 +218,27 @@ spec:
will merge certain fields into this UserData to ensure nodes are
being provisioned with the correct configuration.
type: string
x-kubernetes-validations:
- message: Only one of UserData and AMISelector can be provided
rule: '!has(self.AMISelector) || has(self.AMISelector) != has(self.UserData)'
type: object
x-kubernetes-validations:
- message: If AMIFamily is Custom then AMI Selector must be set
rule: '!has(self.AMIFamily) || !self.AMIFamily == "Custom" || has(self.AMISelector)'
- message: Only one of AMISelector and LaunchTemplate can be provided
rule: '!has(self.AMISelector) || has(self.AMISelector) != has(self.LaunchTemplateName)'
- message: AMI ID must be a valid ami-id
rule: '!has(self.AMISelector) || !has(self.AMISelector["aws-ids"]) ||
self.AMISelector["aws-ids"].matches("^ami-[a-f0-9]{8,17}$")'
- message: AMI ID must be a valid ami-id
rule: '!has(self.AMISelector) || !has(self.AMISelector["aws::ids"])
|| self.AMISelector["aws::ids"].matches("^ami-[a-f0-9]{8,17}$")'
- message: Tags must not match kubernetes patterns
rule: '!has(self.Tags) || !self.Tags.all(e, e.key.matches(''^kubernetes.io/cluster/[0-9A-Za-z][A-Za-z0-9\-_]*$''))'
- message: Tags must not match karpenter provisioner label
rule: '!has(self.Tags) || !self.Tags.all(e, e.key.matches(^karpenter.k8s.aws/provisioner-name$))'
- message: Tags must not match karpenter managed by tag
rule: '!has(self.Tags) || !self.Tags.all(e, e.key.matches(^karpenter.k8s.aws/machine-managed-by$))'
status:
description: AWSNodeTemplateStatus contains the resolved state of the
AWSNodeTemplate
Expand Down
9 changes: 9 additions & 0 deletions pkg/apis/v1alpha1/awsnodetemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ type AWSNodeTemplateSpec struct {
// It must be in the appropriate format based on the AMIFamily in use. Karpenter will merge certain fields into
// this UserData to ensure nodes are being provisioned with the correct configuration.
// +optional
// +kubebuilder:validation:XValidation:message=Only one of UserData and AMISelector can be provided,rule=!has(self.AMISelector) || has(self.AMISelector) != has(self.UserData)
UserData *string `json:"userData,omitempty"`
AWS `json:",inline"`
// AMISelector discovers AMIs to be used by Amazon EC2 tags.
// +optional
// +kubebuilder:validation:XValidation:message=Only one of UserData and AMISelector can be provided,rule=!has(self.AMISelector) || has(self.AMISelector) != has(self.UserData)
AMISelector map[string]string `json:"amiSelector,omitempty" hash:"ignore"`
// DetailedMonitoring controls if detailed monitoring is enabled for instances that are launched
// +optional
Expand All @@ -96,6 +98,13 @@ type AWSNodeTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// +kubebuilder:validation:XValidation:message=If AMIFamily is Custom then AMI Selector must be set,rule=!has(self.AMIFamily) || !self.AMIFamily == "Custom" || has(self.AMISelector)
// +kubebuilder:validation:XValidation:message=Only one of AMISelector and LaunchTemplate can be provided,rule=!has(self.AMISelector) || has(self.AMISelector) != has(self.LaunchTemplateName)
// +kubebuilder:validation:XValidation:message=AMI ID must be a valid ami-id,rule=!has(self.AMISelector) || !has(self.AMISelector["aws-ids"]) || self.AMISelector["aws-ids"].matches("^ami-[a-f0-9]{8,17}$")
// +kubebuilder:validation:XValidation:message=AMI ID must be a valid ami-id,rule=!has(self.AMISelector) || !has(self.AMISelector["aws::ids"]) || self.AMISelector["aws::ids"].matches("^ami-[a-f0-9]{8,17}$")
// +kubebuilder:validation:XValidation:message=Tags must not match kubernetes patterns,rule="!has(self.Tags) || !self.Tags.all(e, e.key.matches('^kubernetes.io/cluster/[0-9A-Za-z][A-Za-z0-9\\-_]*$'))"
// +kubebuilder:validation:XValidation:message=Tags must not match karpenter provisioner label,rule="!has(self.Tags) || !self.Tags.all(e, e.key.matches(^karpenter.k8s.aws/provisioner-name$))"
// +kubebuilder:validation:XValidation:message=Tags must not match karpenter managed by tag,rule="!has(self.Tags) || !self.Tags.all(e, e.key.matches(^karpenter.k8s.aws/machine-managed-by$))"
Spec AWSNodeTemplateSpec `json:"spec,omitempty"`
Status AWSNodeTemplateStatus `json:"status,omitempty"`
}
Expand Down