Skip to content

Commit

Permalink
Add kubernetes-version/injectKubernetesVersion to Metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
rybnico committed Dec 10, 2024
1 parent 96eeffd commit b93f181
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 44 deletions.
4 changes: 4 additions & 0 deletions api/v1alpha1/proxmoxmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,10 @@ type MetadataSettings struct {
// this will basically set the `provider-id` field in the metadata to `proxmox://<instanceID>`.
// +optional
ProviderIDInjection bool `json:"providerIDInjection,omitempty"`
// KubernetesVersionInjection enables the injection of the `kubernetesVersion` into the cloudinit metadata.
// this will basically set the `kubernetes-version` field in the metadata to Machine.Spec.Version
// +optional
KubernetesVersionInjection bool `json:"kubernetesVersionInjection,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ spec:
description: MetadataSettings defines the metadata settings
for this machine's VM.
properties:
kubernetesVersionInjection:
description: |-
KubernetesVersionInjection enables the injection of the `kubernetesVersion` into the cloudinit metadata.
this will basically set the `kubernetes-version` field in the metadata to Machine.Spec.Version
type: boolean
providerIDInjection:
description: |-
ProviderIDInjection enables the injection of the `providerID` into the cloudinit metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ spec:
description: MetadataSettings defines the metadata
settings for this machine's VM.
properties:
kubernetesVersionInjection:
description: |-
KubernetesVersionInjection enables the injection of the `kubernetesVersion` into the cloudinit metadata.
this will basically set the `kubernetes-version` field in the metadata to Machine.Spec.Version
type: boolean
providerIDInjection:
description: |-
ProviderIDInjection enables the injection of the `providerID` into the cloudinit metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ spec:
description: MetadataSettings defines the metadata settings for this
machine's VM.
properties:
kubernetesVersionInjection:
description: |-
KubernetesVersionInjection enables the injection of the `kubernetesVersion` into the cloudinit metadata.
this will basically set the `kubernetes-version` field in the metadata to Machine.Spec.Version
type: boolean
providerIDInjection:
description: |-
ProviderIDInjection enables the injection of the `providerID` into the cloudinit metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ spec:
description: MetadataSettings defines the metadata settings
for this machine's VM.
properties:
kubernetesVersionInjection:
description: |-
KubernetesVersionInjection enables the injection of the `kubernetesVersion` into the cloudinit metadata.
this will basically set the `kubernetes-version` field in the metadata to Machine.Spec.Version
type: boolean
providerIDInjection:
description: |-
ProviderIDInjection enables the injection of the `providerID` into the cloudinit metadata.
Expand Down
14 changes: 7 additions & 7 deletions internal/inject/inject_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestISOInjectorInjectCloudInit(t *testing.T) {
injector := &ISOInjector{
VirtualMachine: vm,
BootstrapData: []byte(""),
MetaRenderer: cloudinit.NewMetadata("xxx-xxxx", "my-custom-vm", true),
MetaRenderer: cloudinit.NewMetadata("xxx-xxxx", "my-custom-vm", "1.2.3", true, true),
NetworkRenderer: cloudinit.NewNetworkConfig([]cloudinit.NetworkConfigData{
{
Name: "eth0",
Expand Down Expand Up @@ -135,7 +135,7 @@ func TestISOInjectorInjectCloudInit_Errors(t *testing.T) {
injector := &ISOInjector{
VirtualMachine: vm,
BootstrapData: []byte(""),
MetaRenderer: cloudinit.NewMetadata("xxx-xxxx", "", true),
MetaRenderer: cloudinit.NewMetadata("xxx-xxxx", "", "", true, true),
NetworkRenderer: cloudinit.NewNetworkConfig([]cloudinit.NetworkConfigData{
{
Name: "eth0",
Expand All @@ -151,7 +151,7 @@ func TestISOInjectorInjectCloudInit_Errors(t *testing.T) {
require.Error(t, err)

// missing network
injector.MetaRenderer = cloudinit.NewMetadata("xxx-xxxx", "my-custom-vm", false)
injector.MetaRenderer = cloudinit.NewMetadata("xxx-xxxx", "my-custom-vm", "1.2.3", false, false)
injector.NetworkRenderer = cloudinit.NewNetworkConfig(nil)
err = injector.Inject(context.Background(), "cloudinit")
require.Error(t, err)
Expand Down Expand Up @@ -200,7 +200,7 @@ func TestISOInjectorInjectIgnition(t *testing.T) {
injector := &ISOInjector{
VirtualMachine: vm,
BootstrapData: []byte(bootstrapData),
MetaRenderer: cloudinit.NewMetadata("xxx-xxxx", "my-custom-vm", false),
MetaRenderer: cloudinit.NewMetadata("xxx-xxxx", "my-custom-vm", "1.2.3", false, false),
IgnitionEnricher: enricher,
}

Expand Down Expand Up @@ -260,14 +260,14 @@ func TestISOInjectorInjectIgnition_Errors(t *testing.T) {
require.Error(t, err)

// missing hostname
injector.MetaRenderer = cloudinit.NewMetadata("xxxx-xxxxx", "", false)
injector.MetaRenderer = cloudinit.NewMetadata("xxxx-xxxxx", "", "", false, false)
e.BootstrapData = []byte(bootstrapData)
err = injector.Inject(context.Background(), "ignition")
require.Error(t, err)

// no bootstrapdata
e.BootstrapData = nil
injector.MetaRenderer = cloudinit.NewMetadata("xxxx-xxxxx", "my-custom-vm", true)
injector.MetaRenderer = cloudinit.NewMetadata("xxxx-xxxxx", "my-custom-vm", "1.2.3", true, true)
injector.BootstrapData = []byte("invalid")
err = injector.Inject(context.Background(), "ignition")
require.Error(t, err)
Expand All @@ -292,7 +292,7 @@ func TestISOInjectorInject_Unsupported(t *testing.T) {
injector := &ISOInjector{
VirtualMachine: vm,
BootstrapData: []byte(""),
MetaRenderer: cloudinit.NewMetadata("xxx-xxxx", "", false),
MetaRenderer: cloudinit.NewMetadata("xxx-xxxx", "", "", false, false),
NetworkRenderer: cloudinit.NewNetworkConfig([]cloudinit.NetworkConfigData{
{
Name: "eth0",
Expand Down
27 changes: 16 additions & 11 deletions internal/service/vmservice/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,18 @@ func reconcileBootstrapData(ctx context.Context, machineScope *scope.MachineScop
return false, err
}

kubernetesVersion := ""
if machineScope.Machine.Spec.Version != nil {
kubernetesVersion = *machineScope.Machine.Spec.Version
}

machineScope.Logger.V(4).Info("reconciling BootstrapData.", "format", format)

// Inject userdata based on the format
if ptr.Deref(format, "") == ignition.FormatIgnition {
err = injectIgnition(ctx, machineScope, bootstrapData, biosUUID, nicData)
err = injectIgnition(ctx, machineScope, bootstrapData, biosUUID, nicData, kubernetesVersion)
} else if ptr.Deref(format, "") == cloudinit.FormatCloudConfig {
err = injectCloudInit(ctx, machineScope, bootstrapData, biosUUID, nicData)
err = injectCloudInit(ctx, machineScope, bootstrapData, biosUUID, nicData, kubernetesVersion)
}
if err != nil {
return false, errors.Wrap(err, "failed to inject bootstrap data")
Expand All @@ -86,12 +91,12 @@ func reconcileBootstrapData(ctx context.Context, machineScope *scope.MachineScop
return false, nil
}

func injectCloudInit(ctx context.Context, machineScope *scope.MachineScope, bootstrapData []byte, biosUUID string, nicData []cloudinit.NetworkConfigData) error {
func injectCloudInit(ctx context.Context, machineScope *scope.MachineScope, bootstrapData []byte, biosUUID string, nicData []cloudinit.NetworkConfigData, kubernetesVersion string) error {
// create network renderer
network := cloudinit.NewNetworkConfig(nicData)

// create metadata renderer
metadata := cloudinit.NewMetadata(biosUUID, machineScope.Name(), ptr.Deref(machineScope.ProxmoxMachine.Spec.MetadataSettings, infrav1alpha1.MetadataSettings{ProviderIDInjection: false}).ProviderIDInjection)
metadata := cloudinit.NewMetadata(biosUUID, machineScope.Name(), kubernetesVersion, ptr.Deref(machineScope.ProxmoxMachine.Spec.MetadataSettings, infrav1alpha1.MetadataSettings{ProviderIDInjection: false}).ProviderIDInjection, ptr.Deref(machineScope.ProxmoxMachine.Spec.MetadataSettings, infrav1alpha1.MetadataSettings{KubernetesVersionInjection: false}).KubernetesVersionInjection)

injector := getISOInjector(machineScope.VirtualMachine, bootstrapData, metadata, network)
if err := injector.Inject(ctx, inject.CloudConfigFormat); err != nil {
Expand All @@ -101,9 +106,9 @@ func injectCloudInit(ctx context.Context, machineScope *scope.MachineScope, boot
return nil
}

func injectIgnition(ctx context.Context, machineScope *scope.MachineScope, bootstrapData []byte, biosUUID string, nicData []cloudinit.NetworkConfigData) error {
func injectIgnition(ctx context.Context, machineScope *scope.MachineScope, bootstrapData []byte, biosUUID string, nicData []cloudinit.NetworkConfigData, kubernetesVersion string) error {
// create metadata renderer
metadata := cloudinit.NewMetadata(biosUUID, machineScope.Name(), ptr.Deref(machineScope.ProxmoxMachine.Spec.MetadataSettings, infrav1alpha1.MetadataSettings{ProviderIDInjection: false}).ProviderIDInjection)
metadata := cloudinit.NewMetadata(biosUUID, machineScope.Name(), kubernetesVersion, ptr.Deref(machineScope.ProxmoxMachine.Spec.MetadataSettings, infrav1alpha1.MetadataSettings{ProviderIDInjection: false}).ProviderIDInjection, ptr.Deref(machineScope.ProxmoxMachine.Spec.MetadataSettings, infrav1alpha1.MetadataSettings{KubernetesVersionInjection: false}).KubernetesVersionInjection)

// create an enricher
enricher := &ignition.Enricher{
Expand Down Expand Up @@ -332,7 +337,7 @@ func getCommonInterfaceConfig(ctx context.Context, machineScope *scope.MachineSc
// Only set IPAddresses if they haven't been set yet
if ippool := ifconfig.IPv4PoolRef; ippool != nil && ciconfig.IPAddress == "" {
// retrieve IPAddress.
var ifname = fmt.Sprintf("%s-%s", ciconfig.Name, infrav1alpha1.DefaultSuffix)
ifname := fmt.Sprintf("%s-%s", ciconfig.Name, infrav1alpha1.DefaultSuffix)
ipAddr, err := findIPAddress(ctx, machineScope, ifname)
if err != nil {
return errors.Wrapf(err, "unable to find IPAddress, device=%s", ifname)
Expand All @@ -347,7 +352,7 @@ func getCommonInterfaceConfig(ctx context.Context, machineScope *scope.MachineSc
ciconfig.Metric = metric
}
if ifconfig.IPv6PoolRef != nil && ciconfig.IPV6Address == "" {
var ifname = fmt.Sprintf("%s-%s", ciconfig.Name, infrav1alpha1.DefaultSuffix+"6")
ifname := fmt.Sprintf("%s-%s", ciconfig.Name, infrav1alpha1.DefaultSuffix+"6")
ipAddr, err := findIPAddress(ctx, machineScope, ifname)
if err != nil {
return errors.Wrapf(err, "unable to find IPAddress, device=%s", ifname)
Expand All @@ -368,7 +373,7 @@ func getVirtualNetworkDevices(_ context.Context, _ *scope.MachineScope, network
networkConfigData := make([]cloudinit.NetworkConfigData, 0, len(network.VRFs))

for _, device := range network.VRFs {
var config = ptr.To(cloudinit.NetworkConfigData{})
config := ptr.To(cloudinit.NetworkConfigData{})
config.Type = "vrf"
config.Name = device.Name
config.Table = device.Table
Expand All @@ -395,10 +400,10 @@ func getAdditionalNetworkDevices(ctx context.Context, machineScope *scope.Machin
networkConfigData := make([]cloudinit.NetworkConfigData, 0, len(network.AdditionalDevices))

// additional network devices append after the provisioning interface
var index = 1
index := 1
// additional network devices.
for _, nic := range network.AdditionalDevices {
var config = ptr.To(cloudinit.NetworkConfigData{})
config := ptr.To(cloudinit.NetworkConfigData{})

if nic.IPv4PoolRef != nil {
device := fmt.Sprintf("%s-%s", nic.Name, infrav1alpha1.DefaultSuffix)
Expand Down
7 changes: 4 additions & 3 deletions internal/service/vmservice/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,8 @@ func TestReconcileBootstrapData_VirtualDevices_VRF(t *testing.T) {
APIGroup: ptr.To("ipam.cluster.x-k8s.io"),
Kind: "InClusterIPPool",
Name: "sample",
}},
},
},
},
},
}
Expand Down Expand Up @@ -500,14 +501,14 @@ func TestReconcileBootstrapDataMissingNetworkConfig(t *testing.T) {
}

func TestDefaultISOInjector(t *testing.T) {
injector := defaultISOInjector(newRunningVM(), []byte("data"), cloudinit.NewMetadata(biosUUID, "test", true), cloudinit.NewNetworkConfig(nil))
injector := defaultISOInjector(newRunningVM(), []byte("data"), cloudinit.NewMetadata(biosUUID, "test", "1.2.3", true, true), cloudinit.NewNetworkConfig(nil))

require.NotEmpty(t, injector)
require.Equal(t, []byte("data"), injector.(*inject.ISOInjector).BootstrapData)
}

func TestIgnitionISOInjector(t *testing.T) {
injector := ignitionISOInjector(newRunningVM(), cloudinit.NewMetadata(biosUUID, "test", true), &ignition.Enricher{
injector := ignitionISOInjector(newRunningVM(), cloudinit.NewMetadata(biosUUID, "test", "1.2.3", true, true), &ignition.Enricher{
BootstrapData: []byte("data"),
Hostname: "test",
})
Expand Down
13 changes: 9 additions & 4 deletions pkg/cloudinit/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ hostname: {{ .Hostname }}
{{- if .ProviderIDInjection }}
provider-id: proxmox://{{ .InstanceID }}
{{- end }}
{{- if .KubernetesVersionInjection }}
kubernetes-version: {{ .KubernetesVersion }}
{{- end }}
`
)

Expand All @@ -32,12 +35,14 @@ type Metadata struct {
}

// NewMetadata returns a new Metadata object.
func NewMetadata(instanceID, hostname string, injectProviderID bool) *Metadata {
func NewMetadata(instanceID, hostname string, kubernetesVersion string, injectProviderID bool, injectKubernetesVersion bool) *Metadata {
ci := new(Metadata)
ci.data = BaseCloudInitData{
Hostname: hostname,
InstanceID: instanceID,
ProviderIDInjection: injectProviderID,
Hostname: hostname,
InstanceID: instanceID,
ProviderIDInjection: injectProviderID,
KubernetesVersion: kubernetesVersion,
KubernetesVersionInjection: injectKubernetesVersion,
}
return ci
}
Expand Down
47 changes: 37 additions & 10 deletions pkg/cloudinit/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,27 @@ const (
local-hostname: proxmox-control-plane
hostname: proxmox-control-plane
provider-id: proxmox://9a82e2ca-4294-11ee-be56-0242ac120002
kubernetes-version: 1.2.3
`
expectedValidMetadataWithoutProviderID = `instance-id: 9a82e2ca-4294-11ee-be56-0242ac120002
local-hostname: proxmox-control-plane
hostname: proxmox-control-plane
kubernetes-version: 1.2.3
`
expectedValidMetadataWithoutKubernetesVersion = `instance-id: 9a82e2ca-4294-11ee-be56-0242ac120002
local-hostname: proxmox-control-plane
hostname: proxmox-control-plane
provider-id: proxmox://9a82e2ca-4294-11ee-be56-0242ac120002
`
)

func TestMetadata_Render(t *testing.T) {
type args struct {
instanceID string
hostname string
injectProviderID bool
instanceID string
hostname string
kubernetesVersion string
injectProviderID bool
injectKubernetesVersion bool
}

type want struct {
Expand All @@ -54,9 +63,11 @@ func TestMetadata_Render(t *testing.T) {
"ValidCloudinit": {
reason: "rendering metadata",
args: args{
instanceID: "9a82e2ca-4294-11ee-be56-0242ac120002",
hostname: "proxmox-control-plane",
injectProviderID: true,
instanceID: "9a82e2ca-4294-11ee-be56-0242ac120002",
hostname: "proxmox-control-plane",
kubernetesVersion: "1.2.3",
injectProviderID: true,
injectKubernetesVersion: true,
},
want: want{
metadata: expectedValidMetadata,
Expand Down Expand Up @@ -84,20 +95,36 @@ func TestMetadata_Render(t *testing.T) {
"ValidCloudinitwithoutProviderID": {
reason: "rendering metadata if providerID is not injected",
args: args{
instanceID: "9a82e2ca-4294-11ee-be56-0242ac120002",
hostname: "proxmox-control-plane",
injectProviderID: false,
instanceID: "9a82e2ca-4294-11ee-be56-0242ac120002",
hostname: "proxmox-control-plane",
kubernetesVersion: "1.2.3",
injectProviderID: false,
injectKubernetesVersion: true,
},
want: want{
metadata: expectedValidMetadataWithoutProviderID,
err: nil,
},
},
"ValidCloudinitwithoutKubernetesVersion": {
reason: "rendering metadata if kubernetesVersion is not injected",
args: args{
instanceID: "9a82e2ca-4294-11ee-be56-0242ac120002",
hostname: "proxmox-control-plane",
kubernetesVersion: "1.2.3",
injectProviderID: true,
injectKubernetesVersion: false,
},
want: want{
metadata: expectedValidMetadataWithoutKubernetesVersion,
err: nil,
},
},
}

for n, tc := range cases {
t.Run(n, func(t *testing.T) {
ci := NewMetadata(tc.args.instanceID, tc.args.hostname, tc.args.injectProviderID)
ci := NewMetadata(tc.args.instanceID, tc.args.hostname, tc.args.kubernetesVersion, tc.args.injectProviderID, tc.args.injectKubernetesVersion)
metadata, err := ci.Render()
require.ErrorIs(t, err, tc.want.err)
require.Equal(t, tc.want.metadata, string(metadata))
Expand Down
10 changes: 6 additions & 4 deletions pkg/cloudinit/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ const (
// BaseCloudInitData is shared across all the various types of files written to disk.
// used to render cloudinit.
type BaseCloudInitData struct {
Hostname string
InstanceID string
ProviderIDInjection bool
NetworkConfigData []NetworkConfigData
Hostname string
InstanceID string
ProviderIDInjection bool
KubernetesVersion string
KubernetesVersionInjection bool
NetworkConfigData []NetworkConfigData
}

// NetworkConfigData is used to render network-config.
Expand Down
11 changes: 6 additions & 5 deletions pkg/ignition/enrich.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ import (

// Enricher is responsible for enriching the Ignition config with additional data.
type Enricher struct {
BootstrapData []byte
Hostname string
InstanceID string
ProviderID string
Network []cloudinit.NetworkConfigData
BootstrapData []byte
Hostname string
InstanceID string
ProviderID string
Network []cloudinit.NetworkConfigData
KubernetesVersion string
}

// Enrich enriches the Ignition config with additional data.
Expand Down

0 comments on commit b93f181

Please sign in to comment.