Skip to content

Commit 5738ca4

Browse files
committed
fix: cleaning up function of running phases etc
1 parent 42c5929 commit 5738ca4

File tree

4 files changed

+147
-30
lines changed

4 files changed

+147
-30
lines changed

nix/packages/pg-ami-builder/cmd/build.go

Lines changed: 81 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -185,26 +185,21 @@ func runBuildPhase1(cmd *cobra.Command, args []string) error {
185185
fmt.Printf("\n✓ Packer build completed successfully!\n")
186186
fmt.Println("✓ AMI created by packer")
187187

188-
// Parse AMI ID from packer output (it's already in stdout above)
189-
// For now, use AWS API to find the AMI by tags
188+
// Find AMI by execution ID tag (injected by our template rewriter)
189+
var amiID string
190190
ec2Client, err := aws.NewEC2Client(ctx, region)
191191
if err != nil {
192192
fmt.Printf("⚠ Could not create EC2 client to find AMI: %v\n", err)
193-
fmt.Println("\n✓ Build phase 1 complete!")
194-
return nil
195-
}
196-
197-
// Find AMI by execution ID tag
198-
amiID, err := ec2Client.FindAMIByTag(ctx, "packerExecutionId", executionID)
199-
if err != nil {
200-
fmt.Printf("⚠ Could not find created AMI: %v\n", err)
201-
fmt.Println("\n✓ Build phase 1 complete!")
202-
return nil
193+
} else {
194+
amiID, err = ec2Client.FindAMIByTag(ctx, "packerExecutionId", executionID)
195+
if err != nil {
196+
fmt.Printf("⚠ Could not find created AMI: %v\n", err)
197+
} else {
198+
fmt.Printf("✓ AMI ID: %s\n", amiID)
199+
}
203200
}
204201

205-
fmt.Printf("✓ AMI ID: %s\n", amiID)
206-
207-
// Save AMI ID to state for phase2
202+
// Save state even if we couldn't find the AMI
208203
stateFilePath := stateFile
209204
if stateFilePath == "" {
210205
stateFilePath, err = state.GetDefaultStateFile()
@@ -215,14 +210,19 @@ func runBuildPhase1(cmd *cobra.Command, args []string) error {
215210
}
216211
}
217212

218-
buildState := &state.State{
219-
Region: region,
220-
PostgresVersion: postgresVersion,
221-
GitSHA: sha,
213+
// Load existing state or create new
214+
buildState, err := state.LoadState(stateFilePath)
215+
if err != nil {
216+
buildState = &state.State{
217+
Region: region,
218+
PostgresVersion: postgresVersion,
219+
GitSHA: sha,
220+
}
222221
}
222+
223223
buildState.SetPhaseState("phase1", &state.PhaseState{
224224
ExecutionID: executionID,
225-
AMIID: amiID,
225+
AMIID: amiID, // Will be empty if not found
226226
Timestamp: time.Now().Format(time.RFC3339),
227227
})
228228

@@ -233,8 +233,13 @@ func runBuildPhase1(cmd *cobra.Command, args []string) error {
233233
}
234234

235235
fmt.Println("\n✓ Build phase 1 complete!")
236-
fmt.Printf("\nNext: Run phase 2 with:\n")
237-
fmt.Printf(" pg-ami-builder build phase2 --postgres-version %s\n", postgresVersion)
236+
if amiID != "" {
237+
fmt.Printf("\nNext: Run phase 2 with:\n")
238+
fmt.Printf(" pg-ami-builder build phase2 --postgres-version %s\n", postgresVersion)
239+
} else {
240+
fmt.Printf("\nNote: AMI ID not automatically detected. You can manually add it to:\n")
241+
fmt.Printf(" %s\n", stateFilePath)
242+
}
238243
return nil
239244
}
240245

@@ -398,7 +403,61 @@ func runBuildPhase2(cmd *cobra.Command, args []string) error {
398403

399404
fmt.Printf("\n✓ Packer build completed successfully!\n")
400405
fmt.Println("✓ Final production AMI created by packer")
406+
407+
// Find AMI by execution ID tag (injected by our template rewriter)
408+
var amiID string
409+
ec2Client, err := aws.NewEC2Client(ctx, region)
410+
if err != nil {
411+
fmt.Printf("⚠ Could not create EC2 client to find AMI: %v\n", err)
412+
} else {
413+
amiID, err = ec2Client.FindAMIByTag(ctx, "packerExecutionId", executionID)
414+
if err != nil {
415+
fmt.Printf("⚠ Could not find created AMI: %v\n", err)
416+
} else {
417+
fmt.Printf("✓ AMI ID: %s\n", amiID)
418+
}
419+
}
420+
421+
// Save state even if we couldn't find the AMI
422+
stateFilePath := stateFile
423+
if stateFilePath == "" {
424+
stateFilePath, err = state.GetDefaultStateFile()
425+
if err != nil {
426+
fmt.Printf("⚠ Could not get state file path: %v\n", err)
427+
fmt.Println("\n✓ Build phase 2 complete!")
428+
return nil
429+
}
430+
}
431+
432+
// Load existing state or create new
433+
buildState, err := state.LoadState(stateFilePath)
434+
if err != nil {
435+
buildState = &state.State{
436+
Region: region,
437+
PostgresVersion: postgresVersion,
438+
GitSHA: sha,
439+
}
440+
}
441+
442+
buildState.SetPhaseState("phase2", &state.PhaseState{
443+
ExecutionID: executionID,
444+
AMIID: amiID, // Will be empty if not found
445+
Timestamp: time.Now().Format(time.RFC3339),
446+
})
447+
448+
if err := state.SaveState(stateFilePath, buildState); err != nil {
449+
fmt.Printf("⚠ Could not save state: %v\n", err)
450+
} else {
451+
fmt.Printf("✓ State saved to: %s\n", stateFilePath)
452+
}
453+
401454
fmt.Println("\n✓ Build phase 2 complete!")
455+
if amiID != "" {
456+
fmt.Printf("\nProduction AMI ready: %s\n", amiID)
457+
} else {
458+
fmt.Printf("\nNote: AMI ID not automatically detected. You can manually add it to:\n")
459+
fmt.Printf(" %s\n", stateFilePath)
460+
}
402461
return nil
403462
}
404463

nix/packages/pg-ami-builder/cmd/cleanup.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,33 @@ func runCleanup(cmd *cobra.Command, args []string) error {
122122

123123
fmt.Println("✓ Instance terminated")
124124

125-
// Clear state file
126-
if stateFilePath != "" {
127-
if err := state.ClearState(stateFilePath); err != nil {
128-
fmt.Printf("Warning: failed to clear state file: %v\n", err)
129-
} else {
130-
fmt.Println("✓ State file cleared")
125+
// Clear phase-specific state
126+
if stateFilePath != "" && cleanupPhase != "" {
127+
// Load state, clear just this phase, save back
128+
buildState, err := state.LoadState(stateFilePath)
129+
if err == nil {
130+
// Clear this specific phase
131+
buildState.SetPhaseState(cleanupPhase, nil)
132+
133+
// Check if both phases are now empty
134+
phase1Empty := buildState.Phase1 == nil || (buildState.Phase1.InstanceID == "" && buildState.Phase1.AMIID == "")
135+
phase2Empty := buildState.Phase2 == nil || (buildState.Phase2.InstanceID == "" && buildState.Phase2.AMIID == "")
136+
137+
if phase1Empty && phase2Empty {
138+
// Both phases empty, delete entire file
139+
if err := state.ClearState(stateFilePath); err != nil {
140+
fmt.Printf("⚠ Failed to clear state file: %v\n", err)
141+
} else {
142+
fmt.Println("✓ State file cleared (all phases cleaned)")
143+
}
144+
} else {
145+
// Save updated state with this phase cleared
146+
if err := state.SaveState(stateFilePath, buildState); err != nil {
147+
fmt.Printf("⚠ Failed to update state file: %v\n", err)
148+
} else {
149+
fmt.Printf("✓ State file updated (%s cleared)\n", cleanupPhase)
150+
}
151+
}
131152
}
132153
}
133154

nix/packages/pg-ami-builder/cmd/ssh.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
var (
1515
sshInstanceID string
16+
sshPhase string
1617
awsEC2ConnectCmd string
1718
)
1819

@@ -51,12 +52,31 @@ func runSSH(cmd *cobra.Command, args []string) error {
5152
return fmt.Errorf("failed to load state: %w", err)
5253
}
5354

54-
instanceID = buildState.InstanceID
5555
region = buildState.Region
56+
57+
// Get instance ID from phase-specific state
58+
if sshPhase != "" {
59+
phaseState := buildState.GetPhaseState(sshPhase)
60+
if phaseState == nil || phaseState.InstanceID == "" {
61+
return fmt.Errorf("no instance found for %s in state file", sshPhase)
62+
}
63+
instanceID = phaseState.InstanceID
64+
} else {
65+
// Auto-detect: prefer phase2, then phase1, then legacy
66+
if buildState.Phase2 != nil && buildState.Phase2.InstanceID != "" {
67+
instanceID = buildState.Phase2.InstanceID
68+
fmt.Println("✓ Auto-detected phase2 instance")
69+
} else if buildState.Phase1 != nil && buildState.Phase1.InstanceID != "" {
70+
instanceID = buildState.Phase1.InstanceID
71+
fmt.Println("✓ Auto-detected phase1 instance")
72+
} else if buildState.InstanceID != "" {
73+
instanceID = buildState.InstanceID
74+
}
75+
}
5676
}
5777

5878
if instanceID == "" {
59-
return fmt.Errorf("no instance ID available (use --instance-id or run build command first)")
79+
return fmt.Errorf("no instance ID available (use --instance-id or --phase, or run build command first)")
6080
}
6181

6282
// Connect via EC2 Instance Connect
@@ -147,6 +167,7 @@ func init() {
147167
rootCmd.AddCommand(sshCmd)
148168

149169
sshCmd.Flags().StringVar(&sshInstanceID, "instance-id", "", "Target specific instance (default: from state file)")
170+
sshCmd.Flags().StringVar(&sshPhase, "phase", "", "Connect to specific phase instance (phase1 or phase2)")
150171
sshCmd.Flags().StringVar(&region, "region", "us-east-1", "AWS region")
151172
sshCmd.Flags().StringVar(&awsEC2ConnectCmd, "aws-ec2-connect-cmd", "", "Custom AWS EC2 Instance Connect command (e.g., 'aws ec2-instance-connect ssh --instance-id i-xxx ...')")
152173
}

nix/packages/pg-ami-builder/internal/packer/runner.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ func RewriteTemplateWithUniqueAMI(templatePath, executionID, sourceAMI string) (
4545
return strings.TrimSuffix(match, `"`) + `-${var.packer-execution-id}"`
4646
})
4747

48+
// Add packerExecutionId to AMI tags (not run_tags)
49+
// Find the tags = { block (after run_tags) and inject packerExecutionId
50+
tagsPattern := regexp.MustCompile(`(?s)(tags\s*=\s*\{)([^}]*creator\s*=\s*"packer"[^}]*)(\})`)
51+
modified = tagsPattern.ReplaceAllStringFunc(modified, func(match string) string {
52+
// Check if packerExecutionId already exists in this tags block
53+
if strings.Contains(match, "packerExecutionId") {
54+
return match // Already has it
55+
}
56+
// Insert packerExecutionId after the opening brace
57+
parts := tagsPattern.FindStringSubmatch(match)
58+
if len(parts) == 4 {
59+
return parts[1] + "\n packerExecutionId = \"${var.packer-execution-id}\"" + parts[2] + parts[3]
60+
}
61+
return match
62+
})
63+
4864
// Create temp file
4965
tempDir := os.TempDir()
5066
tempFile := filepath.Join(tempDir, fmt.Sprintf("packer-%s-%s", executionID, filepath.Base(templatePath)))

0 commit comments

Comments
 (0)