Przeglądaj źródła

Add JSON stream progress writer

Signed-off-by: Felix Fontein <[email protected]>
Felix Fontein 1 rok temu
rodzic
commit
06545d0668

+ 3 - 0
cmd/compose/compose.go

@@ -453,6 +453,8 @@ func RootCommand(dockerCli command.Cli, backend Backend) *cobra.Command { //noli
 				ui.Mode = ui.ModePlain
 			case ui.ModeQuiet, "none":
 				ui.Mode = ui.ModeQuiet
+			case ui.ModeJSON:
+				ui.Mode = ui.ModeJSON
 			default:
 				return fmt.Errorf("unsupported --progress value %q", opts.Progress)
 			}
@@ -603,6 +605,7 @@ var printerModes = []string{
 	ui.ModeAuto,
 	ui.ModeTTY,
 	ui.ModePlain,
+	ui.ModeJSON,
 	ui.ModeQuiet,
 }
 

+ 1 - 1
docs/reference/compose.md

@@ -51,7 +51,7 @@ Define and run multi-container applications with Docker
 | `-f`, `--file`         | `stringArray` |         | Compose configuration files                                                                         |
 | `--parallel`           | `int`         | `-1`    | Control max parallelism, -1 for unlimited                                                           |
 | `--profile`            | `stringArray` |         | Specify a profile to enable                                                                         |
-| `--progress`           | `string`      | `auto`  | Set type of progress output (auto, tty, plain, quiet)                                               |
+| `--progress`           | `string`      | `auto`  | Set type of progress output (auto, tty, plain, json, quiet)                                         |
 | `--project-directory`  | `string`      |         | Specify an alternate working directory<br>(default: the path of the, first specified, Compose file) |
 | `-p`, `--project-name` | `string`      |         | Project name                                                                                        |
 

+ 1 - 1
docs/reference/docker_compose.yaml

@@ -306,7 +306,7 @@ options:
     - option: progress
       value_type: string
       default_value: auto
-      description: Set type of progress output (auto, tty, plain, quiet)
+      description: Set type of progress output (auto, tty, plain, json, quiet)
       deprecated: false
       hidden: false
       experimental: false

+ 1 - 1
docs/reference/docker_compose_build.yaml

@@ -99,7 +99,7 @@ options:
     - option: progress
       value_type: string
       default_value: auto
-      description: Set type of ui output (auto, tty, plain, quiet)
+      description: Set type of ui output (auto, tty, plain, json, quiet)
       deprecated: false
       hidden: true
       experimental: false

+ 88 - 0
pkg/progress/json.go

@@ -0,0 +1,88 @@
+/*
+   Copyright 2024 Docker Compose CLI authors
+
+   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 progress
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"io"
+)
+
+type jsonWriter struct {
+	out    io.Writer
+	done   chan bool
+	dryRun bool
+}
+
+type jsonMessage struct {
+	DryRun bool   `json:"dry-run,omitempty"`
+	Tail   bool   `json:"tail,omitempty"`
+	ID     string `json:"id,omitempty"`
+	Text   string `json:"text,omitempty"`
+	Status string `json:"status,omitempty"`
+}
+
+func (p *jsonWriter) Start(ctx context.Context) error {
+	select {
+	case <-ctx.Done():
+		return ctx.Err()
+	case <-p.done:
+		return nil
+	}
+}
+
+func (p *jsonWriter) Event(e Event) {
+	var message = &jsonMessage{
+		DryRun: p.dryRun,
+		Tail:   false,
+		ID:     e.ID,
+		Text:   e.Text,
+		Status: e.StatusText,
+	}
+	marshal, err := json.Marshal(message)
+	if err == nil {
+		fmt.Fprintln(p.out, string(marshal))
+	}
+}
+
+func (p *jsonWriter) Events(events []Event) {
+	for _, e := range events {
+		p.Event(e)
+	}
+}
+
+func (p *jsonWriter) TailMsgf(msg string, args ...interface{}) {
+	var message = &jsonMessage{
+		DryRun: p.dryRun,
+		Tail:   true,
+		ID:     "",
+		Text:   fmt.Sprintf(msg, args...),
+		Status: "",
+	}
+	marshal, err := json.Marshal(message)
+	if err == nil {
+		fmt.Fprintln(p.out, string(marshal))
+	}
+}
+
+func (p *jsonWriter) Stop() {
+	p.done <- true
+}
+
+func (p *jsonWriter) HasMore(bool) {
+}

+ 9 - 0
pkg/progress/writer.go

@@ -107,6 +107,8 @@ const (
 	ModePlain = "plain"
 	// ModeQuiet don't display events
 	ModeQuiet = "quiet"
+	// ModeJSON outputs a machine-readable JSON stream
+	ModeJSON = "json"
 )
 
 // Mode define how progress should be rendered, either as ModePlain or ModeTTY
@@ -130,6 +132,13 @@ func NewWriter(ctx context.Context, out *streams.Out, progressTitle string) (Wri
 	if tty {
 		return newTTYWriter(out, dryRun, progressTitle)
 	}
+	if Mode == ModeJSON {
+		return &jsonWriter{
+			out:    out,
+			done:   make(chan bool),
+			dryRun: dryRun,
+		}, nil
+	}
 	return &plainWriter{
 		out:    out,
 		done:   make(chan bool),