Skip to content

Commit 562a65c

Browse files
authored
also append resource summary to apply output (#1708)
* also append resource summary to apply output
1 parent 1bf28cf commit 562a65c

File tree

11 files changed

+111
-65
lines changed

11 files changed

+111
-65
lines changed

backend/controllers/projects.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ func RunHistoryForProject(c *gin.Context) {
319319
type SetJobStatusRequest struct {
320320
Status string `json:"status"`
321321
Timestamp time.Time `json:"timestamp"`
322-
JobSummary *terraform_utils.PlanSummary `json:"job_summary"`
322+
JobSummary *terraform_utils.TerraformSummary `json:"job_summary"`
323323
Footprint *terraform_utils.TerraformPlanFootprint `json:"job_plan_footprint"`
324324
PrCommentUrl string `json:"pr_comment_url"`
325325
TerraformOutput string `json:"terraform_output""`

cli/pkg/digger/digger.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,13 @@ func RunJobs(jobs []orchestrator.Job, prService ci.PullRequestService, orgServic
135135
projectNameForBackendReporting := currentJob.ProjectName
136136
// TODO: handle the apply result summary as well to report it to backend. Possibly reporting changed resources as well
137137
// Some kind of generic terraform operation summary might need to be introduced
138-
var planResult *execution.DiggerExecutorPlanResult = nil
139-
if exectorResults[0].PlanResult != nil {
140-
planResult = exectorResults[0].PlanResult
141-
}
138+
summary := exectorResults[0].GetTerraformSummary()
142139
terraformOutput := ""
143140
if reportTerraformOutput {
144141
terraformOutput = exectorResults[0].TerraformOutput
145142
}
146143
prNumber := *currentJob.PullRequestNumber
147-
batchResult, err := backendApi.ReportProjectJobStatus(repoNameForBackendReporting, projectNameForBackendReporting, jobId, "succeeded", time.Now(), planResult, jobPrCommentUrl, terraformOutput)
144+
batchResult, err := backendApi.ReportProjectJobStatus(repoNameForBackendReporting, projectNameForBackendReporting, jobId, "succeeded", time.Now(), &summary, "", jobPrCommentUrl, terraformOutput)
148145
if err != nil {
149146
log.Printf("error reporting Job status: %v.\n", err)
150147
return false, false, fmt.Errorf("error while running command: %v", err)
@@ -328,6 +325,7 @@ func run(command string, job orchestrator.Job, policyChecker policy.Checker, org
328325
return nil, msg, fmt.Errorf(msg)
329326
}
330327
result := execution.DiggerExecutorResult{
328+
OperationType: execution.DiggerOparationTypePlan,
331329
TerraformOutput: plan,
332330
PlanResult: &execution.DiggerExecutorPlanResult{
333331
PlanSummary: *planSummary,
@@ -404,7 +402,7 @@ func run(command string, job orchestrator.Job, policyChecker policy.Checker, org
404402

405403
// Running apply
406404

407-
applyPerformed, output, err := diggerExecutor.Apply()
405+
applySummary, applyPerformed, output, err := diggerExecutor.Apply()
408406
if err != nil {
409407
//TODO reuse executor error handling
410408
log.Printf("Failed to Run digger apply command. %v", err)
@@ -424,8 +422,11 @@ func run(command string, job orchestrator.Job, policyChecker policy.Checker, org
424422
appliesPerProject[job.ProjectName] = true
425423
}
426424
result := execution.DiggerExecutorResult{
425+
OperationType: execution.DiggerOparationTypeApply,
427426
TerraformOutput: output,
428-
ApplyResult: &execution.DiggerExecutorApplyResult{},
427+
ApplyResult: &execution.DiggerExecutorApplyResult{
428+
ApplySummary: *applySummary,
429+
},
429430
}
430431
return &result, output, nil
431432
}
@@ -662,7 +663,7 @@ func RunJob(
662663
if err != nil {
663664
log.Printf("Failed to send usage report. %v", err)
664665
}
665-
_, output, err := diggerExecutor.Apply()
666+
_, _, output, err := diggerExecutor.Apply()
666667
if err != nil {
667668
msg := fmt.Sprintf("Failed to Run digger apply command. %v", err)
668669
log.Printf(msg)

cli/pkg/spec/spec.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
func reportError(spec spec.Spec, backendApi backend2.Api, message string, err error) {
1919
log.Printf(message)
20-
_, reportingError := backendApi.ReportProjectJobStatus(spec.VCS.RepoName, spec.Job.ProjectName, spec.JobId, "failed", time.Now(), nil, "", "")
20+
_, reportingError := backendApi.ReportProjectJobStatus(spec.VCS.RepoName, spec.Job.ProjectName, spec.JobId, "failed", time.Now(), nil, "", "", "")
2121
if reportingError != nil {
2222
usage.ReportErrorAndExit(spec.VCS.RepoOwner, fmt.Sprintf("Failed to run commands. %v", err), 5)
2323
}
@@ -131,7 +131,7 @@ func RunSpec(
131131
jobs := []scheduler.Job{job}
132132

133133
fullRepoName := fmt.Sprintf("%v-%v", spec.VCS.RepoOwner, spec.VCS.RepoName)
134-
_, err = backendApi.ReportProjectJobStatus(fullRepoName, spec.Job.ProjectName, spec.JobId, "started", time.Now(), nil, "", "")
134+
_, err = backendApi.ReportProjectJobStatus(fullRepoName, spec.Job.ProjectName, spec.JobId, "started", time.Now(), nil, "", "", "")
135135
if err != nil {
136136
message := fmt.Sprintf("Failed to report jobSpec status to backend. Exiting. %v", err)
137137
reportError(spec, backendApi, message, err)
@@ -152,7 +152,7 @@ func RunSpec(
152152
reportTerraformOutput := spec.Reporter.ReportTerraformOutput
153153
allAppliesSuccess, _, err := digger.RunJobs(jobs, prService, orgService, lock, reporter, planStorage, policyChecker, commentUpdater, backendApi, spec.JobId, true, reportTerraformOutput, commentId, currentDir)
154154
if !allAppliesSuccess || err != nil {
155-
serializedBatch, reportingError := backendApi.ReportProjectJobStatus(spec.VCS.RepoName, spec.Job.ProjectName, spec.JobId, "failed", time.Now(), nil, "", "")
155+
serializedBatch, reportingError := backendApi.ReportProjectJobStatus(spec.VCS.RepoName, spec.Job.ProjectName, spec.JobId, "failed", time.Now(), nil, "", "", "")
156156
if reportingError != nil {
157157
message := fmt.Sprintf("Failed run commands. %s", err)
158158
reportError(spec, backendApi, message, err)

libs/backendapi/backend.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package backendapi
22

33
import (
4-
"github.com/diggerhq/digger/libs/execution"
54
"github.com/diggerhq/digger/libs/scheduler"
5+
"github.com/diggerhq/digger/libs/terraform_utils"
66
"time"
77
)
88

99
type Api interface {
1010
ReportProject(repo string, projectName string, configuration string) error
1111
ReportProjectRun(repo string, projectName string, startedAt time.Time, endedAt time.Time, status string, command string, output string) error
12-
ReportProjectJobStatus(repo string, projectName string, jobId string, status string, timestamp time.Time, summary *execution.DiggerExecutorPlanResult, PrCommentUrl string, terraformOutput string) (*scheduler.SerializedBatch, error)
12+
ReportProjectJobStatus(repo string, projectName string, jobId string, status string, timestamp time.Time, summary *terraform_utils.TerraformSummary, planJson string, PrCommentUrl string, terraformOutput string) (*scheduler.SerializedBatch, error)
1313
UploadJobArtefact(zipLocation string) (*int, *string, error)
1414
DownloadJobArtefact(downloadTo string) (*string, error)
1515
}

libs/backendapi/diggerapi.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"encoding/json"
66
"fmt"
7-
"github.com/diggerhq/digger/libs/execution"
87
"github.com/diggerhq/digger/libs/scheduler"
98
"github.com/diggerhq/digger/libs/terraform_utils"
109
"io"
@@ -30,7 +29,7 @@ func (n NoopApi) ReportProjectRun(namespace string, projectName string, startedA
3029
return nil
3130
}
3231

33-
func (n NoopApi) ReportProjectJobStatus(repo string, projectName string, jobId string, status string, timestamp time.Time, summary *execution.DiggerExecutorPlanResult, PrCommentUrl string, terraformOutput string) (*scheduler.SerializedBatch, error) {
32+
func (n NoopApi) ReportProjectJobStatus(repo string, projectName string, jobId string, status string, timestamp time.Time, summary *terraform_utils.TerraformSummary, planJson string, PrCommentUrl string, terraformOutput string) (*scheduler.SerializedBatch, error) {
3433
return nil, nil
3534
}
3635

@@ -130,26 +129,26 @@ func (d DiggerApi) ReportProjectRun(namespace string, projectName string, starte
130129
return nil
131130
}
132131

133-
func (d DiggerApi) ReportProjectJobStatus(repo string, projectName string, jobId string, status string, timestamp time.Time, planResult *execution.DiggerExecutorPlanResult, PrCommentUrl string, terraformOutput string) (*scheduler.SerializedBatch, error) {
132+
func (d DiggerApi) ReportProjectJobStatus(repo string, projectName string, jobId string, status string, timestamp time.Time, summary *terraform_utils.TerraformSummary, planJson string, PrCommentUrl string, terraformOutput string) (*scheduler.SerializedBatch, error) {
134133
u, err := url.Parse(d.DiggerHost)
135134
if err != nil {
136135
log.Fatalf("Not able to parse digger cloud url: %v", err)
137136
}
138137

139138
var planSummaryJson interface{}
140-
var planFootprint *terraform_utils.TerraformPlanFootprint
141-
if planResult == nil {
139+
var planFootprint *terraform_utils.TerraformPlanFootprint = &terraform_utils.TerraformPlanFootprint{}
140+
if summary == nil {
142141
log.Printf("Warning: nil passed to plan result, sending empty")
143142
planSummaryJson = nil
144143
planFootprint = nil
145144
} else {
146-
planJson := planResult.TerraformJson
147-
planSummary := planResult.PlanSummary
145+
planSummary := summary
148146
planSummaryJson = planSummary.ToJson()
149-
planFootprint, err = terraform_utils.GetPlanFootprint(planJson)
150-
if err != nil {
151-
log.Printf("Error, could not get footprint from json plan: %v", err)
152-
return nil, fmt.Errorf("error, could not get footprint from json plan: %v", err)
147+
if planJson != "" {
148+
planFootprint, err = terraform_utils.GetPlanFootprint(planJson)
149+
if err != nil {
150+
log.Printf("Error, could not get footprint from json plan: %v", err)
151+
}
153152
}
154153
}
155154

libs/backendapi/mocks.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package backendapi
22

33
import (
4-
"github.com/diggerhq/digger/libs/execution"
54
"github.com/diggerhq/digger/libs/scheduler"
5+
"github.com/diggerhq/digger/libs/terraform_utils"
66
"time"
77
)
88

@@ -17,7 +17,7 @@ func (t MockBackendApi) ReportProjectRun(repo string, projectName string, starte
1717
return nil
1818
}
1919

20-
func (t MockBackendApi) ReportProjectJobStatus(repo string, projectName string, jobId string, status string, timestamp time.Time, summary *execution.DiggerExecutorPlanResult, PrCommentUrl string, terraformOutput string) (*scheduler.SerializedBatch, error) {
20+
func (t MockBackendApi) ReportProjectJobStatus(repo string, projectName string, jobId string, status string, timestamp time.Time, summary *terraform_utils.TerraformSummary, planJson string, PrCommentUrl string, terraformOutput string) (*scheduler.SerializedBatch, error) {
2121
return nil, nil
2222
}
2323

libs/comment_utils/summary/updater.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,15 @@ func (b BasicCommentUpdater) UpdateComment(jobs []scheduler.SerializedJob, prNum
2424
}
2525
firstJobSpec := jobSpecs[0]
2626
jobType := firstJobSpec.JobType
27-
isPlan := jobType == string(scheduler.DiggerCommandPlan)
2827
jobTypeTitle := cases.Title(language.AmericanEnglish).String(string(jobType))
2928
message := ""
30-
if isPlan {
31-
message = message + fmt.Sprintf("| Project | Status | %v | + | ~ | - |\n", jobTypeTitle)
32-
message = message + fmt.Sprintf("|---------|--------|------|---|---|---|\n")
33-
} else {
34-
message = message + fmt.Sprintf("| Project | Status | %v |\n", jobTypeTitle)
35-
message = message + fmt.Sprintf("|---------|--------|-------|\n")
36-
}
29+
message = message + fmt.Sprintf("| Project | Status | %v | + | ~ | - |\n", jobTypeTitle)
30+
message = message + fmt.Sprintf("|---------|--------|------|---|---|---|\n")
31+
3732
for i, job := range jobs {
3833
jobSpec := jobSpecs[i]
3934
prCommentUrl := job.PRCommentUrl
40-
if isPlan {
41-
message = message + fmt.Sprintf("|%v **%v** |<a href='%v'>%v</a> | <a href='%v'>%v</a> | %v | %v | %v|\n", job.Status.ToEmoji(), jobSpec.ProjectName, *job.WorkflowRunUrl, job.Status.ToString(), prCommentUrl, jobTypeTitle, job.ResourcesCreated, job.ResourcesUpdated, job.ResourcesDeleted)
42-
} else {
43-
message = message + fmt.Sprintf("|%v **%v** |<a href='%v'>%v</a> | <a href='%v'>%v</a> |\n", job.Status.ToEmoji(), jobSpec.ProjectName, *job.WorkflowRunUrl, job.Status.ToString(), prCommentUrl, jobTypeTitle)
44-
}
35+
message = message + fmt.Sprintf("|%v **%v** |<a href='%v'>%v</a> | <a href='%v'>%v</a> | %v | %v | %v|\n", job.Status.ToEmoji(), jobSpec.ProjectName, *job.WorkflowRunUrl, job.Status.ToString(), prCommentUrl, jobTypeTitle, job.ResourcesCreated, job.ResourcesUpdated, job.ResourcesDeleted)
4536
}
4637

4738
prService.EditComment(prNumber, prCommentId, message)

libs/execution/execution.go

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import (
2020
)
2121

2222
type Executor interface {
23-
Plan() (*terraform_utils.PlanSummary, bool, bool, string, string, error)
24-
Apply() (bool, string, error)
23+
Plan() (*terraform_utils.TerraformSummary, bool, bool, string, string, error)
24+
Apply() (*terraform_utils.TerraformSummary, bool, string, error)
2525
Destroy() (bool, error)
2626
}
2727

@@ -30,7 +30,7 @@ type LockingExecutorWrapper struct {
3030
Executor Executor
3131
}
3232

33-
func (l LockingExecutorWrapper) Plan() (*terraform_utils.PlanSummary, bool, bool, string, string, error) {
33+
func (l LockingExecutorWrapper) Plan() (*terraform_utils.TerraformSummary, bool, bool, string, string, error) {
3434
plan := ""
3535
locked, err := l.ProjectLock.Lock()
3636
if err != nil {
@@ -44,17 +44,17 @@ func (l LockingExecutorWrapper) Plan() (*terraform_utils.PlanSummary, bool, bool
4444
}
4545
}
4646

47-
func (l LockingExecutorWrapper) Apply() (bool, string, error) {
47+
func (l LockingExecutorWrapper) Apply() (*terraform_utils.TerraformSummary, bool, string, error) {
4848
locked, err := l.ProjectLock.Lock()
4949
if err != nil {
5050
msg := fmt.Sprintf("digger apply, error locking project: %v", err)
51-
return false, msg, fmt.Errorf(msg)
51+
return nil, false, msg, fmt.Errorf(msg)
5252
}
5353
log.Printf("Lock result: %t\n", locked)
5454
if locked {
5555
return l.Executor.Apply()
5656
} else {
57-
return false, "couldn't lock ", nil
57+
return nil, false, "couldn't lock ", nil
5858
}
5959
}
6060

@@ -103,20 +103,37 @@ type DiggerExecutor struct {
103103
PlanPathProvider PlanPathProvider
104104
}
105105

106+
type DiggerOperationType string
107+
108+
var DiggerOparationTypePlan DiggerOperationType = "plan"
109+
var DiggerOparationTypeApply DiggerOperationType = "apply"
110+
106111
type DiggerExecutorResult struct {
112+
OperationType DiggerOperationType
107113
TerraformOutput string
108114
PlanResult *DiggerExecutorPlanResult
109115
ApplyResult *DiggerExecutorApplyResult
110116
}
111117

112118
type DiggerExecutorApplyResult struct {
119+
ApplySummary terraform_utils.TerraformSummary
113120
}
114121

115122
type DiggerExecutorPlanResult struct {
116-
PlanSummary terraform_utils.PlanSummary
123+
PlanSummary terraform_utils.TerraformSummary
117124
TerraformJson string
118125
}
119126

127+
func (d DiggerExecutorResult) GetTerraformSummary() terraform_utils.TerraformSummary {
128+
var summary terraform_utils.TerraformSummary
129+
if d.OperationType == DiggerOparationTypePlan && d.PlanResult != nil {
130+
summary = d.PlanResult.PlanSummary
131+
} else if d.OperationType == DiggerOparationTypeApply && d.ApplyResult != nil {
132+
summary = d.ApplyResult.ApplySummary
133+
}
134+
return summary
135+
}
136+
120137
type PlanPathProvider interface {
121138
LocalPlanFilePath() string
122139
StoredPlanFilePath() string
@@ -180,10 +197,10 @@ func (d DiggerExecutor) RetrievePlanJson() (string, error) {
180197
}
181198
}
182199

183-
func (d DiggerExecutor) Plan() (*terraform_utils.PlanSummary, bool, bool, string, string, error) {
200+
func (d DiggerExecutor) Plan() (*terraform_utils.TerraformSummary, bool, bool, string, string, error) {
184201
plan := ""
185202
terraformPlanOutput := ""
186-
planSummary := &terraform_utils.PlanSummary{}
203+
planSummary := &terraform_utils.TerraformSummary{}
187204
isEmptyPlan := true
188205
var planSteps []scheduler.Step
189206

@@ -217,7 +234,7 @@ func (d DiggerExecutor) Plan() (*terraform_utils.PlanSummary, bool, bool, string
217234
showArgs := []string{"-no-color", "-json", d.PlanPathProvider.LocalPlanFilePath()}
218235
terraformPlanOutput, _, _ = d.TerraformExecutor.Show(showArgs, d.CommandEnvVars)
219236

220-
isEmptyPlan, planSummary, err = terraform_utils.GetPlanSummary(terraformPlanOutput)
237+
isEmptyPlan, planSummary, err = terraform_utils.GetSummaryFromPlanJson(terraformPlanOutput)
221238
if err != nil {
222239
return nil, false, false, "", "", fmt.Errorf("error checking for empty plan: %v", err)
223240
}
@@ -284,14 +301,15 @@ func reportError(r reporting.Reporter, stderr string) {
284301
}
285302
}
286303

287-
func (d DiggerExecutor) Apply() (bool, string, error) {
304+
func (d DiggerExecutor) Apply() (*terraform_utils.TerraformSummary, bool, string, error) {
288305
var applyOutput string
289306
var plansFilename *string
307+
summary := terraform_utils.TerraformSummary{}
290308
if d.PlanStorage != nil {
291309
var err error
292310
plansFilename, err = d.PlanStorage.RetrievePlan(d.PlanPathProvider.LocalPlanFilePath(), d.PlanPathProvider.ArtifactName(), d.PlanPathProvider.StoredPlanFilePath())
293311
if err != nil {
294-
return false, "", fmt.Errorf("error retrieving plan: %v", err)
312+
return nil, false, "", fmt.Errorf("error retrieving plan: %v", err)
295313
}
296314
}
297315

@@ -315,18 +333,24 @@ func (d DiggerExecutor) Apply() (bool, string, error) {
315333
stdout, stderr, err := d.TerraformExecutor.Init(step.ExtraArgs, d.StateEnvVars)
316334
if err != nil {
317335
reportTerraformError(d.Reporter, stderr)
318-
return false, stdout, fmt.Errorf("error running init: %v", err)
336+
return nil, false, stdout, fmt.Errorf("error running init: %v", err)
319337
}
320338
}
321339
if step.Action == "apply" {
322340
applyArgs := []string{"-lock-timeout=3m"}
323341
applyArgs = append(applyArgs, step.ExtraArgs...)
324342
stdout, stderr, err := d.TerraformExecutor.Apply(applyArgs, plansFilename, d.CommandEnvVars)
325343
applyOutput = cleanupTerraformApply(true, err, stdout, stderr)
344+
326345
reportTerraformApplyOutput(d.Reporter, d.projectId(), applyOutput)
327346
if err != nil {
328347
reportApplyError(d.Reporter, err)
329-
return false, stdout, fmt.Errorf("error executing apply: %v", err)
348+
return nil, false, stdout, fmt.Errorf("error executing apply: %v", err)
349+
}
350+
351+
summary, err = terraform_utils.GetSummaryFromTerraformApplyOutput(stdout)
352+
if err != nil {
353+
log.Printf("Warning: get summary from apply output failed: %v", err)
330354
}
331355
}
332356
if step.Action == "run" {
@@ -338,12 +362,12 @@ func (d DiggerExecutor) Apply() (bool, string, error) {
338362
log.Printf("Running %v for **%v**\n", step.Value, d.ProjectNamespace+"#"+d.ProjectName)
339363
_, stderr, err := d.CommandRunner.Run(d.ProjectPath, step.Shell, commands, d.RunEnvVars)
340364
if err != nil {
341-
return false, stderr, fmt.Errorf("error running command: %v", err)
365+
return nil, false, stderr, fmt.Errorf("error running command: %v", err)
342366
}
343367
}
344368
}
345369
reportAdditionalOutput(d.Reporter, d.projectId())
346-
return true, applyOutput, nil
370+
return &summary, true, applyOutput, nil
347371
}
348372

349373
func reportApplyError(r reporting.Reporter, err error) {

0 commit comments

Comments
 (0)