Skip to content

Commit

Permalink
Add option for CloudInit to default to global NS and SearchDomains
Browse files Browse the repository at this point in the history
The CloudInit bootstrap only supports per-interface Nameservers and
SearchDomains while others bootstrap like LinuxPrep support global.
To simplify the UX and to make it easier to switch between bootstrap
providers, add two *bool fields to the CloudInit spec:
 - UseGlobalNameserversAsDefault
 - UseGlobalSearchDomainsAsDefault
that when either nil or true, use the global value when the
corresponding per-interface field is unset.

In v1a2, the validation wehbook would have rejected an attempt to
use the global Nameservers or SearchDomains with CloudInit, so this
change should not result it any behavior change for an existing VM
definition.
  • Loading branch information
Bryan Venteicher committed Dec 13, 2024
1 parent 5960911 commit 5ef669c
Show file tree
Hide file tree
Showing 20 changed files with 437 additions and 59 deletions.
2 changes: 2 additions & 0 deletions api/v1alpha1/virtualmachine_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,8 @@ func restore_v1alpha3_VirtualMachineBootstrapSpec(
dstCloudInit.CloudConfig = srcCloudInit.CloudConfig
dstCloudInit.RawCloudConfig = mergeSecretKeySelector(dstCloudInit.RawCloudConfig, srcCloudInit.RawCloudConfig)
dstCloudInit.SSHAuthorizedKeys = srcCloudInit.SSHAuthorizedKeys
dstCloudInit.UseGlobalNameserversAsDefault = srcCloudInit.UseGlobalNameserversAsDefault
dstCloudInit.UseGlobalSearchDomainsAsDefault = srcCloudInit.UseGlobalSearchDomainsAsDefault
}
}

Expand Down
38 changes: 35 additions & 3 deletions api/v1alpha1/virtualmachine_conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ func TestVirtualMachineConversion(t *testing.T) {
Name: "cloud-init-secret",
Key: "user-data",
},
SSHAuthorizedKeys: []string{"my-ssh-key"},
SSHAuthorizedKeys: []string{"my-ssh-key"},
UseGlobalNameserversAsDefault: ptrOf(true),
UseGlobalSearchDomainsAsDefault: ptrOf(true),
},
},
Network: &vmopv1.VirtualMachineNetworkSpec{
Expand Down Expand Up @@ -258,7 +260,9 @@ func TestVirtualMachineConversion(t *testing.T) {
Name: "cloudinit-secret",
Key: "my-key",
},
SSHAuthorizedKeys: []string{"my-ssh-key"},
SSHAuthorizedKeys: []string{"my-ssh-key"},
UseGlobalNameserversAsDefault: ptrOf(true),
UseGlobalSearchDomainsAsDefault: ptrOf(false),
},
},
},
Expand All @@ -282,7 +286,9 @@ func TestVirtualMachineConversion(t *testing.T) {
},
},
},
SSHAuthorizedKeys: []string{"my-ssh-key"},
SSHAuthorizedKeys: []string{"my-ssh-key"},
UseGlobalNameserversAsDefault: ptrOf(false),
UseGlobalSearchDomainsAsDefault: ptrOf(true),
},
},
},
Expand All @@ -307,6 +313,32 @@ func TestVirtualMachineConversion(t *testing.T) {
hubSpokeHub(g, &hub, &vmopv1a1.VirtualMachine{})
})

t.Run("VirtualMachine hub-spoke-hub with CloudInit w/ just the UseGlobal...AsDefaults", func(t *testing.T) {
g := NewWithT(t)

hub1 := vmopv1.VirtualMachine{
Spec: vmopv1.VirtualMachineSpec{
Bootstrap: &vmopv1.VirtualMachineBootstrapSpec{
CloudInit: &vmopv1.VirtualMachineBootstrapCloudInitSpec{
UseGlobalNameserversAsDefault: ptrOf(true),
},
},
},
}
hubSpokeHub(g, &hub1, &vmopv1a1.VirtualMachine{})

hub2 := vmopv1.VirtualMachine{
Spec: vmopv1.VirtualMachineSpec{
Bootstrap: &vmopv1.VirtualMachineBootstrapSpec{
CloudInit: &vmopv1.VirtualMachineBootstrapCloudInitSpec{
UseGlobalSearchDomainsAsDefault: ptrOf(true),
},
},
},
}
hubSpokeHub(g, &hub2, &vmopv1a1.VirtualMachine{})
})

t.Run("VirtualMachine hub-spoke-hub with LinuxPrep", func(t *testing.T) {
g := NewWithT(t)

Expand Down
20 changes: 20 additions & 0 deletions api/v1alpha2/virtualmachine_bootstrap_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ type VirtualMachineBootstrapCloudInitSpec struct {
//
// +optional
SSHAuthorizedKeys []string `json:"sshAuthorizedKeys,omitempty"`

// UseGlobalNameserversAsDefault will use the global nameservers specified in the
// NetworkSpec as the per-interface nameservers when the per-interface nameservers
// is not provided.
//
// Defaults to true if omitted.
//
// +optional
// +kubebuilder:default:true
UseGlobalNameserversAsDefault *bool `json:"useGlobalNameserversAsDefault,omitempty"`

// UseGlobalSearchDomainsAsDefault will use the global search domains specified in the
// NetworkSpec as the per-interface search domains when the per-interface search domains
// is not provided.
//
// Defaults to true if omitted.
//
// +optional
// +kubebuilder:default:true
UseGlobalSearchDomainsAsDefault *bool `json:"useGlobalSearchDomainsAsDefault,omitempty"`
}

// VirtualMachineBootstrapLinuxPrepSpec describes the LinuxPrep configuration
Expand Down
6 changes: 4 additions & 2 deletions api/v1alpha2/virtualmachine_conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@ func TestVirtualMachineConversion(t *testing.T) {
Name: "cloud-init-secret",
Key: "user-data",
},
SSHAuthorizedKeys: []string{"my-ssh-key"},
SSHAuthorizedKeys: []string{"my-ssh-key"},
UseGlobalNameserversAsDefault: ptrOf(true),
UseGlobalSearchDomainsAsDefault: ptrOf(true),
},
LinuxPrep: &vmopv1.VirtualMachineBootstrapLinuxPrepSpec{
HardwareClockIsUTC: &[]bool{true}[0],
HardwareClockIsUTC: ptrOf(true),
TimeZone: "my-tz",
},
Sysprep: &vmopv1.VirtualMachineBootstrapSysprepSpec{
Expand Down
17 changes: 15 additions & 2 deletions api/v1alpha2/virtualmachine_network_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ type VirtualMachineNetworkInterfaceSpec struct {
// Please note this feature is available only with the following bootstrap
// providers: CloudInit and Sysprep.
//
// When using CloudInit and UseGlobalNameserversAsDefault is either unset or
// true, if nameservers is not provided, the global nameservers will be used
// instead.
//
// Please note that Linux allows only three nameservers
// (https://linux.die.net/man/5/resolv.conf).
//
Expand All @@ -163,6 +167,10 @@ type VirtualMachineNetworkInterfaceSpec struct {
// Please note this feature is available only with the following bootstrap
// providers: CloudInit.
//
// When using CloudInit and UseGlobalSearchDomainsAsDefault is either unset
// or true, if search domains is not provided, the global search domains
// will be used instead.
//
// +optional
SearchDomains []string `json:"searchDomains,omitempty"`
}
Expand Down Expand Up @@ -195,7 +203,10 @@ type VirtualMachineNetworkSpec struct {
//
// Please note global nameservers are only available with the following
// bootstrap providers: LinuxPrep and Sysprep. The Cloud-Init bootstrap
// provider supports per-interface nameservers.
// provider supports per-interface nameservers. However, when Cloud-Init
// is used and UseGlobalNameserversAsDefault is true, the global
// nameservers will be used when the per-interface nameservers is not
// provided.
//
// Please note that Linux allows only three nameservers
// (https://linux.die.net/man/5/resolv.conf).
Expand All @@ -208,7 +219,9 @@ type VirtualMachineNetworkSpec struct {
//
// Please note global search domains are only available with the following
// bootstrap providers: LinuxPrep and Sysprep. The Cloud-Init bootstrap
// provider supports per-interface search domains.
// provider supports per-interface search domains. However, when Cloud-Init
// is used and UseGlobalSearchDomainsAsDefault is true, the global search
// domains will be used when the per-interface search domains is not provided.
//
// +optional
SearchDomains []string `json:"searchDomains,omitempty"`
Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha2/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions api/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions api/v1alpha3/virtualmachine_bootstrap_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ type VirtualMachineBootstrapCloudInitSpec struct {
// SSHAuthorizedKeys is a list of public keys that CloudInit will apply to
// the guest's default user.
SSHAuthorizedKeys []string `json:"sshAuthorizedKeys,omitempty"`

// +optional
// +kubebuilder:default:true

// UseGlobalNameserversAsDefault will use the global nameservers specified in the
// NetworkSpec as the per-interface nameservers when the per-interface nameservers
// is not provided.
//
// Defaults to true if omitted.
UseGlobalNameserversAsDefault *bool `json:"useGlobalNameserversAsDefault,omitempty"`

// +optional
// +kubebuilder:default:true

// UseGlobalSearchDomainsAsDefault will use the global search domains specified in the
// NetworkSpec as the per-interface search domains when the per-interface search domains
// is not provided.
//
// Defaults to true if omitted.
UseGlobalSearchDomainsAsDefault *bool `json:"useGlobalSearchDomainsAsDefault,omitempty"`
}

// VirtualMachineBootstrapLinuxPrepSpec describes the LinuxPrep configuration
Expand Down
17 changes: 15 additions & 2 deletions api/v1alpha3/virtualmachine_network_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ type VirtualMachineNetworkInterfaceSpec struct {
// Please note this feature is available only with the following bootstrap
// providers: CloudInit and Sysprep.
//
// When using CloudInit and UseGlobalNameserversAsDefault is either unset or
// true, if nameservers is not provided, the global nameservers will be used
// instead.
//
// Please note that Linux allows only three nameservers
// (https://linux.die.net/man/5/resolv.conf).
Nameservers []string `json:"nameservers,omitempty"`
Expand All @@ -164,6 +168,10 @@ type VirtualMachineNetworkInterfaceSpec struct {
//
// Please note this feature is available only with the following bootstrap
// providers: CloudInit.
//
// When using CloudInit and UseGlobalSearchDomainsAsDefault is either unset
// or true, if search domains is not provided, the global search domains
// will be used instead.
SearchDomains []string `json:"searchDomains,omitempty"`
}

Expand Down Expand Up @@ -244,7 +252,10 @@ type VirtualMachineNetworkSpec struct {
//
// Please note global nameservers are only available with the following
// bootstrap providers: LinuxPrep and Sysprep. The Cloud-Init bootstrap
// provider supports per-interface nameservers.
// provider supports per-interface nameservers. However, when Cloud-Init
// is used and UseGlobalNameserversAsDefault is true, the global
// nameservers will be used when the per-interface nameservers is not
// provided.
//
// Please note that Linux allows only three nameservers
// (https://linux.die.net/man/5/resolv.conf).
Expand All @@ -257,7 +268,9 @@ type VirtualMachineNetworkSpec struct {
//
// Please note global search domains are only available with the following
// bootstrap providers: LinuxPrep and Sysprep. The Cloud-Init bootstrap
// provider supports per-interface search domains.
// provider supports per-interface search domains. However, when Cloud-Init
// is used and UseGlobalSearchDomainsAsDefault is true, the global search
// domains will be used when the per-interface search domains is not provided.
SearchDomains []string `json:"searchDomains,omitempty"`

// +optional
Expand Down
10 changes: 10 additions & 0 deletions api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,22 @@ spec:
items:
type: string
type: array
useGlobalNameserversAsDefault:
description: |-
UseGlobalNameserversAsDefault will use the global nameservers specified in the
NetworkSpec as the per-interface nameservers when the per-interface nameservers
is not provided.
Defaults to true if omitted.
type: boolean
useGlobalSearchDomainsAsDefault:
description: |-
UseGlobalSearchDomainsAsDefault will use the global search domains specified in the
NetworkSpec as the per-interface search domains when the per-interface search domains
is not provided.
Defaults to true if omitted.
type: boolean
type: object
linuxPrep:
description: |-
Expand Down Expand Up @@ -1410,6 +1426,10 @@ spec:
Please note this feature is available only with the following bootstrap
providers: CloudInit and Sysprep.
When using CloudInit and UseGlobalNameserversAsDefault is either unset or
true, if nameservers is not provided, the global nameservers will be used
instead.
Please note that Linux allows only three nameservers
(https://linux.die.net/man/5/resolv.conf).
items:
Expand Down Expand Up @@ -1480,6 +1500,10 @@ spec:
Please note this feature is available only with the following bootstrap
providers: CloudInit.
When using CloudInit and UseGlobalSearchDomainsAsDefault is either unset
or true, if search domains is not provided, the global search domains
will be used instead.
items:
type: string
type: array
Expand All @@ -1498,7 +1522,10 @@ spec:
Please note global nameservers are only available with the following
bootstrap providers: LinuxPrep and Sysprep. The Cloud-Init bootstrap
provider supports per-interface nameservers.
provider supports per-interface nameservers. However, when Cloud-Init
is used and UseGlobalNameserversAsDefault is true, the global
nameservers will be used when the per-interface nameservers is not
provided.
Please note that Linux allows only three nameservers
(https://linux.die.net/man/5/resolv.conf).
Expand All @@ -1512,7 +1539,9 @@ spec:
Please note global search domains are only available with the following
bootstrap providers: LinuxPrep and Sysprep. The Cloud-Init bootstrap
provider supports per-interface search domains.
provider supports per-interface search domains. However, when Cloud-Init
is used and UseGlobalSearchDomainsAsDefault is true, the global search
domains will be used when the per-interface search domains is not provided.
items:
type: string
type: array
Expand Down
Loading

0 comments on commit 5ef669c

Please sign in to comment.