mirror of https://github.com/containers/podman.git
Merge branch 'containers:main' into naveen/feat/set-perms-actions
This commit is contained in:
commit
6375a85055
|
|
@ -721,14 +721,12 @@ upgrade_test_task:
|
||||||
depends_on:
|
depends_on:
|
||||||
- local_system_test
|
- local_system_test
|
||||||
matrix:
|
matrix:
|
||||||
- env:
|
|
||||||
PODMAN_UPGRADE_FROM: v1.9.0
|
|
||||||
- env:
|
|
||||||
PODMAN_UPGRADE_FROM: v2.0.6
|
|
||||||
- env:
|
- env:
|
||||||
PODMAN_UPGRADE_FROM: v2.1.1
|
PODMAN_UPGRADE_FROM: v2.1.1
|
||||||
- env:
|
- env:
|
||||||
PODMAN_UPGRADE_FROM: v3.1.2
|
PODMAN_UPGRADE_FROM: v3.1.2
|
||||||
|
- env:
|
||||||
|
PODMAN_UPGRADE_FROM: v3.4.4
|
||||||
gce_instance: *standardvm
|
gce_instance: *standardvm
|
||||||
env:
|
env:
|
||||||
TEST_FLAVOR: upgrade_test
|
TEST_FLAVOR: upgrade_test
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
_ "github.com/containers/podman/v4/cmd/podman/completion"
|
_ "github.com/containers/podman/v4/cmd/podman/completion"
|
||||||
_ "github.com/containers/podman/v4/cmd/podman/containers"
|
_ "github.com/containers/podman/v4/cmd/podman/containers"
|
||||||
|
|
@ -20,6 +19,7 @@ import (
|
||||||
_ "github.com/containers/podman/v4/cmd/podman/system"
|
_ "github.com/containers/podman/v4/cmd/podman/system"
|
||||||
_ "github.com/containers/podman/v4/cmd/podman/system/connection"
|
_ "github.com/containers/podman/v4/cmd/podman/system/connection"
|
||||||
_ "github.com/containers/podman/v4/cmd/podman/volumes"
|
_ "github.com/containers/podman/v4/cmd/podman/volumes"
|
||||||
|
"github.com/containers/podman/v4/pkg/domain/entities"
|
||||||
"github.com/containers/podman/v4/pkg/rootless"
|
"github.com/containers/podman/v4/pkg/rootless"
|
||||||
"github.com/containers/podman/v4/pkg/terminal"
|
"github.com/containers/podman/v4/pkg/terminal"
|
||||||
"github.com/containers/storage/pkg/reexec"
|
"github.com/containers/storage/pkg/reexec"
|
||||||
|
|
@ -44,7 +44,29 @@ func parseCommands() *cobra.Command {
|
||||||
cfg := registry.PodmanConfig()
|
cfg := registry.PodmanConfig()
|
||||||
for _, c := range registry.Commands {
|
for _, c := range registry.Commands {
|
||||||
if supported, found := c.Command.Annotations[registry.EngineMode]; found {
|
if supported, found := c.Command.Annotations[registry.EngineMode]; found {
|
||||||
if !strings.Contains(cfg.EngineMode.String(), supported) {
|
if cfg.EngineMode.String() != supported {
|
||||||
|
var client string
|
||||||
|
switch cfg.EngineMode {
|
||||||
|
case entities.TunnelMode:
|
||||||
|
client = "remote"
|
||||||
|
case entities.ABIMode:
|
||||||
|
client = "local"
|
||||||
|
}
|
||||||
|
|
||||||
|
// add error message to the command so the user knows that this command is not supported with local/remote
|
||||||
|
c.Command.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
|
return fmt.Errorf("cannot use command %q with the %s podman client", cmd.CommandPath(), client)
|
||||||
|
}
|
||||||
|
// turn of flag parsing to make we do not get flag errors
|
||||||
|
c.Command.DisableFlagParsing = true
|
||||||
|
|
||||||
|
// mark command as hidden so it is not shown in --help
|
||||||
|
c.Command.Hidden = true
|
||||||
|
|
||||||
|
// overwrite persistent pre/post function to skip setup
|
||||||
|
c.Command.PersistentPostRunE = noop
|
||||||
|
c.Command.PersistentPreRunE = noop
|
||||||
|
addCommand(c)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,22 +87,9 @@ func parseCommands() *cobra.Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
addCommand(c)
|
||||||
parent := rootCmd
|
|
||||||
if c.Parent != nil {
|
|
||||||
parent = c.Parent
|
|
||||||
}
|
|
||||||
parent.AddCommand(c.Command)
|
|
||||||
|
|
||||||
c.Command.SetFlagErrorFunc(flagErrorFuncfunc)
|
|
||||||
|
|
||||||
// - templates need to be set here, as PersistentPreRunE() is
|
|
||||||
// not called when --help is used.
|
|
||||||
// - rootCmd uses cobra default template not ours
|
|
||||||
c.Command.SetHelpTemplate(helpTemplate)
|
|
||||||
c.Command.SetUsageTemplate(usageTemplate)
|
|
||||||
c.Command.DisableFlagsInUseLine = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := terminal.SetConsole(); err != nil {
|
if err := terminal.SetConsole(); err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
@ -94,3 +103,24 @@ func flagErrorFuncfunc(c *cobra.Command, e error) error {
|
||||||
e = fmt.Errorf("%w\nSee '%s --help'", e, c.CommandPath())
|
e = fmt.Errorf("%w\nSee '%s --help'", e, c.CommandPath())
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addCommand(c registry.CliCommand) {
|
||||||
|
parent := rootCmd
|
||||||
|
if c.Parent != nil {
|
||||||
|
parent = c.Parent
|
||||||
|
}
|
||||||
|
parent.AddCommand(c.Command)
|
||||||
|
|
||||||
|
c.Command.SetFlagErrorFunc(flagErrorFuncfunc)
|
||||||
|
|
||||||
|
// - templates need to be set here, as PersistentPreRunE() is
|
||||||
|
// not called when --help is used.
|
||||||
|
// - rootCmd uses cobra default template not ours
|
||||||
|
c.Command.SetHelpTemplate(helpTemplate)
|
||||||
|
c.Command.SetUsageTemplate(usageTemplate)
|
||||||
|
c.Command.DisableFlagsInUseLine = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func noop(cmd *cobra.Command, args []string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/containers/common/pkg/secrets"
|
"github.com/containers/common/pkg/secrets"
|
||||||
"github.com/containers/image/v5/manifest"
|
"github.com/containers/image/v5/manifest"
|
||||||
"github.com/containers/podman/v4/pkg/namespaces"
|
"github.com/containers/podman/v4/pkg/namespaces"
|
||||||
|
"github.com/containers/podman/v4/pkg/specgen"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
@ -405,13 +406,19 @@ type ContainerMiscConfig struct {
|
||||||
InitContainerType string `json:"init_container_type,omitempty"`
|
InitContainerType string `json:"init_container_type,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InfraInherit contains the compatible options inheritable from the infra container
|
||||||
type InfraInherit struct {
|
type InfraInherit struct {
|
||||||
InfraSecurity ContainerSecurityConfig
|
ApparmorProfile string `json:"apparmor_profile,omitempty"`
|
||||||
InfraLabels []string `json:"labelopts,omitempty"`
|
CapAdd []string `json:"cap_add,omitempty"`
|
||||||
InfraVolumes []*ContainerNamedVolume `json:"namedVolumes,omitempty"`
|
CapDrop []string `json:"cap_drop,omitempty"`
|
||||||
InfraOverlay []*ContainerOverlayVolume `json:"overlayVolumes,omitempty"`
|
HostDeviceList []spec.LinuxDevice `json:"host_device_list,omitempty"`
|
||||||
InfraImageVolumes []*ContainerImageVolume `json:"ctrImageVolumes,omitempty"`
|
ImageVolumes []*specgen.ImageVolume `json:"image_volumes,omitempty"`
|
||||||
InfraUserVolumes []string `json:"userVolumes,omitempty"`
|
InfraResources *spec.LinuxResources `json:"resource_limits,omitempty"`
|
||||||
InfraResources *spec.LinuxResources `json:"resources,omitempty"`
|
Mounts []spec.Mount `json:"mounts,omitempty"`
|
||||||
InfraDevices []spec.LinuxDevice `json:"device_host_src,omitempty"`
|
NoNewPrivileges bool `json:"no_new_privileges,omitempty"`
|
||||||
|
OverlayVolumes []*specgen.OverlayVolume `json:"overlay_volumes,omitempty"`
|
||||||
|
SeccompPolicy string `json:"seccomp_policy,omitempty"`
|
||||||
|
SeccompProfilePath string `json:"seccomp_profile_path,omitempty"`
|
||||||
|
SelinuxOpts []string `json:"selinux_opts,omitempty"`
|
||||||
|
Volumes []*specgen.NamedVolume `json:"volumes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,8 +103,8 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namedVolumes, mounts := c.sortUserVolumes(ctrSpec)
|
namedVolumes, mounts := c.SortUserVolumes(ctrSpec)
|
||||||
inspectMounts, err := c.GetInspectMounts(namedVolumes, c.config.ImageVolumes, mounts)
|
inspectMounts, err := c.GetMounts(namedVolumes, c.config.ImageVolumes, mounts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +222,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
|
||||||
// Get inspect-formatted mounts list.
|
// Get inspect-formatted mounts list.
|
||||||
// Only includes user-specified mounts. Only includes bind mounts and named
|
// Only includes user-specified mounts. Only includes bind mounts and named
|
||||||
// volumes, not tmpfs volumes.
|
// volumes, not tmpfs volumes.
|
||||||
func (c *Container) GetInspectMounts(namedVolumes []*ContainerNamedVolume, imageVolumes []*ContainerImageVolume, mounts []spec.Mount) ([]define.InspectMount, error) {
|
func (c *Container) GetMounts(namedVolumes []*ContainerNamedVolume, imageVolumes []*ContainerImageVolume, mounts []spec.Mount) ([]define.InspectMount, error) {
|
||||||
inspectMounts := []define.InspectMount{}
|
inspectMounts := []define.InspectMount{}
|
||||||
|
|
||||||
// No mounts, return early
|
// No mounts, return early
|
||||||
|
|
|
||||||
|
|
@ -2235,9 +2235,9 @@ func (c *Container) prepareCheckpointExport() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sortUserVolumes sorts the volumes specified for a container
|
// SortUserVolumes sorts the volumes specified for a container
|
||||||
// between named and normal volumes
|
// between named and normal volumes
|
||||||
func (c *Container) sortUserVolumes(ctrSpec *spec.Spec) ([]*ContainerNamedVolume, []spec.Mount) {
|
func (c *Container) SortUserVolumes(ctrSpec *spec.Spec) ([]*ContainerNamedVolume, []spec.Mount) {
|
||||||
namedUserVolumes := []*ContainerNamedVolume{}
|
namedUserVolumes := []*ContainerNamedVolume{}
|
||||||
userMounts := []spec.Mount{}
|
userMounts := []spec.Mount{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -773,7 +773,7 @@ func libpodEnvVarsToKubeEnvVars(envs []string, imageEnvs []string) ([]v1.EnvVar,
|
||||||
|
|
||||||
// libpodMountsToKubeVolumeMounts converts the containers mounts to a struct kube understands
|
// libpodMountsToKubeVolumeMounts converts the containers mounts to a struct kube understands
|
||||||
func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, map[string]string, error) {
|
func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, map[string]string, error) {
|
||||||
namedVolumes, mounts := c.sortUserVolumes(c.config.Spec)
|
namedVolumes, mounts := c.SortUserVolumes(c.config.Spec)
|
||||||
vms := make([]v1.VolumeMount, 0, len(mounts))
|
vms := make([]v1.VolumeMount, 0, len(mounts))
|
||||||
vos := make([]v1.Volume, 0, len(mounts))
|
vos := make([]v1.Volume, 0, len(mounts))
|
||||||
annotations := make(map[string]string)
|
annotations := make(map[string]string)
|
||||||
|
|
|
||||||
|
|
@ -602,8 +602,8 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
|
||||||
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
|
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
|
||||||
infraConfig.PidNS = p.PidMode()
|
infraConfig.PidNS = p.PidMode()
|
||||||
infraConfig.UserNS = p.UserNSMode()
|
infraConfig.UserNS = p.UserNSMode()
|
||||||
namedVolumes, mounts := infra.sortUserVolumes(infra.config.Spec)
|
namedVolumes, mounts := infra.SortUserVolumes(infra.config.Spec)
|
||||||
inspectMounts, err = infra.GetInspectMounts(namedVolumes, infra.config.ImageVolumes, mounts)
|
inspectMounts, err = infra.GetMounts(namedVolumes, infra.config.ImageVolumes, mounts)
|
||||||
infraSecurity = infra.GetSecurityOptions()
|
infraSecurity = infra.GetSecurityOptions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -367,20 +367,20 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if Containerfile is in the context directory, if so truncate the contextdirectory off path
|
// Check if Containerfile is in the context directory, if so truncate the context directory off path
|
||||||
// Do NOT add to tarfile
|
// Do NOT add to tarfile
|
||||||
if strings.HasPrefix(containerfile, contextDir+string(filepath.Separator)) {
|
if strings.HasPrefix(containerfile, contextDir+string(filepath.Separator)) {
|
||||||
containerfile = strings.TrimPrefix(containerfile, contextDir+string(filepath.Separator))
|
containerfile = strings.TrimPrefix(containerfile, contextDir+string(filepath.Separator))
|
||||||
dontexcludes = append(dontexcludes, "!"+containerfile)
|
dontexcludes = append(dontexcludes, "!"+containerfile)
|
||||||
} else {
|
} else {
|
||||||
// If Containerfile does not exists assume it is in context directory, do Not add to tarfile
|
// If Containerfile does not exist, assume it is in context directory and do Not add to tarfile
|
||||||
if _, err := os.Lstat(containerfile); err != nil {
|
if _, err := os.Lstat(containerfile); err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
containerfile = c
|
containerfile = c
|
||||||
} else {
|
} else {
|
||||||
// If Containerfile does exists but is not in context directory add it to the tarfile
|
// If Containerfile does exist and not in the context directory, add it to the tarfile
|
||||||
tarContent = append(tarContent, containerfile)
|
tarContent = append(tarContent, containerfile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -586,6 +586,9 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) {
|
||||||
return errors.Wrapf(err, "error checking if %q is excluded", name)
|
return errors.Wrapf(err, "error checking if %q is excluded", name)
|
||||||
}
|
}
|
||||||
if excluded {
|
if excluded {
|
||||||
|
// Note: filepath.SkipDir is not possible to use given .dockerignore semantics.
|
||||||
|
// An exception to exclusions may include an excluded directory, therefore we
|
||||||
|
// are required to visit all files. :(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1491,7 +1491,7 @@ func (ic *ContainerEngine) ContainerRename(ctx context.Context, nameOrID string,
|
||||||
func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts entities.ContainerCloneOptions) (*entities.ContainerCreateReport, error) {
|
func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts entities.ContainerCloneOptions) (*entities.ContainerCreateReport, error) {
|
||||||
spec := specgen.NewSpecGenerator(ctrCloneOpts.Image, ctrCloneOpts.CreateOpts.RootFS)
|
spec := specgen.NewSpecGenerator(ctrCloneOpts.Image, ctrCloneOpts.CreateOpts.RootFS)
|
||||||
var c *libpod.Container
|
var c *libpod.Container
|
||||||
c, err := generate.ConfigToSpec(ic.Libpod, spec, ctrCloneOpts.ID)
|
c, _, err := generate.ConfigToSpec(ic.Libpod, spec, ctrCloneOpts.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,16 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
||||||
if v.Type == kube.KubeVolumeTypeConfigMap && !v.Optional {
|
if v.Type == kube.KubeVolumeTypeConfigMap && !v.Optional {
|
||||||
vol, err := ic.Libpod.NewVolume(ctx, libpod.WithVolumeName(v.Source))
|
vol, err := ic.Libpod.NewVolume(ctx, libpod.WithVolumeName(v.Source))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "cannot create a local volume for volume from configmap %q", v.Source)
|
if errors.Is(err, define.ErrVolumeExists) {
|
||||||
|
// Volume for this configmap already exists do not
|
||||||
|
// error out instead reuse the current volume.
|
||||||
|
vol, err = ic.Libpod.GetVolume(v.Source)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "cannot re-use local volume for volume from configmap %q", v.Source)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, errors.Wrapf(err, "cannot create a local volume for volume from configmap %q", v.Source)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mountPoint, err := vol.MountPoint()
|
mountPoint, err := vol.MountPoint()
|
||||||
if err != nil || mountPoint == "" {
|
if err != nil || mountPoint == "" {
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,6 @@ func (s *SpecGenerator) Validate() error {
|
||||||
//
|
//
|
||||||
// ContainerSecurityConfig
|
// ContainerSecurityConfig
|
||||||
//
|
//
|
||||||
// capadd and privileged are exclusive
|
|
||||||
if len(s.CapAdd) > 0 && s.Privileged {
|
|
||||||
return exclusiveOptions("CapAdd", "privileged")
|
|
||||||
}
|
|
||||||
// userns and idmappings conflict
|
// userns and idmappings conflict
|
||||||
if s.UserNS.IsPrivate() && s.IDMappings == nil {
|
if s.UserNS.IsPrivate() && s.IDMappings == nil {
|
||||||
return errors.Wrap(ErrInvalidSpecConfig, "IDMappings are required when not creating a User namespace")
|
return errors.Wrap(ErrInvalidSpecConfig, "IDMappings are required when not creating a User namespace")
|
||||||
|
|
|
||||||
|
|
@ -337,11 +337,11 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigToSpec takes a completed container config and converts it back into a specgenerator for purposes of cloning an existing container
|
// ConfigToSpec takes a completed container config and converts it back into a specgenerator for purposes of cloning an exisiting container
|
||||||
func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID string) (*libpod.Container, error) {
|
func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID string) (*libpod.Container, *libpod.InfraInherit, error) {
|
||||||
c, err := rt.LookupContainer(containerID)
|
c, err := rt.LookupContainer(contaierID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
conf := c.Config()
|
conf := c.Config()
|
||||||
|
|
||||||
|
|
@ -351,17 +351,22 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID
|
||||||
conf.Systemd = nil
|
conf.Systemd = nil
|
||||||
conf.Mounts = []string{}
|
conf.Mounts = []string{}
|
||||||
|
|
||||||
|
if specg == nil {
|
||||||
|
specg = &specgen.SpecGenerator{}
|
||||||
|
}
|
||||||
|
|
||||||
specg.Pod = conf.Pod
|
specg.Pod = conf.Pod
|
||||||
|
|
||||||
matching, err := json.Marshal(conf)
|
matching, err := json.Marshal(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(matching, specg)
|
err = json.Unmarshal(matching, specg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Systemd = tmpSystemd
|
conf.Systemd = tmpSystemd
|
||||||
conf.Mounts = tmpMounts
|
conf.Mounts = tmpMounts
|
||||||
|
|
||||||
|
|
@ -481,7 +486,29 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
specg.OverlayVolumes = overlay
|
specg.OverlayVolumes = overlay
|
||||||
specg.Mounts = conf.Spec.Mounts
|
_, mounts := c.SortUserVolumes(c.Spec())
|
||||||
|
specg.Mounts = mounts
|
||||||
specg.HostDeviceList = conf.DeviceHostSrc
|
specg.HostDeviceList = conf.DeviceHostSrc
|
||||||
return c, nil
|
mapSecurityConfig(conf, specg)
|
||||||
|
|
||||||
|
if c.IsInfra() { // if we are creating this spec for a pod's infra ctr, map the compatible options
|
||||||
|
spec, err := json.Marshal(specg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
infraInherit := &libpod.InfraInherit{}
|
||||||
|
err = json.Unmarshal(spec, infraInherit)
|
||||||
|
return c, infraInherit, err
|
||||||
|
}
|
||||||
|
// else just return the container
|
||||||
|
return c, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapSecurityConfig takes a libpod.ContainerSecurityConfig and converts it to a specgen.ContinerSecurityConfig
|
||||||
|
func mapSecurityConfig(c *libpod.ContainerConfig, s *specgen.SpecGenerator) {
|
||||||
|
s.Privileged = c.Privileged
|
||||||
|
s.SelinuxOpts = append(s.SelinuxOpts, c.LabelOpts...)
|
||||||
|
s.User = c.User
|
||||||
|
s.Groups = c.Groups
|
||||||
|
s.HostUsers = c.HostUsers
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||||
compatibleOptions := &libpod.InfraInherit{}
|
compatibleOptions := &libpod.InfraInherit{}
|
||||||
var infraSpec *spec.Spec
|
var infraSpec *spec.Spec
|
||||||
if infra != nil {
|
if infra != nil {
|
||||||
options, infraSpec, compatibleOptions, err = Inherit(*infra)
|
options, infraSpec, compatibleOptions, err = Inherit(*infra, s, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -152,8 +152,8 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
infraVolumes := (len(compatibleOptions.InfraVolumes) > 0 || len(compatibleOptions.InfraUserVolumes) > 0 || len(compatibleOptions.InfraImageVolumes) > 0)
|
infraVol := (len(compatibleOptions.Mounts) > 0 || len(compatibleOptions.Volumes) > 0 || len(compatibleOptions.ImageVolumes) > 0 || len(compatibleOptions.OverlayVolumes) > 0)
|
||||||
opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, finalOverlays, imageData, command, infraVolumes, *compatibleOptions)
|
opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, finalOverlays, imageData, command, infraVol, *compatibleOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -446,7 +446,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
||||||
if len(s.SelinuxOpts) > 0 {
|
if len(s.SelinuxOpts) > 0 {
|
||||||
options = append(options, libpod.WithSecLabels(s.SelinuxOpts))
|
options = append(options, libpod.WithSecLabels(s.SelinuxOpts))
|
||||||
} else {
|
} else {
|
||||||
if pod != nil && len(compatibleOptions.InfraLabels) == 0 {
|
if pod != nil && len(compatibleOptions.SelinuxOpts) == 0 {
|
||||||
// duplicate the security options from the pod
|
// duplicate the security options from the pod
|
||||||
processLabel, err := pod.ProcessLabel()
|
processLabel, err := pod.ProcessLabel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -544,32 +544,23 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
||||||
return options, nil
|
return options, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Inherit(infra libpod.Container) (opts []libpod.CtrCreateOption, infraS *spec.Spec, compat *libpod.InfraInherit, err error) {
|
func Inherit(infra libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runtime) (opts []libpod.CtrCreateOption, infraS *spec.Spec, compat *libpod.InfraInherit, err error) {
|
||||||
|
inheritSpec := &specgen.SpecGenerator{}
|
||||||
|
_, compatibleOptions, err := ConfigToSpec(rt, inheritSpec, infra.ID())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
options := []libpod.CtrCreateOption{}
|
options := []libpod.CtrCreateOption{}
|
||||||
compatibleOptions := &libpod.InfraInherit{}
|
|
||||||
infraConf := infra.Config()
|
infraConf := infra.Config()
|
||||||
infraSpec := infraConf.Spec
|
infraSpec := infraConf.Spec
|
||||||
|
|
||||||
config, err := json.Marshal(infraConf)
|
compatByte, err := json.Marshal(compatibleOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(config, compatibleOptions)
|
err = json.Unmarshal(compatByte, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
if infraSpec.Linux != nil && infraSpec.Linux.Resources != nil {
|
|
||||||
resources, err := json.Marshal(infraSpec.Linux.Resources)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(resources, &compatibleOptions.InfraResources)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if compatibleOptions != nil {
|
|
||||||
options = append(options, libpod.WithInfraConfig(*compatibleOptions))
|
|
||||||
}
|
|
||||||
return options, infraSpec, compatibleOptions, nil
|
return options, infraSpec, compatibleOptions, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -352,8 +352,8 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(compatibleOptions.InfraDevices) > 0 && len(s.Devices) == 0 {
|
if len(compatibleOptions.HostDeviceList) > 0 && len(s.Devices) == 0 {
|
||||||
userDevices = compatibleOptions.InfraDevices
|
userDevices = compatibleOptions.HostDeviceList
|
||||||
} else {
|
} else {
|
||||||
userDevices = s.Devices
|
userDevices = s.Devices
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ var (
|
||||||
// TODO: handle options parsing/processing via containers/storage/pkg/mount
|
// TODO: handle options parsing/processing via containers/storage/pkg/mount
|
||||||
func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bool) ([]spec.Mount, []*specgen.NamedVolume, []*specgen.OverlayVolume, []*specgen.ImageVolume, error) {
|
func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bool) ([]spec.Mount, []*specgen.NamedVolume, []*specgen.OverlayVolume, []*specgen.ImageVolume, error) {
|
||||||
// Get mounts from the --mounts flag.
|
// Get mounts from the --mounts flag.
|
||||||
unifiedMounts, unifiedVolumes, unifiedImageVolumes, err := getMounts(mountFlag)
|
unifiedMounts, unifiedVolumes, unifiedImageVolumes, err := Mounts(mountFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -167,12 +167,12 @@ func findMountType(input string) (mountType string, tokens []string, err error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// getMounts takes user-provided input from the --mount flag and creates OCI
|
// Mounts takes user-provided input from the --mount flag and creates OCI
|
||||||
// spec mounts and Libpod named volumes.
|
// spec mounts and Libpod named volumes.
|
||||||
// podman run --mount type=bind,src=/etc/resolv.conf,target=/etc/resolv.conf ...
|
// podman run --mount type=bind,src=/etc/resolv.conf,target=/etc/resolv.conf ...
|
||||||
// podman run --mount type=tmpfs,target=/dev/shm ...
|
// podman run --mount type=tmpfs,target=/dev/shm ...
|
||||||
// podman run --mount type=volume,source=test-volume, ...
|
// podman run --mount type=volume,source=test-volume, ...
|
||||||
func getMounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.NamedVolume, map[string]*specgen.ImageVolume, error) {
|
func Mounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.NamedVolume, map[string]*specgen.ImageVolume, error) {
|
||||||
finalMounts := make(map[string]spec.Mount)
|
finalMounts := make(map[string]spec.Mount)
|
||||||
finalNamedVolumes := make(map[string]*specgen.NamedVolume)
|
finalNamedVolumes := make(map[string]*specgen.NamedVolume)
|
||||||
finalImageVolumes := make(map[string]*specgen.ImageVolume)
|
finalImageVolumes := make(map[string]*specgen.ImageVolume)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -493,14 +495,64 @@ subdir**`
|
||||||
Expect(output).NotTo(ContainSubstring("/testfilter/subdir"))
|
Expect(output).NotTo(ContainSubstring("/testfilter/subdir"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// See https://github.com/containers/podman/issues/13535
|
||||||
|
It("Remote build .containerignore filtering embedded directory (#13535)", func() {
|
||||||
|
SkipIfNotRemote("Testing remote .containerignore file filtering")
|
||||||
|
podmanTest.RestartRemoteService()
|
||||||
|
|
||||||
|
// Switch to temp dir and restore it afterwards
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
podmanTest.AddImageToRWStore(ALPINE)
|
||||||
|
|
||||||
|
contents := bytes.Buffer{}
|
||||||
|
contents.WriteString("FROM " + ALPINE + "\n")
|
||||||
|
contents.WriteString("ADD . /testfilter/\n")
|
||||||
|
contents.WriteString("RUN find /testfilter/ -print\n")
|
||||||
|
|
||||||
|
containerfile := filepath.Join(tempdir, "Containerfile")
|
||||||
|
Expect(ioutil.WriteFile(containerfile, contents.Bytes(), 0644)).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
contextDir, err := CreateTempDirInTempDir()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
defer os.RemoveAll(contextDir)
|
||||||
|
|
||||||
|
Expect(ioutil.WriteFile(filepath.Join(contextDir, "expected"), contents.Bytes(), 0644)).
|
||||||
|
ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
subdirPath := filepath.Join(contextDir, "subdir")
|
||||||
|
Expect(os.MkdirAll(subdirPath, 0755)).ToNot(HaveOccurred())
|
||||||
|
Expect(ioutil.WriteFile(filepath.Join(subdirPath, "extra"), contents.Bytes(), 0644)).
|
||||||
|
ToNot(HaveOccurred())
|
||||||
|
randomFile := filepath.Join(subdirPath, "randomFile")
|
||||||
|
dd := exec.Command("dd", "if=/dev/random", "of="+randomFile, "bs=1G", "count=1")
|
||||||
|
ddSession, err := Start(dd, GinkgoWriter, GinkgoWriter)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Eventually(ddSession).Should(Exit(0))
|
||||||
|
|
||||||
|
// make cwd as context root path
|
||||||
|
Expect(os.Chdir(contextDir)).ToNot(HaveOccurred())
|
||||||
|
defer os.Chdir(cwd)
|
||||||
|
|
||||||
|
By("Test .containerignore filtering subdirectory")
|
||||||
|
err = ioutil.WriteFile(filepath.Join(contextDir, ".containerignore"), []byte(`subdir/`), 0644)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
session := podmanTest.Podman([]string{"build", "-f", containerfile, contextDir})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).To(Exit(0))
|
||||||
|
|
||||||
|
output := session.OutputToString()
|
||||||
|
Expect(output).To(ContainSubstring("Containerfile"))
|
||||||
|
Expect(output).To(ContainSubstring("/testfilter/expected"))
|
||||||
|
Expect(output).NotTo(ContainSubstring("subdir"))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman remote test context dir contains empty dirs and symlinks", func() {
|
It("podman remote test context dir contains empty dirs and symlinks", func() {
|
||||||
if IsRemote() {
|
SkipIfNotRemote("Testing remote contextDir empty")
|
||||||
podmanTest.StopRemoteService()
|
podmanTest.RestartRemoteService()
|
||||||
podmanTest.StartRemoteService()
|
|
||||||
} else {
|
|
||||||
Skip("Only valid at remote test")
|
|
||||||
}
|
|
||||||
// Given
|
|
||||||
// Switch to temp dir and restore it afterwards
|
// Switch to temp dir and restore it afterwards
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/containers/podman/v4/libpod/define"
|
"github.com/containers/podman/v4/libpod/define"
|
||||||
"github.com/containers/podman/v4/pkg/inspect"
|
"github.com/containers/podman/v4/pkg/inspect"
|
||||||
"github.com/containers/podman/v4/pkg/rootless"
|
"github.com/containers/podman/v4/pkg/rootless"
|
||||||
|
"github.com/containers/podman/v4/pkg/util"
|
||||||
. "github.com/containers/podman/v4/test/utils"
|
. "github.com/containers/podman/v4/test/utils"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
"github.com/containers/storage/pkg/reexec"
|
"github.com/containers/storage/pkg/reexec"
|
||||||
|
|
@ -500,14 +501,12 @@ func (p *PodmanTestIntegration) BuildImageWithLabel(dockerfile, imageName string
|
||||||
// PodmanPID execs podman and returns its PID
|
// PodmanPID execs podman and returns its PID
|
||||||
func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) {
|
func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) {
|
||||||
podmanOptions := p.MakeOptions(args, false, false)
|
podmanOptions := p.MakeOptions(args, false, false)
|
||||||
if p.RemoteTest {
|
|
||||||
podmanOptions = append([]string{"--remote", "--url", p.RemoteSocket}, podmanOptions...)
|
|
||||||
}
|
|
||||||
fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
|
fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
|
||||||
|
|
||||||
command := exec.Command(p.PodmanBinary, podmanOptions...)
|
command := exec.Command(p.PodmanBinary, podmanOptions...)
|
||||||
session, err := Start(command, GinkgoWriter, GinkgoWriter)
|
session, err := Start(command, GinkgoWriter, GinkgoWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fail(fmt.Sprintf("unable to run podman command: %s", strings.Join(podmanOptions, " ")))
|
Fail("unable to run podman command: " + strings.Join(podmanOptions, " "))
|
||||||
}
|
}
|
||||||
podmanSession := &PodmanSession{Session: session}
|
podmanSession := &PodmanSession{Session: session}
|
||||||
return &PodmanSessionIntegration{podmanSession}, command.Process.Pid
|
return &PodmanSessionIntegration{podmanSession}, command.Process.Pid
|
||||||
|
|
@ -843,11 +842,13 @@ func (p *PodmanTestIntegration) PodmanNoEvents(args []string) *PodmanSessionInte
|
||||||
// MakeOptions assembles all the podman main options
|
// MakeOptions assembles all the podman main options
|
||||||
func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache bool) []string {
|
func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache bool) []string {
|
||||||
if p.RemoteTest {
|
if p.RemoteTest {
|
||||||
|
if !util.StringInSlice("--remote", args) {
|
||||||
|
return append([]string{"--remote", "--url", p.RemoteSocket}, args...)
|
||||||
|
}
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
var (
|
|
||||||
debug string
|
var debug string
|
||||||
)
|
|
||||||
if _, ok := os.LookupEnv("DEBUG"); ok {
|
if _, ok := os.LookupEnv("DEBUG"); ok {
|
||||||
debug = "--log-level=debug --syslog=true "
|
debug = "--log-level=debug --syslog=true "
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -25,31 +24,28 @@ func IsRemote() bool {
|
||||||
|
|
||||||
// Podman is the exec call to podman on the filesystem
|
// Podman is the exec call to podman on the filesystem
|
||||||
func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
|
func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
|
||||||
var remoteArgs = []string{"--remote", "--url", p.RemoteSocket}
|
args = p.makeOptions(args, false, false)
|
||||||
remoteArgs = append(remoteArgs, args...)
|
podmanSession := p.PodmanBase(args, false, false)
|
||||||
podmanSession := p.PodmanBase(remoteArgs, false, false)
|
|
||||||
return &PodmanSessionIntegration{podmanSession}
|
return &PodmanSessionIntegration{podmanSession}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodmanSystemdScope runs the podman command in a new systemd scope
|
// PodmanSystemdScope runs the podman command in a new systemd scope
|
||||||
func (p *PodmanTestIntegration) PodmanSystemdScope(args []string) *PodmanSessionIntegration {
|
func (p *PodmanTestIntegration) PodmanSystemdScope(args []string) *PodmanSessionIntegration {
|
||||||
var remoteArgs = []string{"--remote", "--url", p.RemoteSocket}
|
args = p.makeOptions(args, false, false)
|
||||||
remoteArgs = append(remoteArgs, args...)
|
|
||||||
|
|
||||||
wrapper := []string{"systemd-run", "--scope"}
|
wrapper := []string{"systemd-run", "--scope"}
|
||||||
if rootless.IsRootless() {
|
if rootless.IsRootless() {
|
||||||
wrapper = []string{"systemd-run", "--scope", "--user"}
|
wrapper = []string{"systemd-run", "--scope", "--user"}
|
||||||
}
|
}
|
||||||
|
|
||||||
podmanSession := p.PodmanAsUserBase(remoteArgs, 0, 0, "", nil, false, false, wrapper, nil)
|
podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, wrapper, nil)
|
||||||
return &PodmanSessionIntegration{podmanSession}
|
return &PodmanSessionIntegration{podmanSession}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodmanExtraFiles is the exec call to podman on the filesystem and passes down extra files
|
// PodmanExtraFiles is the exec call to podman on the filesystem and passes down extra files
|
||||||
func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os.File) *PodmanSessionIntegration {
|
func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os.File) *PodmanSessionIntegration {
|
||||||
var remoteArgs = []string{"--remote", "--url", p.RemoteSocket}
|
args = p.makeOptions(args, false, false)
|
||||||
remoteArgs = append(remoteArgs, args...)
|
podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, nil, extraFiles)
|
||||||
podmanSession := p.PodmanAsUserBase(remoteArgs, 0, 0, "", nil, false, false, nil, extraFiles)
|
|
||||||
return &PodmanSessionIntegration{podmanSession}
|
return &PodmanSessionIntegration{podmanSession}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,57 +92,39 @@ func (p *PodmanTestIntegration) StartRemoteService() {
|
||||||
command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
p.RemoteCommand = command
|
p.RemoteCommand = command
|
||||||
p.RemoteSession = command.Process
|
p.RemoteSession = command.Process
|
||||||
err := p.DelayForService()
|
p.RemoteStartErr = p.DelayForService()
|
||||||
p.RemoteStartErr = err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PodmanTestIntegration) StopRemoteService() {
|
func (p *PodmanTestIntegration) StopRemoteService() {
|
||||||
var out bytes.Buffer
|
|
||||||
var pids []int
|
|
||||||
remoteSession := p.RemoteSession
|
|
||||||
|
|
||||||
if !rootless.IsRootless() {
|
if !rootless.IsRootless() {
|
||||||
if err := remoteSession.Kill(); err != nil {
|
if err := p.RemoteSession.Kill(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error on remote stop-kill %q", err)
|
fmt.Fprintf(os.Stderr, "error on remote stop-kill %q", err)
|
||||||
}
|
}
|
||||||
if _, err := remoteSession.Wait(); err != nil {
|
if _, err := p.RemoteSession.Wait(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error on remote stop-wait %q", err)
|
fmt.Fprintf(os.Stderr, "error on remote stop-wait %q", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
parentPid := fmt.Sprintf("%d", p.RemoteSession.Pid)
|
// Stop any children of `podman system service`
|
||||||
pgrep := exec.Command("pgrep", "-P", parentPid)
|
pkill := exec.Command("pkill", "-P", strconv.Itoa(p.RemoteSession.Pid), "-15")
|
||||||
fmt.Printf("running: pgrep %s\n", parentPid)
|
if err := pkill.Run(); err != nil {
|
||||||
pgrep.Stdout = &out
|
exitErr := err.(*exec.ExitError)
|
||||||
err := pgrep.Run()
|
if exitErr.ExitCode() != 1 {
|
||||||
if err != nil {
|
fmt.Fprintf(os.Stderr, "pkill unable to clean up service %d children, exit code %d\n",
|
||||||
fmt.Fprint(os.Stderr, "unable to find remote pid")
|
p.RemoteSession.Pid, exitErr.ExitCode())
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range strings.Split(out.String(), "\n") {
|
|
||||||
if len(s) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p, err := strconv.Atoi(s)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "unable to convert %s to int", s)
|
|
||||||
}
|
|
||||||
if p != 0 {
|
|
||||||
pids = append(pids, p)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := p.RemoteSession.Kill(); err != nil {
|
||||||
pids = append(pids, p.RemoteSession.Pid)
|
fmt.Fprintf(os.Stderr, "unable to clean up service %d, %v\n", p.RemoteSession.Pid, err)
|
||||||
for _, pid := range pids {
|
|
||||||
syscall.Kill(pid, syscall.SIGKILL)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
socket := strings.Split(p.RemoteSocket, ":")[1]
|
socket := strings.Split(p.RemoteSocket, ":")[1]
|
||||||
if err := os.Remove(socket); err != nil {
|
if err := os.Remove(socket); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
fmt.Println(err)
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
}
|
}
|
||||||
if p.RemoteSocketLock != "" {
|
if p.RemoteSocketLock != "" {
|
||||||
if err := os.Remove(p.RemoteSocketLock); err != nil {
|
if err := os.Remove(p.RemoteSocketLock); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
fmt.Println(err)
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -185,8 +163,9 @@ func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PodmanTestIntegration) DelayForService() error {
|
func (p *PodmanTestIntegration) DelayForService() error {
|
||||||
|
var session *PodmanSessionIntegration
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
session := p.Podman([]string{"info"})
|
session = p.Podman([]string{"info"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
if session.ExitCode() == 0 {
|
if session.ExitCode() == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -195,5 +174,5 @@ func (p *PodmanTestIntegration) DelayForService() error {
|
||||||
}
|
}
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
}
|
}
|
||||||
return errors.New("Service not detected")
|
return fmt.Errorf("service not detected, exit code(%d)", session.ExitCode())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1679,6 +1679,32 @@ var _ = Describe("Podman play kube", func() {
|
||||||
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`))
|
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman play kube test env value from configmap and --replace should reuse the configmap volume", func() {
|
||||||
|
SkipIfRemote("configmap list is not supported as a param")
|
||||||
|
cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
|
||||||
|
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
||||||
|
err := generateKubeYaml("configmap", cm, cmYamlPathname)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false))))
|
||||||
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(0))
|
||||||
|
|
||||||
|
// create pod again with --replace
|
||||||
|
kube = podmanTest.Podman([]string{"play", "kube", "--replace", kubeYaml, "--configmap", cmYamlPathname})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(0))
|
||||||
|
|
||||||
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
|
||||||
|
inspect.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspect).Should(Exit(0))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman play kube test required env value from configmap with missing key", func() {
|
It("podman play kube test required env value from configmap with missing key", func() {
|
||||||
SkipIfRemote("configmap list is not supported as a param")
|
SkipIfRemote("configmap list is not supported as a param")
|
||||||
cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
|
cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
|
||||||
|
|
|
||||||
|
|
@ -874,6 +874,10 @@ ENTRYPOINT ["sleep","99999"]
|
||||||
ctr3 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "cat", "/tmp1/test"})
|
ctr3 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "cat", "/tmp1/test"})
|
||||||
ctr3.WaitWithDefaultTimeout()
|
ctr3.WaitWithDefaultTimeout()
|
||||||
Expect(ctr3.OutputToString()).To(ContainSubstring("hello"))
|
Expect(ctr3.OutputToString()).To(ContainSubstring("hello"))
|
||||||
|
|
||||||
|
ctr4 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "touch", "/tmp1/testing.txt"})
|
||||||
|
ctr4.WaitWithDefaultTimeout()
|
||||||
|
Expect(ctr4).Should(Exit(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman pod create --device", func() {
|
It("podman pod create --device", func() {
|
||||||
|
|
|
||||||
|
|
@ -535,6 +535,11 @@ var _ = Describe("Podman run", func() {
|
||||||
Expect(session).Should(Exit(0))
|
Expect(session).Should(Exit(0))
|
||||||
Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
|
Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"run", "--user=1:1", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapEff", "/proc/self/status"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
|
||||||
|
|
||||||
if os.Geteuid() > 0 {
|
if os.Geteuid() > 0 {
|
||||||
if os.Getenv("SKIP_USERNS") != "" {
|
if os.Getenv("SKIP_USERNS") != "" {
|
||||||
Skip("Skip userns tests.")
|
Skip("Skip userns tests.")
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ var _ = Describe("Podman unshare", func() {
|
||||||
podmanTest *PodmanTestIntegration
|
podmanTest *PodmanTestIntegration
|
||||||
)
|
)
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
SkipIfRemote("podman-remote unshare is not supported")
|
|
||||||
if _, err := os.Stat("/proc/self/uid_map"); err != nil {
|
if _, err := os.Stat("/proc/self/uid_map"); err != nil {
|
||||||
Skip("User namespaces not supported.")
|
Skip("User namespaces not supported.")
|
||||||
}
|
}
|
||||||
|
|
@ -43,6 +42,7 @@ var _ = Describe("Podman unshare", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman unshare", func() {
|
It("podman unshare", func() {
|
||||||
|
SkipIfRemote("podman-remote unshare is not supported")
|
||||||
userNS, _ := os.Readlink("/proc/self/ns/user")
|
userNS, _ := os.Readlink("/proc/self/ns/user")
|
||||||
session := podmanTest.Podman([]string{"unshare", "readlink", "/proc/self/ns/user"})
|
session := podmanTest.Podman([]string{"unshare", "readlink", "/proc/self/ns/user"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
|
|
@ -50,7 +50,8 @@ var _ = Describe("Podman unshare", func() {
|
||||||
Expect(session.OutputToString()).ToNot(ContainSubstring(userNS))
|
Expect(session.OutputToString()).ToNot(ContainSubstring(userNS))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman unshare --rootles-cni", func() {
|
It("podman unshare --rootless-cni", func() {
|
||||||
|
SkipIfRemote("podman-remote unshare is not supported")
|
||||||
session := podmanTest.Podman([]string{"unshare", "--rootless-netns", "ip", "addr"})
|
session := podmanTest.Podman([]string{"unshare", "--rootless-netns", "ip", "addr"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(0))
|
Expect(session).Should(Exit(0))
|
||||||
|
|
@ -58,6 +59,7 @@ var _ = Describe("Podman unshare", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman unshare exit codes", func() {
|
It("podman unshare exit codes", func() {
|
||||||
|
SkipIfRemote("podman-remote unshare is not supported")
|
||||||
session := podmanTest.Podman([]string{"unshare", "false"})
|
session := podmanTest.Podman([]string{"unshare", "false"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(1))
|
Expect(session).Should(Exit(1))
|
||||||
|
|
@ -88,4 +90,12 @@ var _ = Describe("Podman unshare", func() {
|
||||||
Expect(session.OutputToString()).Should(Equal(""))
|
Expect(session.OutputToString()).Should(Equal(""))
|
||||||
Expect(session.ErrorToString()).Should(ContainSubstring("unknown flag: --bogus"))
|
Expect(session.ErrorToString()).Should(ContainSubstring("unknown flag: --bogus"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman unshare check remote error", func() {
|
||||||
|
SkipIfNotRemote("check for podman-remote unshare error")
|
||||||
|
session := podmanTest.Podman([]string{"unshare"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
Expect(session.OutputToString()).To(Equal(`Error: cannot use command "podman-remote unshare" with the remote podman client`))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,16 @@ setup() {
|
||||||
cat >| $pmscript <<EOF
|
cat >| $pmscript <<EOF
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# Argh! podman >= 3.4 something something namespace something, fails with
|
||||||
|
# Error: invalid config provided: cannot set hostname when running in the host UTS namespace: invalid configuration
|
||||||
|
#
|
||||||
|
# https://github.com/containers/podman/issues/11969#issuecomment-943386484
|
||||||
|
#
|
||||||
|
if grep -q utsns /etc/containers/containers.conf; then
|
||||||
|
sed -i -e '/^\utsns=/d' /etc/containers/containers.conf
|
||||||
|
fi
|
||||||
|
|
||||||
# events-backend=journald does not work inside a container
|
# events-backend=journald does not work inside a container
|
||||||
opts="--events-backend=file $_PODMAN_TEST_OPTS"
|
opts="--events-backend=file $_PODMAN_TEST_OPTS"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,9 +100,7 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string
|
||||||
if p.NetworkBackend == Netavark {
|
if p.NetworkBackend == Netavark {
|
||||||
runCmd = append(runCmd, []string{"--network-backend", "netavark"}...)
|
runCmd = append(runCmd, []string{"--network-backend", "netavark"}...)
|
||||||
}
|
}
|
||||||
if p.RemoteTest {
|
|
||||||
podmanOptions = append([]string{"--remote", "--url", p.RemoteSocket}, podmanOptions...)
|
|
||||||
}
|
|
||||||
if env == nil {
|
if env == nil {
|
||||||
fmt.Printf("Running: %s %s\n", strings.Join(runCmd, " "), strings.Join(podmanOptions, " "))
|
fmt.Printf("Running: %s %s\n", strings.Join(runCmd, " "), strings.Join(podmanOptions, " "))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue