mirror of
https://github.com/lxc/crio-lxc.git
synced 2026-02-05 09:45:04 +01:00
Make lxc *ConfigItem wrapper functions private.
Don't encourage API users to mix the lxcri and go-lxc API. The user should only use the OCI specs.Spec to create the container if possible. The go-lxc Container is exported as Container.LinuxContainer and can be used to access the go-lxc API if there is really a need for it. Signed-off-by: Ruben Jenster <r.jenster@drachenfels.de>
This commit is contained in:
34
cgroup.go
34
cgroup.go
@@ -97,7 +97,7 @@ func configureCgroup(rt *Runtime, c *Container) error {
|
||||
}
|
||||
|
||||
if pids := c.Spec.Linux.Resources.Pids; pids != nil {
|
||||
if err := c.SetConfigItem("lxc.cgroup2.pids.max", fmt.Sprintf("%d", pids.Limit)); err != nil {
|
||||
if err := c.setConfigItem("lxc.cgroup2.pids.max", fmt.Sprintf("%d", pids.Limit)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -122,30 +122,30 @@ func configureCgroupPath(rt *Runtime, c *Container) error {
|
||||
c.CgroupDir = c.Spec.Linux.CgroupsPath
|
||||
}
|
||||
|
||||
if err := c.SetConfigItem("lxc.cgroup.relative", "0"); err != nil {
|
||||
if err := c.setConfigItem("lxc.cgroup.relative", "0"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// @since lxc @a900cbaf257c6a7ee9aa73b09c6d3397581d38fb
|
||||
// checking for on of the config items shuld be enough, because they were introduced together ...
|
||||
// lxc.cgroup.dir.payload and lxc.cgroup.dir.monitor
|
||||
splitCgroup := c.SupportsConfigItem("lxc.cgroup.dir.container", "lxc.cgroup.dir.monitor")
|
||||
splitCgroup := c.supportsConfigItem("lxc.cgroup.dir.container", "lxc.cgroup.dir.monitor")
|
||||
|
||||
if !splitCgroup || rt.MonitorCgroup == "" {
|
||||
return c.SetConfigItem("lxc.cgroup.dir", c.CgroupDir)
|
||||
return c.setConfigItem("lxc.cgroup.dir", c.CgroupDir)
|
||||
}
|
||||
|
||||
c.MonitorCgroupDir = filepath.Join(rt.MonitorCgroup, c.ContainerID+".scope")
|
||||
|
||||
if err := c.SetConfigItem("lxc.cgroup.dir.container", c.CgroupDir); err != nil {
|
||||
if err := c.setConfigItem("lxc.cgroup.dir.container", c.CgroupDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.cgroup.dir.monitor", c.MonitorCgroupDir); err != nil {
|
||||
if err := c.setConfigItem("lxc.cgroup.dir.monitor", c.MonitorCgroupDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.SupportsConfigItem("lxc.cgroup.dir.monitor.pivot") {
|
||||
if err := c.SetConfigItem("lxc.cgroup.dir.monitor.pivot", rt.MonitorCgroup); err != nil {
|
||||
if c.supportsConfigItem("lxc.cgroup.dir.monitor.pivot") {
|
||||
if err := c.setConfigItem("lxc.cgroup.dir.monitor.pivot", rt.MonitorCgroup); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -191,16 +191,16 @@ func configureDeviceController(c *Container) error {
|
||||
}
|
||||
// decompose
|
||||
val := fmt.Sprintf("%s %s:%s %s", blockDevice, maj, min, dev.Access)
|
||||
if err := c.SetConfigItem(key, val); err != nil {
|
||||
if err := c.setConfigItem(key, val); err != nil {
|
||||
return err
|
||||
}
|
||||
val = fmt.Sprintf("%s %s:%s %s", charDevice, maj, min, dev.Access)
|
||||
if err := c.SetConfigItem(key, val); err != nil {
|
||||
if err := c.setConfigItem(key, val); err != nil {
|
||||
return err
|
||||
}
|
||||
case blockDevice, charDevice:
|
||||
val := fmt.Sprintf("%s %s:%s %s", dev.Type, maj, min, dev.Access)
|
||||
if err := c.SetConfigItem(key, val); err != nil {
|
||||
if err := c.setConfigItem(key, val); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
@@ -216,32 +216,32 @@ func configureCPUController(clxc *Runtime, slinux *specs.LinuxCPU) error {
|
||||
clxc.Log.Debug().Msg("TODO configure cgroup cpu controller")
|
||||
/*
|
||||
if cpu.Shares != nil && *cpu.Shares > 0 {
|
||||
if err := clxc.SetConfigItem("lxc.cgroup2.cpu.shares", fmt.Sprintf("%d", *cpu.Shares)); err != nil {
|
||||
if err := clxc.setConfigItem("lxc.cgroup2.cpu.shares", fmt.Sprintf("%d", *cpu.Shares)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if cpu.Quota != nil && *cpu.Quota > 0 {
|
||||
if err := clxc.SetConfigItem("lxc.cgroup2.cpu.cfs_quota_us", fmt.Sprintf("%d", *cpu.Quota)); err != nil {
|
||||
if err := clxc.setConfigItem("lxc.cgroup2.cpu.cfs_quota_us", fmt.Sprintf("%d", *cpu.Quota)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if cpu.Period != nil && *cpu.Period != 0 {
|
||||
if err := clxc.SetConfigItem("lxc.cgroup2.cpu.cfs_period_us", fmt.Sprintf("%d", *cpu.Period)); err != nil {
|
||||
if err := clxc.setConfigItem("lxc.cgroup2.cpu.cfs_period_us", fmt.Sprintf("%d", *cpu.Period)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if cpu.Cpus != "" {
|
||||
if err := clxc.SetConfigItem("lxc.cgroup2.cpuset.cpus", cpu.Cpus); err != nil {
|
||||
if err := clxc.setConfigItem("lxc.cgroup2.cpuset.cpus", cpu.Cpus); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if cpu.RealtimePeriod != nil && *cpu.RealtimePeriod > 0 {
|
||||
if err := clxc.SetConfigItem("lxc.cgroup2.cpu.rt_period_us", fmt.Sprintf("%d", *cpu.RealtimePeriod)); err != nil {
|
||||
if err := clxc.setConfigItem("lxc.cgroup2.cpu.rt_period_us", fmt.Sprintf("%d", *cpu.RealtimePeriod)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if cpu.RealtimeRuntime != nil && *cpu.RealtimeRuntime > 0 {
|
||||
if err := clxc.SetConfigItem("lxc.cgroup2.cpu.rt_runtime_us", fmt.Sprintf("%d", *cpu.RealtimeRuntime)); err != nil {
|
||||
if err := clxc.setConfigItem("lxc.cgroup2.cpu.rt_runtime_us", fmt.Sprintf("%d", *cpu.RealtimeRuntime)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
14
container.go
14
container.go
@@ -312,9 +312,9 @@ func (c *Container) kill(ctx context.Context, signum unix.Signal) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetConfigItem is a wrapper function and returns the
|
||||
// first value returned by *lxc.Container.ConfigItem
|
||||
func (c *Container) GetConfigItem(key string) string {
|
||||
// getConfigItem is a wrapper function and returns the
|
||||
// first value returned by lxc.Container.ConfigItem
|
||||
func (c *Container) getConfigItem(key string) string {
|
||||
vals := c.LinuxContainer.ConfigItem(key)
|
||||
if len(vals) > 0 {
|
||||
first := vals[0]
|
||||
@@ -327,9 +327,9 @@ func (c *Container) GetConfigItem(key string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetConfigItem is a wrapper for *lxc.Container.SetConfigItem.
|
||||
// setConfigItem is a wrapper for lxc.Container.setConfigItem.
|
||||
// and only adds additional logging.
|
||||
func (c *Container) SetConfigItem(key, value string) error {
|
||||
func (c *Container) setConfigItem(key, value string) error {
|
||||
err := c.LinuxContainer.SetConfigItem(key, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set config item '%s=%s': %w", key, value, err)
|
||||
@@ -338,8 +338,8 @@ func (c *Container) SetConfigItem(key, value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SupportsConfigItem is a wrapper for *lxc.Container.IsSupportedConfig item.
|
||||
func (c *Container) SupportsConfigItem(keys ...string) bool {
|
||||
// supportsConfigItem is a wrapper for lxc.Container.IsSupportedConfig item.
|
||||
func (c *Container) supportsConfigItem(keys ...string) bool {
|
||||
canCheck := lxc.VersionAtLeast(4, 0, 6)
|
||||
if !canCheck {
|
||||
c.Log.Warn().Msg("lxc.IsSupportedConfigItem is broken in liblxc < 4.0.6")
|
||||
|
||||
40
create.go
40
create.go
@@ -97,13 +97,13 @@ func configureContainer(rt *Runtime, c *Container) error {
|
||||
}
|
||||
|
||||
if c.Spec.Process.OOMScoreAdj != nil {
|
||||
if err := c.SetConfigItem("lxc.proc.oom_score_adj", fmt.Sprintf("%d", *c.Spec.Process.OOMScoreAdj)); err != nil {
|
||||
if err := c.setConfigItem("lxc.proc.oom_score_adj", fmt.Sprintf("%d", *c.Spec.Process.OOMScoreAdj)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if c.Spec.Process.NoNewPrivileges {
|
||||
if err := c.SetConfigItem("lxc.no_new_privs", "1"); err != nil {
|
||||
if err := c.setConfigItem("lxc.no_new_privs", "1"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func configureContainer(rt *Runtime, c *Container) error {
|
||||
if err := writeSeccompProfile(profilePath, c.Spec.Linux.Seccomp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.seccomp.profile", profilePath); err != nil {
|
||||
if err := c.setConfigItem("lxc.seccomp.profile", profilePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func configureContainer(rt *Runtime, c *Container) error {
|
||||
}
|
||||
|
||||
// make sure autodev is disabled
|
||||
if err := c.SetConfigItem("lxc.autodev", "0"); err != nil {
|
||||
if err := c.setConfigItem("lxc.autodev", "0"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ func configureContainer(rt *Runtime, c *Container) error {
|
||||
}
|
||||
|
||||
for key, val := range c.Spec.Linux.Sysctl {
|
||||
if err := c.SetConfigItem("lxc.sysctl."+key, val); err != nil {
|
||||
if err := c.setConfigItem("lxc.sysctl."+key, val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -207,7 +207,7 @@ func configureContainer(rt *Runtime, c *Container) error {
|
||||
}
|
||||
seenLimits = append(seenLimits, name)
|
||||
val := fmt.Sprintf("%d:%d", limit.Soft, limit.Hard)
|
||||
if err := c.SetConfigItem("lxc.prlimit."+name, val); err != nil {
|
||||
if err := c.setConfigItem("lxc.prlimit."+name, val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -226,7 +226,7 @@ func configureHostname(rt *Runtime, c *Container) error {
|
||||
if c.Spec.Hostname == "" {
|
||||
return nil
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.uts.name", c.Spec.Hostname); err != nil {
|
||||
if err := c.setConfigItem("lxc.uts.name", c.Spec.Hostname); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -256,20 +256,20 @@ func configureRootfs(rt *Runtime, c *Container) error {
|
||||
if !filepath.IsAbs(rootfs) {
|
||||
rootfs = filepath.Join(c.BundlePath, rootfs)
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.rootfs.path", rootfs); err != nil {
|
||||
if err := c.setConfigItem("lxc.rootfs.path", rootfs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.SetConfigItem("lxc.rootfs.mount", rootfs); err != nil {
|
||||
if err := c.setConfigItem("lxc.rootfs.mount", rootfs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.SetConfigItem("lxc.rootfs.managed", "0"); err != nil {
|
||||
if err := c.setConfigItem("lxc.rootfs.managed", "0"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Resources not created by the container runtime MUST NOT be deleted by it.
|
||||
if err := c.SetConfigItem("lxc.ephemeral", "0"); err != nil {
|
||||
if err := c.setConfigItem("lxc.ephemeral", "0"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -280,20 +280,20 @@ func configureRootfs(rt *Runtime, c *Container) error {
|
||||
if c.Spec.Root.Readonly {
|
||||
rootfsOptions = append(rootfsOptions, "ro")
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.rootfs.options", strings.Join(rootfsOptions, ",")); err != nil {
|
||||
if err := c.setConfigItem("lxc.rootfs.options", strings.Join(rootfsOptions, ",")); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureReadonlyPaths(c *Container) error {
|
||||
rootmnt := c.GetConfigItem("lxc.rootfs.mount")
|
||||
rootmnt := c.getConfigItem("lxc.rootfs.mount")
|
||||
if rootmnt == "" {
|
||||
return fmt.Errorf("lxc.rootfs.mount unavailable")
|
||||
}
|
||||
for _, p := range c.Spec.Linux.ReadonlyPaths {
|
||||
mnt := fmt.Sprintf("%s %s %s %s", filepath.Join(rootmnt, p), strings.TrimPrefix(p, "/"), "bind", "bind,ro,optional")
|
||||
if err := c.SetConfigItem("lxc.mount.entry", mnt); err != nil {
|
||||
if err := c.setConfigItem("lxc.mount.entry", mnt); err != nil {
|
||||
return fmt.Errorf("failed to make path readonly: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -306,7 +306,7 @@ func configureApparmor(c *Container) error {
|
||||
if aaprofile == "" {
|
||||
aaprofile = "unconfined"
|
||||
}
|
||||
return c.SetConfigItem("lxc.apparmor.profile", aaprofile)
|
||||
return c.setConfigItem("lxc.apparmor.profile", aaprofile)
|
||||
}
|
||||
|
||||
// configureCapabilities configures the linux capabilities / privileges granted to the container processes.
|
||||
@@ -326,7 +326,7 @@ func configureCapabilities(c *Container) error {
|
||||
}
|
||||
}
|
||||
|
||||
return c.SetConfigItem("lxc.cap.keep", keepCaps)
|
||||
return c.setConfigItem("lxc.cap.keep", keepCaps)
|
||||
}
|
||||
|
||||
// NOTE keep in sync with cmd/lxcri-hook#ociHooksAndState
|
||||
@@ -359,22 +359,22 @@ func configureHooks(rt *Runtime, c *Container) error {
|
||||
c.Spec.Hooks = &hooks
|
||||
|
||||
// pass context information as environment variables to hook scripts
|
||||
if err := c.SetConfigItem("lxc.hook.version", "1"); err != nil {
|
||||
if err := c.setConfigItem("lxc.hook.version", "1"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(c.Spec.Hooks.Prestart) > 0 || len(c.Spec.Hooks.CreateRuntime) > 0 {
|
||||
if err := c.SetConfigItem("lxc.hook.pre-mount", rt.libexec(ExecHook)); err != nil {
|
||||
if err := c.setConfigItem("lxc.hook.pre-mount", rt.libexec(ExecHook)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(c.Spec.Hooks.CreateContainer) > 0 {
|
||||
if err := c.SetConfigItem("lxc.hook.mount", rt.libexec(ExecHook)); err != nil {
|
||||
if err := c.setConfigItem("lxc.hook.mount", rt.libexec(ExecHook)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(c.Spec.Hooks.StartContainer) > 0 {
|
||||
if err := c.SetConfigItem("lxc.hook.start", rt.libexec(ExecHook)); err != nil {
|
||||
if err := c.setConfigItem("lxc.hook.start", rt.libexec(ExecHook)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
16
init.go
16
init.go
@@ -43,7 +43,7 @@ func configureInit(rt *Runtime, c *Container) error {
|
||||
Options: []string{"bind", "ro", "nodev", "nosuid", "create=dir"},
|
||||
})
|
||||
|
||||
if err := c.SetConfigItem("lxc.init.cwd", initDir); err != nil {
|
||||
if err := c.setConfigItem("lxc.init.cwd", initDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func configureInit(rt *Runtime, c *Container) error {
|
||||
Type: "bind",
|
||||
Options: []string{"bind", "ro", "nosuid"},
|
||||
})
|
||||
return c.SetConfigItem("lxc.init.cmd", initCmd)
|
||||
return c.setConfigItem("lxc.init.cmd", initCmd)
|
||||
}
|
||||
|
||||
func touchFile(filePath string, perm os.FileMode) error {
|
||||
@@ -90,25 +90,25 @@ func configureInitUser(c *Container) error {
|
||||
// TODO ensure that the user namespace is enabled
|
||||
// See `man lxc.container.conf` lxc.idmap.
|
||||
for _, m := range c.Spec.Linux.UIDMappings {
|
||||
if err := c.SetConfigItem("lxc.idmap", fmt.Sprintf("u %d %d %d", m.ContainerID, m.HostID, m.Size)); err != nil {
|
||||
if err := c.setConfigItem("lxc.idmap", fmt.Sprintf("u %d %d %d", m.ContainerID, m.HostID, m.Size)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, m := range c.Spec.Linux.GIDMappings {
|
||||
if err := c.SetConfigItem("lxc.idmap", fmt.Sprintf("g %d %d %d", m.ContainerID, m.HostID, m.Size)); err != nil {
|
||||
if err := c.setConfigItem("lxc.idmap", fmt.Sprintf("g %d %d %d", m.ContainerID, m.HostID, m.Size)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.SetConfigItem("lxc.init.uid", fmt.Sprintf("%d", c.Spec.Process.User.UID)); err != nil {
|
||||
if err := c.setConfigItem("lxc.init.uid", fmt.Sprintf("%d", c.Spec.Process.User.UID)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.init.gid", fmt.Sprintf("%d", c.Spec.Process.User.GID)); err != nil {
|
||||
if err := c.setConfigItem("lxc.init.gid", fmt.Sprintf("%d", c.Spec.Process.User.GID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(c.Spec.Process.User.AdditionalGids) > 0 && c.SupportsConfigItem("lxc.init.groups") {
|
||||
if len(c.Spec.Process.User.AdditionalGids) > 0 && c.supportsConfigItem("lxc.init.groups") {
|
||||
var b strings.Builder
|
||||
for i, gid := range c.Spec.Process.User.AdditionalGids {
|
||||
if i > 0 {
|
||||
@@ -116,7 +116,7 @@ func configureInitUser(c *Container) error {
|
||||
}
|
||||
fmt.Fprintf(&b, "%d", gid)
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.init.groups", b.String()); err != nil {
|
||||
if err := c.setConfigItem("lxc.init.groups", b.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
4
mount.go
4
mount.go
@@ -44,7 +44,7 @@ func filterMountOptions(rt *Runtime, fs string, opts []string) []string {
|
||||
|
||||
func configureMounts(rt *Runtime, c *Container) error {
|
||||
// excplicitly disable auto-mounting
|
||||
if err := c.SetConfigItem("lxc.mount.auto", ""); err != nil {
|
||||
if err := c.setConfigItem("lxc.mount.auto", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func configureMounts(rt *Runtime, c *Container) error {
|
||||
|
||||
mnt := fmt.Sprintf("%s %s %s %s", ms.Source, ms.Destination, ms.Type, strings.Join(ms.Options, ","))
|
||||
|
||||
if err := c.SetConfigItem("lxc.mount.entry", mnt); err != nil {
|
||||
if err := c.setConfigItem("lxc.mount.entry", mnt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,12 +73,12 @@ func configureNamespaces(c *Container) error {
|
||||
}
|
||||
|
||||
configKey := fmt.Sprintf("lxc.namespace.share.%s", n.Name)
|
||||
if err := c.SetConfigItem(configKey, ns.Path); err != nil {
|
||||
if err := c.setConfigItem(configKey, ns.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return c.SetConfigItem("lxc.namespace.clone", strings.Join(cloneNamespaces, " "))
|
||||
return c.setConfigItem("lxc.namespace.clone", strings.Join(cloneNamespaces, " "))
|
||||
}
|
||||
|
||||
func isNamespaceEnabled(spec *specs.Spec, nsType specs.LinuxNamespaceType) bool {
|
||||
|
||||
@@ -262,7 +262,7 @@ func (rt *Runtime) runStartCmd(ctx context.Context, c *Container) (err error) {
|
||||
if c.ConsoleSocket == "" && !c.Spec.Process.Terminal {
|
||||
// Inherit stdio from calling process (conmon).
|
||||
// lxc.console.path must be set to 'none' or stdio of init process is replaced with a PTY by lxc
|
||||
if err := c.SetConfigItem("lxc.console.path", "none"); err != nil {
|
||||
if err := c.setConfigItem("lxc.console.path", "none"); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Stdin = os.Stdin
|
||||
@@ -270,7 +270,7 @@ func (rt *Runtime) runStartCmd(ctx context.Context, c *Container) (err error) {
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
|
||||
// NOTE any config change via clxc.SetConfigItem
|
||||
// NOTE any config change via clxc.setConfigItem
|
||||
// must be done before calling SaveConfigFile
|
||||
err = c.LinuxContainer.SaveConfigFile(c.ConfigFilePath())
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user