Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/apis/machineconfiguration.openshift.io/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,11 +492,11 @@ type ContainerRuntimeConfiguration struct {
// logSizeMax specifies the Maximum size allowed for the container log file.
// Negative numbers indicate that no size limit is imposed.
// If it is positive, it must be >= 8192 to match/exceed conmon's read buffer.
LogSizeMax resource.Quantity `json:"logSizeMax,omitempty"`
LogSizeMax *resource.Quantity `json:"logSizeMax,omitempty"`

// overlaySize specifies the maximum size of a container image.
// This flag can be used to set quota on the size of container images.
OverlaySize resource.Quantity `json:"overlaySize,omitempty"`
OverlaySize *resource.Quantity `json:"overlaySize,omitempty"`

// defaultRuntime is the name of the OCI runtime to be used as the default.
DefaultRuntime ContainerRuntimeDefaultRuntime `json:"defaultRuntime,omitempty"`
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func RunContainerRuntimeBootstrap(templateDir string, crconfigs []*mcfgv1.Contai

var configFileList []generatedConfigFile
ctrcfg := cfg.Spec.ContainerRuntimeConfig
if !ctrcfg.OverlaySize.IsZero() {
if ctrcfg.OverlaySize != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applies to all changes:

Doesn’t this change the semantics of previously-created CRs? If I understand the situation correctly, it’s possible that users create the CRs with these fields missing, and something (patchContainerRuntimeConfigs??) updates them and adds "0" field values.

In the old version, those 0 values were treated as missing, i.e. the system did exactly what the users wanted, just in a confusing way; with this PR, wouldn’t the 0 values actually start being applied?

I suppose one way to tell would be to add (uint? e2e?) tests with CRs of that kind, and ensure that both empty values and "0" values are treated as missing. (Or maybe those tests already exist? I didn’t find them though a quick grep but I didn’t spend much time looking.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, my mistake, I didn’t notice that logic.

OverlaySize will, AFAICS, still cause mergeConfigChanges to be called, though with no edits. I guess that doesn’t make a difference.


Aesthetically I’d prefer for the code to consistently use a single condition, so that we just have “set to a relevant value / not set to a relevant value”, not “unset / set to zero / set to non-zero” to track.

But that’s weak a code style preference, to be decided by MCO maintainers.

storageTOML, err := mergeConfigChanges(originalStorageIgn, cfg, updateStorageConfig)
if err != nil {
klog.V(2).Infoln(cfg, err, "error merging user changes to storage.conf: %v", err)
Expand All @@ -49,7 +49,7 @@ func RunContainerRuntimeBootstrap(templateDir string, crconfigs []*mcfgv1.Contai
}
}
// Create the cri-o drop-in files
if ctrcfg.LogLevel != "" || ctrcfg.PidsLimit != nil || !ctrcfg.LogSizeMax.IsZero() || ctrcfg.DefaultRuntime != mcfgv1.ContainerRuntimeDefaultRuntimeEmpty {
if ctrcfg.LogLevel != "" || ctrcfg.PidsLimit != nil || ctrcfg.LogSizeMax != nil || ctrcfg.DefaultRuntime != mcfgv1.ContainerRuntimeDefaultRuntimeEmpty {
crioFileConfigs := createCRIODropinFiles(cfg)
configFileList = append(configFileList, crioFileConfigs...)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ func (ctrl *Controller) syncContainerRuntimeConfig(key string) error {

var configFileList []generatedConfigFile
ctrcfg := cfg.Spec.ContainerRuntimeConfig
if !ctrcfg.OverlaySize.IsZero() {
if ctrcfg.OverlaySize != nil {
storageTOML, err := mergeConfigChanges(originalStorageIgn, cfg, updateStorageConfig)
if err != nil {
klog.V(2).Infoln(cfg, err, "error merging user changes to storage.conf: %v", err)
Expand All @@ -623,7 +623,7 @@ func (ctrl *Controller) syncContainerRuntimeConfig(key string) error {
}

// Create the cri-o drop-in files
if ctrcfg.LogLevel != "" || ctrcfg.PidsLimit != nil || !ctrcfg.LogSizeMax.IsZero() || ctrcfg.DefaultRuntime != mcfgv1.ContainerRuntimeDefaultRuntimeEmpty {
if ctrcfg.LogLevel != "" || ctrcfg.PidsLimit != nil || ctrcfg.LogSizeMax != nil || ctrcfg.DefaultRuntime != mcfgv1.ContainerRuntimeDefaultRuntimeEmpty {
crioFileConfigs := createCRIODropinFiles(cfg)
configFileList = append(configFileList, crioFileConfigs...)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package containerruntimeconfig

import (
"context"
"encoding/json"
"fmt"
"reflect"
"testing"
Expand Down Expand Up @@ -494,10 +495,13 @@ func TestContainerRuntimeConfigCreate(t *testing.T) {
f := newFixture(t)
f.newController()

logSizeMax := resource.MustParse("9k")
overlaySize := resource.MustParse("3G")

cc := newControllerConfig(ctrlcommon.ControllerConfigName, platform)
mcp := helpers.NewMachineConfigPool("master", nil, helpers.MasterSelector, "v0")
mcp2 := helpers.NewMachineConfigPool("worker", nil, helpers.WorkerSelector, "v0")
ctrcfg1 := newContainerRuntimeConfig("set-log-level", &mcfgv1.ContainerRuntimeConfiguration{LogLevel: "debug", LogSizeMax: resource.MustParse("9k"), OverlaySize: resource.MustParse("3G")}, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "pools.operator.machineconfiguration.openshift.io/master", ""))
ctrcfg1 := newContainerRuntimeConfig("set-log-level", &mcfgv1.ContainerRuntimeConfiguration{LogLevel: "debug", LogSizeMax: &logSizeMax, OverlaySize: &overlaySize}, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "pools.operator.machineconfiguration.openshift.io/master", ""))
ctrCfgKey, _ := getManagedKeyCtrCfg(mcp, f.client, ctrcfg1)
mcs1 := helpers.NewMachineConfig(getManagedKeyCtrCfgDeprecated(mcp), map[string]string{"node-role": "master"}, "dummy://", []ign3types.File{{}})
mcs2 := mcs1.DeepCopy()
Expand Down Expand Up @@ -531,10 +535,13 @@ func TestContainerRuntimeConfigUpdate(t *testing.T) {
f := newFixture(t)
f.newController()

logSizeMax := resource.MustParse("9k")
overlaySize := resource.MustParse("3G")

cc := newControllerConfig(ctrlcommon.ControllerConfigName, platform)
mcp := helpers.NewMachineConfigPool("master", nil, helpers.MasterSelector, "v0")
mcp2 := helpers.NewMachineConfigPool("worker", nil, helpers.WorkerSelector, "v0")
ctrcfg1 := newContainerRuntimeConfig("set-log-level", &mcfgv1.ContainerRuntimeConfiguration{LogLevel: "debug", LogSizeMax: resource.MustParse("9k"), OverlaySize: resource.MustParse("3G")}, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "pools.operator.machineconfiguration.openshift.io/master", ""))
ctrcfg1 := newContainerRuntimeConfig("set-log-level", &mcfgv1.ContainerRuntimeConfiguration{LogLevel: "debug", LogSizeMax: &logSizeMax, OverlaySize: &overlaySize}, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "pools.operator.machineconfiguration.openshift.io/master", ""))
keyCtrCfg, _ := getManagedKeyCtrCfg(mcp, f.client, ctrcfg1)
mcs := helpers.NewMachineConfig(getManagedKeyCtrCfgDeprecated(mcp), map[string]string{"node-role": "master"}, "dummy://", []ign3types.File{{}})
mcsUpdate := mcs.DeepCopy()
Expand Down Expand Up @@ -1228,10 +1235,12 @@ func TestRegistriesValidation(t *testing.T) {
// for the options in containerruntime config
func TestContainerRuntimeConfigOptions(t *testing.T) {
var (
invalidPidsLimit int64 = 10
validPidsLimit int64 = 2048
validZerolimit int64 = 0
invalidNegLimit int64 = -10
invalidPidsLimit int64 = 10
validPidsLimit int64 = 2048
invalidLogSizeMax = resource.MustParse("3k")
validLogSizeMax = resource.MustParse("10k")
validZerolimit int64 = 0
invalidNegLimit int64 = -10
)
failureTests := []struct {
name string
Expand All @@ -1252,7 +1261,7 @@ func TestContainerRuntimeConfigOptions(t *testing.T) {
{
name: "inalid value of max log size",
config: &mcfgv1.ContainerRuntimeConfiguration{
LogSizeMax: resource.MustParse("3k"),
LogSizeMax: &invalidLogSizeMax,
},
},
{
Expand Down Expand Up @@ -1288,7 +1297,7 @@ func TestContainerRuntimeConfigOptions(t *testing.T) {
{
name: "valid max log size",
config: &mcfgv1.ContainerRuntimeConfiguration{
LogSizeMax: resource.MustParse("10k"),
LogSizeMax: &validLogSizeMax,
},
},
{
Expand Down Expand Up @@ -1324,6 +1333,74 @@ func TestContainerRuntimeConfigOptions(t *testing.T) {
}
}

func TestMarshalResourceQuantityOptionsJSON(t *testing.T) {
var (
validLogSizeMax = resource.MustParse("10k")
validOverlaySize = resource.MustParse("10G")
)

emptyValueTests := []struct {
name string
config *mcfgv1.ContainerRuntimeConfiguration
}{
{
name: "valid log level, overlaySize/logsizeMax should not appear in json",
config: &mcfgv1.ContainerRuntimeConfiguration{
LogLevel: "debug",
},
},
{
name: "valid value of default runtime, overlaySize/logsizeMax should not appear in json",
config: &mcfgv1.ContainerRuntimeConfiguration{
DefaultRuntime: "crun",
},
},
}

successTests := []struct {
name string
config *mcfgv1.ContainerRuntimeConfiguration
expectStr string
}{
{
name: "valid max log size should appear in json",
config: &mcfgv1.ContainerRuntimeConfiguration{
LogSizeMax: &validLogSizeMax,
LogLevel: "debug",
},
expectStr: "\"logSizeMax\":\"10k\"",
},
{
name: "valid max overlay size should appear in json",
config: &mcfgv1.ContainerRuntimeConfiguration{
OverlaySize: &validOverlaySize,
LogLevel: "debug",
},
expectStr: "\"overlaySize\":\"10G\"",
},
}

// Successful Tests
for _, test := range successTests {
ctrcfg := newContainerRuntimeConfig(test.name, test.config, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "", ""))
data, err := json.Marshal(ctrcfg)
if err != nil {
t.Errorf("%s: failed with %v. should have succeeded", test.name, err)
}
require.Contains(t, string(data), test.expectStr)
}

for _, test := range emptyValueTests {
ctrcfg := newContainerRuntimeConfig(test.name, test.config, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "", ""))
data, err := json.Marshal(ctrcfg)
if err != nil {
t.Errorf("%s: failed with %v. should have succeeded", test.name, err)
}
require.NotContains(t, string(data), "\"overlaySize\"", "\"overlaySize\"")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing LogSizeMax might be worthwhile here.

require.NotContains(t, string(data), "\"logSizeMax\"", "\"logSizeMax\"")
}
}

func getKey(config *mcfgv1.ContainerRuntimeConfig, t *testing.T) string {
key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(config)
if err != nil {
Expand Down
10 changes: 5 additions & 5 deletions pkg/controller/container-runtime-config/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,11 @@ func updateStorageConfig(data []byte, internal *mcfgv1.ContainerRuntimeConfigura
return nil, fmt.Errorf("error decoding crio config: %w", err)
}

if internal.OverlaySize.Value() < 0 {
if internal.OverlaySize != nil && internal.OverlaySize.Value() < 0 {
return nil, fmt.Errorf("invalid overlaySize config %q: the overlaySize should be larger than 0", internal.OverlaySize.String())
}

if internal.OverlaySize.Value() != 0 {
if internal.OverlaySize != nil && internal.OverlaySize.Value() != 0 {
tomlConf.Storage.Options.Size = internal.OverlaySize.String()
}

Expand Down Expand Up @@ -347,7 +347,7 @@ func createCRIODropinFiles(cfg *mcfgv1.ContainerRuntimeConfig) []generatedConfig
klog.V(2).Infoln(cfg, err, "error updating user changes for pids-limit to crio.conf.d: %v", err)
}
}
if ctrcfg.LogSizeMax.Value() != 0 {
if ctrcfg.LogSizeMax != nil && ctrcfg.LogSizeMax.Value() != 0 {
tomlConf := tomlConfigCRIOLogSizeMax{}
tomlConf.Crio.Runtime.LogSizeMax = ctrcfg.LogSizeMax.Value()
generatedConfigFileList, err = addTOMLgeneratedConfigFile(generatedConfigFileList, crioDropInFilePathLogSizeMax, tomlConf)
Expand Down Expand Up @@ -495,11 +495,11 @@ func validateUserContainerRuntimeConfig(cfg *mcfgv1.ContainerRuntimeConfig) erro
return fmt.Errorf("invalid PidsLimit %v", *ctrcfg.PidsLimit)
}

if ctrcfg.LogSizeMax.Value() > 0 && ctrcfg.LogSizeMax.Value() <= minLogSize {
if ctrcfg.LogSizeMax != nil && ctrcfg.LogSizeMax.Value() > 0 && ctrcfg.LogSizeMax.Value() <= minLogSize {
return fmt.Errorf("invalid LogSizeMax %q, cannot be less than 8kB", ctrcfg.LogSizeMax.String())
}

if ctrcfg.OverlaySize.Value() < 0 {
if ctrcfg.OverlaySize != nil && ctrcfg.OverlaySize.Value() < 0 {
return fmt.Errorf("invalid overlaySize %q, cannot be less than 0", ctrcfg.OverlaySize.String())
}

Expand Down
122 changes: 122 additions & 0 deletions pkg/controller/container-runtime-config/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ import (
"github.com/containers/image/v5/pkg/sysregistriesv2"
signature "github.com/containers/image/v5/signature"
"github.com/containers/image/v5/types"
storageconfig "github.com/containers/storage/pkg/config"
apicfgv1 "github.com/openshift/api/config/v1"
apioperatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1"
mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/diff"
)

Expand Down Expand Up @@ -834,3 +838,121 @@ func TestGetValidBlockAndAllowedRegistries(t *testing.T) {
})
}
}

func TestCreateCRIODropinFiles(t *testing.T) {
zeroLogSizeMax := resource.MustParse("0k")
validLogSizeMax := resource.MustParse("10G")

// Test zero value of logSizeMax will not be applied
zeroValueTests := []struct {
name string
cfg *mcfgv1.ContainerRuntimeConfiguration
filepath string
}{
{
name: "01-ctrcfg-logSizeMax will not be created if logSizeMax is zero",
cfg: &mcfgv1.ContainerRuntimeConfiguration{
LogSizeMax: &zeroLogSizeMax,
},
filepath: crioDropInFilePathLogSizeMax,
},
}

// Test valid value of logSizeMax will be applied to the drop-in file
validValueTests := []struct {
name string
cfg *mcfgv1.ContainerRuntimeConfiguration
filepath string
want []byte
}{
{
name: "01-ctrcfg-logSizeMax created for valid logSizeMax",
cfg: &mcfgv1.ContainerRuntimeConfiguration{
LogSizeMax: &validLogSizeMax,
},
filepath: crioDropInFilePathLogSizeMax,
want: []byte(`[crio]
[crio.runtime]
log_size_max = 10000000000
`),
},
}

for _, test := range zeroValueTests {
ctrcfg := newContainerRuntimeConfig(test.name, test.cfg, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "", ""))
files := createCRIODropinFiles(ctrcfg)
for _, file := range files {
if file.filePath == test.filepath {
t.Errorf("%s: failed. should not have created dropin file", test.name)
}
}
}

for _, test := range validValueTests {
ctrcfg := newContainerRuntimeConfig(test.name, test.cfg, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "", ""))
files := createCRIODropinFiles(ctrcfg)
for _, file := range files {
if file.filePath == test.filepath {
require.Equal(t, test.want, file.data, "createCRIODropinFiles() Diff, want %v, got %v", test.want, string(file.data))
}
}
}
}

func TestUpdateStorageConfig(t *testing.T) {
templateStorageConfig := tomlConfigStorage{}
buf := bytes.Buffer{}
err := toml.NewEncoder(&buf).Encode(templateStorageConfig)
require.NoError(t, err)
templateBytes := buf.Bytes()

zeroOverLayerSize := resource.MustParse("0k")
validOverLaySize := resource.MustParse("10G")

tests := []struct {
name string
cfg *mcfgv1.ContainerRuntimeConfiguration
want tomlConfigStorage
}{
{
name: "not apply zero value of overlaySize",
cfg: &mcfgv1.ContainerRuntimeConfiguration{
OverlaySize: &zeroOverLayerSize,
},
want: tomlConfigStorage{},
},
{
name: "apply valid overlaySize",
cfg: &mcfgv1.ContainerRuntimeConfiguration{
OverlaySize: &validOverLaySize,
},
want: tomlConfigStorage{
Storage: struct {
Driver string "toml:\"driver\""
RunRoot string "toml:\"runroot\""
GraphRoot string "toml:\"graphroot\""
Options struct{ storageconfig.OptionsConfig } "toml:\"options\""
}{
Options: struct{ storageconfig.OptionsConfig }{
storageconfig.OptionsConfig{
Size: "10G",
},
},
},
},
},
}

for _, test := range tests {
got, err := updateStorageConfig(templateBytes, test.cfg)
require.NoError(t, err)
gotConf := tomlConfigStorage{}
if _, err := toml.Decode(string(got), &gotConf); err != nil {
t.Errorf("error unmarshalling result: %v", err)
return
}
if !reflect.DeepEqual(gotConf, test.want) {
t.Errorf("%s: failed. got %v, want %v", test.name, got, test.want)
}
}
}