diff --git a/azure/aci.go b/azure/aci.go index 0bf48346..25396dfc 100644 --- a/azure/aci.go +++ b/azure/aci.go @@ -224,6 +224,16 @@ func exec(ctx context.Context, address string, password string, reader io.Reader } } +func getACIContainerLogs(ctx context.Context, aciContext store.AciContext, containerGroupName, containerName string) (string, error) { + containerClient := getContainerClient(aciContext.SubscriptionID) + + logs, err := containerClient.ListLogs(ctx, aciContext.ResourceGroup, containerGroupName, containerName, nil) + if err != nil { + return "", fmt.Errorf("cannot get container logs: %v", err) + } + return *logs.Content, err +} + func getContainerGroupsClient(subscriptionID string) (containerinstance.ContainerGroupsClient, error) { auth, _ := auth.NewAuthorizerFromCLI() containerGroupsClient := containerinstance.NewContainerGroupsClient(subscriptionID) diff --git a/azure/backend.go b/azure/backend.go index 544e5e9b..03de06f9 100644 --- a/azure/backend.go +++ b/azure/backend.go @@ -2,7 +2,10 @@ package azure import ( "context" + "fmt" "io" + "strconv" + "strings" "github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance" "github.com/Azure/go-autorest/autorest/azure/auth" @@ -137,3 +140,25 @@ func (cs *containerService) Exec(ctx context.Context, name string, command strin writer, ) } + +func (cs *containerService) Logs(ctx context.Context, containerName string, req containers.LogsRequest) error { + logs, err := getACIContainerLogs(ctx, cs.ctx, containerName, containerName) + if err != nil { + return err + } + if req.Tail != "all" { + tail, err := strconv.Atoi(req.Tail) + if err != nil { + return err + } + lines := strings.Split(logs, "\n") + + // If asked for less lines than exist, take only those lines + if tail <= len(lines) { + logs = strings.Join(lines[len(lines)-tail:], "\n") + } + } + + _, err = fmt.Fprint(req.Writer, logs) + return err +} diff --git a/cli/cmd/logs.go b/cli/cmd/logs.go new file mode 100644 index 00000000..16a39ffe --- /dev/null +++ b/cli/cmd/logs.go @@ -0,0 +1,49 @@ +package cmd + +import ( + "context" + "os" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/docker/api/client" + "github.com/docker/api/containers" +) + +type logsOpts struct { + Follow bool + Tail string +} + +func LogsCommand() *cobra.Command { + var opts logsOpts + cmd := &cobra.Command{ + Use: "logs", + Short: "Fetch the logs of a container", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + return runLogs(cmd.Context(), args[0], opts) + }, + } + + cmd.Flags().BoolVarP(&opts.Follow, "follow", "f", false, "Follow log outut") + cmd.Flags().StringVar(&opts.Tail, "tail", "all", "Number of lines to show from the end of the logs") + + return cmd +} + +func runLogs(ctx context.Context, containerName string, opts logsOpts) error { + c, err := client.New(ctx) + if err != nil { + return errors.Wrap(err, "cannot connect to backend") + } + + req := containers.LogsRequest{ + Follow: opts.Follow, + Tail: opts.Tail, + Writer: os.Stdout, + } + + return c.ContainerService().Logs(ctx, containerName, req) +} diff --git a/cli/main.go b/cli/main.go index 7f6e3b7d..7e1f00da 100644 --- a/cli/main.go +++ b/cli/main.go @@ -102,6 +102,7 @@ func main() { &cmd.ExampleCommand, run.Command(), cmd.ExecCommand(), + cmd.LogsCommand(), ) helpFunc := root.HelpFunc() diff --git a/containers/api.go b/containers/api.go index b4e91421..d437ddb5 100644 --- a/containers/api.go +++ b/containers/api.go @@ -37,6 +37,12 @@ type ContainerConfig struct { Ports []Port } +type LogsRequest struct { + Follow bool + Tail string + Writer io.Writer +} + // ContainerService interacts with the underlying container backend type ContainerService interface { // List returns all the containers @@ -45,4 +51,6 @@ type ContainerService interface { Run(ctx context.Context, config ContainerConfig) error // Exec executes a command inside a running container Exec(ctx context.Context, containerName string, command string, reader io.Reader, writer io.Writer) error + // Logs returns all the logs of a container + Logs(ctx context.Context, containerName string, request LogsRequest) error } diff --git a/example/backend.go b/example/backend.go index f1ec5022..03cff36c 100644 --- a/example/backend.go +++ b/example/backend.go @@ -43,3 +43,8 @@ func (cs *containerService) Exec(ctx context.Context, name string, command strin fmt.Printf("Executing command %q on container %q", command, name) return nil } + +func (cs *containerService) Logs(ctx context.Context, containerName string, request containers.LogsRequest) error { + fmt.Fprintf(request.Writer, "Following logs for container %q", containerName) + return nil +}