aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/netflags.go2
-rw-r--r--cmd/podman/common/util.go4
-rw-r--r--cmd/podman/containers/restore.go24
-rw-r--r--docs/source/markdown/podman-container-restore.1.md15
-rw-r--r--pkg/checkpoint/checkpoint_restore.go9
-rw-r--r--pkg/domain/entities/containers.go1
-rw-r--r--pkg/specgen/generate/pod_create.go2
-rw-r--r--pkg/specgen/generate/ports.go4
-rw-r--r--test/e2e/checkpoint_test.go54
9 files changed, 104 insertions, 11 deletions
diff --git a/cmd/podman/common/netflags.go b/cmd/podman/common/netflags.go
index 4f634f355..78cfe2f13 100644
--- a/cmd/podman/common/netflags.go
+++ b/cmd/podman/common/netflags.go
@@ -170,7 +170,7 @@ func NetFlagsToNetOptions(cmd *cobra.Command, netnsFromConfig bool) (*entities.N
return nil, err
}
if len(inputPorts) > 0 {
- opts.PublishPorts, err = createPortBindings(inputPorts)
+ opts.PublishPorts, err = CreatePortBindings(inputPorts)
if err != nil {
return nil, err
}
diff --git a/cmd/podman/common/util.go b/cmd/podman/common/util.go
index afee55914..6a0af4dff 100644
--- a/cmd/podman/common/util.go
+++ b/cmd/podman/common/util.go
@@ -89,8 +89,8 @@ func createExpose(expose []string) (map[uint16]string, error) {
return toReturn, nil
}
-// createPortBindings iterates ports mappings into SpecGen format.
-func createPortBindings(ports []string) ([]specgen.PortMapping, error) {
+// CreatePortBindings iterates ports mappings into SpecGen format.
+func CreatePortBindings(ports []string) ([]specgen.PortMapping, error) {
// --publish is formatted as follows:
// [[hostip:]hostport[-endPort]:]containerport[-endPort][/protocol]
toReturn := make([]specgen.PortMapping, 0, len(ports))
diff --git a/cmd/podman/containers/restore.go b/cmd/podman/containers/restore.go
index 3b1848abb..b908ea493 100644
--- a/cmd/podman/containers/restore.go
+++ b/cmd/podman/containers/restore.go
@@ -36,9 +36,7 @@ var (
}
)
-var (
- restoreOptions entities.RestoreOptions
-)
+var restoreOptions entities.RestoreOptions
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
@@ -66,10 +64,17 @@ func init() {
flags.BoolVar(&restoreOptions.IgnoreStaticIP, "ignore-static-ip", false, "Ignore IP address set via --static-ip")
flags.BoolVar(&restoreOptions.IgnoreStaticMAC, "ignore-static-mac", false, "Ignore MAC address set via --mac-address")
flags.BoolVar(&restoreOptions.IgnoreVolumes, "ignore-volumes", false, "Do not export volumes associated with container")
+
+ flags.StringSliceP(
+ "publish", "p", []string{},
+ "Publish a container's port, or a range of ports, to the host (default [])",
+ )
+ _ = restoreCommand.RegisterFlagCompletionFunc("publish", completion.AutocompleteNone)
+
validate.AddLatestFlag(restoreCommand, &restoreOptions.Latest)
}
-func restore(_ *cobra.Command, args []string) error {
+func restore(cmd *cobra.Command, args []string) error {
var errs utils.OutputErrors
if rootless.IsRootless() {
return errors.New("restoring a container requires root")
@@ -90,6 +95,17 @@ func restore(_ *cobra.Command, args []string) error {
return errors.Errorf("--tcp-established cannot be used with --name")
}
+ inputPorts, err := cmd.Flags().GetStringSlice("publish")
+ if err != nil {
+ return err
+ }
+ if len(inputPorts) > 0 {
+ restoreOptions.PublishPorts, err = common.CreatePortBindings(inputPorts)
+ if err != nil {
+ return err
+ }
+ }
+
argLen := len(args)
if restoreOptions.Import != "" {
if restoreOptions.All || restoreOptions.Latest {
diff --git a/docs/source/markdown/podman-container-restore.1.md b/docs/source/markdown/podman-container-restore.1.md
index ef8722279..82bf76d1e 100644
--- a/docs/source/markdown/podman-container-restore.1.md
+++ b/docs/source/markdown/podman-container-restore.1.md
@@ -95,6 +95,19 @@ This option must be used in combination with the **--import, -i** option.
When restoring containers from a checkpoint tar.gz file with this option,
the content of associated volumes will not be restored.
+#### **--publish**, **-p**
+
+Replaces the ports that the container publishes, as configured during the
+initial container start, with a new set of port forwarding rules.
+
+```
+# podman run --rm -p 2345:80 -d webserver
+# podman container checkpoint -l --export=dump.tar
+# podman container restore -p 5432:8080 --import=dump.tar
+```
+
+For more details please see **podman run --publish**.
+
## EXAMPLE
podman container restore mywebserver
@@ -104,7 +117,7 @@ podman container restore 860a4b23
podman container restore --import-previous pre-checkpoint.tar.gz --import checkpoint.tar.gz
## SEE ALSO
-podman(1), podman-container-checkpoint(1)
+podman(1), podman-container-checkpoint(1), podman-run(1)
## HISTORY
September 2018, Originally compiled by Adrian Reber <areber@redhat.com>
diff --git a/pkg/checkpoint/checkpoint_restore.go b/pkg/checkpoint/checkpoint_restore.go
index 7a8f71c66..0d45cab5f 100644
--- a/pkg/checkpoint/checkpoint_restore.go
+++ b/pkg/checkpoint/checkpoint_restore.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/errorhandling"
+ "github.com/containers/podman/v3/pkg/specgen/generate"
"github.com/containers/storage/pkg/archive"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
@@ -95,6 +96,14 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
newName = true
}
+ if len(restoreOptions.PublishPorts) > 0 {
+ ports, _, _, err := generate.ParsePortMapping(restoreOptions.PublishPorts)
+ if err != nil {
+ return nil, err
+ }
+ ctrConfig.PortMappings = ports
+ }
+
pullOptions := &libimage.PullOptions{}
pullOptions.Writer = os.Stderr
if _, err := runtime.LibimageRuntime().Pull(ctx, ctrConfig.RootfsImageName, config.PullPolicyMissing, pullOptions); err != nil {
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index bae55e64f..8ed9b9b61 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -199,6 +199,7 @@ type RestoreOptions struct {
Name string
TCPEstablished bool
ImportPrevious string
+ PublishPorts []specgen.PortMapping
}
type RestoreReport struct {
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index 20151f016..07c56b799 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -125,7 +125,7 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod
options = append(options, libpod.WithPodUseImageHosts())
}
if len(p.PortMappings) > 0 {
- ports, _, _, err := parsePortMapping(p.PortMappings)
+ ports, _, _, err := ParsePortMapping(p.PortMappings)
if err != nil {
return nil, err
}
diff --git a/pkg/specgen/generate/ports.go b/pkg/specgen/generate/ports.go
index 8745f0dad..c00ad19fb 100644
--- a/pkg/specgen/generate/ports.go
+++ b/pkg/specgen/generate/ports.go
@@ -24,7 +24,7 @@ const (
// Parse port maps to OCICNI port mappings.
// Returns a set of OCICNI port mappings, and maps of utilized container and
// host ports.
-func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping, map[string]map[string]map[uint16]uint16, map[string]map[string]map[uint16]uint16, error) {
+func ParsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping, map[string]map[string]map[uint16]uint16, map[string]map[string]map[uint16]uint16, error) {
// First, we need to validate the ports passed in the specgen, and then
// convert them into CNI port mappings.
type tempMapping struct {
@@ -254,7 +254,7 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping,
// Make final port mappings for the container
func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData *libimage.ImageData) ([]ocicni.PortMapping, error) {
- finalMappings, containerPortValidate, hostPortValidate, err := parsePortMapping(s.PortMappings)
+ finalMappings, containerPortValidate, hostPortValidate, err := ParsePortMapping(s.PortMappings)
if err != nil {
return nil, err
}
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 4aca3682b..70a1d09ed 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -922,4 +922,58 @@ var _ = Describe("Podman checkpoint", func() {
os.Remove(checkpointFileName)
os.Remove(preCheckpointFileName)
})
+
+ It("podman checkpoint and restore container with different port mappings", func() {
+ localRunString := getRunString([]string{"-p", "1234:6379", "--rm", redis})
+ session := podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ cid := session.OutputToString()
+ fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
+
+ // Open a network connection to the redis server via initial port mapping
+ conn, err := net.Dial("tcp", "localhost:1234")
+ if err != nil {
+ os.Exit(1)
+ }
+ conn.Close()
+
+ // Checkpoint the container
+ result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
+ result.WaitWithDefaultTimeout()
+
+ // As the container has been started with '--rm' it will be completely
+ // cleaned up after checkpointing.
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(0))
+
+ // Restore container with different port mapping
+ result = podmanTest.Podman([]string{"container", "restore", "-p", "1235:6379", "-i", fileName})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+
+ // Open a network connection to the redis server via initial port mapping
+ // This should fail
+ conn, err = net.Dial("tcp", "localhost:1234")
+ Expect(err.Error()).To(ContainSubstring("connection refused"))
+ // Open a network connection to the redis server via new port mapping
+ conn, err = net.Dial("tcp", "localhost:1235")
+ if err != nil {
+ os.Exit(1)
+ }
+ conn.Close()
+
+ result = podmanTest.Podman([]string{"rm", "-fa"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(0))
+
+ // Remove exported checkpoint
+ os.Remove(fileName)
+ })
})