diff options
author | Ashley Cui <acui@redhat.com> | 2020-06-30 17:21:52 -0400 |
---|---|---|
committer | Ashley Cui <acui@redhat.com> | 2020-07-02 13:30:59 -0400 |
commit | 9a1543caec75a7b02dd2ec9a1111756bb1716454 (patch) | |
tree | fb1223410fe7ce9e0831a39c73a70bd9efa0caee /libpod | |
parent | e84695213e35c22ba085e3831cbd025cd55a4c84 (diff) | |
download | podman-9a1543caec75a7b02dd2ec9a1111756bb1716454.tar.gz podman-9a1543caec75a7b02dd2ec9a1111756bb1716454.tar.bz2 podman-9a1543caec75a7b02dd2ec9a1111756bb1716454.zip |
Add --tz flag to create, run
--tz flag sets timezone inside container
Can be set to IANA timezone as well as `local` to match host machine
Signed-off-by: Ashley Cui <acui@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container.go | 9 | ||||
-rw-r--r-- | libpod/container_inspect.go | 2 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 57 | ||||
-rw-r--r-- | libpod/define/container_inspect.go | 3 | ||||
-rw-r--r-- | libpod/options.go | 24 |
5 files changed, 95 insertions, 0 deletions
diff --git a/libpod/container.go b/libpod/container.go index 20688e3ee..8ea25d6a0 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -424,6 +424,10 @@ type ContainerConfig struct { // to 0, 1, 2) that will be passed to the executed process. The total FDs // passed will be 3 + PreserveFDs. PreserveFDs uint `json:"preserveFds,omitempty"` + + // Timezone is the timezone inside the container. + // Local means it has the same timezone as the host machine + Timezone string `json:"timezone,omitempty"` } // ContainerNamedVolume is a named volume that will be mounted into the @@ -1248,3 +1252,8 @@ func (c *Container) AutoRemove() bool { } return c.Spec().Annotations[define.InspectAnnotationAutoremove] == define.InspectResponseTrue } + +func (c *Container) Timezone() string { + return c.config.Timezone + +} diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index c6d9e1a65..9fbdf2c8b 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -322,6 +322,8 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp ctrConfig.CreateCommand = c.config.CreateCommand + ctrConfig.Timezone = c.config.Timezone + return ctrConfig } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 2c78f6bd2..d61268eab 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1241,6 +1241,31 @@ func (c *Container) makeBindMounts() error { c.state.BindMounts["/etc/hostname"] = hostnamePath } + // Make /etc/localtime + if c.Timezone() != "" { + if _, ok := c.state.BindMounts["/etc/localtime"]; !ok { + var zonePath string + if c.Timezone() == "local" { + zonePath, err = filepath.EvalSymlinks("/etc/localtime") + if err != nil { + return errors.Wrapf(err, "error finding local timezone for container %s", c.ID()) + } + } else { + zone := filepath.Join("/usr/share/zoneinfo", c.Timezone()) + zonePath, err = filepath.EvalSymlinks(zone) + if err != nil { + return errors.Wrapf(err, "error setting timezone for container %s", c.ID()) + } + } + localtimePath, err := c.copyTimezoneFile(zonePath) + if err != nil { + return errors.Wrapf(err, "error setting timezone for container %s", c.ID()) + } + c.state.BindMounts["/etc/localtime"] = localtimePath + + } + } + // Make .containerenv // Empty file, so no need to recreate if it exists if _, ok := c.state.BindMounts["/run/.containerenv"]; !ok { @@ -1533,3 +1558,35 @@ func (c *Container) getOCICgroupPath() (string, error) { return "", errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager %s requested", c.runtime.config.Engine.CgroupManager) } } + +func (c *Container) copyTimezoneFile(zonePath string) (string, error) { + var localtimeCopy string = filepath.Join(c.state.RunDir, "localtime") + file, err := os.Stat(zonePath) + if err != nil { + return "", err + } + if file.IsDir() { + return "", errors.New("Invalid timezone: is a directory") + } + src, err := os.Open(zonePath) + if err != nil { + return "", err + } + defer src.Close() + dest, err := os.Create(localtimeCopy) + if err != nil { + return "", err + } + defer dest.Close() + _, err = io.Copy(dest, src) + if err != nil { + return "", err + } + if err := label.Relabel(localtimeCopy, c.config.MountLabel, false); err != nil { + return "", err + } + if err := dest.Chown(c.RootUID(), c.RootGID()); err != nil { + return "", err + } + return localtimeCopy, err +} diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go index 3fbeb8f0b..4e1fcca35 100644 --- a/libpod/define/container_inspect.go +++ b/libpod/define/container_inspect.go @@ -54,6 +54,9 @@ type InspectContainerConfig struct { // CreateCommand is the full command plus arguments of the process the // container has been created with. CreateCommand []string `json:"CreateCommand,omitempty"` + // Timezone is the timezone inside the container. + // Local means it has the same timezone as the host machine + Timezone string `json:"Timezone,omitempty"` } // InspectRestartPolicy holds information about the container's restart policy. diff --git a/libpod/options.go b/libpod/options.go index 4041fb1cf..83d2c2e1f 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1525,6 +1525,30 @@ func withSetAnon() VolumeCreateOption { } } +// WithTimezone sets the timezone in the container +func WithTimezone(path string) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return define.ErrCtrFinalized + } + if path != "local" { + zone := filepath.Join("/usr/share/zoneinfo", path) + + file, err := os.Stat(zone) + if err != nil { + return err + } + //We don't want to mount a timezone directory + if file.IsDir() { + return errors.New("Invalid timezone: is a directory") + } + } + + ctr.config.Timezone = path + return nil + } +} + // Pod Creation Options // WithPodName sets the name of the pod. |