github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/api/handlers/compat/containers.go (about)

     1  package compat
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"sort"
     8  	"strconv"
     9  	"strings"
    10  	"syscall"
    11  	"time"
    12  
    13  	"github.com/hanks177/podman/v4/libpod"
    14  	"github.com/hanks177/podman/v4/libpod/define"
    15  	"github.com/hanks177/podman/v4/pkg/api/handlers"
    16  	"github.com/hanks177/podman/v4/pkg/api/handlers/utils"
    17  	api "github.com/hanks177/podman/v4/pkg/api/types"
    18  	"github.com/hanks177/podman/v4/pkg/domain/entities"
    19  	"github.com/hanks177/podman/v4/pkg/domain/filters"
    20  	"github.com/hanks177/podman/v4/pkg/domain/infra/abi"
    21  	"github.com/hanks177/podman/v4/pkg/ps"
    22  	"github.com/hanks177/podman/v4/pkg/signal"
    23  	"github.com/hanks177/podman/v4/pkg/util"
    24  	"github.com/docker/docker/api/types"
    25  	"github.com/docker/docker/api/types/container"
    26  	"github.com/docker/docker/api/types/network"
    27  	"github.com/docker/go-connections/nat"
    28  	"github.com/docker/go-units"
    29  	"github.com/gorilla/schema"
    30  	"github.com/pkg/errors"
    31  	"github.com/sirupsen/logrus"
    32  )
    33  
    34  func RemoveContainer(w http.ResponseWriter, r *http.Request) {
    35  	decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
    36  	query := struct {
    37  		Force         bool  `schema:"force"`
    38  		Ignore        bool  `schema:"ignore"`
    39  		Depend        bool  `schema:"depend"`
    40  		Link          bool  `schema:"link"`
    41  		Timeout       *uint `schema:"timeout"`
    42  		DockerVolumes bool  `schema:"v"`
    43  		LibpodVolumes bool  `schema:"volumes"`
    44  	}{
    45  		// override any golang type defaults
    46  	}
    47  
    48  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
    49  		utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
    50  		return
    51  	}
    52  
    53  	options := entities.RmOptions{
    54  		Force:  query.Force,
    55  		Ignore: query.Ignore,
    56  	}
    57  	if utils.IsLibpodRequest(r) {
    58  		options.Volumes = query.LibpodVolumes
    59  		options.Timeout = query.Timeout
    60  		options.Depend = query.Depend
    61  	} else {
    62  		if query.Link {
    63  			utils.Error(w, http.StatusBadRequest, utils.ErrLinkNotSupport)
    64  			return
    65  		}
    66  		options.Volumes = query.DockerVolumes
    67  	}
    68  
    69  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
    70  	// Now use the ABI implementation to prevent us from having duplicate
    71  	// code.
    72  	containerEngine := abi.ContainerEngine{Libpod: runtime}
    73  	name := utils.GetName(r)
    74  	reports, err := containerEngine.ContainerRm(r.Context(), []string{name}, options)
    75  	if err != nil {
    76  		if errors.Cause(err) == define.ErrNoSuchCtr {
    77  			utils.ContainerNotFound(w, name, err)
    78  			return
    79  		}
    80  
    81  		utils.InternalServerError(w, err)
    82  		return
    83  	}
    84  	if len(reports) > 0 && reports[0].Err != nil {
    85  		err = reports[0].Err
    86  		if errors.Cause(err) == define.ErrNoSuchCtr {
    87  			utils.ContainerNotFound(w, name, err)
    88  			return
    89  		}
    90  		utils.InternalServerError(w, err)
    91  		return
    92  	}
    93  	if utils.IsLibpodRequest(r) {
    94  		utils.WriteResponse(w, http.StatusOK, reports)
    95  		return
    96  	}
    97  	utils.WriteResponse(w, http.StatusNoContent, nil)
    98  }
    99  
   100  func ListContainers(w http.ResponseWriter, r *http.Request) {
   101  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
   102  	decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
   103  	query := struct {
   104  		All   bool `schema:"all"`
   105  		Limit int  `schema:"limit"`
   106  		Size  bool `schema:"size"`
   107  	}{
   108  		// override any golang type defaults
   109  	}
   110  
   111  	filterMap, err := util.PrepareFilters(r)
   112  	if err != nil {
   113  		utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to decode filter parameters for %s", r.URL.String()))
   114  		return
   115  	}
   116  
   117  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
   118  		utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
   119  		return
   120  	}
   121  
   122  	filterFuncs := make([]libpod.ContainerFilter, 0, len(*filterMap))
   123  	all := query.All || query.Limit > 0
   124  	if len((*filterMap)) > 0 {
   125  		for k, v := range *filterMap {
   126  			generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, runtime)
   127  			if err != nil {
   128  				utils.InternalServerError(w, err)
   129  				return
   130  			}
   131  			filterFuncs = append(filterFuncs, generatedFunc)
   132  		}
   133  	}
   134  
   135  	// Docker thinks that if status is given as an input, then we should override
   136  	// the all setting and always deal with all containers.
   137  	if len((*filterMap)["status"]) > 0 {
   138  		all = true
   139  	}
   140  	if !all {
   141  		runningOnly, err := filters.GenerateContainerFilterFuncs("status", []string{define.ContainerStateRunning.String()}, runtime)
   142  		if err != nil {
   143  			utils.InternalServerError(w, err)
   144  			return
   145  		}
   146  		filterFuncs = append(filterFuncs, runningOnly)
   147  	}
   148  
   149  	containers, err := runtime.GetContainers(filterFuncs...)
   150  	if err != nil {
   151  		utils.InternalServerError(w, err)
   152  		return
   153  	}
   154  	if _, found := r.URL.Query()["limit"]; found && query.Limit > 0 {
   155  		// Sort the libpod containers
   156  		sort.Sort(ps.SortCreateTime{SortContainers: containers})
   157  		// we should perform the lopping before we start getting
   158  		// the expensive information on containers
   159  		if len(containers) > query.Limit {
   160  			containers = containers[:query.Limit]
   161  		}
   162  	}
   163  	list := make([]*handlers.Container, 0, len(containers))
   164  	for _, ctnr := range containers {
   165  		api, err := LibpodToContainer(ctnr, query.Size)
   166  		if err != nil {
   167  			if errors.Cause(err) == define.ErrNoSuchCtr {
   168  				// container was removed between the initial fetch of the list and conversion
   169  				logrus.Debugf("Container %s removed between initial fetch and conversion, ignoring in output", ctnr.ID())
   170  				continue
   171  			}
   172  			utils.InternalServerError(w, err)
   173  			return
   174  		}
   175  		list = append(list, api)
   176  	}
   177  	utils.WriteResponse(w, http.StatusOK, list)
   178  }
   179  
   180  func GetContainer(w http.ResponseWriter, r *http.Request) {
   181  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
   182  	decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
   183  	query := struct {
   184  		Size bool `schema:"size"`
   185  	}{
   186  		// override any golang type defaults
   187  	}
   188  
   189  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
   190  		utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
   191  		return
   192  	}
   193  
   194  	name := utils.GetName(r)
   195  	ctnr, err := runtime.LookupContainer(name)
   196  	if err != nil {
   197  		utils.ContainerNotFound(w, name, err)
   198  		return
   199  	}
   200  	api, err := LibpodToContainerJSON(ctnr, query.Size)
   201  	if err != nil {
   202  		utils.InternalServerError(w, err)
   203  		return
   204  	}
   205  	utils.WriteResponse(w, http.StatusOK, api)
   206  }
   207  
   208  func KillContainer(w http.ResponseWriter, r *http.Request) {
   209  	// /{version}/containers/(name)/kill
   210  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
   211  	decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
   212  	query := struct {
   213  		Signal string `schema:"signal"`
   214  	}{
   215  		Signal: "KILL",
   216  	}
   217  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
   218  		utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
   219  		return
   220  	}
   221  
   222  	// Now use the ABI implementation to prevent us from having duplicate
   223  	// code.
   224  	containerEngine := abi.ContainerEngine{Libpod: runtime}
   225  	name := utils.GetName(r)
   226  	options := entities.KillOptions{
   227  		Signal: query.Signal,
   228  	}
   229  	report, err := containerEngine.ContainerKill(r.Context(), []string{name}, options)
   230  	if err != nil {
   231  		if errors.Cause(err) == define.ErrCtrStateInvalid ||
   232  			errors.Cause(err) == define.ErrCtrStopped {
   233  			utils.Error(w, http.StatusConflict, err)
   234  			return
   235  		}
   236  		if errors.Cause(err) == define.ErrNoSuchCtr {
   237  			utils.ContainerNotFound(w, name, err)
   238  			return
   239  		}
   240  
   241  		utils.InternalServerError(w, err)
   242  		return
   243  	}
   244  
   245  	if len(report) > 0 && report[0].Err != nil {
   246  		utils.InternalServerError(w, report[0].Err)
   247  		return
   248  	}
   249  	// Docker waits for the container to stop if the signal is 0 or
   250  	// SIGKILL.
   251  	if !utils.IsLibpodRequest(r) {
   252  		sig, err := signal.ParseSignalNameOrNumber(query.Signal)
   253  		if err != nil {
   254  			utils.InternalServerError(w, err)
   255  			return
   256  		}
   257  		if sig == 0 || sig == syscall.SIGKILL {
   258  			opts := entities.WaitOptions{
   259  				Condition: []define.ContainerStatus{define.ContainerStateExited, define.ContainerStateStopped},
   260  				Interval:  time.Millisecond * 250,
   261  			}
   262  			if _, err := containerEngine.ContainerWait(r.Context(), []string{name}, opts); err != nil {
   263  				utils.Error(w, http.StatusInternalServerError, err)
   264  				return
   265  			}
   266  		}
   267  	}
   268  	// Success
   269  	utils.WriteResponse(w, http.StatusNoContent, nil)
   270  }
   271  
   272  func WaitContainer(w http.ResponseWriter, r *http.Request) {
   273  	// /{version}/containers/(name)/wait
   274  	utils.WaitContainerDocker(w, r)
   275  }
   276  
   277  func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error) {
   278  	imageID, imageName := l.Image()
   279  
   280  	var (
   281  		err        error
   282  		sizeRootFs int64
   283  		sizeRW     int64
   284  		state      define.ContainerStatus
   285  		status     string
   286  	)
   287  
   288  	if state, err = l.State(); err != nil {
   289  		return nil, err
   290  	}
   291  	stateStr := state.String()
   292  	if stateStr == "configured" {
   293  		stateStr = "created"
   294  	}
   295  
   296  	switch state {
   297  	case define.ContainerStateConfigured, define.ContainerStateCreated:
   298  		status = "Created"
   299  	case define.ContainerStateStopped, define.ContainerStateExited:
   300  		exitCode, _, err := l.ExitCode()
   301  		if err != nil {
   302  			return nil, err
   303  		}
   304  		finishedTime, err := l.FinishedTime()
   305  		if err != nil {
   306  			return nil, err
   307  		}
   308  		status = fmt.Sprintf("Exited (%d) %s ago", exitCode, units.HumanDuration(time.Since(finishedTime)))
   309  	case define.ContainerStateRunning, define.ContainerStatePaused:
   310  		startedTime, err := l.StartedTime()
   311  		if err != nil {
   312  			return nil, err
   313  		}
   314  		status = fmt.Sprintf("Up %s", units.HumanDuration(time.Since(startedTime)))
   315  		if state == define.ContainerStatePaused {
   316  			status += " (Paused)"
   317  		}
   318  	case define.ContainerStateRemoving:
   319  		status = "Removal In Progress"
   320  	case define.ContainerStateStopping:
   321  		status = "Stopping"
   322  	default:
   323  		status = "Unknown"
   324  	}
   325  
   326  	if sz {
   327  		if sizeRW, err = l.RWSize(); err != nil {
   328  			return nil, err
   329  		}
   330  		if sizeRootFs, err = l.RootFsSize(); err != nil {
   331  			return nil, err
   332  		}
   333  	}
   334  
   335  	portMappings, err := l.PortMappings()
   336  	if err != nil {
   337  		return nil, err
   338  	}
   339  
   340  	ports := make([]types.Port, len(portMappings))
   341  	for idx, portMapping := range portMappings {
   342  		ports[idx] = types.Port{
   343  			IP:          portMapping.HostIP,
   344  			PrivatePort: portMapping.ContainerPort,
   345  			PublicPort:  portMapping.HostPort,
   346  			Type:        portMapping.Protocol,
   347  		}
   348  	}
   349  	inspect, err := l.Inspect(false)
   350  	if err != nil {
   351  		return nil, err
   352  	}
   353  
   354  	n, err := json.Marshal(inspect.NetworkSettings)
   355  	if err != nil {
   356  		return nil, err
   357  	}
   358  	networkSettings := types.SummaryNetworkSettings{}
   359  	if err := json.Unmarshal(n, &networkSettings); err != nil {
   360  		return nil, err
   361  	}
   362  
   363  	m, err := json.Marshal(inspect.Mounts)
   364  	if err != nil {
   365  		return nil, err
   366  	}
   367  	mounts := []types.MountPoint{}
   368  	if err := json.Unmarshal(m, &mounts); err != nil {
   369  		return nil, err
   370  	}
   371  
   372  	return &handlers.Container{
   373  		Container: types.Container{
   374  			ID:         l.ID(),
   375  			Names:      []string{fmt.Sprintf("/%s", l.Name())},
   376  			Image:      imageName,
   377  			ImageID:    "sha256:" + imageID,
   378  			Command:    strings.Join(l.Command(), " "),
   379  			Created:    l.CreatedTime().Unix(),
   380  			Ports:      ports,
   381  			SizeRw:     sizeRW,
   382  			SizeRootFs: sizeRootFs,
   383  			Labels:     l.Labels(),
   384  			State:      stateStr,
   385  			Status:     status,
   386  			HostConfig: struct {
   387  				NetworkMode string `json:",omitempty"`
   388  			}{
   389  				"host",
   390  			},
   391  			NetworkSettings: &networkSettings,
   392  			Mounts:          mounts,
   393  		},
   394  		ContainerCreateConfig: types.ContainerCreateConfig{},
   395  	}, nil
   396  }
   397  
   398  func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, error) {
   399  	_, imageName := l.Image()
   400  	inspect, err := l.Inspect(sz)
   401  	if err != nil {
   402  		return nil, err
   403  	}
   404  	// Docker uses UTC
   405  	if inspect != nil && inspect.State != nil {
   406  		inspect.State.StartedAt = inspect.State.StartedAt.UTC()
   407  		inspect.State.FinishedAt = inspect.State.FinishedAt.UTC()
   408  	}
   409  	i, err := json.Marshal(inspect.State)
   410  	if err != nil {
   411  		return nil, err
   412  	}
   413  	state := types.ContainerState{}
   414  	if err := json.Unmarshal(i, &state); err != nil {
   415  		return nil, err
   416  	}
   417  
   418  	// docker considers paused to be running
   419  	if state.Paused {
   420  		state.Running = true
   421  	}
   422  
   423  	// docker calls the configured state "created"
   424  	if state.Status == define.ContainerStateConfigured.String() {
   425  		state.Status = define.ContainerStateCreated.String()
   426  	}
   427  
   428  	if l.HasHealthCheck() && state.Status != "created" {
   429  		state.Health = &types.Health{
   430  			Status:        inspect.State.Health.Status,
   431  			FailingStreak: inspect.State.Health.FailingStreak,
   432  		}
   433  
   434  		log := inspect.State.Health.Log
   435  
   436  		for _, item := range log {
   437  			res := &types.HealthcheckResult{}
   438  			s, _ := time.Parse(time.RFC3339Nano, item.Start)
   439  			e, _ := time.Parse(time.RFC3339Nano, item.End)
   440  			res.Start = s
   441  			res.End = e
   442  			res.ExitCode = item.ExitCode
   443  			res.Output = item.Output
   444  			state.Health.Log = append(state.Health.Log, res)
   445  		}
   446  	}
   447  
   448  	formatCapabilities(inspect.HostConfig.CapDrop)
   449  	formatCapabilities(inspect.HostConfig.CapAdd)
   450  
   451  	h, err := json.Marshal(inspect.HostConfig)
   452  	if err != nil {
   453  		return nil, err
   454  	}
   455  	hc := container.HostConfig{}
   456  	if err := json.Unmarshal(h, &hc); err != nil {
   457  		return nil, err
   458  	}
   459  
   460  	// k8s-file == json-file
   461  	if hc.LogConfig.Type == define.KubernetesLogging {
   462  		hc.LogConfig.Type = define.JSONLogging
   463  	}
   464  	g, err := json.Marshal(inspect.GraphDriver)
   465  	if err != nil {
   466  		return nil, err
   467  	}
   468  	graphDriver := types.GraphDriverData{}
   469  	if err := json.Unmarshal(g, &graphDriver); err != nil {
   470  		return nil, err
   471  	}
   472  
   473  	cb := types.ContainerJSONBase{
   474  		ID:              l.ID(),
   475  		Created:         l.CreatedTime().UTC().Format(time.RFC3339Nano), // Docker uses UTC
   476  		Path:            inspect.Path,
   477  		Args:            inspect.Args,
   478  		State:           &state,
   479  		Image:           imageName,
   480  		ResolvConfPath:  inspect.ResolvConfPath,
   481  		HostnamePath:    inspect.HostnamePath,
   482  		HostsPath:       inspect.HostsPath,
   483  		LogPath:         l.LogPath(),
   484  		Node:            nil,
   485  		Name:            fmt.Sprintf("/%s", l.Name()),
   486  		RestartCount:    int(inspect.RestartCount),
   487  		Driver:          inspect.Driver,
   488  		Platform:        "linux",
   489  		MountLabel:      inspect.MountLabel,
   490  		ProcessLabel:    inspect.ProcessLabel,
   491  		AppArmorProfile: inspect.AppArmorProfile,
   492  		ExecIDs:         inspect.ExecIDs,
   493  		HostConfig:      &hc,
   494  		GraphDriver:     graphDriver,
   495  		SizeRw:          inspect.SizeRw,
   496  		SizeRootFs:      &inspect.SizeRootFs,
   497  	}
   498  
   499  	// set Path and Args
   500  	processArgs := l.Config().Spec.Process.Args
   501  	if len(processArgs) > 0 {
   502  		cb.Path = processArgs[0]
   503  	}
   504  	if len(processArgs) > 1 {
   505  		cb.Args = processArgs[1:]
   506  	}
   507  	stopTimeout := int(l.StopTimeout())
   508  
   509  	exposedPorts := make(nat.PortSet)
   510  	for ep := range inspect.HostConfig.PortBindings {
   511  		splitp := strings.SplitN(ep, "/", 2)
   512  		if len(splitp) != 2 {
   513  			return nil, errors.Errorf("PORT/PROTOCOL Format required for %q", ep)
   514  		}
   515  		exposedPort, err := nat.NewPort(splitp[1], splitp[0])
   516  		if err != nil {
   517  			return nil, err
   518  		}
   519  		exposedPorts[exposedPort] = struct{}{}
   520  	}
   521  
   522  	var healthcheck *container.HealthConfig
   523  	if inspect.Config.Healthcheck != nil {
   524  		healthcheck = &container.HealthConfig{
   525  			Test:        inspect.Config.Healthcheck.Test,
   526  			Interval:    inspect.Config.Healthcheck.Interval,
   527  			Timeout:     inspect.Config.Healthcheck.Timeout,
   528  			StartPeriod: inspect.Config.Healthcheck.StartPeriod,
   529  			Retries:     inspect.Config.Healthcheck.Retries,
   530  		}
   531  	}
   532  
   533  	config := container.Config{
   534  		Hostname:        l.Hostname(),
   535  		Domainname:      inspect.Config.DomainName,
   536  		User:            l.User(),
   537  		AttachStdin:     inspect.Config.AttachStdin,
   538  		AttachStdout:    inspect.Config.AttachStdout,
   539  		AttachStderr:    inspect.Config.AttachStderr,
   540  		ExposedPorts:    exposedPorts,
   541  		Tty:             inspect.Config.Tty,
   542  		OpenStdin:       inspect.Config.OpenStdin,
   543  		StdinOnce:       inspect.Config.StdinOnce,
   544  		Env:             inspect.Config.Env,
   545  		Cmd:             l.Command(),
   546  		Healthcheck:     healthcheck,
   547  		ArgsEscaped:     false,
   548  		Image:           imageName,
   549  		Volumes:         nil,
   550  		WorkingDir:      l.WorkingDir(),
   551  		Entrypoint:      l.Entrypoint(),
   552  		NetworkDisabled: false,
   553  		MacAddress:      "",
   554  		OnBuild:         nil,
   555  		Labels:          l.Labels(),
   556  		StopSignal:      strconv.Itoa(int(l.StopSignal())),
   557  		StopTimeout:     &stopTimeout,
   558  		Shell:           nil,
   559  	}
   560  
   561  	m, err := json.Marshal(inspect.Mounts)
   562  	if err != nil {
   563  		return nil, err
   564  	}
   565  	mounts := []types.MountPoint{}
   566  	if err := json.Unmarshal(m, &mounts); err != nil {
   567  		return nil, err
   568  	}
   569  
   570  	p, err := json.Marshal(inspect.NetworkSettings.Ports)
   571  	if err != nil {
   572  		return nil, err
   573  	}
   574  	ports := nat.PortMap{}
   575  	if err := json.Unmarshal(p, &ports); err != nil {
   576  		return nil, err
   577  	}
   578  
   579  	n, err := json.Marshal(inspect.NetworkSettings)
   580  	if err != nil {
   581  		return nil, err
   582  	}
   583  
   584  	networkSettings := types.NetworkSettings{}
   585  	if err := json.Unmarshal(n, &networkSettings); err != nil {
   586  		return nil, err
   587  	}
   588  	// do not report null instead use an empty map
   589  	if networkSettings.Networks == nil {
   590  		networkSettings.Networks = map[string]*network.EndpointSettings{}
   591  	}
   592  
   593  	c := types.ContainerJSON{
   594  		ContainerJSONBase: &cb,
   595  		Mounts:            mounts,
   596  		Config:            &config,
   597  		NetworkSettings:   &networkSettings,
   598  	}
   599  	return &c, nil
   600  }
   601  
   602  func formatCapabilities(slice []string) {
   603  	for i := range slice {
   604  		slice[i] = strings.TrimPrefix(slice[i], "CAP_")
   605  	}
   606  }
   607  
   608  func RenameContainer(w http.ResponseWriter, r *http.Request) {
   609  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
   610  	decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
   611  
   612  	name := utils.GetName(r)
   613  	query := struct {
   614  		Name string `schema:"name"`
   615  	}{}
   616  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
   617  		utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
   618  		return
   619  	}
   620  
   621  	ctr, err := runtime.LookupContainer(name)
   622  	if err != nil {
   623  		utils.ContainerNotFound(w, name, err)
   624  		return
   625  	}
   626  
   627  	if _, err := runtime.RenameContainer(r.Context(), ctr, query.Name); err != nil {
   628  		if errors.Cause(err) == define.ErrPodExists || errors.Cause(err) == define.ErrCtrExists {
   629  			utils.Error(w, http.StatusConflict, err)
   630  			return
   631  		}
   632  		utils.InternalServerError(w, err)
   633  		return
   634  	}
   635  
   636  	utils.WriteResponse(w, http.StatusNoContent, nil)
   637  }