osbuild2: add support for org.osbuild.cloud-init stage
Add support for the `org.osbuild.cloud-init` osbuild stage [1], which allows one to configure cloud-init by creating configuration files under `/etc/cloud/cloud.cfg.d/`. Add unit test cases for the newly added stage. [1] https://github.com/osbuild/osbuild/pull/689 Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
parent
9957f378ca
commit
20e1cfeba4
4 changed files with 166 additions and 0 deletions
73
internal/osbuild2/cloud_init_stage.go
Normal file
73
internal/osbuild2/cloud_init_stage.go
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package osbuild2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type CloudInitStageOptions struct {
|
||||
ConfigFiles map[string]CloudInitConfigFile `json:"configuration_files,omitempty"`
|
||||
}
|
||||
|
||||
func (CloudInitStageOptions) isStageOptions() {}
|
||||
|
||||
func NewCloudInitStage(options *CloudInitStageOptions) *Stage {
|
||||
return &Stage{
|
||||
Type: "org.osbuild.cloud-init",
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// Represents a cloud-init configuration file
|
||||
type CloudInitConfigFile struct {
|
||||
SystemInfo *CloudInitConfigSystemInfo `json:"system_info,omitempty"`
|
||||
}
|
||||
|
||||
// Unexported struct for use in CloudInitConfigFile's MarshalJSON() to prevent recursion
|
||||
type cloudInitConfigFile struct {
|
||||
SystemInfo *CloudInitConfigSystemInfo `json:"system_info,omitempty"`
|
||||
}
|
||||
|
||||
func (c CloudInitConfigFile) MarshalJSON() ([]byte, error) {
|
||||
if c.SystemInfo == nil {
|
||||
return nil, fmt.Errorf("at least one cloud-init configuration option must be specified")
|
||||
}
|
||||
configFile := cloudInitConfigFile(c)
|
||||
return json.Marshal(configFile)
|
||||
}
|
||||
|
||||
// Represents the 'system_info' configuration section
|
||||
type CloudInitConfigSystemInfo struct {
|
||||
DefaultUser *CloudInitConfigDefaultUser `json:"default_user,omitempty"`
|
||||
}
|
||||
|
||||
// Unexported struct for use in CloudInitConfigSystemInfo's MarshalJSON() to prevent recursion
|
||||
type cloudInitConfigSystemInfo struct {
|
||||
DefaultUser *CloudInitConfigDefaultUser `json:"default_user,omitempty"`
|
||||
}
|
||||
|
||||
func (si CloudInitConfigSystemInfo) MarshalJSON() ([]byte, error) {
|
||||
if si.DefaultUser == nil {
|
||||
return nil, fmt.Errorf("at least one configuration option must be specified for 'system_info' section")
|
||||
}
|
||||
systemInfo := cloudInitConfigSystemInfo(si)
|
||||
return json.Marshal(systemInfo)
|
||||
}
|
||||
|
||||
// Configuration of the 'default' user created by cloud-init.
|
||||
type CloudInitConfigDefaultUser struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// Unexported struct for use in CloudInitConfigDefaultUser's MarshalJSON() to prevent recursion
|
||||
type cloudInitConfigDefaultUser struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (du CloudInitConfigDefaultUser) MarshalJSON() ([]byte, error) {
|
||||
if du.Name == "" {
|
||||
return nil, fmt.Errorf("at least one configuration option must be specified for 'default_user' section")
|
||||
}
|
||||
defaultUser := cloudInitConfigDefaultUser(du)
|
||||
return json.Marshal(defaultUser)
|
||||
}
|
||||
61
internal/osbuild2/cloud_init_stage_test.go
Normal file
61
internal/osbuild2/cloud_init_stage_test.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package osbuild2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewCloudInitStage(t *testing.T) {
|
||||
expectedStage := &Stage{
|
||||
Type: "org.osbuild.cloud-init",
|
||||
Options: &CloudInitStageOptions{},
|
||||
}
|
||||
actualStage := NewCloudInitStage(&CloudInitStageOptions{})
|
||||
assert.Equal(t, expectedStage, actualStage)
|
||||
}
|
||||
|
||||
func TestCloudInitStage_MarshalJSON_Invalid(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
options CloudInitStageOptions
|
||||
}{
|
||||
{
|
||||
name: "no-config-file-section",
|
||||
options: CloudInitStageOptions{
|
||||
ConfigFiles: map[string]CloudInitConfigFile{
|
||||
"00-default_user.cfg": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no-system-info-section-option",
|
||||
options: CloudInitStageOptions{
|
||||
ConfigFiles: map[string]CloudInitConfigFile{
|
||||
"00-default_user.cfg": {
|
||||
SystemInfo: &CloudInitConfigSystemInfo{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no-default-user-section-option",
|
||||
options: CloudInitStageOptions{
|
||||
ConfigFiles: map[string]CloudInitConfigFile{
|
||||
"00-default_user.cfg": {
|
||||
SystemInfo: &CloudInitConfigSystemInfo{
|
||||
DefaultUser: &CloudInitConfigDefaultUser{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for idx, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotBytes, err := json.Marshal(tt.options)
|
||||
assert.NotNilf(t, err, "json.Marshal() didn't return an error, but: %s [idx: %d]", string(gotBytes), idx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -85,6 +85,8 @@ func (stage *Stage) UnmarshalJSON(data []byte) error {
|
|||
options = new(GroupsStageOptions)
|
||||
case "org.osbuild.timezone":
|
||||
options = new(TimezoneStageOptions)
|
||||
case "org.osbuild.cloud-init":
|
||||
options = new(CloudInitStageOptions)
|
||||
case "org.osbuild.chrony":
|
||||
options = new(ChronyStageOptions)
|
||||
case "org.osbuild.dracut":
|
||||
|
|
|
|||
|
|
@ -52,6 +52,36 @@ func TestStage_UnmarshalJSON(t *testing.T) {
|
|||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "cloud-init",
|
||||
fields: fields{
|
||||
Type: "org.osbuild.cloud-init",
|
||||
Options: &CloudInitStageOptions{},
|
||||
},
|
||||
args: args{
|
||||
data: []byte(`{"type":"org.osbuild.cloud-init","options":{}}`),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cloud-init-data",
|
||||
fields: fields{
|
||||
Type: "org.osbuild.cloud-init",
|
||||
Options: &CloudInitStageOptions{
|
||||
ConfigFiles: map[string]CloudInitConfigFile{
|
||||
"00-default_user.cfg": {
|
||||
SystemInfo: &CloudInitConfigSystemInfo{
|
||||
DefaultUser: &CloudInitConfigDefaultUser{
|
||||
Name: "ec2-user",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
data: []byte(`{"type":"org.osbuild.cloud-init","options":{"configuration_files":{"00-default_user.cfg":{"system_info":{"default_user":{"name":"ec2-user"}}}}}}`),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "chrony",
|
||||
fields: fields{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue