flyte

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 18, 2019 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package flyte is where you find the main public api for the flyte client. Almost all of your interactions with the client will occur here.

Index

Examples

Constants

This section is empty.

Variables

View Source
var StartHealthCheckServer = true // this is only overridden for testing purposes

Functions

This section is empty.

Types

type Command

type Command struct {
	Name         string         // the name of the command
	OutputEvents []EventDef     // the events a pack can output
	Handler      CommandHandler // the handler is where the functionality of a pack is implemented when a command is called
	HelpURL      *url.URL       // optional
}

Defines a command - its name, the events it can output and a handler for incoming actions. The help URL is optional.

Example
package main

import (
	"encoding/json"
	"fmt"
	"github.com/HotelsDotCom/flyte-client/flyte"
	"net/url"
)

type CreateIssueInput struct {
	Project    string `json:"project"`
	TicketText string `json:"ticketText"`
}

type IssueCreatedPayload struct {
	Project  string   `json:"project"`
	IssueId  string   `json:"issueId"`
	Location *url.URL `json:"location"`
}

func createURL(u string) *url.URL {
	url, _ := url.Parse(u)
	return url
}

func main() {
	// to create a command, we need to create and populate at least one output event. often, these will represent
	// a success or failure case
	issueCreatedEventDef := flyte.EventDef{
		Name: "IssueCreated",
	}
	issueCreationErrorEventDef := flyte.EventDef{
		Name: "IssueCreationError",
	}

	// we also need a command handler. this is where the functionality of the command will be implemented
	createIssueHandler := func(input json.RawMessage) flyte.Event {

		// deserialize the raw JSON into our domain struct
		var createIssueInput CreateIssueInput
		json.Unmarshal(input, &createIssueInput)

		// call some ticket creation code...
		// ...

		// if it succeeds then return something like the following. The payload will be serialised to JSON and sent to the Flyte api server.
		return flyte.Event{
			EventDef: issueCreatedEventDef,
			Payload: IssueCreatedPayload{
				Project:  "FOO",
				IssueId:  "123",
				Location: createURL("http://jira/FOO/123"),
			},
		}
	}

	// you can also provide an optional help URL. this will help document your command to your end users
	helpUrl, _ := url.Parse("http://jirapack/help#create-issue-command")

	// you can now give the command a name. it is now ready to be passed into the pack definition
	createIssueCommand := flyte.Command{
		Name: "createIssue",
		OutputEvents: []flyte.EventDef{
			issueCreatedEventDef,
			issueCreationErrorEventDef,
		},
		Handler: createIssueHandler,
		HelpURL: helpUrl,
	}
	fmt.Printf("%+v", createIssueCommand)
}
Output:

type CommandHandler

type CommandHandler func(input json.RawMessage) Event

Command handlers will be invoked with the input JSON when they are invoked from a flow step in the flyte server.

Example
package main

import (
	"encoding/json"
	"fmt"
	"github.com/HotelsDotCom/flyte-client/flyte"
)

func main() {
	// In this example the client will call this handler every time it receives a "createIssue" action from the Flyte api. The handler will take the input JSON from the action
	// and must return a flyte.Event. Handlers are where the functionality of the pack is implemented so will likely form the bulk of most packs.

	// the JSON input passed into the handler will be deserialized into this struct
	type CreateIssueInput struct {
		Project    string `json:"project"`
		TicketText string `json:"ticketText"`
	}

	// this event definition will be passed into the returned flyte.Event below
	issueCreatedEventDef := flyte.EventDef{
		Name: "IssueCreated",
	}

	// this payload struct will used in the returned flyte.Event below
	type IssueCreatedPayload struct {
		Project string `json:"project"`
		IssueId string `json:"issueId"`
	}

	// the handler once created, can now be used in a flyte.Command struct
	createIssueHandler := func(input json.RawMessage) flyte.Event {

		// deserialize the raw JSON into our domain struct
		var createIssueInput CreateIssueInput
		json.Unmarshal(input, &createIssueInput)

		// call some ticket creation code...
		// ...

		// if it succeeds then return something like the following. The payload will be serialised to JSON and sent to the Flyte api server.
		return flyte.Event{
			EventDef: issueCreatedEventDef,
			Payload: IssueCreatedPayload{
				Project: "FOO",
				IssueId: "123",
			},
		}
	}
	fmt.Printf("%+v", createIssueHandler(json.RawMessage{}))
}
Output:

type Event

type Event struct {
	EventDef EventDef
	Payload  interface{}
}

The event data the pack can send for events it observes (using SendEvent()) or from commands that have been called. The payload will be marshalled into JSON, so should be annotated appropriately.

Example
package main

import (
	"fmt"
	"github.com/HotelsDotCom/flyte-client/flyte"
	"net/url"
)

func main() {
	// to create an event, you first need to create a named event definition
	// to help document your event to your end users, you can provide an optional help URL
	helpUrl, _ := url.Parse("http://jirapack/help#create-issue-command")
	issueCreatedEventDef := flyte.EventDef{
		Name:    "IssueCreated",
		HelpURL: helpUrl, // optional
	}

	// you will also need to provide a payload containing the relevant data for the event.
	// the payload will be marshalled into JSON, so should be annotated appropriately
	type IssueCreatedPayload struct {
		Project string `json:"project"`
		IssueId string `json:"issueId"`
	}

	// then simply pass in the event definition and a populated payload struct to create the event
	event := flyte.Event{
		EventDef: issueCreatedEventDef,
		Payload: IssueCreatedPayload{
			Project: "FOO",
			IssueId: "123",
		},
	}
	fmt.Printf("%+v", event)
}
Output:

func NewFatalEvent

func NewFatalEvent(payload interface{}) Event

This is the preferred way for packs to handle serious errors within the handler.

Example
package main

import (
	"fmt"
	"github.com/HotelsDotCom/flyte-client/flyte"
)

func main() {
	payload := fmt.Errorf("some error").Error()
	fmt.Printf("%v", flyte.NewFatalEvent(payload))
}
Output:

type EventDef

type EventDef struct {
	Name    string
	HelpURL *url.URL
}

Defines an event. The help URL is optional.

Example
package main

import (
	"fmt"
	"github.com/HotelsDotCom/flyte-client/flyte"
	"net/url"
)

func main() {
	// an event definition defines an event. to help the end user, you can provide an optional help URL
	helpUrl, _ := url.Parse("http://jirapack/help#issue-created-event-def")

	// once created, the event definition is ready to be passed into a flyte.Event struct
	issueCreatedEventDef := flyte.EventDef{
		Name:    "IssueCreated",
		HelpURL: helpUrl,
	}
	fmt.Printf("%+v", issueCreatedEventDef)
}
Output:

type Pack

type Pack interface {
	// Start will register the pack with the flyte server and will begin handling actions and invoking commands.
	// The pack will also be available to send observed events.
	Start()

	// SendEvent spontaneously sends an event that the pack has observed to the flyte server.
	SendEvent(Event) error
}

func NewPack

func NewPack(packDef PackDef, client client.Client, healthChecks ...healthcheck.HealthCheck) Pack

Creates a Pack struct with the details from the pack definition and a connection to the flyte api through the client. Optionally, you can also pass in pack health checks

Example
package main

import (
	"encoding/json"
	"github.com/HotelsDotCom/flyte-client/client"
	"github.com/HotelsDotCom/flyte-client/flyte"
	"net/url"
	"time"
)

func main() {
	// First we create event definitions that describe what events our pack can raise.
	// An EventDef contains the name of the event (mandatory) and a help URL (optional)
	issueCreatedEventDef := flyte.EventDef{
		Name: "IssueCreated",
	}
	issueCreationErrorEventDef := flyte.EventDef{
		Name: "IssueCreationError",
	}

	// This pack has a single "createIssue" command. To implement a command we must provide a "CommandHandler" function matching the signature below.
	// The client will call this handler every time it receives a "createIssue" action from the Flyte api. The handler will take the input JSON from the action
	// and must return a flyte.Event. Handlers are where the functionality of the pack is implemented so will likely form the bulk of most packs.
	createIssueHandler := func(input json.RawMessage) flyte.Event {

		// deserialize the raw JSON into our domain struct
		var createIssueInput CreateIssueInput
		json.Unmarshal(input, &createIssueInput)

		// call some ticket creation code...
		// ...

		// if it succeeds then return something like the following. The payload will be serialised to JSON and sent to the Flyte api server.
		return flyte.Event{
			EventDef: issueCreatedEventDef,
			Payload: IssueCreatedPayload{
				Project:  "FOO",
				IssueId:  "123",
				Location: createURL("http://jira/FOO/123"),
			},
		}
	}

	// Next we create a struct that defines the "createIssue" command. Note the handler above is passed to it.
	// Also note that we specify what events the command can output.
	// The help URL is optional
	createIssueCommand := flyte.Command{
		Name: "createIssue",
		OutputEvents: []flyte.EventDef{
			issueCreatedEventDef,
			issueCreationErrorEventDef,
		},
		HelpURL: createURL("http://jirapack/help#create-issue-command"),
		Handler: createIssueHandler,
	}

	// The final struct we must define is the PackDef struct which pulls together the above structs to give the full definition of the pack.
	packDef := flyte.PackDef{
		Name:     "JiraPack",
		Commands: []flyte.Command{createIssueCommand},
		HelpURL:  createURL("http://jirapack/help#create-issue-command"),
	}

	// Finally we call NewPack() to create a pack struct. This can then be started by calling Start()
	p := flyte.NewPack(packDef, client.NewClient(createURL("http://example.com"), 10*time.Second))
	// p.Start() is not blocking, it is user's responsibility to make sure that the program does not exit immediately
	p.Start()
}

type CreateIssueInput struct {
	Project    string `json:"project"`
	TicketText string `json:"ticketText"`
}

type IssueCreatedPayload struct {
	Project  string   `json:"project"`
	IssueId  string   `json:"issueId"`
	Location *url.URL `json:"location"`
}

func createURL(u string) *url.URL {
	url, _ := url.Parse(u)
	return url
}
Output:

type PackDef

type PackDef struct {
	Name      string            // the pack name
	Labels    map[string]string // the pack labels. These act as a filter that determines when the pack will execute against a flow
	EventDefs []EventDef        // the event definitions of a pack. These can be events a pack observes and sends spontaneously
	Commands  []Command         // the commands a pack exposes
	HelpURL   *url.URL          // a help url to a page that describes what the pack does and how it is used
}

The main configuration struct for defining a pack.

Example
package main

import (
	"encoding/json"
	"fmt"
	"github.com/HotelsDotCom/flyte-client/flyte"
	"net/url"
)

type CreateIssueInput struct {
	Project    string `json:"project"`
	TicketText string `json:"ticketText"`
}

type IssueCreatedPayload struct {
	Project  string   `json:"project"`
	IssueId  string   `json:"issueId"`
	Location *url.URL `json:"location"`
}

func main() {
	// First we create event definitions that describe what events our pack can raise.
	// An event definition contains the name of the event (mandatory) and a help URL (optional)
	issueCreatedEventDef := flyte.EventDef{
		Name: "IssueCreated",
	}
	issueCreationErrorEventDef := flyte.EventDef{
		Name: "IssueCreationError",
	}

	// This pack has a single "createIssue" command. To implement a command we must provide a "CommandHandler" function matching the signature below.
	// The client will call this handler every time it receives a "createIssue" action from the Flyte api. The handler will take the input JSON from the action
	// and must return a flyte.Event. Handlers are where the functionality of the pack is implemented so will likely form the bulk of most packs.
	createIssueHandler := func(input json.RawMessage) flyte.Event {

		// deserialize the raw JSON into our domain struct
		var createIssueInput CreateIssueInput
		json.Unmarshal(input, &createIssueInput)

		// call some ticket creation code...
		// ...

		// if it succeeds then return something like the following. The payload will be serialised to JSON and sent to the Flyte api server.
		return flyte.Event{
			EventDef: issueCreatedEventDef,
			Payload: IssueCreatedPayload{
				Project: "FOO",
				IssueId: "123",
			},
		}
	}

	// Next we create a struct that defines the "createIssue" command. Note the handler above is passed to it.
	// Also note that we specify what events the command can output.
	createIssueCommand := flyte.Command{
		Name: "createIssue",
		OutputEvents: []flyte.EventDef{
			issueCreatedEventDef,
			issueCreationErrorEventDef,
		},
		Handler: createIssueHandler,
	}

	// you can add (optional) labels that act as a filter that determines when the pack will execute against a flow
	// in this example the pack will only run in a 'production' environment
	labels := make(map[string]string)
	labels["env"] = "prod"

	// you can provide a help URL that describes what the pack does and is used for
	helpUrl, _ := url.Parse("http://jirapack/help#create-issue-command")

	// now we are ready to create the PackDef struct which pulls together the above structs to give the full definition of the pack.
	packDef := flyte.PackDef{
		Name:   "JiraPack",
		Labels: labels,
		EventDefs: []flyte.EventDef{
			issueCreatedEventDef,
			issueCreationErrorEventDef,
		},
		Commands: []flyte.Command{createIssueCommand},
		HelpURL:  helpUrl,
	}
	fmt.Printf("%+v", packDef)
}
Output:

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL