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 }
func (c *Container) containerStart(name string, hostConfig *containertypes.HostConfig, bind bool) error { var err error // Get an API client to the portlayer client := c.containerProxy.Client() // Look up the container name in the metadata cache to get long ID vc := cache.ContainerCache().GetContainer(name) if vc == nil { return NotFoundError(name) } id := vc.ContainerID // handle legacy hostConfig if hostConfig != nil { // hostConfig exist for backwards compatibility. TODO: Figure out which parameters we // need to look at in hostConfig } else if vc != nil { hostConfig = vc.HostConfig } if vc != nil && hostConfig.NetworkMode.NetworkName() == "" { hostConfig.NetworkMode = vc.HostConfig.NetworkMode } // get a handle to the container handle, err := c.Handle(id, name) if err != nil { return err } var endpoints []*models.EndpointConfig // bind network if bind { var bindRes *scopes.BindContainerOK bindRes, err = client.Scopes.BindContainer(scopes.NewBindContainerParamsWithContext(ctx).WithHandle(handle)) if err != nil { switch err := err.(type) { case *scopes.BindContainerNotFound: cache.ContainerCache().DeleteContainer(id) return NotFoundError(name) case *scopes.BindContainerInternalServerError: return InternalServerError(err.Payload.Message) default: return InternalServerError(err.Error()) } } handle = bindRes.Payload.Handle endpoints = bindRes.Payload.Endpoints // unbind in case we fail later defer func() { if err != nil { client.Scopes.UnbindContainer(scopes.NewUnbindContainerParamsWithContext(ctx).WithHandle(handle)) } }() // unmap ports that vc needs if they're not being used by previously mapped container err = c.cleanupPortBindings(vc) if err != nil { return err } } // change the state of the container // TODO: We need a resolved ID from the name var stateChangeRes *containers.StateChangeOK stateChangeRes, err = client.Containers.StateChange(containers.NewStateChangeParamsWithContext(ctx).WithHandle(handle).WithState("RUNNING")) if err != nil { switch err := err.(type) { case *containers.StateChangeNotFound: cache.ContainerCache().DeleteContainer(id) return NotFoundError(name) case *containers.StateChangeDefault: return InternalServerError(err.Payload.Message) default: return InternalServerError(err.Error()) } } handle = stateChangeRes.Payload // map ports if bind { e := c.findPortBoundNetworkEndpoint(hostConfig, endpoints) if err = MapPorts(hostConfig, e, id); err != nil { return InternalServerError(fmt.Sprintf("error mapping ports: %s", err)) } defer func() { if err != nil { UnmapPorts(hostConfig) } }() } // commit the handle; this will reconfigure and start the vm _, err = client.Containers.Commit(containers.NewCommitParamsWithContext(ctx).WithHandle(handle)) if err != nil { switch err := err.(type) { case *containers.CommitNotFound: cache.ContainerCache().DeleteContainer(id) return NotFoundError(name) case *containers.CommitConflict: return ConflictError(err.Error()) case *containers.CommitDefault: return InternalServerError(err.Payload.Message) default: return InternalServerError(err.Error()) } } return nil }