github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/cli/command/system/events.go (about)

     1  package system
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/ioutil"
     7  	"sort"
     8  	"strings"
     9  	"text/template"
    10  	"time"
    11  
    12  	"golang.org/x/net/context"
    13  
    14  	"github.com/docker/docker/api/types"
    15  	eventtypes "github.com/docker/docker/api/types/events"
    16  	"github.com/docker/docker/cli"
    17  	"github.com/docker/docker/cli/command"
    18  	"github.com/docker/docker/opts"
    19  	"github.com/docker/docker/pkg/jsonlog"
    20  	"github.com/docker/docker/utils/templates"
    21  	"github.com/spf13/cobra"
    22  )
    23  
    24  type eventsOptions struct {
    25  	since  string
    26  	until  string
    27  	filter opts.FilterOpt
    28  	format string
    29  }
    30  
    31  // NewEventsCommand creates a new cobra.Command for `docker events`
    32  func NewEventsCommand(dockerCli *command.DockerCli) *cobra.Command {
    33  	opts := eventsOptions{filter: opts.NewFilterOpt()}
    34  
    35  	cmd := &cobra.Command{
    36  		Use:   "events [OPTIONS]",
    37  		Short: "Get real time events from the server",
    38  		Args:  cli.NoArgs,
    39  		RunE: func(cmd *cobra.Command, args []string) error {
    40  			return runEvents(dockerCli, &opts)
    41  		},
    42  	}
    43  
    44  	flags := cmd.Flags()
    45  	flags.StringVar(&opts.since, "since", "", "Show all events created since timestamp")
    46  	flags.StringVar(&opts.until, "until", "", "Stream events until this timestamp")
    47  	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")
    48  	flags.StringVar(&opts.format, "format", "", "Format the output using the given Go template")
    49  
    50  	return cmd
    51  }
    52  
    53  func runEvents(dockerCli *command.DockerCli, opts *eventsOptions) error {
    54      fmt.Println("cli/command/system/events.go  runEvent()")
    55  	tmpl, err := makeTemplate(opts.format)
    56  	if err != nil {
    57  		return cli.StatusError{
    58  			StatusCode: 64,
    59  			Status:     "Error parsing format: " + err.Error()}
    60  	}
    61  	options := types.EventsOptions{
    62  		Since:   opts.since,
    63  		Until:   opts.until,
    64  		Filters: opts.filter.Value(),
    65  	}
    66  
    67  	ctx, cancel := context.WithCancel(context.Background())
    68  	events, errs := dockerCli.Client().Events(ctx, options)
    69  	defer cancel()
    70  
    71  	out := dockerCli.Out()
    72  
    73  	for {
    74  		select {
    75  		case event := <-events:
    76  			if err := handleEvent(out, event, tmpl); err != nil {
    77  				return err
    78  			}
    79  		case err := <-errs:
    80  			if err == io.EOF {
    81  				return nil
    82  			}
    83  			return err
    84  		}
    85  	}
    86  }
    87  
    88  func handleEvent(out io.Writer, event eventtypes.Message, tmpl *template.Template) error {
    89  	if tmpl == nil {
    90  		return prettyPrintEvent(out, event)
    91  	}
    92  
    93  	return formatEvent(out, event, tmpl)
    94  }
    95  
    96  func makeTemplate(format string) (*template.Template, error) {
    97  	if format == "" {
    98  		return nil, nil
    99  	}
   100  	tmpl, err := templates.Parse(format)
   101  	if err != nil {
   102  		return tmpl, err
   103  	}
   104  	// we execute the template for an empty message, so as to validate
   105  	// a bad template like "{{.badFieldString}}"
   106  	return tmpl, tmpl.Execute(ioutil.Discard, &eventtypes.Message{})
   107  }
   108  
   109  // prettyPrintEvent prints all types of event information.
   110  // Each output includes the event type, actor id, name and action.
   111  // Actor attributes are printed at the end if the actor has any.
   112  func prettyPrintEvent(out io.Writer, event eventtypes.Message) error {
   113  	if event.TimeNano != 0 {
   114  		fmt.Fprintf(out, "%s ", time.Unix(0, event.TimeNano).Format(jsonlog.RFC3339NanoFixed))
   115  	} else if event.Time != 0 {
   116  		fmt.Fprintf(out, "%s ", time.Unix(event.Time, 0).Format(jsonlog.RFC3339NanoFixed))
   117  	}
   118  
   119  	fmt.Fprintf(out, "%s %s %s", event.Type, event.Action, event.Actor.ID)
   120  
   121  	if len(event.Actor.Attributes) > 0 {
   122  		var attrs []string
   123  		var keys []string
   124  		for k := range event.Actor.Attributes {
   125  			keys = append(keys, k)
   126  		}
   127  		sort.Strings(keys)
   128  		for _, k := range keys {
   129  			v := event.Actor.Attributes[k]
   130  			attrs = append(attrs, fmt.Sprintf("%s=%s", k, v))
   131  		}
   132  		fmt.Fprintf(out, " (%s)", strings.Join(attrs, ", "))
   133  	}
   134  	fmt.Fprint(out, "\n")
   135  	return nil
   136  }
   137  
   138  func formatEvent(out io.Writer, event eventtypes.Message, tmpl *template.Template) error {
   139  	defer out.Write([]byte{'\n'})
   140  	return tmpl.Execute(out, event)
   141  }