Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
8 changes: 8 additions & 0 deletions pkg/azure/api/providerspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ type AzureVirtualMachineProperties struct {
MachineSet *AzureMachineSetConfig `json:"machineSet,omitempty"`
// SecurityProfile specifies the security profile to be used for the virtual machine.
SecurityProfile *AzureSecurityProfile `json:"securityProfile,omitempty"`
// CapacityReservation represents the configuration for capacity reservations on Azure.
CapacityReservation *CapacityReservation `json:"capacityReservation,omitempty"`
}

// CapacityReservation represents the configuration for capacity reservations on Azure.
type CapacityReservation struct {
// CapacityReservationGroupID is the resource ID of the capacity reservation group to use.
CapacityReservationGroupID *string `json:"capacityReservationGroupID,omitempty"`
}

// AzureSecurityProfile specifies the security profile to be used for the virtual machine.
Expand Down
34 changes: 34 additions & 0 deletions pkg/azure/api/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"slices"
"strings"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
"github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1"
"github.com/gardener/machine-controller-manager/pkg/util/provider/machinecodes/codes"
Expand Down Expand Up @@ -128,6 +129,7 @@ func validateProperties(properties api.AzureVirtualMachineProperties, fldPath *f
allErrs = append(allErrs, validateOSProfile(properties.OsProfile, fldPath.Child("osProfile"))...)
// validate availability set and vmss
allErrs = append(allErrs, validateAvailabilityAndScalingConfig(properties, fldPath)...)
allErrs = append(allErrs, validateCapacityReservationConfig(properties.CapacityReservation, fldPath.Child("capacityReservation"))...)
allErrs = append(allErrs, validateSecurityProfile(properties.SecurityProfile, fldPath.Child("securityProfile"))...)
return allErrs
}
Expand Down Expand Up @@ -294,6 +296,38 @@ func validateAvailabilityAndScalingConfig(properties api.AzureVirtualMachineProp
return allErrs
}

func validateCapacityReservationConfig(capacityReservationConfig *api.CapacityReservation, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList

if capacityReservationConfig == nil {
return allErrs
}

if capacityReservationGroupID := capacityReservationConfig.CapacityReservationGroupID; capacityReservationGroupID != nil {
resourceID, err := arm.ParseResourceID(*capacityReservationGroupID)
if err != nil {
allErrs = append(
allErrs,
field.Invalid(
fldPath.Child("capacityReservationGroupID"),
*capacityReservationGroupID,
fmt.Sprintf("invalid Azure resource ID: %v", err),
),
)
} else if resourceType := resourceID.ResourceType.Type; !strings.EqualFold(resourceType, "CapacityReservationGroups") {
allErrs = append(
allErrs,
field.Invalid(
fldPath.Child("capacityReservationGroupID"),
*capacityReservationGroupID,
fmt.Sprintf("provided resource ID must be of type 'CapacityReservationGroups', got '%s'", resourceType),
),
)
}
}
return allErrs
}

func validateTags(tags map[string]string, fldPath *field.Path) field.ErrorList {
const (
clusterKeyPrefix = "kubernetes.io-cluster-"
Expand Down
20 changes: 20 additions & 0 deletions pkg/azure/api/validation/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,26 @@ func TestValidateTags(t *testing.T) {
))
}

func TestCapacityReservationConfig(t *testing.T) {
fldPath := field.NewPath("providerSpec.capacityReservation")

// invalid resource group IDs should fail validation
testConfig := &api.CapacityReservation{CapacityReservationGroupID: ptr.To("Foo/bar/baz")}
g := NewWithT(t)
errList := validateCapacityReservationConfig(testConfig, fldPath)
g.Expect(len(errList)).To(Equal(1))
g.Expect(errList).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{"Type": Equal(field.ErrorTypeInvalid), "Field": Equal("providerSpec.capacityReservation.capacityReservationGroupID")})),
))

// IDs for other resource types should fail validation
testConfig = &api.CapacityReservation{CapacityReservationGroupID: ptr.To("/subscriptions/foo/resourceGroups/bar/providers/Microsoft.Compute/FooResource/foobar")}
errList = validateCapacityReservationConfig(testConfig, fldPath)
g.Expect(errList).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{"Type": Equal(field.ErrorTypeInvalid), "Field": Equal("providerSpec.capacityReservation.capacityReservationGroupID")})),
))
}

func createSecret(clientID, clientSecret, workloadIdentityTokenFile, subscriptionID, tenantID, userData string) *corev1.Secret {
data := make(map[string][]byte, 4)
if !utils.IsEmptyString(clientID) {
Expand Down
7 changes: 7 additions & 0 deletions pkg/azure/provider/helpers/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,7 @@ func createVMCreationParams(providerSpec api.AzureProviderSpec, imageRef armcomp
}
}
}

if diskSecurityProfile := providerSpec.Properties.StorageProfile.OsDisk.ManagedDisk.SecurityProfile; diskSecurityProfile != nil {
if diskSecurityProfile.SecurityEncryptionType != nil {
securityEncryptionType := armcompute.SecurityEncryptionTypes(*diskSecurityProfile.SecurityEncryptionType)
Expand All @@ -780,6 +781,12 @@ func createVMCreationParams(providerSpec api.AzureProviderSpec, imageRef armcomp
}
}

if capacityReservationConfig := providerSpec.Properties.CapacityReservation; capacityReservationConfig != nil {
vm.Properties.CapacityReservation = &armcompute.CapacityReservationProfile{
CapacityReservationGroup: &armcompute.SubResource{ID: capacityReservationConfig.CapacityReservationGroupID},
}
}

return vm, nil
}

Expand Down
Loading