atc

package module
v0.0.0-...-7fe2d08 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2016 License: Apache-2.0 Imports: 11 Imported by: 0

README

atc

air traffic control - web ui and build scheduler

Air Traffic Control

by NATS Press Office

about

atc is the brain of Concourse. It's responsible for scheduling builds across the cluster of workers, providing the API for the system, as well as serving the web interface.

It can be scaled horizontally behind a load balancer in order to scale the system.

Documentation

Index

Constants

View Source
const (
	LinkRelNext     = "next"
	LinkRelPrevious = "previous"

	PaginationQuerySince      = "since"
	PaginationQueryUntil      = "until"
	PaginationQueryLimit      = "limit"
	PaginationWebLimit        = 100
	PaginationAPIDefaultLimit = 100
)
View Source
const (
	SaveConfig = "SaveConfig"
	GetConfig  = "GetConfig"

	GetBuild            = "GetBuild"
	GetBuildPlan        = "GetBuildPlan"
	CreateBuild         = "CreateBuild"
	ListBuilds          = "ListBuilds"
	BuildEvents         = "BuildEvents"
	BuildResources      = "BuildResources"
	AbortBuild          = "AbortBuild"
	GetBuildPreparation = "GetBuildPreparation"

	GetJob         = "GetJob"
	CreateJobBuild = "CreateJobBuild"
	ListJobs       = "ListJobs"
	ListJobBuilds  = "ListJobBuilds"
	ListJobInputs  = "ListJobInputs"
	GetJobBuild    = "GetJobBuild"
	PauseJob       = "PauseJob"
	UnpauseJob     = "UnpauseJob"
	GetVersionsDB  = "GetVersionsDB"
	JobBadge       = "JobBadge"

	ListResources   = "ListResources"
	GetResource     = "GetResource"
	PauseResource   = "PauseResource"
	UnpauseResource = "UnpauseResource"
	CheckResource   = "CheckResource"

	ListResourceVersions          = "ListResourceVersions"
	EnableResourceVersion         = "EnableResourceVersion"
	DisableResourceVersion        = "DisableResourceVersion"
	ListBuildsWithVersionAsInput  = "ListBuildsWithVersionAsInput"
	ListBuildsWithVersionAsOutput = "ListBuildsWithVersionAsOutput"

	ListAllPipelines = "ListAllPipelines"
	ListPipelines    = "ListPipelines"
	GetPipeline      = "GetPipeline"
	DeletePipeline   = "DeletePipeline"
	OrderPipelines   = "OrderPipelines"
	PausePipeline    = "PausePipeline"
	UnpausePipeline  = "UnpausePipeline"
	RevealPipeline   = "RevealPipeline"
	ConcealPipeline  = "ConcealPipeline"
	RenamePipeline   = "RenamePipeline"

	CreatePipe = "CreatePipe"
	WritePipe  = "WritePipe"
	ReadPipe   = "ReadPipe"

	RegisterWorker = "RegisterWorker"
	ListWorkers    = "ListWorkers"

	SetLogLevel = "SetLogLevel"
	GetLogLevel = "GetLogLevel"

	DownloadCLI = "DownloadCLI"
	GetInfo     = "Info"

	ListContainers  = "ListContainers"
	GetContainer    = "GetContainer"
	HijackContainer = "HijackContainer"

	ListVolumes = "ListVolumes"

	ListAuthMethods = "ListAuthMethods"
	GetAuthToken    = "GetAuthToken"

	ListTeams = "ListTeams"
	SetTeam   = "SetTeam"
)
View Source
const ConfigVersionHeader = "X-Concourse-Config-Version"
View Source
const DefaultPipelineName = "main"
View Source
const DefaultTeamName = "main"
View Source
const VersionEvery = "every"
View Source
const VersionLatest = "latest"
View Source
const VersionPinned = "pinned"

Variables

View Source
var Routes = rata.Routes([]rata.Route{
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/config", Method: "PUT", Name: SaveConfig},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/config", Method: "GET", Name: GetConfig},

	{Path: "/api/v1/builds", Method: "POST", Name: CreateBuild},
	{Path: "/api/v1/builds", Method: "GET", Name: ListBuilds},
	{Path: "/api/v1/builds/:build_id", Method: "GET", Name: GetBuild},
	{Path: "/api/v1/builds/:build_id/plan", Method: "GET", Name: GetBuildPlan},
	{Path: "/api/v1/builds/:build_id/events", Method: "GET", Name: BuildEvents},
	{Path: "/api/v1/builds/:build_id/resources", Method: "GET", Name: BuildResources},
	{Path: "/api/v1/builds/:build_id/abort", Method: "POST", Name: AbortBuild},
	{Path: "/api/v1/builds/:build_id/preparation", Method: "GET", Name: GetBuildPreparation},

	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs", Method: "GET", Name: ListJobs},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs/:job_name", Method: "GET", Name: GetJob},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs/:job_name/builds", Method: "GET", Name: ListJobBuilds},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs/:job_name/builds", Method: "POST", Name: CreateJobBuild},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs/:job_name/inputs", Method: "GET", Name: ListJobInputs},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs/:job_name/builds/:build_name", Method: "GET", Name: GetJobBuild},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs/:job_name/pause", Method: "PUT", Name: PauseJob},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs/:job_name/unpause", Method: "PUT", Name: UnpauseJob},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/jobs/:job_name/badge", Method: "GET", Name: JobBadge},

	{Path: "/api/v1/pipelines", Method: "GET", Name: ListAllPipelines},
	{Path: "/api/v1/teams/:team_name/pipelines", Method: "GET", Name: ListPipelines},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name", Method: "GET", Name: GetPipeline},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name", Method: "DELETE", Name: DeletePipeline},
	{Path: "/api/v1/teams/:team_name/pipelines/ordering", Method: "PUT", Name: OrderPipelines},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/pause", Method: "PUT", Name: PausePipeline},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/unpause", Method: "PUT", Name: UnpausePipeline},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/reveal", Method: "PUT", Name: RevealPipeline},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/conceal", Method: "PUT", Name: ConcealPipeline},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/versions-db", Method: "GET", Name: GetVersionsDB},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/rename", Method: "PUT", Name: RenamePipeline},

	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources", Method: "GET", Name: ListResources},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name", Method: "GET", Name: GetResource},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name/pause", Method: "PUT", Name: PauseResource},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name/unpause", Method: "PUT", Name: UnpauseResource},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name/check", Method: "POST", Name: CheckResource},

	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name/versions", Method: "GET", Name: ListResourceVersions},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name/versions/:resource_version_id/enable", Method: "PUT", Name: EnableResourceVersion},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name/versions/:resource_version_id/disable", Method: "PUT", Name: DisableResourceVersion},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name/versions/:resource_version_id/input_to", Method: "GET", Name: ListBuildsWithVersionAsInput},
	{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/resources/:resource_name/versions/:resource_version_id/output_of", Method: "GET", Name: ListBuildsWithVersionAsOutput},

	{Path: "/api/v1/pipes", Method: "POST", Name: CreatePipe},
	{Path: "/api/v1/pipes/:pipe_id", Method: "PUT", Name: WritePipe},
	{Path: "/api/v1/pipes/:pipe_id", Method: "GET", Name: ReadPipe},

	{Path: "/api/v1/workers", Method: "GET", Name: ListWorkers},
	{Path: "/api/v1/workers", Method: "POST", Name: RegisterWorker},

	{Path: "/api/v1/log-level", Method: "GET", Name: GetLogLevel},
	{Path: "/api/v1/log-level", Method: "PUT", Name: SetLogLevel},

	{Path: "/api/v1/cli", Method: "GET", Name: DownloadCLI},
	{Path: "/api/v1/info", Method: "GET", Name: GetInfo},

	{Path: "/api/v1/containers", Method: "GET", Name: ListContainers},
	{Path: "/api/v1/containers/:id", Method: "GET", Name: GetContainer},
	{Path: "/api/v1/containers/:id/hijack", Method: "GET", Name: HijackContainer},

	{Path: "/api/v1/volumes", Method: "GET", Name: ListVolumes},

	{Path: "/api/v1/teams/:team_name/auth/methods", Method: "GET", Name: ListAuthMethods},
	{Path: "/api/v1/teams/:team_name/auth/token", Method: "GET", Name: GetAuthToken},

	{Path: "/api/v1/teams", Method: "GET", Name: ListTeams},
	{Path: "/api/v1/teams/:team_name", Method: "PUT", Name: SetTeam},
})
View Source
var SanitizeDecodeHook = func(
	dataKind reflect.Kind,
	valKind reflect.Kind,
	data interface{},
) (interface{}, error) {
	if valKind == reflect.Map {
		if dataKind == reflect.Map {
			return sanitize(data)
		}
	}

	if valKind == reflect.String {
		if dataKind == reflect.String {
			return data, nil
		}

		if dataKind == reflect.Float64 {
			if f, ok := data.(float64); ok {
				return strconv.FormatFloat(f, 'f', -1, 64), nil
			}

			return nil, errors.New("impossible: float64 != float64")
		}

		return json.Marshal(data)
	}

	return data, nil
}
View Source
var VersionConfigDecodeHook = func(
	srcType reflect.Type,
	dstType reflect.Type,
	data interface{},
) (interface{}, error) {
	if dstType != reflect.TypeOf(VersionConfig{}) {
		return data, nil
	}

	switch {
	case srcType.Kind() == reflect.String:
		if s, ok := data.(string); ok {
			return VersionConfig{
				Every:  s == VersionEvery,
				Latest: s == VersionLatest,
			}, nil
		}
	case srcType.Kind() == reflect.Map:
		version := Version{}
		if versionConfig, ok := data.(map[interface{}]interface{}); ok {
			for key, val := range versionConfig {
				if sKey, ok := key.(string); ok {
					if sVal, ok := val.(string); ok {
						version[sKey] = strings.TrimSpace(sVal)
					}
				}
			}

			return VersionConfig{
				Pinned: version,
			}, nil
		}
	}

	return data, nil
}

Functions

This section is empty.

Types

type AggregatePlan

type AggregatePlan []Plan

func (AggregatePlan) Public

func (plan AggregatePlan) Public() *json.RawMessage

type AuthMethod

type AuthMethod struct {
	Type AuthType `json:"type"`

	DisplayName string `json:"display_name"`
	AuthURL     string `json:"auth_url"`
}

type AuthToken

type AuthToken struct {
	Type  string `json:"type"`
	Value string `json:"value"`
}

type AuthType

type AuthType string
const (
	AuthTypeBasic AuthType = "basic"
	AuthTypeOAuth AuthType = "oauth"
)

type BasicAuth

type BasicAuth struct {
	BasicAuthUsername string `json:"basic_auth_username,omitempty"`
	BasicAuthPassword string `json:"basic_auth_password,omitempty"`
}

type Build

type Build struct {
	ID           int    `json:"id"`
	TeamName     string `json:"team_name"`
	Name         string `json:"name"`
	Status       string `json:"status"`
	JobName      string `json:"job_name,omitempty"`
	URL          string `json:"url"`
	APIURL       string `json:"api_url"`
	PipelineName string `json:"pipeline_name,omitempty"`
	StartTime    int64  `json:"start_time,omitempty"`
	EndTime      int64  `json:"end_time,omitempty"`
	ReapTime     int64  `json:"reap_time,omitempty"`
}

func (Build) Abortable

func (b Build) Abortable() bool

func (Build) IsRunning

func (b Build) IsRunning() bool

func (Build) OneOff

func (b Build) OneOff() bool

type BuildInput

type BuildInput struct {
	Name     string   `json:"name"`
	Resource string   `json:"resource"`
	Type     string   `json:"type"`
	Source   Source   `json:"source"`
	Params   Params   `json:"params,omitempty"`
	Version  Version  `json:"version"`
	Tags     []string `json:"tags,omitempty"`
}

type BuildInputsOutputs

type BuildInputsOutputs struct {
	Inputs  []PublicBuildInput  `json:"inputs"`
	Outputs []VersionedResource `json:"outputs"`
}

type BuildPreparation

type BuildPreparation struct {
	BuildID             int                               `json:"build_id"`
	PausedPipeline      BuildPreparationStatus            `json:"paused_pipeline"`
	PausedJob           BuildPreparationStatus            `json:"paused_job"`
	MaxRunningBuilds    BuildPreparationStatus            `json:"max_running_builds"`
	Inputs              map[string]BuildPreparationStatus `json:"inputs"`
	InputsSatisfied     BuildPreparationStatus            `json:"inputs_satisfied"`
	MissingInputReasons MissingInputReasons               `json:"missing_input_reasons"`
}

type BuildPreparationStatus

type BuildPreparationStatus string
const (
	BuildPreparationStatusUnknown     BuildPreparationStatus = "unknown"
	BuildPreparationStatusBlocking    BuildPreparationStatus = "blocking"
	BuildPreparationStatusNotBlocking BuildPreparationStatus = "not_blocking"
)

type BuildStatus

type BuildStatus string
const (
	StatusStarted   BuildStatus = "started"
	StatusPending   BuildStatus = "pending"
	StatusSucceeded BuildStatus = "succeeded"
	StatusFailed    BuildStatus = "failed"
	StatusErrored   BuildStatus = "errored"
	StatusAborted   BuildStatus = "aborted"
)

type CheckRequestBody

type CheckRequestBody struct {
	From Version `json:"from"`
}

type CheckResponseBody

type CheckResponseBody struct {
	ExitStatus int    `json:"exit_status"`
	Stderr     string `json:"stderr"`
}

type Config

type Config struct {
	Groups        GroupConfigs    `yaml:"groups" json:"groups" mapstructure:"groups"`
	Resources     ResourceConfigs `yaml:"resources" json:"resources" mapstructure:"resources"`
	ResourceTypes ResourceTypes   `yaml:"resource_types" json:"resource_types" mapstructure:"resource_types"`
	Jobs          JobConfigs      `yaml:"jobs" json:"jobs" mapstructure:"jobs"`
}

func (Config) JobIsPublic

func (config Config) JobIsPublic(jobName string) (bool, error)

type ConfigResponse

type ConfigResponse struct {
	Config    *Config   `json:"config"`
	Errors    []string  `json:"errors"`
	RawConfig RawConfig `json:"raw_config"`
}

type Container

type Container struct {
	ID                   string   `json:"id"`
	TTLInSeconds         int64    `json:"ttl_in_seconds"`
	ValidityInSeconds    int64    `json:"validity_in_seconds"`
	WorkerName           string   `json:"worker_name"`
	PipelineName         string   `json:"pipeline_name"`
	JobName              string   `json:"job_name,omitempty"`
	BuildName            string   `json:"build_name,omitempty"`
	BuildID              int      `json:"build_id,omitempty"`
	StepType             string   `json:"step_type,omitempty"`
	StepName             string   `json:"step_name,omitempty"`
	ResourceName         string   `json:"resource_name,omitempty"`
	WorkingDirectory     string   `json:"working_directory,omitempty"`
	EnvironmentVariables []string `json:"env_variables,omitempty"`
	Attempts             []int    `json:"attempt,omitempty"`
	User                 string   `json:"user,omitempty"`
}

type DependentGetPlan

type DependentGetPlan struct {
	Type          string        `json:"type"`
	Name          string        `json:"name,omitempty"`
	Resource      string        `json:"resource"`
	ResourceTypes ResourceTypes `json:"resource_types,omitempty"`
	Pipeline      string        `json:"pipeline"`
	PipelineID    int           `json:"pipeline_id"`
	Params        Params        `json:"params,omitempty"`
	Tags          Tags          `json:"tags,omitempty"`
	Source        Source        `json:"source"`
}

func (DependentGetPlan) GetPlan

func (plan DependentGetPlan) GetPlan() GetPlan

func (DependentGetPlan) Public

func (plan DependentGetPlan) Public() *json.RawMessage

type DoPlan

type DoPlan []Plan

func (DoPlan) Public

func (plan DoPlan) Public() *json.RawMessage

type EnsurePlan

type EnsurePlan struct {
	Step Plan `json:"step"`
	Next Plan `json:"ensure"`
}

func (EnsurePlan) Public

func (plan EnsurePlan) Public() *json.RawMessage

type Event

type Event interface {
	EventType() EventType
	Version() EventVersion
}

type EventType

type EventType string

type EventVersion

type EventVersion string

semantic version for an individual event.

minor bumps are expected to be backwards-compatible, meaning clients can interpret them via the older handlers, and they can unmarshal into the new version trivially.

ATC will always emit the highest possible minor version for an event. this is so that we don't have to maintain copies of the event every time there's a minor bump.

an example of a minor bump would be an additive change, i.e. a new field.

major bumps are backwards-incompatible.

an example of a major bump would be the changing or removal of a field.

type GetPlan

type GetPlan struct {
	Type          string        `json:"type"`
	Name          string        `json:"name,omitempty"`
	Resource      string        `json:"resource"`
	ResourceTypes ResourceTypes `json:"resource_types,omitempty"`
	Pipeline      string        `json:"pipeline"`
	PipelineID    int           `json:"pipeline_id"`
	Source        Source        `json:"source"`
	Params        Params        `json:"params,omitempty"`
	Version       Version       `json:"version,omitempty"`
	Tags          Tags          `json:"tags,omitempty"`
}

func (GetPlan) Public

func (plan GetPlan) Public() *json.RawMessage

type GitHubAuth

type GitHubAuth struct {
	ClientID      string       `json:"client_id,omitempty"`
	ClientSecret  string       `json:"client_secret,omitempty"`
	Organizations []string     `json:"organizations,omitempty"`
	Teams         []GitHubTeam `json:"teams,omitempty"`
	Users         []string     `json:"users,omitempty"`
	AuthURL       string       `json:"auth_url,omitempty"`
	TokenURL      string       `json:"token_url,omitempty"`
	APIURL        string       `json:"api_url,omitempty"`
}

type GitHubTeam

type GitHubTeam struct {
	OrganizationName string `json:"organization_name,omitempty"`
	TeamName         string `json:"team_name,omitempty"`
}

type GroupConfig

type GroupConfig struct {
	Name      string   `yaml:"name" json:"name" mapstructure:"name"`
	Jobs      []string `yaml:"jobs,omitempty" json:"jobs,omitempty" mapstructure:"jobs"`
	Resources []string `yaml:"resources,omitempty" json:"resources,omitempty" mapstructure:"resources"`
}

type GroupConfigs

type GroupConfigs []GroupConfig

func (GroupConfigs) Lookup

func (groups GroupConfigs) Lookup(name string) (GroupConfig, bool)

type HijackInput

type HijackInput struct {
	Closed  bool           `json:"closed,omitempty"`
	Stdin   []byte         `json:"stdin,omitempty"`
	TTYSpec *HijackTTYSpec `json:"tty,omitempty"`
}

type HijackOutput

type HijackOutput struct {
	Stdout     []byte `json:"stdout,omitempty"`
	Stderr     []byte `json:"stderr,omitempty"`
	Error      string `json:"error,omitempty"`
	ExitStatus *int   `json:"exit_status,omitempty"`
}

type HijackProcessSpec

type HijackProcessSpec struct {
	Path string   `json:"path"`
	Args []string `json:"args"`
	Env  []string `json:"env"`
	Dir  string   `json:"dir"`

	Privileged bool   `json:"privileged"`
	User       string `json:"user"`

	TTY *HijackTTYSpec `json:"tty"`
}

type HijackTTYSpec

type HijackTTYSpec struct {
	WindowSize HijackWindowSize `json:"window_size"`
}

type HijackWindowSize

type HijackWindowSize struct {
	Columns int `json:"columns"`
	Rows    int `json:"rows"`
}

type ImageResource

type ImageResource struct {
	Type   string `yaml:"type" json:"type" mapstructure:"type"`
	Source Source `yaml:"source" json:"source" mapstructure:"source"`
}

type Info

type Info struct {
	Version string `json:"version"`
}

type Job

type Job struct {
	Name                 string `json:"name"`
	URL                  string `json:"url"`
	Paused               bool   `json:"paused,omitempty"`
	FirstLoggedBuildID   int    `json:"first_logged_build_id,omitempty"`
	DisableManualTrigger bool   `json:"disable_manual_trigger,omitempty"`
	NextBuild            *Build `json:"next_build"`
	FinishedBuild        *Build `json:"finished_build"`

	Inputs  []JobInput  `json:"inputs"`
	Outputs []JobOutput `json:"outputs"`

	Groups []string `json:"groups"`
}

type JobConfig

type JobConfig struct {
	Name   string `yaml:"name" json:"name" mapstructure:"name"`
	Public bool   `yaml:"public,omitempty" json:"public,omitempty" mapstructure:"public"`

	DisableManualTrigger bool     `yaml:"disable_manual_trigger,omitempty" json:"disable_manual_trigger,omitempty" mapstructure:"disable_manual_trigger"`
	Serial               bool     `yaml:"serial,omitempty" json:"serial,omitempty" mapstructure:"serial"`
	SerialGroups         []string `yaml:"serial_groups,omitempty" json:"serial_groups,omitempty" mapstructure:"serial_groups"`
	RawMaxInFlight       int      `yaml:"max_in_flight,omitempty" json:"max_in_flight,omitempty" mapstructure:"max_in_flight"`
	BuildLogsToRetain    int      `yaml:"build_logs_to_retain,omitempty" json:"build_logs_to_retain,omitempty" mapstructure:"build_logs_to_retain"`

	Plan PlanSequence `yaml:"plan,omitempty" json:"plan,omitempty" mapstructure:"plan"`
}

func (JobConfig) GetSerialGroups

func (config JobConfig) GetSerialGroups() []string

func (JobConfig) MaxInFlight

func (config JobConfig) MaxInFlight() int

type JobConfigs

type JobConfigs []JobConfig

func (JobConfigs) Lookup

func (jobs JobConfigs) Lookup(name string) (JobConfig, bool)

type JobInput

type JobInput struct {
	Name     string   `json:"name"`
	Resource string   `json:"resource"`
	Passed   []string `json:"passed,omitempty"`
	Trigger  bool     `json:"trigger"`
}

type JobOutput

type JobOutput struct {
	Name     string `json:"name"`
	Resource string `json:"resource"`
}

type LogLevel

type LogLevel string
const (
	LogLevelInvalid LogLevel = ""
	LogLevelDebug   LogLevel = "debug"
	LogLevelInfo    LogLevel = "info"
	LogLevelError   LogLevel = "error"
	LogLevelFatal   LogLevel = "fatal"
)

type MalformedConfigError

type MalformedConfigError struct {
	UnmarshalError error
}

func (MalformedConfigError) Error

func (malformedConfigError MalformedConfigError) Error() string

type MetadataField

type MetadataField struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

type MissingInputReasons

type MissingInputReasons map[string]string

type OnFailurePlan

type OnFailurePlan struct {
	Step Plan `json:"step"`
	Next Plan `json:"on_failure"`
}

func (OnFailurePlan) Public

func (plan OnFailurePlan) Public() *json.RawMessage

type OnSuccessPlan

type OnSuccessPlan struct {
	Step Plan `json:"step"`
	Next Plan `json:"on_success"`
}

func (OnSuccessPlan) Public

func (plan OnSuccessPlan) Public() *json.RawMessage

type Params

type Params map[string]interface{}

type Pipe

type Pipe struct {
	ID string `json:"id"`

	ReadURL  string `json:"read_url"`
	WriteURL string `json:"write_url"`
}

type Pipeline

type Pipeline struct {
	Name     string       `json:"name"`
	URL      string       `json:"url"`
	Paused   bool         `json:"paused"`
	Public   bool         `json:"public"`
	Groups   GroupConfigs `json:"groups,omitempty"`
	TeamName string       `json:"team_name"`
}

type Plan

type Plan struct {
	ID       PlanID `json:"id"`
	Attempts []int  `json:"attempts,omitempty"`

	Aggregate    *AggregatePlan    `json:"aggregate,omitempty"`
	Do           *DoPlan           `json:"do,omitempty"`
	Get          *GetPlan          `json:"get,omitempty"`
	Put          *PutPlan          `json:"put,omitempty"`
	Task         *TaskPlan         `json:"task,omitempty"`
	Ensure       *EnsurePlan       `json:"ensure,omitempty"`
	OnSuccess    *OnSuccessPlan    `json:"on_success,omitempty"`
	OnFailure    *OnFailurePlan    `json:"on_failure,omitempty"`
	Try          *TryPlan          `json:"try,omitempty"`
	DependentGet *DependentGetPlan `json:"dependent_get,omitempty"`
	Timeout      *TimeoutPlan      `json:"timeout,omitempty"`
	Retry        *RetryPlan        `json:"retry,omitempty"`
}

func (Plan) Public

func (plan Plan) Public() *json.RawMessage

type PlanConfig

type PlanConfig struct {

	// compose a nested sequence of plans
	// name of the nested 'do'
	RawName string `yaml:"name,omitempty" json:"name,omitempty" mapstructure:"name"`

	// a nested chain of steps to run
	Do *PlanSequence `yaml:"do,omitempty" json:"do,omitempty" mapstructure:"do"`

	// corresponds to an Aggregate plan, keyed by the name of each sub-plan
	Aggregate *PlanSequence `yaml:"aggregate,omitempty" json:"aggregate,omitempty" mapstructure:"aggregate"`

	// corresponds to Get and Put resource plans, respectively
	// name of 'input', e.g. bosh-stemcell
	Get string `yaml:"get,omitempty" json:"get,omitempty" mapstructure:"get"`
	// jobs that this resource must have made it through
	Passed []string `yaml:"passed,omitempty" json:"passed,omitempty" mapstructure:"passed"`
	// whether to trigger based on this resource changing
	Trigger bool `yaml:"trigger,omitempty" json:"trigger,omitempty" mapstructure:"trigger"`

	// name of 'output', e.g. rootfs-tarball
	Put string `yaml:"put,omitempty" json:"put,omitempty" mapstructure:"put"`

	// corresponding resource config, e.g. aws-stemcell
	Resource string `yaml:"resource,omitempty" json:"resource,omitempty" mapstructure:"resource"`

	// corresponds to a Task plan
	// name of 'task', e.g. unit, go1.3, go1.4
	Task string `yaml:"task,omitempty" json:"task,omitempty" mapstructure:"task"`
	// run task privileged
	Privileged bool `yaml:"privileged,omitempty" json:"privileged,omitempty" mapstructure:"privileged"`
	// task config path, e.g. foo/build.yml
	TaskConfigPath string `yaml:"file,omitempty" json:"file,omitempty" mapstructure:"file"`
	// inlined task config
	TaskConfig *TaskConfig `yaml:"config,omitempty" json:"config,omitempty" mapstructure:"config"`

	// used by Get and Put for specifying params to the resource
	Params Params `yaml:"params,omitempty" json:"params,omitempty" mapstructure:"params"`

	// used to pass specific inputs/outputs as generic inputs/outputs in task config
	InputMapping  map[string]string `yaml:"input_mapping,omitempty" json:"input_mapping,omitempty" mapstructure:"input_mapping"`
	OutputMapping map[string]string `yaml:"output_mapping,omitempty" json:"output_mapping,omitempty" mapstructure:"output_mapping"`

	// used to specify an image artifact from a previous build to be used as the image for a subsequent task container
	ImageArtifactName string `yaml:"image,omitempty" json:"image,omitempty" mapstructure:"image"`

	// used by Put to specify params for the subsequent Get
	GetParams Params `yaml:"get_params,omitempty" json:"get_params,omitempty" mapstructure:"get_params"`

	// used by any step to specify which workers are eligible to run the step
	Tags Tags `yaml:"tags,omitempty" json:"tags,omitempty" mapstructure:"tags"`

	// used by any step to run something when the step reports a failure
	Failure *PlanConfig `yaml:"on_failure,omitempty" json:"on_failure,omitempty" mapstructure:"on_failure"`

	// used on any step to always execute regardless of the step's completed state
	Ensure *PlanConfig `yaml:"ensure,omitempty" json:"ensure,omitempty" mapstructure:"ensure"`

	// used on any step to execute on successful completion of the step
	Success *PlanConfig `yaml:"on_success,omitempty" json:"on_success,omitempty" mapstructure:"on_success"`

	// used on any step to swallow failures and errors
	Try *PlanConfig `yaml:"try,omitempty" json:"try,omitempty" mapstructure:"try"`

	// used on any step to interrupt the step after a given duration
	Timeout string `yaml:"timeout,omitempty" json:"timeout,omitempty" mapstructure:"timeout"`

	// not present in yaml
	DependentGet string `yaml:"-" json:"-"`

	// repeat the step up to N times, until it works
	Attempts int `yaml:"attempts,omitempty" json:"attempts,omitempty" mapstructure:"attempts"`

	Version *VersionConfig `yaml:"version,omitempty" json:"version,omitempty" mapstructure:"version"`
}

A PlanConfig is a flattened set of configuration corresponding to a particular Plan, where Source and Version are populated lazily.

func (PlanConfig) Name

func (config PlanConfig) Name() string

func (PlanConfig) ResourceName

func (config PlanConfig) ResourceName() string

type PlanFactory

type PlanFactory struct {
	// contains filtered or unexported fields
}

func NewPlanFactory

func NewPlanFactory(startingNum int64) PlanFactory

func (PlanFactory) NewPlan

func (factory PlanFactory) NewPlan(step Step) Plan

type PlanID

type PlanID string

type PlanSequence

type PlanSequence []PlanConfig

A PlanSequence corresponds to a chain of Compose plan, with an implicit `on: [success]` after every Task plan.

type PlanTraversal

type PlanTraversal interface {
	Traverse(plan *Plan) error
}

func NewPlanTraversal

func NewPlanTraversal(f PlanTraverseFunc) PlanTraversal

type PlanTraverseFunc

type PlanTraverseFunc func(plan *Plan) error

type PublicBuildInput

type PublicBuildInput struct {
	Name            string          `json:"name"`
	Resource        string          `json:"resource"`
	Type            string          `json:"type"`
	Version         Version         `json:"version"`
	Metadata        []MetadataField `json:"metadata"`
	PipelineID      int             `json:"pipeline_id"`
	FirstOccurrence bool            `json:"first_occurrence"`
}

type PublicBuildPlan

type PublicBuildPlan struct {
	Schema string           `json:"schema"`
	Plan   *json.RawMessage `json:"plan"`
}

type PutPlan

type PutPlan struct {
	Type          string        `json:"type"`
	Name          string        `json:"name,omitempty"`
	Resource      string        `json:"resource"`
	ResourceTypes ResourceTypes `json:"resource_types,omitempty"`
	Pipeline      string        `json:"pipeline"`
	PipelineID    int           `json:"pipeline_id"`
	Source        Source        `json:"source"`
	Params        Params        `json:"params,omitempty"`
	Tags          Tags          `json:"tags,omitempty"`
}

func (PutPlan) Public

func (plan PutPlan) Public() *json.RawMessage

type RawConfig

type RawConfig string

func (RawConfig) String

func (r RawConfig) String() string

type Resource

type Resource struct {
	Name   string   `json:"name"`
	Type   string   `json:"type"`
	Groups []string `json:"groups"`
	URL    string   `json:"url"`

	Paused bool `json:"paused,omitempty"`

	FailingToCheck bool   `json:"failing_to_check,omitempty"`
	CheckError     string `json:"check_error,omitempty"`
}

type ResourceConfig

type ResourceConfig struct {
	Name string `yaml:"name" json:"name" mapstructure:"name"`

	Type       string `yaml:"type" json:"type" mapstructure:"type"`
	Source     Source `yaml:"source" json:"source" mapstructure:"source"`
	CheckEvery string `yaml:"check_every,omitempty" json:"check_every" mapstructure:"check_every"`
}

type ResourceConfigs

type ResourceConfigs []ResourceConfig

func (ResourceConfigs) Lookup

func (resources ResourceConfigs) Lookup(name string) (ResourceConfig, bool)

type ResourceType

type ResourceType struct {
	Name   string `yaml:"name" json:"name" mapstructure:"name"`
	Type   string `yaml:"type" json:"type" mapstructure:"type"`
	Source Source `yaml:"source" json:"source" mapstructure:"source"`
}

type ResourceTypes

type ResourceTypes []ResourceType

func (ResourceTypes) Lookup

func (types ResourceTypes) Lookup(name string) (ResourceType, bool)

func (ResourceTypes) Without

func (types ResourceTypes) Without(name string) ResourceTypes

type RetryPlan

type RetryPlan []Plan

func (RetryPlan) Public

func (plan RetryPlan) Public() *json.RawMessage

type Source

type Source map[string]interface{}

type Step

type Step interface {
	Public() *json.RawMessage
}

type Tags

type Tags []string

type TaskConfig

type TaskConfig struct {
	// The platform the task must run on (e.g. linux, windows).
	Platform string `json:"platform,omitempty" yaml:"platform,omitempty" mapstructure:"platform"`

	// Optional string specifying an image to use for the build. Depending on the
	// platform, this may or may not be required (e.g. Windows/OS X vs. Linux).
	Image string `json:"image,omitempty" yaml:"image,omitempty" mapstructure:"image"`

	ImageResource *ImageResource `json:"image_resource,omitempty" yaml:"image_resource,omitempty" mapstructure:"image_resource"`

	// Parameters to pass to the task via environment variables.
	Params map[string]string `json:"params,omitempty" yaml:"params,omitempty" mapstructure:"params"`

	// Script to execute.
	Run TaskRunConfig `json:"run,omitempty" yaml:"run,omitempty" mapstructure:"run"`

	// The set of (logical, name-only) inputs required by the task.
	Inputs []TaskInputConfig `json:"inputs,omitempty" yaml:"inputs,omitempty" mapstructure:"inputs"`

	// The set of (logical, name-only) outputs provided by the task.
	Outputs []TaskOutputConfig `json:"outputs,omitempty" yaml:"outputs,omitempty" mapstructure:"outputs"`
}

func LoadTaskConfig

func LoadTaskConfig(configBytes []byte) (TaskConfig, error)

func (TaskConfig) Merge

func (config TaskConfig) Merge(other TaskConfig) TaskConfig

func (TaskConfig) Validate

func (config TaskConfig) Validate() error

type TaskInputConfig

type TaskInputConfig struct {
	Name string `json:"name" yaml:"name"`
	Path string `json:"path,omitempty" yaml:"path"`
}

type TaskOutputConfig

type TaskOutputConfig struct {
	Name string `json:"name" yaml:"name"`
	Path string `json:"path,omitempty" yaml:"path"`
}

type TaskPlan

type TaskPlan struct {
	Name string `json:"name,omitempty"`

	Privileged bool `json:"privileged"`
	Tags       Tags `json:"tags,omitempty"`

	ConfigPath string      `json:"config_path,omitempty"`
	Config     *TaskConfig `json:"config,omitempty"`

	Params            Params            `json:"params,omitempty"`
	InputMapping      map[string]string `json:"input_mapping,omitempty"`
	OutputMapping     map[string]string `json:"output_mapping,omitempty"`
	ImageArtifactName string            `json:"image,omitempty"`

	Pipeline      string        `json:"pipeline"`
	PipelineID    int           `json:"pipeline_id"`
	ResourceTypes ResourceTypes `json:"resource_types,omitempty"`
}

func (TaskPlan) Public

func (plan TaskPlan) Public() *json.RawMessage

type TaskRunConfig

type TaskRunConfig struct {
	Path string   `json:"path" yaml:"path"`
	Args []string `json:"args,omitempty" yaml:"args"`
	Dir  string   `json:"dir",omitempty" yaml:"dir"`

	// The user that the task will run as (defaults to whatever the docker image specifies)
	User string `json:"user,omitempty" yaml:"user,omitempty" mapstructure:"user"`
}

type Team

type Team struct {
	// ID is the team's ID
	ID int `json:"id,omitempty"`

	// Name is the team's name
	Name string `json:"name,omitempty"`

	BasicAuth  *BasicAuth  `json:"basic_auth,omitempty"`
	GitHubAuth *GitHubAuth `json:"github_auth,omitempty"`
	UAAAuth    *UAAAuth    `json:"uaa_auth,omitempty"`
}

Team owns your pipelines

type TimeoutPlan

type TimeoutPlan struct {
	Step     Plan   `json:"step"`
	Duration string `json:"duration"`
}

func (TimeoutPlan) Public

func (plan TimeoutPlan) Public() *json.RawMessage

type TryPlan

type TryPlan struct {
	Step Plan `json:"step"`
}

func (TryPlan) Public

func (plan TryPlan) Public() *json.RawMessage

type UAAAuth

type UAAAuth struct {
	ClientID     string   `json:"client_id,omitempty"`
	ClientSecret string   `json:"client_secret,omitempty"`
	AuthURL      string   `json:"auth_url,omitempty"`
	TokenURL     string   `json:"token_url,omitempty"`
	CFSpaces     []string `json:"cf_spaces,omitempty"`
	CFURL        string   `json:"cf_url,omitempty"`
	CFCACert     string   `json:"cf_ca_cert,omitempty"`
}

type Version

type Version map[string]string

type VersionConfig

type VersionConfig struct {
	Every  bool    `yaml:"every,omitempty" json:"every,omitempty"`
	Latest bool    `yaml:"latest,omitempty" json:"latest,omitempty"`
	Pinned Version `yaml:"pinned,omitempty" json:"pinned,omitempty"`
}

A VersionConfig represents the choice to include every version of a resource, the latest version of a resource, or a pinned (specific) one.

func (*VersionConfig) MarshalJSON

func (c *VersionConfig) MarshalJSON() ([]byte, error)

func (*VersionConfig) MarshalYAML

func (c *VersionConfig) MarshalYAML() (interface{}, error)

func (*VersionConfig) UnmarshalJSON

func (c *VersionConfig) UnmarshalJSON(version []byte) error

func (*VersionConfig) UnmarshalYAML

func (c *VersionConfig) UnmarshalYAML(unmarshal func(interface{}) error) error

type VersionedResource

type VersionedResource struct {
	ID         int             `json:"id"`
	PipelineID int             `json:"pipeline_id"`
	Type       string          `json:"type"`
	Metadata   []MetadataField `json:"metadata"`
	Resource   string          `json:"resource"`
	Version    Version         `json:"version"`
	Enabled    bool            `json:"enabled"`
}

type Volume

type Volume struct {
	ID                string `json:"id"`
	TTLInSeconds      int64  `json:"ttl_in_seconds"`
	ValidityInSeconds int64  `json:"validity_in_seconds"`
	WorkerName        string `json:"worker_name"`
	Type              string `json:"type"`
	Identifier        string `json:"identifier"`
	SizeInBytes       int64  `json:"size_in_bytes"`
}

type Worker

type Worker struct {
	// not garden_addr, for backwards-compatibility
	GardenAddr      string `json:"addr"`
	BaggageclaimURL string `json:"baggageclaim_url"`

	HTTPProxyURL  string `json:"http_proxy_url,omitempty"`
	HTTPSProxyURL string `json:"https_proxy_url,omitempty"`
	NoProxy       string `json:"no_proxy,omitempty"`

	ActiveContainers int `json:"active_containers"`

	ResourceTypes []WorkerResourceType `json:"resource_types"`

	Platform  string   `json:"platform"`
	Tags      []string `json:"tags"`
	Team      string   `json:"team"`
	Name      string   `json:"name"`
	StartTime int64    `json:"start_time"`
}

type WorkerResourceType

type WorkerResourceType struct {
	Type    string `json:"type"`
	Image   string `json:"image"`
	Version string `json:"version"`
}

Directories

Path Synopsis
api
containerserver/containerserverfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
jobserver/jobserverfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
pipes/pipesfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
resourceserver/resourceserverfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
teamserver/teamserverfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
volumeserver/volumeserverfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
workerserver/workerserverfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
authfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
github/githubfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
provider/providerfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
uaa
buildreaperfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
buildsfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
cmd
atc
containerkeepaliverfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
db
dbfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
migrations/migrationsfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
enginefakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
execfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
leaserunnerfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
lostandfoundfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
metricfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
pipelinesfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
radarfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
resourcefakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
buildstarter/buildstarterfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
buildstarter/maxinflight/maxinflightfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
factory/factoryfakes
This file was generated by counterfeiter
This file was generated by counterfeiter
inputmapper/inputconfig/inputconfigfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
inputmapper/inputmapperfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
schedulerfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
web
webfakes
This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter
transport/transportfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
workerfakes
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter

Jump to

Keyboard shortcuts

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