Skip to content

Commit

Permalink
add az machine pool rolling upgrades with maxsurge, maxunavailable, a…
Browse files Browse the repository at this point in the history
…nd deletepolicy
  • Loading branch information
devigned committed Jun 9, 2021
1 parent d8a2c53 commit ff4f6ad
Show file tree
Hide file tree
Showing 66 changed files with 6,220 additions and 1,017 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -587,5 +587,5 @@ verify-modules: modules
.PHONY: verify-gen
verify-gen: generate
@if !(git diff --quiet HEAD); then \
echo "generated files are out of date, run make generate"; exit 1; \
git diff; echo "generated files are out of date, run make generate"; exit 1; \
fi
12 changes: 12 additions & 0 deletions api/v1alpha4/conditions_consts.go
Expand Up @@ -62,4 +62,16 @@ const (
ScaleSetDeletingReason = "ScaleSetDeleting"
// ScaleSetProvisionFailedReason used for failures during scale set provisioning.
ScaleSetProvisionFailedReason = "ScaleSetProvisionFailed"

// ScaleSetDesiredReplicasCondition reports on the scaling state of the machine pool
ScaleSetDesiredReplicasCondition clusterv1.ConditionType = "ScaleSetDesiredReplicas"
// ScaleSetScaleUpReason describes the machine pool scaling up
ScaleSetScaleUpReason = "ScaleSetScalingUp"
// ScaleSetScaleDownReason describes the machine pool scaling down
ScaleSetScaleDownReason = "ScaleSetScalingDown"

// ScaleSetModelUpdatedCondition reports on the model state of the pool
ScaleSetModelUpdatedCondition clusterv1.ConditionType = "ScaleSetModelUpdated"
// ScaleSetModelOutOfDateReason describes the machine pool model being out of date
ScaleSetModelOutOfDateReason = "ScaleSetModelOutOfDate"
)
5 changes: 5 additions & 0 deletions api/v1alpha4/types.go
Expand Up @@ -587,3 +587,8 @@ type AzureBastion struct {
// +optional
PublicIP PublicIPSpec `json:"publicIP,omitempty"`
}

// IsTerminalProvisioningState returns true if the ProvisioningState is a terminal state for an Azure resource
func IsTerminalProvisioningState(state ProvisioningState) bool {
return state == Failed || state == Succeeded
}
80 changes: 60 additions & 20 deletions azure/converters/vmss.go
Expand Up @@ -19,14 +19,13 @@ package converters
import (
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-30/compute"
"github.com/Azure/go-autorest/autorest/to"

infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1alpha4"
infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1alpha4"
"sigs.k8s.io/cluster-api-provider-azure/azure"
)

// SDKToVMSS converts an Azure SDK VirtualMachineScaleSet to the AzureMachinePool type.
func SDKToVMSS(sdkvmss compute.VirtualMachineScaleSet, sdkinstances []compute.VirtualMachineScaleSetVM) *infrav1exp.VMSS {
vmss := &infrav1exp.VMSS{
func SDKToVMSS(sdkvmss compute.VirtualMachineScaleSet, sdkinstances []compute.VirtualMachineScaleSetVM) *azure.VMSS {
vmss := &azure.VMSS{
ID: to.String(sdkvmss.ID),
Name: to.String(sdkvmss.Name),
State: infrav1.ProvisioningState(to.String(sdkvmss.ProvisioningState)),
Expand All @@ -46,25 +45,66 @@ func SDKToVMSS(sdkvmss compute.VirtualMachineScaleSet, sdkinstances []compute.Vi
}

if len(sdkinstances) > 0 {
vmss.Instances = make([]infrav1exp.VMSSVM, len(sdkinstances))
vmss.Instances = make([]azure.VMSSVM, len(sdkinstances))
for i, vm := range sdkinstances {
instance := infrav1exp.VMSSVM{
ID: to.String(vm.ID),
InstanceID: to.String(vm.InstanceID),
Name: to.String(vm.OsProfile.ComputerName),
State: infrav1.ProvisioningState(to.String(vm.ProvisioningState)),
}

if vm.LatestModelApplied != nil {
instance.LatestModelApplied = *vm.LatestModelApplied
}

if vm.Zones != nil && len(*vm.Zones) > 0 {
instance.AvailabilityZone = to.StringSlice(vm.Zones)[0]
}
vmss.Instances[i] = instance
vmss.Instances[i] = *SDKToVMSSVM(vm)
}
}

if sdkvmss.VirtualMachineProfile != nil &&
sdkvmss.VirtualMachineProfile.StorageProfile != nil &&
sdkvmss.VirtualMachineProfile.StorageProfile.ImageReference != nil {

imageRef := sdkvmss.VirtualMachineProfile.StorageProfile.ImageReference
vmss.Image = SDKImageToImage(imageRef, sdkvmss.Plan != nil)
}

return vmss
}

// SDKToVMSSVM converts an Azure SDK VirtualMachineScaleSetVM into an infrav1exp.VMSSVM
func SDKToVMSSVM(sdkInstance compute.VirtualMachineScaleSetVM) *azure.VMSSVM {
instance := azure.VMSSVM{
ID: to.String(sdkInstance.ID),
InstanceID: to.String(sdkInstance.InstanceID),
}

if sdkInstance.VirtualMachineScaleSetVMProperties == nil {
return &instance
}

instance.State = infrav1.Creating
if sdkInstance.ProvisioningState != nil {
instance.State = infrav1.ProvisioningState(to.String(sdkInstance.ProvisioningState))
}

if sdkInstance.OsProfile != nil && sdkInstance.OsProfile.ComputerName != nil {
instance.Name = *sdkInstance.OsProfile.ComputerName
}

if sdkInstance.StorageProfile != nil && sdkInstance.StorageProfile.ImageReference != nil {
imageRef := sdkInstance.StorageProfile.ImageReference
instance.Image = SDKImageToImage(imageRef, sdkInstance.Plan != nil)
}

if sdkInstance.Zones != nil && len(*sdkInstance.Zones) > 0 {
// an instance should only have 1 zone, so we select the first item of the slice
instance.AvailabilityZone = to.StringSlice(sdkInstance.Zones)[0]
}

return &instance
}

// SDKImageToImage converts a SDK image reference to infrav1.Image
func SDKImageToImage(sdkImageRef *compute.ImageReference, isThirdPartyImage bool) infrav1.Image {
return infrav1.Image{
ID: sdkImageRef.ID,
Marketplace: &infrav1.AzureMarketplaceImage{
Publisher: to.String(sdkImageRef.Publisher),
Offer: to.String(sdkImageRef.Offer),
SKU: to.String(sdkImageRef.Sku),
Version: to.String(sdkImageRef.Version),
ThirdPartyImage: isThirdPartyImage,
},
}
}
13 changes: 6 additions & 7 deletions azure/converters/vmss_test.go
Expand Up @@ -23,16 +23,15 @@ import (
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-30/compute"
"github.com/Azure/go-autorest/autorest/to"
"github.com/onsi/gomega"

"sigs.k8s.io/cluster-api-provider-azure/azure"
"sigs.k8s.io/cluster-api-provider-azure/azure/converters"
infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1alpha4"
)

func Test_SDKToVMSS(t *testing.T) {
cases := []struct {
Name string
SubjectFactory func(*gomega.GomegaWithT) (compute.VirtualMachineScaleSet, []compute.VirtualMachineScaleSetVM)
Expect func(*gomega.GomegaWithT, *infrav1exp.VMSS)
Expect func(*gomega.GomegaWithT, *azure.VMSS)
}{
{
Name: "ShouldPopulateWithData",
Expand Down Expand Up @@ -83,8 +82,8 @@ func Test_SDKToVMSS(t *testing.T) {
},
}
},
Expect: func(g *gomega.GomegaWithT, actual *infrav1exp.VMSS) {
expected := infrav1exp.VMSS{
Expect: func(g *gomega.GomegaWithT, actual *azure.VMSS) {
expected := azure.VMSS{
ID: "vmssID",
Name: "vmssName",
Sku: "skuName",
Expand All @@ -94,11 +93,11 @@ func Test_SDKToVMSS(t *testing.T) {
Tags: map[string]string{
"foo": "bazz",
},
Instances: make([]infrav1exp.VMSSVM, 2),
Instances: make([]azure.VMSSVM, 2),
}

for i := 0; i < 2; i++ {
expected.Instances[i] = infrav1exp.VMSSVM{
expected.Instances[i] = azure.VMSSVM{
ID: fmt.Sprintf("vm/%d", i),
InstanceID: fmt.Sprintf("%d", i),
Name: fmt.Sprintf("instance-00000%d", i),
Expand Down
5 changes: 5 additions & 0 deletions azure/errors.go
Expand Up @@ -109,6 +109,11 @@ func (t ReconcileError) IsTerminal() bool {
return t.errorType == TerminalErrorType
}

// Is returns true if the target is a ReconcileError
func (t ReconcileError) Is(target error) bool {
return errors.As(target, &ReconcileError{})
}

// RequeueAfter returns requestAfter value
func (t ReconcileError) RequeueAfter() time.Duration {
return t.requestAfter
Expand Down
2 changes: 1 addition & 1 deletion azure/scope/machine.go
Expand Up @@ -297,7 +297,7 @@ func (m *MachineScope) Role() string {
return infrav1.Node
}

// GetVMID returns the AzureMachine instance id by parsing Spec.ProviderID.
// GetVMID returns the AzureMachine instance id by parsing Spec.FakeProviderID.
func (m *MachineScope) GetVMID() string {
parsed, err := noderefutil.NewProviderID(m.ProviderID())
if err != nil {
Expand Down

0 comments on commit ff4f6ad

Please sign in to comment.