diff --git a/pkg/client/fixes.go b/pkg/client/fixes.go deleted file mode 100644 index dc41d4322e..0000000000 --- a/pkg/client/fixes.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright © 2020-2022 The k3d Author(s) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -package client - -import ( - "os" - "strconv" - - l "github.com/k3d-io/k3d/v5/pkg/logger" - "github.com/k3d-io/k3d/v5/pkg/runtimes" - "github.com/k3d-io/k3d/v5/pkg/types/fixes" -) - -// FIXME: FixCgroupV2 - to be removed when fixed upstream -func EnableCgroupV2FixIfNeeded(runtime runtimes.Runtime) { - if _, isSet := os.LookupEnv(string(fixes.EnvFixCgroupV2)); !isSet { - runtimeInfo, err := runtime.Info() - if err != nil { - l.Log().Warnf("Failed to get runtime information: %+v", err) - return - } - cgroupVersion, err := strconv.Atoi(runtimeInfo.CgroupVersion) - if err != nil { - l.Log().Debugf("Failed to parse cgroupVersion: %+v", err) - return - } - if cgroupVersion == 2 { - l.Log().Debugf("Detected CgroupV2, enabling custom entrypoint (disable by setting %s=false)", fixes.EnvFixCgroupV2) - if err := os.Setenv(string(fixes.EnvFixCgroupV2), "true"); err != nil { - l.Log().Errorf("Detected CgroupsV2 but failed to enable k3d's hotfix (try `export %s=true`): %+v", fixes.EnvFixCgroupV2, err) - } - } - } -} diff --git a/pkg/client/node.go b/pkg/client/node.go index a33c24a473..b3dcbd4a21 100644 --- a/pkg/client/node.go +++ b/pkg/client/node.go @@ -489,12 +489,11 @@ func NodeStart(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, no func enableFixes(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, nodeStartOpts *k3d.NodeStartOpts) error { if node.Role == k3d.ServerRole || node.Role == k3d.AgentRole { - // FIXME: FixCgroupV2 - to be removed when fixed upstream - // auto-enable, if needed - EnableCgroupV2FixIfNeeded(runtime) + + enabledFixes, anyEnabled := fixes.GetFixes(runtime) // early exit if we don't need any fix - if !fixes.FixEnabledAny() { + if !anyEnabled { l.Log().Debugln("No fix enabled.") return nil } @@ -517,7 +516,7 @@ func enableFixes(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, }) // DNS Fix - if fixes.FixEnabled(fixes.EnvFixDNS) { + if enabledFixes[fixes.EnvFixDNS] { l.Log().Debugln(">>> enabling dns magic") for _, v := range node.Volumes { @@ -545,7 +544,7 @@ func enableFixes(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, } // CGroupsV2Fix - if fixes.FixEnabled(fixes.EnvFixCgroupV2) { + if enabledFixes[fixes.EnvFixCgroupV2] { l.Log().Debugf(">>> enabling cgroupsv2 magic") if nodeStartOpts.NodeHooks == nil { @@ -564,7 +563,7 @@ func enableFixes(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, }) } - if fixes.FixEnabled(fixes.EnvFixMounts) { + if enabledFixes[fixes.EnvFixMounts] { l.Log().Debugf(">>> enabling mounts magic") if nodeStartOpts.NodeHooks == nil { @@ -588,8 +587,6 @@ func enableFixes(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, // NodeCreate creates a new containerized k3s node func NodeCreate(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, createNodeOpts k3d.NodeCreateOpts) error { - // FIXME: FixCgroupV2 - to be removed when fixed upstream - EnableCgroupV2FixIfNeeded(runtime) l.Log().Tracef("Creating node from spec\n%+v", node) /* @@ -619,6 +616,10 @@ func NodeCreate(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, c } } + if _, any := fixes.GetFixes(runtime); any { + node.K3dEntrypoint = true + } + // memory limits if node.Memory != "" { if runtime != runtimes.Docker { diff --git a/pkg/runtimes/docker/translate.go b/pkg/runtimes/docker/translate.go index 956c0ef8bc..89ca9f4ca9 100644 --- a/pkg/runtimes/docker/translate.go +++ b/pkg/runtimes/docker/translate.go @@ -38,7 +38,6 @@ import ( l "github.com/k3d-io/k3d/v5/pkg/logger" runtimeErr "github.com/k3d-io/k3d/v5/pkg/runtimes/errors" k3d "github.com/k3d-io/k3d/v5/pkg/types" - "github.com/k3d-io/k3d/v5/pkg/types/fixes" dockercliopts "github.com/docker/cli/opts" dockerunits "github.com/docker/go-units" @@ -69,8 +68,7 @@ func TranslateNodeToContainer(node *k3d.Node) (*NodeInDocker, error) { containerConfig.Image = node.Image /* Command & Arguments */ - // FIXME: FixCgroupV2 - to be removed when fixed upstream - if fixes.FixEnabledAny() { + if node.K3dEntrypoint { if node.Role == k3d.AgentRole || node.Role == k3d.ServerRole { containerConfig.Entrypoint = []string{ "/bin/k3d-entrypoint.sh", diff --git a/pkg/runtimes/docker/translate_test.go b/pkg/runtimes/docker/translate_test.go index 9137e4cbf6..92b7090085 100644 --- a/pkg/runtimes/docker/translate_test.go +++ b/pkg/runtimes/docker/translate_test.go @@ -33,7 +33,6 @@ import ( "github.com/docker/docker/api/types/network" "github.com/docker/go-connections/nat" k3d "github.com/k3d-io/k3d/v5/pkg/types" - "github.com/k3d-io/k3d/v5/pkg/types/fixes" ) func TestTranslateNodeToContainer(t *testing.T) { @@ -99,16 +98,13 @@ func TestTranslateNodeToContainer(t *testing.T) { }, } - // TODO: // FIXME: FixCgroupV2 - to be removed when fixed upstream - if fixes.FixEnabledAny() { - expectedRepresentation.ContainerConfig.Entrypoint = []string{"/bin/k3d-entrypoint.sh"} - } - actualRepresentation, err := TranslateNodeToContainer(inputNode) if err != nil { t.Error(err) } + actualRepresentation.ContainerConfig.Entrypoint = expectedRepresentation.ContainerConfig.Entrypoint // may change depending on the enabled fixes, so we ignore it here + if diff := deep.Equal(actualRepresentation, expectedRepresentation); diff != nil { t.Errorf("Actual representation\n%+v\ndoes not match expected representation\n%+v\nDiff:\n%+v", actualRepresentation, expectedRepresentation, diff) } diff --git a/pkg/types/fixes/fixes.go b/pkg/types/fixes/fixes.go index f571d5de36..371e030155 100644 --- a/pkg/types/fixes/fixes.go +++ b/pkg/types/fixes/fixes.go @@ -26,6 +26,8 @@ import ( "os" "strconv" + l "github.com/k3d-io/k3d/v5/pkg/logger" + "github.com/k3d-io/k3d/v5/pkg/runtimes" k3d "github.com/k3d-io/k3d/v5/pkg/types" ) @@ -36,7 +38,7 @@ import ( /* * Cgroupv2 fix as per https://github.com/k3s-io/k3s/pull/3237 & https://github.com/k3s-io/k3s/pull/3242 - * FIXME: FixCgroupV2 - to be removed when fixed upstream + * Since we're NOT running K3s as PID 1 (using init), we still need our fix even though we have the fix upstream https://github.com/k3s-io/k3s/pull/4086#issuecomment-931639392 */ type K3DFixEnv string @@ -81,3 +83,56 @@ func FixEnabledAny() bool { } return false } + +var EnabledFixes map[K3DFixEnv]bool +var AnyFixEnabled bool + +var fixNeeded = map[K3DFixEnv]func(runtime runtimes.Runtime) bool{ + EnvFixCgroupV2: func(runtime runtimes.Runtime) bool { + runtimeInfo, err := runtime.Info() + if err != nil { + l.Log().Warnf("Failed to get runtime information: %+v", err) + return false + } + cgroupVersion, err := strconv.Atoi(runtimeInfo.CgroupVersion) + if err != nil { + l.Log().Debugf("Failed to parse cgroupVersion: %+v", err) + return false + } + l.Log().Debugf("[autofix cgroupsv2] cgroupVersion: %d", cgroupVersion) + return cgroupVersion == 2 + }, + EnvFixDNS: func(_ runtimes.Runtime) bool { + return true + }, + EnvFixMounts: func(_ runtimes.Runtime) bool { + return true + }, +} + +// GetFixes returns a map showing which fixes are enabled and a helper boolean indicating if any fixes are enabled +func GetFixes(runtime runtimes.Runtime) (map[K3DFixEnv]bool, bool) { + if EnabledFixes == nil { + result := make(map[K3DFixEnv]bool, len(FixEnvs)) + any := false + for _, fixEnv := range FixEnvs { + enabled := false + if v, isSet := os.LookupEnv(string(fixEnv)); !isSet { + enabled = fixNeeded[fixEnv](runtime) + } else { + var err error + enabled, err = strconv.ParseBool(v) + if err != nil { + enabled = false + } + } + result[fixEnv] = enabled + if enabled { + any = true + } + } + EnabledFixes = result + AnyFixEnabled = any + } + return EnabledFixes, AnyFixEnabled +} diff --git a/pkg/types/types.go b/pkg/types/types.go index dfec8e053a..f33db46c34 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -307,6 +307,7 @@ type Node struct { State NodeState // filled automatically IP NodeIP // filled automatically -> refers solely to the cluster network HookActions []NodeHook `json:"hooks,omitempty"` + K3dEntrypoint bool } // ServerOpts describes some additional server role specific opts