Skip to content
Merged
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
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
26 changes: 26 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,32 @@ 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(len(errList)).To(Equal(1))
g.Expect(errList).To(ConsistOf(
PointTo(MatchFields(IgnoreExtras, Fields{"Type": Equal(field.ErrorTypeInvalid), "Field": Equal("providerSpec.capacityReservation.capacityReservationGroupID")})),
))

// Valid ID should work
testConfig = &api.CapacityReservation{CapacityReservationGroupID: ptr.To("/subscriptions/foo/resourceGroups/bar/providers/Microsoft.Compute/CapacityReservationGroups/foobar")}
errList = validateCapacityReservationConfig(testConfig, fldPath)
g.Expect(errList).To(BeEmpty())
}

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