Skip to content

Commit

Permalink
Merge pull request openshift#3128 from cgwalters/helper-ign-file-with…
Browse files Browse the repository at this point in the history
…-compression

Move Ignition file generation to controller/common, fix Compression
  • Loading branch information
openshift-merge-robot committed May 3, 2022
2 parents 3528c8b + da5184f commit eff34a5
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 105 deletions.
47 changes: 47 additions & 0 deletions pkg/controller/common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ import (
mcfgclientset "github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned"
)

// strToPtr converts the input string to a pointer to itself
func strToPtr(s string) *string {
return &s
}

// MergeMachineConfigs combines multiple machineconfig objects into one object.
// It sorts all the configs in increasing order of their name.
// It uses the Ignition config from first object as base and appends all the rest.
Expand Down Expand Up @@ -765,6 +770,48 @@ func CalculateConfigFileDiffs(oldIgnConfig, newIgnConfig *ign3types.Config) []st
return diffFileSet
}

// NewIgnFile returns a simple ignition3 file from just path and file contents.
// It also ensures the compression field is set to the empty string, which is
// currently required for ensuring child configs that may be merged layer
// know that the input is not compressed.
//
// Note the default Ignition file mode is 0644, owned by root/root.
func NewIgnFile(path, contents string) ign3types.File {
return NewIgnFileBytes(path, []byte(contents))
}

// NewIgnFileBytes is like NewIgnFile, but accepts binary data
func NewIgnFileBytes(path string, contents []byte) ign3types.File {
return ign3types.File{
Node: ign3types.Node{
Path: path,
},
FileEmbedded1: ign3types.FileEmbedded1{
Contents: ign3types.Resource{
Source: strToPtr(dataurl.EncodeBytes(contents)),
Compression: strToPtr(""),
},
},
}
}

// NewIgnFileBytesOverwriting is like NewIgnFileBytes, but overwrites existing files by default
func NewIgnFileBytesOverwriting(path string, contents []byte) ign3types.File {
overwrite := true
return ign3types.File{
Node: ign3types.Node{
Path: path,
Overwrite: &overwrite,
},
FileEmbedded1: ign3types.FileEmbedded1{
Contents: ign3types.Resource{
Source: strToPtr(dataurl.EncodeBytes(contents)),
Compression: strToPtr(""), // See https://github.com/coreos/butane/issues/332
},
},
}
}

// GetIgnitionFileDataByPath retrieves the file data for a specified path from a given ignition config
func GetIgnitionFileDataByPath(config *ign3types.Config, path string) ([]byte, error) {
for _, f := range config.Storage.Files {
Expand Down
28 changes: 26 additions & 2 deletions pkg/controller/common/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/clarketm/json"
ign2types "github.com/coreos/ignition/config/v2_2/types"
ign3 "github.com/coreos/ignition/v2/config/v3_2"
ign3types "github.com/coreos/ignition/v2/config/v3_2/types"
validate3 "github.com/coreos/ignition/v2/config/validate"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -450,12 +451,35 @@ func TestRemoveIgnDuplicateFilesAndUnits(t *testing.T) {
assert.Equal(t, expectedIgn2Config, convertedIgn2Config)
}

// TestIgnitionMergeCompressed tests https://github.com/coreos/butane/issues/332
func TestIgnitionMergeCompressed(t *testing.T) {
testIgn3Config := ign3types.Config{}
testIgn3Config.Ignition.Version = "3.2.0"
mode := 420
testfiledata := "data:;base64,H4sIAAAAAAAAA0vLz+cCAKhlMn4EAAAA"
compression := "gzip"
tempFile := ign3types.File{Node: ign3types.Node{Path: "/etc/testfileconfig"},
FileEmbedded1: ign3types.FileEmbedded1{Contents: ign3types.Resource{Source: &testfiledata, Compression: &compression}, Mode: &mode}}
testIgn3Config.Storage.Files = append(testIgn3Config.Storage.Files, tempFile)

testIgn3Config2 := ign3types.Config{}
testIgn3Config2.Ignition.Version = "3.2.0"
testIgn3Config2.Storage.Files = append(testIgn3Config2.Storage.Files, NewIgnFile("/etc/testfileconfig", "hello world"))

merged := ign3.Merge(testIgn3Config, testIgn3Config2)
assert.NotNil(t, merged)
mergedFile := merged.Storage.Files[0]
contents, err := DecodeIgnitionFileContents(mergedFile.Contents.Source, mergedFile.Contents.Compression)
require.NoError(t, err)
assert.Equal(t, string(contents), "hello world")
}

func TestCalculateConfigFileDiffs(t *testing.T) {
var testIgn3ConfigOld ign3types.Config
var testIgn3ConfigNew ign3types.Config

oldTempFile := helpers.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "oldcertificates")
newTempFile := helpers.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "newcertificates")
oldTempFile := NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "oldcertificates")
newTempFile := NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "newcertificates")

// Make an "old" config with the existing file in it
testIgn3ConfigOld.Ignition.Version = "3.2.0"
Expand Down
19 changes: 1 addition & 18 deletions pkg/controller/container-runtime-config/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
apicfgv1 "github.com/openshift/api/config/v1"
apioperatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1"
"github.com/openshift/runtime-utils/pkg/registries"
"github.com/vincent-petithory/dataurl"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -108,29 +107,13 @@ type updateConfigFunc func(data []byte, internal *mcfgv1.ContainerRuntimeConfigu
// updated data.
func createNewIgnition(configs []generatedConfigFile) ign3types.Config {
tempIgnConfig := ctrlcommon.NewIgnConfig()
mode := 0644
overwrite := true
// Create ignitions
for _, ignConf := range configs {
// If the file is not included, the data will be nil so skip over
if ignConf.data == nil {
continue
}
configdu := dataurl.New(ignConf.data, "text/plain")
configdu.Encoding = dataurl.EncodingASCII
configduStr := configdu.String()
configTempFile := ign3types.File{
Node: ign3types.Node{
Path: ignConf.filePath,
Overwrite: &overwrite,
},
FileEmbedded1: ign3types.FileEmbedded1{
Mode: &mode,
Contents: ign3types.Resource{
Source: &(configduStr),
},
},
}
configTempFile := ctrlcommon.NewIgnFileBytesOverwriting(ignConf.filePath, ignConf.data)
tempIgnConfig.Storage.Files = append(tempIgnConfig.Storage.Files, configTempFile)
}

Expand Down
63 changes: 6 additions & 57 deletions pkg/controller/kubelet-config/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
ign3types "github.com/coreos/ignition/v2/config/v3_2/types"
"github.com/imdario/mergo"
osev1 "github.com/openshift/api/config/v1"
"github.com/vincent-petithory/dataurl"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -50,73 +49,23 @@ func createNewKubeletDynamicSystemReservedIgnition(autoSystemReserved *bool, use
}

config := fmt.Sprintf("NODE_SIZING_ENABLED=%s\nSYSTEM_RESERVED_MEMORY=%s\nSYSTEM_RESERVED_CPU=%s\n", autoNodeSizing, systemReservedMemory, systemReservedCPU)

mode := 0644
overwrite := true
du := dataurl.New([]byte(config), "text/plain")
du.Encoding = dataurl.EncodingASCII
duStr := du.String()

return &ign3types.File{
Node: ign3types.Node{
Path: "/etc/node-sizing-enabled.env",
Overwrite: &overwrite,
},
FileEmbedded1: ign3types.FileEmbedded1{
Mode: &mode,
Contents: ign3types.Resource{
Source: &(duStr),
},
},
}
r := ctrlcommon.NewIgnFileBytesOverwriting("/etc/node-sizing-enabled.env", []byte(config))
return &r
}

func createNewKubeletLogLevelIgnition(level int32) *ign3types.File {
config := fmt.Sprintf("[Service]\nEnvironment=\"KUBELET_LOG_LEVEL=%d\"\n", level)

mode := 0644
overwrite := true
du := dataurl.New([]byte(config), "text/plain")
du.Encoding = dataurl.EncodingASCII
duStr := du.String()

return &ign3types.File{
Node: ign3types.Node{
Path: "/etc/systemd/system/kubelet.service.d/20-logging.conf",
Overwrite: &overwrite,
},
FileEmbedded1: ign3types.FileEmbedded1{
Mode: &mode,
Contents: ign3types.Resource{
Source: &(duStr),
},
},
}
r := ctrlcommon.NewIgnFileBytesOverwriting("/etc/systemd/system/kubelet.service.d/20-logging.conf", []byte(config))
return &r
}

func createNewKubeletIgnition(jsonConfig []byte) *ign3types.File {
// Want the kubelet.conf file to have the pretty JSON formatting
buf := new(bytes.Buffer)
json.Indent(buf, jsonConfig, "", " ")

mode := 0644
overwrite := true
du := dataurl.New(buf.Bytes(), "text/plain")
du.Encoding = dataurl.EncodingASCII
duStr := du.String()

return &ign3types.File{
Node: ign3types.Node{
Path: "/etc/kubernetes/kubelet.conf",
Overwrite: &overwrite,
},
FileEmbedded1: ign3types.FileEmbedded1{
Mode: &mode,
Contents: ign3types.Resource{
Source: &(duStr),
},
},
}
r := ctrlcommon.NewIgnFileBytesOverwriting("/etc/kubernetes/kubelet.conf", buf.Bytes())
return &r
}

func createNewDefaultFeatureGate() *osev1.FeatureGate {
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/node/node_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -959,8 +959,8 @@ func TestAlertOnPausedKubeletCA(t *testing.T) {
mcp := helpers.NewMachineConfigPool("worker", nil, helpers.WorkerSelector, "v1")

mcfiles := []ign3types.File{
helpers.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", TestKubeletCABundle),
helpers.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "newcertificates"),
ctrlcommon.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", TestKubeletCABundle),
ctrlcommon.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "newcertificates"),
}

mcs := []*mcfgv1.MachineConfig{
Expand Down
24 changes: 12 additions & 12 deletions pkg/daemon/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -571,18 +571,18 @@ func TestDropinCheck(t *testing.T) {
// i.e. whether we need to reboot and what actions need to be taken if no reboot is needed
func TestCalculatePostConfigChangeAction(t *testing.T) {
files := map[string]ign3types.File{
"pullsecret1": helpers.NewIgnFile("/var/lib/kubelet/config.json", "kubelet conf 1\n"),
"pullsecret2": helpers.NewIgnFile("/var/lib/kubelet/config.json", "kubelet conf 2\n"),
"registries1": helpers.NewIgnFile("/etc/containers/registries.conf", "registries content 1\n"),
"registries2": helpers.NewIgnFile("/etc/containers/registries.conf", "registries content 2\n"),
"randomfile1": helpers.NewIgnFile("/etc/random-reboot-file", "test\n"),
"randomfile2": helpers.NewIgnFile("/etc/random-reboot-file", "test 2\n"),
"kubeletCA1": helpers.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "kubeletCA1\n"),
"kubeletCA2": helpers.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "kubeletCA2\n"),
"policy1": helpers.NewIgnFile("/etc/containers/policy.json", "policy1"),
"policy2": helpers.NewIgnFile("/etc/containers/policy.json", "policy2"),
"containers-gpg1": helpers.NewIgnFile("/etc/machine-config-daemon/no-reboot/containers-gpg.pub", "containers-gpg1"),
"containers-gpg2": helpers.NewIgnFile("/etc/machine-config-daemon/no-reboot/containers-gpg.pub", "containers-gpg2"),
"pullsecret1": ctrlcommon.NewIgnFile("/var/lib/kubelet/config.json", "kubelet conf 1\n"),
"pullsecret2": ctrlcommon.NewIgnFile("/var/lib/kubelet/config.json", "kubelet conf 2\n"),
"registries1": ctrlcommon.NewIgnFile("/etc/containers/registries.conf", "registries content 1\n"),
"registries2": ctrlcommon.NewIgnFile("/etc/containers/registries.conf", "registries content 2\n"),
"randomfile1": ctrlcommon.NewIgnFile("/etc/random-reboot-file", "test\n"),
"randomfile2": ctrlcommon.NewIgnFile("/etc/random-reboot-file", "test 2\n"),
"kubeletCA1": ctrlcommon.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "kubeletCA1\n"),
"kubeletCA2": ctrlcommon.NewIgnFile("/etc/kubernetes/kubelet-ca.crt", "kubeletCA2\n"),
"policy1": ctrlcommon.NewIgnFile("/etc/containers/policy.json", "policy1"),
"policy2": ctrlcommon.NewIgnFile("/etc/containers/policy.json", "policy2"),
"containers-gpg1": ctrlcommon.NewIgnFile("/etc/machine-config-daemon/no-reboot/containers-gpg.pub", "containers-gpg1"),
"containers-gpg2": ctrlcommon.NewIgnFile("/etc/machine-config-daemon/no-reboot/containers-gpg.pub", "containers-gpg2"),
}

tests := []struct {
Expand Down
14 changes: 0 additions & 14 deletions test/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/clarketm/json"
ign3types "github.com/coreos/ignition/v2/config/v3_2/types"
"github.com/vincent-petithory/dataurl"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -151,19 +150,6 @@ func NewMachineConfigPool(name string, mcSelector, nodeSelector *metav1.LabelSel
}
}

// NewIgnFile returns a simple ignition3 file from just path and file contents
func NewIgnFile(path, contents string) ign3types.File {
return ign3types.File{
Node: ign3types.Node{
Path: path,
},
FileEmbedded1: ign3types.FileEmbedded1{
Contents: ign3types.Resource{
Source: StrToPtr(dataurl.EncodeBytes([]byte(contents)))},
},
}
}

// CreateMachineConfigFromIgnition returns a MachineConfig object from an Ignition config passed to it
func CreateMachineConfigFromIgnition(ignCfg interface{}) *mcfgv1.MachineConfig {
return &mcfgv1.MachineConfig{
Expand Down

0 comments on commit eff34a5

Please sign in to comment.