Skip to content

Commit

Permalink
Add support for custom vm extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
willie-yao committed Sep 14, 2022
1 parent afc2ca0 commit f7c3b3c
Show file tree
Hide file tree
Showing 22 changed files with 521 additions and 5 deletions.
4 changes: 4 additions & 0 deletions api/v1alpha3/azuremachine_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ func (src *AzureMachine) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.DNSServers = restored.Spec.DNSServers
}

if len(restored.Spec.VMExtensions) > 0 {
dst.Spec.VMExtensions = restored.Spec.VMExtensions
}

dst.Spec.SubnetName = restored.Spec.SubnetName

dst.Status.LongRunningOperationStates = restored.Status.LongRunningOperationStates
Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha3/azuremachinetemplate_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ func (src *AzureMachineTemplate) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.Template.Spec.DNSServers = restored.Spec.Template.Spec.DNSServers
}

if len(restored.Spec.Template.Spec.VMExtensions) > 0 {
dst.Spec.Template.Spec.VMExtensions = restored.Spec.Template.Spec.VMExtensions
}

return nil
}

Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha4/azuremachine_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func (src *AzureMachine) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.DNSServers = restored.Spec.DNSServers
}

if len(restored.Spec.VMExtensions) > 0 {
dst.Spec.VMExtensions = restored.Spec.VMExtensions
}

return nil
}

Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha4/azuremachinetemplate_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ func (src *AzureMachineTemplate) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.Template.Spec.DNSServers = restored.Spec.Template.Spec.DNSServers
}

if len(restored.Spec.Template.Spec.VMExtensions) > 0 {
dst.Spec.Template.Spec.VMExtensions = restored.Spec.Template.Spec.VMExtensions
}

return nil
}

Expand Down
4 changes: 4 additions & 0 deletions api/v1beta1/azuremachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ type AzureMachineSpec struct {
// DNSServers adds a list of DNS Server IP addresses to the VM NICs.
// +optional
DNSServers []string `json:"dnsServers,omitempty"`

// VMExtensions specifies a list of extensions to be added to the virtual machine.
// +optional
VMExtensions []VMExtension `json:"vmExtensions,omitempty"`
}

// SpotVMOptions defines the options relevant to running the Machine on Spot VMs.
Expand Down
16 changes: 16 additions & 0 deletions api/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,22 @@ type DataDisk struct {
CachingType string `json:"cachingType,omitempty"`
}

// VMExtension specifies the parameters for a custom VM extension
type VMExtension struct {
// Name is the name of the extension.
Name string `json:"name"`
// Publisher is the name of the extension handler publisher.
Publisher string `json:"publisher"`
// Version specifies the version of the script handler.
Version string `json:"version"`
// Settings is a JSON formatted public settings for the extension.
// +optional
Settings Tags `json:"settings,omitempty"`
// ProtectedSettings is a JSON formatted protected settings for the extension.
// +optional
ProtectedSettings Tags `json:"protectedSettings,omitempty"`
}

// ManagedDiskParameters defines the parameters of a managed disk.
type ManagedDiskParameters struct {
// +optional
Expand Down
21 changes: 18 additions & 3 deletions azure/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,21 @@ func (m *MachineScope) HasSystemAssignedIdentity() bool {
// VMExtensionSpecs returns the VM extension specs.
func (m *MachineScope) VMExtensionSpecs() []azure.ResourceSpecGetter {
var extensionSpecs = []azure.ResourceSpecGetter{}
for _, extension := range m.AzureMachine.Spec.VMExtensions {
extensionSpecs = append(extensionSpecs, &vmextensions.VMExtensionSpec{
ExtensionSpec: azure.ExtensionSpec{
Name: extension.Name,
VMName: m.Name(),
Publisher: extension.Publisher,
Version: extension.Version,
Settings: extension.Settings,
ProtectedSettings: extension.ProtectedSettings,
},
ResourceGroup: m.ResourceGroup(),
Location: m.Location(),
})
}

bootstrapExtensionSpec := azure.GetBootstrappingVMExtension(m.AzureMachine.Spec.OSDisk.OSType, m.CloudEnvironment(), m.Name())

if bootstrapExtensionSpec != nil {
Expand All @@ -359,9 +374,9 @@ func (m *MachineScope) Subnet() infrav1.SubnetSpec {

// AvailabilityZone returns the AzureMachine Availability Zone.
// Priority for selecting the AZ is
// 1) Machine.Spec.FailureDomain
// 2) AzureMachine.Spec.FailureDomain (This is to support deprecated AZ)
// 3) No AZ
// 1. Machine.Spec.FailureDomain
// 2. AzureMachine.Spec.FailureDomain (This is to support deprecated AZ)
// 3. No AZ
func (m *MachineScope) AvailabilityZone() string {
if m.Machine.Spec.FailureDomain != nil {
return *m.Machine.Spec.FailureDomain
Expand Down
77 changes: 77 additions & 0 deletions azure/scope/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,83 @@ func TestMachineScope_VMExtensionSpecs(t *testing.T) {
},
want: []azure.ResourceSpecGetter{},
},
{
name: "If a custom VM extension is specified, it returns the custom VM extension",
machineScope: MachineScope{
Machine: &clusterv1.Machine{},
AzureMachine: &infrav1.AzureMachine{
ObjectMeta: metav1.ObjectMeta{
Name: "machine-name",
},
Spec: infrav1.AzureMachineSpec{
OSDisk: infrav1.OSDisk{
OSType: "Linux",
},
VMExtensions: []infrav1.VMExtension{
{
Name: "custom-vm-extension",
Publisher: "Microsoft.Azure.Extensions",
Version: "2.0",
Settings: map[string]string{
"timestamp": "1234567890",
},
ProtectedSettings: map[string]string{
"commandToExecute": "echo hello world",
},
},
},
},
},
ClusterScoper: &ClusterScope{
AzureClients: AzureClients{
EnvironmentSettings: auth.EnvironmentSettings{
Environment: autorestazure.Environment{
Name: autorestazure.PublicCloud.Name,
},
},
},
AzureCluster: &infrav1.AzureCluster{
Spec: infrav1.AzureClusterSpec{
ResourceGroup: "my-rg",
AzureClusterClassSpec: infrav1.AzureClusterClassSpec{
Location: "westus",
},
},
},
},
},
want: []azure.ResourceSpecGetter{
&vmextensions.VMExtensionSpec{
ExtensionSpec: azure.ExtensionSpec{
Name: "custom-vm-extension",
VMName: "machine-name",
Publisher: "Microsoft.Azure.Extensions",
Version: "2.0",
Settings: map[string]string{
"timestamp": "1234567890",
},
ProtectedSettings: map[string]string{
"commandToExecute": "echo hello world",
},
},
ResourceGroup: "my-rg",
Location: "westus",
},
&vmextensions.VMExtensionSpec{
ExtensionSpec: azure.ExtensionSpec{
Name: "CAPZ.Linux.Bootstrapping",
VMName: "machine-name",
Publisher: "Microsoft.Azure.ContainerUpstream",
Version: "1.0",
ProtectedSettings: map[string]string{
"commandToExecute": azure.LinuxBootstrapExtensionCommand,
},
},
ResourceGroup: "my-rg",
Location: "westus",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
16 changes: 16 additions & 0 deletions azure/scope/machinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ func (m *MachinePoolScope) ScaleSetSpec() azure.ScaleSetSpec {
SpotVMOptions: m.AzureMachinePool.Spec.Template.SpotVMOptions,
FailureDomains: m.MachinePool.Spec.FailureDomains,
TerminateNotificationTimeout: m.AzureMachinePool.Spec.Template.TerminateNotificationTimeout,
VMExtensions: m.AzureMachinePool.Spec.Template.VMExtensions,
}
}

Expand Down Expand Up @@ -613,6 +614,21 @@ func (m *MachinePoolScope) HasSystemAssignedIdentity() bool {
// VMSSExtensionSpecs returns the VMSS extension specs.
func (m *MachinePoolScope) VMSSExtensionSpecs() []azure.ResourceSpecGetter {
var extensionSpecs = []azure.ResourceSpecGetter{}

for _, extension := range m.AzureMachinePool.Spec.Template.VMExtensions {
extensionSpecs = append(extensionSpecs, &scalesets.VMSSExtensionSpec{
ExtensionSpec: azure.ExtensionSpec{
Name: extension.Name,
VMName: m.Name(),
Publisher: extension.Publisher,
Version: extension.Version,
Settings: extension.Settings,
ProtectedSettings: extension.ProtectedSettings,
},
ResourceGroup: m.ResourceGroup(),
})
}

bootstrapExtensionSpec := azure.GetBootstrappingVMExtension(m.AzureMachinePool.Spec.Template.OSDisk.OSType, m.CloudEnvironment(), m.Name())

if bootstrapExtensionSpec != nil {
Expand Down
77 changes: 77 additions & 0 deletions azure/scope/machinepool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,83 @@ func TestMachinePoolScope_VMSSExtensionSpecs(t *testing.T) {
},
want: []azure.ResourceSpecGetter{},
},
{
name: "If a custom VM extension is specified, it returns the custom VM extension",
machinePoolScope: MachinePoolScope{
MachinePool: &expv1.MachinePool{},
AzureMachinePool: &infrav1exp.AzureMachinePool{
ObjectMeta: metav1.ObjectMeta{
Name: "machinepool-name",
},
Spec: infrav1exp.AzureMachinePoolSpec{
Template: infrav1exp.AzureMachinePoolMachineTemplate{
OSDisk: infrav1.OSDisk{
OSType: "Linux",
},
VMExtensions: []infrav1.VMExtension{
{
Name: "custom-vm-extension",
Publisher: "Microsoft.Azure.Extensions",
Version: "2.0",
Settings: map[string]string{
"timestamp": "1234567890",
},
ProtectedSettings: map[string]string{
"commandToExecute": "echo hello world",
},
},
},
},
},
},
ClusterScoper: &ClusterScope{
AzureClients: AzureClients{
EnvironmentSettings: auth.EnvironmentSettings{
Environment: autorestazure.Environment{
Name: autorestazure.PublicCloud.Name,
},
},
},
AzureCluster: &infrav1.AzureCluster{
Spec: infrav1.AzureClusterSpec{
ResourceGroup: "my-rg",
AzureClusterClassSpec: infrav1.AzureClusterClassSpec{
Location: "westus",
},
},
},
},
},
want: []azure.ResourceSpecGetter{
&scalesets.VMSSExtensionSpec{
ExtensionSpec: azure.ExtensionSpec{
Name: "custom-vm-extension",
VMName: "machinepool-name",
Publisher: "Microsoft.Azure.Extensions",
Version: "2.0",
Settings: map[string]string{
"timestamp": "1234567890",
},
ProtectedSettings: map[string]string{
"commandToExecute": "echo hello world",
},
},
ResourceGroup: "my-rg",
},
&scalesets.VMSSExtensionSpec{
ExtensionSpec: azure.ExtensionSpec{
Name: "CAPZ.Linux.Bootstrapping",
VMName: "machinepool-name",
Publisher: "Microsoft.Azure.ContainerUpstream",
Version: "1.0",
ProtectedSettings: map[string]string{
"commandToExecute": azure.LinuxBootstrapExtensionCommand,
},
},
ResourceGroup: "my-rg",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion azure/services/scalesets/vmssextension_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (s *VMSSExtensionSpec) Parameters(existing interface{}) (interface{}, error
Publisher: to.StringPtr(s.Publisher),
Type: to.StringPtr(s.Name),
TypeHandlerVersion: to.StringPtr(s.Version),
Settings: nil,
Settings: s.Settings,
ProtectedSettings: s.ProtectedSettings,
},
}, nil
Expand Down
Loading

0 comments on commit f7c3b3c

Please sign in to comment.