mirror of
https://github.com/containers/podman.git
synced 2025-06-23 02:18:13 +08:00
podman kube play --replace should force removal of pods and containers
Fixes: https://github.com/containers/podman/issues/20025 Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
@ -25,6 +25,7 @@ func KubePlay(w http.ResponseWriter, r *http.Request) {
|
|||||||
Network []string `schema:"network"`
|
Network []string `schema:"network"`
|
||||||
NoHosts bool `schema:"noHosts"`
|
NoHosts bool `schema:"noHosts"`
|
||||||
NoTrunc bool `schema:"noTrunc"`
|
NoTrunc bool `schema:"noTrunc"`
|
||||||
|
Replace bool `schema:"replace"`
|
||||||
PublishPorts []string `schema:"publishPorts"`
|
PublishPorts []string `schema:"publishPorts"`
|
||||||
ServiceContainer bool `schema:"serviceContainer"`
|
ServiceContainer bool `schema:"serviceContainer"`
|
||||||
Start bool `schema:"start"`
|
Start bool `schema:"start"`
|
||||||
@ -97,6 +98,7 @@ func KubePlay(w http.ResponseWriter, r *http.Request) {
|
|||||||
Password: password,
|
Password: password,
|
||||||
PublishPorts: query.PublishPorts,
|
PublishPorts: query.PublishPorts,
|
||||||
Quiet: true,
|
Quiet: true,
|
||||||
|
Replace: query.Replace,
|
||||||
ServiceContainer: query.ServiceContainer,
|
ServiceContainer: query.ServiceContainer,
|
||||||
StaticIPs: staticIPs,
|
StaticIPs: staticIPs,
|
||||||
StaticMACs: staticMACs,
|
StaticMACs: staticMACs,
|
||||||
|
@ -17,31 +17,53 @@ func (s *APIServer) registerKubeHandlers(r *mux.Router) error {
|
|||||||
// description: Create and run pods based on a Kubernetes YAML file (pod or service kind).
|
// description: Create and run pods based on a Kubernetes YAML file (pod or service kind).
|
||||||
// parameters:
|
// parameters:
|
||||||
// - in: query
|
// - in: query
|
||||||
|
// name: logDriver
|
||||||
|
// type: string
|
||||||
|
// description: Logging driver for the containers in the pod.
|
||||||
|
// - in: query
|
||||||
|
// name: logOptions
|
||||||
|
// type: array
|
||||||
|
// description: logging driver options
|
||||||
|
// items:
|
||||||
|
// type: string
|
||||||
|
// - in: query
|
||||||
// name: network
|
// name: network
|
||||||
// type: array
|
// type: array
|
||||||
// description: USe the network mode or specify an array of networks.
|
// description: USe the network mode or specify an array of networks.
|
||||||
// items:
|
// items:
|
||||||
// type: string
|
// type: string
|
||||||
// - in: query
|
// - in: query
|
||||||
// name: tlsVerify
|
// name: noHosts
|
||||||
// type: boolean
|
// type: boolean
|
||||||
// default: true
|
// default: false
|
||||||
// description: Require HTTPS and verify signatures when contacting registries.
|
// description: do not setup /etc/hosts file in container
|
||||||
// - in: query
|
// - in: query
|
||||||
// name: logDriver
|
// name: noTrunc
|
||||||
|
// type: boolean
|
||||||
|
// default: false
|
||||||
|
// description: use annotations that are not truncated to the Kubernetes maximum length of 63 characters
|
||||||
|
// - in: query
|
||||||
|
// name: publishPorts
|
||||||
|
// type: array
|
||||||
|
// description: publish a container's port, or a range of ports, to the host
|
||||||
|
// items:
|
||||||
// type: string
|
// type: string
|
||||||
// description: Logging driver for the containers in the pod.
|
|
||||||
// - in: query
|
// - in: query
|
||||||
// name: start
|
// name: replace
|
||||||
// type: boolean
|
// type: boolean
|
||||||
// default: true
|
// default: false
|
||||||
// description: Start the pod after creating it.
|
// description: replace existing pods and containers
|
||||||
// - in: query
|
// - in: query
|
||||||
// name: serviceContainer
|
// name: serviceContainer
|
||||||
// type: boolean
|
// type: boolean
|
||||||
// default: false
|
// default: false
|
||||||
// description: Starts a service container before all pods.
|
// description: Starts a service container before all pods.
|
||||||
// - in: query
|
// - in: query
|
||||||
|
// name: start
|
||||||
|
// type: boolean
|
||||||
|
// default: true
|
||||||
|
// description: Start the pod after creating it.
|
||||||
|
// - in: query
|
||||||
// name: staticIPs
|
// name: staticIPs
|
||||||
// type: array
|
// type: array
|
||||||
// description: Static IPs used for the pods.
|
// description: Static IPs used for the pods.
|
||||||
@ -54,19 +76,19 @@ func (s *APIServer) registerKubeHandlers(r *mux.Router) error {
|
|||||||
// items:
|
// items:
|
||||||
// type: string
|
// type: string
|
||||||
// - in: query
|
// - in: query
|
||||||
// name: wait
|
// name: tlsVerify
|
||||||
// type: boolean
|
// type: boolean
|
||||||
// default: false
|
// default: true
|
||||||
// description: Clean up all objects created when a SIGTERM is received or pods exit.
|
// description: Require HTTPS and verify signatures when contacting registries.
|
||||||
// - in: query
|
|
||||||
// name: noTrunc
|
|
||||||
// type: boolean
|
|
||||||
// default: false
|
|
||||||
// description: use annotations that are not truncated to the Kubernetes maximum length of 63 characters
|
|
||||||
// - in: query
|
// - in: query
|
||||||
// name: userns
|
// name: userns
|
||||||
// type: string
|
// type: string
|
||||||
// description: Set the user namespace mode for the pods.
|
// description: Set the user namespace mode for the pods.
|
||||||
|
// - in: query
|
||||||
|
// name: wait
|
||||||
|
// type: boolean
|
||||||
|
// default: false
|
||||||
|
// description: Clean up all objects created when a SIGTERM is received or pods exit.
|
||||||
// - in: body
|
// - in: body
|
||||||
// name: request
|
// name: request
|
||||||
// description: Kubernetes YAML file.
|
// description: Kubernetes YAML file.
|
||||||
|
@ -42,6 +42,8 @@ type PlayOptions struct {
|
|||||||
LogDriver *string
|
LogDriver *string
|
||||||
// LogOptions for the container. For example: journald
|
// LogOptions for the container. For example: journald
|
||||||
LogOptions *[]string
|
LogOptions *[]string
|
||||||
|
// Replace - replace existing pods and containers
|
||||||
|
Replace *bool
|
||||||
// Start - don't start the pod if false
|
// Start - don't start the pod if false
|
||||||
Start *bool
|
Start *bool
|
||||||
// NoTrunc - use annotations that were not truncated to the
|
// NoTrunc - use annotations that were not truncated to the
|
||||||
|
@ -258,6 +258,21 @@ func (o *PlayOptions) GetLogOptions() []string {
|
|||||||
return *o.LogOptions
|
return *o.LogOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithReplace set field Replace to given value
|
||||||
|
func (o *PlayOptions) WithReplace(value bool) *PlayOptions {
|
||||||
|
o.Replace = &value
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReplace returns value of field Replace
|
||||||
|
func (o *PlayOptions) GetReplace() bool {
|
||||||
|
if o.Replace == nil {
|
||||||
|
var z bool
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
return *o.Replace
|
||||||
|
}
|
||||||
|
|
||||||
// WithStart set field Start to given value
|
// WithStart set field Start to given value
|
||||||
func (o *PlayOptions) WithStart(value bool) *PlayOptions {
|
func (o *PlayOptions) WithStart(value bool) *PlayOptions {
|
||||||
o.Start = &value
|
o.Start = &value
|
||||||
|
@ -109,6 +109,12 @@ func (ic *ContainerEngine) createServiceContainer(ctx context.Context, name stri
|
|||||||
// via the `sdNotifyAnnotation` annotation in the K8s YAML.
|
// via the `sdNotifyAnnotation` annotation in the K8s YAML.
|
||||||
opts = append(opts, libpod.WithSdNotifyMode(define.SdNotifyModeIgnore))
|
opts = append(opts, libpod.WithSdNotifyMode(define.SdNotifyModeIgnore))
|
||||||
|
|
||||||
|
if options.Replace {
|
||||||
|
if _, err := ic.ContainerRm(ctx, []string{spec.Name}, entities.RmOptions{Force: true, Ignore: true}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new libpod container based on the spec.
|
// Create a new libpod container based on the spec.
|
||||||
ctr, err := ic.Libpod.NewContainer(ctx, runtimeSpec, spec, false, opts...)
|
ctr, err := ic.Libpod.NewContainer(ctx, runtimeSpec, spec, false, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -813,6 +819,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
opts = append(opts, libpod.WithSdNotifyMode(define.SdNotifyModeIgnore))
|
opts = append(opts, libpod.WithSdNotifyMode(define.SdNotifyModeIgnore))
|
||||||
|
if options.Replace {
|
||||||
|
if _, err := ic.ContainerRm(ctx, []string{spec.Name}, entities.RmOptions{Force: true, Ignore: true}); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...)
|
ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -913,6 +925,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||||||
opts = append(opts, libpod.WithSdNotifySocket(proxy.SocketPath()))
|
opts = append(opts, libpod.WithSdNotifySocket(proxy.SocketPath()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.Replace {
|
||||||
|
if _, err := ic.ContainerRm(ctx, []string{spec.Name}, entities.RmOptions{Force: true, Ignore: true}); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...)
|
ctr, err := generate.ExecuteCreate(ctx, ic.Libpod, rtSpec, spec, false, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -1516,7 +1534,7 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, opt
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
reports.RmReport, err = ic.PodRm(ctx, podNames, entities.PodRmOptions{Ignore: true})
|
reports.RmReport, err = ic.PodRm(ctx, podNames, entities.PodRmOptions{Ignore: true, Force: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, opts en
|
|||||||
options := new(kube.PlayOptions).WithAuthfile(opts.Authfile).WithUsername(opts.Username).WithPassword(opts.Password)
|
options := new(kube.PlayOptions).WithAuthfile(opts.Authfile).WithUsername(opts.Username).WithPassword(opts.Password)
|
||||||
options.WithCertDir(opts.CertDir).WithQuiet(opts.Quiet).WithSignaturePolicy(opts.SignaturePolicy).WithConfigMaps(opts.ConfigMaps)
|
options.WithCertDir(opts.CertDir).WithQuiet(opts.Quiet).WithSignaturePolicy(opts.SignaturePolicy).WithConfigMaps(opts.ConfigMaps)
|
||||||
options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Networks).WithSeccompProfileRoot(opts.SeccompProfileRoot)
|
options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Networks).WithSeccompProfileRoot(opts.SeccompProfileRoot)
|
||||||
options.WithStaticIPs(opts.StaticIPs).WithStaticMACs(opts.StaticMACs).WithWait(opts.Wait).WithServiceContainer(opts.ServiceContainer)
|
options.WithStaticIPs(opts.StaticIPs).WithStaticMACs(opts.StaticMACs).WithWait(opts.Wait).WithServiceContainer(opts.ServiceContainer).WithReplace(opts.Replace)
|
||||||
if len(opts.LogOptions) > 0 {
|
if len(opts.LogOptions) > 0 {
|
||||||
options.WithLogOptions(opts.LogOptions)
|
options.WithLogOptions(opts.LogOptions)
|
||||||
}
|
}
|
||||||
|
@ -411,6 +411,27 @@ _EOF
|
|||||||
run_podman rmi -f userimage:latest
|
run_podman rmi -f userimage:latest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Ocassionaly a remnant storage container is left behind which causes
|
||||||
|
# podman play kube --replace to fail. This tests created a conflicting
|
||||||
|
# storage container name using buildah to make sure --replace, still
|
||||||
|
# functions proplery by removing the storage container.
|
||||||
|
@test "podman kube play --replace external storage" {
|
||||||
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
||||||
|
mkdir -p $TESTDIR
|
||||||
|
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
||||||
|
run_podman play kube $PODMAN_TMPDIR/test.yaml
|
||||||
|
# Force removal of container
|
||||||
|
run_podman rm --force -t0 test_pod-test
|
||||||
|
# Create external container using buildah with same name
|
||||||
|
buildah from --name test_pod-test $IMAGE
|
||||||
|
# --replace deletes the buildah container and replace it with new one
|
||||||
|
run_podman play kube --replace $PODMAN_TMPDIR/test.yaml
|
||||||
|
|
||||||
|
run_podman stop -a -t 0
|
||||||
|
run_podman pod rm -t 0 -f test_pod
|
||||||
|
run_podman rmi -f userimage:latest
|
||||||
|
}
|
||||||
|
|
||||||
@test "podman kube --annotation" {
|
@test "podman kube --annotation" {
|
||||||
TESTDIR=$PODMAN_TMPDIR/testdir
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
||||||
RANDOMSTRING=$(random_string 15)
|
RANDOMSTRING=$(random_string 15)
|
||||||
|
Reference in New Issue
Block a user