Skip to content

Use terraform remote state backend#3

Open
Vignesh (vigneshr-07) wants to merge 1 commit into
voy/add-remote-state-storagefrom
tf-native-remote-backend
Open

Use terraform remote state backend#3
Vignesh (vigneshr-07) wants to merge 1 commit into
voy/add-remote-state-storagefrom
tf-native-remote-backend

Conversation

@vigneshr-07
Copy link
Copy Markdown
Collaborator

@vigneshr-07 Vignesh (vigneshr-07) commented Oct 15, 2025

User description

The current implementation of state management uses our own implementation for managing local and remote state. On Matt Morrison (@sl1pm4t)'s suggestion, this PR attempts to use Terraform's native state backend management instead.

Migrated from ditto-cloud-bootstrap PR #29


Generated description

Below is a concise technical summary of the changes proposed in this PR:

graph LR
BootstrapCmd_("BootstrapCmd"):::modified
NewStateManager_("NewStateManager"):::added
InitializeWithBackend_("InitializeWithBackend"):::added
FinalizeStateTransfer_("FinalizeStateTransfer"):::added
checkBucketAccess_("checkBucketAccess"):::added
configureRemoteBackend_("configureRemoteBackend"):::added
ProviderConfig_("ProviderConfig"):::modified
checkAndMigrateToRemoteBackend_("checkAndMigrateToRemoteBackend"):::added
BootstrapCmd_ -- "Creates StateManager with provider config, workingDir, tf." --> NewStateManager_
BootstrapCmd_ -- "Initializes backend (remote preferred, fallback to local)." --> InitializeWithBackend_
BootstrapCmd_ -- "Defers copying state back and post-apply migration check." --> FinalizeStateTransfer_
InitializeWithBackend_ -- "Probes remote bucket accessibility with timed blob write test." --> checkBucketAccess_
InitializeWithBackend_ -- "Configures backend.tf and reinitializes Terraform to remote." --> configureRemoteBackend_
configureRemoteBackend_ -- "Retrieves provider-specific backend config (bucket, prefix, region)." --> ProviderConfig_
FinalizeStateTransfer_ -- "After copying, checks bucket and migrates local state remotely." --> checkAndMigrateToRemoteBackend_
checkAndMigrateToRemoteBackend_ -- "Reconfigures and reinitializes Terraform to use remote backend." --> configureRemoteBackend_
classDef added stroke:#15AA7A
classDef removed stroke:#CD5270
classDef modified stroke:#EDAC4C
linkStyle default stroke:#CBD5E1,font-size:13px
Loading

Implements Terraform's native remote state backend management to replace the previous custom local and remote state handling. Updates the StateManager and provider configurations to support automatic migration from local to remote storage during the bootstrap process.

TopicDetails
State Management Refactor the StateManager to utilize tfexec for backend initialization and handle the migration of state files between local and remote storage.
Modified files (2)
  • cmd/internal/bootstrap/bootstrap.go
  • cmd/internal/bootstrap/state.go
Latest Contributors(1)
UserCommitDate
vigneshwar.rajkumar@di...Update-project-referen...October 28, 2025
Cloud Backends Introduce TerraformBackendConfig implementations for AWS and GCP to generate provider-specific backend configuration files and initialization options.
Modified files (3)
  • cmd/internal/bootstrap/aws.go
  • cmd/internal/bootstrap/gcp.go
  • terraform/gcp/main.tf
Latest Contributors(1)
UserCommitDate
vigneshwar.rajkumar@di...Refactor-GCP-configura...November 20, 2025
This pull request is reviewed by Baz. Review like a pro on (Baz).

The current implementation of state management uses our own implementation for managing local and remote state. On @sl1pm4t's suggestion, this PR attempts to use Terraform's native state backend management instead.

## State backend configuration

This implementation dynamically creates a file in the working directory that contains the state backend definition.

Migrated from ditto-cloud-bootstrap PR #29
@vigneshr-07 Vignesh (vigneshr-07) requested a review from a team as a code owner October 15, 2025 20:55
@vigneshr-07 Vignesh (vigneshr-07) changed the base branch from main to voy/add-remote-state-storage October 15, 2025 20:55
Comment on lines +131 to 148
// FinalizeStateTransfer handles copying state files back and cleanup operations
func (s *StateManager) FinalizeStateTransfer(ctx context.Context) {
// Only handle finalization if we have both paths (local backend scenario)
if s.localStatePath == "" || s.workingStatePath == "" {
return
}
defer reader.Close()

// Create local file
localFile, err := os.Create(localPath)
// Copy the state file back to the original location
s.progressColor.Printf("Copying state file back to %q\n", s.localStatePath)
stateFileData, err := os.ReadFile(s.workingStatePath)
if err != nil {
return fmt.Errorf("failed to create local state file: %w", err)
s.progressColor.Printf("unable to read state file from temporary directory: %v", err)
return
}
if err := os.WriteFile(s.localStatePath, stateFileData, 0600); err != nil {
s.progressColor.Printf("unable to write state file to %q: %v", s.localStatePath, err)
return
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FinalizeStateTransfer now unconditionally copies the temp working state back to localStatePath; when a remote backend is configured Terraform never writes a local terraform.tfstate, so we end up overwriting the user's state file with the pre-migration copy and leaving it stale. Can we skip this copy when a remote backend was used so we don't overwrite the real remote state with outdated local data?

Prompt for AI Agents:

In cmd/internal/bootstrap/state.go around lines 131 to 148, the FinalizeStateTransfer
method unconditionally copies the temporary working state back to localStatePath which
can overwrite a user's remote state when a remote backend was configured. Change this so
FinalizeStateTransfer first checks whether a remote backend was successfully configured
and only performs the copy when no remote backend is in use. Concretely: add a boolean
field (e.g. remoteBackendConfigured) to StateManager, set it to true at the end of
configureRemoteBackend on successful initialization, and update FinalizeStateTransfer to
return early (skip the copy) if remoteBackendConfigured is true; keep current behavior
otherwise.

Fix in Cursor

Finding type: Logical Bugs

Comment on lines +269 to +289
// Try a simple write/read test
testObjectName := ".test_file_" + time.Now().Format("20060102150405")
writer, err := bucket.NewWriter(ctx, testObjectName, nil)
if err != nil {
return fmt.Errorf("failed to create bucket writer: %w", err)
s.logger.Debug("Remote state bucket doesn't exist or is not accessible",
"error", err,
"bucket", bucketURL)
return false, nil
}

if _, err := io.Copy(writer, localFile); err != nil {
if _, err := writer.Write([]byte("test")); err != nil {
writer.Close()
return fmt.Errorf("failed to upload state file content: %w", err)
return false, nil
}

if err := writer.Close(); err != nil {
return fmt.Errorf("failed to close bucket writer: %w", err)
return false, nil
}

s.logger.Debug("Remote state bucket exists and is accessible", "bucket", bucketURL)
return true, nil
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remote bucket probe writes .test_file_<timestamp> every run but never deletes it, so repeated bootstrap runs leave orphaned test objects in the bucket; can we delete the test object after the probe succeeds?

Prompt for AI Agents:

In cmd/internal/bootstrap/state.go around lines 269-289, the checkBucketAccess function
writes a test object named .test_file_<timestamp> to the bucket but never deletes it,
leaving orphaned probe objects. After the writer.Close() succeeds, delete that test
object by calling bucket.Delete(ctx, testObjectName) and handle any delete error by
logging a debug/warn message without returning an error (so probe still reports
accessible). Ensure the deletion is attempted only when the write/close completed
successfully and that bucket.Close() remains deferred as-is.

Fix in Cursor

Finding type: Logical Bugs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant