sylt

package
v0.0.0-...-623dc82 Latest Latest
Warning

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

Go to latest
Published: Dec 23, 2024 License: Apache-2.0 Imports: 14 Imported by: 4

Documentation

Overview

Package sylt implements a workflow and actions engine for lingon.

Actions can be implemented for specific tooling by implementing the Actioner interface. For example, TerraAction exists for deploying terra stacks.

A Workflow type exists to combine and multiple actions into a workflow. Actions should be designed to be runnable independently of a workflow.

"Sylt" is a Swedish word for jam. This package is where we turn lingon into sylt.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrMissingActionName = errors.New("missing action name")
	ErrMissingActionType = errors.New("missing stack type")
)
View Source
var ErrDuplicateAction = errors.New("duplicate action name and type")

Functions

func RequireResourceState

func RequireResourceState[V any, T ResourceStater[V]](res T, err *error) V

RequireResourceState checks if the given terra.Resource has state. If the resource has state, it is returned. If the resource does not have state, an error is added to the given error. If the error is a MissingStateError, the resource is added to the list of resources that are missing state.

var err error
res1 := RequireResourceState(stack.Resource1, &err)
res2 := RequireResourceState(stack.Resource2, &err)
if err != nil {
	return err
}
Example
Output:

missing state for resources: [dummy.dummy]
false
true

Types

type ActionType

type ActionType string
const ActionTypeTerra ActionType = "terra"

type Actioner

type Actioner interface {
	// ActionName is used to identify an action.
	// It also helps with logging and debugging.
	// It is called ActionName so that a struct can use a field member "Name".
	ActionName() string
	// ActionType is the type of the action.
	// It is called ActionType to be consistent with ActionName.
	// All actions must define an action type.
	ActionType() ActionType
	// Run the action.
	Run(ctx context.Context, opts RunOpts) error
	// Cleanup the action.
	// It is used to cleanup after the action.
	// It is only called if destroy is true.
	Cleanup(ctx context.Context, opts RunOpts) error
}

Actioner defines the interface for actions. Actions should be designed to be runnable independently, or as part of a sylt workflow.

For example, see TerraAction for deploying terra stacks. Custom actions can be defined. The benefit to this is a consistent way to manage (i.e. create, update, destroy) resources. For those things that don't fit into terra or kube, just define an action.

type CleanupOption

type CleanupOption func(*cleanupOpts)

func WithCleanupDestroy

func WithCleanupDestroy(b bool) CleanupOption

WithCleanupDestroy sets the destroy option for Cleanup.

func WithCleanupDryRun

func WithCleanupDryRun(b bool) CleanupOption

WithCleanupDryRun sets the dry run option for Cleanup.

type MissingStateError

type MissingStateError struct {
	// Resources that are missing state.
	Resources []terra.Resource
}

MissingStateError is returned when the state is missing for resources.

func (*MissingStateError) Error

func (se *MissingStateError) Error() string

type ResourceStater

type ResourceStater[T any] interface {
	terra.Resource
	State() (T, bool)
}

type RunOpts

type RunOpts struct {
	DryRun  bool
	Destroy bool
}

type StateStatus

type StateStatus int

StateStatus defines how complete the state is for a stack.

const (
	// StateStatusUnknown the state mode has not been determined yet
	// (e.g. no plan/apply).
	StateStatusUnknown StateStatus = 0
	// StateStatusEmpty there is no state (e.g. no apply yet).
	StateStatusEmpty StateStatus = 1
	// StateStatusPartial there is a state, but there are resources in the stack
	// that are not in the state yet (e.g. need to be applied).
	StateStatusPartial StateStatus = 2
	// StateStatusSync all resources in the stack have state and the state does
	// not have resources that are not in the stack.
	StateStatusSync StateStatus = 3
	// StateStatusOverflow all resources in the stack have state but the state
	// has more resources than the stack.
	StateStatusOverflow StateStatus = 4
)

func StackImportState

func StackImportState(
	stack terra.Exporter,
	state *tfjson.State,
) (StateStatus, error)

StackImportState imports the Terraform state into the Terraform Stack. A StateStatus is returned indicating how complete the state of the resources is.

type TerraAction

type TerraAction[T terra.Exporter] struct {
	// Name is the name of the action.
	// It is used to create a directory to store the terraform files.
	// The directory will be `.lingon/terra/<name>`.
	Name string
	// Stack is the terra stack to export (to hcl) and run terra commands on.
	Stack T
	// contains filtered or unexported fields
}

TerraAction is an action that performs terra commands on a stack. It implements the Actioner interface so can be used together with a Workflow or independently. Use the Terra function to create a TerraAction.

func Terra

func Terra[T terra.Exporter](
	name string,
	stack T,
	opts ...TerraOption,
) *TerraAction[T]

Terra creates a new TerraAction.

func (*TerraAction[T]) ActionName

func (a *TerraAction[T]) ActionName() string

func (*TerraAction[T]) ActionType

func (a *TerraAction[T]) ActionType() ActionType

func (*TerraAction[T]) Apply

func (a *TerraAction[T]) Apply(ctx context.Context) error

Apply runs the terra apply command.

func (*TerraAction[T]) Cleanup

func (a *TerraAction[T]) Cleanup(ctx context.Context, opts RunOpts) error

Cleanup destroys the stack if the destroy option is set. It honours the dry run option.

func (*TerraAction[T]) Export

func (a *TerraAction[T]) Export() error

Export exports the stack to HCL.

func (*TerraAction[T]) HasChanges

func (a *TerraAction[T]) HasChanges() bool

HasChanges returns true if the plan (if any) has no diff, or if we ran apply on the stack, and if the objects in the stack all have some state. If there is no plan, but the state is full, the stack is considered in sync. Being in sync means there is no drift. This is best effort: things can always change between the time terra plan and apply were run.

func (*TerraAction[T]) ImportState

func (a *TerraAction[T]) ImportState(ctx context.Context) error

ImportState runs `terra show` and imports the state into the stack.

func (*TerraAction[T]) Init

func (a *TerraAction[T]) Init(ctx context.Context) error

Init runs the terra init command.

func (*TerraAction[T]) Plan

func (a *TerraAction[T]) Plan(
	ctx context.Context,
) (bool, error)

Plan runs the terra plan command and imports the plan into the stack.

func (*TerraAction[T]) PlanDestroy

func (a *TerraAction[T]) PlanDestroy(
	ctx context.Context,
) (bool, error)

PlanDestroy runs the terra plan command with the destroy flag and imports the plan into the stack.

func (*TerraAction[T]) Run

func (a *TerraAction[T]) Run(ctx context.Context, opts RunOpts) error

type TerraOption

type TerraOption func(*terraOpts)

func WithTerraCmd

func WithTerraCmd(cmd string) TerraOption

type Workflow

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

Workflow runs actions implementing the Actioner interface, to perform things like deploying terra stacks and kube apps. Use the NewWorkflow function to create a new workflow.

func NewWorkflow

func NewWorkflow(opts ...WorkflowOption) *Workflow

func (*Workflow) Cleanup

func (w *Workflow) Cleanup(ctx context.Context, opts ...CleanupOption) error

Cleanup should be run after all actions have been processed. If the destroy option is set, Cleanup will call destroy on all actions, in the reverse order they were run.

Calling Cleanup can be easily achieved with a Go defer statement, e.g.

defer func() {
	if err := wf.Cleanup(ctx); err != nil {
		// Handle error.
	}
}()

Or in a test using the t.Cleanup function, e.g.

t.Cleanup(func() {
	if err := wf.Cleanup(
		ctx,
		sylt.WithCleanupDestroy(true),
	); err != nil {
		t.Fatalf("finishing: %s", err)
	}
})

func (*Workflow) Run

func (w *Workflow) Run(ctx context.Context, action Actioner) error

Run performs the given action. It adds the action to the workflow's list of ordered action. When Cleanup() is called on the workflow, if the destroy flag is set, the actions's Cleanup() function are called in reverse order.

type WorkflowOption

type WorkflowOption func(*workflowOpts)

func WithWorkflowDestroy

func WithWorkflowDestroy(b bool) WorkflowOption

WithWorkflowDestroy sets the destroy option for Workflow.

func WithWorkflowDryRun

func WithWorkflowDryRun(b bool) WorkflowOption

WithWorkflowDryRun sets the dry run option for Workflow.

Jump to

Keyboard shortcuts

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