Merge pull request #461 from docker/aci_stop

ACI Stop implementation
This commit is contained in:
Guillaume Tardif 2020-08-12 10:48:29 +02:00 committed by GitHub
commit d54fd53930
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 4 deletions

View File

@ -24,6 +24,8 @@ import (
"strings"
"time"
"github.com/docker/api/errdefs"
"github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/to"
@ -139,6 +141,19 @@ func deleteACIContainerGroup(ctx context.Context, aciContext store.AciContext, c
return containerGroupsClient.Delete(ctx, aciContext.ResourceGroup, containerGroupName)
}
func stopACIContainerGroup(ctx context.Context, aciContext store.AciContext, containerGroupName string) error {
containerGroupsClient, err := getContainerGroupsClient(aciContext.SubscriptionID)
if err != nil {
return fmt.Errorf("cannot get container group client: %v", err)
}
result, err := containerGroupsClient.Stop(ctx, aciContext.ResourceGroup, containerGroupName)
if result.StatusCode == http.StatusNotFound {
return errdefs.ErrNotFound
}
return err
}
func execACIContainer(ctx context.Context, aciContext store.AciContext, command, containerGroup string, containerName string) (c containerinstance.ContainerExecResponse, err error) {
containerClient, err := getContainerClient(aciContext.SubscriptionID)
if err != nil {

View File

@ -221,8 +221,16 @@ func addTag(groupDefinition *containerinstance.ContainerGroup, tagName string) {
groupDefinition.Tags[tagName] = to.StringPtr(tagName)
}
func (cs *aciContainerService) Stop(ctx context.Context, containerName string, timeout *uint32) error {
return errdefs.ErrNotImplemented
func (cs *aciContainerService) Stop(ctx context.Context, containerID string, timeout *uint32) error {
if timeout != nil && *timeout != uint32(0) {
return errors.Errorf("ACI integration does not support setting a timeout to stop a container before killing it.")
}
groupName, containerName := getGroupAndContainerName(containerID)
if groupName != containerID {
msg := "cannot stop service %q from compose application %q, you can stop the entire compose app with docker stop %s"
return errors.New(fmt.Sprintf(msg, containerName, groupName, groupName))
}
return stopACIContainerGroup(ctx, cs.ctx, groupName)
}
func getGroupAndContainerName(containerID string) (string, string) {

77
cli/cmd/stop.go Normal file
View File

@ -0,0 +1,77 @@
/*
Copyright 2020 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"context"
"fmt"
"github.com/docker/api/errdefs"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/hashicorp/go-multierror"
"github.com/docker/api/client"
)
type stopOpts struct {
timeout uint32
}
// StopCommand deletes containers
func StopCommand() *cobra.Command {
var opts stopOpts
cmd := &cobra.Command{
Use: "stop",
Short: "Stop one or more running containers",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runStop(cmd.Context(), args, opts)
},
}
cmd.Flags().Uint32Var(&opts.timeout, "timeout", 0, "Seconds to wait for stop before killing it (default 0, no timeout)")
return cmd
}
func runStop(ctx context.Context, args []string, opts stopOpts) error {
c, err := client.New(ctx)
if err != nil {
return errors.Wrap(err, "cannot connect to backend")
}
var errs *multierror.Error
for _, id := range args {
err := c.ContainerService().Stop(ctx, id, &opts.timeout)
if err != nil {
if errdefs.IsNotFoundError(err) {
errs = multierror.Append(errs, fmt.Errorf("container %s not found", id))
} else {
errs = multierror.Append(errs, err)
}
continue
}
fmt.Println(id)
}
if errs != nil {
errs.ErrorFormat = formatErrors
}
return errs.ErrorOrNil()
}

View File

@ -124,6 +124,7 @@ func main() {
login.Command(),
logout.Command(),
cmd.VersionCommand(version),
cmd.StopCommand(),
)
helpFunc := root.HelpFunc()

View File

@ -360,8 +360,21 @@ func TestContainerRunAttached(t *testing.T) {
poll.WaitOn(t, checkLog, poll.WithDelay(1*time.Second), poll.WithTimeout(20*time.Second))
})
t.Run("rm attached", func(t *testing.T) {
res := c.RunDockerCmd("rm", "-f", container)
t.Run("stop wrong container", func(t *testing.T) {
res := c.RunDockerCmd("stop", "unknown-container")
res.Assert(t, icmd.Expected{
Err: "Error: container unknown-container not found",
ExitCode: 1,
})
})
t.Run("stop container", func(t *testing.T) {
res := c.RunDockerCmd("stop", container)
res.Assert(t, icmd.Expected{Out: container})
})
t.Run("rm stopped container", func(t *testing.T) {
res := c.RunDockerCmd("rm", container)
res.Assert(t, icmd.Expected{Out: container})
})
}