// Retrieve the image metadata from the image cache. func getImageConfigFromCache(image string) (*metadata.ImageConfig, error) { // Use docker reference code to validate the id's format digest, named, err := reference.ParseIDOrReference(image) if err != nil { return nil, err } // Try to get the image config from our image cache imageCache := ImageCache() if digest != "" { config, err := imageCache.GetImageByDigest(digest) if err != nil { log.Errorf("Inspect lookup failed for image %s: %s. Returning no such image.", image, err) return nil, derr.NewRequestNotFoundError(fmt.Errorf("No such image: %s", image)) } if config != nil { return config, nil } } else { config, err := imageCache.GetImageByNamed(named) if err != nil { log.Errorf("Inspect lookup failed for image %s: %s. Returning no such image.", image, err) return nil, derr.NewRequestNotFoundError(fmt.Errorf("No such image: %s", image)) } if config != nil { return config, nil } } return nil, derr.NewRequestNotFoundError(fmt.Errorf("No such image: %s", image)) }
// GetContainer looks for a container using the provided information, which could be // one of the following inputs from the caller: // - A full container ID, which will exact match a container in daemon's list // - A container name, which will only exact match via the GetByName() function // - A partial container ID prefix (e.g. short ID) of any length that is // unique enough to only return a single container object // If none of these searches succeed, an error is returned func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, error) { if len(prefixOrName) == 0 { return nil, errors.NewBadRequestError(fmt.Errorf("No container name or ID supplied")) } if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil { // prefix is an exact match to a full container ID return containerByID, nil } // GetByName will match only an exact name provided; we ignore errors if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil { // prefix is an exact match to a full container Name return containerByName, nil } containerID, indexError := daemon.idIndex.Get(prefixOrName) if indexError != nil { // When truncindex defines an error type, use that instead if indexError == truncindex.ErrNotExist { err := fmt.Errorf("No such container: %s", prefixOrName) return nil, errors.NewRequestNotFoundError(err) } return nil, indexError } return daemon.containers.Get(containerID), nil }
// ContainerRunning returns true if the given container is running func (c *ContainerProxy) ContainerRunning(vc *viccontainer.VicContainer) (bool, error) { defer trace.End(trace.Begin("")) if c.client == nil { return false, derr.NewErrorWithStatusCode(fmt.Errorf("ContainerProxy.CommitContainerHandle failed to create a portlayer client"), http.StatusInternalServerError) } results, err := c.client.Containers.GetContainerInfo(containers.NewGetContainerInfoParamsWithContext(ctx).WithID(vc.ContainerID)) if err != nil { switch err := err.(type) { case *containers.GetContainerInfoNotFound: return false, derr.NewRequestNotFoundError(fmt.Errorf("No such container: %s", vc.ContainerID)) case *containers.GetContainerInfoInternalServerError: return false, derr.NewErrorWithStatusCode(fmt.Errorf("Error from portlayer: %#v", err.Payload), http.StatusInternalServerError) default: return false, derr.NewErrorWithStatusCode(fmt.Errorf("Unknown error from the container portlayer"), http.StatusInternalServerError) } } inspectJSON, err := ContainerInfoToDockerContainerInspect(vc, results.Payload, c.portlayerName) if err != nil { log.Errorf("containerInfoToDockerContainerInspect failed with %s", err) return false, err } return inspectJSON.State.Running, nil }
// VolumeRm : docker personality for VIC func (v *Volume) VolumeRm(name string) error { defer trace.End(trace.Begin("Volume.VolumeRm")) client := PortLayerClient() if client == nil { return derr.NewErrorWithStatusCode(fmt.Errorf("Failed to get a portlayer client"), http.StatusInternalServerError) } // FIXME: check whether this is a name or a UUID. UUID expected for now. _, err := client.Storage.RemoveVolume(storage.NewRemoveVolumeParamsWithContext(ctx).WithName(name)) if err != nil { switch err := err.(type) { case *storage.RemoveVolumeNotFound: return derr.NewRequestNotFoundError(fmt.Errorf("Get %s: no such volume", name)) case *storage.RemoveVolumeConflict: return derr.NewRequestConflictError(fmt.Errorf(err.Payload.Message)) case *storage.RemoveVolumeInternalServerError: return derr.NewErrorWithStatusCode(fmt.Errorf("Server error from portlayer: %s", err.Payload.Message), http.StatusInternalServerError) default: return derr.NewErrorWithStatusCode(fmt.Errorf("Server error from portlayer: %s", err), http.StatusInternalServerError) } } return nil }
// GetImage parses input to retrieve a cached image func (ic *ICache) GetImage(idOrRef string) (*metadata.ImageConfig, error) { ic.m.RLock() defer ic.m.RUnlock() // get the full image ID if supplied a prefix if id, err := ic.idIndex.Get(idOrRef); err == nil { idOrRef = id } digest, named, err := reference.ParseIDOrReference(idOrRef) if err != nil { return nil, err } var config *metadata.ImageConfig if digest != "" { config, err = ic.getImageByDigest(digest) if err != nil { return nil, err } } else { config, err = ic.getImageByNamed(named) if err != nil { return nil, err } } if config == nil { return nil, derr.NewRequestNotFoundError(fmt.Errorf("No such image: %s", idOrRef)) } return copyImageConfig(config), nil }
func (ic *ICache) getImageByDigest(digest digest.Digest) (*metadata.ImageConfig, error) { var config *metadata.ImageConfig config, ok := ic.cacheByID[string(digest)] if !ok { return nil, derr.NewRequestNotFoundError(fmt.Errorf("No such image: %s", digest)) } return copyImageConfig(config), nil }
func MockCreateHandleData() []CreateHandleMockData { createHandleTimeoutErr := client.NewAPIError("unknown error", "context deadline exceeded", http.StatusServiceUnavailable) mockCreateHandleData := []CreateHandleMockData{ {"busybox", "321cba", "handle", nil, ""}, {"busybox", "", "", derr.NewRequestNotFoundError(fmt.Errorf("No such image: abc123")), "No such image"}, {"busybox", "", "", derr.NewErrorWithStatusCode(createHandleTimeoutErr, http.StatusInternalServerError), "context deadline exceeded"}, } return mockCreateHandleData }
func MockCommitData() []CommitHandleMockData { noSuchImageErr := fmt.Errorf("No such image: busybox") mockCommitData := []CommitHandleMockData{ {"buxybox", "", nil}, {"busybox", "failed to create a portlayer", derr.NewErrorWithStatusCode(fmt.Errorf("container.ContainerCreate failed to create a portlayer client"), http.StatusInternalServerError)}, {"busybox", "No such image", derr.NewRequestNotFoundError(noSuchImageErr)}, } return mockCommitData }
func (d *Daemon) imageNotExistToErrcode(err error) error { if dne, isDNE := err.(ErrImageDoesNotExist); isDNE { if strings.Contains(dne.RefOrID, "@") { e := fmt.Errorf("No such image: %s", dne.RefOrID) return errors.NewRequestNotFoundError(e) } tag := reference.DefaultTag ref, err := reference.ParseNamed(dne.RefOrID) if err != nil { e := fmt.Errorf("No such image: %s:%s", dne.RefOrID, tag) return errors.NewRequestNotFoundError(e) } if tagged, isTagged := ref.(reference.NamedTagged); isTagged { tag = tagged.Tag() } e := fmt.Errorf("No such image: %s:%s", ref.Name(), tag) return errors.NewRequestNotFoundError(e) } return err }
// CreateContainerHandle creates a new VIC container by calling the portlayer // // returns: // (containerID, containerHandle, error) func (c *ContainerProxy) CreateContainerHandle(imageID string, config types.ContainerCreateConfig) (string, string, error) { defer trace.End(trace.Begin(imageID)) if c.client == nil { return "", "", derr.NewErrorWithStatusCode(fmt.Errorf("ContainerProxy.CreateContainerHandle failed to create a portlayer client"), http.StatusInternalServerError) } if imageID == "" { return "", "", derr.NewRequestNotFoundError(fmt.Errorf("No image specified")) } // Call the Exec port layer to create the container host, err := sys.UUID() if err != nil { return "", "", derr.NewErrorWithStatusCode(fmt.Errorf("ContainerProxy.CreateContainerHandle got unexpected error getting VCH UUID"), http.StatusInternalServerError) } plCreateParams := dockerContainerCreateParamsToPortlayer(config, imageID, host) createResults, err := c.client.Containers.Create(plCreateParams) if err != nil { if _, ok := err.(*containers.CreateNotFound); ok { cerr := fmt.Errorf("No such image: %s", imageID) log.Errorf("%s (%s)", cerr, err) return "", "", derr.NewRequestNotFoundError(cerr) } // If we get here, most likely something went wrong with the port layer API server return "", "", derr.NewErrorWithStatusCode(err, http.StatusInternalServerError) } id := createResults.Payload.ID h := createResults.Payload.Handle return id, h, nil }
// ContainerCreate creates a container. func (c *Container) ContainerCreate(config types.ContainerCreateConfig) (types.ContainerCreateResponse, error) { defer trace.End(trace.Begin("")) var err error // bail early if container name already exists if exists := cache.ContainerCache().GetContainer(config.Name); exists != nil { err := fmt.Errorf("Conflict. The name %q is already in use by container %s. You have to remove (or rename) that container to be able to re use that name.", config.Name, exists.ContainerID) log.Errorf("%s", err.Error()) return types.ContainerCreateResponse{}, derr.NewRequestConflictError(err) } // get the image from the cache image, err := cache.ImageCache().Get(config.Config.Image) if err != nil { // if no image found then error thrown and a pull // will be initiated by the docker client log.Errorf("ContainerCreate: image %s error: %s", config.Config.Image, err.Error()) return types.ContainerCreateResponse{}, derr.NewRequestNotFoundError(err) } setCreateConfigOptions(config.Config, image.Config) log.Debugf("config.Config = %+v", config.Config) if err = validateCreateConfig(&config); err != nil { return types.ContainerCreateResponse{}, err } // Create a container representation in the personality server. This representation // will be stored in the cache if create succeeds in the port layer. container, err := createInternalVicContainer(image, &config) if err != nil { return types.ContainerCreateResponse{}, err } // Create an actualized container in the VIC port layer id, err := c.containerCreate(container, config) if err != nil { return types.ContainerCreateResponse{}, err } // Container created ok, save the container id and save the config override from the API // caller and save this container internal representation in our personality server's cache copyConfigOverrides(container, config) container.ContainerID = id cache.ContainerCache().AddContainer(container) log.Debugf("Container create - name(%s), containerID(%s), config(%#v), host(%#v)", container.Name, container.ContainerID, container.Config, container.HostConfig) return types.ContainerCreateResponse{ID: id}, nil }
func (n *Network) FindNetwork(idName string) (libnetwork.Network, error) { ok, err := PortLayerClient().Scopes.List(scopes.NewListParamsWithContext(ctx).WithIDName(idName)) if err != nil { switch err := err.(type) { case *scopes.ListNotFound: return nil, derr.NewRequestNotFoundError(fmt.Errorf("network %s not found", idName)) case *scopes.ListDefault: return nil, derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError) default: return nil, derr.NewErrorWithStatusCode(err, http.StatusInternalServerError) } } return &network{cfg: ok.Payload[0]}, nil }
func (n *Network) DeleteNetwork(name string) error { client := PortLayerClient() if _, err := client.Scopes.DeleteScope(scopes.NewDeleteScopeParamsWithContext(ctx).WithIDName(name)); err != nil { switch err := err.(type) { case *scopes.DeleteScopeNotFound: return derr.NewRequestNotFoundError(fmt.Errorf("network %s not found", name)) case *scopes.DeleteScopeInternalServerError: return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError) default: return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError) } } return nil }
// CommitContainerHandle() commits any changes to container handle. // func (c *ContainerProxy) CommitContainerHandle(handle, imageID string) error { defer trace.End(trace.Begin(handle)) if c.client == nil { return derr.NewErrorWithStatusCode(fmt.Errorf("ContainerProxy.CommitContainerHandle failed to create a portlayer client"), http.StatusInternalServerError) } _, err := c.client.Containers.Commit(containers.NewCommitParamsWithContext(ctx).WithHandle(handle)) if err != nil { cerr := fmt.Errorf("No such image: %s", imageID) log.Errorf("%s (%s)", cerr, err) // FIXME: Containers.Commit returns more errors than it's swagger spec says. // When no image exist, it also sends back non swagger errors. We should fix // this once Commit returns correct error codes. return derr.NewRequestNotFoundError(cerr) } return nil }
//VolumeRm : docker personality for VIC func (v *Volume) VolumeRm(name string) error { defer trace.End(trace.Begin("Volume.VolumeRm")) client := PortLayerClient() if client == nil { return derr.NewErrorWithStatusCode(fmt.Errorf("Failed to get a portlayer client"), http.StatusInternalServerError) } //FIXME: check whether this is a name or a UUID. UUID expected for now. _, err := client.Storage.RemoveVolume(storage.NewRemoveVolumeParams().WithName(name)) if err != nil { if _, ok := err.(*storage.RemoveVolumeNotFound); ok { return derr.NewRequestNotFoundError(fmt.Errorf("Get %s: no such volume", name)) } if _, ok := err.(*storage.RemoveVolumeConflict); ok { return derr.NewRequestConflictError(fmt.Errorf("Volume is in use")) } return derr.NewErrorWithStatusCode(fmt.Errorf("Server error from portlayer: %s", err), http.StatusInternalServerError) } return nil }
// createMux initializes the main router the server uses. func (s *Server) createMux() *mux.Router { m := mux.NewRouter() logrus.Debug("Registering routers") for _, apiRouter := range s.routers { for _, r := range apiRouter.Routes() { f := s.makeHTTPHandler(r.Handler()) logrus.Debugf("Registering %s, %s", r.Method(), r.Path()) m.Path(versionMatcher + r.Path()).Methods(r.Method()).Handler(f) m.Path(r.Path()).Methods(r.Method()).Handler(f) } } err := errors.NewRequestNotFoundError(fmt.Errorf("page not found")) notFoundHandler := httputils.MakeErrorHandler(err) m.HandleFunc(versionMatcher+"/{path:.*}", notFoundHandler) m.NotFoundHandler = notFoundHandler return m }
// Get parses input to retrieve a cached image func (ic *ICache) Get(idOrRef string) (*metadata.ImageConfig, error) { defer trace.End(trace.Begin("")) ic.m.RLock() defer ic.m.RUnlock() // cover the case of creating by a full reference if config, ok := ic.cacheByName[idOrRef]; ok { return config, nil } // get the full image ID if supplied a prefix if id, err := ic.iDIndex.Get(idOrRef); err == nil { idOrRef = id } imgDigest, named, err := reference.ParseIDOrReference(idOrRef) if err != nil { return nil, err } var config *metadata.ImageConfig if imgDigest != "" { config = ic.getImageByDigest(imgDigest) } else { config = ic.getImageByNamed(named) } if config == nil { // docker automatically prints out ":latest" tag if not specified in case if image is not found. postfixLatest := "" if !strings.Contains(idOrRef, ":") { postfixLatest += ":" + reference.DefaultTag } return nil, derr.NewRequestNotFoundError(fmt.Errorf( "No such image: %s%s", idOrRef, postfixLatest)) } return copyImageConfig(config), nil }
// StreamContainerLogs reads the log stream from the portlayer rest server and writes // it directly to the io.Writer that is passed in. func (c *ContainerProxy) StreamContainerLogs(name string, out io.Writer, started chan struct{}, showTimestamps bool, followLogs bool, since int64, tailLines int64) error { defer trace.End(trace.Begin("")) plClient, transport := c.createNewAttachClientWithTimeouts(attachConnectTimeout, 0, attachAttemptTimeout) defer transport.Close() close(started) params := containers.NewGetContainerLogsParamsWithContext(ctx). WithID(name). WithFollow(&followLogs). WithTimestamp(&showTimestamps). WithSince(&since). WithTaillines(&tailLines) _, err := plClient.Containers.GetContainerLogs(params, out) if err != nil { switch err := err.(type) { case *containers.GetContainerLogsNotFound: return derr.NewRequestNotFoundError(fmt.Errorf("No such container: %s", name)) case *containers.GetContainerLogsInternalServerError: return derr.NewErrorWithStatusCode(fmt.Errorf("Server error from the interaction port layer"), http.StatusInternalServerError) default: //Check for EOF. Since the connection, transport, and data handling are //encapsulated inisde of Swagger, we can only detect EOF by checking the //error string if strings.Contains(err.Error(), swaggerSubstringEOF) { return nil } unknownErrMsg := fmt.Errorf("Unknown error from the interaction port layer: %s", err) return derr.NewErrorWithStatusCode(unknownErrMsg, http.StatusInternalServerError) } } return nil }
func errExecNotFound(id string) error { err := fmt.Errorf("No such exec instance '%s' found in daemon", id) return errors.NewRequestNotFoundError(err) }
// validateCreateConfig() checks the parameters for ContainerCreate(). // It may "fix up" the config param passed into ConntainerCreate() if needed. func validateCreateConfig(config *types.ContainerCreateConfig) error { defer trace.End(trace.Begin("Container.validateCreateConfig")) // process cpucount here var cpuCount int64 = DefaultCPUs // support windows client if config.HostConfig.CPUCount > 0 { cpuCount = config.HostConfig.CPUCount } else { // we hijack --cpuset-cpus in the non-windows case if config.HostConfig.CpusetCpus != "" { cpus := strings.Split(config.HostConfig.CpusetCpus, ",") if c, err := strconv.Atoi(cpus[0]); err == nil { cpuCount = int64(c) } else { return fmt.Errorf("Error parsing CPU count: %s", err) } } } config.HostConfig.CPUCount = cpuCount // fix-up cpu/memory settings here if cpuCount < MinCPUs { config.HostConfig.CPUCount = MinCPUs } log.Infof("Container CPU count: %d", config.HostConfig.CPUCount) // convert from bytes to MiB for vsphere memoryMB := config.HostConfig.Memory / units.MiB if memoryMB == 0 { memoryMB = MemoryDefaultMB } else if memoryMB < MemoryMinMB { memoryMB = MemoryMinMB } // check that memory is aligned if remainder := memoryMB % MemoryAlignMB; remainder != 0 { log.Warnf("Default container VM memory must be %d aligned for hotadd, rounding up.", MemoryAlignMB) memoryMB += MemoryAlignMB - remainder } config.HostConfig.Memory = memoryMB log.Infof("Container memory: %d MB", config.HostConfig.Memory) if config.NetworkingConfig == nil { config.NetworkingConfig = &dnetwork.NetworkingConfig{} } if config.HostConfig == nil || config.Config == nil { return BadRequestError("invalid config") } // validate port bindings if config.HostConfig != nil { var ips []string if addrs, err := externalIPv4Addrs(); err != nil { log.Warnf("could not get address for external interface: %s", err) } else { ips = make([]string, len(addrs)) for i := range addrs { ips[i] = addrs[i].IP.String() } } for _, pbs := range config.HostConfig.PortBindings { for _, pb := range pbs { if pb.HostIP != "" && pb.HostIP != "0.0.0.0" { // check if specified host ip equals any of the addresses on the "client" interface found := false for _, i := range ips { if i == pb.HostIP { found = true break } } if !found { return InternalServerError("host IP for port bindings is only supported for 0.0.0.0 and the external interface IP address") } } start, end, _ := nat.ParsePortRangeToInt(pb.HostPort) if start != end { return InternalServerError("host port ranges are not supported for port bindings") } } } } // TODO(jzt): users other than root are not currently supported // We should check for USER in config.Config.Env once we support Dockerfiles. if config.Config.User != "" && config.Config.User != "root" { return InternalServerError("Failed to create container - users other than root are not currently supported") } // https://github.com/vmware/vic/issues/1378 if len(config.Config.Entrypoint) == 0 && len(config.Config.Cmd) == 0 { return derr.NewRequestNotFoundError(fmt.Errorf("No command specified")) } // Was a name provided - if not create a friendly name if config.Name == "" { //TODO: Assume we could have a name collison here : need to // provide validation / retry CDG June 9th 2016 config.Name = namesgenerator.GetRandomName(0) } return nil }
// ContainerInfoToDockerContainerInspect takes a ContainerInfo swagger-based struct // returned from VIC's port layer and creates an engine-api based container inspect struct. // There maybe other asset gathering if ContainerInfo does not have all the information func ContainerInfoToDockerContainerInspect(vc *viccontainer.VicContainer, info *models.ContainerInfo, portlayerName string) (*types.ContainerJSON, error) { if vc == nil || info == nil || info.ContainerConfig == nil { return nil, derr.NewRequestNotFoundError(fmt.Errorf("No such container: %s", vc.ContainerID)) } // Set default container state attributes containerState := &types.ContainerState{} if info.ProcessConfig != nil { if info.ProcessConfig.Pid != nil { containerState.Pid = int(*info.ProcessConfig.Pid) } if info.ProcessConfig.ExitCode != nil { containerState.ExitCode = int(*info.ProcessConfig.ExitCode) } if info.ProcessConfig.ErrorMsg != nil { containerState.Error = *info.ProcessConfig.ErrorMsg } if info.ProcessConfig.Started != nil { swaggerTime := time.Time(*info.ProcessConfig.Started) containerState.StartedAt = swaggerTime.Format(time.RFC3339Nano) } if info.ProcessConfig.Finished != nil { swaggerTime := time.Time(*info.ProcessConfig.Finished) containerState.FinishedAt = swaggerTime.Format(time.RFC3339Nano) } } inspectJSON := &types.ContainerJSON{ ContainerJSONBase: &types.ContainerJSONBase{ State: containerState, ResolvConfPath: "", HostnamePath: "", HostsPath: "", Driver: portlayerName, MountLabel: "", ProcessLabel: "", AppArmorProfile: "", ExecIDs: nil, HostConfig: hostConfigFromContainerInfo(vc, info, portlayerName), GraphDriver: types.GraphDriverData{Name: portlayerName}, SizeRw: nil, SizeRootFs: nil, }, Mounts: mountsFromContainerInfo(vc, info, portlayerName), Config: containerConfigFromContainerInfo(vc, info), NetworkSettings: networkFromContainerInfo(vc, info), } if inspectJSON.NetworkSettings != nil { log.Debugf("Docker inspect - network settings = %#v", inspectJSON.NetworkSettings) } else { log.Debug("Docker inspect - network settings = nil") } if info.ProcessConfig != nil { if info.ProcessConfig.ExecPath != nil { inspectJSON.Path = *info.ProcessConfig.ExecPath } if info.ProcessConfig.ExecArgs != nil { // args[0] is the command and should not appear in the args list here inspectJSON.Args = info.ProcessConfig.ExecArgs[1:] } } if info.ContainerConfig != nil { if info.ContainerConfig.State != nil { containerState.Status = strings.ToLower(*info.ContainerConfig.State) // https://github.com/docker/docker/blob/master/container/state.go#L77 if containerState.Status == "stopped" { containerState.Status = "exited" } if containerState.Status == "running" { containerState.Running = true } } if info.ContainerConfig.LayerID != nil { inspectJSON.Image = *info.ContainerConfig.LayerID } if info.ContainerConfig.LogPath != nil { inspectJSON.LogPath = *info.ContainerConfig.LogPath } if info.ContainerConfig.RestartCount != nil { inspectJSON.RestartCount = int(*info.ContainerConfig.RestartCount) } if info.ContainerConfig.ContainerID != nil { inspectJSON.ID = *info.ContainerConfig.ContainerID } if info.ContainerConfig.Created != nil { inspectJSON.Created = time.Unix(*info.ContainerConfig.Created, 0).Format(time.RFC3339Nano) } if len(info.ContainerConfig.Names) > 0 { inspectJSON.Name = info.ContainerConfig.Names[0] } } return inspectJSON, nil }
func ResourceNotFoundError(cid, res string) error { return derr.NewRequestNotFoundError(fmt.Errorf("No such %s for container: %s", res, cid)) }
// NotFoundError returns a 404 docker error when a container is not found. func NotFoundError(msg string) error { return derr.NewRequestNotFoundError(fmt.Errorf("No such container: %s", msg)) }
func (n *Network) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *apinet.EndpointSettings) error { vc := cache.ContainerCache().GetContainer(containerName) if vc != nil { containerName = vc.ContainerID } client := PortLayerClient() getRes, err := client.Containers.Get(containers.NewGetParamsWithContext(ctx).WithID(containerName)) if err != nil { switch err := err.(type) { case *containers.GetNotFound: return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message)) case *containers.GetDefault: return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError) default: return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError) } } h := getRes.Payload nc := &models.NetworkConfig{NetworkName: networkName} if endpointConfig != nil { if endpointConfig.IPAMConfig != nil && endpointConfig.IPAMConfig.IPv4Address != "" { nc.Address = &endpointConfig.IPAMConfig.IPv4Address } // Pass Links and Aliases to PL nc.Aliases = vicendpoint.Alias(endpointConfig) } addConRes, err := client.Scopes.AddContainer(scopes.NewAddContainerParamsWithContext(ctx). WithScope(nc.NetworkName). WithConfig(&models.ScopesAddContainerConfig{ Handle: h, NetworkConfig: nc, })) if err != nil { switch err := err.(type) { case *scopes.AddContainerNotFound: return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message)) case *scopes.AddContainerInternalServerError: return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError) default: return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError) } } h = addConRes.Payload // only bind if the container is running // get the state of the container getStateRes, err := client.Containers.GetState(containers.NewGetStateParamsWithContext(ctx).WithHandle(h)) if err != nil { switch err := err.(type) { case *containers.GetStateNotFound: return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message)) case *containers.GetStateDefault: return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError) default: return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError) } } h = getStateRes.Payload.Handle if getStateRes.Payload.State == "RUNNING" { bindRes, err := client.Scopes.BindContainer(scopes.NewBindContainerParamsWithContext(ctx).WithHandle(h)) if err != nil { switch err := err.(type) { case *scopes.BindContainerNotFound: return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message)) case *scopes.BindContainerInternalServerError: return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError) default: return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError) } } defer func() { if err == nil { return } if _, err2 := client.Scopes.UnbindContainer(scopes.NewUnbindContainerParamsWithContext(ctx).WithHandle(h)); err2 != nil { log.Warnf("failed bind container rollback: %s", err2) } }() h = bindRes.Payload.Handle } // commit handle _, err = client.Containers.Commit(containers.NewCommitParamsWithContext(ctx).WithHandle(h)) if err != nil { switch err := err.(type) { case *containers.CommitNotFound: return derr.NewRequestNotFoundError(fmt.Errorf(err.Payload.Message)) case *containers.CommitDefault: return derr.NewErrorWithStatusCode(fmt.Errorf(err.Payload.Message), http.StatusInternalServerError) default: return derr.NewErrorWithStatusCode(err, http.StatusInternalServerError) } } return nil }
// VolumeJoinNotFoundError returns a 404 docker error for a volume join request. func VolumeJoinNotFoundError(msg string) error { return derr.NewRequestNotFoundError(fmt.Errorf(msg)) }