Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5c77cdf

Browse files
committed
fix: persist terraform modules during template import (#17665)
1 parent 4970fb9 commit 5c77cdf

27 files changed

+587
-229
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ site/stats/
5050
*.tfplan
5151
*.lock.hcl
5252
.terraform/
53+
!provisioner/terraform/testdata/modules-source-caching/.terraform/
5354

5455
**/.coderv2/*
5556
**/__debug_bin

cli/testdata/coder_provisioner_list_--output_json.golden

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"last_seen_at": "====[timestamp]=====",
88
"name": "test",
99
"version": "v0.0.0-devel",
10-
"api_version": "1.4",
10+
"api_version": "1.5",
1111
"provisioners": [
1212
"echo"
1313
],

coderd/database/dbauthz/dbauthz.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,19 @@ import (
1212
"time"
1313

1414
"github.com/google/uuid"
15-
"golang.org/x/xerrors"
16-
1715
"github.com/open-policy-agent/opa/topdown"
16+
"golang.org/x/xerrors"
1817

1918
"cdr.dev/slog"
2019

21-
"github.com/coder/coder/v2/coderd/prebuilds"
22-
"github.com/coder/coder/v2/coderd/rbac/policy"
23-
"github.com/coder/coder/v2/coderd/rbac/rolestore"
24-
2520
"github.com/coder/coder/v2/coderd/database"
2621
"github.com/coder/coder/v2/coderd/database/dbtime"
2722
"github.com/coder/coder/v2/coderd/httpapi/httpapiconstraints"
2823
"github.com/coder/coder/v2/coderd/httpmw/loggermw"
24+
"github.com/coder/coder/v2/coderd/prebuilds"
2925
"github.com/coder/coder/v2/coderd/rbac"
26+
"github.com/coder/coder/v2/coderd/rbac/policy"
27+
"github.com/coder/coder/v2/coderd/rbac/rolestore"
3028
"github.com/coder/coder/v2/coderd/util/slice"
3129
"github.com/coder/coder/v2/provisionersdk"
3230
)
@@ -347,6 +345,7 @@ var (
347345
rbac.ResourceNotificationPreference.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete},
348346
rbac.ResourceNotificationTemplate.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete},
349347
rbac.ResourceCryptoKey.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete},
348+
rbac.ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
350349
}),
351350
Org: map[string][]rbac.Permission{},
352351
User: []rbac.Permission{},

coderd/database/dbgen/dbgen.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -999,9 +999,10 @@ func TemplateVersionTerraformValues(t testing.TB, db database.Store, orig databa
999999
t.Helper()
10001000

10011001
params := database.InsertTemplateVersionTerraformValuesByJobIDParams{
1002-
JobID: takeFirst(orig.JobID, uuid.New()),
1003-
CachedPlan: takeFirstSlice(orig.CachedPlan, []byte("{}")),
1004-
UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()),
1002+
JobID: takeFirst(orig.JobID, uuid.New()),
1003+
CachedPlan: takeFirstSlice(orig.CachedPlan, []byte("{}")),
1004+
CachedModuleFiles: orig.CachedModuleFiles,
1005+
UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()),
10051006
}
10061007

10071008
err := db.InsertTemplateVersionTerraformValuesByJobID(genCtx, params)

coderd/database/dbmem/dbmem.go

+1
Original file line numberDiff line numberDiff line change
@@ -9315,6 +9315,7 @@ func (q *FakeQuerier) InsertTemplateVersionTerraformValuesByJobID(_ context.Cont
93159315
row := database.TemplateVersionTerraformValue{
93169316
TemplateVersionID: templateVersion.ID,
93179317
CachedPlan: arg.CachedPlan,
9318+
CachedModuleFiles: arg.CachedModuleFiles,
93189319
UpdatedAt: arg.UpdatedAt,
93199320
}
93209321
q.templateVersionTerraformValues = append(q.templateVersionTerraformValues, row)

coderd/database/dump.sql

+5-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/foreign_key_constraint.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE template_version_terraform_values DROP COLUMN cached_module_files;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE template_version_terraform_values ADD COLUMN cached_module_files uuid references files(id);

coderd/database/models.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

+20-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/templateversionterraformvalues.sql

+2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ INSERT INTO
1111
template_version_terraform_values (
1212
template_version_id,
1313
cached_plan,
14+
cached_module_files,
1415
updated_at
1516
)
1617
VALUES
1718
(
1819
(select id from template_versions where job_id = @job_id),
1920
@cached_plan,
21+
@cached_module_files,
2022
@updated_at
2123
);

coderd/provisionerdserver/provisionerdserver.go

+59-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package provisionerdserver
22

33
import (
44
"context"
5+
"crypto/sha256"
56
"database/sql"
7+
"encoding/hex"
68
"encoding/json"
79
"errors"
810
"fmt"
@@ -50,6 +52,10 @@ import (
5052
sdkproto "github.com/coder/coder/v2/provisionersdk/proto"
5153
)
5254

55+
const (
56+
tarMimeType = "application/x-tar"
57+
)
58+
5359
const (
5460
// DefaultAcquireJobLongPollDur is the time the (deprecated) AcquireJob rpc waits to try to obtain a job before
5561
// canceling and returning an empty job.
@@ -1426,11 +1432,59 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob)
14261432
return nil, xerrors.Errorf("update template version external auth providers: %w", err)
14271433
}
14281434

1429-
if len(jobType.TemplateImport.Plan) > 0 {
1430-
err := s.Database.InsertTemplateVersionTerraformValuesByJobID(ctx, database.InsertTemplateVersionTerraformValuesByJobIDParams{
1431-
JobID: jobID,
1432-
CachedPlan: jobType.TemplateImport.Plan,
1433-
UpdatedAt: now,
1435+
plan := jobType.TemplateImport.Plan
1436+
moduleFiles := jobType.TemplateImport.ModuleFiles
1437+
// If there is a plan, or a module files archive we need to insert a
1438+
// template_version_terraform_values row.
1439+
if len(plan) > 0 || len(moduleFiles) > 0 {
1440+
// ...but the plan and the module files archive are both optional! So
1441+
// we need to fallback to a valid JSON object if the plan was omitted.
1442+
if len(plan) == 0 {
1443+
plan = []byte("{}")
1444+
}
1445+
1446+
// ...and we only want to insert a files row if an archive was provided.
1447+
var fileID uuid.NullUUID
1448+
if len(moduleFiles) > 0 {
1449+
hashBytes := sha256.Sum256(moduleFiles)
1450+
hash := hex.EncodeToString(hashBytes[:])
1451+
1452+
// nolint:gocritic // Requires reading "system" files
1453+
file, err := s.Database.GetFileByHashAndCreator(dbauthz.AsSystemRestricted(ctx), database.GetFileByHashAndCreatorParams{Hash: hash, CreatedBy: uuid.Nil})
1454+
switch {
1455+
case err == nil:
1456+
// This set of modules is already cached, which means we can reuse them
1457+
fileID = uuid.NullUUID{
1458+
Valid: true,
1459+
UUID: file.ID,
1460+
}
1461+
case !xerrors.Is(err, sql.ErrNoRows):
1462+
return nil, xerrors.Errorf("check for cached modules: %w", err)
1463+
default:
1464+
// nolint:gocritic // Requires creating a "system" file
1465+
file, err = s.Database.InsertFile(dbauthz.AsSystemRestricted(ctx), database.InsertFileParams{
1466+
ID: uuid.New(),
1467+
Hash: hash,
1468+
CreatedBy: uuid.Nil,
1469+
CreatedAt: dbtime.Now(),
1470+
Mimetype: tarMimeType,
1471+
Data: moduleFiles,
1472+
})
1473+
if err != nil {
1474+
return nil, xerrors.Errorf("insert template version terraform modules: %w", err)
1475+
}
1476+
fileID = uuid.NullUUID{
1477+
Valid: true,
1478+
UUID: file.ID,
1479+
}
1480+
}
1481+
}
1482+
1483+
err = s.Database.InsertTemplateVersionTerraformValuesByJobID(ctx, database.InsertTemplateVersionTerraformValuesByJobIDParams{
1484+
JobID: jobID,
1485+
UpdatedAt: now,
1486+
CachedPlan: plan,
1487+
CachedModuleFiles: fileID,
14341488
})
14351489
if err != nil {
14361490
return nil, xerrors.Errorf("insert template version terraform data: %w", err)

provisioner/echo/serve.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ var (
5252
PlanComplete = []*proto.Response{{
5353
Type: &proto.Response_Plan{
5454
Plan: &proto.PlanComplete{
55-
Plan: []byte("{}"),
55+
Plan: []byte("{}"),
56+
ModuleFiles: []byte{},
5657
},
5758
},
5859
}}
@@ -249,6 +250,7 @@ func TarWithOptions(ctx context.Context, logger slog.Logger, responses *Response
249250
Parameters: resp.GetApply().GetParameters(),
250251
ExternalAuthProviders: resp.GetApply().GetExternalAuthProviders(),
251252
Plan: []byte("{}"),
253+
ModuleFiles: []byte{},
252254
}},
253255
})
254256
}

provisioner/terraform/executor.go

+7
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,20 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
307307

308308
graphTimings.ingest(createGraphTimingsEvent(timingGraphComplete))
309309

310+
moduleFiles, err := getModulesArchive(e.workdir)
311+
if err != nil {
312+
// TODO: we probably want to persist this error or make it louder eventually
313+
e.logger.Warn(ctx, "failed to archive terraform modules", slog.Error(err))
314+
}
315+
310316
return &proto.PlanComplete{
311317
Parameters: state.Parameters,
312318
Resources: state.Resources,
313319
ExternalAuthProviders: state.ExternalAuthProviders,
314320
Timings: append(e.timings.aggregate(), graphTimings.aggregate()...),
315321
Presets: state.Presets,
316322
Plan: plan,
323+
ModuleFiles: moduleFiles,
317324
}, nil
318325
}
319326

0 commit comments

Comments
 (0)