Skip to content

Commit

Permalink
add NoCloud propogation method
Browse files Browse the repository at this point in the history
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
  • Loading branch information
kvaps committed Aug 3, 2023
1 parent 5bc186e commit 7727d5b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 49 deletions.
107 changes: 58 additions & 49 deletions pkg/cloud-init/cloud-init.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,7 @@ func ReadCloudInitVolumeDataSource(vmi *v1.VirtualMachineInstance, secretSourceD

for _, volume := range vmi.Spec.Volumes {
if volume.CloudInitNoCloud != nil {
err := resolveNoCloudSecrets(vmi, secretSourceDir)
if err != nil {
return nil, err
}

keys, err := resolveConfigDriveSecrets(vmi, secretSourceDir)
keys, err := resolveNoCloudSecrets(vmi, secretSourceDir)
if err != nil {
return nil, err
}
Expand All @@ -168,52 +163,14 @@ func ReadCloudInitVolumeDataSource(vmi *v1.VirtualMachineInstance, secretSourceD
return nil, nil
}

// resolveNoCloudSecrets is looking for CloudInitNoCloud volumes with UserDataSecretRef
// requests. It reads the `userdata` secret the corresponds to the given CloudInitNoCloud
// volume and sets the UserData field on that volume.
//
// Note: when using this function, make sure that your code can access the secret volumes.
func resolveNoCloudSecrets(vmi *v1.VirtualMachineInstance, secretSourceDir string) error {
volume := findCloudInitNoCloudSecretVolume(vmi.Spec.Volumes)
if volume == nil {
return nil
}

baseDir := filepath.Join(secretSourceDir, volume.Name)
var userDataError, networkDataError error
var userData, networkData string
if volume.CloudInitNoCloud.UserDataSecretRef != nil {
userData, userDataError = readFirstFoundFileFromDir(baseDir, []string{"userdata", "userData"})
}
if volume.CloudInitNoCloud.NetworkDataSecretRef != nil {
networkData, networkDataError = readFirstFoundFileFromDir(baseDir, []string{"networkdata", "networkData"})
}
if userDataError != nil && networkDataError != nil {
return fmt.Errorf("no cloud-init data-source found at volume: %s", volume.Name)
}

if userData != "" {
volume.CloudInitNoCloud.UserData = userData
}
if networkData != "" {
volume.CloudInitNoCloud.NetworkData = networkData
}

return nil
}

// resolveConfigDriveSecrets is looking for CloudInitConfigDriveSource volume source with
// UserDataSecretRef and NetworkDataSecretRef and resolves the secret from the corresponding
// VolumeMount.
//
// Note: when using this function, make sure that your code can access the secret volumes.
func resolveConfigDriveSecrets(vmi *v1.VirtualMachineInstance, secretSourceDir string) (map[string]string, error) {
func resolveSSHPublicKeys(accessCredentials []v1.AccessCredential, secretSourceDir string) (map[string]string, error) {
keys := make(map[string]string)
count := 0
for _, accessCred := range vmi.Spec.AccessCredentials {
for _, accessCred := range accessCredentials {

// check to see if access credential is propagated by config drive or not
if accessCred.SSHPublicKey == nil || accessCred.SSHPublicKey.PropagationMethod.ConfigDrive == nil {
// check to see if access credential is propagated by no cloud, config drive or not
// TODO: how to pass propogation method in argument?
if accessCred.SSHPublicKey == nil || (accessCred.SSHPublicKey.PropagationMethod.ConfigDrive == nil || accessCred.SSHPublicKey.PropagationMethod.NoCloud == nil) {
continue
}

Expand Down Expand Up @@ -249,6 +206,58 @@ func resolveConfigDriveSecrets(vmi *v1.VirtualMachineInstance, secretSourceDir s
count++
}
}
return keys, nil
}

// resolveNoCloudSecrets is looking for CloudInitNoCloud volumes with UserDataSecretRef
// requests. It reads the `userdata` secret the corresponds to the given CloudInitNoCloud
// volume and sets the UserData field on that volume.
//
// Note: when using this function, make sure that your code can access the secret volumes.
func resolveNoCloudSecrets(vmi *v1.VirtualMachineInstance, secretSourceDir string) (map[string]string, error) {
keys, err := resolveSSHPublicKeys(vmi.Spec.AccessCredentials, secretSourceDir)
if err != nil {
return keys, err
}

volume := findCloudInitNoCloudSecretVolume(vmi.Spec.Volumes)
if volume == nil {
return keys, nil
}

baseDir := filepath.Join(secretSourceDir, volume.Name)
var userDataError, networkDataError error
var userData, networkData string
if volume.CloudInitNoCloud.UserDataSecretRef != nil {
userData, userDataError = readFirstFoundFileFromDir(baseDir, []string{"userdata", "userData"})
}
if volume.CloudInitNoCloud.NetworkDataSecretRef != nil {
networkData, networkDataError = readFirstFoundFileFromDir(baseDir, []string{"networkdata", "networkData"})
}
if userDataError != nil && networkDataError != nil {
return keys, fmt.Errorf("no cloud-init data-source found at volume: %s", volume.Name)
}

if userData != "" {
volume.CloudInitNoCloud.UserData = userData
}
if networkData != "" {
volume.CloudInitNoCloud.NetworkData = networkData
}

return keys, nil
}

// resolveConfigDriveSecrets is looking for CloudInitConfigDriveSource volume source with
// UserDataSecretRef and NetworkDataSecretRef and resolves the secret from the corresponding
// VolumeMount.
//
// Note: when using this function, make sure that your code can access the secret volumes.
func resolveConfigDriveSecrets(vmi *v1.VirtualMachineInstance, secretSourceDir string) (map[string]string, error) {
keys, err := resolveSSHPublicKeys(vmi.Spec.AccessCredentials, secretSourceDir)
if err != nil {
return keys, err
}

volume := findCloudInitConfigDriveSecretVolume(vmi.Spec.Volumes)
if volume == nil {
Expand Down
5 changes: 5 additions & 0 deletions staging/src/kubevirt.io/api/core/v1/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,11 @@ type SSHPublicKeyAccessCredentialPropagationMethod struct {
// +optional
ConfigDrive *ConfigDriveSSHPublicKeyAccessCredentialPropagation `json:"configDrive,omitempty"`

// NoCloudPropagation means that the ssh public keys are injected
// into the VM using metadata using the noCloud cloud-init provider
// +optional
NoCloud *ConfigDriveSSHPublicKeyAccessCredentialPropagation `json:"noCloud,omitempty"`

// QemuGuestAgentAccessCredentailPropagation means ssh public keys are
// dynamically injected into the vm at runtime via the qemu guest agent.
// This feature requires the qemu guest agent to be running within the guest.
Expand Down

0 comments on commit 7727d5b

Please sign in to comment.