summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/inspect/inspect.go21
-rw-r--r--cmd/podman/play/kube.go5
-rw-r--r--cmd/podman/system/service_abi.go27
-rw-r--r--docs/source/markdown/podman-play-kube.1.md4
-rw-r--r--libpod/boltdb_state.go18
-rw-r--r--libpod/container.go14
-rw-r--r--libpod/network/create.go43
-rw-r--r--libpod/networking_linux.go138
-rw-r--r--pkg/api/handlers/compat/networks.go63
-rw-r--r--pkg/api/handlers/libpod/play.go5
-rw-r--r--pkg/api/server/register_play.go5
-rw-r--r--pkg/bindings/play/play.go5
-rw-r--r--pkg/domain/entities/play.go2
-rw-r--r--pkg/domain/infra/abi/network.go6
-rw-r--r--pkg/domain/infra/abi/play.go26
-rw-r--r--pkg/domain/infra/runtime_libpod.go24
-rw-r--r--test/apiv2/rest_api/test_rest_v2_0_0.py14
-rw-r--r--test/e2e/play_kube_test.go15
-rw-r--r--test/e2e/pod_pod_namespaces_test.go (renamed from test/e2e/pod_pod_namespaces.go)0
-rw-r--r--test/e2e/run_seccomp_test.go (renamed from test/e2e/run_seccomp.go)0
-rw-r--r--test/e2e/run_security_labels_test.go (renamed from test/e2e/run_security_labels.go)0
-rw-r--r--test/e2e/run_working_dir_test.go (renamed from test/e2e/run_working_dir.go)0
-rw-r--r--test/python/docker/test_containers.py10
23 files changed, 309 insertions, 136 deletions
diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go
index f9bd75c93..13f36ebbd 100644
--- a/cmd/podman/inspect/inspect.go
+++ b/cmd/podman/inspect/inspect.go
@@ -2,6 +2,7 @@ package inspect
import (
"context"
+ "encoding/json" // due to a bug in json-iterator it cannot be used here
"fmt"
"os"
"regexp"
@@ -28,17 +29,14 @@ const (
ContainerType = "container"
// ImageType is the image type.
ImageType = "image"
- //NetworkType is the network type
+ // NetworkType is the network type
NetworkType = "network"
- //PodType is the pod type.
+ // PodType is the pod type.
PodType = "pod"
- //VolumeType is the volume type
+ // VolumeType is the volume type
VolumeType = "volume"
)
-// Pull in configured json library
-var json = registry.JSONLibrary()
-
// AddInspectFlagSet takes a command and adds the inspect flags and returns an
// InspectOptions object.
func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions {
@@ -173,7 +171,7 @@ func (i *inspector) inspect(namesOrIDs []string) error {
data = append(data, podData)
}
}
- if i.podOptions.Latest { //latest means there are no names in the namesOrID array
+ if i.podOptions.Latest { // latest means there are no names in the namesOrID array
podData, err := i.containerEngine.PodInspect(ctx, i.podOptions)
if err != nil {
cause := errors.Cause(err)
@@ -238,9 +236,12 @@ func (i *inspector) inspect(namesOrIDs []string) error {
}
func printJSON(data []interface{}) error {
- enc := json.NewEncoder(os.Stdout)
- enc.SetIndent("", " ")
- return enc.Encode(data)
+ buf, err := json.MarshalIndent(data, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = fmt.Println(string(buf))
+ return err
}
func printTmpl(typ, row string, data []interface{}) error {
diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go
index a9e91bd68..db70ad7d4 100644
--- a/cmd/podman/play/kube.go
+++ b/cmd/podman/play/kube.go
@@ -22,6 +22,7 @@ type playKubeOptionsWrapper struct {
TLSVerifyCLI bool
CredentialsCLI string
+ StartCLI bool
}
var (
@@ -68,6 +69,7 @@ func init() {
flags.BoolVarP(&kubeOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
flags.BoolVar(&kubeOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
+ flags.BoolVar(&kubeOptions.StartCLI, "start", true, "Start the pod after creating it")
authfileFlagName := "authfile"
flags.StringVar(&kubeOptions.Authfile, authfileFlagName, auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
@@ -100,6 +102,9 @@ func kube(cmd *cobra.Command, args []string) error {
if cmd.Flags().Changed("tls-verify") {
kubeOptions.SkipTLSVerify = types.NewOptionalBool(!kubeOptions.TLSVerifyCLI)
}
+ if cmd.Flags().Changed("start") {
+ kubeOptions.Start = types.NewOptionalBool(kubeOptions.StartCLI)
+ }
if kubeOptions.Authfile != "" {
if _, err := os.Stat(kubeOptions.Authfile); err != nil {
return err
diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go
index 84f9293d4..8c52616be 100644
--- a/cmd/podman/system/service_abi.go
+++ b/cmd/podman/system/service_abi.go
@@ -5,12 +5,8 @@ package system
import (
"context"
"net"
- "os"
- "os/signal"
"strings"
- "github.com/containers/podman/v2/cmd/podman/utils"
- "github.com/containers/podman/v2/libpod"
api "github.com/containers/podman/v2/pkg/api/server"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/domain/infra"
@@ -43,7 +39,7 @@ func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entiti
return err
}
- startWatcher(rt)
+ infra.StartWatcher(rt)
server, err := api.NewServerWithSettings(rt, opts.Timeout, listener)
if err != nil {
return err
@@ -60,24 +56,3 @@ func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entiti
}
return err
}
-
-// startWatcher starts a new SIGHUP go routine for the current config.
-func startWatcher(rt *libpod.Runtime) {
- // Setup the signal notifier
- ch := make(chan os.Signal, 1)
- signal.Notify(ch, utils.SIGHUP)
-
- go func() {
- for {
- // Block until the signal is received
- logrus.Debugf("waiting for SIGHUP to reload configuration")
- <-ch
- if err := rt.Reload(); err != nil {
- logrus.Errorf("unable to reload configuration: %v", err)
- continue
- }
- }
- }()
-
- logrus.Debugf("registered SIGHUP watcher for config")
-}
diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md
index e14d1ed79..67584ffcc 100644
--- a/docs/source/markdown/podman-play-kube.1.md
+++ b/docs/source/markdown/podman-play-kube.1.md
@@ -58,6 +58,10 @@ Suppress output information when pulling images
Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (Not available for remote commands)
+#### **--start**=*true|false*
+
+Start the pod after creating it, set to false to only create it.
+
#### **--tls-verify**=*true|false*
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index be0adfe6a..dcb2ff751 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -1296,10 +1296,6 @@ func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error {
}
ctrAliasesBkt := dbCtr.Bucket(aliasesBkt)
- if ctrAliasesBkt == nil {
- return errors.Wrapf(define.ErrNoAliases, "container %s has no network aliases", ctr.ID())
- }
-
ctrNetworksBkt := dbCtr.Bucket(networksBkt)
if ctrNetworksBkt == nil {
return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not connected to any CNI networks, so cannot disconnect", ctr.ID())
@@ -1313,13 +1309,15 @@ func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error {
return errors.Wrapf(err, "error removing container %s from network %s", ctr.ID(), network)
}
- bktExists := ctrAliasesBkt.Bucket([]byte(network))
- if bktExists == nil {
- return nil
- }
+ if ctrAliasesBkt != nil {
+ bktExists := ctrAliasesBkt.Bucket([]byte(network))
+ if bktExists == nil {
+ return nil
+ }
- if err := ctrAliasesBkt.DeleteBucket([]byte(network)); err != nil {
- return errors.Wrapf(err, "error removing container %s network aliases for network %s", ctr.ID(), network)
+ if err := ctrAliasesBkt.DeleteBucket([]byte(network)); err != nil {
+ return errors.Wrapf(err, "error removing container %s network aliases for network %s", ctr.ID(), network)
+ }
}
return nil
diff --git a/libpod/container.go b/libpod/container.go
index 333e1d848..9009a4ec8 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -1088,3 +1088,17 @@ func (c *Container) networks() ([]string, error) {
return networks, err
}
+
+// networksByNameIndex provides us with a map of container networks where key
+// is network name and value is the index position
+func (c *Container) networksByNameIndex() (map[string]int, error) {
+ networks, err := c.networks()
+ if err != nil {
+ return nil, err
+ }
+ networkNamesByIndex := make(map[string]int, len(networks))
+ for index, name := range networks {
+ networkNamesByIndex[name] = index
+ }
+ return networkNamesByIndex, nil
+}
diff --git a/libpod/network/create.go b/libpod/network/create.go
index c11904ecf..387f4fcd3 100644
--- a/libpod/network/create.go
+++ b/libpod/network/create.go
@@ -8,7 +8,7 @@ import (
"path/filepath"
"github.com/containernetworking/cni/pkg/version"
- "github.com/containers/podman/v2/libpod"
+ "github.com/containers/common/pkg/config"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/rootless"
"github.com/containers/podman/v2/pkg/util"
@@ -16,25 +16,21 @@ import (
)
// Create the CNI network
-func Create(name string, options entities.NetworkCreateOptions, r *libpod.Runtime) (*entities.NetworkCreateReport, error) {
+func Create(name string, options entities.NetworkCreateOptions, runtimeConfig *config.Config) (*entities.NetworkCreateReport, error) {
var fileName string
if err := isSupportedDriver(options.Driver); err != nil {
return nil, err
}
- config, err := r.GetConfig()
- if err != nil {
- return nil, err
- }
// Acquire a lock for CNI
- l, err := acquireCNILock(filepath.Join(config.Engine.TmpDir, LockFileName))
+ l, err := acquireCNILock(filepath.Join(runtimeConfig.Engine.TmpDir, LockFileName))
if err != nil {
return nil, err
}
defer l.releaseCNILock()
if len(options.MacVLAN) > 0 {
- fileName, err = createMacVLAN(r, name, options)
+ fileName, err = createMacVLAN(name, options, runtimeConfig)
} else {
- fileName, err = createBridge(r, name, options)
+ fileName, err = createBridge(name, options, runtimeConfig)
}
if err != nil {
return nil, err
@@ -81,17 +77,17 @@ func validateBridgeOptions(options entities.NetworkCreateOptions) error {
}
// createBridge creates a CNI network
-func createBridge(r *libpod.Runtime, name string, options entities.NetworkCreateOptions) (string, error) {
+func createBridge(name string, options entities.NetworkCreateOptions, runtimeConfig *config.Config) (string, error) {
+ var (
+ ipamRanges [][]IPAMLocalHostRangeConf
+ err error
+ routes []IPAMRoute
+ )
isGateway := true
ipMasq := true
- runtimeConfig, err := r.GetConfig()
- if err != nil {
- return "", err
- }
// validate options
- err = validateBridgeOptions(options)
- if err != nil {
+ if err := validateBridgeOptions(options); err != nil {
return "", err
}
@@ -102,8 +98,6 @@ func createBridge(r *libpod.Runtime, name string, options entities.NetworkCreate
subnet := &options.Subnet
ipRange := &options.Range
gateway := options.Gateway
- var ipamRanges [][]IPAMLocalHostRangeConf
- var routes []IPAMRoute
if subnet.IP != nil {
// if network is provided, does it conflict with existing CNI or live networks
err = ValidateUserNetworkIsAvailable(runtimeConfig, subnet)
@@ -201,7 +195,7 @@ func createBridge(r *libpod.Runtime, name string, options entities.NetworkCreate
return cniPathName, err
}
-func createMacVLAN(r *libpod.Runtime, name string, options entities.NetworkCreateOptions) (string, error) {
+func createMacVLAN(name string, options entities.NetworkCreateOptions, runtimeConfig *config.Config) (string, error) {
var (
plugins []CNIPlugins
)
@@ -210,17 +204,12 @@ func createMacVLAN(r *libpod.Runtime, name string, options entities.NetworkCreat
return "", err
}
- config, err := r.GetConfig()
- if err != nil {
- return "", err
- }
-
// Make sure the host-device exists
if !util.StringInSlice(options.MacVLAN, liveNetNames) {
return "", errors.Errorf("failed to find network interface %q", options.MacVLAN)
}
if len(name) > 0 {
- netNames, err := GetNetworkNamesFromFileSystem(config)
+ netNames, err := GetNetworkNamesFromFileSystem(runtimeConfig)
if err != nil {
return "", err
}
@@ -228,7 +217,7 @@ func createMacVLAN(r *libpod.Runtime, name string, options entities.NetworkCreat
return "", errors.Errorf("the network name %s is already used", name)
}
} else {
- name, err = GetFreeDeviceName(config)
+ name, err = GetFreeDeviceName(runtimeConfig)
if err != nil {
return "", err
}
@@ -241,7 +230,7 @@ func createMacVLAN(r *libpod.Runtime, name string, options entities.NetworkCreat
if err != nil {
return "", err
}
- cniPathName := filepath.Join(GetCNIConfDir(config), fmt.Sprintf("%s.conflist", name))
+ cniPathName := filepath.Join(GetCNIConfDir(runtimeConfig), fmt.Sprintf("%s.conflist", name))
err = ioutil.WriteFile(cniPathName, b, 0644)
return cniPathName, err
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index fed90cfc3..3882e095a 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -13,6 +13,7 @@ import (
"os"
"os/exec"
"path/filepath"
+ "sort"
"strings"
"syscall"
"time"
@@ -20,6 +21,7 @@ import (
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/libpod/network"
"github.com/containers/podman/v2/pkg/errorhandling"
"github.com/containers/podman/v2/pkg/netns"
"github.com/containers/podman/v2/pkg/rootless"
@@ -981,3 +983,139 @@ func (w *logrusDebugWriter) Write(p []byte) (int, error) {
logrus.Debugf("%s%s", w.prefix, string(p))
return len(p), nil
}
+
+// DisconnectContainerFromNetwork removes a container from its CNI network
+func (r *Runtime) DisconnectContainerFromNetwork(nameOrID, netName string, force bool) error {
+ ctr, err := r.LookupContainer(nameOrID)
+ if err != nil {
+ return err
+ }
+
+ networks, err := ctr.networksByNameIndex()
+ if err != nil {
+ return err
+ }
+
+ exists, err := network.Exists(r.config, netName)
+ if err != nil {
+ return err
+ }
+ if !exists {
+ return errors.Wrap(define.ErrNoSuchNetwork, netName)
+ }
+
+ index, nameExists := networks[netName]
+ if !nameExists && len(networks) > 0 {
+ return errors.Errorf("container %s is not connected to network %s", nameOrID, netName)
+ }
+
+ ctr.lock.Lock()
+ defer ctr.lock.Unlock()
+ if err := ctr.syncContainer(); err != nil {
+ return err
+ }
+
+ podConfig := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), []string{netName}, ctr.config.PortMappings, nil, nil)
+ if err := r.netPlugin.TearDownPod(podConfig); err != nil {
+ return err
+ }
+ if err := r.state.NetworkDisconnect(ctr, netName); err != nil {
+ return err
+ }
+
+ // update network status
+ networkStatus := ctr.state.NetworkStatus
+ // if len is one and we confirmed earlier that the container is in
+ // fact connected to the network, then just return an empty slice
+ if len(networkStatus) == 1 {
+ ctr.state.NetworkStatus = make([]*cnitypes.Result, 0)
+ } else {
+ // clip out the index of the network
+ networkStatus[len(networkStatus)-1], networkStatus[index] = networkStatus[index], networkStatus[len(networkStatus)-1]
+ // shorten the slice by one
+ ctr.state.NetworkStatus = networkStatus[:len(networkStatus)-1]
+ }
+ return nil
+}
+
+// ConnectContainerToNetwork connects a container to a CNI network
+func (r *Runtime) ConnectContainerToNetwork(nameOrID, netName string, aliases []string) error {
+ ctr, err := r.LookupContainer(nameOrID)
+ if err != nil {
+ return err
+ }
+
+ networks, err := ctr.networksByNameIndex()
+ if err != nil {
+ return err
+ }
+
+ exists, err := network.Exists(r.config, netName)
+ if err != nil {
+ return err
+ }
+ if !exists {
+ return errors.Wrap(define.ErrNoSuchNetwork, netName)
+ }
+
+ _, nameExists := networks[netName]
+ if !nameExists && len(networks) > 0 {
+ return errors.Errorf("container %s is not connected to network %s", nameOrID, netName)
+ }
+
+ ctr.lock.Lock()
+ defer ctr.lock.Unlock()
+ if err := ctr.syncContainer(); err != nil {
+ return err
+ }
+
+ if err := r.state.NetworkConnect(ctr, netName, aliases); err != nil {
+ return err
+ }
+
+ podConfig := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), []string{netName}, ctr.config.PortMappings, nil, nil)
+ podConfig.Aliases = make(map[string][]string, 1)
+ podConfig.Aliases[netName] = aliases
+ results, err := r.netPlugin.SetUpPod(podConfig)
+ if err != nil {
+ return err
+ }
+ if len(results) != 1 {
+ return errors.New("when adding aliases, results must be of length 1")
+ }
+
+ networkResults := make([]*cnitypes.Result, 0)
+ for _, r := range results {
+ resultCurrent, err := cnitypes.GetResult(r.Result)
+ if err != nil {
+ return errors.Wrapf(err, "error parsing CNI plugin result %q: %v", r.Result, err)
+ }
+ networkResults = append(networkResults, resultCurrent)
+ }
+
+ // update network status
+ networkStatus := ctr.state.NetworkStatus
+ // if len is one and we confirmed earlier that the container is in
+ // fact connected to the network, then just return an empty slice
+ if len(networkStatus) == 0 {
+ ctr.state.NetworkStatus = append(ctr.state.NetworkStatus, networkResults...)
+ } else {
+ // build a list of network names so we can sort and
+ // get the new name's index
+ var networkNames []string
+ for netName := range networks {
+ networkNames = append(networkNames, netName)
+ }
+ networkNames = append(networkNames, netName)
+ // sort
+ sort.Strings(networkNames)
+ // get index of new network name
+ index := sort.SearchStrings(networkNames, netName)
+ // Append a zero value to to the slice
+ networkStatus = append(networkStatus, &cnitypes.Result{})
+ // populate network status
+ copy(networkStatus[index+1:], networkStatus[index:])
+ networkStatus[index] = networkResults[0]
+ }
+ return nil
+}
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index abbb6d2c0..64ddebf9c 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -312,48 +312,40 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
}
// Connect adds a container to a network
-// TODO: For now this func is a no-op that checks the container name, network name, and
-// responds with a 200. This allows the call to remain intact. We need to decide how
-// we make this work with CNI networking and setup/teardown.
func Connect(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
- var netConnect types.NetworkConnect
+ var (
+ aliases []string
+ netConnect types.NetworkConnect
+ )
if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
- config, err := runtime.GetConfig()
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
name := utils.GetName(r)
- exists, err := network.Exists(config, name)
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
- if !exists {
- utils.Error(w, "network not found", http.StatusNotFound, define.ErrNoSuchNetwork)
- return
+ if netConnect.EndpointConfig != nil {
+ if netConnect.EndpointConfig.Aliases != nil {
+ aliases = netConnect.EndpointConfig.Aliases
+ }
}
- if _, err = runtime.LookupContainer(netConnect.Container); err != nil {
+ err := runtime.ConnectContainerToNetwork(netConnect.Container, name, aliases)
+ if err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr {
utils.ContainerNotFound(w, netConnect.Container, err)
return
}
- utils.Error(w, "unable to lookup container", http.StatusInternalServerError, err)
+ if errors.Cause(err) == define.ErrNoSuchNetwork {
+ utils.Error(w, "network not found", http.StatusNotFound, err)
+ return
+ }
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
return
}
- logrus.Warnf("network connect endpoint is not fully implemented - tried to connect container %s to network %s", netConnect.Container, name)
utils.WriteResponse(w, http.StatusOK, "OK")
}
// Disconnect removes a container from a network
-// TODO: For now this func is a no-op that checks the container name, network name, and
-// responds with a 200. This allows the call to remain intact. We need to decide how
-// we make this work with CNI networking and setup/teardown.
func Disconnect(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
@@ -362,29 +354,20 @@ func Disconnect(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
- config, err := runtime.GetConfig()
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
+
name := utils.GetName(r)
- exists, err := network.Exists(config, name)
+ err := runtime.DisconnectContainerFromNetwork(netDisconnect.Container, name, netDisconnect.Force)
if err != nil {
- utils.InternalServerError(w, err)
- return
- }
- if !exists {
- utils.Error(w, "network not found", http.StatusNotFound, define.ErrNoSuchNetwork)
- return
- }
- if _, err = runtime.LookupContainer(netDisconnect.Container); err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr {
- utils.ContainerNotFound(w, netDisconnect.Container, err)
+ utils.Error(w, "container not found", http.StatusNotFound, err)
+ return
+ }
+ if errors.Cause(err) == define.ErrNoSuchNetwork {
+ utils.Error(w, "network not found", http.StatusNotFound, err)
return
}
- utils.Error(w, "unable to lookup container", http.StatusInternalServerError, err)
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
return
}
- logrus.Warnf("network disconnect endpoint is not fully implemented - tried to connect container %s to network %s", netDisconnect.Container, name)
utils.WriteResponse(w, http.StatusOK, "OK")
}
diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go
index 0c7a6e19d..42ff26a57 100644
--- a/pkg/api/handlers/libpod/play.go
+++ b/pkg/api/handlers/libpod/play.go
@@ -23,8 +23,10 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
Network string `schema:"reference"`
TLSVerify bool `schema:"tlsVerify"`
LogDriver string `schema:"logDriver"`
+ Start bool `schema:"start"`
}{
TLSVerify: true,
+ Start: true,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
@@ -73,6 +75,9 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
if _, found := r.URL.Query()["tlsVerify"]; found {
options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
}
+ if _, found := r.URL.Query()["start"]; found {
+ options.Start = types.NewOptionalBool(query.Start)
+ }
report, err := containerEngine.PlayKube(r.Context(), tmpfile.Name(), options)
if err != nil {
diff --git a/pkg/api/server/register_play.go b/pkg/api/server/register_play.go
index e41f8311d..6aa349a3b 100644
--- a/pkg/api/server/register_play.go
+++ b/pkg/api/server/register_play.go
@@ -29,6 +29,11 @@ func (s *APIServer) registerPlayHandlers(r *mux.Router) error {
// name: logDriver
// type: string
// description: Logging driver for the containers in the pod.
+ // - in: query
+ // name: start
+ // type: boolean
+ // default: true
+ // description: Start the pod after creating it.
// - in: body
// name: request
// description: Kubernetes YAML file.
diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go
index 8af3b8fb1..cfb40d74b 100644
--- a/pkg/bindings/play/play.go
+++ b/pkg/bindings/play/play.go
@@ -30,7 +30,10 @@ func Kube(ctx context.Context, path string, options entities.PlayKubeOptions) (*
params.Set("network", options.Network)
params.Set("logDriver", options.LogDriver)
if options.SkipTLSVerify != types.OptionalBoolUndefined {
- params.Set("tlsVerify", strconv.FormatBool(options.SkipTLSVerify == types.OptionalBoolTrue))
+ params.Set("tlsVerify", strconv.FormatBool(options.SkipTLSVerify != types.OptionalBoolTrue))
+ }
+ if options.Start != types.OptionalBoolUndefined {
+ params.Set("start", strconv.FormatBool(options.Start == types.OptionalBoolTrue))
}
// TODO: have a global system context we can pass around (1st argument)
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index 7e4afcc28..0b42e1a3f 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -28,6 +28,8 @@ type PlayKubeOptions struct {
ConfigMaps []string
// LogDriver for the container. For example: journald
LogDriver string
+ // Start - don't start the pod if false
+ Start types.OptionalBool
}
// PlayKubePod represents a single pod and associated containers created by play kube
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index 4f572fb88..06941f8d0 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -110,7 +110,11 @@ func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, o
}
func (ic *ContainerEngine) NetworkCreate(ctx context.Context, name string, options entities.NetworkCreateOptions) (*entities.NetworkCreateReport, error) {
- return network.Create(name, options, ic.Libpod)
+ runtimeConfig, err := ic.Libpod.GetConfig()
+ if err != nil {
+ return nil, err
+ }
+ return network.Create(name, options, runtimeConfig)
}
func ifPassesFilterTest(netconf *libcni.NetworkConfigList, filter []string) bool {
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index c0948e099..4bcc6469c 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -297,20 +297,22 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
containers = append(containers, ctr)
}
- //start the containers
- podStartErrors, err := pod.Start(ctx)
- if err != nil {
- return nil, err
- }
+ if options.Start != types.OptionalBoolFalse {
+ //start the containers
+ podStartErrors, err := pod.Start(ctx)
+ if err != nil {
+ return nil, err
+ }
- // Previous versions of playkube started containers individually and then
- // looked for errors. Because we now use the uber-Pod start call, we should
- // iterate the map of possible errors and return one if there is a problem. This
- // keeps the behavior the same
+ // Previous versions of playkube started containers individually and then
+ // looked for errors. Because we now use the uber-Pod start call, we should
+ // iterate the map of possible errors and return one if there is a problem. This
+ // keeps the behavior the same
- for _, e := range podStartErrors {
- if e != nil {
- return nil, e
+ for _, e := range podStartErrors {
+ if e != nil {
+ return nil, e
+ }
}
}
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index 26c9c7e2e..b786a5fbf 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -6,8 +6,10 @@ import (
"context"
"fmt"
"os"
+ "os/signal"
"sync"
+ "github.com/containers/podman/v2/cmd/podman/utils"
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/pkg/cgroups"
"github.com/containers/podman/v2/pkg/domain/entities"
@@ -16,6 +18,7 @@ import (
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
flag "github.com/spf13/pflag"
)
@@ -348,3 +351,24 @@ func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []strin
}
return &options, nil
}
+
+// StartWatcher starts a new SIGHUP go routine for the current config.
+func StartWatcher(rt *libpod.Runtime) {
+ // Setup the signal notifier
+ ch := make(chan os.Signal, 1)
+ signal.Notify(ch, utils.SIGHUP)
+
+ go func() {
+ for {
+ // Block until the signal is received
+ logrus.Debugf("waiting for SIGHUP to reload configuration")
+ <-ch
+ if err := rt.Reload(); err != nil {
+ logrus.Errorf("unable to reload configuration: %v", err)
+ continue
+ }
+ }
+ }()
+
+ logrus.Debugf("registered SIGHUP watcher for config")
+}
diff --git a/test/apiv2/rest_api/test_rest_v2_0_0.py b/test/apiv2/rest_api/test_rest_v2_0_0.py
index 7192347c7..49e18f063 100644
--- a/test/apiv2/rest_api/test_rest_v2_0_0.py
+++ b/test/apiv2/rest_api/test_rest_v2_0_0.py
@@ -187,12 +187,14 @@ class TestApi(unittest.TestCase):
payload = json.loads(create.text)
self.assertIsNotNone(payload["Id"])
- connect = requests.post(
- PODMAN_URL + "/v1.40/networks/TestNetwork/connect",
- json={"Container": payload["Id"]},
- )
- self.assertEqual(connect.status_code, 200, create.text)
- self.assertEqual(connect.text, "OK\n")
+ # This cannot be done until full completion of the network connect
+ # stack and network disconnect stack are complete
+ # connect = requests.post(
+ # PODMAN_URL + "/v1.40/networks/TestNetwork/connect",
+ # json={"Container": payload["Id"]},
+ # )
+ # self.assertEqual(connect.status_code, 200, connect.text)
+ # self.assertEqual(connect.text, "OK\n")
def test_commit(self):
r = requests.post(_url(ctnr("/commit?container={}")))
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 7ae474c76..92e4544f9 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -1482,4 +1482,19 @@ MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.OutputToString()).To(ContainSubstring("journald"))
})
+
+ It("podman play kube test only creating the containers", func() {
+ pod := getPod()
+ err := generateKubeYaml("pod", pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", "--start=false", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .State.Running }}"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(Equal("false"))
+ })
})
diff --git a/test/e2e/pod_pod_namespaces.go b/test/e2e/pod_pod_namespaces_test.go
index 20b8bdb39..20b8bdb39 100644
--- a/test/e2e/pod_pod_namespaces.go
+++ b/test/e2e/pod_pod_namespaces_test.go
diff --git a/test/e2e/run_seccomp.go b/test/e2e/run_seccomp_test.go
index 7d04cc60a..7d04cc60a 100644
--- a/test/e2e/run_seccomp.go
+++ b/test/e2e/run_seccomp_test.go
diff --git a/test/e2e/run_security_labels.go b/test/e2e/run_security_labels_test.go
index 0c5621e3f..0c5621e3f 100644
--- a/test/e2e/run_security_labels.go
+++ b/test/e2e/run_security_labels_test.go
diff --git a/test/e2e/run_working_dir.go b/test/e2e/run_working_dir_test.go
index 7d8db361c..7d8db361c 100644
--- a/test/e2e/run_working_dir.go
+++ b/test/e2e/run_working_dir_test.go
diff --git a/test/python/docker/test_containers.py b/test/python/docker/test_containers.py
index 5fb340fd4..0fd419d9d 100644
--- a/test/python/docker/test_containers.py
+++ b/test/python/docker/test_containers.py
@@ -60,10 +60,14 @@ class TestContainers(unittest.TestCase):
def test_create_network(self):
net = self.client.networks.create("testNetwork", driver="bridge")
ctnr = self.client.containers.create(image="alpine", detach=True)
- net.connect(ctnr)
- nets = self.client.networks.list(greedy=True)
- self.assertGreaterEqual(len(nets), 1)
+ # TODO fix when ready
+ # This test will not work until all connect|disconnect
+ # code is fixed.
+ # net.connect(ctnr)
+
+ # nets = self.client.networks.list(greedy=True)
+ # self.assertGreaterEqual(len(nets), 1)
# TODO fix endpoint to include containers
# for n in nets: