runner

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Dec 15, 2025 License: MPL-2.0 Imports: 49 Imported by: 0

Documentation

Overview

Package runner contains the runner, the component responsible for carrying out runs by executing terraform processes, either as part of the server or remotely via agents.

Index

Constants

View Source
const DefaultMaxJobs = 5

Variables

View Source
var (
	ErrInvalidJobStateTransition = errors.New("invalid job state transition")
	ErrMalformedJobSpecString    = errors.New("malformed stringified job spec")
)
View Source
var (
	ErrCannotDeletePoolReferencedByWorkspaces = errors.New("agent pool is still being used by workspaces in your organization. You must switch your workspaces to a different agent pool or execution mode before you can delete this agent pool")
	ErrWorkspaceNotAllowedToUsePool           = errors.New("access to this agent pool is not allowed - you must explictly grant access to the workspace first")
	ErrPoolAssignedWorkspacesNotAllowed       = errors.New("workspaces assigned to the pool have not been granted access to the pool")
)
View Source
var ErrInvalidStateTransition = errors.New("invalid runner state transition")
View Source
var PluginCacheDir = filepath.Join(os.TempDir(), "plugin-cache")

Functions

func NewAgentsCommand

func NewAgentsCommand(apiClient *otfapi.Client) *cobra.Command

Types

type AgentOptions

type AgentOptions struct {
	*Config

	URL   string
	Token string
}

func NewAgentOptionsFromFlags

func NewAgentOptionsFromFlags(flags *pflag.FlagSet) *AgentOptions

type AgentToken added in v0.4.8

type AgentToken struct {
	ID          resource.TfeID `jsonapi:"primary,agent_tokens" db:"agent_token_id"`
	CreatedAt   time.Time
	AgentPoolID resource.TfeID `jsonapi:"attribute" json:"agent_pool_id" db:"agent_pool_id"`
	Description string         `jsonapi:"attribute" json:"description"`
}

AgentToken represents the authentication token for an agent. NOTE: the cryptographic token itself is not retained.

func (*AgentToken) LogValue added in v0.4.8

func (a *AgentToken) LogValue() slog.Value

type Config

type Config struct {
	Name         string // descriptive name given to runner
	MaxJobs      int    // number of jobs the runner can execute at any one time
	Debug        bool   // toggle debug mode
	PluginCache  bool   // toggle use of terraform's shared plugin cache
	EngineBinDir string // destination directory for engine binaries
}

func NewConfig added in v0.3.20

func NewConfig() *Config

func NewConfigFromFlags

func NewConfigFromFlags(flags *pflag.FlagSet) *Config

type CreateAgentPoolOptions

type CreateAgentPoolOptions struct {
	Name string `schema:"name,required"`
	// name of org
	Organization organization.Name `schema:"organization_name,required"`
	// defaults to true
	OrganizationScoped *bool
	// IDs of workspaces allowed to access the pool.
	AllowedWorkspaces []resource.TfeID
}

type CreateAgentTokenOptions

type CreateAgentTokenOptions struct {
	Description string `json:"description" schema:"description,required"`
}

type Job

type Job struct {
	ID resource.TfeID `jsonapi:"primary,jobs" db:"job_id"`
	// ID of the run that this job is for.
	RunID resource.TfeID `jsonapi:"attribute" json:"run_id" db:"run_id"`
	// Phase of run that this job is for.
	Phase otfrun.PhaseType `jsonapi:"attribute" json:"phase"`
	// Current status of job.
	Status JobStatus `jsonapi:"attribute" json:"status"`
	// ID of agent pool the job's workspace is assigned to use. If non-nil then
	// the job is allocated to an agent runner belonging to the pool. If nil then
	// the job is allocated to a server runner.
	AgentPoolID *resource.TfeID `jsonapi:"attribute" json:"agent_pool_id" db:"agent_pool_id"`
	// Name of job's organization
	Organization organization.Name `jsonapi:"attribute" json:"organization" db:"organization_name"`
	// ID of job's workspace
	WorkspaceID resource.TfeID `jsonapi:"attribute" json:"workspace_id" db:"workspace_id"`
	// ID of runner that this job is allocated to. Only set once job enters
	// JobAllocated state.
	RunnerID *resource.TfeID `jsonapi:"attribute" json:"runner_id" db:"runner_id"`
}

Job is the unit of work corresponding to a run phase. A job is allocated to a runner, which then executes the work through to completion.

func (*Job) CanAccess

func (j *Job) CanAccess(action authz.Action, req authz.Request) bool

func (*Job) LogValue

func (j *Job) LogValue() slog.Value

func (*Job) String

func (j *Job) String() string

type JobEvent added in v0.3.23

type JobEvent struct {
	ID resource.TfeID `json:"job_id"`
	// ID of the run that this job is for.
	RunID resource.TfeID `jsonapi:"attribute" json:"run_id" db:"run_id"`
	// Current status of job.
	Status JobStatus `json:"status"`
	// ID of runner that this job is allocated to. Only set once job enters
	// JobAllocated state.
	RunnerID *resource.TfeID `json:"runner_id"`
	// Signaled is non-nil when a cancelation signal has been sent to the job
	// and it is true when it has been forceably canceled.
	Signaled *bool `json:"signaled"`
}

type JobStatus

type JobStatus string
const (
	JobUnallocated JobStatus = "unallocated"
	JobAllocated   JobStatus = "allocated"
	JobRunning     JobStatus = "running"
	JobFinished    JobStatus = "finished"
	JobErrored     JobStatus = "errored"
	JobCanceled    JobStatus = "canceled"
)

type ListOptions added in v0.3.17

type ListOptions struct {
	resource.PageOptions
	// Organization filters runners by the organization of their agent pool.
	//
	// NOTE: setting this does not exclude server runners (which do not belong
	// to an organization). To exclude servers runners as well set Server below to
	// false.
	Organization *organization.Name `schema:"organization_name"`
	// PoolID filters runners by agent pool ID
	PoolID *resource.TfeID `schema:"pool_id"`
	// HideServerRunners if true filters out server runners
	HideServerRunners bool `schema:"hide_server_runners"`
}

type ListPoolOptions added in v0.4.8

type ListPoolOptions struct {
	// Filter pools by those with this substring in their name. Optional.
	NameSubstring *string
	// Filter pools to those accessible to the named workspace. Optional.
	AllowedWorkspaceName *string
	// Filter pools to those accessible to the workspace with the given ID. Optional.
	AllowedWorkspaceID *resource.TfeID
}

type Pool

type Pool struct {
	ID        resource.TfeID `json:"agent_pool_id" db:"agent_pool_id"`
	Name      string
	CreatedAt time.Time `json:"created_at" db:"created_at"`
	// Pool belongs to an organization with this name.
	Organization organization.Name `json:"organization_name" db:"organization_name"`
	// Whether pool of agents is accessible to all workspaces in organization
	// (true) or only those specified in AllowedWorkspaces (false).
	OrganizationScoped bool `json:"organization_scoped" db:"organization_scoped"`
	// IDs of workspaces allowed to access pool. Ignored if OrganizationScoped
	// is true.
	AllowedWorkspaces []resource.TfeID `json:"allowed_workspace_ids" db:"allowed_workspace_ids"`
	// IDs of workspaces assigned to the pool. Note: this is a subset of
	// AllowedWorkspaces.
	AssignedWorkspaces []resource.TfeID `json:"workspace_ids" db:"workspace_ids"`
}

Pool is a group of remote runners sharing one or more tokens, assigned to an organization or particular workspaces within the organization.

func (*Pool) LogValue

func (p *Pool) LogValue() slog.Value

type RegisterRunnerOptions added in v0.4.8

type RegisterRunnerOptions struct {
	// Descriptive name. Optional.
	Name string `json:"name"`
	// Version of agent.
	Version string `json:"version"`
	// Number of jobs the agent can handle at any one time.
	Concurrency int `json:"concurrency"`
	// IPAddress of agent. Optional. Not sent over the wire; instead the server
	// handler is responsible for determining client's IP address.
	IPAddress *netip.Addr `json:"-"`
	// ID of agent's pool. Only set if runner is an agent.
	AgentPoolID *string `json:"-"`
	// CurrentJobs are those jobs the agent has discovered leftover from a
	// previous agent. Not currently used but may be made use of in later
	// versions.
	CurrentJobs []resource.TfeID `json:"current-jobs,omitempty"`
}

type Runner

type Runner struct {
	*RunnerMeta

	Debug           bool   // toggle debug mode
	PluginCache     bool   // toggle use of terraform's shared plugin cache
	TerraformBinDir string // destination directory for terraform binaries
	// contains filtered or unexported fields
}

func NewAgent

func NewAgent(logger logr.Logger, opts AgentOptions) (*Runner, error)

func NewServerRunner

func NewServerRunner(opts ServerRunnerOptions) (*Runner, error)

NewServerRunner constructs a server runner.

func (*Runner) Start

func (r *Runner) Start(ctx context.Context) error

Start the runner daemon.

func (*Runner) Started added in v0.3.23

func (r *Runner) Started() <-chan struct{}

type RunnerEvent added in v0.3.23

type RunnerEvent struct {
	ID     resource.TfeID `json:"runner_id"`
	Status RunnerStatus   `json:"status"`
}

type RunnerMeta

type RunnerMeta struct {
	ID resource.TfeID `jsonapi:"primary,runners" db:"runner_id"`
	// Optional name
	Name string `jsonapi:"attribute" json:"name"`
	// Version of runner
	Version string `jsonapi:"attribute" json:"version"`
	// Current status of runner
	Status RunnerStatus `jsonapi:"attribute" json:"status"`
	// Max number of jobs runner can execute
	MaxJobs int `jsonapi:"attribute" json:"max_jobs" db:"max_jobs"`
	// Current number of jobs allocated to runner.
	CurrentJobs int `jsonapi:"attribute" json:"current_jobs" db:"current_jobs"`
	// Last time a ping was received from the runner.
	LastPingAt time.Time `jsonapi:"attribute" json:"last-ping-at" db:"last_ping_at"`
	// Last time the status was updated
	LastStatusAt time.Time `jsonapi:"attribute" json:"last-status-at" db:"last_status_at"`
	// IP address of runner.
	IPAddress netip.Addr `jsonapi:"attribute" json:"ip-address" db:"ip_address"`
	// Info about the runner's agent pool. Non-nil if agent runner; nil if server
	// runner.
	AgentPool *Pool `jsonapi:"attribute" json:"agent-pool" db:"agent_pool"`
}

RunnerMeta is information about a runner.

func (*RunnerMeta) CanAccess

func (m *RunnerMeta) CanAccess(action authz.Action, req authz.Request) bool

func (*RunnerMeta) IsAgent

func (m *RunnerMeta) IsAgent() bool

func (*RunnerMeta) LogValue

func (m *RunnerMeta) LogValue() slog.Value

func (*RunnerMeta) String

func (m *RunnerMeta) String() string

type RunnerStatus

type RunnerStatus string
const (
	RunnerIdle    RunnerStatus = "idle"
	RunnerBusy    RunnerStatus = "busy"
	RunnerExited  RunnerStatus = "exited"
	RunnerErrored RunnerStatus = "errored"
	RunnerUnknown RunnerStatus = "unknown"
)

type ServerRunnerOptions

type ServerRunnerOptions struct {
	*Config

	Logger     logr.Logger
	Runners    *Service
	Runs       runClient
	Workspaces workspaceClient
	Variables  variablesClient
	State      stateClient
	Configs    configClient
	Server     hostnameClient
	Jobs       operationJobsClient
}

ServerRunnerOptions are options for constructing a server runner.

type Service

type Service struct {
	logr.Logger
	*authz.Authorizer

	Signaler *jobSignaler
	// contains filtered or unexported fields
}

func NewService

func NewService(opts ServiceOptions) *Service

func (*Service) AddHandlers

func (s *Service) AddHandlers(r *mux.Router)

func (*Service) CreateAgentPool

func (s *Service) CreateAgentPool(ctx context.Context, opts CreateAgentPoolOptions) (*Pool, error)

func (*Service) CreateAgentToken

func (s *Service) CreateAgentToken(ctx context.Context, poolID resource.TfeID, opts CreateAgentTokenOptions) (*AgentToken, []byte, error)

func (*Service) DeleteAgentPool added in v0.4.8

func (s *Service) DeleteAgentPool(ctx context.Context, poolID resource.TfeID) (*Pool, error)

func (*Service) DeleteAgentToken

func (s *Service) DeleteAgentToken(ctx context.Context, tokenID resource.TfeID) (*AgentToken, error)

func (*Service) DeleteRunner added in v0.4.8

func (s *Service) DeleteRunner(ctx context.Context, runnerID resource.TfeID) error

func (*Service) GenerateDynamicCredentialsToken added in v0.4.0

func (s *Service) GenerateDynamicCredentialsToken(ctx context.Context, jobID resource.TfeID, audience string) ([]byte, error)

func (*Service) GetAgentPool

func (s *Service) GetAgentPool(ctx context.Context, poolID resource.TfeID) (*Pool, error)

func (*Service) GetAgentToken

func (s *Service) GetAgentToken(ctx context.Context, tokenID resource.TfeID) (*AgentToken, error)

func (*Service) List added in v0.3.17

func (s *Service) List(ctx context.Context, opts ListOptions) (*resource.Page[*RunnerMeta], error)

func (*Service) ListAgentPoolsByOrganization added in v0.4.8

func (s *Service) ListAgentPoolsByOrganization(ctx context.Context, organization organization.Name, opts ListPoolOptions) ([]*Pool, error)

func (*Service) ListAgentTokens

func (s *Service) ListAgentTokens(ctx context.Context, poolID resource.TfeID) ([]*AgentToken, error)

func (*Service) ListRunners added in v0.4.8

func (s *Service) ListRunners(ctx context.Context, opts ListOptions) ([]*RunnerMeta, error)

func (Service) NewAgentToken

func (f Service) NewAgentToken(poolID resource.TfeID, opts CreateAgentTokenOptions) (*AgentToken, []byte, error)

NewAgentToken constructs a token for an agent, returning both the representation of the token, and the cryptographic token itself.

func (*Service) NewAllocator

func (s *Service) NewAllocator(logger logr.Logger) *allocator

func (*Service) NewManager

func (s *Service) NewManager() *manager

func (*Service) Register added in v0.4.8

func (s *Service) Register(ctx context.Context, opts RegisterRunnerOptions) (*RunnerMeta, error)

func (*Service) UpdateAgentPool added in v0.4.8

func (s *Service) UpdateAgentPool(ctx context.Context, poolID resource.TfeID, opts UpdatePoolOptions) (*Pool, error)

func (*Service) Watch added in v0.3.17

func (s *Service) Watch(ctx context.Context) (<-chan pubsub.Event[*RunnerEvent], func())

func (*Service) WatchAgentPools

func (s *Service) WatchAgentPools(ctx context.Context) (<-chan pubsub.Event[*Pool], func())

func (*Service) WatchJobs

func (s *Service) WatchJobs(ctx context.Context) (<-chan pubsub.Event[*JobEvent], func())

func (*Service) WatchRunners

func (s *Service) WatchRunners(ctx context.Context) (<-chan pubsub.Event[*RunnerEvent], func())

type ServiceOptions

type ServiceOptions struct {
	logr.Logger
	*sql.DB
	*sql.Listener
	*tfeapi.Responder

	RunService                *otfrun.Service
	WorkspaceService          *workspace.Service
	TokensService             *tokens.Service
	Authorizer                *authz.Authorizer
	DynamicCredentialsService *dynamiccreds.Service
	HostnameService           *internal.HostnameService
}

type TFEAgentPool added in v0.3.17

type TFEAgentPool struct {
	ID                 resource.TfeID `jsonapi:"primary,agent-pools"`
	Name               string         `jsonapi:"attribute" json:"name"`
	AgentCount         int            `jsonapi:"attribute" json:"agent-count"`
	OrganizationScoped bool           `jsonapi:"attribute" json:"organization-scoped"`

	// Relations
	Organization      *organization.TFEOrganization `jsonapi:"relationship" json:"organization"`
	Workspaces        []*workspace.TFEWorkspace     `jsonapi:"relationship" json:"workspaces"`
	AllowedWorkspaces []*workspace.TFEWorkspace     `jsonapi:"relationship" json:"allowed-workspaces"`
}

TFEAgentPool represents a Terraform Cloud agent pool.

type TFEAgentPoolCreateOptions added in v0.3.17

type TFEAgentPoolCreateOptions struct {
	// Type is a public field utilized by JSON:API to
	// set the resource type via the field tag.
	// It is not a user-defined value and does not need to be set.
	// https://jsonapi.org/format/#crud-creating
	Type string `jsonapi:"primary,agent-pools"`

	// Required: A name to identify the agent pool.
	Name *string `jsonapi:"attribute" json:"name"`

	// True if the agent pool is organization scoped, false otherwise.
	OrganizationScoped *bool `jsonapi:"attribute" json:"organization-scoped,omitempty"`

	// List of workspaces that are associated with an agent pool.
	AllowedWorkspaces []*workspace.TFEWorkspace `jsonapi:"relationship" json:"allowed-workspaces,omitempty"`
}

TFEAgentPoolCreateOptions represents the options for creating an agent pool.

type TFEAgentPoolListOptions added in v0.3.17

type TFEAgentPoolListOptions struct {
	types.ListOptions

	// Optional: A search query string used to filter agent pool. Agent pools are searchable by name
	Query *string `schema:"q,omitempty"`

	// Optional: String (workspace name) used to filter the results.
	AllowedWorkspacesName *string `schema:"filter[allowed_workspaces][name],omitempty"`
}

TFEAgentPoolListOptions represents the options for listing agent pools.

type TFEAgentPoolUpdateOptions added in v0.3.17

type TFEAgentPoolUpdateOptions struct {
	// Type is a public field utilized by JSON:API to
	// set the resource type via the field tag.
	// It is not a user-defined value and does not need to be set.
	// https://jsonapi.org/format/#crud-creating
	Type string `jsonapi:"primary,agent-pools"`

	// A new name to identify the agent pool.
	Name *string `jsonapi:"attribute" json:"name,omitempty"`

	// True if the agent pool is organization scoped, false otherwise.
	OrganizationScoped *bool `jsonapi:"attribute" json:"organization-scoped,omitempty"`

	// A new list of workspaces that are associated with an agent pool.
	AllowedWorkspaces []*workspace.TFEWorkspace `jsonapi:"relationship" json:"allowed-workspaces,omitempty"`
}

TFEAgentPoolUpdateOptions represents the options for updating an agent pool.

type TFEAgentToken added in v0.3.17

type TFEAgentToken struct {
	ID          resource.TfeID `jsonapi:"primary,authentication-tokens"`
	CreatedAt   time.Time      `jsonapi:"attribute" json:"created-at"`
	Description string         `jsonapi:"attribute" json:"description"`
	LastUsedAt  time.Time      `jsonapi:"attribute" json:"last-used-at"`
	Token       string         `jsonapi:"attribute" json:"token"`
}

TFEAgentToken represents a TFE agent token.

type TFEAgentTokenCreateOptions added in v0.3.17

type TFEAgentTokenCreateOptions struct {
	// Type is a public field utilized by JSON:API to set the resource type via
	// the field tag.  It is not a user-defined value and does not need to be
	// set.  https://jsonapi.org/format/#crud-creating
	Type string `jsonapi:"primary,agent-tokens"`

	// Description is a meaningful description of the purpose of the agent
	// token.
	Description string `jsonapi:"attribute" json:"description"`
}

TFEAgentTokenCreateOptions represents the options for creating a new otf agent token.

type UpdatePoolOptions added in v0.4.8

type UpdatePoolOptions struct {
	Name               *string
	OrganizationScoped *bool `schema:"organization_scoped"`
	// IDs of workspaces allowed to access the pool.
	AllowedWorkspaces []resource.TfeID `schema:"allowed_workspaces"`
	// IDs of workspaces assigned to the pool. Note: this is a subset of
	// AssignedWorkspaces.
	AssignedWorkspaces []resource.TfeID `schema:"assigned_workspaces"`
}

Jump to

Keyboard shortcuts

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