aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorMatthew Heon <mheon@redhat.com>2021-01-12 14:29:27 -0500
committerMatthew Heon <mheon@redhat.com>2021-01-14 18:29:28 -0500
commit997de2f8e9e5453a99108bde012aa6c41d7323ec (patch)
tree499660321cf95f726636fcdd3dd4a8afbb86e2f5 /pkg
parent2b7793b6121d336a285fb7b9a7612c221cbf63d2 (diff)
downloadpodman-997de2f8e9e5453a99108bde012aa6c41d7323ec.tar.gz
podman-997de2f8e9e5453a99108bde012aa6c41d7323ec.tar.bz2
podman-997de2f8e9e5453a99108bde012aa6c41d7323ec.zip
Initial implementation of renaming containers
Basic theory: We remove the container, but *only from the DB*. We leave it in c/storage, we leave the lock allocated, we leave it running (if it is). Then we create an identical container with an altered name, and add that back to the database. Theoretically we now have a renamed container. The advantage of this approach is that it doesn't just apply to rename - we can use this to make *any* configuration change to a container that does not alter its container ID. Potential problems are numerous. This process is *THOROUGHLY* non-atomic at present - if you `kill -9` Podman mid-rename things will be in a bad place, for example. Also, we can't rename containers that can't be removed normally - IE, containers with dependencies (pod infra containers, for example). The largest potential improvement will be to move the majority of the work into the DB, with a `RecreateContainer()` method - that will add atomicity, and let us remove the container without worrying about depencies and similar issues. Potential problems: long-running processes that edit the DB and may have an older version of the configuration around. Most notable example is `podman run --rm` - the removal command needed to be manually edited to avoid this one. This begins to get at the heart of me not wanting to do this in the first place... This provides CLI and API implementations for frontend, but no tunnel implementation. It will be added in a future release (just held back for time now - we need this in 3.0 and are running low on time). This is honestly kind of horrifying, but I think it will work. Signed-off-by: Matthew Heon <mheon@redhat.com>
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/containers.go31
-rw-r--r--pkg/api/server/register_containers.go62
-rw-r--r--pkg/domain/entities/containers.go6
-rw-r--r--pkg/domain/entities/engine_container.go1
-rw-r--r--pkg/domain/infra/abi/containers.go16
-rw-r--r--pkg/domain/infra/tunnel/containers.go5
6 files changed, 117 insertions, 4 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 0f89c859e..6e1945db1 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -465,3 +465,34 @@ func formatCapabilities(slice []string) {
slice[i] = strings.TrimPrefix(slice[i], "CAP_")
}
}
+
+func RenameContainer(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+
+ name := utils.GetName(r)
+ query := struct {
+ Name string `schema:"name"`
+ }{}
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
+ utils.ContainerNotFound(w, name, err)
+ return
+ }
+
+ if _, err := runtime.RenameContainer(r.Context(), ctr, query.Name); err != nil {
+ if errors.Cause(err) == define.ErrPodExists || errors.Cause(err) == define.ErrCtrExists {
+ utils.Error(w, "Something went wrong.", http.StatusConflict, err)
+ return
+ }
+ utils.InternalServerError(w, err)
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusNoContent, nil)
+}
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index b80dea545..74a04b2e6 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -291,9 +291,6 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
r.HandleFunc(VersionedPath("/containers/{name}/pause"), s.APIHandler(compat.PauseContainer)).Methods(http.MethodPost)
// Added non version path to URI to support docker non versioned paths
r.HandleFunc("/containers/{name}/pause", s.APIHandler(compat.PauseContainer)).Methods(http.MethodPost)
- r.HandleFunc(VersionedPath("/containers/{name}/rename"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
- // Added non version path to URI to support docker non versioned paths
- r.HandleFunc("/containers/{name}/rename", s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
// swagger:operation POST /containers/{name}/restart compat restartContainer
// ---
// tags:
@@ -610,6 +607,36 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name}/export"), s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet)
r.HandleFunc("/containers/{name}/export", s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet)
+ // swagger:operation POST /containers/{name}/rename compat renameContainer
+ // ---
+ // tags:
+ // - containers (compat)
+ // summary: Rename an existing container
+ // description: Change the name of an existing container.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: Full or partial ID or full name of the container to rename
+ // - in: query
+ // name: name
+ // type: string
+ // required: true
+ // description: New name for the container
+ // produces:
+ // - application/json
+ // responses:
+ // 204:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // $ref: "#/responses/ConflictError"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/containers/{name}/rename"), s.APIHandler(compat.RenameContainer)).Methods(http.MethodPost)
+ r.HandleFunc("/containers/{name}/rename", s.APIHandler(compat.RenameContainer)).Methods(http.MethodPost)
/*
libpod endpoints
@@ -1463,5 +1490,34 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name}/init"), s.APIHandler(libpod.InitContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/containers/{name}/rename libpod libpodRenameContainer
+ // ---
+ // tags:
+ // - containers
+ // summary: Rename an existing container
+ // description: Change the name of an existing container.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: Full or partial ID or full name of the container to rename
+ // - in: query
+ // name: name
+ // type: string
+ // required: true
+ // description: New name for the container
+ // produces:
+ // - application/json
+ // responses:
+ // 204:
+ // description: no error
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // $ref: "#/responses/ConflictError"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/rename"), s.APIHandler(compat.RenameContainer)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 96687b1de..d8576c101 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -434,3 +434,9 @@ type ContainerStatsReport struct {
// Results, set when there is no error.
Stats []define.ContainerStats
}
+
+// ContainerRenameOptions describes input options for renaming a container.
+type ContainerRenameOptions struct {
+ // NewName is the new name that will be given to the container.
+ NewName string
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 7d38a97f2..d2552770c 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -37,6 +37,7 @@ type ContainerEngine interface {
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerPort(ctx context.Context, nameOrID string, options ContainerPortOptions) ([]*ContainerPortReport, error)
ContainerPrune(ctx context.Context, options ContainerPruneOptions) ([]*reports.PruneReport, error)
+ ContainerRename(ctr context.Context, nameOrID string, options ContainerRenameOptions) error
ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
ContainerRestore(ctx context.Context, namesOrIds []string, options RestoreOptions) ([]*RestoreReport, error)
ContainerRm(ctx context.Context, namesOrIds []string, options RmOptions) ([]*RmReport, error)
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index b5f5a0e91..a8f4d44a8 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -902,7 +902,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
if err := ic.Libpod.RemoveContainer(ctx, ctr, false, true); err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr ||
errors.Cause(err) == define.ErrCtrRemoved {
- logrus.Warnf("Container %s does not exist: %v", ctr.ID(), err)
+ logrus.Infof("Container %s was already removed, skipping --rm", ctr.ID())
} else {
logrus.Errorf("Error removing container %s: %v", ctr.ID(), err)
}
@@ -1312,3 +1312,17 @@ func (ic *ContainerEngine) ShouldRestart(ctx context.Context, nameOrID string) (
return &entities.BoolReport{Value: ctr.ShouldRestart(ctx)}, nil
}
+
+// ContainerRename renames the given container.
+func (ic *ContainerEngine) ContainerRename(ctx context.Context, nameOrID string, opts entities.ContainerRenameOptions) error {
+ ctr, err := ic.Libpod.LookupContainer(nameOrID)
+ if err != nil {
+ return err
+ }
+
+ if _, err := ic.Libpod.RenameContainer(ctx, ctr, opts.NewName); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 49bcdec98..8aab4a9cd 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -820,3 +820,8 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
func (ic *ContainerEngine) ShouldRestart(_ context.Context, id string) (bool, error) {
return containers.ShouldRestart(ic.ClientCtx, id, nil)
}
+
+// ContainerRename renames the given container.
+func (ic *ContainerEngine) ContainerRename(ctx context.Context, nameOrID string, opts entities.ContainerRenameOptions) error {
+ return errors.Errorf("NOT YET IMPLEMENTED")
+}