diff --git a/azure/scope/managedcontrolplane.go b/azure/scope/managedcontrolplane.go index bbcb9bd9005..5776bf57408 100644 --- a/azure/scope/managedcontrolplane.go +++ b/azure/scope/managedcontrolplane.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/to" "github.com/go-logr/logr" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" @@ -488,7 +489,7 @@ func (s *ManagedControlPlaneScope) GetAgentPoolSpecs(ctx context.Context) ([]azu } ammp := azure.AgentPoolSpec{ - Name: *pool.Spec.Name, + Name: to.String(pool.Spec.Name), SKU: pool.Spec.SKU, Replicas: 1, OSDiskSizeGB: 0, @@ -528,7 +529,7 @@ func (s *ManagedControlPlaneScope) AgentPoolSpec() azure.AgentPoolSpec { } agentPoolSpec := azure.AgentPoolSpec{ - Name: *s.InfraMachinePool.Spec.Name, + Name: to.String(s.InfraMachinePool.Spec.Name), ResourceGroup: s.ControlPlane.Spec.ResourceGroupName, Cluster: s.ControlPlane.Name, SKU: s.InfraMachinePool.Spec.SKU, @@ -547,6 +548,12 @@ func (s *ManagedControlPlaneScope) AgentPoolSpec() azure.AgentPoolSpec { agentPoolSpec.OSDiskSizeGB = *s.InfraMachinePool.Spec.OSDiskSizeGB } + if s.InfraMachinePool.Spec.Scaling != nil { + agentPoolSpec.EnableAutoScaling = to.BoolPtr(true) + agentPoolSpec.MaxCount = s.InfraMachinePool.Spec.Scaling.MaxSize + agentPoolSpec.MinCount = s.InfraMachinePool.Spec.Scaling.MinSize + } + return agentPoolSpec } diff --git a/azure/scope/managedcontrolplane_test.go b/azure/scope/managedcontrolplane_test.go new file mode 100644 index 00000000000..a48652da3cf --- /dev/null +++ b/azure/scope/managedcontrolplane_test.go @@ -0,0 +1,179 @@ +/* +Copyright 2021 The Kubernetes Authors. + +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 scope + +import ( + "context" + "testing" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/to" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/cluster-api-provider-azure/azure" + infrav1 "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1beta1" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + capiv1exp "sigs.k8s.io/cluster-api/exp/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func TestManagedControlPlaneScope_Autoscaling(t *testing.T) { + scheme := runtime.NewScheme() + _ = capiv1exp.AddToScheme(scheme) + _ = infrav1.AddToScheme(scheme) + + cases := []struct { + Name string + Input ManagedControlPlaneScopeParams + Expected azure.AgentPoolSpec + }{ + { + Name: "Without Autoscaling", + Input: ManagedControlPlaneScopeParams{ + AzureClients: AzureClients{ + Authorizer: autorest.NullAuthorizer{}, + }, + Cluster: &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster1", + Namespace: "default", + }, + }, + ControlPlane: &infrav1.AzureManagedControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster1", + Namespace: "default", + }, + Spec: infrav1.AzureManagedControlPlaneSpec{ + SubscriptionID: "00000000-0000-0000-0000-000000000000", + }, + }, + MachinePool: getMachinePool("pool0"), + InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem), + PatchTarget: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem), + }, + Expected: azure.AgentPoolSpec{ + + Name: "pool0", + SKU: "Standard_D2s_v3", + Replicas: 1, + Mode: "System", + Cluster: "cluster1", + VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + }, + }, + { + Name: "With Autoscaling", + Input: ManagedControlPlaneScopeParams{ + AzureClients: AzureClients{ + Authorizer: autorest.NullAuthorizer{}, + }, + Cluster: &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster1", + Namespace: "default", + }, + }, + ControlPlane: &infrav1.AzureManagedControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster1", + Namespace: "default", + }, + Spec: infrav1.AzureManagedControlPlaneSpec{ + SubscriptionID: "00000000-0000-0000-0000-000000000000", + }, + }, + MachinePool: getMachinePool("pool1"), + InfraMachinePool: getAzureMachinePoolWithScaling("pool1", 2, 10), + PatchTarget: getAzureMachinePoolWithScaling("pool1", 2, 10), + }, + Expected: azure.AgentPoolSpec{ + Name: "pool1", + SKU: "Standard_D2s_v3", + Mode: "User", + Cluster: "cluster1", + Replicas: 1, + EnableAutoScaling: to.BoolPtr(true), + MinCount: to.Int32Ptr(2), + MaxCount: to.Int32Ptr(10), + VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + }, + }, + } + + for _, c := range cases { + c := c + t.Run(c.Name, func(t *testing.T) { + g := NewWithT(t) + fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(c.Input.MachinePool, c.Input.InfraMachinePool, c.Input.ControlPlane).Build() + c.Input.Client = fakeClient + s, err := NewManagedControlPlaneScope(context.TODO(), c.Input) + g.Expect(err).To(Succeed()) + agentPool := s.AgentPoolSpec() + g.Expect(agentPool).To(Equal(c.Expected)) + }) + } +} + +func getAzureMachinePool(name string, mode infrav1.NodePoolMode) *infrav1.AzureManagedMachinePool { + return &infrav1.AzureManagedMachinePool{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "default", + Labels: map[string]string{ + clusterv1.ClusterLabelName: "cluster1", + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "cluster.x-k8s.io/v1beta1", + Kind: "MachinePool", + Name: name, + }, + }, + }, + Spec: infrav1.AzureManagedMachinePoolSpec{ + Mode: string(mode), + SKU: "Standard_D2s_v3", + Name: to.StringPtr(name), + }, + } +} + +func getAzureMachinePoolWithScaling(name string, min, max int32) *infrav1.AzureManagedMachinePool { + managedPool := getAzureMachinePool(name, infrav1.NodePoolModeUser) + managedPool.Spec.Scaling = &infrav1.ManagedMachinePoolScaling{ + MinSize: to.Int32Ptr(min), + MaxSize: to.Int32Ptr(max), + } + return managedPool +} + +func getMachinePool(name string) *capiv1exp.MachinePool { + return &capiv1exp.MachinePool{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "default", + Labels: map[string]string{ + clusterv1.ClusterLabelName: "cluster1", + }, + }, + Spec: capiv1exp.MachinePoolSpec{ + ClusterName: "cluster1", + }, + } +} diff --git a/azure/services/agentpools/agentpools.go b/azure/services/agentpools/agentpools.go index 558588afb69..41774b61d00 100644 --- a/azure/services/agentpools/agentpools.go +++ b/azure/services/agentpools/agentpools.go @@ -76,6 +76,9 @@ func (s *Service) Reconcile(ctx context.Context) error { OrchestratorVersion: agentPoolSpec.Version, VnetSubnetID: &agentPoolSpec.VnetSubnetID, Mode: containerservice.AgentPoolMode(agentPoolSpec.Mode), + EnableAutoScaling: agentPoolSpec.EnableAutoScaling, + MaxCount: agentPoolSpec.MaxCount, + MinCount: agentPoolSpec.MinCount, }, } @@ -110,6 +113,9 @@ func (s *Service) Reconcile(ctx context.Context) error { Count: existingPool.Count, OrchestratorVersion: existingPool.OrchestratorVersion, Mode: existingPool.Mode, + EnableAutoScaling: existingPool.EnableAutoScaling, + MinCount: existingPool.MinCount, + MaxCount: existingPool.MaxCount, }, } @@ -118,6 +124,9 @@ func (s *Service) Reconcile(ctx context.Context) error { Count: profile.Count, OrchestratorVersion: profile.OrchestratorVersion, Mode: profile.Mode, + EnableAutoScaling: profile.EnableAutoScaling, + MinCount: profile.MinCount, + MaxCount: profile.MaxCount, }, } diff --git a/azure/types.go b/azure/types.go index 0cf5e361969..e74bae16a5b 100644 --- a/azure/types.go +++ b/azure/types.go @@ -434,4 +434,13 @@ type AgentPoolSpec struct { // Mode represents mode of an agent pool. Possible values include: 'System', 'User'. Mode string + + // Maximum number of nodes for auto-scaling + MaxCount *int32 `json:"maxCount,omitempty"` + + // Minimum number of nodes for auto-scaling + MinCount *int32 `json:"minCount,omitempty"` + + // EnableAutoScaling - Whether to enable auto-scaler + EnableAutoScaling *bool `json:"enableAutoScaling,omitempty"` } diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedmachinepools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedmachinepools.yaml index 0c226170b3d..3443612b52b 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedmachinepools.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedmachinepools.yaml @@ -219,6 +219,17 @@ spec: items: type: string type: array + scaling: + description: Scaling specifies the autoscaling parameters for the + node pool. + properties: + maxSize: + format: int32 + type: integer + minSize: + format: int32 + type: integer + type: object sku: description: SKU is the size of the VMs in the node pool. type: string diff --git a/docs/book/src/topics/managedcluster.md b/docs/book/src/topics/managedcluster.md index 39902133ebd..7461b6d1eb5 100644 --- a/docs/book/src/topics/managedcluster.md +++ b/docs/book/src/topics/managedcluster.md @@ -245,6 +245,24 @@ spec: - 917056a9-8eb5-439c-g679-b34901ade75h # fake admin groupId ``` +### AKS Cluster Autoscaler + +Azure Kubernetes Service can be configured to use cluster autoscaler by specifying `scaling` spec in the `AzureManagedMachinePool` + +``` +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: AzureManagedMachinePool +metadata: + name: agentpool0 +spec: + mode: System + osDiskSizeGB: 512 + sku: Standard_D2s_v3 + scaling: + minSize: 2 + maxSize: 10 +``` + ### Use a public Standard Load Balancer A public Load Balancer when integrated with AKS serves two purposes: diff --git a/exp/api/v1alpha3/azuremanagedmachinepool_conversion.go b/exp/api/v1alpha3/azuremanagedmachinepool_conversion.go index b02f694cd07..2e62ce74d78 100644 --- a/exp/api/v1alpha3/azuremanagedmachinepool_conversion.go +++ b/exp/api/v1alpha3/azuremanagedmachinepool_conversion.go @@ -38,6 +38,7 @@ func (src *AzureManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error { // } dst.Spec.Name = restored.Spec.Name + dst.Spec.Scaling = restored.Spec.Scaling return nil } diff --git a/exp/api/v1alpha3/zz_generated.conversion.go b/exp/api/v1alpha3/zz_generated.conversion.go index 9905e89f7cb..628aee1be58 100644 --- a/exp/api/v1alpha3/zz_generated.conversion.go +++ b/exp/api/v1alpha3/zz_generated.conversion.go @@ -879,6 +879,7 @@ func autoConvert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha3_AzureManagedMac out.SKU = in.SKU out.OSDiskSizeGB = (*int32)(unsafe.Pointer(in.OSDiskSizeGB)) out.ProviderIDList = *(*[]string)(unsafe.Pointer(&in.ProviderIDList)) + // WARNING: in.Scaling requires manual conversion: does not exist in peer-type return nil } diff --git a/exp/api/v1alpha4/azuremanagedmachinepool_conversion.go b/exp/api/v1alpha4/azuremanagedmachinepool_conversion.go index c4ad1d2ec98..718a74afa77 100644 --- a/exp/api/v1alpha4/azuremanagedmachinepool_conversion.go +++ b/exp/api/v1alpha4/azuremanagedmachinepool_conversion.go @@ -17,20 +17,45 @@ limitations under the License. package v1alpha4 import ( + apiconversion "k8s.io/apimachinery/pkg/conversion" expv1beta1 "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1beta1" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" "sigs.k8s.io/controller-runtime/pkg/conversion" ) // ConvertTo converts this AzureManagedMachinePool to the Hub version (v1beta1). -func (src *AzureManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error { // nolint +func (src *AzureManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*expv1beta1.AzureManagedMachinePool) + if err := Convert_v1alpha4_AzureManagedMachinePool_To_v1beta1_AzureManagedMachinePool(src, dst, nil); err != nil { + return err + } + + // Manually restore data. + restored := &expv1beta1.AzureManagedMachinePool{} + if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { + return err + } + dst.Spec.Scaling = restored.Spec.Scaling return Convert_v1alpha4_AzureManagedMachinePool_To_v1beta1_AzureManagedMachinePool(src, dst, nil) } // ConvertFrom converts from the Hub version (v1beta1) to this version. -func (dst *AzureManagedMachinePool) ConvertFrom(srcRaw conversion.Hub) error { // nolint +func (dst *AzureManagedMachinePool) ConvertFrom(srcRaw conversion.Hub) error { src := srcRaw.(*expv1beta1.AzureManagedMachinePool) - return Convert_v1beta1_AzureManagedMachinePool_To_v1alpha4_AzureManagedMachinePool(src, dst, nil) + if err := Convert_v1beta1_AzureManagedMachinePool_To_v1alpha4_AzureManagedMachinePool(src, dst, nil); err != nil { + return err + } + + // Preserve Hub data on down-conversion. + if err := utilconversion.MarshalData(src, dst); err != nil { + return err + } + + return nil +} + +func Convert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha4_AzureManagedMachinePoolSpec(in *expv1beta1.AzureManagedMachinePoolSpec, out *AzureManagedMachinePoolSpec, s apiconversion.Scope) error { + return autoConvert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha4_AzureManagedMachinePoolSpec(in, out, s) } diff --git a/exp/api/v1alpha4/zz_generated.conversion.go b/exp/api/v1alpha4/zz_generated.conversion.go index 2d75e1f1923..5124229cd7d 100644 --- a/exp/api/v1alpha4/zz_generated.conversion.go +++ b/exp/api/v1alpha4/zz_generated.conversion.go @@ -278,11 +278,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1beta1.AzureManagedMachinePoolSpec)(nil), (*AzureManagedMachinePoolSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha4_AzureManagedMachinePoolSpec(a.(*v1beta1.AzureManagedMachinePoolSpec), b.(*AzureManagedMachinePoolSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*AzureManagedMachinePoolStatus)(nil), (*v1beta1.AzureManagedMachinePoolStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha4_AzureManagedMachinePoolStatus_To_v1beta1_AzureManagedMachinePoolStatus(a.(*AzureManagedMachinePoolStatus), b.(*v1beta1.AzureManagedMachinePoolStatus), scope) }); err != nil { @@ -363,6 +358,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta1.AzureManagedMachinePoolSpec)(nil), (*AzureManagedMachinePoolSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha4_AzureManagedMachinePoolSpec(a.(*v1beta1.AzureManagedMachinePoolSpec), b.(*AzureManagedMachinePoolSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*clusterapiproviderazureapiv1beta1.Image)(nil), (*clusterapiproviderazureapiv1alpha4.Image)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_Image_To_v1alpha4_Image(a.(*clusterapiproviderazureapiv1beta1.Image), b.(*clusterapiproviderazureapiv1alpha4.Image), scope) }); err != nil { @@ -1134,7 +1134,17 @@ func Convert_v1beta1_AzureManagedMachinePool_To_v1alpha4_AzureManagedMachinePool func autoConvert_v1alpha4_AzureManagedMachinePoolList_To_v1beta1_AzureManagedMachinePoolList(in *AzureManagedMachinePoolList, out *v1beta1.AzureManagedMachinePoolList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]v1beta1.AzureManagedMachinePool)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.AzureManagedMachinePool, len(*in)) + for i := range *in { + if err := Convert_v1alpha4_AzureManagedMachinePool_To_v1beta1_AzureManagedMachinePool(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -1145,7 +1155,17 @@ func Convert_v1alpha4_AzureManagedMachinePoolList_To_v1beta1_AzureManagedMachine func autoConvert_v1beta1_AzureManagedMachinePoolList_To_v1alpha4_AzureManagedMachinePoolList(in *v1beta1.AzureManagedMachinePoolList, out *AzureManagedMachinePoolList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]AzureManagedMachinePool)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AzureManagedMachinePool, len(*in)) + for i := range *in { + if err := Convert_v1beta1_AzureManagedMachinePool_To_v1alpha4_AzureManagedMachinePool(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -1174,14 +1194,10 @@ func autoConvert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha4_AzureManagedMac out.SKU = in.SKU out.OSDiskSizeGB = (*int32)(unsafe.Pointer(in.OSDiskSizeGB)) out.ProviderIDList = *(*[]string)(unsafe.Pointer(&in.ProviderIDList)) + // WARNING: in.Scaling requires manual conversion: does not exist in peer-type return nil } -// Convert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha4_AzureManagedMachinePoolSpec is an autogenerated conversion function. -func Convert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha4_AzureManagedMachinePoolSpec(in *v1beta1.AzureManagedMachinePoolSpec, out *AzureManagedMachinePoolSpec, s conversion.Scope) error { - return autoConvert_v1beta1_AzureManagedMachinePoolSpec_To_v1alpha4_AzureManagedMachinePoolSpec(in, out, s) -} - func autoConvert_v1alpha4_AzureManagedMachinePoolStatus_To_v1beta1_AzureManagedMachinePoolStatus(in *AzureManagedMachinePoolStatus, out *v1beta1.AzureManagedMachinePoolStatus, s conversion.Scope) error { out.Ready = in.Ready out.Replicas = in.Replicas diff --git a/exp/api/v1beta1/azuremanagedmachinepool_types.go b/exp/api/v1beta1/azuremanagedmachinepool_types.go index b18dc8df004..0ebcb0846b8 100644 --- a/exp/api/v1beta1/azuremanagedmachinepool_types.go +++ b/exp/api/v1beta1/azuremanagedmachinepool_types.go @@ -57,6 +57,16 @@ type AzureManagedMachinePoolSpec struct { // ProviderIDList is the unique identifier as specified by the cloud provider. // +optional ProviderIDList []string `json:"providerIDList,omitempty"` + + // Scaling specifies the autoscaling parameters for the node pool. + // +optional + Scaling *ManagedMachinePoolScaling `json:"scaling,omitempty"` +} + +// ManagedMachinePoolScaling specifies scaling options. +type ManagedMachinePoolScaling struct { + MinSize *int32 `json:"minSize,omitempty"` + MaxSize *int32 `json:"maxSize,omitempty"` } // AzureManagedMachinePoolStatus defines the observed state of AzureManagedMachinePool. diff --git a/exp/api/v1beta1/zz_generated.deepcopy.go b/exp/api/v1beta1/zz_generated.deepcopy.go index 68e1ba653e1..0a43a0dbf08 100644 --- a/exp/api/v1beta1/zz_generated.deepcopy.go +++ b/exp/api/v1beta1/zz_generated.deepcopy.go @@ -765,6 +765,11 @@ func (in *AzureManagedMachinePoolSpec) DeepCopyInto(out *AzureManagedMachinePool *out = make([]string, len(*in)) copy(*out, *in) } + if in.Scaling != nil { + in, out := &in.Scaling, &out.Scaling + *out = new(ManagedMachinePoolScaling) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureManagedMachinePoolSpec. @@ -898,6 +903,31 @@ func (in *ManagedControlPlaneVirtualNetwork) DeepCopy() *ManagedControlPlaneVirt return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedMachinePoolScaling) DeepCopyInto(out *ManagedMachinePoolScaling) { + *out = *in + if in.MinSize != nil { + in, out := &in.MinSize, &out.MinSize + *out = new(int32) + **out = **in + } + if in.MaxSize != nil { + in, out := &in.MaxSize, &out.MaxSize + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedMachinePoolScaling. +func (in *ManagedMachinePoolScaling) DeepCopy() *ManagedMachinePoolScaling { + if in == nil { + return nil + } + out := new(ManagedMachinePoolScaling) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SKU) DeepCopyInto(out *SKU) { *out = *in