mirror of
https://github.com/containers/podman.git
synced 2025-05-19 16:18:51 +08:00
InfraContainer Rework
InfraContainer should go through the same creation process as regular containers. This change was from the cmd level down, involving new container CLI opts and specgen creating functions. What now happens is that both container and pod cli options are populated in cmd and used to create a podSpecgen and a containerSpecgen. The process then goes as follows FillOutSpecGen (infra) -> MapSpec (podOpts -> infraOpts) -> PodCreate -> MakePod -> createPodOptions -> NewPod -> CompleteSpec (infra) -> MakeContainer -> NewContainer -> newContainer -> AddInfra (to pod state) Signed-off-by: cdoern <cdoern@redhat.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -19,122 +19,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ContainerCLIOpts struct {
|
||||
Annotation []string
|
||||
Attach []string
|
||||
Authfile string
|
||||
BlkIOWeight string
|
||||
BlkIOWeightDevice []string
|
||||
CapAdd []string
|
||||
CapDrop []string
|
||||
CgroupNS string
|
||||
CGroupsMode string
|
||||
CGroupParent string
|
||||
CIDFile string
|
||||
ConmonPIDFile string
|
||||
CPUPeriod uint64
|
||||
CPUQuota int64
|
||||
CPURTPeriod uint64
|
||||
CPURTRuntime int64
|
||||
CPUShares uint64
|
||||
CPUS float64
|
||||
CPUSetCPUs string
|
||||
CPUSetMems string
|
||||
Devices []string
|
||||
DeviceCGroupRule []string
|
||||
DeviceReadBPs []string
|
||||
DeviceReadIOPs []string
|
||||
DeviceWriteBPs []string
|
||||
DeviceWriteIOPs []string
|
||||
Entrypoint *string
|
||||
Env []string
|
||||
EnvHost bool
|
||||
EnvFile []string
|
||||
Expose []string
|
||||
GIDMap []string
|
||||
GroupAdd []string
|
||||
HealthCmd string
|
||||
HealthInterval string
|
||||
HealthRetries uint
|
||||
HealthStartPeriod string
|
||||
HealthTimeout string
|
||||
Hostname string
|
||||
HTTPProxy bool
|
||||
ImageVolume string
|
||||
Init bool
|
||||
InitContainerType string
|
||||
InitPath string
|
||||
Interactive bool
|
||||
IPC string
|
||||
KernelMemory string
|
||||
Label []string
|
||||
LabelFile []string
|
||||
LogDriver string
|
||||
LogOptions []string
|
||||
Memory string
|
||||
MemoryReservation string
|
||||
MemorySwap string
|
||||
MemorySwappiness int64
|
||||
Name string
|
||||
NoHealthCheck bool
|
||||
OOMKillDisable bool
|
||||
OOMScoreAdj int
|
||||
Arch string
|
||||
OS string
|
||||
Variant string
|
||||
Personality string
|
||||
PID string
|
||||
PIDsLimit *int64
|
||||
Platform string
|
||||
Pod string
|
||||
PodIDFile string
|
||||
PreserveFDs uint
|
||||
Privileged bool
|
||||
PublishAll bool
|
||||
Pull string
|
||||
Quiet bool
|
||||
ReadOnly bool
|
||||
ReadOnlyTmpFS bool
|
||||
Restart string
|
||||
Replace bool
|
||||
Requires []string
|
||||
Rm bool
|
||||
RootFS bool
|
||||
Secrets []string
|
||||
SecurityOpt []string
|
||||
SdNotifyMode string
|
||||
ShmSize string
|
||||
SignaturePolicy string
|
||||
StopSignal string
|
||||
StopTimeout uint
|
||||
StorageOpt []string
|
||||
SubUIDName string
|
||||
SubGIDName string
|
||||
Sysctl []string
|
||||
Systemd string
|
||||
Timeout uint
|
||||
TLSVerify bool
|
||||
TmpFS []string
|
||||
TTY bool
|
||||
Timezone string
|
||||
Umask string
|
||||
UIDMap []string
|
||||
Ulimit []string
|
||||
User string
|
||||
UserNS string
|
||||
UTS string
|
||||
Mount []string
|
||||
Volume []string
|
||||
VolumesFrom []string
|
||||
Workdir string
|
||||
SeccompPolicy string
|
||||
PidFile string
|
||||
|
||||
Net *entities.NetOptions
|
||||
|
||||
CgroupConf []string
|
||||
}
|
||||
|
||||
func stringMaptoArray(m map[string]string) []string {
|
||||
a := make([]string, 0, len(m))
|
||||
for k, v := range m {
|
||||
@ -145,7 +29,7 @@ func stringMaptoArray(m map[string]string) []string {
|
||||
|
||||
// ContainerCreateToContainerCLIOpts converts a compat input struct to cliopts so it can be converted to
|
||||
// a specgen spec.
|
||||
func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*ContainerCLIOpts, []string, error) {
|
||||
func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.ContainerCreateOptions, []string, error) {
|
||||
var (
|
||||
capAdd []string
|
||||
cappDrop []string
|
||||
@ -341,7 +225,7 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c
|
||||
// Note: several options here are marked as "don't need". this is based
|
||||
// on speculation by Matt and I. We think that these come into play later
|
||||
// like with start. We believe this is just a difference in podman/compat
|
||||
cliOpts := ContainerCLIOpts{
|
||||
cliOpts := entities.ContainerCreateOptions{
|
||||
// Attach: nil, // don't need?
|
||||
Authfile: "",
|
||||
CapAdd: append(capAdd, cc.HostConfig.CapAdd...),
|
||||
|
@ -8,8 +8,10 @@ import (
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func DefineNetFlags(cmd *cobra.Command) {
|
||||
@ -87,12 +89,15 @@ func DefineNetFlags(cmd *cobra.Command) {
|
||||
// NetFlagsToNetOptions parses the network flags for the given cmd.
|
||||
// The netnsFromConfig bool is used to indicate if the --network flag
|
||||
// should always be parsed regardless if it was set on the cli.
|
||||
func NetFlagsToNetOptions(cmd *cobra.Command, netnsFromConfig bool) (*entities.NetOptions, error) {
|
||||
func NetFlagsToNetOptions(opts *entities.NetOptions, flags pflag.FlagSet, netnsFromConfig bool) (*entities.NetOptions, error) {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
opts := entities.NetOptions{}
|
||||
opts.AddHosts, err = cmd.Flags().GetStringSlice("add-host")
|
||||
if opts == nil {
|
||||
opts = &entities.NetOptions{}
|
||||
}
|
||||
|
||||
opts.AddHosts, err = flags.GetStringSlice("add-host")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -103,56 +108,50 @@ func NetFlagsToNetOptions(cmd *cobra.Command, netnsFromConfig bool) (*entities.N
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("dns") {
|
||||
servers, err := cmd.Flags().GetStringSlice("dns")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, d := range servers {
|
||||
if d == "none" {
|
||||
opts.UseImageResolvConf = true
|
||||
if len(servers) > 1 {
|
||||
return nil, errors.Errorf("%s is not allowed to be specified with other DNS ip addresses", d)
|
||||
}
|
||||
break
|
||||
servers, err := flags.GetStringSlice("dns")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, d := range servers {
|
||||
if d == "none" {
|
||||
opts.UseImageResolvConf = true
|
||||
if len(servers) > 1 {
|
||||
return nil, errors.Errorf("%s is not allowed to be specified with other DNS ip addresses", d)
|
||||
}
|
||||
dns := net.ParseIP(d)
|
||||
if dns == nil {
|
||||
return nil, errors.Errorf("%s is not an ip address", d)
|
||||
}
|
||||
opts.DNSServers = append(opts.DNSServers, dns)
|
||||
break
|
||||
}
|
||||
dns := net.ParseIP(d)
|
||||
if dns == nil {
|
||||
return nil, errors.Errorf("%s is not an ip address", d)
|
||||
}
|
||||
opts.DNSServers = append(opts.DNSServers, dns)
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("dns-opt") {
|
||||
options, err := cmd.Flags().GetStringSlice("dns-opt")
|
||||
if err != nil {
|
||||
options, err := flags.GetStringSlice("dns-opt")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts.DNSOptions = options
|
||||
|
||||
dnsSearches, err := flags.GetStringSlice("dns-search")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Validate domains are good
|
||||
for _, dom := range dnsSearches {
|
||||
if dom == "." {
|
||||
if len(dnsSearches) > 1 {
|
||||
return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
|
||||
}
|
||||
continue
|
||||
}
|
||||
if _, err := parse.ValidateDomain(dom); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts.DNSOptions = options
|
||||
}
|
||||
opts.DNSSearch = dnsSearches
|
||||
|
||||
if cmd.Flags().Changed("dns-search") {
|
||||
dnsSearches, err := cmd.Flags().GetStringSlice("dns-search")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Validate domains are good
|
||||
for _, dom := range dnsSearches {
|
||||
if dom == "." {
|
||||
if len(dnsSearches) > 1 {
|
||||
return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
|
||||
}
|
||||
continue
|
||||
}
|
||||
if _, err := parse.ValidateDomain(dom); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
opts.DNSSearch = dnsSearches
|
||||
}
|
||||
|
||||
m, err := cmd.Flags().GetString("mac-address")
|
||||
m, err := flags.GetString("mac-address")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -164,18 +163,18 @@ func NetFlagsToNetOptions(cmd *cobra.Command, netnsFromConfig bool) (*entities.N
|
||||
opts.StaticMAC = &mac
|
||||
}
|
||||
|
||||
inputPorts, err := cmd.Flags().GetStringSlice("publish")
|
||||
inputPorts, err := flags.GetStringSlice("publish")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(inputPorts) > 0 {
|
||||
opts.PublishPorts, err = CreatePortBindings(inputPorts)
|
||||
opts.PublishPorts, err = specgenutil.CreatePortBindings(inputPorts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ip, err := cmd.Flags().GetString("ip")
|
||||
ip, err := flags.GetString("ip")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -190,15 +189,15 @@ func NetFlagsToNetOptions(cmd *cobra.Command, netnsFromConfig bool) (*entities.N
|
||||
opts.StaticIP = &staticIP
|
||||
}
|
||||
|
||||
opts.NoHosts, err = cmd.Flags().GetBool("no-hosts")
|
||||
opts.NoHosts, err = flags.GetBool("no-hosts")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse the --network value only when the flag is set or we need to use
|
||||
// the netns config value, e.g. when --pod is not used
|
||||
if netnsFromConfig || cmd.Flag("network").Changed {
|
||||
network, err := cmd.Flags().GetString("network")
|
||||
if netnsFromConfig || flags.Changed("network") {
|
||||
network, err := flags.GetString("network")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -215,12 +214,13 @@ func NetFlagsToNetOptions(cmd *cobra.Command, netnsFromConfig bool) (*entities.N
|
||||
opts.CNINetworks = cniNets
|
||||
}
|
||||
|
||||
aliases, err := cmd.Flags().GetStringSlice("network-alias")
|
||||
aliases, err := flags.GetStringSlice("network-alias")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(aliases) > 0 {
|
||||
opts.Aliases = aliases
|
||||
}
|
||||
return &opts, err
|
||||
|
||||
return opts, err
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@ -52,8 +53,8 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
cliVals common.ContainerCLIOpts
|
||||
InitContainerType string
|
||||
cliVals entities.ContainerCreateOptions
|
||||
)
|
||||
|
||||
func createFlags(cmd *cobra.Command) {
|
||||
@ -67,13 +68,18 @@ func createFlags(cmd *cobra.Command) {
|
||||
)
|
||||
|
||||
flags.SetInterspersed(false)
|
||||
common.DefineCreateFlags(cmd, &cliVals)
|
||||
common.DefineCreateFlags(cmd, &cliVals, false)
|
||||
common.DefineNetFlags(cmd)
|
||||
|
||||
flags.SetNormalizeFunc(utils.AliasFlags)
|
||||
|
||||
if registry.IsRemote() {
|
||||
_ = flags.MarkHidden("conmon-pidfile")
|
||||
if cliVals.IsInfra {
|
||||
_ = flags.MarkHidden("infra-conmon-pidfile")
|
||||
} else {
|
||||
_ = flags.MarkHidden("conmon-pidfile")
|
||||
}
|
||||
|
||||
_ = flags.MarkHidden("pidfile")
|
||||
}
|
||||
|
||||
@ -97,7 +103,8 @@ func create(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "" && cliVals.PodIDFile == "")
|
||||
flags := cmd.Flags()
|
||||
cliVals.Net, err = common.NetFlagsToNetOptions(nil, *flags, cliVals.Pod == "" && cliVals.PodIDFile == "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -113,22 +120,22 @@ func create(cmd *cobra.Command, args []string) error {
|
||||
cliVals.InitContainerType = initctr
|
||||
}
|
||||
|
||||
if err := createInit(cmd); err != nil {
|
||||
cliVals, err = CreateInit(cmd, cliVals, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
imageName := args[0]
|
||||
rawImageName := ""
|
||||
if !cliVals.RootFS {
|
||||
rawImageName = args[0]
|
||||
name, err := pullImage(args[0])
|
||||
name, err := PullImage(args[0], cliVals)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imageName = name
|
||||
}
|
||||
s := specgen.NewSpecGenerator(imageName, cliVals.RootFS)
|
||||
if err := common.FillOutSpecGen(s, &cliVals, args); err != nil {
|
||||
if err := specgenutil.FillOutSpecGen(s, &cliVals, args); err != nil {
|
||||
return err
|
||||
}
|
||||
s.RawImageName = rawImageName
|
||||
@ -169,100 +176,101 @@ func replaceContainer(name string) error {
|
||||
return removeContainers([]string{name}, rmOptions, false)
|
||||
}
|
||||
|
||||
func createInit(c *cobra.Command) error {
|
||||
cliVals.StorageOpt = registry.PodmanConfig().StorageOpts
|
||||
|
||||
if c.Flag("shm-size").Changed {
|
||||
cliVals.ShmSize = c.Flag("shm-size").Value.String()
|
||||
}
|
||||
|
||||
if (c.Flag("dns").Changed || c.Flag("dns-opt").Changed || c.Flag("dns-search").Changed) && (cliVals.Net.Network.NSMode == specgen.NoNetwork || cliVals.Net.Network.IsContainer()) {
|
||||
return errors.Errorf("conflicting options: dns and the network mode.")
|
||||
}
|
||||
|
||||
if c.Flag("cpu-period").Changed && c.Flag("cpus").Changed {
|
||||
return errors.Errorf("--cpu-period and --cpus cannot be set together")
|
||||
}
|
||||
if c.Flag("cpu-quota").Changed && c.Flag("cpus").Changed {
|
||||
return errors.Errorf("--cpu-quota and --cpus cannot be set together")
|
||||
}
|
||||
if c.Flag("pod").Changed && !strings.HasPrefix(c.Flag("pod").Value.String(), "new:") && c.Flag("userns").Changed {
|
||||
return errors.Errorf("--userns and --pod cannot be set together")
|
||||
}
|
||||
|
||||
noHosts, err := c.Flags().GetBool("no-hosts")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if noHosts && c.Flag("add-host").Changed {
|
||||
return errors.Errorf("--no-hosts and --add-host cannot be set together")
|
||||
}
|
||||
cliVals.UserNS = c.Flag("userns").Value.String()
|
||||
func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra bool) (entities.ContainerCreateOptions, error) {
|
||||
vals.UserNS = c.Flag("userns").Value.String()
|
||||
// if user did not modify --userns flag and did turn on
|
||||
// uid/gid mappings, set userns flag to "private"
|
||||
if !c.Flag("userns").Changed && cliVals.UserNS == "host" {
|
||||
if len(cliVals.UIDMap) > 0 ||
|
||||
len(cliVals.GIDMap) > 0 ||
|
||||
cliVals.SubUIDName != "" ||
|
||||
cliVals.SubGIDName != "" {
|
||||
cliVals.UserNS = "private"
|
||||
if !c.Flag("userns").Changed && vals.UserNS == "host" {
|
||||
if len(vals.UIDMap) > 0 ||
|
||||
len(vals.GIDMap) > 0 ||
|
||||
vals.SubUIDName != "" ||
|
||||
vals.SubGIDName != "" {
|
||||
vals.UserNS = "private"
|
||||
}
|
||||
}
|
||||
|
||||
cliVals.IPC = c.Flag("ipc").Value.String()
|
||||
cliVals.UTS = c.Flag("uts").Value.String()
|
||||
cliVals.PID = c.Flag("pid").Value.String()
|
||||
cliVals.CgroupNS = c.Flag("cgroupns").Value.String()
|
||||
if c.Flag("entrypoint").Changed {
|
||||
val := c.Flag("entrypoint").Value.String()
|
||||
cliVals.Entrypoint = &val
|
||||
}
|
||||
if !isInfra {
|
||||
if c.Flag("shm-size").Changed {
|
||||
vals.ShmSize = c.Flag("shm-size").Value.String()
|
||||
}
|
||||
if c.Flag("cpu-period").Changed && c.Flag("cpus").Changed {
|
||||
return vals, errors.Errorf("--cpu-period and --cpus cannot be set together")
|
||||
}
|
||||
if c.Flag("cpu-quota").Changed && c.Flag("cpus").Changed {
|
||||
return vals, errors.Errorf("--cpu-quota and --cpus cannot be set together")
|
||||
}
|
||||
vals.IPC = c.Flag("ipc").Value.String()
|
||||
vals.UTS = c.Flag("uts").Value.String()
|
||||
vals.PID = c.Flag("pid").Value.String()
|
||||
vals.CgroupNS = c.Flag("cgroupns").Value.String()
|
||||
|
||||
if c.Flags().Changed("group-add") {
|
||||
groups := []string{}
|
||||
for _, g := range cliVals.GroupAdd {
|
||||
if g == "keep-groups" {
|
||||
if len(cliVals.GroupAdd) > 1 {
|
||||
return errors.New("the '--group-add keep-groups' option is not allowed with any other --group-add options")
|
||||
if c.Flags().Changed("group-add") {
|
||||
groups := []string{}
|
||||
for _, g := range cliVals.GroupAdd {
|
||||
if g == "keep-groups" {
|
||||
if len(cliVals.GroupAdd) > 1 {
|
||||
return vals, errors.New("the '--group-add keep-groups' option is not allowed with any other --group-add options")
|
||||
}
|
||||
if registry.IsRemote() {
|
||||
return vals, errors.New("the '--group-add keep-groups' option is not supported in remote mode")
|
||||
}
|
||||
vals.Annotation = append(vals.Annotation, "run.oci.keep_original_groups=1")
|
||||
} else {
|
||||
groups = append(groups, g)
|
||||
}
|
||||
if registry.IsRemote() {
|
||||
return errors.New("the '--group-add keep-groups' option is not supported in remote mode")
|
||||
}
|
||||
cliVals.Annotation = append(cliVals.Annotation, "run.oci.keep_original_groups=1")
|
||||
} else {
|
||||
groups = append(groups, g)
|
||||
}
|
||||
vals.GroupAdd = groups
|
||||
}
|
||||
cliVals.GroupAdd = groups
|
||||
|
||||
if c.Flags().Changed("pids-limit") {
|
||||
val := c.Flag("pids-limit").Value.String()
|
||||
pidsLimit, err := strconv.ParseInt(val, 10, 32)
|
||||
if err != nil {
|
||||
return vals, err
|
||||
}
|
||||
vals.PIDsLimit = &pidsLimit
|
||||
}
|
||||
if c.Flags().Changed("env") {
|
||||
env, err := c.Flags().GetStringArray("env")
|
||||
if err != nil {
|
||||
return vals, errors.Wrapf(err, "retrieve env flag")
|
||||
}
|
||||
vals.Env = env
|
||||
}
|
||||
if c.Flag("cgroups").Changed && vals.CGroupsMode == "split" && registry.IsRemote() {
|
||||
return vals, errors.Errorf("the option --cgroups=%q is not supported in remote mode", vals.CGroupsMode)
|
||||
}
|
||||
|
||||
if c.Flag("pod").Changed && !strings.HasPrefix(c.Flag("pod").Value.String(), "new:") && c.Flag("userns").Changed {
|
||||
return vals, errors.Errorf("--userns and --pod cannot be set together")
|
||||
}
|
||||
}
|
||||
if (c.Flag("dns").Changed || c.Flag("dns-opt").Changed || c.Flag("dns-search").Changed) && vals.Net != nil && (vals.Net.Network.NSMode == specgen.NoNetwork || vals.Net.Network.IsContainer()) {
|
||||
return vals, errors.Errorf("conflicting options: dns and the network mode: " + string(vals.Net.Network.NSMode))
|
||||
}
|
||||
noHosts, err := c.Flags().GetBool("no-hosts")
|
||||
if err != nil {
|
||||
return vals, err
|
||||
}
|
||||
if noHosts && c.Flag("add-host").Changed {
|
||||
return vals, errors.Errorf("--no-hosts and --add-host cannot be set together")
|
||||
}
|
||||
|
||||
if c.Flags().Changed("pids-limit") {
|
||||
val := c.Flag("pids-limit").Value.String()
|
||||
pidsLimit, err := strconv.ParseInt(val, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cliVals.PIDsLimit = &pidsLimit
|
||||
}
|
||||
if c.Flags().Changed("env") {
|
||||
env, err := c.Flags().GetStringArray("env")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "retrieve env flag")
|
||||
}
|
||||
cliVals.Env = env
|
||||
}
|
||||
if c.Flag("cgroups").Changed && cliVals.CGroupsMode == "split" && registry.IsRemote() {
|
||||
return errors.Errorf("the option --cgroups=%q is not supported in remote mode", cliVals.CGroupsMode)
|
||||
if !isInfra && c.Flag("entrypoint").Changed {
|
||||
val := c.Flag("entrypoint").Value.String()
|
||||
vals.Entrypoint = &val
|
||||
} else if isInfra && c.Flag("infra-command").Changed {
|
||||
|
||||
}
|
||||
|
||||
// Docker-compatibility: the "-h" flag for run/create is reserved for
|
||||
// the hostname (see https://github.com/containers/podman/issues/1367).
|
||||
|
||||
return nil
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
func pullImage(imageName string) (string, error) {
|
||||
pullPolicy, err := config.ParsePullPolicy(cliVals.Pull)
|
||||
func PullImage(imageName string, cliVals entities.ContainerCreateOptions) (string, error) {
|
||||
pullPolicy, err := config.ValidatePullPolicy(cliVals.Pull)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -316,11 +324,14 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions
|
||||
return nil, errors.Errorf("new pod name must be at least one character")
|
||||
}
|
||||
|
||||
userns, err := specgen.ParseUserNamespace(cliVals.UserNS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var err error
|
||||
uns := specgen.Namespace{NSMode: specgen.Default}
|
||||
if cliVals.UserNS != "" {
|
||||
uns, err = specgen.ParseNamespace(cliVals.UserNS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
createOptions := entities.PodCreateOptions{
|
||||
Name: podName,
|
||||
Infra: true,
|
||||
@ -330,12 +341,36 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions
|
||||
Cpus: cliVals.CPUS,
|
||||
CpusetCpus: cliVals.CPUSetCPUs,
|
||||
Pid: cliVals.PID,
|
||||
Userns: userns,
|
||||
Userns: uns,
|
||||
}
|
||||
// Unset config values we passed to the pod to prevent them being used twice for the container and pod.
|
||||
s.ContainerBasicConfig.Hostname = ""
|
||||
s.ContainerNetworkConfig = specgen.ContainerNetworkConfig{}
|
||||
|
||||
s.Pod = podName
|
||||
return registry.ContainerEngine().PodCreate(context.Background(), createOptions)
|
||||
podSpec := entities.PodSpec{}
|
||||
podGen := specgen.NewPodSpecGenerator()
|
||||
podSpec.PodSpecGen = *podGen
|
||||
podGen, err = entities.ToPodSpecGen(*&podSpec.PodSpecGen, &createOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
infraOpts := entities.ContainerCreateOptions{ImageVolume: "bind", Net: netOpts, Quiet: true}
|
||||
rawImageName := config.DefaultInfraImage
|
||||
name, err := PullImage(rawImageName, infraOpts)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
imageName := name
|
||||
podGen.InfraImage = imageName
|
||||
podGen.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false)
|
||||
podGen.InfraContainerSpec.RawImageName = rawImageName
|
||||
podGen.InfraContainerSpec.NetworkOptions = podGen.NetworkOptions
|
||||
err = specgenutil.FillOutSpecGen(podGen.InfraContainerSpec, &infraOpts, []string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
podSpec.PodSpecGen = *podGen
|
||||
return registry.ContainerEngine().PodCreate(context.Background(), podSpec)
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/containers/podman/v3/cmd/podman/utils"
|
||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -63,7 +64,7 @@ func prune(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
pruneOptions.Filters, err = common.ParseFilters(filter)
|
||||
pruneOptions.Filters, err = specgenutil.ParseFilters(filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -106,7 +107,7 @@ func restore(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
if len(inputPorts) > 0 {
|
||||
restoreOptions.PublishPorts, err = common.CreatePortBindings(inputPorts)
|
||||
restoreOptions.PublishPorts, err = specgenutil.CreatePortBindings(inputPorts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/containers/podman/v3/pkg/errorhandling"
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
@ -60,7 +61,7 @@ func runFlags(cmd *cobra.Command) {
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.SetInterspersed(false)
|
||||
common.DefineCreateFlags(cmd, &cliVals)
|
||||
common.DefineCreateFlags(cmd, &cliVals, false)
|
||||
common.DefineNetFlags(cmd)
|
||||
|
||||
flags.SetNormalizeFunc(utils.AliasFlags)
|
||||
@ -106,10 +107,6 @@ func init() {
|
||||
|
||||
func run(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "" && cliVals.PodIDFile == "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Breaking change should be made fatal in next major Release
|
||||
if cliVals.TTY && cliVals.Interactive && !terminal.IsTerminal(int(os.Stdin.Fd())) {
|
||||
@ -122,11 +119,17 @@ func run(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
runOpts.CIDFile = cliVals.CIDFile
|
||||
runOpts.Rm = cliVals.Rm
|
||||
if err := createInit(cmd); err != nil {
|
||||
flags := cmd.Flags()
|
||||
cliVals.Net, err = common.NetFlagsToNetOptions(nil, *flags, cliVals.Pod == "" && cliVals.PodIDFile == "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runOpts.CIDFile = cliVals.CIDFile
|
||||
runOpts.Rm = cliVals.Rm
|
||||
if cliVals, err = CreateInit(cmd, cliVals, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for fd := 3; fd < int(3+runOpts.PreserveFDs); fd++ {
|
||||
if !rootless.IsFdInherited(fd) {
|
||||
return errors.Errorf("file descriptor %d is not available - the preserve-fds option requires that file descriptors must be passed", fd)
|
||||
@ -137,7 +140,7 @@ func run(cmd *cobra.Command, args []string) error {
|
||||
rawImageName := ""
|
||||
if !cliVals.RootFS {
|
||||
rawImageName = args[0]
|
||||
name, err := pullImage(args[0])
|
||||
name, err := PullImage(args[0], cliVals)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -178,7 +181,7 @@ func run(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
cliVals.PreserveFDs = runOpts.PreserveFDs
|
||||
s := specgen.NewSpecGenerator(imageName, cliVals.RootFS)
|
||||
if err := common.FillOutSpecGen(s, &cliVals, args); err != nil {
|
||||
if err := specgenutil.FillOutSpecGen(s, &cliVals, args); err != nil {
|
||||
return err
|
||||
}
|
||||
s.RawImageName = rawImageName
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/containers/podman/v3/cmd/podman/utils"
|
||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -59,7 +60,7 @@ func prune(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
filterMap, err := common.ParseFilters(filter)
|
||||
filterMap, err := specgenutil.ParseFilters(filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/containers/podman/v3/cmd/podman/utils"
|
||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
@ -67,7 +68,7 @@ func networkPrune(cmd *cobra.Command, _ []string) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
networkPruneOptions.Filters, err = common.ParseFilters(filter)
|
||||
networkPruneOptions.Filters, err = specgenutil.ParseFilters(filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -11,14 +11,17 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/pkg/completion"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/common/pkg/sysinfo"
|
||||
"github.com/containers/podman/v3/cmd/podman/common"
|
||||
"github.com/containers/podman/v3/cmd/podman/containers"
|
||||
"github.com/containers/podman/v3/cmd/podman/parse"
|
||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/errorhandling"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/pkg/errors"
|
||||
@ -44,11 +47,11 @@ var (
|
||||
|
||||
var (
|
||||
createOptions entities.PodCreateOptions
|
||||
infraOptions entities.ContainerCreateOptions
|
||||
labels, labelFile []string
|
||||
podIDFile string
|
||||
replace bool
|
||||
share string
|
||||
userns string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -58,62 +61,19 @@ func init() {
|
||||
})
|
||||
flags := createCommand.Flags()
|
||||
flags.SetInterspersed(false)
|
||||
|
||||
infraOptions.IsInfra = true
|
||||
common.DefineCreateFlags(createCommand, &infraOptions, true)
|
||||
common.DefineNetFlags(createCommand)
|
||||
|
||||
cpusetflagName := "cpuset-cpus"
|
||||
flags.StringVar(&createOptions.CpusetCpus, cpusetflagName, "", "CPUs in which to allow execution")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(cpusetflagName, completion.AutocompleteDefault)
|
||||
|
||||
cpusflagName := "cpus"
|
||||
flags.Float64Var(&createOptions.Cpus, cpusflagName, 0.000, "set amount of CPUs for the pod")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(cpusflagName, completion.AutocompleteDefault)
|
||||
|
||||
cgroupParentflagName := "cgroup-parent"
|
||||
flags.StringVar(&createOptions.CGroupParent, cgroupParentflagName, "", "Set parent cgroup for the pod")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(cgroupParentflagName, completion.AutocompleteDefault)
|
||||
|
||||
usernsFlagName := "userns"
|
||||
flags.StringVar(&userns, usernsFlagName, os.Getenv("PODMAN_USERNS"), "User namespace to use")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(usernsFlagName, common.AutocompleteUserNamespace)
|
||||
|
||||
flags.BoolVar(&createOptions.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")
|
||||
|
||||
infraConmonPidfileFlagName := "infra-conmon-pidfile"
|
||||
flags.StringVar(&createOptions.InfraConmonPidFile, infraConmonPidfileFlagName, "", "Path to the file that will receive the POD of the infra container's conmon")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(infraConmonPidfileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
infraImageFlagName := "infra-image"
|
||||
flags.String(infraImageFlagName, containerConfig.Engine.InfraImage, "The image of the infra container to associate with the pod")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(infraImageFlagName, common.AutocompleteImages)
|
||||
|
||||
infraCommandFlagName := "infra-command"
|
||||
flags.String(infraCommandFlagName, containerConfig.Engine.InfraCommand, "The command to run on the infra container when the pod is started")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(infraCommandFlagName, completion.AutocompleteNone)
|
||||
|
||||
infraNameFlagName := "infra-name"
|
||||
flags.StringVarP(&createOptions.InfraName, infraNameFlagName, "", "", "The name used as infra container name")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(infraNameFlagName, completion.AutocompleteNone)
|
||||
|
||||
labelFileFlagName := "label-file"
|
||||
flags.StringSliceVar(&labelFile, labelFileFlagName, []string{}, "Read in a line delimited file of labels")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(labelFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
labelFlagName := "label"
|
||||
flags.StringSliceVarP(&labels, labelFlagName, "l", []string{}, "Set metadata on pod (default [])")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(labelFlagName, completion.AutocompleteNone)
|
||||
|
||||
nameFlagName := "name"
|
||||
flags.StringVarP(&createOptions.Name, nameFlagName, "n", "", "Assign a name to the pod")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(nameFlagName, completion.AutocompleteNone)
|
||||
|
||||
hostnameFlagName := "hostname"
|
||||
flags.StringVarP(&createOptions.Hostname, hostnameFlagName, "", "", "Set a hostname to the pod")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(hostnameFlagName, completion.AutocompleteNone)
|
||||
|
||||
pidFlagName := "pid"
|
||||
flags.StringVar(&createOptions.Pid, pidFlagName, "", "PID namespace to use")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(pidFlagName, common.AutocompleteNamespace)
|
||||
infraImageFlagName := "infra-image"
|
||||
flags.String(infraImageFlagName, containerConfig.Engine.InfraImage, "The image of the infra container to associate with the pod")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(infraImageFlagName, common.AutocompleteImages)
|
||||
|
||||
podIDFileFlagName := "pod-id-file"
|
||||
flags.StringVar(&podIDFile, podIDFileFlagName, "", "Write the pod ID to the file")
|
||||
@ -137,25 +97,30 @@ func aliasNetworkFlag(_ *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
|
||||
func create(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
err error
|
||||
podIDFD *os.File
|
||||
err error
|
||||
podIDFD *os.File
|
||||
imageName string
|
||||
rawImageName string
|
||||
)
|
||||
labelFile = infraOptions.LabelFile
|
||||
labels = infraOptions.Label
|
||||
createOptions.Labels, err = parse.GetAllLabels(labelFile, labels)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to process labels")
|
||||
}
|
||||
|
||||
imageName = config.DefaultInfraImage
|
||||
img := imageName
|
||||
if !createOptions.Infra {
|
||||
if cmd.Flag("no-hosts").Changed {
|
||||
return fmt.Errorf("cannot specify no-hosts without an infra container")
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
createOptions.Net, err = common.NetFlagsToNetOptions(nil, *flags, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("Not creating an infra container")
|
||||
if cmd.Flag("infra-conmon-pidfile").Changed {
|
||||
return errors.New("cannot set infra-conmon-pid without an infra container")
|
||||
}
|
||||
if cmd.Flag("infra-command").Changed {
|
||||
return errors.New("cannot set infra-command without an infra container")
|
||||
}
|
||||
if cmd.Flag("infra-image").Changed {
|
||||
return errors.New("cannot set infra-image without an infra container")
|
||||
}
|
||||
createOptions.InfraImage = ""
|
||||
if createOptions.InfraName != "" {
|
||||
return errors.New("cannot set infra-name without an infra container")
|
||||
@ -166,28 +131,43 @@ func create(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
createOptions.Share = nil
|
||||
} else {
|
||||
// reassign certain optios for lbpod api, these need to be populated in spec
|
||||
createOptions.InfraConmonPidFile = infraOptions.ConmonPIDFile
|
||||
createOptions.InfraName = infraOptions.Name
|
||||
createOptions.Hostname = infraOptions.Hostname
|
||||
createOptions.Cpus = infraOptions.CPUS
|
||||
createOptions.CpusetCpus = infraOptions.CPUSetCPUs
|
||||
createOptions.Pid = infraOptions.PID
|
||||
flags := cmd.Flags()
|
||||
infraOptions.Net, err = common.NetFlagsToNetOptions(nil, *flags, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
infraOptions, err = containers.CreateInit(cmd, infraOptions, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
createOptions.Net = infraOptions.Net
|
||||
createOptions.Share = strings.Split(share, ",")
|
||||
if cmd.Flag("infra-command").Changed {
|
||||
// Only send content to server side if user changed defaults
|
||||
createOptions.InfraCommand, err = cmd.Flags().GetString("infra-command")
|
||||
cmdIn, err := cmd.Flags().GetString("infra-command")
|
||||
infraOptions.Entrypoint = &cmdIn
|
||||
createOptions.InfraCommand = cmdIn
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if cmd.Flag("infra-image").Changed {
|
||||
// Only send content to server side if user changed defaults
|
||||
createOptions.InfraImage, err = cmd.Flags().GetString("infra-image")
|
||||
img, err = cmd.Flags().GetString("infra-image")
|
||||
imageName = img
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createOptions.Userns, err = specgen.ParseUserNamespace(userns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.Flag("pod-id-file").Changed {
|
||||
podIDFD, err = util.OpenExclusiveFile(podIDFile)
|
||||
if err != nil && os.IsExist(err) {
|
||||
@ -200,13 +180,6 @@ func create(cmd *cobra.Command, args []string) error {
|
||||
defer errorhandling.SyncQuiet(podIDFD)
|
||||
}
|
||||
|
||||
createOptions.Pid = cmd.Flag("pid").Value.String()
|
||||
|
||||
createOptions.Net, err = common.NetFlagsToNetOptions(cmd, createOptions.Infra)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(createOptions.Net.PublishPorts) > 0 {
|
||||
if !createOptions.Infra {
|
||||
return errors.Errorf("you must have an infra container to publish port bindings to the host")
|
||||
@ -261,10 +234,44 @@ func create(cmd *cobra.Command, args []string) error {
|
||||
copy = "" + strconv.Itoa(core)
|
||||
}
|
||||
}
|
||||
response, err := registry.ContainerEngine().PodCreate(context.Background(), createOptions)
|
||||
podSpec := specgen.NewPodSpecGenerator()
|
||||
podSpec, err = entities.ToPodSpecGen(*podSpec, &createOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if createOptions.Infra {
|
||||
rawImageName = img
|
||||
if !infraOptions.RootFS {
|
||||
curr := infraOptions.Quiet
|
||||
infraOptions.Quiet = true
|
||||
name, err := containers.PullImage(imageName, infraOptions)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
imageName = name
|
||||
infraOptions.Quiet = curr
|
||||
}
|
||||
podSpec.InfraImage = imageName
|
||||
if infraOptions.Entrypoint != nil {
|
||||
createOptions.InfraCommand = *infraOptions.Entrypoint
|
||||
}
|
||||
infraOptions.CPUS = createOptions.Cpus
|
||||
infraOptions.CPUSetCPUs = createOptions.CpusetCpus
|
||||
infraOptions.PID = createOptions.Pid
|
||||
podSpec.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false)
|
||||
podSpec.InfraContainerSpec.RawImageName = rawImageName
|
||||
podSpec.InfraContainerSpec.NetworkOptions = podSpec.NetworkOptions
|
||||
err = specgenutil.FillOutSpecGen(podSpec.InfraContainerSpec, &infraOptions, []string{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
PodSpec := entities.PodSpec{PodSpecGen: *podSpec}
|
||||
response, err := registry.ContainerEngine().PodCreate(context.Background(), PodSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(podIDFile) > 0 {
|
||||
if err = ioutil.WriteFile(podIDFile, []byte(response.Id), 0644); err != nil {
|
||||
return errors.Wrapf(err, "failed to write pod ID to file")
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -66,7 +67,7 @@ func init() {
|
||||
}
|
||||
|
||||
func rm(_ *cobra.Command, args []string) error {
|
||||
ids, err := common.ReadPodIDFiles(rmOptions.PodIDFiles)
|
||||
ids, err := specgenutil.ReadPodIDFiles(rmOptions.PodIDFiles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/containers/podman/v3/cmd/podman/utils"
|
||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -64,7 +65,7 @@ func start(cmd *cobra.Command, args []string) error {
|
||||
errs utils.OutputErrors
|
||||
)
|
||||
|
||||
ids, err := common.ReadPodIDFiles(startOptions.PodIDFiles)
|
||||
ids, err := specgenutil.ReadPodIDFiles(startOptions.PodIDFiles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/containers/podman/v3/cmd/podman/utils"
|
||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -78,7 +79,7 @@ func stop(cmd *cobra.Command, args []string) error {
|
||||
stopOptions.Timeout = int(stopOptions.TimeoutCLI)
|
||||
}
|
||||
|
||||
ids, err := common.ReadPodIDFiles(stopOptions.PodIDFiles)
|
||||
ids, err := specgenutil.ReadPodIDFiles(stopOptions.PodIDFiles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -51,7 +51,26 @@ Set custom DNS options in the /etc/resolv.conf file that will be shared between
|
||||
|
||||
Set custom DNS search domains in the /etc/resolv.conf file that will be shared between all containers in the pod.
|
||||
|
||||
#### **--help**
|
||||
#### **--gidmap**=*container_gid:host_gid:amount*
|
||||
|
||||
GID map for the user namespace. Using this flag will run the container with user namespace enabled. It conflicts with the `--userns` and `--subgidname` flags.
|
||||
|
||||
#### **--uidmap**=*container_uid*:*from_uid*:*amount*
|
||||
|
||||
Run the container in a new user namespace using the supplied mapping. This
|
||||
option conflicts with the **--userns** and **--subuidname** options. This
|
||||
option provides a way to map host UIDs to container UIDs. It can be passed
|
||||
several times to map different ranges.
|
||||
|
||||
#### **--subgidname**=*name*
|
||||
|
||||
Name for GID map from the `/etc/subgid` file. Using this flag will run the container with user namespace enabled. This flag conflicts with `--userns` and `--gidmap`.
|
||||
|
||||
#### **--subuidname**=*name*
|
||||
|
||||
Name for UID map from the `/etc/subuid` file. Using this flag will run the container with user namespace enabled. This flag conflicts with `--userns` and `--uidmap`.
|
||||
|
||||
#### **--help**, **-h**
|
||||
|
||||
Print usage statement.
|
||||
|
||||
|
@ -972,11 +972,12 @@ func (c *Container) checkDependenciesRunning() ([]string, error) {
|
||||
}
|
||||
|
||||
// Check the status
|
||||
conf := depCtr.Config()
|
||||
state, err := depCtr.State()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error retrieving state of dependency %s of container %s", dep, c.ID())
|
||||
}
|
||||
if state != define.ContainerStateRunning {
|
||||
if state != define.ContainerStateRunning && !conf.IsInfra {
|
||||
notRunning = append(notRunning, dep)
|
||||
}
|
||||
depCtrs[dep] = depCtr
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/lookup"
|
||||
"github.com/containers/podman/v3/pkg/namespaces"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
@ -72,7 +74,7 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
|
||||
return nil, servicePorts, err
|
||||
}
|
||||
servicePorts = containerPortsToServicePorts(ports)
|
||||
hostNetwork = p.config.InfraContainer.HostNetwork
|
||||
hostNetwork = infraContainer.NetworkMode() == string(namespaces.NetworkMode(specgen.Host))
|
||||
}
|
||||
pod, err := p.podWithContainers(allContainers, ports, hostNetwork)
|
||||
if err != nil {
|
||||
|
@ -632,7 +632,6 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re
|
||||
}
|
||||
|
||||
podName := getCNIPodName(ctr)
|
||||
|
||||
networks, _, err := ctr.networks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/libpod/events"
|
||||
netTypes "github.com/containers/podman/v3/libpod/network/types"
|
||||
"github.com/containers/podman/v3/pkg/namespaces"
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
@ -21,7 +22,6 @@ import (
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -713,7 +713,6 @@ func (r *Runtime) WithPod(pod *Pod) CtrCreateOption {
|
||||
if pod == nil {
|
||||
return define.ErrInvalidArg
|
||||
}
|
||||
|
||||
ctr.config.Pod = pod.ID()
|
||||
|
||||
return nil
|
||||
@ -1430,20 +1429,6 @@ func WithRestartRetries(tries uint) CtrCreateOption {
|
||||
}
|
||||
}
|
||||
|
||||
// withIsInfra sets the container to be an infra container. This means the container will be sometimes hidden
|
||||
// and expected to be the first container in the pod.
|
||||
func withIsInfra() CtrCreateOption {
|
||||
return func(ctr *Container) error {
|
||||
if ctr.valid {
|
||||
return define.ErrCtrFinalized
|
||||
}
|
||||
|
||||
ctr.config.IsInfra = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamedVolumes adds the given named volumes to the container.
|
||||
func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption {
|
||||
return func(ctr *Container) error {
|
||||
@ -1541,6 +1526,20 @@ func WithCreateCommand(cmd []string) CtrCreateOption {
|
||||
}
|
||||
}
|
||||
|
||||
// withIsInfra allows us to dfferentiate between infra containers and regular containers
|
||||
// within the container config
|
||||
func withIsInfra() CtrCreateOption {
|
||||
return func(ctr *Container) error {
|
||||
if ctr.valid {
|
||||
return define.ErrCtrFinalized
|
||||
}
|
||||
|
||||
ctr.config.IsInfra = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithCreateWorkingDir tells Podman to create the container's working directory
|
||||
// if it does not exist.
|
||||
func WithCreateWorkingDir() CtrCreateOption {
|
||||
@ -1812,45 +1811,14 @@ func WithInitCtrType(containerType string) CtrCreateOption {
|
||||
|
||||
// Pod Creation Options
|
||||
|
||||
// WithInfraImage sets the infra image for libpod.
|
||||
// An infra image is used for inter-container kernel
|
||||
// namespace sharing within a pod. Typically, an infra
|
||||
// container is lightweight and is there to reap
|
||||
// zombie processes within its pid namespace.
|
||||
func WithInfraImage(img string) PodCreateOption {
|
||||
// WithPodCreateCommand adds the full command plus arguments of the current
|
||||
// process to the pod config.
|
||||
func WithPodCreateCommand(createCmd []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.InfraImage = img
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithInfraCommand sets the command to
|
||||
// run on pause container start up.
|
||||
func WithInfraCommand(cmd []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.InfraCommand = cmd
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithInfraName sets the infra container name for a single pod.
|
||||
func WithInfraName(name string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.InfraName = name
|
||||
|
||||
pod.config.CreateCommand = createCmd
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -1891,26 +1859,14 @@ func WithPodHostname(hostname string) PodCreateOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodCreateCommand adds the full command plus arguments of the current
|
||||
// process to the pod config.
|
||||
func WithPodCreateCommand(createCmd []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
pod.config.CreateCommand = createCmd
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithInfraConmonPidFile sets the path to a custom conmon PID file for the
|
||||
// infra container.
|
||||
func WithInfraConmonPidFile(path string) PodCreateOption {
|
||||
func WithInfraConmonPidFile(path string, infraSpec *specgen.SpecGenerator) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
pod.config.InfraContainer.ConmonPidFile = path
|
||||
infraSpec.ConmonPidFile = path
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -2099,320 +2055,25 @@ func WithInfraContainer() PodCreateOption {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.HasInfraContainer = true
|
||||
pod.config.HasInfra = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithInfraContainerPorts tells the pod to add port bindings to the pause container
|
||||
func WithInfraContainerPorts(bindings []ocicni.PortMapping) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set pod ports as no infra container is being created")
|
||||
}
|
||||
pod.config.InfraContainer.PortBindings = bindings
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodStaticIP sets a static IP for the pod.
|
||||
func WithPodStaticIP(ip net.IP) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set pod static IP as no infra container is being created")
|
||||
}
|
||||
|
||||
if pod.config.InfraContainer.HostNetwork {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set static IP if host network is specified")
|
||||
}
|
||||
|
||||
if len(pod.config.InfraContainer.Networks) > 1 {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set a static IP if joining more than 1 CNI network")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.StaticIP = ip
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodStaticMAC sets a static MAC address for the pod.
|
||||
func WithPodStaticMAC(mac net.HardwareAddr) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set pod static MAC as no infra container is being created")
|
||||
}
|
||||
|
||||
if pod.config.InfraContainer.HostNetwork {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set static MAC if host network is specified")
|
||||
}
|
||||
|
||||
if len(pod.config.InfraContainer.Networks) > 1 {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set a static MAC if joining more than 1 CNI network")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.StaticMAC = mac
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodUseImageResolvConf sets a pod to use an image's resolv.conf and not
|
||||
// create its own.
|
||||
func WithPodUseImageResolvConf() PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
|
||||
}
|
||||
|
||||
if len(pod.config.InfraContainer.DNSServer) != 0 ||
|
||||
len(pod.config.InfraContainer.DNSSearch) != 0 ||
|
||||
len(pod.config.InfraContainer.DNSOption) != 0 {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "requested use of image resolv.conf conflicts with already-configured DNS settings")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.UseImageResolvConf = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodDNS sets the DNS Servers for a pod.
|
||||
func WithPodDNS(dnsServer []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
|
||||
}
|
||||
|
||||
if pod.config.InfraContainer.UseImageResolvConf {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS servers if pod will not create /etc/resolv.conf")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.DNSServer = dnsServer
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodDNSSearch sets the DNS Search domains for a pod.
|
||||
func WithPodDNSSearch(dnsSearch []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
|
||||
}
|
||||
|
||||
if pod.config.InfraContainer.UseImageResolvConf {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS search domains if pod will not create /etc/resolv.conf")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.DNSSearch = dnsSearch
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodDNSOption sets DNS Options for a pod.
|
||||
func WithPodDNSOption(dnsOption []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
|
||||
}
|
||||
|
||||
if pod.config.InfraContainer.UseImageResolvConf {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS options if pod will not create /etc/resolv.conf")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.DNSOption = dnsOption
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodUseImageHosts tells the pod not to create /etc/hosts and instead to
|
||||
// use the one provided by the image.
|
||||
func WithPodUseImageHosts() PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod hosts as no infra container is being created")
|
||||
}
|
||||
|
||||
if len(pod.config.InfraContainer.HostAdd) != 0 {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.UseImageHosts = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodHosts adds additional entries to the pod's /etc/hosts
|
||||
func WithPodHosts(hosts []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod hosts as no infra container is being created")
|
||||
}
|
||||
|
||||
if pod.config.InfraContainer.UseImageHosts {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if container is using image hosts")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.HostAdd = hosts
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodNetworks sets additional CNI networks for the pod to join.
|
||||
func WithPodNetworks(networks []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod CNI networks as no infra container is being created")
|
||||
}
|
||||
|
||||
if (pod.config.InfraContainer.StaticIP != nil || pod.config.InfraContainer.StaticMAC != nil) &&
|
||||
len(networks) > 1 {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot join more than one CNI network if setting a static IP or MAC address")
|
||||
}
|
||||
|
||||
if pod.config.InfraContainer.HostNetwork {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot join pod to CNI networks if host network is specified")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.Networks = networks
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodNoNetwork tells the pod to disable external networking.
|
||||
func WithPodNoNetwork() PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod networking as no infra container is being created")
|
||||
}
|
||||
|
||||
if len(pod.config.InfraContainer.PortBindings) > 0 ||
|
||||
pod.config.InfraContainer.StaticIP != nil ||
|
||||
pod.config.InfraContainer.StaticMAC != nil ||
|
||||
len(pod.config.InfraContainer.Networks) > 0 ||
|
||||
pod.config.InfraContainer.HostNetwork {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.NoNetwork = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodHostNetwork tells the pod to use the host's network namespace.
|
||||
func WithPodHostNetwork() PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod host networking as no infra container is being created")
|
||||
}
|
||||
|
||||
if len(pod.config.InfraContainer.PortBindings) > 0 ||
|
||||
pod.config.InfraContainer.StaticIP != nil ||
|
||||
pod.config.InfraContainer.StaticMAC != nil ||
|
||||
len(pod.config.InfraContainer.Networks) > 0 ||
|
||||
pod.config.InfraContainer.NoNetwork {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.HostNetwork = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodInfraExitCommand sets an exit command for the pod's infra container.
|
||||
// Semantics are identical to WithExitCommand() above - the ID of the container
|
||||
// will be appended to the end of the provided command (note that this will
|
||||
// specifically be the ID of the infra container *and not the pod's id*.
|
||||
func WithPodInfraExitCommand(exitCmd []string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod infra container exit command as no infra container is being created")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.ExitCommand = exitCmd
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodSlirp4netns tells the pod to use slirp4netns.
|
||||
func WithPodSlirp4netns(networkOptions map[string][]string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod networking as no infra container is being created")
|
||||
}
|
||||
if pod.config.InfraContainer.HostNetwork {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot set both HostNetwork and Slirp4netns")
|
||||
}
|
||||
pod.config.InfraContainer.Slirp4netns = true
|
||||
pod.config.InfraContainer.NetworkOptions = networkOptions
|
||||
|
||||
return nil
|
||||
func WithInfraContainerPorts(bindings []ocicni.PortMapping, infraSpec *specgen.SpecGenerator) []netTypes.PortMapping {
|
||||
bindingSpec := []netTypes.PortMapping{}
|
||||
for _, bind := range bindings {
|
||||
currBind := netTypes.PortMapping{}
|
||||
currBind.ContainerPort = uint16(bind.ContainerPort)
|
||||
currBind.HostIP = bind.HostIP
|
||||
currBind.HostPort = uint16(bind.HostPort)
|
||||
currBind.Protocol = bind.Protocol
|
||||
bindingSpec = append(bindingSpec, currBind)
|
||||
}
|
||||
infraSpec.PortMappings = bindingSpec
|
||||
return infraSpec.PortMappings
|
||||
}
|
||||
|
||||
// WithVolatile sets the volatile flag for the container storage.
|
||||
@ -2428,78 +2089,3 @@ func WithVolatile() CtrCreateOption {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodUserns sets the userns for the infra container in a pod.
|
||||
func WithPodUserns(userns specgen.Namespace) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
|
||||
if !pod.config.InfraContainer.HasInfraContainer {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod userns as no infra container is being created")
|
||||
}
|
||||
|
||||
pod.config.InfraContainer.Userns = userns
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodCPUPAQ takes the given cpu period and quota and inserts them in the proper place.
|
||||
func WithPodCPUPAQ(period uint64, quota int64) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
if pod.CPUPeriod() != 0 && pod.CPUQuota() != 0 {
|
||||
pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{
|
||||
Period: &period,
|
||||
Quota: "a,
|
||||
}
|
||||
} else {
|
||||
pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{}
|
||||
pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{
|
||||
Period: &period,
|
||||
Quota: "a,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodCPUSetCPUS computes and sets the Cpus linux resource string which determines the amount of cores, from those available, we are allowed to execute on
|
||||
func WithPodCPUSetCPUs(inp string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
if pod.ResourceLim().CPU.Period != nil {
|
||||
pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp
|
||||
} else {
|
||||
pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{}
|
||||
pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{}
|
||||
pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithPodPidNS(inp specgen.Namespace) PodCreateOption {
|
||||
return func(p *Pod) error {
|
||||
if p.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
if p.config.UsePodPID {
|
||||
switch inp.NSMode {
|
||||
case "container":
|
||||
return errors.Wrap(define.ErrInvalidArg, "Cannot take container in a different NS as an argument")
|
||||
case "host":
|
||||
p.config.UsePodPID = false
|
||||
}
|
||||
p.config.InfraContainer.PidNS = inp
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
171
libpod/pod.go
171
libpod/pod.go
@ -2,14 +2,12 @@ package libpod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/libpod/lock"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -63,7 +61,7 @@ type PodConfig struct {
|
||||
UsePodUTS bool `json:"sharesUts,omitempty"`
|
||||
UsePodCgroupNS bool `json:"sharesCgroupNS,omitempty"`
|
||||
|
||||
InfraContainer *InfraContainerConfig `json:"infraConfig"`
|
||||
HasInfra bool `json:"hasInfra,omitempty"`
|
||||
|
||||
// Time pod was created
|
||||
CreatedTime time.Time `json:"created"`
|
||||
@ -85,41 +83,6 @@ type podState struct {
|
||||
InfraContainerID string
|
||||
}
|
||||
|
||||
// InfraContainerConfig is the configuration for the pod's infra container.
|
||||
// Generally speaking, these are equivalent to container configuration options
|
||||
// you will find in container_config.go (and even named identically), save for
|
||||
// HasInfraContainer (which determines if an infra container is even created -
|
||||
// if it is false, no other options in this struct will be used) and HostNetwork
|
||||
// (this involves the created OCI spec, and as such is not represented directly
|
||||
// in container_config.go).
|
||||
// Generally speaking, aside from those two exceptions, these options will set
|
||||
// the equivalent field in the container's configuration.
|
||||
type InfraContainerConfig struct {
|
||||
ConmonPidFile string `json:"conmonPidFile"`
|
||||
HasInfraContainer bool `json:"makeInfraContainer"`
|
||||
NoNetwork bool `json:"noNetwork,omitempty"`
|
||||
HostNetwork bool `json:"infraHostNetwork,omitempty"`
|
||||
PidNS specgen.Namespace `json:"infraPid,omitempty"`
|
||||
PortBindings []ocicni.PortMapping `json:"infraPortBindings"`
|
||||
StaticIP net.IP `json:"staticIP,omitempty"`
|
||||
StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"`
|
||||
UseImageResolvConf bool `json:"useImageResolvConf,omitempty"`
|
||||
DNSServer []string `json:"dnsServer,omitempty"`
|
||||
DNSSearch []string `json:"dnsSearch,omitempty"`
|
||||
DNSOption []string `json:"dnsOption,omitempty"`
|
||||
UseImageHosts bool `json:"useImageHosts,omitempty"`
|
||||
HostAdd []string `json:"hostsAdd,omitempty"`
|
||||
Networks []string `json:"networks,omitempty"`
|
||||
ExitCommand []string `json:"exitCommand,omitempty"`
|
||||
InfraImage string `json:"infraImage,omitempty"`
|
||||
InfraCommand []string `json:"infraCommand,omitempty"`
|
||||
InfraName string `json:"infraName,omitempty"`
|
||||
Slirp4netns bool `json:"slirp4netns,omitempty"`
|
||||
NetworkOptions map[string][]string `json:"network_options,omitempty"`
|
||||
ResourceLimits *specs.LinuxResources `json:"resource_limits,omitempty"`
|
||||
Userns specgen.Namespace `json:"userns,omitempty"`
|
||||
}
|
||||
|
||||
// ID retrieves the pod's ID
|
||||
func (p *Pod) ID() string {
|
||||
return p.config.ID
|
||||
@ -139,45 +102,104 @@ func (p *Pod) Namespace() string {
|
||||
// ResourceLim returns the cpuset resource limits for the pod
|
||||
func (p *Pod) ResourceLim() *specs.LinuxResources {
|
||||
resCopy := &specs.LinuxResources{}
|
||||
if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
|
||||
return nil
|
||||
}
|
||||
if resCopy != nil && resCopy.CPU != nil {
|
||||
return resCopy
|
||||
}
|
||||
empty := &specs.LinuxResources{
|
||||
CPU: &specs.LinuxCPU{},
|
||||
}
|
||||
infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
|
||||
if err != nil {
|
||||
return empty
|
||||
}
|
||||
conf := infra.config.Spec
|
||||
if err != nil {
|
||||
return empty
|
||||
}
|
||||
if conf.Linux == nil || conf.Linux.Resources == nil {
|
||||
return empty
|
||||
}
|
||||
if err = JSONDeepCopy(conf.Linux.Resources, resCopy); err != nil {
|
||||
return nil
|
||||
}
|
||||
if resCopy.CPU != nil {
|
||||
return resCopy
|
||||
}
|
||||
|
||||
return empty
|
||||
}
|
||||
|
||||
// CPUPeriod returns the pod CPU period
|
||||
func (p *Pod) CPUPeriod() uint64 {
|
||||
resCopy := &specs.LinuxResources{}
|
||||
if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
|
||||
if p.state.InfraContainerID == "" {
|
||||
return 0
|
||||
}
|
||||
if resCopy != nil && resCopy.CPU != nil && resCopy.CPU.Period != nil {
|
||||
return *resCopy.CPU.Period
|
||||
infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
conf := infra.config.Spec
|
||||
if conf != nil && conf.Linux != nil && conf.Linux.Resources != nil && conf.Linux.Resources.CPU != nil && conf.Linux.Resources.CPU.Period != nil {
|
||||
return *conf.Linux.Resources.CPU.Period
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// CPUQuota returns the pod CPU quota
|
||||
func (p *Pod) CPUQuota() int64 {
|
||||
resCopy := &specs.LinuxResources{}
|
||||
if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
|
||||
if p.state.InfraContainerID == "" {
|
||||
return 0
|
||||
}
|
||||
if resCopy != nil && resCopy.CPU != nil && resCopy.CPU.Quota != nil {
|
||||
return *resCopy.CPU.Quota
|
||||
infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
conf := infra.config.Spec
|
||||
if conf != nil && conf.Linux != nil && conf.Linux.Resources != nil && conf.Linux.Resources.CPU != nil && conf.Linux.Resources.CPU.Quota != nil {
|
||||
return *conf.Linux.Resources.CPU.Quota
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// PidMode returns the PID mode given by the user ex: pod, private...
|
||||
func (p *Pod) PidMode() string {
|
||||
return string(p.config.InfraContainer.PidNS.NSMode)
|
||||
infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
conf := infra.Config()
|
||||
ctrSpec := conf.Spec
|
||||
if ctrSpec != nil && ctrSpec.Linux != nil {
|
||||
for _, ns := range ctrSpec.Linux.Namespaces {
|
||||
if ns.Type == specs.PIDNamespace {
|
||||
if ns.Path != "" {
|
||||
return fmt.Sprintf("ns:%s", ns.Path)
|
||||
}
|
||||
return "private"
|
||||
}
|
||||
}
|
||||
return "host"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// PidMode returns the PID mode given by the user ex: pod, private...
|
||||
func (p *Pod) UserNSMode() string {
|
||||
infra, err := p.infraContainer()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
conf := infra.Config()
|
||||
ctrSpec := conf.Spec
|
||||
if ctrSpec != nil && ctrSpec.Linux != nil {
|
||||
for _, ns := range ctrSpec.Linux.Namespaces {
|
||||
if ns.Type == specs.UserNamespace {
|
||||
if ns.Path != "" {
|
||||
return fmt.Sprintf("ns:%s", ns.Path)
|
||||
}
|
||||
return "private"
|
||||
}
|
||||
}
|
||||
return "host"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Labels returns the pod's labels
|
||||
@ -263,20 +285,24 @@ func (p *Pod) CgroupPath() (string, error) {
|
||||
if p.state.CgroupPath != "" {
|
||||
return p.state.CgroupPath, nil
|
||||
}
|
||||
if !p.HasInfraContainer() {
|
||||
if p.state.InfraContainerID == "" {
|
||||
return "", errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container")
|
||||
}
|
||||
|
||||
id := p.state.InfraContainerID
|
||||
id, err := p.infraContainerID()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if id != "" {
|
||||
ctr, err := p.runtime.state.Container(id)
|
||||
ctr, err := p.infraContainer()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "could not get infra")
|
||||
}
|
||||
if ctr != nil {
|
||||
ctr.Start(context.Background(), false)
|
||||
ctr.Start(context.Background(), true)
|
||||
cgroupPath, err := ctr.CGroupPath()
|
||||
fmt.Println(cgroupPath)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "could not get container cgroup")
|
||||
}
|
||||
@ -325,7 +351,7 @@ func (p *Pod) allContainers() ([]*Container, error) {
|
||||
|
||||
// HasInfraContainer returns whether the pod will create an infra container
|
||||
func (p *Pod) HasInfraContainer() bool {
|
||||
return p.config.InfraContainer.HasInfraContainer
|
||||
return p.config.HasInfra
|
||||
}
|
||||
|
||||
// SharesNamespaces checks if the pod has any kernel namespaces set as shared. An infra container will not be
|
||||
@ -350,19 +376,26 @@ func (p *Pod) InfraContainerID() (string, error) {
|
||||
return p.infraContainerID()
|
||||
}
|
||||
|
||||
// InfraContainer returns the infra container.
|
||||
func (p *Pod) InfraContainer() (*Container, error) {
|
||||
if !p.HasInfraContainer() {
|
||||
return nil, errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container")
|
||||
}
|
||||
id, err := p.InfraContainerID()
|
||||
// infraContainer is the unlocked versio of InfraContainer which returns the infra container
|
||||
func (p *Pod) infraContainer() (*Container, error) {
|
||||
id, err := p.infraContainerID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if id == "" {
|
||||
return nil, errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container")
|
||||
}
|
||||
|
||||
return p.runtime.state.Container(id)
|
||||
}
|
||||
|
||||
// InfraContainer returns the infra container.
|
||||
func (p *Pod) InfraContainer() (*Container, error) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
return p.infraContainer()
|
||||
}
|
||||
|
||||
// TODO add pod batching
|
||||
// Lock pod to avoid lock contention
|
||||
// Store and lock all containers (no RemoveContainer in batch guarantees cache will not become stale)
|
||||
@ -412,13 +445,7 @@ func (p *Pod) ProcessLabel() (string, error) {
|
||||
if !p.HasInfraContainer() {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
id, err := p.InfraContainerID()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctr, err := p.runtime.state.Container(id)
|
||||
ctr, err := p.infraContainer()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -582,41 +582,46 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
|
||||
// Infra config contains detailed information on the pod's infra
|
||||
// container.
|
||||
var infraConfig *define.InspectPodInfraConfig
|
||||
if p.config.InfraContainer != nil && p.config.InfraContainer.HasInfraContainer {
|
||||
if p.state.InfraContainerID != "" {
|
||||
infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
infraConfig = new(define.InspectPodInfraConfig)
|
||||
infraConfig.HostNetwork = p.config.InfraContainer.HostNetwork
|
||||
infraConfig.StaticIP = p.config.InfraContainer.StaticIP
|
||||
infraConfig.StaticMAC = p.config.InfraContainer.StaticMAC.String()
|
||||
infraConfig.NoManageResolvConf = p.config.InfraContainer.UseImageResolvConf
|
||||
infraConfig.NoManageHosts = p.config.InfraContainer.UseImageHosts
|
||||
infraConfig.HostNetwork = !infra.Config().ContainerNetworkConfig.UseImageHosts
|
||||
infraConfig.StaticIP = infra.Config().ContainerNetworkConfig.StaticIP
|
||||
infraConfig.NoManageResolvConf = infra.Config().UseImageResolvConf
|
||||
infraConfig.NoManageHosts = infra.Config().UseImageHosts
|
||||
infraConfig.CPUPeriod = p.CPUPeriod()
|
||||
infraConfig.CPUQuota = p.CPUQuota()
|
||||
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
|
||||
infraConfig.PidNS = p.PidMode()
|
||||
infraConfig.UserNS = p.config.InfraContainer.Userns.String()
|
||||
infraConfig.UserNS = p.UserNSMode()
|
||||
|
||||
if len(p.config.InfraContainer.DNSServer) > 0 {
|
||||
infraConfig.DNSServer = make([]string, 0, len(p.config.InfraContainer.DNSServer))
|
||||
infraConfig.DNSServer = append(infraConfig.DNSServer, p.config.InfraContainer.DNSServer...)
|
||||
if len(infra.Config().ContainerNetworkConfig.DNSServer) > 0 {
|
||||
infraConfig.DNSServer = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSServer))
|
||||
for _, entry := range infra.Config().ContainerNetworkConfig.DNSServer {
|
||||
infraConfig.DNSServer = append(infraConfig.DNSServer, entry.String())
|
||||
}
|
||||
}
|
||||
if len(p.config.InfraContainer.DNSSearch) > 0 {
|
||||
infraConfig.DNSSearch = make([]string, 0, len(p.config.InfraContainer.DNSSearch))
|
||||
infraConfig.DNSSearch = append(infraConfig.DNSSearch, p.config.InfraContainer.DNSSearch...)
|
||||
if len(infra.Config().ContainerNetworkConfig.DNSSearch) > 0 {
|
||||
infraConfig.DNSSearch = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSSearch))
|
||||
infraConfig.DNSSearch = append(infraConfig.DNSSearch, infra.Config().ContainerNetworkConfig.DNSSearch...)
|
||||
}
|
||||
if len(p.config.InfraContainer.DNSOption) > 0 {
|
||||
infraConfig.DNSOption = make([]string, 0, len(p.config.InfraContainer.DNSOption))
|
||||
infraConfig.DNSOption = append(infraConfig.DNSOption, p.config.InfraContainer.DNSOption...)
|
||||
if len(infra.Config().ContainerNetworkConfig.DNSOption) > 0 {
|
||||
infraConfig.DNSOption = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSOption))
|
||||
infraConfig.DNSOption = append(infraConfig.DNSOption, infra.Config().ContainerNetworkConfig.DNSOption...)
|
||||
}
|
||||
if len(p.config.InfraContainer.HostAdd) > 0 {
|
||||
infraConfig.HostAdd = make([]string, 0, len(p.config.InfraContainer.HostAdd))
|
||||
infraConfig.HostAdd = append(infraConfig.HostAdd, p.config.InfraContainer.HostAdd...)
|
||||
if len(infra.Config().HostAdd) > 0 {
|
||||
infraConfig.HostAdd = make([]string, 0, len(infra.Config().HostAdd))
|
||||
infraConfig.HostAdd = append(infraConfig.HostAdd, infra.Config().HostAdd...)
|
||||
}
|
||||
if len(p.config.InfraContainer.Networks) > 0 {
|
||||
infraConfig.Networks = make([]string, 0, len(p.config.InfraContainer.Networks))
|
||||
infraConfig.Networks = append(infraConfig.Networks, p.config.InfraContainer.Networks...)
|
||||
if len(infra.Config().ContainerNetworkConfig.Networks) > 0 {
|
||||
infraConfig.Networks = make([]string, 0, len(infra.Config().ContainerNetworkConfig.Networks))
|
||||
infraConfig.Networks = append(infraConfig.Networks, infra.Config().ContainerNetworkConfig.Networks...)
|
||||
}
|
||||
infraConfig.NetworkOptions = p.config.InfraContainer.NetworkOptions
|
||||
infraConfig.PortBindings = makeInspectPortBindings(p.config.InfraContainer.PortBindings, nil)
|
||||
infraConfig.NetworkOptions = infra.Config().ContainerNetworkConfig.NetworkOptions
|
||||
infraConfig.PortBindings = makeInspectPortBindings(infra.Config().ContainerNetworkConfig.PortMappings, nil)
|
||||
}
|
||||
|
||||
inspectData := define.InspectPodData{
|
||||
|
@ -20,7 +20,7 @@ func newPod(runtime *Runtime) *Pod {
|
||||
pod.config.ID = stringid.GenerateNonCryptoID()
|
||||
pod.config.Labels = make(map[string]string)
|
||||
pod.config.CreatedTime = time.Now()
|
||||
pod.config.InfraContainer = new(InfraContainerConfig)
|
||||
// pod.config.InfraContainer = new(ContainerConfig)
|
||||
pod.state = new(podState)
|
||||
pod.runtime = runtime
|
||||
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/containers/podman/v3/pkg/cgroups"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities/reports"
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/stringid"
|
||||
"github.com/docker/go-units"
|
||||
@ -38,12 +39,15 @@ type CtrCreateOption func(*Container) error
|
||||
type ContainerFilter func(*Container) bool
|
||||
|
||||
// NewContainer creates a new container from a given OCI config.
|
||||
func (r *Runtime) NewContainer(ctx context.Context, rSpec *spec.Spec, options ...CtrCreateOption) (*Container, error) {
|
||||
func (r *Runtime) NewContainer(ctx context.Context, rSpec *spec.Spec, spec *specgen.SpecGenerator, infra bool, options ...CtrCreateOption) (*Container, error) {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
if !r.valid {
|
||||
return nil, define.ErrRuntimeStopped
|
||||
}
|
||||
if infra {
|
||||
options = append(options, withIsInfra())
|
||||
}
|
||||
return r.newContainer(ctx, rSpec, options...)
|
||||
}
|
||||
|
||||
@ -172,6 +176,7 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf
|
||||
}
|
||||
ctr.config.ShmSize = size
|
||||
ctr.config.StopSignal = 15
|
||||
|
||||
ctr.config.StopTimeout = r.config.Engine.StopTimeout
|
||||
} else {
|
||||
// This is a restore from an imported checkpoint
|
||||
@ -211,7 +216,11 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf
|
||||
}
|
||||
|
||||
func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ...CtrCreateOption) (*Container, error) {
|
||||
ctr, err := r.initContainerVariables(rSpec, nil)
|
||||
var ctr *Container
|
||||
var err error
|
||||
|
||||
ctr, err = r.initContainerVariables(rSpec, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error initializing container variables")
|
||||
}
|
||||
@ -230,7 +239,9 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
|
||||
if err := ctr.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ctr.config.IsInfra {
|
||||
ctr.config.StopTimeout = 10
|
||||
}
|
||||
// normalize the networks to names
|
||||
// ocicni only knows about cni names so we have to make
|
||||
// sure we do not use ids internally
|
||||
@ -327,7 +338,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
|
||||
switch r.config.Engine.CgroupManager {
|
||||
case config.CgroupfsCgroupsManager:
|
||||
if ctr.config.CgroupParent == "" {
|
||||
if pod != nil && pod.config.UsePodCgroup {
|
||||
if pod != nil && pod.config.UsePodCgroup && !ctr.IsInfra() {
|
||||
podCgroup, err := pod.CgroupPath()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error retrieving pod %s cgroup", pod.ID())
|
||||
@ -348,7 +359,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
|
||||
case config.SystemdCgroupsManager:
|
||||
if ctr.config.CgroupParent == "" {
|
||||
switch {
|
||||
case pod != nil && pod.config.UsePodCgroup:
|
||||
case pod != nil && pod.config.UsePodCgroup && !ctr.IsInfra():
|
||||
podCgroup, err := pod.CgroupPath()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error retrieving pod %s cgroup", pod.ID())
|
||||
@ -833,7 +844,10 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol
|
||||
return id, err
|
||||
}
|
||||
|
||||
infraID := pod.state.InfraContainerID
|
||||
infraID, err := pod.infraContainerID()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if c.ID() == infraID {
|
||||
return id, errors.Errorf("container %s is the infra container of pod %s and cannot be removed without removing the pod", c.ID(), pod.ID())
|
||||
}
|
||||
|
@ -1,284 +0,0 @@
|
||||
// +build linux
|
||||
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/namespaces"
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
// IDTruncLength is the length of the pod's id that will be used to make the
|
||||
// infra container name
|
||||
IDTruncLength = 12
|
||||
)
|
||||
|
||||
func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawImageName, imgID string, config *v1.ImageConfig) (*Container, error) {
|
||||
// Set up generator for infra container defaults
|
||||
g, err := generate.New("linux")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set Pod hostname
|
||||
g.Config.Hostname = p.config.Hostname
|
||||
|
||||
var options []CtrCreateOption
|
||||
|
||||
// Command: If user-specified, use that preferentially.
|
||||
// If not set and the config file is set, fall back to that.
|
||||
var infraCtrCommand []string
|
||||
if p.config.InfraContainer.InfraCommand != nil {
|
||||
logrus.Debugf("User-specified infra container entrypoint %v", p.config.InfraContainer.InfraCommand)
|
||||
infraCtrCommand = p.config.InfraContainer.InfraCommand
|
||||
} else if r.config.Engine.InfraCommand != "" {
|
||||
logrus.Debugf("Config-specified infra container entrypoint %s", r.config.Engine.InfraCommand)
|
||||
infraCtrCommand = []string{r.config.Engine.InfraCommand}
|
||||
}
|
||||
// Only if set by the user or containers.conf, we set entrypoint for the
|
||||
// infra container.
|
||||
// This is only used by commit, so it shouldn't matter... But someone
|
||||
// may eventually want to commit an infra container?
|
||||
// TODO: Should we actually do this if set by containers.conf?
|
||||
if infraCtrCommand != nil {
|
||||
// Need to duplicate the array - we are going to add Cmd later
|
||||
// so the current array will be changed.
|
||||
newArr := make([]string, 0, len(infraCtrCommand))
|
||||
newArr = append(newArr, infraCtrCommand...)
|
||||
options = append(options, WithEntrypoint(newArr))
|
||||
}
|
||||
|
||||
isRootless := rootless.IsRootless()
|
||||
|
||||
// I've seen circumstances where config is being passed as nil.
|
||||
// Let's err on the side of safety and make sure it's safe to use.
|
||||
if config != nil {
|
||||
if infraCtrCommand == nil {
|
||||
// If we have no entrypoint and command from the image,
|
||||
// we can't go on - the infra container has no command.
|
||||
if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 {
|
||||
return nil, errors.Errorf("infra container has no command")
|
||||
}
|
||||
if len(config.Entrypoint) > 0 {
|
||||
infraCtrCommand = config.Entrypoint
|
||||
} else {
|
||||
// Use the Docker default "/bin/sh -c"
|
||||
// entrypoint, as we're overriding command.
|
||||
// If an image doesn't want this, it can
|
||||
// override entrypoint too.
|
||||
infraCtrCommand = []string{"/bin/sh", "-c"}
|
||||
}
|
||||
}
|
||||
if len(config.Cmd) > 0 {
|
||||
infraCtrCommand = append(infraCtrCommand, config.Cmd...)
|
||||
}
|
||||
|
||||
if len(config.Env) > 0 {
|
||||
for _, nameValPair := range config.Env {
|
||||
nameValSlice := strings.Split(nameValPair, "=")
|
||||
if len(nameValSlice) < 2 {
|
||||
return nil, errors.Errorf("Invalid environment variable structure in pause image")
|
||||
}
|
||||
g.AddProcessEnv(nameValSlice[0], nameValSlice[1])
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case p.config.InfraContainer.HostNetwork:
|
||||
if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
|
||||
return nil, errors.Wrapf(err, "error removing network namespace from pod %s infra container", p.ID())
|
||||
}
|
||||
case p.config.InfraContainer.NoNetwork:
|
||||
// Do nothing - we have a network namespace by default,
|
||||
// but should not configure slirp.
|
||||
default:
|
||||
// Since user namespace sharing is not implemented, we only need to check if it's rootless
|
||||
netmode := "bridge"
|
||||
if p.config.InfraContainer.Slirp4netns {
|
||||
netmode = "slirp4netns"
|
||||
if len(p.config.InfraContainer.NetworkOptions) != 0 {
|
||||
options = append(options, WithNetworkOptions(p.config.InfraContainer.NetworkOptions))
|
||||
}
|
||||
}
|
||||
// FIXME allow pods to have exposed ports
|
||||
options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, nil, !p.config.InfraContainer.Userns.IsHost(), netmode, p.config.InfraContainer.Networks))
|
||||
}
|
||||
|
||||
// For each option in InfraContainerConfig - if set, pass into
|
||||
// the infra container we're creating with the appropriate
|
||||
// With... option.
|
||||
if p.config.InfraContainer.StaticIP != nil {
|
||||
options = append(options, WithStaticIP(p.config.InfraContainer.StaticIP))
|
||||
}
|
||||
if p.config.InfraContainer.StaticMAC != nil {
|
||||
options = append(options, WithStaticMAC(p.config.InfraContainer.StaticMAC))
|
||||
}
|
||||
if p.config.InfraContainer.UseImageResolvConf {
|
||||
options = append(options, WithUseImageResolvConf())
|
||||
}
|
||||
if len(p.config.InfraContainer.DNSServer) > 0 {
|
||||
options = append(options, WithDNS(p.config.InfraContainer.DNSServer))
|
||||
}
|
||||
if len(p.config.InfraContainer.DNSSearch) > 0 {
|
||||
options = append(options, WithDNSSearch(p.config.InfraContainer.DNSSearch))
|
||||
}
|
||||
if len(p.config.InfraContainer.DNSOption) > 0 {
|
||||
options = append(options, WithDNSOption(p.config.InfraContainer.DNSOption))
|
||||
}
|
||||
if p.config.InfraContainer.UseImageHosts {
|
||||
options = append(options, WithUseImageHosts())
|
||||
}
|
||||
if len(p.config.InfraContainer.HostAdd) > 0 {
|
||||
options = append(options, WithHosts(p.config.InfraContainer.HostAdd))
|
||||
}
|
||||
if len(p.config.InfraContainer.ExitCommand) > 0 {
|
||||
options = append(options, WithExitCommand(p.config.InfraContainer.ExitCommand))
|
||||
}
|
||||
|
||||
if p.config.UsePodPID && p.config.InfraContainer.PidNS.NSMode != "host" {
|
||||
g.AddOrReplaceLinuxNamespace(string(spec.LinuxNamespaceType("pid")), p.config.InfraContainer.PidNS.Value)
|
||||
} else if p.config.InfraContainer.PidNS.NSMode == "host" {
|
||||
newNS := []spec.LinuxNamespace{}
|
||||
for _, entry := range g.Config.Linux.Namespaces {
|
||||
if entry.Type != spec.LinuxNamespaceType("pid") {
|
||||
newNS = append(newNS, entry)
|
||||
}
|
||||
}
|
||||
g.Config.Linux.Namespaces = newNS
|
||||
}
|
||||
}
|
||||
|
||||
for _, ctl := range r.config.Containers.DefaultSysctls {
|
||||
sysctl := strings.SplitN(ctl, "=", 2)
|
||||
if len(sysctl) < 2 {
|
||||
return nil, errors.Errorf("invalid default sysctl %s", ctl)
|
||||
}
|
||||
|
||||
// Ignore net sysctls if --net=host
|
||||
if p.config.InfraContainer.HostNetwork && strings.HasPrefix(sysctl[0], "net.") {
|
||||
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since Network Namespace set to host", sysctl[0], sysctl[1])
|
||||
continue
|
||||
}
|
||||
|
||||
g.AddLinuxSysctl(sysctl[0], sysctl[1])
|
||||
}
|
||||
|
||||
g.SetRootReadonly(true)
|
||||
g.SetProcessArgs(infraCtrCommand)
|
||||
|
||||
logrus.Debugf("Using %q as infra container command", infraCtrCommand)
|
||||
|
||||
mapopt, err := util.ParseIDMapping(namespaces.UsernsMode(p.config.InfraContainer.Userns.String()), []string{}, []string{}, "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user, err := specgen.SetupUserNS(mapopt, p.config.InfraContainer.Userns, &g)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user != "" {
|
||||
options = append(options, WithUser(user))
|
||||
}
|
||||
|
||||
g.RemoveMount("/dev/shm")
|
||||
if isRootless {
|
||||
g.RemoveMount("/dev/pts")
|
||||
devPts := spec.Mount{
|
||||
Destination: "/dev/pts",
|
||||
Type: "devpts",
|
||||
Source: "devpts",
|
||||
Options: []string{"private", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"},
|
||||
}
|
||||
g.AddMount(devPts)
|
||||
}
|
||||
|
||||
// Add default sysctls from containers.conf
|
||||
defaultSysctls, err := util.ValidateSysctls(r.config.Sysctls())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for sysctlKey, sysctlVal := range defaultSysctls {
|
||||
// Ignore mqueue sysctls if not sharing IPC
|
||||
if !p.config.UsePodIPC && strings.HasPrefix(sysctlKey, "fs.mqueue.") {
|
||||
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since IPC Namespace for pod is unused", sysctlKey, sysctlVal)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ignore net sysctls if host network or not sharing network
|
||||
if (p.config.InfraContainer.HostNetwork || !p.config.UsePodNet) && strings.HasPrefix(sysctlKey, "net.") {
|
||||
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since Network Namespace for pod is unused", sysctlKey, sysctlVal)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ignore uts sysctls if not sharing UTS
|
||||
if !p.config.UsePodUTS && (strings.HasPrefix(sysctlKey, "kernel.domainname") || strings.HasPrefix(sysctlKey, "kernel.hostname")) {
|
||||
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since UTS Namespace for pod is unused", sysctlKey, sysctlVal)
|
||||
continue
|
||||
}
|
||||
g.AddLinuxSysctl(sysctlKey, sysctlVal)
|
||||
}
|
||||
|
||||
containerName := p.config.InfraContainer.InfraName
|
||||
if containerName == "" {
|
||||
containerName = p.ID()[:IDTruncLength] + "-infra"
|
||||
}
|
||||
logrus.Infof("Infra container name %s", containerName)
|
||||
options = append(options, r.WithPod(p))
|
||||
options = append(options, WithRootFSFromImage(imgID, imgName, rawImageName))
|
||||
options = append(options, WithName(containerName))
|
||||
options = append(options, withIsInfra())
|
||||
options = append(options, WithIDMappings(*mapopt))
|
||||
if len(p.config.InfraContainer.ConmonPidFile) > 0 {
|
||||
options = append(options, WithConmonPidFile(p.config.InfraContainer.ConmonPidFile))
|
||||
}
|
||||
newRes := new(spec.LinuxResources)
|
||||
newRes.CPU = new(spec.LinuxCPU)
|
||||
newRes.CPU = p.ResourceLim().CPU
|
||||
g.Config.Linux.Resources.CPU = newRes.CPU
|
||||
|
||||
return r.newContainer(ctx, g.Config, options...)
|
||||
}
|
||||
|
||||
// createInfraContainer wrap creates an infra container for a pod.
|
||||
// An infra container becomes the basis for kernel namespace sharing between
|
||||
// containers in the pod.
|
||||
func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container, error) {
|
||||
if !r.valid {
|
||||
return nil, define.ErrRuntimeStopped
|
||||
}
|
||||
imageName := p.config.InfraContainer.InfraImage
|
||||
if imageName == "" {
|
||||
imageName = r.config.Engine.InfraImage
|
||||
}
|
||||
|
||||
pulledImages, err := r.LibimageRuntime().Pull(ctx, imageName, config.PullPolicyMissing, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error pulling infra-container image")
|
||||
}
|
||||
|
||||
newImage := pulledImages[0]
|
||||
data, err := newImage.Inspect(ctx, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imageName = "none"
|
||||
if len(newImage.Names()) > 0 {
|
||||
imageName = newImage.Names()[0]
|
||||
}
|
||||
imageID := data.ID
|
||||
|
||||
return r.makeInfraContainer(ctx, p, imageName, r.config.Engine.InfraImage, imageID, data.Config)
|
||||
}
|
@ -14,13 +14,14 @@ import (
|
||||
"github.com/containers/podman/v3/libpod/events"
|
||||
"github.com/containers/podman/v3/pkg/cgroups"
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NewPod makes a new, empty pod
|
||||
func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Pod, deferredErr error) {
|
||||
func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, options ...PodCreateOption) (_ *Pod, deferredErr error) {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
@ -50,8 +51,8 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
|
||||
pod.config.Name = name
|
||||
}
|
||||
|
||||
if pod.config.Hostname == "" {
|
||||
pod.config.Hostname = pod.config.Name
|
||||
if p.InfraContainerSpec != nil && p.InfraContainerSpec.Hostname == "" {
|
||||
p.InfraContainerSpec.Hostname = pod.config.Name
|
||||
}
|
||||
|
||||
// Allocate a lock for the pod
|
||||
@ -88,6 +89,9 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
|
||||
// launch should do it for us
|
||||
if pod.config.UsePodCgroup {
|
||||
pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
|
||||
if p.InfraContainerSpec != nil {
|
||||
p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
|
||||
}
|
||||
}
|
||||
}
|
||||
case config.SystemdCgroupsManager:
|
||||
@ -108,6 +112,9 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
|
||||
return nil, errors.Wrapf(err, "unable to create pod cgroup for pod %s", pod.ID())
|
||||
}
|
||||
pod.state.CgroupPath = cgroupPath
|
||||
if p.InfraContainerSpec != nil {
|
||||
p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager)
|
||||
@ -127,28 +134,40 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
|
||||
if err := r.state.AddPod(pod); err != nil {
|
||||
return nil, errors.Wrapf(err, "error adding pod to state")
|
||||
}
|
||||
defer func() {
|
||||
if deferredErr != nil {
|
||||
if err := r.removePod(ctx, pod, true, true); err != nil {
|
||||
logrus.Errorf("Error removing pod after pause container creation failure: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return pod, nil
|
||||
}
|
||||
|
||||
if pod.HasInfraContainer() {
|
||||
ctr, err := r.createInfraContainer(ctx, pod)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error adding Infra Container")
|
||||
}
|
||||
pod.state.InfraContainerID = ctr.ID()
|
||||
if err := pod.save(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// AddInfra adds the created infra container to the pod state
|
||||
func (r *Runtime) AddInfra(ctx context.Context, pod *Pod, infraCtr *Container) (*Pod, error) {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
if !r.valid {
|
||||
return nil, define.ErrRuntimeStopped
|
||||
}
|
||||
pod.state.InfraContainerID = infraCtr.ID()
|
||||
if err := pod.save(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pod.newPodEvent(events.Create)
|
||||
return pod, nil
|
||||
}
|
||||
|
||||
// SavePod is a helper function to save the pod state from outside of libpod
|
||||
func (r *Runtime) SavePod(pod *Pod) error {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
if !r.valid {
|
||||
return define.ErrRuntimeStopped
|
||||
}
|
||||
if err := pod.save(); err != nil {
|
||||
return err
|
||||
}
|
||||
pod.newPodEvent(events.Create)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) error {
|
||||
if err := p.updatePod(); err != nil {
|
||||
return err
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/domain/infra/abi"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/containers/storage"
|
||||
"github.com/gorilla/schema"
|
||||
"github.com/pkg/errors"
|
||||
@ -80,7 +81,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
sg := specgen.NewSpecGenerator(imgNameOrID, cliOpts.RootFS)
|
||||
if err := common.FillOutSpecGen(sg, cliOpts, args); err != nil {
|
||||
if err := specgenutil.FillOutSpecGen(sg, cliOpts, args); err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "fill out specgen"))
|
||||
return
|
||||
}
|
||||
|
@ -28,7 +28,12 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
ctr, err := generate.MakeContainer(context.Background(), runtime, &sg)
|
||||
rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), runtime, &sg)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
ctr, err := generate.ExecuteCreate(context.Background(), runtime, rtSpec, spec, false, opts...)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
|
@ -1,11 +1,15 @@
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/libimage"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/podman/v3/libpod"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/api/handlers"
|
||||
@ -14,6 +18,7 @@ import (
|
||||
"github.com/containers/podman/v3/pkg/domain/infra/abi"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgen/generate"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
"github.com/gorilla/schema"
|
||||
"github.com/pkg/errors"
|
||||
@ -25,24 +30,70 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
|
||||
runtime = r.Context().Value("runtime").(*libpod.Runtime)
|
||||
err error
|
||||
)
|
||||
var psg specgen.PodSpecGenerator
|
||||
psg := specgen.PodSpecGenerator{InfraContainerSpec: &specgen.SpecGenerator{}}
|
||||
if err := json.NewDecoder(r.Body).Decode(&psg); err != nil {
|
||||
utils.Error(w, "failed to decode specgen", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
|
||||
return
|
||||
}
|
||||
// parse userns so we get the valid default value of userns
|
||||
psg.Userns, err = specgen.ParseUserNamespace(psg.Userns.String())
|
||||
if err != nil {
|
||||
utils.Error(w, "failed to parse userns", http.StatusInternalServerError, errors.Wrap(err, "failed to parse userns"))
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
|
||||
return
|
||||
}
|
||||
pod, err := generate.MakePod(&psg, runtime)
|
||||
if !psg.NoInfra {
|
||||
infraOptions := &entities.ContainerCreateOptions{ImageVolume: "bind", IsInfra: true, Net: &entities.NetOptions{}} // options for pulling the image and FillOutSpec
|
||||
err = specgenutil.FillOutSpecGen(psg.InfraContainerSpec, infraOptions, []string{}) // necessary for default values in many cases (userns, idmappings)
|
||||
if err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error filling out specgen"))
|
||||
return
|
||||
}
|
||||
out, err := json.Marshal(psg) // marshal our spec so the matching options can be unmarshaled into infra
|
||||
if err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
|
||||
return
|
||||
}
|
||||
tempSpec := &specgen.SpecGenerator{} // temporary spec since infra cannot be decoded into
|
||||
err = json.Unmarshal(out, tempSpec) // unmarhal matching options
|
||||
if err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
|
||||
return
|
||||
}
|
||||
psg.InfraContainerSpec = tempSpec // set infra spec equal to temp
|
||||
// a few extra that do not have the same json tags
|
||||
psg.InfraContainerSpec.Name = psg.InfraName
|
||||
psg.InfraContainerSpec.ConmonPidFile = psg.InfraConmonPidFile
|
||||
psg.InfraContainerSpec.ContainerCreateCommand = psg.InfraCommand
|
||||
imageName := psg.InfraImage
|
||||
rawImageName := psg.InfraImage
|
||||
if imageName == "" {
|
||||
imageName = config.DefaultInfraImage
|
||||
rawImageName = config.DefaultInfraImage
|
||||
}
|
||||
curr := infraOptions.Quiet
|
||||
infraOptions.Quiet = true
|
||||
pullOptions := &libimage.PullOptions{}
|
||||
pulledImages, err := runtime.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, pullOptions)
|
||||
if err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "could not pull image"))
|
||||
return
|
||||
}
|
||||
if _, err := alltransports.ParseImageName(imageName); err == nil {
|
||||
if len(pulledImages) != 0 {
|
||||
imageName = pulledImages[0].ID()
|
||||
}
|
||||
}
|
||||
infraOptions.Quiet = curr
|
||||
psg.InfraImage = imageName
|
||||
psg.InfraContainerSpec.Image = imageName
|
||||
psg.InfraContainerSpec.RawImageName = rawImageName
|
||||
}
|
||||
podSpecComplete := entities.PodSpec{PodSpecGen: psg}
|
||||
pod, err := generate.MakePod(&podSpecComplete, runtime)
|
||||
if err != nil {
|
||||
httpCode := http.StatusInternalServerError
|
||||
if errors.Cause(err) == define.ErrPodExists {
|
||||
httpCode = http.StatusConflict
|
||||
}
|
||||
utils.Error(w, "Something went wrong.", httpCode, err)
|
||||
utils.Error(w, "Something went wrong.", httpCode, errors.Wrap(err, "failed to make pod"))
|
||||
return
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.ID()})
|
||||
|
@ -1,8 +1,6 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
)
|
||||
import "github.com/containers/podman/v3/pkg/domain/entities"
|
||||
|
||||
// LibpodImagesRemoveReport is the return type for image removal via the rest
|
||||
// api.
|
||||
|
@ -9,27 +9,25 @@ import (
|
||||
"github.com/containers/podman/v3/pkg/api/handlers"
|
||||
"github.com/containers/podman/v3/pkg/bindings"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
func CreatePodFromSpec(ctx context.Context, s *specgen.PodSpecGenerator, options *CreateOptions) (*entities.PodCreateReport, error) {
|
||||
func CreatePodFromSpec(ctx context.Context, spec *entities.PodSpec) (*entities.PodCreateReport, error) {
|
||||
var (
|
||||
pcr entities.PodCreateReport
|
||||
)
|
||||
if options == nil {
|
||||
options = new(CreateOptions)
|
||||
if spec == nil {
|
||||
spec = new(entities.PodSpec)
|
||||
}
|
||||
_ = options
|
||||
conn, err := bindings.GetClient(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
specgenString, err := jsoniter.MarshalToString(s)
|
||||
specString, err := jsoniter.MarshalToString(spec.PodSpecGen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stringReader := strings.NewReader(specgenString)
|
||||
stringReader := strings.NewReader(specString)
|
||||
response, err := conn.DoRequest(stringReader, http.MethodPost, "/pods/create", nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/bindings"
|
||||
"github.com/containers/podman/v3/pkg/bindings/pods"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
@ -333,9 +334,9 @@ var _ = Describe("Podman pods", func() {
|
||||
})
|
||||
|
||||
It("simple create pod", func() {
|
||||
ps := specgen.PodSpecGenerator{}
|
||||
ps.Name = "foobar"
|
||||
_, err := pods.CreatePodFromSpec(bt.conn, &ps, nil)
|
||||
ps := entities.PodSpec{PodSpecGen: specgen.PodSpecGenerator{InfraContainerSpec: &specgen.SpecGenerator{}}}
|
||||
ps.PodSpecGen.Name = "foobar"
|
||||
_, err := pods.CreatePodFromSpec(bt.conn, &ps)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
exists, err := pods.Exists(bt.conn, "foobar", nil)
|
||||
|
@ -68,7 +68,7 @@ type ContainerEngine interface {
|
||||
NetworkRm(ctx context.Context, namesOrIds []string, options NetworkRmOptions) ([]*NetworkRmReport, error)
|
||||
PlayKube(ctx context.Context, path string, opts PlayKubeOptions) (*PlayKubeReport, error)
|
||||
PlayKubeDown(ctx context.Context, path string, opts PlayKubeDownOptions) (*PlayKubeReport, error)
|
||||
PodCreate(ctx context.Context, opts PodCreateOptions) (*PodCreateReport, error)
|
||||
PodCreate(ctx context.Context, specg PodSpec) (*PodCreateReport, error)
|
||||
PodExists(ctx context.Context, nameOrID string) (*BoolReport, error)
|
||||
PodInspect(ctx context.Context, options PodInspectOptions) (*PodInspectReport, error)
|
||||
PodKill(ctx context.Context, namesOrIds []string, options PodKillOptions) ([]*PodKillReport, error)
|
||||
|
@ -106,6 +106,14 @@ type PodRmReport struct {
|
||||
Id string //nolint
|
||||
}
|
||||
|
||||
// PddSpec is an abstracted version of PodSpecGen designed to eventually accept options
|
||||
// not meant to be in a specgen
|
||||
type PodSpec struct {
|
||||
PodSpecGen specgen.PodSpecGenerator
|
||||
}
|
||||
|
||||
// PodCreateOptions provides all possible options for creating a pod and its infra container
|
||||
// swagger:model PodCreateOptions
|
||||
type PodCreateOptions struct {
|
||||
CGroupParent string
|
||||
CreateCommand []string
|
||||
@ -125,6 +133,123 @@ type PodCreateOptions struct {
|
||||
Userns specgen.Namespace
|
||||
}
|
||||
|
||||
type ContainerCreateOptions struct {
|
||||
Annotation []string
|
||||
Attach []string
|
||||
Authfile string
|
||||
BlkIOWeight string
|
||||
BlkIOWeightDevice []string
|
||||
CapAdd []string
|
||||
CapDrop []string
|
||||
CgroupNS string
|
||||
CGroupsMode string
|
||||
CGroupParent string
|
||||
CIDFile string
|
||||
ConmonPIDFile string
|
||||
CPUPeriod uint64
|
||||
CPUQuota int64
|
||||
CPURTPeriod uint64
|
||||
CPURTRuntime int64
|
||||
CPUShares uint64
|
||||
CPUS float64
|
||||
CPUSetCPUs string
|
||||
CPUSetMems string
|
||||
Devices []string
|
||||
DeviceCGroupRule []string
|
||||
DeviceReadBPs []string
|
||||
DeviceReadIOPs []string
|
||||
DeviceWriteBPs []string
|
||||
DeviceWriteIOPs []string
|
||||
Entrypoint *string
|
||||
Env []string
|
||||
EnvHost bool
|
||||
EnvFile []string
|
||||
Expose []string
|
||||
GIDMap []string
|
||||
GroupAdd []string
|
||||
HealthCmd string
|
||||
HealthInterval string
|
||||
HealthRetries uint
|
||||
HealthStartPeriod string
|
||||
HealthTimeout string
|
||||
Hostname string
|
||||
HTTPProxy bool
|
||||
ImageVolume string
|
||||
Init bool
|
||||
InitContainerType string
|
||||
InitPath string
|
||||
Interactive bool
|
||||
IPC string
|
||||
KernelMemory string
|
||||
Label []string
|
||||
LabelFile []string
|
||||
LogDriver string
|
||||
LogOptions []string
|
||||
Memory string
|
||||
MemoryReservation string
|
||||
MemorySwap string
|
||||
MemorySwappiness int64
|
||||
Name string
|
||||
NoHealthCheck bool
|
||||
OOMKillDisable bool
|
||||
OOMScoreAdj int
|
||||
Arch string
|
||||
OS string
|
||||
Variant string
|
||||
PID string
|
||||
PIDsLimit *int64
|
||||
Platform string
|
||||
Pod string
|
||||
PodIDFile string
|
||||
Personality string
|
||||
PreserveFDs uint
|
||||
Privileged bool
|
||||
PublishAll bool
|
||||
Pull string
|
||||
Quiet bool
|
||||
ReadOnly bool
|
||||
ReadOnlyTmpFS bool
|
||||
Restart string
|
||||
Replace bool
|
||||
Requires []string
|
||||
Rm bool
|
||||
RootFS bool
|
||||
Secrets []string
|
||||
SecurityOpt []string
|
||||
SdNotifyMode string
|
||||
ShmSize string
|
||||
SignaturePolicy string
|
||||
StopSignal string
|
||||
StopTimeout uint
|
||||
StorageOpt []string
|
||||
SubUIDName string
|
||||
SubGIDName string
|
||||
Sysctl []string
|
||||
Systemd string
|
||||
Timeout uint
|
||||
TLSVerify bool
|
||||
TmpFS []string
|
||||
TTY bool
|
||||
Timezone string
|
||||
Umask string
|
||||
UIDMap []string
|
||||
Ulimit []string
|
||||
User string
|
||||
UserNS string
|
||||
UTS string
|
||||
Mount []string
|
||||
Volume []string
|
||||
VolumesFrom []string
|
||||
Workdir string
|
||||
SeccompPolicy string
|
||||
PidFile string
|
||||
IsInfra bool
|
||||
|
||||
Net *NetOptions
|
||||
|
||||
CgroupConf []string
|
||||
}
|
||||
|
||||
type PodCreateReport struct {
|
||||
Id string //nolint
|
||||
}
|
||||
@ -149,21 +274,15 @@ func (p *PodCreateOptions) CPULimits() *specs.LinuxCPU {
|
||||
return cpu
|
||||
}
|
||||
|
||||
func setNamespaces(p *PodCreateOptions) ([4]specgen.Namespace, error) {
|
||||
allNS := [4]specgen.Namespace{}
|
||||
if p.Pid != "" {
|
||||
pid, err := specgen.ParseNamespace(p.Pid)
|
||||
if err != nil {
|
||||
return [4]specgen.Namespace{}, err
|
||||
}
|
||||
allNS[0] = pid
|
||||
}
|
||||
return allNS, nil
|
||||
}
|
||||
|
||||
func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
|
||||
func ToPodSpecGen(s specgen.PodSpecGenerator, p *PodCreateOptions) (*specgen.PodSpecGenerator, error) {
|
||||
// Basic Config
|
||||
s.Name = p.Name
|
||||
s.InfraName = p.InfraName
|
||||
out, err := specgen.ParseNamespace(p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.Pid = out
|
||||
s.Hostname = p.Hostname
|
||||
s.Labels = p.Labels
|
||||
s.NoInfra = !p.Infra
|
||||
@ -174,32 +293,26 @@ func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
|
||||
s.InfraConmonPidFile = p.InfraConmonPidFile
|
||||
}
|
||||
s.InfraImage = p.InfraImage
|
||||
s.InfraName = p.InfraName
|
||||
s.SharedNamespaces = p.Share
|
||||
s.PodCreateCommand = p.CreateCommand
|
||||
|
||||
// Networking config
|
||||
s.NetNS = p.Net.Network
|
||||
s.StaticIP = p.Net.StaticIP
|
||||
s.StaticMAC = p.Net.StaticMAC
|
||||
s.PortMappings = p.Net.PublishPorts
|
||||
s.CNINetworks = p.Net.CNINetworks
|
||||
s.NetworkOptions = p.Net.NetworkOptions
|
||||
if p.Net.UseImageResolvConf {
|
||||
s.NoManageResolvConf = true
|
||||
}
|
||||
s.DNSServer = p.Net.DNSServers
|
||||
s.DNSSearch = p.Net.DNSSearch
|
||||
s.DNSOption = p.Net.DNSOptions
|
||||
s.NoManageHosts = p.Net.NoHosts
|
||||
s.HostAdd = p.Net.AddHosts
|
||||
|
||||
namespaces, err := setNamespaces(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !namespaces[0].IsDefault() {
|
||||
s.Pid = namespaces[0]
|
||||
if p.Net != nil {
|
||||
s.NetNS = p.Net.Network
|
||||
s.StaticIP = p.Net.StaticIP
|
||||
s.StaticMAC = p.Net.StaticMAC
|
||||
s.PortMappings = p.Net.PublishPorts
|
||||
s.CNINetworks = p.Net.CNINetworks
|
||||
s.NetworkOptions = p.Net.NetworkOptions
|
||||
if p.Net.UseImageResolvConf {
|
||||
s.NoManageResolvConf = true
|
||||
}
|
||||
s.DNSServer = p.Net.DNSServers
|
||||
s.DNSSearch = p.Net.DNSSearch
|
||||
s.DNSOption = p.Net.DNSOptions
|
||||
s.NoManageHosts = p.Net.NoHosts
|
||||
s.HostAdd = p.Net.AddHosts
|
||||
}
|
||||
|
||||
// Cgroup
|
||||
@ -219,7 +332,7 @@ func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
|
||||
}
|
||||
}
|
||||
s.Userns = p.Userns
|
||||
return nil
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
type PodPruneOptions struct {
|
||||
|
@ -31,21 +31,33 @@ type VolumeDeleteReport struct{ Report }
|
||||
|
||||
// NetOptions reflect the shared network options between
|
||||
// pods and containers
|
||||
type NetFlags struct {
|
||||
AddHosts []string `json:"add-host,omitempty"`
|
||||
DNS []string `json:"dns,omitempty"`
|
||||
DNSOpt []string `json:"dns-opt,omitempty"`
|
||||
DNDSearch []string `json:"dns-search,omitempty"`
|
||||
MacAddr string `json:"mac-address,omitempty"`
|
||||
Publish []string `json:"publish,omitempty"`
|
||||
IP string `json:"ip,omitempty"`
|
||||
NoHosts bool `json:"no-hosts,omitempty"`
|
||||
Network string `json:"network,omitempty"`
|
||||
NetworkAlias []string `json:"network-alias,omitempty"`
|
||||
}
|
||||
type NetOptions struct {
|
||||
AddHosts []string
|
||||
Aliases []string
|
||||
CNINetworks []string
|
||||
UseImageResolvConf bool
|
||||
DNSOptions []string
|
||||
DNSSearch []string
|
||||
DNSServers []net.IP
|
||||
Network specgen.Namespace
|
||||
NoHosts bool
|
||||
PublishPorts []types.PortMapping
|
||||
StaticIP *net.IP
|
||||
StaticMAC *net.HardwareAddr
|
||||
AddHosts []string `json:"hostadd,omitempty"`
|
||||
Aliases []string `json:"network_alias,omitempty"`
|
||||
CNINetworks []string `json:"cni_networks,omitempty"`
|
||||
UseImageResolvConf bool `json:"no_manage_resolv_conf,omitempty"`
|
||||
DNSOptions []string `json:"dns_option,omitempty"`
|
||||
DNSSearch []string `json:"dns_search,omitempty"`
|
||||
DNSServers []net.IP `json:"dns_server,omitempty"`
|
||||
Network specgen.Namespace `json:"netns,omitempty"`
|
||||
NoHosts bool `json:"no_manage_hosts,omitempty"`
|
||||
PublishPorts []types.PortMapping `json:"portmappings,omitempty"`
|
||||
StaticIP *net.IP `json:"static_ip,omitempty"`
|
||||
StaticMAC *net.HardwareAddr `json:"static_mac,omitempty"`
|
||||
// NetworkOptions are additional options for each network
|
||||
NetworkOptions map[string][]string
|
||||
NetworkOptions map[string][]string `json:"network_options,omitempty"`
|
||||
}
|
||||
|
||||
// All CLI inspect commands and inspect sub-commands use the same options
|
||||
|
@ -583,7 +583,11 @@ func (ic *ContainerEngine) ContainerCreate(ctx context.Context, s *specgen.SpecG
|
||||
for _, w := range warn {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", w)
|
||||
}
|
||||
ctr, err := generate.MakeContainer(ctx, ic.Libpod, s)
|
||||
rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), ic.Libpod, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -915,7 +919,11 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
|
||||
for _, w := range warn {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", w)
|
||||
}
|
||||
ctr, err := generate.MakeContainer(ctx, ic.Libpod, opts.Spec)
|
||||
rtSpec, spec, optsN, err := generate.MakeContainer(ctx, ic.Libpod, opts.Spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, optsN...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -60,9 +60,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if len(ctr.Dependencies()) > 0 {
|
||||
return nil, errors.Wrapf(define.ErrNotImplemented, "containers with dependencies")
|
||||
}
|
||||
// now that infra holds NS data, we need to support dependencies.
|
||||
// we cannot deal with ctrs already in a pod.
|
||||
if len(ctr.PodID()) > 0 {
|
||||
return nil, errors.Errorf("container %s is associated with pod %s: use generate on the pod itself", ctr.ID(), ctr.PodID())
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@ -22,6 +23,7 @@ import (
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgen/generate"
|
||||
"github.com/containers/podman/v3/pkg/specgen/generate/kube"
|
||||
"github.com/containers/podman/v3/pkg/specgenutil"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
@ -179,10 +181,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
||||
}
|
||||
}
|
||||
|
||||
p, err := kube.ToPodGen(ctx, podName, podYAML)
|
||||
podOpt := entities.PodCreateOptions{Infra: true, Net: &entities.NetOptions{StaticIP: &net.IP{}, StaticMAC: &net.HardwareAddr{}}}
|
||||
podOpt, err = kube.ToPodOpt(ctx, podName, podOpt, podYAML)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if options.Network != "" {
|
||||
ns, cniNets, netOpts, err := specgen.ParseNetworkString(options.Network)
|
||||
if err != nil {
|
||||
@ -193,42 +197,37 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
||||
return nil, errors.Errorf("invalid value passed to --network: bridge or host networking must be configured in YAML")
|
||||
}
|
||||
logrus.Debugf("Pod %q joining CNI networks: %v", podName, cniNets)
|
||||
p.NetNS.NSMode = specgen.Bridge
|
||||
p.CNINetworks = append(p.CNINetworks, cniNets...)
|
||||
podOpt.Net.Network.NSMode = specgen.Bridge
|
||||
podOpt.Net.CNINetworks = append(podOpt.Net.CNINetworks, cniNets...)
|
||||
if len(netOpts) > 0 {
|
||||
p.NetworkOptions = netOpts
|
||||
podOpt.Net.NetworkOptions = netOpts
|
||||
}
|
||||
}
|
||||
|
||||
if len(options.StaticIPs) > *ipIndex {
|
||||
p.StaticIP = &options.StaticIPs[*ipIndex]
|
||||
podOpt.Net.StaticIP = &options.StaticIPs[*ipIndex]
|
||||
} else if len(options.StaticIPs) > 0 {
|
||||
// only warn if the user has set at least one ip
|
||||
logrus.Warn("No more static ips left using a random one")
|
||||
}
|
||||
if len(options.StaticMACs) > *ipIndex {
|
||||
p.StaticMAC = &options.StaticMACs[*ipIndex]
|
||||
podOpt.Net.StaticMAC = &options.StaticMACs[*ipIndex]
|
||||
} else if len(options.StaticIPs) > 0 {
|
||||
// only warn if the user has set at least one mac
|
||||
logrus.Warn("No more static macs left using a random one")
|
||||
}
|
||||
*ipIndex++
|
||||
|
||||
// Create the Pod
|
||||
pod, err := generate.MakePod(p, ic.Libpod)
|
||||
p := specgen.NewPodSpecGenerator()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
podInfraID, err := pod.InfraContainerID()
|
||||
p, err = entities.ToPodSpecGen(*p, &podOpt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !options.Quiet {
|
||||
writer = os.Stderr
|
||||
}
|
||||
|
||||
podSpec := entities.PodSpec{PodSpecGen: *p}
|
||||
volumes, err := kube.InitializeVolumes(podYAML.Spec.Volumes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -267,112 +266,146 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
||||
configMaps = append(configMaps, cm)
|
||||
}
|
||||
|
||||
if podOpt.Infra {
|
||||
imagePull := config.DefaultInfraImage
|
||||
if podOpt.InfraImage != config.DefaultInfraImage && podOpt.InfraImage != "" {
|
||||
imagePull = podOpt.InfraImage
|
||||
}
|
||||
|
||||
pulledImages, err := pullImage(ic, writer, imagePull, options, config.PullPolicyNewer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
infraOptions := entities.ContainerCreateOptions{ImageVolume: "bind"}
|
||||
|
||||
podSpec.PodSpecGen.InfraImage = pulledImages[0].Names()[0]
|
||||
podSpec.PodSpecGen.NoInfra = false
|
||||
podSpec.PodSpecGen.InfraContainerSpec = specgen.NewSpecGenerator(pulledImages[0].Names()[0], false)
|
||||
podSpec.PodSpecGen.InfraContainerSpec.NetworkOptions = p.NetworkOptions
|
||||
|
||||
err = specgenutil.FillOutSpecGen(podSpec.PodSpecGen.InfraContainerSpec, &infraOptions, []string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the Pod
|
||||
pod, err := generate.MakePod(&podSpec, ic.Libpod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
podInfraID, err := pod.InfraContainerID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !options.Quiet {
|
||||
writer = os.Stderr
|
||||
}
|
||||
|
||||
containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers))
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, container := range podYAML.Spec.Containers {
|
||||
// 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, 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 !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)
|
||||
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))
|
||||
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]
|
||||
}
|
||||
// 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)
|
||||
// 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,
|
||||
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,
|
||||
}
|
||||
specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
|
||||
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
|
||||
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
|
||||
}
|
||||
containers = append(containers, ctr)
|
||||
}
|
||||
|
||||
specgenOpts := kube.CtrSpecGenOptions{
|
||||
Container: container,
|
||||
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,
|
||||
}
|
||||
specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctr, err := generate.MakeContainer(ctx, ic.Libpod, specGen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
containers = append(containers, ctr)
|
||||
}
|
||||
|
||||
if options.Start != types.OptionalBoolFalse {
|
||||
@ -383,6 +416,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
||||
}
|
||||
for id, err := range podStartErrors {
|
||||
playKubePod.ContainerErrors = append(playKubePod.ContainerErrors, errors.Wrapf(err, "error starting container %s", id).Error())
|
||||
fmt.Println(playKubePod.ContainerErrors)
|
||||
}
|
||||
}
|
||||
|
||||
@ -656,3 +690,21 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ enti
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
// pullImage is a helper function to set up the proper pull options and pull the image for certain containers
|
||||
func pullImage(ic *ContainerEngine, writer io.Writer, imagePull string, options entities.PlayKubeOptions, pullPolicy config.PullPolicy) ([]*libimage.Image, error) {
|
||||
// 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(context.Background(), imagePull, pullPolicy, pullOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pulledImages, nil
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
dfilters "github.com/containers/podman/v3/pkg/domain/filters"
|
||||
"github.com/containers/podman/v3/pkg/signal"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgen/generate"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -248,12 +247,8 @@ func (ic *ContainerEngine) prunePodHelper(ctx context.Context) ([]*entities.PodP
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) PodCreate(ctx context.Context, opts entities.PodCreateOptions) (*entities.PodCreateReport, error) {
|
||||
podSpec := specgen.NewPodSpecGenerator()
|
||||
if err := opts.ToPodSpecGen(podSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pod, err := generate.MakePod(podSpec, ic.Libpod)
|
||||
func (ic *ContainerEngine) PodCreate(ctx context.Context, specg entities.PodSpec) (*entities.PodCreateReport, error) {
|
||||
pod, err := generate.MakePod(&specg, ic.Libpod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/containers/podman/v3/libpod/events"
|
||||
"github.com/containers/podman/v3/pkg/bindings/system"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/bindings/pods"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -179,10 +178,8 @@ func (ic *ContainerEngine) PodPrune(ctx context.Context, opts entities.PodPruneO
|
||||
return pods.Prune(ic.ClientCtx, nil)
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) PodCreate(ctx context.Context, opts entities.PodCreateOptions) (*entities.PodCreateReport, error) {
|
||||
podSpec := specgen.NewPodSpecGenerator()
|
||||
opts.ToPodSpecGen(podSpec)
|
||||
return pods.CreatePodFromSpec(ic.ClientCtx, podSpec, nil)
|
||||
func (ic *ContainerEngine) PodCreate(ctx context.Context, specg entities.PodSpec) (*entities.PodCreateReport, error) {
|
||||
return pods.CreatePodFromSpec(ic.ClientCtx, &specg)
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) PodTop(ctx context.Context, opts entities.PodTopOptions) (*entities.StringSliceReport, error) {
|
||||
|
@ -22,10 +22,10 @@ import (
|
||||
// MakeContainer creates a container based on the SpecGenerator.
|
||||
// Returns the created, container and any warnings resulting from creating the
|
||||
// container, or an error.
|
||||
func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator) (*libpod.Container, error) {
|
||||
func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator) (*spec.Spec, *specgen.SpecGenerator, []libpod.CtrCreateOption, error) {
|
||||
rtc, err := rt.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
// If joining a pod, retrieve the pod for use.
|
||||
@ -33,7 +33,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||
if s.Pod != "" {
|
||||
pod, err = rt.LookupPod(s.Pod)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error retrieving pod %s", s.Pod)
|
||||
return nil, nil, nil, errors.Wrapf(err, "error retrieving pod %s", s.Pod)
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,47 +41,48 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||
if s.PidNS.IsDefault() {
|
||||
defaultNS, err := GetDefaultNamespaceMode("pid", rtc, pod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
s.PidNS = defaultNS
|
||||
}
|
||||
if s.IpcNS.IsDefault() {
|
||||
defaultNS, err := GetDefaultNamespaceMode("ipc", rtc, pod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
s.IpcNS = defaultNS
|
||||
}
|
||||
if s.UtsNS.IsDefault() {
|
||||
defaultNS, err := GetDefaultNamespaceMode("uts", rtc, pod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
s.UtsNS = defaultNS
|
||||
}
|
||||
if s.UserNS.IsDefault() {
|
||||
defaultNS, err := GetDefaultNamespaceMode("user", rtc, pod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
s.UserNS = defaultNS
|
||||
}
|
||||
if s.NetNS.IsDefault() {
|
||||
defaultNS, err := GetDefaultNamespaceMode("net", rtc, pod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
s.NetNS = defaultNS
|
||||
}
|
||||
if s.CgroupNS.IsDefault() {
|
||||
defaultNS, err := GetDefaultNamespaceMode("cgroup", rtc, pod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
s.CgroupNS = defaultNS
|
||||
}
|
||||
|
||||
options := []libpod.CtrCreateOption{}
|
||||
|
||||
if s.ContainerCreateCommand != nil {
|
||||
options = append(options, libpod.WithCreateCommand(s.ContainerCreateCommand))
|
||||
}
|
||||
@ -94,12 +95,11 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||
var resolvedImageName string
|
||||
newImage, resolvedImageName, err = rt.LibimageRuntime().LookupImage(s.Image, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
imageData, err = newImage.Inspect(ctx, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
// If the input name changed, we could properly resolve the
|
||||
// image. Otherwise, it must have been an ID where we're
|
||||
@ -115,29 +115,32 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||
options = append(options, libpod.WithRootFSFromImage(newImage.ID(), resolvedImageName, s.RawImageName))
|
||||
}
|
||||
if err := s.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "invalid config provided")
|
||||
return nil, nil, nil, errors.Wrap(err, "invalid config provided")
|
||||
}
|
||||
|
||||
finalMounts, finalVolumes, finalOverlays, err := finalizeMounts(ctx, s, rt, rtc, newImage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
command, err := makeCommand(ctx, s, imageData, rtc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, finalOverlays, imageData, command)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
options = append(options, opts...)
|
||||
|
||||
exitCommandArgs, err := CreateExitCommandArgs(rt.StorageConfig(), rtc, logrus.IsLevelEnabled(logrus.DebugLevel), s.Remove, false)
|
||||
var exitCommandArgs []string
|
||||
|
||||
exitCommandArgs, err = CreateExitCommandArgs(rt.StorageConfig(), rtc, logrus.IsLevelEnabled(logrus.DebugLevel), s.Remove, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
options = append(options, libpod.WithExitCommand(exitCommandArgs))
|
||||
|
||||
if len(s.Aliases) > 0 {
|
||||
@ -147,23 +150,26 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||
if containerType := s.InitContainerType; len(containerType) > 0 {
|
||||
options = append(options, libpod.WithInitCtrType(containerType))
|
||||
}
|
||||
|
||||
if len(s.Name) > 0 {
|
||||
logrus.Debugf("setting container name %s", s.Name)
|
||||
options = append(options, libpod.WithName(s.Name))
|
||||
}
|
||||
if len(s.Devices) > 0 {
|
||||
opts = extractCDIDevices(s)
|
||||
options = append(options, opts...)
|
||||
}
|
||||
runtimeSpec, err := SpecGenToOCI(ctx, s, rt, rtc, newImage, finalMounts, pod, command)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
ctr, err := rt.NewContainer(ctx, runtimeSpec, options...)
|
||||
return runtimeSpec, s, options, err
|
||||
}
|
||||
func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *spec.Spec, s *specgen.SpecGenerator, infra bool, options ...libpod.CtrCreateOption) (*libpod.Container, error) {
|
||||
ctr, err := rt.NewContainer(ctx, runtimeSpec, s, infra, options...)
|
||||
if err != nil {
|
||||
return ctr, err
|
||||
}
|
||||
|
||||
// Copy the content from the underlying image into the newly created
|
||||
// volume if configured to do so.
|
||||
return ctr, rt.PrepareVolumeOnCreateContainer(ctx, ctr)
|
||||
}
|
||||
|
||||
@ -256,11 +262,6 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
||||
if len(s.SdNotifyMode) > 0 {
|
||||
options = append(options, libpod.WithSdNotifyMode(s.SdNotifyMode))
|
||||
}
|
||||
|
||||
if len(s.Name) > 0 {
|
||||
logrus.Debugf("setting container name %s", s.Name)
|
||||
options = append(options, libpod.WithName(s.Name))
|
||||
}
|
||||
if pod != nil {
|
||||
logrus.Debugf("adding container to pod %s", pod.Name())
|
||||
options = append(options, rt.WithPod(pod))
|
||||
@ -379,11 +380,11 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
||||
options = append(options, libpod.WithPrivileged(s.Privileged))
|
||||
|
||||
// Get namespace related options
|
||||
namespaceOptions, err := namespaceOptions(ctx, s, rt, pod, imageData)
|
||||
namespaceOpts, err := namespaceOptions(ctx, s, rt, pod, imageData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options = append(options, namespaceOptions...)
|
||||
options = append(options, namespaceOpts...)
|
||||
|
||||
if len(s.ConmonPidFile) > 0 {
|
||||
options = append(options, libpod.WithConmonPidFile(s.ConmonPidFile))
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/podman/v3/libpod/network/types"
|
||||
ann "github.com/containers/podman/v3/pkg/annotations"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/specgen/generate"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
@ -23,25 +24,26 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
)
|
||||
|
||||
func ToPodGen(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec) (*specgen.PodSpecGenerator, error) {
|
||||
p := specgen.NewPodSpecGenerator()
|
||||
func ToPodOpt(ctx context.Context, podName string, p entities.PodCreateOptions, podYAML *v1.PodTemplateSpec) (entities.PodCreateOptions, error) {
|
||||
// p := specgen.NewPodSpecGenerator()
|
||||
p.Net = &entities.NetOptions{}
|
||||
p.Name = podName
|
||||
p.Labels = podYAML.ObjectMeta.Labels
|
||||
// Kube pods must share {ipc, net, uts} by default
|
||||
p.SharedNamespaces = append(p.SharedNamespaces, "ipc")
|
||||
p.SharedNamespaces = append(p.SharedNamespaces, "net")
|
||||
p.SharedNamespaces = append(p.SharedNamespaces, "uts")
|
||||
p.Share = append(p.Share, "ipc")
|
||||
p.Share = append(p.Share, "net")
|
||||
p.Share = append(p.Share, "uts")
|
||||
// TODO we only configure Process namespace. We also need to account for Host{IPC,Network,PID}
|
||||
// which is not currently possible with pod create
|
||||
if podYAML.Spec.ShareProcessNamespace != nil && *podYAML.Spec.ShareProcessNamespace {
|
||||
p.SharedNamespaces = append(p.SharedNamespaces, "pid")
|
||||
p.Share = append(p.Share, "pid")
|
||||
}
|
||||
p.Hostname = podYAML.Spec.Hostname
|
||||
if p.Hostname == "" {
|
||||
p.Hostname = podName
|
||||
}
|
||||
if podYAML.Spec.HostNetwork {
|
||||
p.NetNS.NSMode = specgen.Host
|
||||
p.Net.Network = specgen.Namespace{NSMode: "host"}
|
||||
}
|
||||
if podYAML.Spec.HostAliases != nil {
|
||||
hosts := make([]string, 0, len(podYAML.Spec.HostAliases))
|
||||
@ -50,10 +52,10 @@ func ToPodGen(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec)
|
||||
hosts = append(hosts, host+":"+hostAlias.IP)
|
||||
}
|
||||
}
|
||||
p.HostAdd = hosts
|
||||
p.Net.AddHosts = hosts
|
||||
}
|
||||
podPorts := getPodPorts(podYAML.Spec.Containers)
|
||||
p.PortMappings = podPorts
|
||||
p.Net.PublishPorts = podPorts
|
||||
|
||||
if dnsConfig := podYAML.Spec.DNSConfig; dnsConfig != nil {
|
||||
// name servers
|
||||
@ -62,11 +64,11 @@ func ToPodGen(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec)
|
||||
for _, server := range dnsServers {
|
||||
servers = append(servers, net.ParseIP(server))
|
||||
}
|
||||
p.DNSServer = servers
|
||||
p.Net.DNSServers = servers
|
||||
}
|
||||
// search domains
|
||||
if domains := dnsConfig.Searches; len(domains) > 0 {
|
||||
p.DNSSearch = domains
|
||||
p.Net.DNSSearch = domains
|
||||
}
|
||||
// dns options
|
||||
if options := dnsConfig.Options; len(options) > 0 {
|
||||
@ -110,6 +112,8 @@ type CtrSpecGenOptions struct {
|
||||
LogDriver string
|
||||
// Labels define key-value pairs of metadata
|
||||
Labels map[string]string
|
||||
//
|
||||
IsInfra bool
|
||||
}
|
||||
|
||||
func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGenerator, error) {
|
||||
@ -216,19 +220,19 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
|
||||
}
|
||||
}
|
||||
// If only the yaml.Command is specified, set it as the entrypoint and drop the image Cmd
|
||||
if len(opts.Container.Command) != 0 {
|
||||
if !opts.IsInfra && len(opts.Container.Command) != 0 {
|
||||
s.Entrypoint = opts.Container.Command
|
||||
s.Command = []string{}
|
||||
}
|
||||
// Only override the cmd field if yaml.Args is specified
|
||||
// Keep the image entrypoint, or the yaml.command if specified
|
||||
if len(opts.Container.Args) != 0 {
|
||||
if !opts.IsInfra && len(opts.Container.Args) != 0 {
|
||||
s.Command = opts.Container.Args
|
||||
}
|
||||
|
||||
// FIXME,
|
||||
// we are currently ignoring imageData.Config.ExposedPorts
|
||||
if opts.Container.WorkingDir != "" {
|
||||
if !opts.IsInfra && opts.Container.WorkingDir != "" {
|
||||
s.WorkDir = opts.Container.WorkingDir
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,7 @@ func namespaceOptions(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.
|
||||
if s.NetNS.Value != "" {
|
||||
val = fmt.Sprintf("slirp4netns:%s", s.NetNS.Value)
|
||||
}
|
||||
toReturn = append(toReturn, libpod.WithNetNS(portMappings, expose, postConfigureNetNS, val, nil))
|
||||
toReturn = append(toReturn, libpod.WithNetNS(portMappings, expose, postConfigureNetNS, val, s.CNINetworks))
|
||||
case specgen.Private:
|
||||
fallthrough
|
||||
case specgen.Bridge:
|
||||
|
@ -201,7 +201,8 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
|
||||
Options: []string{"rprivate", "nosuid", "noexec", "nodev", "rw"},
|
||||
}
|
||||
g.AddMount(sysMnt)
|
||||
} else if !canMountSys {
|
||||
}
|
||||
if !canMountSys {
|
||||
addCgroup = false
|
||||
g.RemoveMount("/sys")
|
||||
r := "ro"
|
||||
|
@ -2,53 +2,82 @@ package generate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v3/libpod"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func MakePod(p *specgen.PodSpecGenerator, rt *libpod.Runtime) (*libpod.Pod, error) {
|
||||
if err := p.Validate(); err != nil {
|
||||
func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
|
||||
if err := p.PodSpecGen.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options, err := createPodOptions(p, rt)
|
||||
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
|
||||
var err error
|
||||
p.PodSpecGen.InfraContainerSpec, err = MapSpec(&p.PodSpecGen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
options, err := createPodOptions(&p.PodSpecGen, rt, p.PodSpecGen.InfraContainerSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rt.NewPod(context.Background(), options...)
|
||||
pod, err := rt.NewPod(context.Background(), p.PodSpecGen, options...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
|
||||
p.PodSpecGen.InfraContainerSpec.ContainerCreateCommand = []string{} // we do NOT want os.Args as the command, will display the pod create cmd
|
||||
if p.PodSpecGen.InfraContainerSpec.Name == "" {
|
||||
p.PodSpecGen.InfraContainerSpec.Name = pod.ID()[:12] + "-infra"
|
||||
}
|
||||
_, err = CompleteSpec(context.Background(), rt, p.PodSpecGen.InfraContainerSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.PodSpecGen.InfraContainerSpec.User = "" // infraSpec user will get incorrectly assigned via the container creation process, overwrite here
|
||||
rtSpec, spec, opts, err := MakeContainer(context.Background(), rt, p.PodSpecGen.InfraContainerSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
spec.Pod = pod.ID()
|
||||
opts = append(opts, rt.WithPod(pod))
|
||||
spec.CgroupParent = pod.CgroupParent()
|
||||
infraCtr, err := ExecuteCreate(context.Background(), rt, rtSpec, spec, true, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pod, err = rt.AddInfra(context.Background(), pod, infraCtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return pod, nil
|
||||
}
|
||||
|
||||
func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod.PodCreateOption, error) {
|
||||
func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime, infraSpec *specgen.SpecGenerator) ([]libpod.PodCreateOption, error) {
|
||||
var (
|
||||
options []libpod.PodCreateOption
|
||||
)
|
||||
if !p.NoInfra {
|
||||
if !p.NoInfra { //&& infraSpec != nil {
|
||||
options = append(options, libpod.WithInfraContainer())
|
||||
nsOptions, err := GetNamespaceOptions(p.SharedNamespaces, p.NetNS.IsHost())
|
||||
nsOptions, err := GetNamespaceOptions(p.SharedNamespaces, p.InfraContainerSpec.NetNS.IsHost())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options = append(options, nsOptions...)
|
||||
// Use pod user and infra userns only when --userns is not set to host
|
||||
if !p.Userns.IsHost() {
|
||||
if !p.InfraContainerSpec.UserNS.IsHost() && !p.InfraContainerSpec.UserNS.IsDefault() {
|
||||
options = append(options, libpod.WithPodUser())
|
||||
options = append(options, libpod.WithPodUserns(p.Userns))
|
||||
}
|
||||
|
||||
// Make our exit command
|
||||
storageConfig := rt.StorageConfig()
|
||||
runtimeConfig, err := rt.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exitCommand, err := CreateExitCommandArgs(storageConfig, runtimeConfig, logrus.IsLevelEnabled(logrus.DebugLevel), false, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error creating infra container exit command")
|
||||
}
|
||||
options = append(options, libpod.WithPodInfraExitCommand(exitCommand))
|
||||
}
|
||||
if len(p.CgroupParent) > 0 {
|
||||
options = append(options, libpod.WithPodCgroupParent(p.CgroupParent))
|
||||
@ -59,62 +88,27 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod
|
||||
if len(p.Name) > 0 {
|
||||
options = append(options, libpod.WithPodName(p.Name))
|
||||
}
|
||||
if p.ResourceLimits != nil && p.ResourceLimits.CPU != nil && p.ResourceLimits.CPU.Period != nil && p.ResourceLimits.CPU.Quota != nil {
|
||||
if *p.ResourceLimits.CPU.Period != 0 || *p.ResourceLimits.CPU.Quota != 0 {
|
||||
options = append(options, libpod.WithPodCPUPAQ((*p.ResourceLimits.CPU.Period), (*p.ResourceLimits.CPU.Quota)))
|
||||
}
|
||||
}
|
||||
if p.ResourceLimits != nil && p.ResourceLimits.CPU != nil && p.ResourceLimits.CPU.Cpus != "" {
|
||||
options = append(options, libpod.WithPodCPUSetCPUs(p.ResourceLimits.CPU.Cpus))
|
||||
if p.PodCreateCommand != nil {
|
||||
options = append(options, libpod.WithPodCreateCommand(p.PodCreateCommand))
|
||||
}
|
||||
|
||||
if len(p.Hostname) > 0 {
|
||||
options = append(options, libpod.WithPodHostname(p.Hostname))
|
||||
}
|
||||
if len(p.HostAdd) > 0 {
|
||||
options = append(options, libpod.WithPodHosts(p.HostAdd))
|
||||
}
|
||||
if len(p.DNSServer) > 0 {
|
||||
var dnsServers []string
|
||||
for _, d := range p.DNSServer {
|
||||
dnsServers = append(dnsServers, d.String())
|
||||
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// MapSpec modifies the already filled Infra specgenerator,
|
||||
// replacing necessary values with those specified in pod creation
|
||||
func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) {
|
||||
if len(p.PortMappings) > 0 {
|
||||
ports, _, _, err := ParsePortMapping(p.PortMappings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options = append(options, libpod.WithPodDNS(dnsServers))
|
||||
p.InfraContainerSpec.PortMappings = libpod.WithInfraContainerPorts(ports, p.InfraContainerSpec)
|
||||
}
|
||||
if len(p.DNSOption) > 0 {
|
||||
options = append(options, libpod.WithPodDNSOption(p.DNSOption))
|
||||
}
|
||||
if len(p.DNSSearch) > 0 {
|
||||
options = append(options, libpod.WithPodDNSSearch(p.DNSSearch))
|
||||
}
|
||||
if p.StaticIP != nil {
|
||||
options = append(options, libpod.WithPodStaticIP(*p.StaticIP))
|
||||
}
|
||||
if p.StaticMAC != nil {
|
||||
options = append(options, libpod.WithPodStaticMAC(*p.StaticMAC))
|
||||
}
|
||||
if p.NoManageResolvConf {
|
||||
options = append(options, libpod.WithPodUseImageResolvConf())
|
||||
}
|
||||
if len(p.CNINetworks) > 0 {
|
||||
options = append(options, libpod.WithPodNetworks(p.CNINetworks))
|
||||
}
|
||||
|
||||
if len(p.InfraImage) > 0 {
|
||||
options = append(options, libpod.WithInfraImage(p.InfraImage))
|
||||
}
|
||||
|
||||
if len(p.InfraName) > 0 {
|
||||
options = append(options, libpod.WithInfraName(p.InfraName))
|
||||
}
|
||||
|
||||
if len(p.InfraCommand) > 0 {
|
||||
options = append(options, libpod.WithInfraCommand(p.InfraCommand))
|
||||
}
|
||||
|
||||
if !p.Pid.IsDefault() {
|
||||
options = append(options, libpod.WithPodPidNS(p.Pid))
|
||||
}
|
||||
|
||||
switch p.NetNS.NSMode {
|
||||
case specgen.Default, "":
|
||||
if p.NoInfra {
|
||||
@ -123,42 +117,88 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod
|
||||
}
|
||||
if rootless.IsRootless() {
|
||||
logrus.Debugf("Pod will use slirp4netns")
|
||||
options = append(options, libpod.WithPodSlirp4netns(p.NetworkOptions))
|
||||
if p.InfraContainerSpec.NetNS.NSMode != "host" {
|
||||
p.InfraContainerSpec.NetworkOptions = p.NetworkOptions
|
||||
p.InfraContainerSpec.NetNS.NSMode = specgen.NamespaceMode("slirp4netns")
|
||||
}
|
||||
} else {
|
||||
logrus.Debugf("Pod using bridge network mode")
|
||||
}
|
||||
case specgen.Bridge:
|
||||
p.InfraContainerSpec.NetNS.NSMode = specgen.Bridge
|
||||
logrus.Debugf("Pod using bridge network mode")
|
||||
case specgen.Host:
|
||||
logrus.Debugf("Pod will use host networking")
|
||||
options = append(options, libpod.WithPodHostNetwork())
|
||||
if len(p.InfraContainerSpec.PortMappings) > 0 ||
|
||||
p.InfraContainerSpec.StaticIP != nil ||
|
||||
p.InfraContainerSpec.StaticMAC != nil ||
|
||||
len(p.InfraContainerSpec.CNINetworks) > 0 ||
|
||||
p.InfraContainerSpec.NetNS.NSMode == specgen.NoNetwork {
|
||||
return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified")
|
||||
}
|
||||
p.InfraContainerSpec.NetNS.NSMode = specgen.Host
|
||||
case specgen.Slirp:
|
||||
logrus.Debugf("Pod will use slirp4netns")
|
||||
options = append(options, libpod.WithPodSlirp4netns(p.NetworkOptions))
|
||||
if p.InfraContainerSpec.NetNS.NSMode != "host" {
|
||||
p.InfraContainerSpec.NetworkOptions = p.NetworkOptions
|
||||
p.InfraContainerSpec.NetNS.NSMode = specgen.NamespaceMode("slirp4netns")
|
||||
}
|
||||
case specgen.NoNetwork:
|
||||
logrus.Debugf("Pod will not use networking")
|
||||
options = append(options, libpod.WithPodNoNetwork())
|
||||
if len(p.InfraContainerSpec.PortMappings) > 0 ||
|
||||
p.InfraContainerSpec.StaticIP != nil ||
|
||||
p.InfraContainerSpec.StaticMAC != nil ||
|
||||
len(p.InfraContainerSpec.CNINetworks) > 0 ||
|
||||
p.InfraContainerSpec.NetNS.NSMode == "host" {
|
||||
return nil, errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified")
|
||||
}
|
||||
p.InfraContainerSpec.NetNS.NSMode = specgen.NoNetwork
|
||||
default:
|
||||
return nil, errors.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode)
|
||||
}
|
||||
|
||||
if p.NoManageHosts {
|
||||
options = append(options, libpod.WithPodUseImageHosts())
|
||||
}
|
||||
if len(p.PortMappings) > 0 {
|
||||
ports, _, _, err := ParsePortMapping(p.PortMappings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options = append(options, libpod.WithInfraContainerPorts(ports))
|
||||
}
|
||||
options = append(options, libpod.WithPodCgroups())
|
||||
if p.PodCreateCommand != nil {
|
||||
options = append(options, libpod.WithPodCreateCommand(p.PodCreateCommand))
|
||||
}
|
||||
if len(p.InfraConmonPidFile) > 0 {
|
||||
options = append(options, libpod.WithInfraConmonPidFile(p.InfraConmonPidFile))
|
||||
libpod.WithPodCgroups()
|
||||
if len(p.InfraCommand) > 0 {
|
||||
p.InfraContainerSpec.Entrypoint = p.InfraCommand
|
||||
}
|
||||
|
||||
return options, nil
|
||||
if len(p.HostAdd) > 0 {
|
||||
p.InfraContainerSpec.HostAdd = p.HostAdd
|
||||
}
|
||||
if len(p.DNSServer) > 0 {
|
||||
var dnsServers []net.IP
|
||||
dnsServers = append(dnsServers, p.DNSServer...)
|
||||
|
||||
p.InfraContainerSpec.DNSServers = dnsServers
|
||||
}
|
||||
if len(p.DNSOption) > 0 {
|
||||
p.InfraContainerSpec.DNSOptions = p.DNSOption
|
||||
}
|
||||
if len(p.DNSSearch) > 0 {
|
||||
p.InfraContainerSpec.DNSSearch = p.DNSSearch
|
||||
}
|
||||
if p.StaticIP != nil {
|
||||
p.InfraContainerSpec.StaticIP = p.StaticIP
|
||||
}
|
||||
if p.StaticMAC != nil {
|
||||
p.InfraContainerSpec.StaticMAC = p.StaticMAC
|
||||
}
|
||||
if p.NoManageResolvConf {
|
||||
p.InfraContainerSpec.UseImageResolvConf = true
|
||||
}
|
||||
if len(p.CNINetworks) > 0 {
|
||||
p.InfraContainerSpec.CNINetworks = p.CNINetworks
|
||||
}
|
||||
if p.NoManageHosts {
|
||||
p.InfraContainerSpec.UseImageHosts = p.NoManageHosts
|
||||
}
|
||||
|
||||
if len(p.InfraConmonPidFile) > 0 {
|
||||
p.InfraContainerSpec.ConmonPidFile = p.InfraConmonPidFile
|
||||
}
|
||||
|
||||
if p.InfraImage != config.DefaultInfraImage {
|
||||
p.InfraContainerSpec.Image = p.InfraImage
|
||||
}
|
||||
return p.InfraContainerSpec, nil
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ type PodBasicConfig struct {
|
||||
// Pid sets the process id namespace of the pod
|
||||
// Optional (defaults to private if unset). This sets the PID namespace of the infra container
|
||||
// This configuration will then be shared with the entire pod if PID namespace sharing is enabled via --share
|
||||
Pid Namespace `json:"pid,omitempty:"`
|
||||
Pid Namespace `json:"pidns,omitempty"`
|
||||
// Userns is used to indicate which kind of Usernamespace to enter.
|
||||
// Any containers created within the pod will inherit the pod's userns settings.
|
||||
// Optional
|
||||
@ -173,6 +173,7 @@ type PodSpecGenerator struct {
|
||||
PodNetworkConfig
|
||||
PodCgroupConfig
|
||||
PodResourceConfig
|
||||
InfraContainerSpec *SpecGenerator `json:"-"`
|
||||
}
|
||||
|
||||
type PodResourceConfig struct {
|
||||
|
@ -1,13 +1,14 @@
|
||||
package common
|
||||
package specgenutil
|
||||
|
||||
import (
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// validate determines if the flags and values given by the user are valid. things checked
|
||||
// by validate must not need any state information on the flag (i.e. changed)
|
||||
func (c *ContainerCLIOpts) validate() error {
|
||||
func validate(c *entities.ContainerCreateOptions) error {
|
||||
var ()
|
||||
if c.Rm && (c.Restart != "" && c.Restart != "no" && c.Restart != "on-failure") {
|
||||
return errors.Errorf(`the --rm option conflicts with --restart, when the restartPolicy is not "" and "no"`)
|
||||
@ -23,7 +24,11 @@ func (c *ContainerCLIOpts) validate() error {
|
||||
"ignore": "",
|
||||
}
|
||||
if _, ok := imageVolType[c.ImageVolume]; !ok {
|
||||
return errors.Errorf("invalid image-volume type %q. Pick one of bind, tmpfs, or ignore", c.ImageVolume)
|
||||
if c.IsInfra {
|
||||
c.ImageVolume = "bind"
|
||||
} else {
|
||||
return errors.Errorf("invalid image-volume type %q. Pick one of bind, tmpfs, or ignore", c.ImageVolume)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package specgenutil
|
||||
|
||||
import (
|
||||
"github.com/docker/go-connections/nat"
|
@ -1,6 +1,7 @@
|
||||
package common
|
||||
package specgenutil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
@ -11,8 +12,9 @@ import (
|
||||
"github.com/containers/podman/v3/cmd/podman/parse"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
ann "github.com/containers/podman/v3/pkg/annotations"
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
envLib "github.com/containers/podman/v3/pkg/env"
|
||||
ns "github.com/containers/podman/v3/pkg/namespaces"
|
||||
"github.com/containers/podman/v3/pkg/namespaces"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
systemdDefine "github.com/containers/podman/v3/pkg/systemd/define"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
@ -21,7 +23,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func getCPULimits(c *ContainerCLIOpts) *specs.LinuxCPU {
|
||||
func getCPULimits(c *entities.ContainerCreateOptions) *specs.LinuxCPU {
|
||||
cpu := &specs.LinuxCPU{}
|
||||
hasLimits := false
|
||||
|
||||
@ -67,7 +69,7 @@ func getCPULimits(c *ContainerCLIOpts) *specs.LinuxCPU {
|
||||
return cpu
|
||||
}
|
||||
|
||||
func getIOLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts) (*specs.LinuxBlockIO, error) {
|
||||
func getIOLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (*specs.LinuxBlockIO, error) {
|
||||
var err error
|
||||
io := &specs.LinuxBlockIO{}
|
||||
hasLimits := false
|
||||
@ -122,7 +124,7 @@ func getIOLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts) (*specs.LinuxBlo
|
||||
return io, nil
|
||||
}
|
||||
|
||||
func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts) (*specs.LinuxMemory, error) {
|
||||
func getMemoryLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (*specs.LinuxMemory, error) {
|
||||
var err error
|
||||
memory := &specs.LinuxMemory{}
|
||||
hasLimits := false
|
||||
@ -167,7 +169,7 @@ func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts) (*specs.Linu
|
||||
memory.Kernel = &mk
|
||||
hasLimits = true
|
||||
}
|
||||
if c.MemorySwappiness >= 0 {
|
||||
if c.MemorySwappiness > 0 {
|
||||
swappiness := uint64(c.MemorySwappiness)
|
||||
memory.Swappiness = &swappiness
|
||||
hasLimits = true
|
||||
@ -182,7 +184,7 @@ func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts) (*specs.Linu
|
||||
return memory, nil
|
||||
}
|
||||
|
||||
func setNamespaces(s *specgen.SpecGenerator, c *ContainerCLIOpts) error {
|
||||
func setNamespaces(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) error {
|
||||
var err error
|
||||
|
||||
if c.PID != "" {
|
||||
@ -222,18 +224,22 @@ func setNamespaces(s *specgen.SpecGenerator, c *ContainerCLIOpts) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) error {
|
||||
func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions, args []string) error {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
// validate flags as needed
|
||||
if err := c.validate(); err != nil {
|
||||
if err := validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.User = c.User
|
||||
inputCommand := args[1:]
|
||||
var inputCommand []string
|
||||
if !c.IsInfra {
|
||||
if len(args) > 1 {
|
||||
inputCommand = args[1:]
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.HealthCmd) > 0 {
|
||||
if c.NoHealthCheck {
|
||||
return errors.New("Cannot specify both --no-healthcheck and --health-cmd")
|
||||
@ -247,12 +253,33 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
||||
Test: []string{"NONE"},
|
||||
}
|
||||
}
|
||||
|
||||
userNS := ns.UsernsMode(c.UserNS)
|
||||
if err := setNamespaces(s, c); err != nil {
|
||||
return err
|
||||
}
|
||||
userNS := namespaces.UsernsMode(s.UserNS.NSMode)
|
||||
tempIDMap, err := util.ParseIDMapping(namespaces.UsernsMode(c.UserNS), []string{}, []string{}, "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.IDMappings, err = util.ParseIDMapping(userNS, c.UIDMap, c.GIDMap, c.SubUIDName, c.SubGIDName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(s.IDMappings.GIDMap) == 0 {
|
||||
s.IDMappings.AutoUserNsOpts.AdditionalGIDMappings = tempIDMap.AutoUserNsOpts.AdditionalGIDMappings
|
||||
if s.UserNS.NSMode == specgen.NamespaceMode("auto") {
|
||||
s.IDMappings.AutoUserNs = true
|
||||
}
|
||||
}
|
||||
if len(s.IDMappings.UIDMap) == 0 {
|
||||
s.IDMappings.AutoUserNsOpts.AdditionalUIDMappings = tempIDMap.AutoUserNsOpts.AdditionalUIDMappings
|
||||
if s.UserNS.NSMode == specgen.NamespaceMode("auto") {
|
||||
s.IDMappings.AutoUserNs = true
|
||||
}
|
||||
}
|
||||
if tempIDMap.AutoUserNsOpts.Size != 0 {
|
||||
s.IDMappings.AutoUserNsOpts.Size = tempIDMap.AutoUserNsOpts.Size
|
||||
}
|
||||
// If some mappings are specified, assume a private user namespace
|
||||
if userNS.IsDefaultValue() && (!s.IDMappings.HostUIDMapping || !s.IDMappings.HostGIDMapping) {
|
||||
s.UserNS.NSMode = specgen.Private
|
||||
@ -267,7 +294,9 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
||||
}
|
||||
// We are not handling the Expose flag yet.
|
||||
// s.PortsExpose = c.Expose
|
||||
s.PortMappings = c.Net.PublishPorts
|
||||
if c.Net != nil {
|
||||
s.PortMappings = c.Net.PublishPorts
|
||||
}
|
||||
s.PublishExposedPorts = c.PublishAll
|
||||
s.Pod = c.Pod
|
||||
|
||||
@ -288,10 +317,6 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
||||
}
|
||||
s.Expose = expose
|
||||
|
||||
if err := setNamespaces(s, c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if sig := c.StopSignal; len(sig) > 0 {
|
||||
stopSignal, err := util.ParseSignal(sig)
|
||||
if err != nil {
|
||||
@ -380,6 +405,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
||||
}
|
||||
|
||||
// Include the command used to create the container.
|
||||
|
||||
s.ContainerCreateCommand = os.Args
|
||||
|
||||
if len(inputCommand) > 0 {
|
||||
@ -394,28 +420,34 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
||||
}
|
||||
s.ShmSize = &shmSize
|
||||
}
|
||||
s.CNINetworks = c.Net.CNINetworks
|
||||
|
||||
// Network aliases
|
||||
if len(c.Net.Aliases) > 0 {
|
||||
// build a map of aliases where key=cniName
|
||||
aliases := make(map[string][]string, len(s.CNINetworks))
|
||||
for _, cniNetwork := range s.CNINetworks {
|
||||
aliases[cniNetwork] = c.Net.Aliases
|
||||
}
|
||||
s.Aliases = aliases
|
||||
if c.Net != nil {
|
||||
s.CNINetworks = c.Net.CNINetworks
|
||||
}
|
||||
|
||||
s.HostAdd = c.Net.AddHosts
|
||||
s.UseImageResolvConf = c.Net.UseImageResolvConf
|
||||
s.DNSServers = c.Net.DNSServers
|
||||
s.DNSSearch = c.Net.DNSSearch
|
||||
s.DNSOptions = c.Net.DNSOptions
|
||||
s.StaticIP = c.Net.StaticIP
|
||||
s.StaticMAC = c.Net.StaticMAC
|
||||
s.NetworkOptions = c.Net.NetworkOptions
|
||||
s.UseImageHosts = c.Net.NoHosts
|
||||
// Network aliases
|
||||
if c.Net != nil {
|
||||
if len(c.Net.Aliases) > 0 {
|
||||
// build a map of aliases where key=cniName
|
||||
aliases := make(map[string][]string, len(s.CNINetworks))
|
||||
for _, cniNetwork := range s.CNINetworks {
|
||||
aliases[cniNetwork] = c.Net.Aliases
|
||||
}
|
||||
s.Aliases = aliases
|
||||
}
|
||||
}
|
||||
|
||||
if c.Net != nil {
|
||||
s.HostAdd = c.Net.AddHosts
|
||||
s.UseImageResolvConf = c.Net.UseImageResolvConf
|
||||
s.DNSServers = c.Net.DNSServers
|
||||
s.DNSSearch = c.Net.DNSSearch
|
||||
s.DNSOptions = c.Net.DNSOptions
|
||||
s.StaticIP = c.Net.StaticIP
|
||||
s.StaticMAC = c.Net.StaticMAC
|
||||
s.NetworkOptions = c.Net.NetworkOptions
|
||||
s.UseImageHosts = c.Net.NoHosts
|
||||
}
|
||||
s.ImageVolumeMode = c.ImageVolume
|
||||
if s.ImageVolumeMode == "bind" {
|
||||
s.ImageVolumeMode = "anonymous"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package specgenutil
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
@ -1,4 +1,4 @@
|
||||
package common
|
||||
package specgenutil
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -559,7 +559,7 @@ ENTRYPOINT ["sleep","99999"]
|
||||
It("podman pod create --cpuset-cpus", func() {
|
||||
podName := "testPod"
|
||||
ctrName := "testCtr"
|
||||
numCPU := float64(sysinfo.NumCPU())
|
||||
numCPU := float64(sysinfo.NumCPU()) - 1
|
||||
numCPUStr := strconv.Itoa(int(numCPU))
|
||||
in := "0-" + numCPUStr
|
||||
podCreate := podmanTest.Podman([]string{"pod", "create", "--cpuset-cpus", in, "--name", podName})
|
||||
@ -588,20 +588,14 @@ ENTRYPOINT ["sleep","99999"]
|
||||
podInspect.WaitWithDefaultTimeout()
|
||||
Expect(podInspect).Should(Exit(0))
|
||||
podJSON := podInspect.InspectPodToJSON()
|
||||
Expect(podJSON.InfraConfig.PidNS).To(Equal("path"))
|
||||
Expect(podJSON.InfraConfig.PidNS).To(Equal(ns))
|
||||
|
||||
podName = "pidPod2"
|
||||
ns = "pod"
|
||||
|
||||
podCreate = podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
|
||||
podCreate.WaitWithDefaultTimeout()
|
||||
Expect(podCreate).Should(Exit(0))
|
||||
|
||||
podInspect = podmanTest.Podman([]string{"pod", "inspect", podName})
|
||||
podInspect.WaitWithDefaultTimeout()
|
||||
Expect(podInspect).Should(Exit(0))
|
||||
podJSON = podInspect.InspectPodToJSON()
|
||||
Expect(podJSON.InfraConfig.PidNS).To(Equal("pod"))
|
||||
Expect(podCreate).Should(ExitWithError())
|
||||
|
||||
podName = "pidPod3"
|
||||
ns = "host"
|
||||
|
Reference in New Issue
Block a user