staging

package
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Jan 6, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package staging provides staging functionality for AWS parameter and secret changes.

Package staging provides staging functionality for AWS parameter and secret changes.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotStaged is returned when a parameter/secret is not staged.
	ErrNotStaged = errors.New("not staged")
)

Functions

func CheckConflicts

func CheckConflicts(ctx context.Context, strategy ApplyStrategy, entries map[string]Entry) map[string]struct{}

CheckConflicts checks if AWS resources were modified after staging. Returns a map of names that have conflicts.

For Create operations: conflicts if resource now exists (someone else created it). For Update/Delete operations with BaseModifiedAt: conflicts if AWS was modified after base.

Types

type ApplyStrategy

type ApplyStrategy interface {
	ServiceStrategy

	// Apply applies a staged entry operation to AWS.
	// Handles OperationCreate, OperationUpdate, and OperationDelete based on entry.Operation.
	Apply(ctx context.Context, name string, entry Entry) error

	// ApplyTags applies staged tag changes to AWS.
	ApplyTags(ctx context.Context, name string, tagEntry TagEntry) error

	// FetchLastModified returns the last modified time of the resource in AWS.
	// Returns zero time if the resource doesn't exist (for create operations).
	FetchLastModified(ctx context.Context, name string) (time.Time, error)
}

ApplyStrategy defines service-specific apply operations.

type DeleteOptions

type DeleteOptions struct {
	// Force enables immediate permanent deletion without recovery window.
	Force bool `json:"force,omitempty"`
	// RecoveryWindow is the number of days before permanent deletion (7-30).
	// Only used when Force is false. 0 means default (30 days).
	RecoveryWindow int `json:"recovery_window,omitempty"`
}

DeleteOptions holds options for Secrets Manager delete operations.

type DeleteStrategy added in v0.1.1

type DeleteStrategy interface {
	ServiceStrategy

	// FetchLastModified returns the last modified time of the resource in AWS.
	// Used for conflict detection when applying delete operations.
	FetchLastModified(ctx context.Context, name string) (time.Time, error)
}

DeleteStrategy defines service-specific delete staging operations.

type DiffStrategy

type DiffStrategy interface {
	ServiceStrategy

	// FetchCurrent fetches the current value from AWS for diffing.
	FetchCurrent(ctx context.Context, name string) (*FetchResult, error)
}

DiffStrategy defines service-specific diff/fetch operations.

type EditFetchResult

type EditFetchResult struct {
	// Value is the current value in AWS.
	Value string
	// LastModified is the last modification time of the resource.
	// Used for conflict detection when applying staged changes.
	LastModified time.Time
}

EditFetchResult holds the result of fetching a value for editing.

type EditStrategy

type EditStrategy interface {
	Parser

	// FetchCurrentValue fetches the current value from AWS for editing.
	// Returns the value and last modified time for conflict detection.
	FetchCurrentValue(ctx context.Context, name string) (*EditFetchResult, error)
}

EditStrategy defines service-specific edit operations.

type Entry

type Entry struct {
	Operation   Operation `json:"operation"`
	Value       *string   `json:"value,omitempty"` // nil for delete, pointer to distinguish from empty string
	Description *string   `json:"description,omitempty"`
	StagedAt    time.Time `json:"staged_at"`
	// BaseModifiedAt records the AWS LastModified time when the value was fetched.
	// Used for conflict detection: if AWS was modified after this time, it's a conflict.
	// Only set for update/delete operations (nil for create since there's no base).
	BaseModifiedAt *time.Time `json:"base_modified_at,omitempty"`
	// DeleteOptions holds Secrets Manager-specific delete options.
	// Only used when Operation is OperationDelete and service is Secrets Manager.
	DeleteOptions *DeleteOptions `json:"delete_options,omitempty"`
}

Entry represents a single staged entity change (create/update/delete). Tags are managed separately in TagEntry.

type EntryPrinter

type EntryPrinter struct {
	Writer io.Writer
}

EntryPrinter prints staged entries to the given writer.

func (*EntryPrinter) PrintEntry

func (p *EntryPrinter) PrintEntry(name string, entry Entry, verbose, showDeleteOptions bool)

PrintEntry prints a single staged entry. If verbose is true, shows detailed information including timestamp and value. If showDeleteOptions is true, shows delete options (Force/RecoveryWindow) for delete operations.

type FetchResult

type FetchResult struct {
	// Value is the current value in AWS.
	Value string
	// Identifier is a display string for the version (e.g., "#3" for SSM Parameter Store, "#abc123" for Secrets Manager).
	Identifier string
}

FetchResult holds the result of fetching a value from AWS.

type FullStrategy

type FullStrategy interface {
	ApplyStrategy
	DiffStrategy
	EditStrategy
	ResetStrategy
}

FullStrategy combines all service-specific strategy interfaces. This enables unified stage commands that work with either SSM Parameter Store or Secrets Manager.

func ParamFactory

func ParamFactory(ctx context.Context) (FullStrategy, error)

ParamFactory creates a FullStrategy with an initialized AWS client.

func SecretFactory

func SecretFactory(ctx context.Context) (FullStrategy, error)

SecretFactory creates a FullStrategy with an initialized AWS client.

type Operation

type Operation string

Operation represents the type of staged change.

const (
	// OperationCreate represents a create operation (new item).
	OperationCreate Operation = "create"
	// OperationUpdate represents an update operation (existing item).
	OperationUpdate Operation = "update"
	// OperationDelete represents a delete operation.
	OperationDelete Operation = "delete"
)

type ParamClient

ParamClient is the combined interface for SSM Parameter Store stage operations.

type ParamStrategy

type ParamStrategy struct {
	Client ParamClient
}

ParamStrategy implements ServiceStrategy for SSM Parameter Store.

func NewParamStrategy

func NewParamStrategy(client ParamClient) *ParamStrategy

NewParamStrategy creates a new SSM Parameter Store strategy.

func (*ParamStrategy) Apply

func (s *ParamStrategy) Apply(ctx context.Context, name string, entry Entry) error

Apply applies a staged operation to AWS SSM Parameter Store.

func (*ParamStrategy) ApplyTags added in v0.3.0

func (s *ParamStrategy) ApplyTags(ctx context.Context, name string, tagEntry TagEntry) error

ApplyTags applies staged tag changes to AWS SSM Parameter Store.

func (*ParamStrategy) FetchCurrent

func (s *ParamStrategy) FetchCurrent(ctx context.Context, name string) (*FetchResult, error)

FetchCurrent fetches the current value from AWS SSM Parameter Store for diffing.

func (*ParamStrategy) FetchCurrentValue

func (s *ParamStrategy) FetchCurrentValue(ctx context.Context, name string) (*EditFetchResult, error)

FetchCurrentValue fetches the current value from AWS SSM Parameter Store for editing. Returns *ResourceNotFoundError if the parameter doesn't exist.

func (*ParamStrategy) FetchLastModified

func (s *ParamStrategy) FetchLastModified(ctx context.Context, name string) (time.Time, error)

FetchLastModified returns the last modified time of the parameter in AWS. Returns zero time if the parameter doesn't exist.

func (*ParamStrategy) FetchVersion

func (s *ParamStrategy) FetchVersion(ctx context.Context, input string) (value string, versionLabel string, err error)

FetchVersion fetches the value for a specific version.

func (*ParamStrategy) HasDeleteOptions

func (s *ParamStrategy) HasDeleteOptions() bool

HasDeleteOptions returns false as SSM Parameter Store doesn't have delete options.

func (*ParamStrategy) ItemName

func (s *ParamStrategy) ItemName() string

ItemName returns the item name for messages.

func (*ParamStrategy) ParseName

func (s *ParamStrategy) ParseName(input string) (string, error)

ParseName parses and validates a name for editing.

func (*ParamStrategy) ParseSpec

func (s *ParamStrategy) ParseSpec(input string) (name string, hasVersion bool, err error)

ParseSpec parses a version spec string for reset.

func (*ParamStrategy) Service

func (s *ParamStrategy) Service() Service

Service returns the service type.

func (*ParamStrategy) ServiceName

func (s *ParamStrategy) ServiceName() string

ServiceName returns the user-friendly service name.

type Parser

type Parser interface {
	ServiceStrategy

	// ParseName parses and validates a name, returning only the base name without version specifiers.
	// Returns an error if version specifiers are present.
	ParseName(input string) (string, error)

	// ParseSpec parses a version spec string.
	// Returns the base name and whether a version/shift was specified.
	ParseSpec(input string) (name string, hasVersion bool, err error)
}

Parser provides name/spec parsing without AWS access. Use this interface when only parsing is needed (e.g., status, add commands).

func ParamParserFactory

func ParamParserFactory() Parser

ParamParserFactory creates a Parser without an AWS client. Use this for operations that don't need AWS access (e.g., status, parsing).

func SecretParserFactory

func SecretParserFactory() Parser

SecretParserFactory creates a Parser without an AWS client. Use this for operations that don't need AWS access (e.g., status, parsing).

type ParserFactory

type ParserFactory func() Parser

ParserFactory creates a Parser without AWS client.

type ResetStrategy

type ResetStrategy interface {
	Parser

	// FetchVersion fetches the value for a specific version.
	// Returns the value and a version label for display.
	FetchVersion(ctx context.Context, input string) (value string, versionLabel string, err error)

	// FetchCurrentValue fetches the current value from AWS for auto-skip detection.
	// Uses same signature as EditStrategy for implementation reuse.
	FetchCurrentValue(ctx context.Context, name string) (*EditFetchResult, error)
}

ResetStrategy defines service-specific reset operations.

type ResourceNotFoundError added in v0.4.8

type ResourceNotFoundError struct {
	Err error
}

ResourceNotFoundError indicates a resource was not found in AWS.

func (*ResourceNotFoundError) Error added in v0.4.8

func (e *ResourceNotFoundError) Error() string

func (*ResourceNotFoundError) Unwrap added in v0.4.8

func (e *ResourceNotFoundError) Unwrap() error

type SecretStrategy

type SecretStrategy struct {
	Client SecretClient
}

SecretStrategy implements ServiceStrategy for Secrets Manager.

func NewSecretStrategy

func NewSecretStrategy(client SecretClient) *SecretStrategy

NewSecretStrategy creates a new Secrets Manager strategy.

func (*SecretStrategy) Apply

func (s *SecretStrategy) Apply(ctx context.Context, name string, entry Entry) error

Apply applies a staged operation to AWS Secrets Manager.

func (*SecretStrategy) ApplyTags added in v0.3.0

func (s *SecretStrategy) ApplyTags(ctx context.Context, name string, tagEntry TagEntry) error

ApplyTags applies staged tag changes to AWS Secrets Manager.

func (*SecretStrategy) FetchCurrent

func (s *SecretStrategy) FetchCurrent(ctx context.Context, name string) (*FetchResult, error)

FetchCurrent fetches the current value from AWS Secrets Manager for diffing.

func (*SecretStrategy) FetchCurrentValue

func (s *SecretStrategy) FetchCurrentValue(ctx context.Context, name string) (*EditFetchResult, error)

FetchCurrentValue fetches the current value from AWS Secrets Manager for editing. Returns *ResourceNotFoundError if the secret doesn't exist.

func (*SecretStrategy) FetchLastModified

func (s *SecretStrategy) FetchLastModified(ctx context.Context, name string) (time.Time, error)

FetchLastModified returns the last modified time of the secret in AWS. Returns zero time if the secret doesn't exist.

func (*SecretStrategy) FetchVersion

func (s *SecretStrategy) FetchVersion(ctx context.Context, input string) (value string, versionLabel string, err error)

FetchVersion fetches the value for a specific version.

func (*SecretStrategy) HasDeleteOptions

func (s *SecretStrategy) HasDeleteOptions() bool

HasDeleteOptions returns true as Secrets Manager has delete options.

func (*SecretStrategy) ItemName

func (s *SecretStrategy) ItemName() string

ItemName returns the item name for messages.

func (*SecretStrategy) ParseName

func (s *SecretStrategy) ParseName(input string) (string, error)

ParseName parses and validates a name for editing.

func (*SecretStrategy) ParseSpec

func (s *SecretStrategy) ParseSpec(input string) (name string, hasVersion bool, err error)

ParseSpec parses a version spec string for reset.

func (*SecretStrategy) Service

func (s *SecretStrategy) Service() Service

Service returns the service type.

func (*SecretStrategy) ServiceName

func (s *SecretStrategy) ServiceName() string

ServiceName returns the user-friendly service name.

type Service

type Service string

Service represents which AWS service the staged change belongs to.

const (
	// ServiceParam represents AWS Systems Manager Parameter Store.
	ServiceParam Service = "param"
	// ServiceSecret represents AWS Secrets Manager.
	ServiceSecret Service = "secret"
)

type ServiceStrategy

type ServiceStrategy interface {
	// Service returns the service type (ServiceParam or ServiceSecret).
	Service() Service

	// ServiceName returns the user-friendly service name (e.g., "SSM Parameter Store", "Secrets Manager").
	ServiceName() string

	// ItemName returns the item name for messages (e.g., "parameter", "secret").
	ItemName() string

	// HasDeleteOptions returns true if delete options should be displayed.
	HasDeleteOptions() bool
}

ServiceStrategy defines the common interface for service-specific operations. This enables Strategy Pattern to consolidate duplicate code across SSM Parameter Store and Secrets Manager commands.

type State

type State struct {
	Version int                             `json:"version"`
	Entries map[Service]map[string]Entry    `json:"entries,omitempty"`
	Tags    map[Service]map[string]TagEntry `json:"tags,omitempty"`
}

State represents the entire staging state (v2). Entries and Tags are managed separately for cleaner separation of concerns.

type Store

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

Store manages the staging state.

func NewStore

func NewStore(accountID, region string) (*Store, error)

NewStore creates a new Store with the default state file path. The state file is stored under ~/.suve/{accountID}/{region}/stage.json to isolate staging state per AWS account and region.

func NewStoreWithPath

func NewStoreWithPath(path string) *Store

NewStoreWithPath creates a new Store with a custom state file path. This is primarily for testing.

func (*Store) Count

func (s *Store) Count(service Service) (int, error)

Count returns the number of staged entry changes. Note: This counts entries only, not tag changes. Use CountAll for total count.

func (*Store) GetEntry added in v0.3.0

func (s *Store) GetEntry(service Service, name string) (*Entry, error)

GetEntry retrieves a staged entry.

func (*Store) GetTag added in v0.3.0

func (s *Store) GetTag(service Service, name string) (*TagEntry, error)

GetTag retrieves staged tag changes.

func (*Store) HasChanges

func (s *Store) HasChanges(service Service) (bool, error)

HasChanges returns true if there are any staged changes (entries or tags).

func (*Store) ListEntries added in v0.3.0

func (s *Store) ListEntries(service Service) (map[Service]map[string]Entry, error)

ListEntries returns all staged entries for a service. If service is empty, returns all staged entries.

func (*Store) ListTags added in v0.3.0

func (s *Store) ListTags(service Service) (map[Service]map[string]TagEntry, error)

ListTags returns all staged tag changes for a service. If service is empty, returns all staged tag changes.

func (*Store) Load

func (s *Store) Load() (*State, error)

Load loads the current staging state from disk.

func (*Store) Save

func (s *Store) Save(state *State) error

Save saves the staging state to disk.

func (*Store) StageEntry added in v0.3.0

func (s *Store) StageEntry(service Service, name string, entry Entry) error

StageEntry adds or updates a staged entry change.

func (*Store) StageTag added in v0.3.0

func (s *Store) StageTag(service Service, name string, tagEntry TagEntry) error

StageTag adds or updates staged tag changes.

func (*Store) UnstageAll

func (s *Store) UnstageAll(service Service) error

UnstageAll removes all staged changes for a service. If service is empty, removes all staged changes.

func (*Store) UnstageEntry added in v0.3.0

func (s *Store) UnstageEntry(service Service, name string) error

UnstageEntry removes a staged entry change.

func (*Store) UnstageTag added in v0.3.0

func (s *Store) UnstageTag(service Service, name string) error

UnstageTag removes staged tag changes.

type StoreReadWriter added in v0.1.1

type StoreReadWriter interface {
	StoreReader
	StoreWriter
}

StoreReadWriter combines read and write access to staging state.

type StoreReader added in v0.1.1

type StoreReader interface {
	// GetEntry retrieves a staged entry.
	GetEntry(service Service, name string) (*Entry, error)
	// GetTag retrieves staged tag changes.
	GetTag(service Service, name string) (*TagEntry, error)
	// ListEntries returns all staged entries for a service.
	ListEntries(service Service) (map[Service]map[string]Entry, error)
	// ListTags returns all staged tag changes for a service.
	ListTags(service Service) (map[Service]map[string]TagEntry, error)
	// Load loads the current staging state from disk.
	Load() (*State, error)
}

StoreReader provides read-only access to staging state.

type StoreWriter added in v0.1.1

type StoreWriter interface {
	// StageEntry adds or updates a staged entry.
	StageEntry(service Service, name string, entry Entry) error
	// StageTag adds or updates staged tag changes.
	StageTag(service Service, name string, tagEntry TagEntry) error
	// UnstageEntry removes a staged entry.
	UnstageEntry(service Service, name string) error
	// UnstageTag removes staged tag changes.
	UnstageTag(service Service, name string) error
	// UnstageAll removes all staged changes for a service.
	UnstageAll(service Service) error
}

StoreWriter provides write access to staging state.

type StrategyFactory

type StrategyFactory func(ctx context.Context) (FullStrategy, error)

StrategyFactory creates a FullStrategy for a given context. Used to defer AWS client initialization until command execution.

type TagEntry added in v0.3.0

type TagEntry struct {
	Add    map[string]string   `json:"add,omitempty"`    // Tags to add or update
	Remove maputil.Set[string] `json:"remove,omitempty"` // Tag keys to remove
	// StagedAt records when the tag change was staged.
	StagedAt time.Time `json:"staged_at"`
	// BaseModifiedAt records the AWS LastModified time when tags were fetched.
	// Used for conflict detection.
	BaseModifiedAt *time.Time `json:"base_modified_at,omitempty"`
}

TagEntry represents staged tag changes for an entity. Managed separately from Entry for cleaner separation of concerns.

Directories

Path Synopsis
Package runner provides shared runners and command builders for stage commands.
Package runner provides shared runners and command builders for stage commands.

Jump to

Keyboard shortcuts

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