diff --git a/pkg/apis/v1beta1/nodeclaim.go b/pkg/apis/v1beta1/nodeclaim.go new file mode 100644 index 000000000000..8b4705b11264 --- /dev/null +++ b/pkg/apis/v1beta1/nodeclaim.go @@ -0,0 +1,84 @@ +/* +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "context" + + admissionregistrationv1 "k8s.io/api/admissionregistration/v1" + v1 "k8s.io/api/core/v1" + "knative.dev/pkg/apis" + + "github.com/aws/karpenter-core/pkg/apis/v1beta1" + "github.com/aws/karpenter-core/pkg/scheduling" +) + +// NodeClaim is an alias type for additional validation +// +kubebuilder:object:root=true +type NodeClaim v1beta1.NodeClaim + +// NodeClaimSpec is an alias type for additional validation +type NodeClaimSpec v1beta1.NodeClaimSpec + +func (n *NodeClaim) SupportedVerbs() []admissionregistrationv1.OperationType { + return []admissionregistrationv1.OperationType{ + admissionregistrationv1.Create, + admissionregistrationv1.Update, + } +} + +func (n *NodeClaim) Validate(_ context.Context) (errs *apis.FieldError) { return nil } + +func (n *NodeClaim) SetDefaults(ctx context.Context) { + spec := NodeClaimSpec(n.Spec) + spec.SetDefaults(ctx) + n.Spec = v1beta1.NodeClaimSpec(spec) +} + +func (n *NodeClaimSpec) SetDefaults(_ context.Context) { + requirements := scheduling.NewNodeSelectorRequirements(n.Requirements...) + + // default to linux OS + if !requirements.Has(v1.LabelOSStable) { + n.Requirements = append(n.Requirements, v1.NodeSelectorRequirement{ + Key: v1.LabelOSStable, Operator: v1.NodeSelectorOpIn, Values: []string{string(v1.Linux)}, + }) + } + + // default to amd64 + if !requirements.Has(v1.LabelArchStable) { + n.Requirements = append(n.Requirements, v1.NodeSelectorRequirement{ + Key: v1.LabelArchStable, Operator: v1.NodeSelectorOpIn, Values: []string{v1beta1.ArchitectureAmd64}, + }) + } + + // default to on-demand + if !requirements.Has(v1beta1.CapacityTypeLabelKey) { + n.Requirements = append(n.Requirements, v1.NodeSelectorRequirement{ + Key: v1beta1.CapacityTypeLabelKey, Operator: v1.NodeSelectorOpIn, Values: []string{v1beta1.CapacityTypeOnDemand}, + }) + } + + // default to C, M, R categories if no instance type constraints are specified + if !requirements.Has(v1.LabelInstanceTypeStable) && + !requirements.Has(LabelInstanceFamily) && + !requirements.Has(LabelInstanceCategory) && + !requirements.Has(LabelInstanceGeneration) { + n.Requirements = append(n.Requirements, []v1.NodeSelectorRequirement{ + {Key: LabelInstanceCategory, Operator: v1.NodeSelectorOpIn, Values: []string{"c", "m", "r"}}, + {Key: LabelInstanceGeneration, Operator: v1.NodeSelectorOpGt, Values: []string{"2"}}, + }...) + } +} diff --git a/pkg/apis/v1beta1/nodepool.go b/pkg/apis/v1beta1/nodepool.go new file mode 100644 index 000000000000..4ba59038c649 --- /dev/null +++ b/pkg/apis/v1beta1/nodepool.go @@ -0,0 +1,43 @@ +/* +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "context" + + admissionregistrationv1 "k8s.io/api/admissionregistration/v1" + "knative.dev/pkg/apis" + + "github.com/aws/karpenter-core/pkg/apis/v1beta1" +) + +// NodePool is an alias type for additional validation +// +kubebuilder:object:root=true +type NodePool v1beta1.NodePool + +func (n *NodePool) SupportedVerbs() []admissionregistrationv1.OperationType { + return []admissionregistrationv1.OperationType{ + admissionregistrationv1.Create, + admissionregistrationv1.Update, + } +} + +func (n *NodePool) Validate(_ context.Context) (errs *apis.FieldError) { return nil } + +func (n *NodePool) SetDefaults(ctx context.Context) { + spec := NodeClaimSpec(n.Spec.Template.Spec) + spec.SetDefaults(ctx) + n.Spec.Template.Spec = v1beta1.NodeClaimSpec(spec) +} diff --git a/pkg/apis/v1beta1/zz_generated.deepcopy.go b/pkg/apis/v1beta1/zz_generated.deepcopy.go index 8895ec4ea8f9..e68e5c1c0cfd 100644 --- a/pkg/apis/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/v1beta1/zz_generated.deepcopy.go @@ -19,6 +19,7 @@ limitations under the License. package v1beta1 import ( + apisv1beta1 "github.com/aws/karpenter-core/pkg/apis/v1beta1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -182,6 +183,85 @@ func (in *MetadataOptions) DeepCopy() *MetadataOptions { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeClaim) DeepCopyInto(out *NodeClaim) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeClaim. +func (in *NodeClaim) DeepCopy() *NodeClaim { + if in == nil { + return nil + } + out := new(NodeClaim) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeClaim) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeClaimSpec) DeepCopyInto(out *NodeClaimSpec) { + *out = *in + if in.Taints != nil { + in, out := &in.Taints, &out.Taints + *out = make([]v1.Taint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.StartupTaints != nil { + in, out := &in.StartupTaints, &out.StartupTaints + *out = make([]v1.Taint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Requirements != nil { + in, out := &in.Requirements, &out.Requirements + *out = make([]v1.NodeSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Resources.DeepCopyInto(&out.Resources) + if in.KubeletConfiguration != nil { + in, out := &in.KubeletConfiguration, &out.KubeletConfiguration + *out = new(apisv1beta1.KubeletConfiguration) + (*in).DeepCopyInto(*out) + } + if in.NodeClass != nil { + in, out := &in.NodeClass, &out.NodeClass + *out = new(apisv1beta1.NodeClassReference) + **out = **in + } + if in.Provider != nil { + in, out := &in.Provider, &out.Provider + *out = new(runtime.RawExtension) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeClaimSpec. +func (in *NodeClaimSpec) DeepCopy() *NodeClaimSpec { + if in == nil { + return nil + } + out := new(NodeClaimSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeClass) DeepCopyInto(out *NodeClass) { *out = *in @@ -388,6 +468,33 @@ func (in *NodeClassStatus) DeepCopy() *NodeClassStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodePool) DeepCopyInto(out *NodePool) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodePool. +func (in *NodePool) DeepCopy() *NodePool { + if in == nil { + return nil + } + out := new(NodePool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodePool) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityGroup) DeepCopyInto(out *SecurityGroup) { *out = *in