Skip to content

Commit f2d4bf9

Browse files
authored
fix: planstorage functionality (#222)
1 parent 26c1b90 commit f2d4bf9

File tree

5 files changed

+70
-28
lines changed

5 files changed

+70
-28
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
venv/
44
**/__pycache__/
55
__azurite*
6+
digger

pkg/digger/digger.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,19 @@ func RunCommandsPerProject(commandsPerProject []ProjectCommand, repoOwner string
7373
}
7474

7575
var terraformExecutor terraform.TerraformExecutor
76-
76+
projectPath := path.Join(workingDir, projectCommands.ProjectDir)
7777
if projectCommands.Terragrunt {
78-
terraformExecutor = terraform.Terragrunt{WorkingDir: path.Join(workingDir, projectCommands.ProjectDir)}
78+
terraformExecutor = terraform.Terragrunt{WorkingDir: projectPath}
7979
} else {
80-
terraformExecutor = terraform.Terraform{WorkingDir: path.Join(workingDir, projectCommands.ProjectDir), Workspace: projectCommands.ProjectWorkspace}
80+
terraformExecutor = terraform.Terraform{WorkingDir: projectPath, Workspace: projectCommands.ProjectWorkspace}
8181
}
8282

8383
commandRunner := CommandRunner{}
8484
diggerExecutor := DiggerExecutor{
85+
repoOwner,
86+
repoName,
8587
projectCommands.ProjectName,
88+
projectPath,
8689
projectCommands.StateEnvVars,
8790
projectCommands.CommandEnvVars,
8891
projectCommands.ApplyStage,
@@ -338,7 +341,10 @@ func parseProjectName(comment string) string {
338341
}
339342

340343
type DiggerExecutor struct {
344+
repoOwner string
345+
repoName string
341346
projectName string
347+
projectPath string
342348
stateEnvVars map[string]string
343349
commandEnvVars map[string]string
344350
applyStage *configuration.Stage
@@ -378,11 +384,18 @@ func (c CommandRunner) Run(command string) (string, string, error) {
378384
}
379385

380386
func (d DiggerExecutor) planFileName() string {
381-
return d.projectName + ".tfplan"
387+
return d.repoName + "#" + d.projectName + ".tfplan"
382388
}
383389

384-
func (d DiggerExecutor) Plan(prNumber int) error {
390+
func (d DiggerExecutor) localPlanFilePath() string {
391+
return path.Join(d.projectPath, d.planFileName())
392+
}
393+
394+
func (d DiggerExecutor) storedPlanFilePath() string {
395+
return path.Join(d.repoOwner, d.planFileName())
396+
}
385397

398+
func (d DiggerExecutor) Plan(prNumber int) error {
386399
res, err := d.lock.Lock(prNumber)
387400
if err != nil {
388401
return fmt.Errorf("error locking project: %v", err)
@@ -418,7 +431,7 @@ func (d DiggerExecutor) Plan(prNumber int) error {
418431
return fmt.Errorf("error executing plan: %v", err)
419432
}
420433
if d.planStorage != nil {
421-
err = d.planStorage.StorePlan(d.planFileName())
434+
err = d.planStorage.StorePlan(d.localPlanFilePath(), d.storedPlanFilePath())
422435
if err != nil {
423436
return fmt.Errorf("error storing plan: %v", err)
424437
}
@@ -443,7 +456,7 @@ func (d DiggerExecutor) Apply(prNumber int) error {
443456
var plansFilename *string
444457
if d.planStorage != nil {
445458
var err error
446-
plansFilename, err = d.planStorage.RetrievePlan(d.planFileName())
459+
plansFilename, err = d.planStorage.RetrievePlan(d.localPlanFilePath(), d.storedPlanFilePath())
447460
if err != nil {
448461
return fmt.Errorf("error retrieving plan: %v", err)
449462
}
@@ -509,6 +522,10 @@ func (d DiggerExecutor) Unlock(prNumber int) error {
509522
if err != nil {
510523
return fmt.Errorf("failed to aquire lock: %s, %v", d.lock.LockId(), err)
511524
}
525+
err = d.planStorage.DeleteStoredPlan(d.storedPlanFilePath())
526+
if err != nil {
527+
return fmt.Errorf("failed to delete stored plan file '%v': %v", d.storedPlanFilePath(), err)
528+
}
512529
return nil
513530
}
514531

pkg/digger/digger_test.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,21 @@ type MockPlanStorage struct {
128128
Commands []RunInfo
129129
}
130130

131-
func (m *MockPlanStorage) StorePlan(planFileName string) error {
132-
m.Commands = append(m.Commands, RunInfo{"StorePlan", planFileName, time.Now()})
131+
func (m *MockPlanStorage) StorePlan(localPlanFilePath string, storedPlanFilePath string) error {
132+
m.Commands = append(m.Commands, RunInfo{"StorePlan", localPlanFilePath, time.Now()})
133133
return nil
134134
}
135135

136-
func (m *MockPlanStorage) RetrievePlan(planFileName string) (*string, error) {
137-
m.Commands = append(m.Commands, RunInfo{"RetrievePlan", planFileName, time.Now()})
136+
func (m *MockPlanStorage) RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error) {
137+
m.Commands = append(m.Commands, RunInfo{"RetrievePlan", localPlanFilePath, time.Now()})
138138
return nil, nil
139139
}
140140

141+
func (m *MockPlanStorage) DeleteStoredPlan(storedPlanFilePath string) error {
142+
m.Commands = append(m.Commands, RunInfo{"DeleteStoredPlan", storedPlanFilePath, time.Now()})
143+
return nil
144+
}
145+
141146
func TestCorrectCommandExecutionWhenApplying(t *testing.T) {
142147

143148
commandRunner := &MockCommandRunner{}
@@ -177,7 +182,7 @@ func TestCorrectCommandExecutionWhenApplying(t *testing.T) {
177182

178183
commandStrings := allCommandsInOrderWithParams(terraformExecutor, commandRunner, prManager, lock, planStorage)
179184

180-
assert.Equal(t, []string{"RetrievePlan .tfplan", "IsMergeable 1", "Lock 1", "Init ", "Apply ", "LockId ", "PublishComment 1 <details>\n <summary>Apply for ****</summary>\n\n ```terraform\n\n ```\n</details>", "Run echo", "LockId "}, commandStrings)
185+
assert.Equal(t, []string{"RetrievePlan #.tfplan", "IsMergeable 1", "Lock 1", "Init ", "Apply ", "LockId ", "PublishComment 1 <details>\n <summary>Apply for ****</summary>\n\n ```terraform\n\n ```\n</details>", "Run echo", "LockId "}, commandStrings)
181186
}
182187

183188
func TestCorrectCommandExecutionWhenPlanning(t *testing.T) {
@@ -219,7 +224,7 @@ func TestCorrectCommandExecutionWhenPlanning(t *testing.T) {
219224

220225
commandStrings := allCommandsInOrderWithParams(terraformExecutor, commandRunner, prManager, lock, planStorage)
221226

222-
assert.Equal(t, []string{"Lock 1", "Init ", "Plan -out .tfplan", "StorePlan .tfplan", "LockId ", "PublishComment 1 <details>\n <summary>Plan for ****</summary>\n\n ```terraform\n\n ```\n</details>", "Run echo", "LockId "}, commandStrings)
227+
assert.Equal(t, []string{"Lock 1", "Init ", "Plan -out #.tfplan", "StorePlan #.tfplan", "LockId ", "PublishComment 1 <details>\n <summary>Plan for ****</summary>\n\n ```terraform\n\n ```\n</details>", "Run echo", "LockId "}, commandStrings)
223228
}
224229

225230
func allCommandsInOrderWithParams(terraformExecutor *MockTerraformExecutor, commandRunner *MockCommandRunner, prManager *MockPRManager, lock *MockProjectLock, planStorage *MockPlanStorage) []string {

pkg/utils/mocks.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,14 @@ func (t MockPullRequestManager) IsClosed(prNumber int) (bool, error) {
7777
type MockPlanStorage struct {
7878
}
7979

80-
func (t MockPlanStorage) StorePlan(planfile string) error {
80+
func (t MockPlanStorage) StorePlan(localPlanFilePath string, storedPlanFilePath string) error {
8181
return nil
8282
}
8383

84-
func (t MockPlanStorage) RetrievePlan(planfile string) (*string, error) {
84+
func (t MockPlanStorage) RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error) {
8585
return nil, nil
8686
}
87+
88+
func (t MockPlanStorage) DeleteStoredPlan(storedPlanFilePath string) error {
89+
return nil
90+
}

pkg/utils/plan_storage.go

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import (
1414
)
1515

1616
type PlanStorage interface {
17-
StorePlan(planFileName string) error
18-
RetrievePlan(planFileName string) (*string, error)
17+
StorePlan(localPlanFilePath string, storedPlanFilePath string) error
18+
RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error)
19+
DeleteStoredPlan(storedPlanFilePath string) error
1920
}
2021

2122
type PlanStorageGcp struct {
@@ -32,14 +33,14 @@ type GithubPlanStorage struct {
3233
ZipManager Zipper
3334
}
3435

35-
func (psg *PlanStorageGcp) StorePlan(planFileName string) error {
36-
file, err := os.Open(planFileName)
36+
func (psg *PlanStorageGcp) StorePlan(localPlanFilePath string, storedPlanFilePath string) error {
37+
file, err := os.Open(localPlanFilePath)
3738
if err != nil {
3839
return fmt.Errorf("unable to open file: %v", err)
3940
}
4041
defer file.Close()
4142

42-
obj := psg.Bucket.Object(planFileName)
43+
obj := psg.Bucket.Object(storedPlanFilePath)
4344
wc := obj.NewWriter(psg.Context)
4445

4546
if _, err = io.Copy(wc, file); err != nil {
@@ -54,15 +55,15 @@ func (psg *PlanStorageGcp) StorePlan(planFileName string) error {
5455
return nil
5556
}
5657

57-
func (psg *PlanStorageGcp) RetrievePlan(planFileName string) (*string, error) {
58-
obj := psg.Bucket.Object(planFileName)
58+
func (psg *PlanStorageGcp) RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error) {
59+
obj := psg.Bucket.Object(storedPlanFilePath)
5960
rc, err := obj.NewReader(psg.Context)
6061
if err != nil {
6162
return nil, fmt.Errorf("unable to read data from bucket: %v", err)
6263
}
6364
defer rc.Close()
6465

65-
file, err := os.Create(planFileName)
66+
file, err := os.Create(localPlanFilePath)
6667
if err != nil {
6768
return nil, fmt.Errorf("unable to create file: %v", err)
6869
}
@@ -72,15 +73,25 @@ func (psg *PlanStorageGcp) RetrievePlan(planFileName string) (*string, error) {
7273
return nil, fmt.Errorf("unable to write data to file: %v", err)
7374
}
7475

75-
return &planFileName, nil
76+
return &localPlanFilePath, nil
7677
}
7778

78-
func (gps *GithubPlanStorage) StorePlan(planFileName string) error {
79-
_ = fmt.Sprintf("Skipping storing plan %s. It should be achieved using actions/upload-artifact@v3", planFileName)
79+
func (psg *PlanStorageGcp) DeleteStoredPlan(storedPlanFilePath string) error {
80+
obj := psg.Bucket.Object(storedPlanFilePath)
81+
err := obj.Delete(psg.Context)
82+
83+
if err != nil {
84+
return fmt.Errorf("unable to delete file '%v' from bucket: %v", storedPlanFilePath, err)
85+
}
8086
return nil
8187
}
8288

83-
func (gps *GithubPlanStorage) RetrievePlan(planFileName string) (*string, error) {
89+
func (gps *GithubPlanStorage) StorePlan(localPlanFilePath string, storedPlanFilePath string) error {
90+
_ = fmt.Sprintf("Skipping storing plan %s. It should be achieved using actions/upload-artifact@v3", localPlanFilePath)
91+
return nil
92+
}
93+
94+
func (gps *GithubPlanStorage) RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error) {
8495
plansFilename, err := gps.DownloadLatestPlans()
8596

8697
if err != nil {
@@ -91,14 +102,18 @@ func (gps *GithubPlanStorage) RetrievePlan(planFileName string) (*string, error)
91102
return nil, fmt.Errorf("no plans found for this PR")
92103
}
93104

94-
plansFilename, err = gps.ZipManager.GetFileFromZip(plansFilename, planFileName)
105+
plansFilename, err = gps.ZipManager.GetFileFromZip(plansFilename, storedPlanFilePath)
95106

96107
if err != nil {
97108
return nil, fmt.Errorf("error extracting plan: %v", err)
98109
}
99110
return &plansFilename, nil
100111
}
101112

113+
func (gps *GithubPlanStorage) DeleteStoredPlan(storedPlanFilePath string) error {
114+
return nil
115+
}
116+
102117
func (gps *GithubPlanStorage) DownloadLatestPlans() (string, error) {
103118
artifacts, _, err := gps.Client.Actions.ListArtifacts(context.Background(), gps.Owner, gps.RepoName, &github.ListOptions{
104119
PerPage: 100,

0 commit comments

Comments
 (0)