From a880c9c019ae4e230a546ccbced5fe4a2269c75b Mon Sep 17 00:00:00 2001 From: Martin Sehnoutka Date: Tue, 9 Nov 2021 16:13:06 +0100 Subject: [PATCH] osbuild2: new stage yum config This stage was introduced in osbuild 41. Add support into osbuild-composer and a test using test data from osbuild repo. --- internal/osbuild2/stage.go | 2 + internal/osbuild2/stage_test.go | 10 ++ internal/osbuild2/yum_config_stage.go | 57 +++++++++++ internal/osbuild2/yum_config_stage_test.go | 112 +++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 internal/osbuild2/yum_config_stage.go create mode 100644 internal/osbuild2/yum_config_stage_test.go diff --git a/internal/osbuild2/stage.go b/internal/osbuild2/stage.go index 7dc10dbb6..a5fbd6c30 100644 --- a/internal/osbuild2/stage.go +++ b/internal/osbuild2/stage.go @@ -152,6 +152,8 @@ func (stage *Stage) UnmarshalJSON(data []byte) error { options = new(AuthconfigStageOptions) case "org.osbuild.pwquality.conf": options = new(PwqualityConfStageOptions) + case "org.osbuild.yum.config": + options = new(YumConfigStageOptions) default: return fmt.Errorf("unexpected stage type: %s", rawStage.Type) } diff --git a/internal/osbuild2/stage_test.go b/internal/osbuild2/stage_test.go index 69410e5c2..763a70f00 100644 --- a/internal/osbuild2/stage_test.go +++ b/internal/osbuild2/stage_test.go @@ -667,6 +667,16 @@ func TestStage_UnmarshalJSON(t *testing.T) { data: []byte(`{"type":"org.osbuild.pwquality.conf","options":{"config":{}}}`), }, }, + { + name: "yum.config", + fields: fields{ + Type: "org.osbuild.yum.config", + Options: &YumConfigStageOptions{}, + }, + args: args{ + data: []byte(`{"type":"org.osbuild.yum.config","options":{}}`), + }, + }, } for idx, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/osbuild2/yum_config_stage.go b/internal/osbuild2/yum_config_stage.go new file mode 100644 index 000000000..89d6f2cc8 --- /dev/null +++ b/internal/osbuild2/yum_config_stage.go @@ -0,0 +1,57 @@ +package osbuild2 + +import ( + "fmt" +) + +type YumConfigConfig struct { + HttpCaching *string `json:"http_caching,omitempty"` +} + +type YumConfigPlugins struct { + Langpacks *YumConfigPluginsLangpacks `json:"langpacks,omitempty"` +} + +type YumConfigPluginsLangpacks struct { + Locales []string `json:"locales"` +} + +type YumConfigStageOptions struct { + Config *YumConfigConfig `json:"config,omitempty"` + Plugins *YumConfigPlugins `json:"plugins,omitempty"` +} + +func (YumConfigStageOptions) isStageOptions() {} + +func (o YumConfigStageOptions) validate() error { + // Allow values from the osbuild schema + if o.Config != nil && o.Config.HttpCaching != nil { + valid := false + allowed_http_caching_values := []string{"all", "packages", "lazy:packages", "none"} + for _, v := range allowed_http_caching_values { + if v == *o.Config.HttpCaching { + valid = true + } + } + if !valid { + return fmt.Errorf("yum config parameter http_caching does not allow %s as a value", *o.Config.HttpCaching) + } + } + + if o.Plugins != nil && o.Plugins.Langpacks != nil && len(o.Plugins.Langpacks.Locales) < 1 { + return fmt.Errorf("locales must contain at least one element") + } + + return nil +} + +func NewYumConfigStage(options *YumConfigStageOptions) *Stage { + if err := options.validate(); err != nil { + panic(err) + } + + return &Stage{ + Type: "org.osbuild.yum.config", + Options: options, + } +} diff --git a/internal/osbuild2/yum_config_stage_test.go b/internal/osbuild2/yum_config_stage_test.go new file mode 100644 index 000000000..918e74255 --- /dev/null +++ b/internal/osbuild2/yum_config_stage_test.go @@ -0,0 +1,112 @@ +package osbuild2 + +import ( + "encoding/json" + "reflect" + "testing" + + "github.com/osbuild/osbuild-composer/internal/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewYumConfigStage(t *testing.T) { + expectedStage := &Stage{ + Type: "org.osbuild.yum.config", + Options: &YumConfigStageOptions{}, + } + actualStage := NewYumConfigStage(&YumConfigStageOptions{}) + assert.Equal(t, expectedStage, actualStage) +} + +func TestJsonYumConfigStage(t *testing.T) { + expectedOptions := YumConfigStageOptions{ + Config: &YumConfigConfig{ + HttpCaching: common.StringToPtr("packages"), + }, + Plugins: &YumConfigPlugins{ + &YumConfigPluginsLangpacks{ + Locales: []string{"en_US.UTF-8"}, + }, + }, + } + inputString := `{"config": { + "http_caching": "packages" + }, + "plugins": { + "langpacks": { + "locales": [ + "en_US.UTF-8" + ] + } + }}` + var inputOptions YumConfigStageOptions + err := json.Unmarshal([]byte(inputString), &inputOptions) + assert.NoError(t, err, "failed to parse JSON yum config") + assert.True(t, reflect.DeepEqual(expectedOptions, inputOptions)) + + inputOptions = YumConfigStageOptions{ + Config: &YumConfigConfig{ + HttpCaching: common.StringToPtr("packages"), + }, + } + expectedString := `{"config":{"http_caching":"packages"}}` + inputBytes, err := json.Marshal(inputOptions) + assert.NoError(t, err, "failed to marshal YUM config into JSON") + assert.Equal(t, expectedString, string(inputBytes)) +} + +func TestYumConfigValidate(t *testing.T) { + tests := []struct { + options YumConfigStageOptions + valid bool + }{ + { + YumConfigStageOptions{}, + true, + }, + { + YumConfigStageOptions{ + Plugins: &YumConfigPlugins{ + Langpacks: &YumConfigPluginsLangpacks{ + Locales: []string{}, + }, + }, + }, + false, + }, + { + YumConfigStageOptions{ + Plugins: &YumConfigPlugins{ + Langpacks: &YumConfigPluginsLangpacks{ + Locales: []string{"en_US.UTF-8"}, + }, + }, + }, + true, + }, + { + YumConfigStageOptions{ + Config: &YumConfigConfig{ + HttpCaching: common.StringToPtr(""), + }, + }, + false, + }, + { + YumConfigStageOptions{ + Config: &YumConfigConfig{ + HttpCaching: common.StringToPtr("all"), + }, + }, + true, + }, + } + for _, test := range tests { + if test.valid { + require.NotPanics(t, func() { NewYumConfigStage(&test.options) }) + } else { + require.Panics(t, func() { NewYumConfigStage(&test.options) }) + } + } +}