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

Skip to content

Commit 6606e01

Browse files
committed
The full end-to-end operation works
1 parent 0a83477 commit 6606e01

File tree

9 files changed

+68
-22
lines changed

9 files changed

+68
-22
lines changed

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
"retrier",
4545
"sdkproto",
4646
"stretchr",
47+
"tfexec",
48+
"tfstate",
4749
"unconvert",
4850
"xerrors",
4951
"yamux"

coderd/coderdtest/coderdtest.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ func (s *Server) AddProvisionerd(t *testing.T) io.Closer {
7878
ServeOptions: &provisionersdk.ServeOptions{
7979
Listener: tfServer,
8080
},
81+
Logger: slogtest.Make(t, nil).Named("terraform-provisioner").Leveled(slog.LevelDebug),
8182
})
8283
require.NoError(t, err)
8384
}()
@@ -101,6 +102,7 @@ func (s *Server) AddProvisionerd(t *testing.T) io.Closer {
101102
func New(t *testing.T) Server {
102103
// This can be hotswapped for a live database instance.
103104
db := databasefake.New()
105+
pubsub := database.NewPubsubInMemory()
104106
if os.Getenv("DB") != "" {
105107
connectionURL, close, err := postgres.Open()
106108
require.NoError(t, err)
@@ -113,11 +115,15 @@ func New(t *testing.T) Server {
113115
err = database.Migrate(sqlDB)
114116
require.NoError(t, err)
115117
db = database.New(sqlDB)
118+
119+
pubsub, err = database.NewPubsub(context.Background(), sqlDB, connectionURL)
120+
require.NoError(t, err)
116121
}
117122

118123
handler := coderd.New(&coderd.Options{
119124
Logger: slogtest.Make(t, nil),
120125
Database: db,
126+
Pubsub: pubsub,
121127
})
122128
srv := httptest.NewServer(handler)
123129
serverURL, err := url.Parse(srv.URL)

coderd/provisionerdaemons.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,10 @@ func (api *api) provisionerDaemonsServe(rw http.ResponseWriter, r *http.Request)
7676
}
7777
mux := drpcmux.New()
7878
err = proto.DRPCRegisterProvisionerDaemon(mux, &provisionerdServer{
79-
ID: daemon.ID,
80-
Database: api.Database,
81-
Pubsub: api.Pubsub,
79+
ID: daemon.ID,
80+
Database: api.Database,
81+
Pubsub: api.Pubsub,
82+
Provisioners: daemon.Provisioners,
8283
})
8384
if err != nil {
8485
_ = conn.Close(websocket.StatusInternalError, fmt.Sprintf("drpc register provisioner daemon: %s", err))
@@ -103,9 +104,10 @@ type projectImportJob struct {
103104

104105
// Implementation of the provisioner daemon protobuf server.
105106
type provisionerdServer struct {
106-
ID uuid.UUID
107-
Database database.Store
108-
Pubsub database.Pubsub
107+
ID uuid.UUID
108+
Provisioners []database.ProvisionerType
109+
Database database.Store
110+
Pubsub database.Pubsub
109111
}
110112

111113
// AcquireJob queries the database to lock a job.
@@ -120,7 +122,7 @@ func (server *provisionerdServer) AcquireJob(ctx context.Context, _ *proto.Empty
120122
UUID: server.ID,
121123
Valid: true,
122124
},
123-
Types: []database.ProvisionerType{database.ProvisionerTypeTerraform},
125+
Types: server.Provisioners,
124126
})
125127
if errors.Is(err, sql.ErrNoRows) {
126128
// The provisioner daemon assumes no jobs are available if

coderd/workspacehistory.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func (api *api) postWorkspaceHistoryByUser(rw http.ResponseWriter, r *http.Reque
144144
}
145145

146146
workspaceHistory, err = db.InsertWorkspaceHistory(r.Context(), database.InsertWorkspaceHistoryParams{
147-
ID: uuid.New(),
147+
ID: workspaceHistoryID,
148148
CreatedAt: database.Now(),
149149
UpdatedAt: database.Now(),
150150
WorkspaceID: workspace.ID,

coderd/workspacehistory_test.go

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,18 @@ func TestWorkspaceHistory(t *testing.T) {
3636
setupProjectHistory := func(t *testing.T, client *codersdk.Client, user coderd.CreateInitialUserRequest, project coderd.Project, files map[string]string) coderd.ProjectHistory {
3737
var buffer bytes.Buffer
3838
writer := tar.NewWriter(&buffer)
39-
err := writer.WriteHeader(&tar.Header{
40-
Name: "file",
41-
Size: 1 << 10,
42-
})
43-
require.NoError(t, err)
44-
_, err = writer.Write(make([]byte, 1<<10))
39+
for path, content := range files {
40+
err := writer.WriteHeader(&tar.Header{
41+
Name: path,
42+
Size: int64(len(content)),
43+
})
44+
require.NoError(t, err)
45+
_, err = writer.Write([]byte(content))
46+
require.NoError(t, err)
47+
}
48+
err := writer.Flush()
4549
require.NoError(t, err)
50+
4651
projectHistory, err := client.CreateProjectHistory(context.Background(), user.Organization, project.Name, coderd.CreateProjectHistoryRequest{
4752
StorageMethod: database.ProjectStorageMethodInlineArchive,
4853
StorageSource: buffer.Bytes(),
@@ -65,7 +70,9 @@ func TestWorkspaceHistory(t *testing.T) {
6570
history, err := server.Client.ListWorkspaceHistory(context.Background(), "", workspace.Name)
6671
require.NoError(t, err)
6772
require.Len(t, history, 0)
68-
projectVersion := setupProjectHistory(t, server.Client, user, project, map[string]string{})
73+
projectVersion := setupProjectHistory(t, server.Client, user, project, map[string]string{
74+
"example": "file",
75+
})
6976
_, err = server.Client.CreateWorkspaceHistory(context.Background(), "", workspace.Name, coderd.CreateWorkspaceHistoryRequest{
7077
ProjectHistoryID: projectVersion.ID,
7178
Transition: database.WorkspaceTransitionCreate,
@@ -84,7 +91,9 @@ func TestWorkspaceHistory(t *testing.T) {
8491
project, workspace := setupProjectAndWorkspace(t, server.Client, user)
8592
_, err := server.Client.WorkspaceHistory(context.Background(), "", workspace.Name, "")
8693
require.Error(t, err)
87-
projectHistory := setupProjectHistory(t, server.Client, user, project, map[string]string{})
94+
projectHistory := setupProjectHistory(t, server.Client, user, project, map[string]string{
95+
"some": "file",
96+
})
8897
_, err = server.Client.CreateWorkspaceHistory(context.Background(), "", workspace.Name, coderd.CreateWorkspaceHistoryRequest{
8998
ProjectHistoryID: projectHistory.ID,
9099
Transition: database.WorkspaceTransitionCreate,
@@ -100,12 +109,23 @@ func TestWorkspaceHistory(t *testing.T) {
100109
_ = server.AddProvisionerd(t)
101110
user := server.RandomInitialUser(t)
102111
project, workspace := setupProjectAndWorkspace(t, server.Client, user)
103-
projectHistory := setupProjectHistory(t, server.Client, user, project, map[string]string{})
112+
projectHistory := setupProjectHistory(t, server.Client, user, project, map[string]string{
113+
"main.tf": `resource "null_resource" "example" {}`,
114+
})
104115
_, err := server.Client.CreateWorkspaceHistory(context.Background(), "", workspace.Name, coderd.CreateWorkspaceHistoryRequest{
105116
ProjectHistoryID: projectHistory.ID,
106117
Transition: database.WorkspaceTransitionCreate,
107118
})
108119
require.NoError(t, err)
120+
121+
var workspaceHistory coderd.WorkspaceHistory
122+
require.Eventually(t, func() bool {
123+
workspaceHistory, err = server.Client.WorkspaceHistory(context.Background(), "", workspace.Name, "")
124+
require.NoError(t, err)
125+
return workspaceHistory.Provision.Status.Completed()
126+
}, 5*time.Second, 50*time.Millisecond)
127+
require.Equal(t, "", workspaceHistory.Provision.Error)
128+
require.Equal(t, coderd.ProvisionerJobStatusSucceeded, workspaceHistory.Provision.Status)
109129
})
110130

111131
t.Run("CreateHistoryAlreadyInProgress", func(t *testing.T) {
@@ -114,7 +134,9 @@ func TestWorkspaceHistory(t *testing.T) {
114134
_ = server.AddProvisionerd(t)
115135
user := server.RandomInitialUser(t)
116136
project, workspace := setupProjectAndWorkspace(t, server.Client, user)
117-
projectHistory := setupProjectHistory(t, server.Client, user, project, map[string]string{})
137+
projectHistory := setupProjectHistory(t, server.Client, user, project, map[string]string{
138+
"some": "content",
139+
})
118140

119141
_, err := server.Client.CreateWorkspaceHistory(context.Background(), "", workspace.Name, coderd.CreateWorkspaceHistoryRequest{
120142
ProjectHistoryID: projectHistory.ID,

codersdk/projects_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func TestProjects(t *testing.T) {
7171
require.NoError(t, err)
7272
})
7373

74-
t.Run("UnauthenticatedHistorys", func(t *testing.T) {
74+
t.Run("UnauthenticatedHistory", func(t *testing.T) {
7575
t.Parallel()
7676
server := coderdtest.New(t)
7777
_, err := server.Client.ListProjectHistory(context.Background(), "org", "project")

provisioner/terraform/provision.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ func (t *terraform) Provision(request *proto.Provision_Request, stream proto.DRP
3838
return xerrors.Errorf("terraform version %q is too old. required >= %q", version.String(), minimumTerraformVersion.String())
3939
}
4040

41+
env := map[string]string{
42+
// Makes sequential runs significantly faster.
43+
// https://github.com/hashicorp/terraform/blob/d35bc0531255b496beb5d932f185cbcdb2d61a99/internal/command/cliconfig/cliconfig.go#L24
44+
"TF_PLUGIN_CACHE_DIR": os.ExpandEnv("$HOME/.terraform.d/plugin-cache"),
45+
}
46+
4147
reader, writer := io.Pipe()
4248
defer reader.Close()
4349
defer writer.Close()
@@ -55,12 +61,13 @@ func (t *terraform) Provision(request *proto.Provision_Request, stream proto.DRP
5561
}
5662
}()
5763
terraform.SetStdout(writer)
64+
t.logger.Debug(ctx, "running initialization")
5865
err = terraform.Init(ctx)
5966
if err != nil {
6067
return xerrors.Errorf("initialize terraform: %w", err)
6168
}
69+
t.logger.Debug(ctx, "ran initialization")
6270

63-
env := map[string]string{}
6471
options := []tfexec.ApplyOption{tfexec.JSON(true)}
6572
for _, param := range request.ParameterValues {
6673
switch param.DestinationScheme {
@@ -124,10 +131,12 @@ func (t *terraform) Provision(request *proto.Provision_Request, stream proto.DRP
124131
}()
125132

126133
terraform.SetStdout(writer)
134+
t.logger.Debug(ctx, "running apply")
127135
err = terraform.Apply(ctx, options...)
128136
if err != nil {
129137
return xerrors.Errorf("apply terraform: %w", err)
130138
}
139+
t.logger.Debug(ctx, "ran apply")
131140

132141
statefileContent, err := os.ReadFile(statefilePath)
133142
if err != nil {

provisioner/terraform/serve.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"github.com/hashicorp/go-version"
88
"golang.org/x/xerrors"
99

10+
"cdr.dev/slog"
11+
1012
"github.com/coder/coder/provisionersdk"
1113
)
1214

@@ -29,6 +31,7 @@ type ServeOptions struct {
2931
// BinaryPath specifies the "terraform" binary to use.
3032
// If omitted, the $PATH will attempt to find it.
3133
BinaryPath string
34+
Logger slog.Logger
3235
}
3336

3437
// Serve starts a dRPC server on the provided transport speaking Terraform provisioner.
@@ -43,9 +46,11 @@ func Serve(ctx context.Context, options *ServeOptions) error {
4346

4447
return provisionersdk.Serve(ctx, &terraform{
4548
binaryPath: options.BinaryPath,
49+
logger: options.Logger,
4650
}, options.ServeOptions)
4751
}
4852

4953
type terraform struct {
5054
binaryPath string
55+
logger slog.Logger
5156
}

provisionerd/provisionerd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ func (p *provisionerDaemon) runJob(ctx context.Context) {
239239
return
240240
}
241241

242-
err := os.MkdirAll(p.opts.WorkDirectory, 0600)
242+
err := os.MkdirAll(p.opts.WorkDirectory, 0700)
243243
if err != nil {
244244
p.cancelActiveJob(fmt.Sprintf("create work directory %q: %s", p.opts.WorkDirectory, err))
245245
return
@@ -277,7 +277,7 @@ func (p *provisionerDaemon) runJob(ctx context.Context) {
277277
case tar.TypeReg:
278278
file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, mode)
279279
if err != nil {
280-
p.cancelActiveJob(fmt.Sprintf("create file %q: %s", path, err))
280+
p.cancelActiveJob(fmt.Sprintf("create file %q (mode %s): %s", path, mode, err))
281281
return
282282
}
283283
// Max file size of 10MB.

0 commit comments

Comments
 (0)