Documentation
¶
Index ¶
- Constants
- Variables
- func PullDir(root, repoFullName string, pullNum int) string
- type LocalPlanStore
- func (s *LocalPlanStore) DeleteForPull(_, _ string, _ int) error
- func (s *LocalPlanStore) DeletePlanForProject(_, _ string, _ int, _, _, _ string) error
- func (s *LocalPlanStore) ListWorkspaces(owner, repo string, pullNum int) ([]string, error)
- func (s *LocalPlanStore) Load(_ command.ProjectContext, _ string) error
- func (s *LocalPlanStore) Remove(_ command.ProjectContext, planPath string) error
- func (s *LocalPlanStore) RestorePlans(_, _, _ string, _ int) error
- func (s *LocalPlanStore) Save(_ command.ProjectContext, _ string) error
- type PlanStore
- type S3Client
- type S3PlanStore
- func (s *S3PlanStore) DeleteForPull(owner, repo string, pullNum int) error
- func (s *S3PlanStore) DeletePlanForProject(owner, repo string, pullNum int, workspace, repoRelDir, projectName string) error
- func (s *S3PlanStore) ListWorkspaces(owner, repo string, pullNum int) ([]string, error)
- func (s *S3PlanStore) Load(ctx command.ProjectContext, planPath string) error
- func (s *S3PlanStore) Remove(ctx command.ProjectContext, planPath string) error
- func (s *S3PlanStore) RestorePlans(pullDir, owner, repo string, pullNum int) error
- func (s *S3PlanStore) Save(ctx command.ProjectContext, planPath string) error
- func (s *S3PlanStore) TestS3Key(ctx command.ProjectContext, planPath string) string
- type S3PlanStoreConfig
Constants ¶
const ReposDir = "repos"
ReposDir is the directory beneath a data dir or a plan store dir under which the per-repository trees are laid out.
Variables ¶
var ErrRestoreNotSupported = errors.New("plan store does not support restore")
ErrRestoreNotSupported is returned by PlanStore implementations that do not support restoring plans (e.g. LocalPlanStore). Callers use errors.Is to distinguish this from actual restore failures.
Functions ¶
Types ¶
type LocalPlanStore ¶
type LocalPlanStore struct {
// SeparatePlanDir is the plan store directory when it is configured to be
// distinct from the data dir. Plans written there outlive the checkout, so
// a working dir lost to a restart can still be recovered without an
// external store. Empty means plans live inside the checkout and die with
// it, which leaves nothing to recover from.
SeparatePlanDir string
}
LocalPlanStore implements PlanStore using the local filesystem. Save and Load are no-ops because terraform already reads/writes locally.
func (*LocalPlanStore) DeleteForPull ¶
func (s *LocalPlanStore) DeleteForPull(_, _ string, _ int) error
func (*LocalPlanStore) DeletePlanForProject ¶
func (s *LocalPlanStore) DeletePlanForProject(_, _ string, _ int, _, _, _ string) error
func (*LocalPlanStore) ListWorkspaces ¶
func (s *LocalPlanStore) ListWorkspaces(owner, repo string, pullNum int) ([]string, error)
ListWorkspaces reports the workspaces that still have plans on disk in a separate plan store dir. Without one there is no inventory to read, because the plans went away with the checkout.
func (*LocalPlanStore) Load ¶
func (s *LocalPlanStore) Load(_ command.ProjectContext, _ string) error
func (*LocalPlanStore) Remove ¶
func (s *LocalPlanStore) Remove(_ command.ProjectContext, planPath string) error
func (*LocalPlanStore) RestorePlans ¶
func (s *LocalPlanStore) RestorePlans(_, _, _ string, _ int) error
RestorePlans has nothing to fetch: with a separate plan store dir the plans are already on disk, untouched by the loss of the checkout. It only needs to report that recovery is possible at all.
func (*LocalPlanStore) Save ¶
func (s *LocalPlanStore) Save(_ command.ProjectContext, _ string) error
type PlanStore ¶
type PlanStore interface {
// Save persists a plan file after terraform writes it to planPath.
Save(ctx command.ProjectContext, planPath string) error
// Load ensures a plan file exists at planPath before terraform reads it.
Load(ctx command.ProjectContext, planPath string) error
// Remove deletes a plan file (local + external) after apply/import/state-rm.
Remove(ctx command.ProjectContext, planPath string) error
// ListWorkspaces returns the distinct workspace names that have stored
// plans for the given pull request. Used by the "apply all" path so that
// every workspace can be cloned before RestorePlans writes plans into it
// (Clone falls through to forceClone which os.RemoveAll's the target dir,
// wiping any restored plan files). Implementations that don't support
// restore should return (nil, nil).
ListWorkspaces(owner, repo string, pullNum int) ([]string, error)
// RestorePlans discovers and downloads all plans for a pull request into
// pullDir. Only used by the "apply all" path (buildAllProjectCommandsByPlan)
// where the set of planned projects is unknown. Targeted apply does not
// call this; DefaultProjectCommandRunner.doApply calls Load before plan
// validation so the local .tfplan exists after a re-clone.
// Callers must ensure each workspace directory is cloned (has a .git) before
// invoking this; see ListWorkspaces.
//
// Capability probe: callers may invoke this with an empty pullDir to detect
// whether the implementation supports restore at all. Implementations that
// don't support restore MUST return ErrRestoreNotSupported. Implementations
// that do support restore MUST treat empty pullDir as a no-op (return nil).
RestorePlans(pullDir, owner, repo string, pullNum int) error
// DeleteForPull removes all stored plan files for a pull request.
// Called during PR close/merge cleanup.
DeleteForPull(owner, repo string, pullNum int) error
// DeletePlanForProject removes a specific project's plan from external storage.
// Called when a single lock is deleted via the UI or API.
DeletePlanForProject(owner, repo string, pullNum int, workspace, repoRelDir, projectName string) error
}
PlanStore abstracts plan file persistence. LocalPlanStore wraps current filesystem behavior (Save/Load are no-ops). S3PlanStore uploads after plan and downloads before apply.
type S3Client ¶
type S3Client interface {
HeadBucket(ctx context.Context, params *s3.HeadBucketInput, optFns ...func(*s3.Options)) (*s3.HeadBucketOutput, error)
PutObject(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error)
GetObject(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error)
DeleteObject(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error)
ListObjectsV2(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error)
}
S3Client is the subset of the S3 API used by S3PlanStore, extracted for testability.
type S3PlanStore ¶
type S3PlanStore struct {
// contains filtered or unexported fields
}
S3PlanStore implements PlanStore by persisting plan files to S3.
func NewS3PlanStore ¶
func NewS3PlanStore(cfg S3PlanStoreConfig, logger logging.SimpleLogging) (*S3PlanStore, error)
NewS3PlanStore creates an S3PlanStore using the AWS SDK default credential chain.
func NewS3PlanStoreWithClient ¶
func NewS3PlanStoreWithClient(client S3Client, bucket, prefix string, logger logging.SimpleLogging) *S3PlanStore
NewS3PlanStoreWithClient creates an S3PlanStore with an injected S3Client (for testing).
func (*S3PlanStore) DeleteForPull ¶
func (s *S3PlanStore) DeleteForPull(owner, repo string, pullNum int) error
DeleteForPull removes all plan objects stored under the pull request prefix in S3.
func (*S3PlanStore) DeletePlanForProject ¶
func (s *S3PlanStore) DeletePlanForProject(owner, repo string, pullNum int, workspace, repoRelDir, projectName string) error
func (*S3PlanStore) ListWorkspaces ¶
func (s *S3PlanStore) ListWorkspaces(owner, repo string, pullNum int) ([]string, error)
RestorePlans lists all plan files for a pull request in S3 (via prefix scan) and downloads them into pullDir so PendingPlanFinder can discover them. Only called from the "apply all" path where we don't know which projects were planned. The single-project path skips this and uses Load directly.
Note: plans downloaded here will be re-downloaded by Load() in ApplyStepRunner, which also validates head-commit metadata. This means each plan is fetched from S3 twice in the "apply all" path. Acceptable since plan files are small; eliminating it would require shared state between RestorePlans and Load. ListWorkspaces scans the pull request's prefix in S3 and returns the unique workspace names (first path segment after owner/repo/pullNum/) that have at least one .tfplan stored. Callers use this to clone each workspace before invoking RestorePlans, so plan files don't get wiped by a subsequent Clone.
func (*S3PlanStore) Load ¶
func (s *S3PlanStore) Load(ctx command.ProjectContext, planPath string) error
Load downloads the plan file from S3 and writes it to planPath.
func (*S3PlanStore) Remove ¶
func (s *S3PlanStore) Remove(ctx command.ProjectContext, planPath string) error
Remove deletes the plan file from S3 and locally.
func (*S3PlanStore) RestorePlans ¶
func (s *S3PlanStore) RestorePlans(pullDir, owner, repo string, pullNum int) error
func (*S3PlanStore) Save ¶
func (s *S3PlanStore) Save(ctx command.ProjectContext, planPath string) error
Save uploads the plan file at planPath to S3.
func (*S3PlanStore) TestS3Key ¶
func (s *S3PlanStore) TestS3Key(ctx command.ProjectContext, planPath string) string
TestS3Key is exported for testing only.