diff options
30 files changed, 541 insertions, 194 deletions
diff --git a/docs/source/markdown/podman-generate-kube.1.md b/docs/source/markdown/podman-generate-kube.1.md index 2e00b58b6..2e9f68bf3 100644 --- a/docs/source/markdown/podman-generate-kube.1.md +++ b/docs/source/markdown/podman-generate-kube.1.md @@ -16,6 +16,9 @@ Volumes appear in the generated YAML according to two different volume types. Bi Potential name conflicts between volumes are avoided by using a standard naming scheme for each volume type. The *hostPath* volume types are named according to the path on the host machine, replacing forward slashes with hyphens less any leading and trailing forward slashes. The special case of the filesystem root, `/`, translates to the name `root`. Additionally, the name is suffixed with `-host` to avoid naming conflicts with *persistentVolumeClaim* volumes. Each *persistentVolumeClaim* volume type uses the name of its associated named volume suffixed with `-pvc`. +Note that if an init container is created with type `once` and the pod has been started, the init container will not show up in the generated kube YAML as `once` type init containers are deleted after they are run. If the pod has only been created and not started, it will be in the generated kube YAML. +Init containers created with type `always` will always be generated in the kube YAML as they are never deleted, even after running to completion. + Note that the generated Kubernetes YAML file can be used to re-run the deployment via podman-play-kube(1). ## OPTIONS diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md index 6af1bde1d..c170d6495 100644 --- a/docs/source/markdown/podman-play-kube.1.md +++ b/docs/source/markdown/podman-play-kube.1.md @@ -20,6 +20,8 @@ Currently, the supported Kubernetes kinds are: Only two volume types are supported by play kube, the *hostPath* and *persistentVolumeClaim* volume types. For the *hostPath* volume type, only the *default (empty)*, *DirectoryOrCreate*, *Directory*, *FileOrCreate*, *File*, and *Socket* subtypes are supported. The *CharDevice* and *BlockDevice* subtypes are not supported. Podman interprets the value of *hostPath* *path* as a file path when it contains at least one forward slash, otherwise Podman treats the value as the name of a named volume. When using a *persistentVolumeClaim*, the value for *claimName* is the name for the Podman named volume. +Note: When playing a kube YAML with init containers, the init container will be created with init type value `always`. + Note: *hostPath* volume types created by play kube will be given an SELinux private label (Z) Note: If the `:latest` tag is used, Podman will attempt to pull the image from a registry. If the image was built locally with Podman or Buildah, it will have `localhost` as the domain, in that case, Podman will use the image from the local store even if it has the `:latest` tag. diff --git a/docs/source/markdown/podman-system-connection-add.1.md b/docs/source/markdown/podman-system-connection-add.1.md index ad9acb4d8..fa763d7cc 100644 --- a/docs/source/markdown/podman-system-connection-add.1.md +++ b/docs/source/markdown/podman-system-connection-add.1.md @@ -41,9 +41,9 @@ $ podman system connection add QA podman.example.com $ podman system connection add --identity ~/.ssh/dev_rsa production ssh://root@server.example.com:2222 -$ podman system connection add unix:///run/podman/podman.sock +$ podman system connection add testing unix:///run/podman/podman.sock -$ podman system connection add tcp://localhost:8080 +$ podman system connection add debug tcp://localhost:8080 ``` ## SEE ALSO podman-system(1) , podman-system-connection(1) , containers.conf(5) @@ -16,7 +16,7 @@ require ( github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.16.0 github.com/containers/ocicrypt v1.1.2 - github.com/containers/psgo v1.5.2 + github.com/containers/psgo v1.6.0 github.com/containers/storage v1.35.0 github.com/coreos/go-systemd/v22 v22.3.2 github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3 @@ -50,7 +50,7 @@ require ( github.com/opencontainers/runc v1.0.2 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 github.com/opencontainers/runtime-tools v0.9.0 - github.com/opencontainers/selinux v1.8.4 + github.com/opencontainers/selinux v1.8.5 github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 github.com/rootless-containers/rootlesskit v0.14.5 @@ -256,8 +256,8 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0= github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/psgo v1.5.2 h1:3aoozst/GIwsrr/5jnFy3FrJay98uujPCu9lTuSZ/Cw= -github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU= +github.com/containers/psgo v1.6.0 h1:jkl/5kndKmJ/bnSFq8in6xRDAzgW26GnNuTxoycNFvk= +github.com/containers/psgo v1.6.0/go.mod h1:ggVhB2KQi9qGZdqSlczqN0BwcJdotmpRru87S1anRO8= github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM= github.com/containers/storage v1.32.6/go.mod h1:mdB+b89p+jU8zpzLTVXA0gWMmIo0WrkfGMh1R8O2IQw= github.com/containers/storage v1.33.1/go.mod h1:FUZPF4nJijX8ixdhByZJXf02cvbyLi6dyDwXdIe8QVY= @@ -732,7 +732,6 @@ github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283 h1:TVzvdjOalkJBNkbpPVMAr4KV9QRf2IjfxdyxwAK78Gs= github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -757,8 +756,9 @@ github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwy github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.8.4 h1:krlgQ6/j9CkCXT5oW0yVXdQFOME3NjKuuAZXuR6O7P4= github.com/opencontainers/selinux v1.8.4/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= +github.com/opencontainers/selinux v1.8.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA= +github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656 h1:WaxyNFpmIDu4i6so9r6LVFIbSaXqsj8oitMitt86ae4= github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo= github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw= @@ -768,7 +768,6 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -832,7 +831,6 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf h1:b0+ZBD3rohnkQ4q5duD1+RyTXTg9yk+qTOPMSQtapO0= github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -1117,7 +1115,6 @@ golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1201,6 +1198,7 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/libpod/container.go b/libpod/container.go index 0986a0d80..a4bbb5dd0 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -1062,6 +1062,11 @@ func (c *Container) IsInfra() bool { return c.config.IsInfra } +// IsInitCtr returns whether the container is an init container +func (c *Container) IsInitCtr() bool { + return len(c.config.InitContainerType) > 0 +} + // IsReadOnly returns whether the container is running in read only mode func (c *Container) IsReadOnly() bool { return c.config.Spec.Root.Readonly diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go index ee03570ab..0d4cba85e 100644 --- a/libpod/container_top_linux.go +++ b/libpod/container_top_linux.go @@ -47,7 +47,7 @@ func (c *Container) Top(descriptors []string) ([]string, error) { if psgoErr == nil { return output, nil } - if errors.Cause(psgoErr) != psgo.ErrUnknownDescriptor { + if !errors.Is(psgoErr, psgo.ErrUnknownDescriptor) { return nil, psgoErr } diff --git a/libpod/kube.go b/libpod/kube.go index fff040adb..812bb101b 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -4,6 +4,7 @@ import ( "fmt" "math/rand" "os" + "sort" "strconv" "strings" "time" @@ -220,8 +221,14 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor deDupPodVolumes := make(map[string]*v1.Volume) first := true podContainers := make([]v1.Container, 0, len(containers)) + podInitCtrs := []v1.Container{} podAnnotations := make(map[string]string) dnsInfo := v1.PodDNSConfig{} + + // Let's sort the containers in order of created time + // This will ensure that the init containers are defined in the correct order in the kube yaml + sort.Slice(containers, func(i, j int) bool { return containers[i].CreatedTime().Before(containers[j].CreatedTime()) }) + for _, ctr := range containers { if !ctr.IsInfra() { // Convert auto-update labels into kube annotations @@ -229,6 +236,8 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor podAnnotations[k] = v } + isInit := ctr.IsInitCtr() + ctr, volumes, _, err := containerToV1Container(ctr) if err != nil { return nil, err @@ -245,6 +254,10 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor ctr.Ports = ports first = false } + if isInit { + podInitCtrs = append(podInitCtrs, ctr) + continue + } podContainers = append(podContainers, ctr) // Deduplicate volumes, so if containers in the pod share a volume, it's only // listed in the volumes section once @@ -278,13 +291,14 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor return newPodObject( p.Name(), podAnnotations, + podInitCtrs, podContainers, podVolumes, &dnsInfo, hostNetwork), nil } -func newPodObject(podName string, annotations map[string]string, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod { +func newPodObject(podName string, annotations map[string]string, initCtrs, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod { tm := v12.TypeMeta{ Kind: "Pod", APIVersion: "v1", @@ -304,9 +318,10 @@ func newPodObject(podName string, annotations map[string]string, containers []v1 Annotations: annotations, } ps := v1.PodSpec{ - Containers: containers, - Volumes: volumes, - HostNetwork: hostNetwork, + Containers: containers, + HostNetwork: hostNetwork, + InitContainers: initCtrs, + Volumes: volumes, } if dnsOptions != nil { ps.DNSConfig = dnsOptions @@ -323,6 +338,7 @@ func newPodObject(podName string, annotations map[string]string, containers []v1 // for a single container. we "insert" that container description in a pod. func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { kubeCtrs := make([]v1.Container, 0, len(ctrs)) + kubeInitCtrs := []v1.Container{} kubeVolumes := make([]v1.Volume, 0) hostNetwork := true podDNS := v1.PodDNSConfig{} @@ -333,6 +349,8 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { kubeAnnotations[k] = v } + isInit := ctr.IsInitCtr() + if !ctr.HostNetwork() { hostNetwork = false } @@ -340,7 +358,11 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { if err != nil { return nil, err } - kubeCtrs = append(kubeCtrs, kubeCtr) + if isInit { + kubeInitCtrs = append(kubeInitCtrs, kubeCtr) + } else { + kubeCtrs = append(kubeCtrs, kubeCtr) + } kubeVolumes = append(kubeVolumes, kubeVols...) // Combine DNS information in sum'd structure @@ -379,6 +401,7 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { return newPodObject( strings.ReplaceAll(ctrs[0].Name(), "_", ""), kubeAnnotations, + kubeInitCtrs, kubeCtrs, kubeVolumes, &podDNS, diff --git a/libpod/stats.go b/libpod/stats.go index 6f0360ef1..975152535 100644 --- a/libpod/stats.go +++ b/libpod/stats.go @@ -30,7 +30,7 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de } } - if c.state.State != define.ContainerStateRunning { + if c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused { return stats, define.ErrCtrStateInvalid } @@ -54,6 +54,12 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de return nil, err } + // If the current total usage in the cgroup is less than what was previously + // recorded then it means the container was restarted and runs in a new cgroup + if previousStats.Duration > cgroupStats.CPU.Usage.Total { + previousStats = &define.ContainerStats{} + } + previousCPU := previousStats.CPUNano now := uint64(time.Now().UnixNano()) stats.Duration = cgroupStats.CPU.Usage.Total @@ -65,7 +71,7 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit) stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100 stats.PIDs = 0 - if conState == define.ContainerStateRunning { + if conState == define.ContainerStateRunning || conState == define.ContainerStatePaused { stats.PIDs = cgroupStats.Pids.Current } stats.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats) diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index 851955207..b95fbfdd8 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -97,7 +97,7 @@ streamLabel: // A label to flatten the scope default: // Container stats - stats, err := ctnr.GetContainerStats(stats) + stats, err = ctnr.GetContainerStats(stats) if err != nil { logrus.Errorf("Unable to get container stats: %v", err) return diff --git a/pkg/api/handlers/swagger/swagger.go b/pkg/api/handlers/swagger/swagger.go index 2296eea3a..9844839b7 100644 --- a/pkg/api/handlers/swagger/swagger.go +++ b/pkg/api/handlers/swagger/swagger.go @@ -176,3 +176,12 @@ type swagInspectPodResponse struct { define.InspectPodData } } + +// Get stats for one or more containers +// swagger:response ContainerStats +type swagContainerStatsResponse struct { + // in:body + Body struct { + define.ContainerStats + } +} diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 2a32966cc..8dcea1301 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -1124,11 +1124,9 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // - application/json // responses: // 200: - // description: no error + // $ref: "#/responses/ContainerStats" // 404: // $ref: "#/responses/NoSuchContainer" - // 409: - // $ref: "#/responses/ConflictError" // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/stats"), s.APIHandler(libpod.StatsContainer)).Methods(http.MethodGet) diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go index 77329e328..f630b3f24 100644 --- a/pkg/domain/entities/play.go +++ b/pkg/domain/entities/play.go @@ -51,6 +51,8 @@ type PlayKubePod struct { ID string // Containers - the IDs of the containers running in the created pod. Containers []string + // InitContainers - the IDs of the init containers to be run in the created pod. + InitContainers []string // Logs - non-fatal errors and log messages while processing. Logs []string // ContainerErrors - any errors that occurred while starting containers diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index c6d5dcc3d..87506f70c 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -304,76 +304,59 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY } containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers)) + initContainers := make([]*libpod.Container, 0, len(podYAML.Spec.InitContainers)) cwd, err := os.Getwd() if err != nil { return nil, err } + + for _, initCtr := range podYAML.Spec.InitContainers { + // Init containers cannot have either of lifecycle, livenessProbe, readinessProbe, or startupProbe set + if initCtr.Lifecycle != nil || initCtr.LivenessProbe != nil || initCtr.ReadinessProbe != nil || initCtr.StartupProbe != nil { + return nil, errors.Errorf("cannot create an init container that has either of lifecycle, livenessProbe, readinessProbe, or startupProbe set") + } + pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, initCtr, options) + if err != nil { + return nil, err + } + + specgenOpts := kube.CtrSpecGenOptions{ + Container: initCtr, + Image: pulledImage, + Volumes: volumes, + PodID: pod.ID(), + PodName: podName, + PodInfraID: podInfraID, + ConfigMaps: configMaps, + SeccompPaths: seccompPaths, + RestartPolicy: ctrRestartPolicy, + NetNSIsHost: p.NetNS.IsHost(), + SecretsManager: secretsManager, + LogDriver: options.LogDriver, + Labels: labels, + InitContainerType: define.AlwaysInitContainer, + } + specGen, err := kube.ToSpecGen(ctx, &specgenOpts) + if err != nil { + return nil, err + } + rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen) + if err != nil { + return nil, err + } + ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...) + if err != nil { + return nil, err + } + + initContainers = append(initContainers, ctr) + } for _, container := range podYAML.Spec.Containers { if !strings.Contains("infra", container.Name) { - // Contains all labels obtained from kube - labels := make(map[string]string) - var pulledImage *libimage.Image - buildFile, err := getBuildFile(container.Image, cwd) + pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, container, options) if err != nil { return nil, err } - existsLocally, err := ic.Libpod.LibimageRuntime().Exists(container.Image) - if err != nil { - return nil, err - } - if (len(buildFile) > 0 && !existsLocally) || (len(buildFile) > 0 && options.Build) { - buildOpts := new(buildahDefine.BuildOptions) - commonOpts := new(buildahDefine.CommonBuildOptions) - buildOpts.ConfigureNetwork = buildahDefine.NetworkDefault - buildOpts.Isolation = buildahDefine.IsolationChroot - buildOpts.CommonBuildOpts = commonOpts - buildOpts.Output = container.Image - if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil { - return nil, err - } - i, _, err := ic.Libpod.LibimageRuntime().LookupImage(container.Image, new(libimage.LookupImageOptions)) - if err != nil { - return nil, err - } - pulledImage = i - } else { - // NOTE: set the pull policy to "newer". This will cover cases - // where the "latest" tag requires a pull and will also - // transparently handle "localhost/" prefixed files which *may* - // refer to a locally built image OR an image running a - // registry on localhost. - pullPolicy := config.PullPolicyNewer - if len(container.ImagePullPolicy) > 0 { - // Make sure to lower the strings since K8s pull policy - // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905). - rawPolicy := string(container.ImagePullPolicy) - pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy)) - if err != nil { - return nil, err - } - } - pulledImages, err := pullImage(ic, writer, container.Image, options, pullPolicy) - if err != nil { - return nil, err - } - pulledImage = pulledImages[0] - } - - // Handle kube annotations - for k, v := range annotations { - switch k { - // Auto update annotation without container name will apply to - // all containers within the pod - case autoupdate.Label, autoupdate.AuthfileLabel: - labels[k] = v - // Auto update annotation with container name will apply only - // to the specified container - case fmt.Sprintf("%s/%s", autoupdate.Label, container.Name), - fmt.Sprintf("%s/%s", autoupdate.AuthfileLabel, container.Name): - prefixAndCtr := strings.Split(k, "/") - labels[prefixAndCtr[0]] = v - } - } specgenOpts := kube.CtrSpecGenOptions{ Container: container, @@ -394,7 +377,6 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY if err != nil { return nil, err } - rtSpec, spec, opts, err := generate.MakeContainer(ctx, ic.Libpod, specGen) if err != nil { return nil, err @@ -423,12 +405,96 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY for _, ctr := range containers { playKubePod.Containers = append(playKubePod.Containers, ctr.ID()) } + for _, initCtr := range initContainers { + playKubePod.InitContainers = append(playKubePod.InitContainers, initCtr.ID()) + } report.Pods = append(report.Pods, playKubePod) return &report, nil } +// getImageAndLabelInfo returns the image information and how the image should be pulled plus as well as labels to be used for the container in the pod. +// Moved this to a separate function so that it can be used for both init and regular containers when playing a kube yaml. +func (ic *ContainerEngine) getImageAndLabelInfo(ctx context.Context, cwd string, annotations map[string]string, writer io.Writer, container v1.Container, options entities.PlayKubeOptions) (*libimage.Image, map[string]string, error) { + // Contains all labels obtained from kube + labels := make(map[string]string) + var pulledImage *libimage.Image + buildFile, err := getBuildFile(container.Image, cwd) + if err != nil { + return nil, nil, err + } + existsLocally, err := ic.Libpod.LibimageRuntime().Exists(container.Image) + if err != nil { + return nil, nil, err + } + if (len(buildFile) > 0 && !existsLocally) || (len(buildFile) > 0 && options.Build) { + buildOpts := new(buildahDefine.BuildOptions) + commonOpts := new(buildahDefine.CommonBuildOptions) + buildOpts.ConfigureNetwork = buildahDefine.NetworkDefault + buildOpts.Isolation = buildahDefine.IsolationChroot + buildOpts.CommonBuildOpts = commonOpts + buildOpts.Output = container.Image + if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil { + return nil, nil, err + } + i, _, err := ic.Libpod.LibimageRuntime().LookupImage(container.Image, new(libimage.LookupImageOptions)) + if err != nil { + return nil, nil, err + } + pulledImage = i + } else { + // NOTE: set the pull policy to "newer". This will cover cases + // where the "latest" tag requires a pull and will also + // transparently handle "localhost/" prefixed files which *may* + // refer to a locally built image OR an image running a + // registry on localhost. + pullPolicy := config.PullPolicyNewer + if len(container.ImagePullPolicy) > 0 { + // Make sure to lower the strings since K8s pull policy + // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905). + rawPolicy := string(container.ImagePullPolicy) + pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy)) + if err != nil { + return nil, nil, err + } + } + // This ensures the image is the image store + pullOptions := &libimage.PullOptions{} + pullOptions.AuthFilePath = options.Authfile + pullOptions.CertDirPath = options.CertDir + pullOptions.SignaturePolicyPath = options.SignaturePolicy + pullOptions.Writer = writer + pullOptions.Username = options.Username + pullOptions.Password = options.Password + pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify + + pulledImages, err := ic.Libpod.LibimageRuntime().Pull(ctx, container.Image, pullPolicy, pullOptions) + if err != nil { + return nil, nil, err + } + pulledImage = pulledImages[0] + } + + // Handle kube annotations + for k, v := range annotations { + switch k { + // Auto update annotation without container name will apply to + // all containers within the pod + case autoupdate.Label, autoupdate.AuthfileLabel: + labels[k] = v + // Auto update annotation with container name will apply only + // to the specified container + case fmt.Sprintf("%s/%s", autoupdate.Label, container.Name), + fmt.Sprintf("%s/%s", autoupdate.AuthfileLabel, container.Name): + prefixAndCtr := strings.Split(k, "/") + labels[prefixAndCtr[0]] = v + } + } + + return pulledImage, labels, nil +} + // playKubePVC creates a podman volume from a kube persistent volume claim. func (ic *ContainerEngine) playKubePVC(ctx context.Context, pvcYAML *v1.PersistentVolumeClaim, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { var report entities.PlayKubeReport diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index a9289d6b3..89b556b14 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -135,10 +135,25 @@ func getDirs(usrName string) []Directory { Path: d, User: getNodeUsr(usrName), }, - DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(493)}, + DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)}, } dirs[i] = newDir } + + // Issue #11489: make sure that we can inject a custom registries.conf + // file on the system level to force a single search registry. + // The remote client does not yet support prompting for short-name + // resolution, so we enforce a single search registry (i.e., docker.io) + // as a workaround. + dirs = append(dirs, Directory{ + Node: Node{ + Group: getNodeGrp("root"), + Path: "/etc/containers/registries.conf.d", + User: getNodeUsr("root"), + }, + DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)}, + }) + return dirs } @@ -158,7 +173,7 @@ func getFiles(usrName string) []File { Contents: Resource{ Source: strToPtr("data:,%5BUnit%5D%0ADescription%3DA%20systemd%20user%20unit%20demo%0AAfter%3Dnetwork-online.target%0AWants%3Dnetwork-online.target%20podman.socket%0A%5BService%5D%0AExecStart%3D%2Fusr%2Fbin%2Fsleep%20infinity%0A"), }, - Mode: intToPtr(484), + Mode: intToPtr(0744), }, }) @@ -175,7 +190,7 @@ func getFiles(usrName string) []File { Contents: Resource{ Source: strToPtr("data:,%5Bcontainers%5D%0D%0Anetns%3D%22bridge%22%0D%0Arootless_networking%3D%22cni%22"), }, - Mode: intToPtr(484), + Mode: intToPtr(0744), }, }) // Add a file into linger @@ -185,7 +200,7 @@ func getFiles(usrName string) []File { Path: "/var/lib/systemd/linger/core", User: getNodeUsr(usrName), }, - FileEmbedded1: FileEmbedded1{Mode: intToPtr(420)}, + FileEmbedded1: FileEmbedded1{Mode: intToPtr(0644)}, }) // Set machine_enabled to true to indicate we're in a VM @@ -200,9 +215,30 @@ func getFiles(usrName string) []File { Contents: Resource{ Source: strToPtr("data:,%5Bengine%5D%0Amachine_enabled%3Dtrue%0A"), }, - Mode: intToPtr(420), + Mode: intToPtr(0644), + }, + }) + + // Issue #11489: make sure that we can inject a custom registries.conf + // file on the system level to force a single search registry. + // The remote client does not yet support prompting for short-name + // resolution, so we enforce a single search registry (i.e., docker.io) + // as a workaround. + files = append(files, File{ + Node: Node{ + Group: getNodeGrp("root"), + Path: "/etc/containers/registries.conf.d/999-podman-machine.conf", + User: getNodeUsr("root"), + }, + FileEmbedded1: FileEmbedded1{ + Append: nil, + Contents: Resource{ + Source: strToPtr("data:,unqualified-search-registries%3D%5B%22docker.io%22%5D"), + }, + Mode: intToPtr(0644), }, }) + return files } diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index 5188abc3a..c01d7a1f0 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -114,6 +114,9 @@ type CtrSpecGenOptions struct { Labels map[string]string // IsInfra bool + // InitContainerType sets what type the init container is + // Note: When playing a kube yaml, the inti container type will be set to "always" only + InitContainerType string } func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGenerator, error) { @@ -135,6 +138,8 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener Driver: opts.LogDriver, } + s.InitContainerType = opts.InitContainerType + setupSecurityContext(s, opts.Container) err := setupLivenessProbe(s, opts.Container, opts.RestartPolicy) if err != nil { diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 8996bf6a0..bf89a0708 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -174,6 +174,78 @@ var _ = Describe("Podman generate kube", func() { Expect(string(kube.Out.Contents())).To(ContainSubstring(`name: pod2`)) }) + It("podman generate kube on pod with init containers", func() { + session := podmanTest.Podman([]string{"create", "--pod", "new:toppod", "--init-ctr", "always", ALPINE, "echo", "hello"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"create", "--pod", "toppod", "--init-ctr", "always", ALPINE, "echo", "world"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"create", "--pod", "toppod", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"generate", "kube", "toppod"}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + pod := new(v1.Pod) + err := yaml.Unmarshal(kube.Out.Contents(), pod) + Expect(err).To(BeNil()) + Expect(pod.Spec.HostNetwork).To(Equal(false)) + + numContainers := len(pod.Spec.Containers) + len(pod.Spec.InitContainers) + Expect(numContainers).To(Equal(3)) + + // Init container should be in the generated kube yaml if created with "once" type and the pod has not been started + session = podmanTest.Podman([]string{"create", "--pod", "new:toppod-2", "--init-ctr", "once", ALPINE, "echo", "using once type"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"create", "--pod", "toppod-2", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube = podmanTest.Podman([]string{"generate", "kube", "toppod-2"}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + pod = new(v1.Pod) + err = yaml.Unmarshal(kube.Out.Contents(), pod) + Expect(err).To(BeNil()) + Expect(pod.Spec.HostNetwork).To(Equal(false)) + + numContainers = len(pod.Spec.Containers) + len(pod.Spec.InitContainers) + Expect(numContainers).To(Equal(2)) + + // Init container should not be in the generated kube yaml if created with "once" type and the pod has been started + session = podmanTest.Podman([]string{"create", "--pod", "new:toppod-3", "--init-ctr", "once", ALPINE, "echo", "using once type"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"create", "--pod", "toppod-3", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"pod", "start", "toppod-3"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube = podmanTest.Podman([]string{"generate", "kube", "toppod-3"}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + pod = new(v1.Pod) + err = yaml.Unmarshal(kube.Out.Contents(), pod) + Expect(err).To(BeNil()) + Expect(pod.Spec.HostNetwork).To(Equal(false)) + + numContainers = len(pod.Spec.Containers) + len(pod.Spec.InitContainers) + Expect(numContainers).To(Equal(1)) + }) + It("podman generate kube on pod with host network", func() { podSession := podmanTest.Podman([]string{"pod", "create", "--name", "testHostNetwork", "--network", "host"}) podSession.WaitWithDefaultTimeout() diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go index ea7a96428..2e5e07de9 100644 --- a/test/e2e/pause_test.go +++ b/test/e2e/pause_test.go @@ -79,6 +79,11 @@ var _ = Describe("Podman pause", func() { Expect(result).To(ExitWithError()) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) Expect(strings.ToLower(podmanTest.GetContainerStatus())).To(ContainSubstring(createdState)) + + // check we can read stats for a paused container + result = podmanTest.Podman([]string{"stats", "--no-stream", cid}) + result.WaitWithDefaultTimeout() + Expect(result).To(ExitWithError()) }) It("podman pause a running container by id", func() { diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index fa30f068c..15bd10616 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/containers/common/pkg/config" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/util" . "github.com/containers/podman/v3/test/utils" "github.com/containers/storage/pkg/stringid" @@ -263,6 +264,17 @@ spec: {{ end }} ip: {{ .IP }} {{ end }} + initContainers: +{{ with .InitCtrs }} + {{ range . }} + - command: + {{ range .Cmd }} + - {{.}} + {{ end }} + image: {{ .Image }} + name: {{ .Name }} + {{ end }} +{{ end }} containers: {{ with .Ctrs }} {{ range . }} @@ -665,6 +677,7 @@ type Pod struct { HostNetwork bool HostAliases []HostAlias Ctrs []*Ctr + InitCtrs []*Ctr Volumes []*Volume Labels map[string]string Annotations map[string]string @@ -686,6 +699,7 @@ func getPod(options ...podOption) *Pod { HostNetwork: false, HostAliases: nil, Ctrs: make([]*Ctr, 0), + InitCtrs: make([]*Ctr, 0), Volumes: make([]*Volume, 0), Labels: make(map[string]string), Annotations: make(map[string]string), @@ -728,6 +742,12 @@ func withCtr(c *Ctr) podOption { } } +func withPodInitCtr(ic *Ctr) podOption { + return func(pod *Pod) { + pod.InitCtrs = append(pod.InitCtrs, ic) + } +} + func withRestartPolicy(policy string) podOption { return func(pod *Pod) { pod.RestartPolicy = policy @@ -847,6 +867,7 @@ type Ctr struct { VolumeReadOnly bool Env []Env EnvFrom []EnvFrom + InitCtrType string } // getCtr takes a list of ctrOptions and returns a Ctr with sane defaults @@ -870,6 +891,7 @@ func getCtr(options ...ctrOption) *Ctr { VolumeReadOnly: false, Env: []Env{}, EnvFrom: []EnvFrom{}, + InitCtrType: "", } for _, option := range options { option(&c) @@ -885,6 +907,12 @@ func withName(name string) ctrOption { } } +func withInitCtr() ctrOption { + return func(c *Ctr) { + c.InitCtrType = define.AlwaysInitContainer + } +} + func withCmd(cmd []string) ctrOption { return func(c *Ctr) { c.Cmd = cmd @@ -1294,6 +1322,33 @@ var _ = Describe("Podman play kube", func() { Expect(inspect.OutputToString()).To(ContainSubstring(`[]`)) }) + // If you have an init container in the pod yaml, podman should create and run the init container with play kube + It("podman play kube test with init containers", func() { + pod := getPod(withPodInitCtr(getCtr(withImage(ALPINE), withCmd([]string{"echo", "hello"}), withInitCtr(), withName("init-test"))), withCtr(getCtr(withImage(ALPINE), withCmd([]string{"top"})))) + err := generateKubeYaml("pod", pod, kubeYaml) + Expect(err).To(BeNil()) + + kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + // Expect the number of containers created to be 3, one init, infra, and regular container + numOfCtrs := podmanTest.NumberOfContainers() + Expect(numOfCtrs).To(Equal(3)) + + // Init container should have exited after running + inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-init-test"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).Should(Exit(0)) + Expect(inspect.OutputToString()).To(ContainSubstring("exited")) + + // Regular container should be in running state + inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).Should(Exit(0)) + Expect(inspect.OutputToString()).To(ContainSubstring("running")) + }) + // If you supply only args for a Container, the default Entrypoint defined in the Docker image is run with the args that you supplied. It("podman play kube test correct command with only set args in yaml file", func() { pod := getPod(withCtr(getCtr(withImage(registry), withCmd(nil), withArg([]string{"echo", "hello"})))) diff --git a/vendor/github.com/containers/psgo/go.mod b/vendor/github.com/containers/psgo/go.mod index 5f3341aa9..699874cf7 100644 --- a/vendor/github.com/containers/psgo/go.mod +++ b/vendor/github.com/containers/psgo/go.mod @@ -1,11 +1,10 @@ module github.com/containers/psgo -go 1.12 +go 1.13 require ( - github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4 - github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9 - github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe - github.com/stretchr/testify v1.5.1 - golang.org/x/sys v0.0.0-20190425145619-16072639606e + github.com/opencontainers/runc v1.0.2 + github.com/sirupsen/logrus v1.8.1 + github.com/stretchr/testify v1.7.0 + golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 ) diff --git a/vendor/github.com/containers/psgo/go.sum b/vendor/github.com/containers/psgo/go.sum index 781b26f2b..0ba04956f 100644 --- a/vendor/github.com/containers/psgo/go.sum +++ b/vendor/github.com/containers/psgo/go.sum @@ -1,27 +1,78 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4 h1:y5PMn9UW9cD5xvjoMs9pJ77zs5DgGkiDv0BI/Qew51o= -github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9 h1:dIsTcVF0w9viTLHXUEkDI7cXITMe+M/MRRM2MwisVow= -github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe h1:PBQLA9wc7FrXiUBnlfs/diNlg3ZdrP21tzcgL3OlVhU= -github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190425145619-16072639606e h1:4ktJgTV34+N3qOZUc5fAaG3Pb11qzMm3PkAoTAgUZ2I= -golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= +golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/vendor/github.com/containers/psgo/internal/proc/ns.go b/vendor/github.com/containers/psgo/internal/proc/ns.go index 53e5ebda0..4778048f2 100644 --- a/vendor/github.com/containers/psgo/internal/proc/ns.go +++ b/vendor/github.com/containers/psgo/internal/proc/ns.go @@ -19,8 +19,6 @@ import ( "fmt" "io" "os" - - "github.com/pkg/errors" ) type IDMap struct { @@ -51,7 +49,7 @@ func ParseUserNamespace(pid string) (string, error) { func ReadMappings(path string) ([]IDMap, error) { file, err := os.Open(path) if err != nil { - return nil, errors.Wrapf(err, "cannot open %s", path) + return nil, err } defer file.Close() @@ -64,7 +62,7 @@ func ReadMappings(path string) ([]IDMap, error) { if err == io.EOF { return mappings, nil } - return nil, errors.Wrapf(err, "cannot read line from %s", path) + return nil, fmt.Errorf("cannot read line from %s: %w", path, err) } if line == nil { return mappings, nil @@ -72,7 +70,7 @@ func ReadMappings(path string) ([]IDMap, error) { containerID, hostID, size := 0, 0, 0 if _, err := fmt.Sscanf(string(line), "%d %d %d", &containerID, &hostID, &size); err != nil { - return nil, errors.Wrapf(err, "cannot parse %s", string(line)) + return nil, fmt.Errorf("cannot parse %s: %w", string(line), err) } mappings = append(mappings, IDMap{ContainerID: containerID, HostID: hostID, Size: size}) } diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go index df31139f8..2753915fd 100644 --- a/vendor/github.com/containers/psgo/internal/proc/status.go +++ b/vendor/github.com/containers/psgo/internal/proc/status.go @@ -20,8 +20,6 @@ import ( "os" "os/exec" "strings" - - "github.com/pkg/errors" ) // Status is a direct translation of a `/proc/[pid]/status`, which provides much @@ -251,12 +249,12 @@ func parseStatus(pid string, lines []string) (*Status, error) { s.TracerPid = fields[1] case "Uid:": if len(fields) != 5 { - return nil, errors.Wrap(errUnexpectedInput, line) + return nil, fmt.Errorf(line+": %w", errUnexpectedInput) } s.Uids = []string{fields[1], fields[2], fields[3], fields[4]} case "Gid:": if len(fields) != 5 { - return nil, errors.Wrap(errUnexpectedInput, line) + return nil, fmt.Errorf(line+": %w", errUnexpectedInput) } s.Gids = []string{fields[1], fields[2], fields[3], fields[4]} case "FDSize:": diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go index a581921d5..8fd49e416 100644 --- a/vendor/github.com/containers/psgo/internal/process/process.go +++ b/vendor/github.com/containers/psgo/internal/process/process.go @@ -15,6 +15,8 @@ package process import ( + "errors" + "fmt" "os" "strconv" "time" @@ -22,7 +24,6 @@ import ( "github.com/containers/psgo/internal/host" "github.com/containers/psgo/internal/proc" "github.com/opencontainers/runc/libcontainer/user" - "github.com/pkg/errors" ) // Process includes process-related from the /proc FS. @@ -50,7 +51,7 @@ type Process struct { func LookupGID(gid string) (string, error) { gidNum, err := strconv.Atoi(gid) if err != nil { - return "", errors.Wrap(err, "error parsing group ID") + return "", fmt.Errorf("error parsing group ID: %w", err) } g, err := user.LookupGid(gidNum) if err != nil { @@ -64,7 +65,7 @@ func LookupGID(gid string) (string, error) { func LookupUID(uid string) (string, error) { uidNum, err := strconv.Atoi(uid) if err != nil { - return "", errors.Wrap(err, "error parsing user ID") + return "", fmt.Errorf("error parsing user ID: %w", err) } u, err := user.LookupUid(uidNum) if err != nil { @@ -107,7 +108,7 @@ func FromPIDs(pids []string, joinUserNS bool) ([]*Process, error) { for _, pid := range pids { p, err := New(pid, joinUserNS) if err != nil { - if os.IsNotExist(errors.Cause(err)) { + if errors.Is(err, os.ErrNotExist) { // proc parsing is racy // Let's ignore "does not exist" errors continue diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go index 7c74fd716..b0569fa1c 100644 --- a/vendor/github.com/containers/psgo/psgo.go +++ b/vendor/github.com/containers/psgo/psgo.go @@ -27,6 +27,7 @@ package psgo import ( + "errors" "fmt" "io/ioutil" "os" @@ -40,7 +41,6 @@ import ( "github.com/containers/psgo/internal/dev" "github.com/containers/psgo/internal/proc" "github.com/containers/psgo/internal/process" - "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -109,7 +109,7 @@ func findID(idStr string, mapping []IDMap, lookupFunc func(uid string) (string, id, err := strconv.ParseInt(idStr, 10, 0) if err != nil { - return "", errors.Wrapf(err, "cannot parse %s", idStr) + return "", fmt.Errorf("cannot parse ID: %w", err) } for _, m := range mapping { if int(id) >= m.ContainerID && int(id) < m.ContainerID+m.Size { @@ -122,7 +122,7 @@ func findID(idStr string, mapping []IDMap, lookupFunc func(uid string) (string, // User not found, read the overflow overflow, err := ioutil.ReadFile(overflowFile) if err != nil { - return "", errors.Wrapf(err, "cannot read %s", overflowFile) + return "", err } return string(overflow), nil } @@ -147,7 +147,7 @@ func translateDescriptors(descriptors []string) ([]aixFormatDescriptor, error) { } } if !found { - return nil, errors.Wrapf(ErrUnknownDescriptor, "'%s'", d) + return nil, fmt.Errorf("'%s': %w", d, ErrUnknownDescriptor) } } @@ -412,13 +412,13 @@ func JoinNamespaceAndProcessInfoWithOptions(pid string, descriptors []string, op // extract user namespaces prior to joining the mount namespace currentUserNs, err := proc.ParseUserNamespace("self") if err != nil { - dataErr = errors.Wrapf(err, "error determining user namespace") + dataErr = fmt.Errorf("error determining user namespace: %w", err) return } pidUserNs, err := proc.ParseUserNamespace(pid) if err != nil { - dataErr = errors.Wrapf(err, "error determining user namespace of PID %s", pid) + dataErr = fmt.Errorf("error determining user namespace of PID %s: %w", pid, err) } // join the mount namespace of pid @@ -478,11 +478,11 @@ func JoinNamespaceAndProcessInfoByPidsWithOptions(pids []string, descriptors []s for _, pid := range pids { ns, err := proc.ParsePIDNamespace(pid) if err != nil { - if os.IsNotExist(errors.Cause(err)) { + if errors.Is(err, os.ErrNotExist) { // catch race conditions continue } - return nil, errors.Wrapf(err, "error extracting PID namespace") + return nil, fmt.Errorf("error extracting PID namespace: %w", err) } if _, exists := nsMap[ns]; !exists { nsMap[ns] = true @@ -493,7 +493,7 @@ func JoinNamespaceAndProcessInfoByPidsWithOptions(pids []string, descriptors []s data := [][]string{} for i, pid := range pidList { pidData, err := JoinNamespaceAndProcessInfoWithOptions(pid, descriptors, options) - if os.IsNotExist(errors.Cause(err)) { + if errors.Is(err, os.ErrNotExist) { // catch race conditions continue } diff --git a/vendor/github.com/containers/psgo/vendor.conf b/vendor/github.com/containers/psgo/vendor.conf deleted file mode 100644 index 1fba46ec1..000000000 --- a/vendor/github.com/containers/psgo/vendor.conf +++ /dev/null @@ -1,8 +0,0 @@ -github.com/davecgh/go-spew master -github.com/opencontainers/runc master -github.com/pkg/errors master -github.com/pmezard/go-difflib master -github.com/sirupsen/logrus master -github.com/stretchr/testify master -golang.org/x/crypto master -golang.org/x/sys master diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go index 9ffd77afa..0eedcaa78 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go @@ -38,6 +38,8 @@ var ( // CategoryRange allows the upper bound on the category range to be adjusted CategoryRange = DefaultCategoryRange + + privContainerMountLabel string ) // Context is a representation of the SELinux label broken into 4 parts @@ -280,5 +282,7 @@ func GetDefaultContextWithLevel(user, level, scon string) (string, error) { // PrivContainerMountLabel returns mount label for privileged containers func PrivContainerMountLabel() string { + // Make sure label is initialized. + _ = label("") return privContainerMountLabel } diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go index a804473e4..295b2bc4e 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go @@ -12,7 +12,6 @@ import ( "os" "path" "path/filepath" - "regexp" "strconv" "strings" "sync" @@ -34,8 +33,6 @@ const ( xattrNameSelinux = "security.selinux" ) -var policyRoot = filepath.Join(selinuxDir, readConfig(selinuxTypeTag)) - type selinuxState struct { enabledSet bool enabled bool @@ -70,7 +67,6 @@ const ( ) var ( - assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) readOnlyFileLabel string state = selinuxState{ mcsList: make(map[string]bool), @@ -79,8 +75,24 @@ var ( // for attrPath() attrPathOnce sync.Once haveThreadSelf bool + + // for policyRoot() + policyRootOnce sync.Once + policyRootVal string + + // for label() + loadLabelsOnce sync.Once + labels map[string]string ) +func policyRoot() string { + policyRootOnce.Do(func() { + policyRootVal = filepath.Join(selinuxDir, readConfig(selinuxTypeTag)) + }) + + return policyRootVal +} + func (s *selinuxState) setEnable(enabled bool) bool { s.Lock() defer s.Unlock() @@ -222,7 +234,7 @@ func readConfig(target string) string { scanner := bufio.NewScanner(in) for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) + line := bytes.TrimSpace(scanner.Bytes()) if len(line) == 0 { // Skip blank lines continue @@ -231,11 +243,12 @@ func readConfig(target string) string { // Skip comments continue } - if groups := assignRegex.FindStringSubmatch(line); groups != nil { - key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) - if key == target { - return strings.Trim(val, "\"") - } + fields := bytes.SplitN(line, []byte{'='}, 2) + if len(fields) != 2 { + continue + } + if bytes.Equal(fields[0], []byte(target)) { + return string(bytes.Trim(fields[1], `"`)) } } return "" @@ -274,12 +287,15 @@ func readCon(fpath string) (string, error) { if err := isProcHandle(in); err != nil { return "", err } + return readConFd(in) +} - var retval string - if _, err := fmt.Fscanf(in, "%s", &retval); err != nil { +func readConFd(in *os.File) (string, error) { + data, err := ioutil.ReadAll(in) + if err != nil { return "", err } - return strings.Trim(retval, "\x00"), nil + return string(bytes.TrimSuffix(data, []byte{0})), nil } // classIndex returns the int index for an object class in the loaded policy, @@ -389,7 +405,7 @@ func writeCon(fpath, val string) error { _, err = out.Write(nil) } if err != nil { - return &os.PathError{Op: "write", Path: fpath, Err: err} + return err } return nil } @@ -664,11 +680,7 @@ func readWriteCon(fpath string, val string) (string, error) { return "", err } - var retval string - if _, err := fmt.Fscanf(f, "%s", &retval); err != nil { - return "", err - } - return strings.Trim(retval, "\x00"), nil + return readConFd(f) } // setExecLabel sets the SELinux label that the kernel will use for any programs @@ -723,10 +735,10 @@ func keyLabel() (string, error) { // get returns the Context as a string func (c Context) get() string { - if c["level"] != "" { - return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"]) + if level := c["level"]; level != "" { + return c["user"] + ":" + c["role"] + ":" + c["type"] + ":" + level } - return fmt.Sprintf("%s:%s:%s", c["user"], c["role"], c["type"]) + return c["user"] + ":" + c["role"] + ":" + c["type"] } // newContext creates a new Context struct from the specified label @@ -891,24 +903,21 @@ func openContextFile() (*os.File, error) { if f, err := os.Open(contextFile); err == nil { return f, nil } - lxcPath := filepath.Join(policyRoot, "/contexts/lxc_contexts") - return os.Open(lxcPath) + return os.Open(filepath.Join(policyRoot(), "/contexts/lxc_contexts")) } -var labels, privContainerMountLabel = loadLabels() - -func loadLabels() (map[string]string, string) { - labels := make(map[string]string) +func loadLabels() { + labels = make(map[string]string) in, err := openContextFile() if err != nil { - return labels, "" + return } defer in.Close() scanner := bufio.NewScanner(in) for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) + line := bytes.TrimSpace(scanner.Bytes()) if len(line) == 0 { // Skip blank lines continue @@ -917,38 +926,47 @@ func loadLabels() (map[string]string, string) { // Skip comments continue } - if groups := assignRegex.FindStringSubmatch(line); groups != nil { - key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) - labels[key] = strings.Trim(val, "\"") + fields := bytes.SplitN(line, []byte{'='}, 2) + if len(fields) != 2 { + continue } + key, val := bytes.TrimSpace(fields[0]), bytes.TrimSpace(fields[1]) + labels[string(key)] = string(bytes.Trim(val, `"`)) } con, _ := NewContext(labels["file"]) con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1) - reserveLabel(con.get()) - return labels, con.get() + privContainerMountLabel = con.get() + reserveLabel(privContainerMountLabel) +} + +func label(key string) string { + loadLabelsOnce.Do(func() { + loadLabels() + }) + return labels[key] } // kvmContainerLabels returns the default processLabel and mountLabel to be used // for kvm containers by the calling process. func kvmContainerLabels() (string, string) { - processLabel := labels["kvm_process"] + processLabel := label("kvm_process") if processLabel == "" { - processLabel = labels["process"] + processLabel = label("process") } - return addMcs(processLabel, labels["file"]) + return addMcs(processLabel, label("file")) } // initContainerLabels returns the default processLabel and file labels to be // used for containers running an init system like systemd by the calling process. func initContainerLabels() (string, string) { - processLabel := labels["init_process"] + processLabel := label("init_process") if processLabel == "" { - processLabel = labels["process"] + processLabel = label("process") } - return addMcs(processLabel, labels["file"]) + return addMcs(processLabel, label("file")) } // containerLabels returns an allocated processLabel and fileLabel to be used for @@ -958,9 +976,9 @@ func containerLabels() (processLabel string, fileLabel string) { return "", "" } - processLabel = labels["process"] - fileLabel = labels["file"] - readOnlyFileLabel = labels["ro_file"] + processLabel = label("process") + fileLabel = label("file") + readOnlyFileLabel = label("ro_file") if processLabel == "" || fileLabel == "" { return "", fileLabel @@ -1180,15 +1198,14 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) { } func getDefaultContextWithLevel(user, level, scon string) (string, error) { - userPath := filepath.Join(policyRoot, selinuxUsersDir, user) - defaultPath := filepath.Join(policyRoot, defaultContexts) - + userPath := filepath.Join(policyRoot(), selinuxUsersDir, user) fu, err := os.Open(userPath) if err != nil { return "", err } defer fu.Close() + defaultPath := filepath.Join(policyRoot(), defaultContexts) fd, err := os.Open(defaultPath) if err != nil { return "", err diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go index b7218a0b6..42657759c 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go @@ -2,8 +2,6 @@ package selinux -const privContainerMountLabel = "" - func setDisabled() { } @@ -152,3 +150,7 @@ func disableSecOpt() []string { func getDefaultContextWithLevel(user, level, scon string) (string, error) { return "", nil } + +func label(_ string) string { + return "" +} diff --git a/vendor/modules.txt b/vendor/modules.txt index b314944d4..0edf27275 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -191,7 +191,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7 github.com/containers/ocicrypt/spec github.com/containers/ocicrypt/utils github.com/containers/ocicrypt/utils/keyprovider -# github.com/containers/psgo v1.5.2 +# github.com/containers/psgo v1.6.0 github.com/containers/psgo github.com/containers/psgo/internal/capabilities github.com/containers/psgo/internal/cgroups @@ -524,7 +524,7 @@ github.com/opencontainers/runtime-tools/generate github.com/opencontainers/runtime-tools/generate/seccomp github.com/opencontainers/runtime-tools/specerror github.com/opencontainers/runtime-tools/validate -# github.com/opencontainers/selinux v1.8.4 +# github.com/opencontainers/selinux v1.8.5 github.com/opencontainers/selinux/go-selinux github.com/opencontainers/selinux/go-selinux/label github.com/opencontainers/selinux/pkg/pwalk |