diff --git a/azure/aci.go b/azure/aci.go index 6b13283f..7785a440 100644 --- a/azure/aci.go +++ b/azure/aci.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "net/http" + "strings" "time" "github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance" @@ -29,6 +30,7 @@ import ( tm "github.com/buger/goterm" "github.com/gobwas/ws" "github.com/gobwas/ws/wsutil" + "github.com/morikuni/aec" "github.com/pkg/errors" "github.com/docker/api/azure/login" @@ -234,6 +236,42 @@ func getACIContainerLogs(ctx context.Context, aciContext store.AciContext, conta return *logs.Content, err } +func streamLogs(ctx context.Context, aciContext store.AciContext, containerGroupName, containerName string, out io.Writer) error { + lastOutput := 0 + for { + select { + case <-ctx.Done(): + return nil + default: + logs, err := getACIContainerLogs(ctx, aciContext, containerGroupName, containerName, nil) + if err != nil { + return err + } + logLines := strings.Split(logs, "\n") + currentOutput := len(logLines) + + b := aec.EmptyBuilder + for i := 0; i < lastOutput; i++ { + b = b.Up(1) + } + + // Note: a backend should not do this normally, this breaks the log + // streaming over gRPC but this is the only thing we can do with + // the kind of logs ACI is giving us. Hopefully Azue will give us + // a real logs streaming api soon. + fmt.Fprint(out, b.Column(0).ANSI) + + for i := 0; i < currentOutput-1; i++ { + fmt.Fprintln(out, logLines[i]) + } + + lastOutput = currentOutput - 1 + + time.Sleep(2 * time.Second) + } + } +} + func getContainerGroupsClient(subscriptionID string) (containerinstance.ContainerGroupsClient, error) { containerGroupsClient := containerinstance.NewContainerGroupsClient(subscriptionID) err := setupClient(&containerGroupsClient.Client) diff --git a/azure/backend.go b/azure/backend.go index 623bfddf..20406cf5 100644 --- a/azure/backend.go +++ b/azure/backend.go @@ -24,12 +24,8 @@ import ( "strconv" "strings" - "github.com/Azure/go-autorest/autorest/to" - - "github.com/docker/api/context/cloud" - "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/to" "github.com/compose-spec/compose-go/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -40,7 +36,9 @@ import ( "github.com/docker/api/compose" "github.com/docker/api/containers" apicontext "github.com/docker/api/context" + "github.com/docker/api/context/cloud" "github.com/docker/api/context/store" + "github.com/docker/api/errdefs" ) const singleContainerName = "single--container--aci" @@ -238,6 +236,10 @@ func (cs *aciContainerService) Logs(ctx context.Context, containerName string, r groupName, containerAciName := getGroupAndContainerName(containerName) var tail *int32 + if req.Follow { + return streamLogs(ctx, cs.ctx, groupName, containerAciName, req.Writer) + } + if req.Tail != "all" { reqTail, err := strconv.Atoi(req.Tail) if err != nil {