package cmd
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/go-openapi/strfmt"
"github.com/satori/go.uuid"
"github.com/spf13/cobra"
"golang.org/x/net/context"
"github.com/vmware/dispatch/pkg/api/v1"
"github.com/vmware/dispatch/pkg/dispatchcli/i18n"
eventTypes "github.com/vmware/dispatch/pkg/events"
)
var (
emitLong = i18n.T(`Emit an event.`)
emitExample = i18n.T(``)
emitEventDataBinary = false
emitEventData = ""
emitEventDataFromFile = ""
emitEventSource = "dispatch"
emitEventID = ""
emitEventContentType = ""
emitEventTypeVersion = ""
emitEventSchemaURL = ""
)
func NewCmdEmit(out io.Writer, errOut io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "emit EVENT_TYPE [--data PAYLOAD]|[--data-from-file PATH] [--source SOURCE] [--event-type-version VERSION] [--content-type CONTENT_TYPE] [--event-id EVENT_ID]",
Short: i18n.T("Emit a dispatch event"),
Long: emitLong,
Example: emitExample,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
err := runEmit(out, errOut, cmd, args)
CheckErr(err)
},
}
cmd.Flags().StringVar(&emitEventTypeVersion, "event-type-version", "", "Event type version.")
cmd.Flags().StringVar(&emitEventSource, "source-id", emitEventSource, "Event source.")
cmd.Flags().StringVar(&emitEventID, "event-id", "", "Event ID. If empty, will be autogenerated.")
cmd.Flags().StringVar(&emitEventContentType, "content-type", "", "Content type of the payload. Defaults to application/json if --data is used. For --data-from-file, it will try to detect the type.")
cmd.Flags().StringVar(&emitEventData, "data", "", "Event data payload. Mutually exclusive with --data-from-file")
cmd.Flags().StringVar(&emitEventDataFromFile, "data-from-file", "", "Read event payload from the given file path. Mutually exclusive with --data")
cmd.Flags().BoolVar(&emitEventDataBinary, "binary", false, "Sets payload as binary (will be base64 encoded). If not specified, automatic detection will be attempted.")
cmd.Flags().StringVar(&emitEventSchemaURL, "event-schema-url", "", "Event Schema URL.")
return cmd
}
func runEmit(out, errOut io.Writer, cmd *cobra.Command, args []string) error {
if emitEventID == "" {
emitEventID = uuid.NewV4().String()
}
data, contentType, err := getData()
if err != nil {
fmt.Fprintf(errOut, "Error reading event data: %s", err)
return err
}
emission := &v1.Emission{
CloudEvent: v1.CloudEvent{
CloudEventsVersion: eventTypes.CloudEventsVersion,
ContentType: contentType,
Data: data,
EventID: emitEventID,
EventTime: strfmt.DateTime(time.Now()),
EventType: args[0],
EventTypeVersion: emitEventTypeVersion,
SchemaURL: emitEventSchemaURL,
Source: emitEventSource,
},
}
client := eventManagerClient()
_, err = client.EmitEvent(context.TODO(), "", emission)
if err != nil {
return err
}
fmt.Fprintln(out, "event emitted")
return nil
}
func getData() (data []byte, contentType string, err error) {
if emitEventData == "" && emitEventDataFromFile == "" {
return nil, "", nil
}
if emitEventData != "" && emitEventDataFromFile != "" {
return nil, "", errors.New("--data and --data-from-file are mutually exclusive, specify only one of them")
}
if emitEventData != "" {
return json.RawMessage(emitEventData), "application/json", nil
}
buf, err := ioutil.ReadFile(emitEventDataFromFile)
if err != nil {
return nil, "", err
}
contentType = http.DetectContentType(buf)
if emitEventDataBinary || !strings.HasPrefix(contentType, "text") {
encodedBuf := make([]byte, base64.StdEncoding.EncodedLen(len(buf)))
base64.StdEncoding.Encode(encodedBuf, buf)
buf = encodedBuf
}
if emitEventContentType != "" {
contentType = emitEventContentType
}
return buf, contentType, nil
}