github.com/ncdc/docker@v0.10.1-0.20160129113957-6c6729ef5b74/api/client/events.go (about)

     1  package client
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  	"time"
     9  
    10  	Cli "github.com/docker/docker/cli"
    11  	"github.com/docker/docker/opts"
    12  	"github.com/docker/docker/pkg/jsonlog"
    13  	flag "github.com/docker/docker/pkg/mflag"
    14  	"github.com/docker/engine-api/types"
    15  	eventtypes "github.com/docker/engine-api/types/events"
    16  	"github.com/docker/engine-api/types/filters"
    17  )
    18  
    19  // CmdEvents prints a live stream of real time events from the server.
    20  //
    21  // Usage: docker events [OPTIONS]
    22  func (cli *DockerCli) CmdEvents(args ...string) error {
    23  	cmd := Cli.Subcmd("events", nil, Cli.DockerCommands["events"].Description, true)
    24  	since := cmd.String([]string{"-since"}, "", "Show all events created since timestamp")
    25  	until := cmd.String([]string{"-until"}, "", "Stream events until this timestamp")
    26  	flFilter := opts.NewListOpts(nil)
    27  	cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided")
    28  	cmd.Require(flag.Exact, 0)
    29  
    30  	cmd.ParseFlags(args, true)
    31  
    32  	eventFilterArgs := filters.NewArgs()
    33  
    34  	// Consolidate all filter flags, and sanity check them early.
    35  	// They'll get process in the daemon/server.
    36  	for _, f := range flFilter.GetAll() {
    37  		var err error
    38  		eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs)
    39  		if err != nil {
    40  			return err
    41  		}
    42  	}
    43  
    44  	options := types.EventsOptions{
    45  		Since:   *since,
    46  		Until:   *until,
    47  		Filters: eventFilterArgs,
    48  	}
    49  
    50  	responseBody, err := cli.client.Events(options)
    51  	if err != nil {
    52  		return err
    53  	}
    54  	defer responseBody.Close()
    55  
    56  	return streamEvents(responseBody, cli.out)
    57  }
    58  
    59  // streamEvents decodes prints the incoming events in the provided output.
    60  func streamEvents(input io.Reader, output io.Writer) error {
    61  	return decodeEvents(input, func(event eventtypes.Message, err error) error {
    62  		if err != nil {
    63  			return err
    64  		}
    65  		printOutput(event, output)
    66  		return nil
    67  	})
    68  }
    69  
    70  type eventProcessor func(event eventtypes.Message, err error) error
    71  
    72  func decodeEvents(input io.Reader, ep eventProcessor) error {
    73  	dec := json.NewDecoder(input)
    74  	for {
    75  		var event eventtypes.Message
    76  		err := dec.Decode(&event)
    77  		if err != nil && err == io.EOF {
    78  			break
    79  		}
    80  
    81  		if procErr := ep(event, err); procErr != nil {
    82  			return procErr
    83  		}
    84  	}
    85  	return nil
    86  }
    87  
    88  // printOutput prints all types of event information.
    89  // Each output includes the event type, actor id, name and action.
    90  // Actor attributes are printed at the end if the actor has any.
    91  func printOutput(event eventtypes.Message, output io.Writer) {
    92  	if event.TimeNano != 0 {
    93  		fmt.Fprintf(output, "%s ", time.Unix(0, event.TimeNano).Format(jsonlog.RFC3339NanoFixed))
    94  	} else if event.Time != 0 {
    95  		fmt.Fprintf(output, "%s ", time.Unix(event.Time, 0).Format(jsonlog.RFC3339NanoFixed))
    96  	}
    97  
    98  	fmt.Fprintf(output, "%s %s %s", event.Type, event.Action, event.Actor.ID)
    99  
   100  	if len(event.Actor.Attributes) > 0 {
   101  		var attrs []string
   102  		for k, v := range event.Actor.Attributes {
   103  			attrs = append(attrs, fmt.Sprintf("%s=%s", k, v))
   104  		}
   105  		fmt.Fprintf(output, " (%s)", strings.Join(attrs, ", "))
   106  	}
   107  	fmt.Fprint(output, "\n")
   108  }