Skip to content

Commit 358b7ec

Browse files
committed
Merge branch 'main' into parameters
2 parents d8b19ad + e75bde4 commit 358b7ec

36 files changed

+1531
-175
lines changed

.github/workflows/coder.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ jobs:
151151
- run: go install gotest.tools/gotestsum@latest
152152

153153
- uses: hashicorp/setup-terraform@v1
154-
if: runner.os == 'Linux'
155154
with:
156155
terraform_version: 1.1.2
157156
terraform_wrapper: false

.vscode/settings.json

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,29 @@
2727
"coderd",
2828
"coderdtest",
2929
"codersdk",
30+
"drpc",
31+
"drpcconn",
32+
"drpcmux",
33+
"drpcserver",
34+
"goleak",
35+
"hashicorp",
3036
"httpmw",
37+
"moby",
38+
"nhooyr",
3139
"nolint",
40+
"nosec",
3241
"oneof",
3342
"parameterscopeid",
43+
"protobuf",
44+
"provisionerd",
3445
"provisionersdk",
46+
"retrier",
47+
"sdkproto",
3548
"stretchr",
36-
"xerrors"
49+
"tfexec",
50+
"tfstate",
51+
"unconvert",
52+
"xerrors",
53+
"yamux"
3754
]
3855
}

coderd/cmd/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"cdr.dev/slog"
1212
"cdr.dev/slog/sloggers/sloghuman"
1313
"github.com/coder/coder/coderd"
14+
"github.com/coder/coder/database"
1415
"github.com/coder/coder/database/databasefake"
1516
)
1617

@@ -24,6 +25,7 @@ func Root() *cobra.Command {
2425
handler := coderd.New(&coderd.Options{
2526
Logger: slog.Make(sloghuman.Sink(os.Stderr)),
2627
Database: databasefake.New(),
28+
Pubsub: database.NewPubsubInMemory(),
2729
})
2830

2931
listener, err := net.Listen("tcp", address)

coderd/coderd.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ func New(options *Options) http.Handler {
6868
r.Route("/history", func(r chi.Router) {
6969
r.Get("/", api.projectHistoryByOrganization)
7070
r.Post("/", api.postProjectHistoryByOrganization)
71+
r.Route("/{projecthistory}", func(r chi.Router) {
72+
r.Use(httpmw.ExtractProjectHistoryParam(api.Database))
73+
r.Get("/", api.projectHistoryByOrganizationAndName)
74+
})
7175
})
7276
})
7377
})
@@ -88,11 +92,19 @@ func New(options *Options) http.Handler {
8892
r.Route("/history", func(r chi.Router) {
8993
r.Post("/", api.postWorkspaceHistoryByUser)
9094
r.Get("/", api.workspaceHistoryByUser)
91-
r.Get("/latest", api.latestWorkspaceHistoryByUser)
95+
r.Route("/{workspacehistory}", func(r chi.Router) {
96+
r.Use(httpmw.ExtractWorkspaceHistoryParam(options.Database))
97+
r.Get("/", api.workspaceHistoryByName)
98+
})
9299
})
93100
})
94101
})
95102
})
103+
104+
r.Route("/provisioners/daemons", func(r chi.Router) {
105+
r.Get("/", api.provisionerDaemons)
106+
r.Get("/serve", api.provisionerDaemonsServe)
107+
})
96108
})
97109
r.NotFound(site.Handler().ServeHTTP)
98110
return r

coderd/coderdtest/coderdtest.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,27 @@ package coderdtest
33
import (
44
"context"
55
"database/sql"
6+
"io"
67
"net/http/httptest"
78
"net/url"
89
"os"
910
"testing"
11+
"time"
1012

1113
"github.com/stretchr/testify/require"
1214

15+
"cdr.dev/slog"
1316
"cdr.dev/slog/sloggers/slogtest"
1417
"github.com/coder/coder/coderd"
1518
"github.com/coder/coder/codersdk"
1619
"github.com/coder/coder/cryptorand"
1720
"github.com/coder/coder/database"
1821
"github.com/coder/coder/database/databasefake"
1922
"github.com/coder/coder/database/postgres"
23+
"github.com/coder/coder/provisioner/terraform"
24+
"github.com/coder/coder/provisionerd"
25+
"github.com/coder/coder/provisionersdk"
26+
"github.com/coder/coder/provisionersdk/proto"
2027
)
2128

2229
// Server represents a test instance of coderd.
@@ -57,11 +64,46 @@ func (s *Server) RandomInitialUser(t *testing.T) coderd.CreateInitialUserRequest
5764
return req
5865
}
5966

67+
// AddProvisionerd launches a new provisionerd instance!
68+
func (s *Server) AddProvisionerd(t *testing.T) io.Closer {
69+
tfClient, tfServer := provisionersdk.TransportPipe()
70+
ctx, cancelFunc := context.WithCancel(context.Background())
71+
t.Cleanup(func() {
72+
_ = tfClient.Close()
73+
_ = tfServer.Close()
74+
cancelFunc()
75+
})
76+
go func() {
77+
err := terraform.Serve(ctx, &terraform.ServeOptions{
78+
ServeOptions: &provisionersdk.ServeOptions{
79+
Listener: tfServer,
80+
},
81+
Logger: slogtest.Make(t, nil).Named("terraform-provisioner").Leveled(slog.LevelDebug),
82+
})
83+
require.NoError(t, err)
84+
}()
85+
86+
closer := provisionerd.New(s.Client.ProvisionerDaemonClient, &provisionerd.Options{
87+
Logger: slogtest.Make(t, nil).Named("provisionerd").Leveled(slog.LevelDebug),
88+
PollInterval: 50 * time.Millisecond,
89+
UpdateInterval: 50 * time.Millisecond,
90+
Provisioners: provisionerd.Provisioners{
91+
string(database.ProvisionerTypeTerraform): proto.NewDRPCProvisionerClient(provisionersdk.Conn(tfClient)),
92+
},
93+
WorkDirectory: t.TempDir(),
94+
})
95+
t.Cleanup(func() {
96+
_ = closer.Close()
97+
})
98+
return closer
99+
}
100+
60101
// New constructs a new coderd test instance. This returned Server
61102
// should contain no side-effects.
62103
func New(t *testing.T) Server {
63104
// This can be hotswapped for a live database instance.
64105
db := databasefake.New()
106+
pubsub := database.NewPubsubInMemory()
65107
if os.Getenv("DB") != "" {
66108
connectionURL, close, err := postgres.Open()
67109
require.NoError(t, err)
@@ -74,11 +116,18 @@ func New(t *testing.T) Server {
74116
err = database.Migrate(sqlDB)
75117
require.NoError(t, err)
76118
db = database.New(sqlDB)
119+
120+
pubsub, err = database.NewPubsub(context.Background(), sqlDB, connectionURL)
121+
require.NoError(t, err)
122+
t.Cleanup(func() {
123+
_ = pubsub.Close()
124+
})
77125
}
78126

79127
handler := coderd.New(&coderd.Options{
80128
Logger: slogtest.Make(t, nil),
81129
Database: db,
130+
Pubsub: pubsub,
82131
})
83132
srv := httptest.NewServer(handler)
84133
serverURL, err := url.Parse(srv.URL)

coderd/coderdtest/coderdtest_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ func TestNew(t *testing.T) {
1616
t.Parallel()
1717
server := coderdtest.New(t)
1818
_ = server.RandomInitialUser(t)
19+
_ = server.AddProvisionerd(t)
1920
}

coderd/projecthistory.go

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"archive/tar"
55
"bytes"
66
"database/sql"
7+
"encoding/json"
78
"errors"
89
"fmt"
910
"net/http"
@@ -12,6 +13,7 @@ import (
1213
"github.com/go-chi/render"
1314
"github.com/google/uuid"
1415
"github.com/moby/moby/pkg/namesgenerator"
16+
"golang.org/x/xerrors"
1517

1618
"github.com/coder/coder/database"
1719
"github.com/coder/coder/httpapi"
@@ -26,6 +28,7 @@ type ProjectHistory struct {
2628
UpdatedAt time.Time `json:"updated_at"`
2729
Name string `json:"name"`
2830
StorageMethod database.ProjectStorageMethod `json:"storage_method"`
31+
Import ProvisionerJob `json:"import"`
2932
}
3033

3134
// CreateProjectHistoryRequest enables callers to create a new Project Version.
@@ -50,12 +53,33 @@ func (api *api) projectHistoryByOrganization(rw http.ResponseWriter, r *http.Req
5053
}
5154
apiHistory := make([]ProjectHistory, 0)
5255
for _, version := range history {
53-
apiHistory = append(apiHistory, convertProjectHistory(version))
56+
job, err := api.Database.GetProvisionerJobByID(r.Context(), version.ImportJobID)
57+
if err != nil {
58+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
59+
Message: fmt.Sprintf("get provisioner job: %s", err),
60+
})
61+
return
62+
}
63+
apiHistory = append(apiHistory, convertProjectHistory(version, job))
5464
}
5565
render.Status(r, http.StatusOK)
5666
render.JSON(rw, r, apiHistory)
5767
}
5868

69+
// Return a single project history by organization and name.
70+
func (api *api) projectHistoryByOrganizationAndName(rw http.ResponseWriter, r *http.Request) {
71+
projectHistory := httpmw.ProjectHistoryParam(r)
72+
job, err := api.Database.GetProvisionerJobByID(r.Context(), projectHistory.ImportJobID)
73+
if err != nil {
74+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
75+
Message: fmt.Sprintf("get provisioner job: %s", err),
76+
})
77+
return
78+
}
79+
render.Status(r, http.StatusOK)
80+
render.JSON(rw, r, convertProjectHistory(projectHistory, job))
81+
}
82+
5983
// Creates a new version of the project. An import job is queued to parse
6084
// the storage method provided. Once completed, the import job will specify
6185
// the version as latest.
@@ -82,37 +106,71 @@ func (api *api) postProjectHistoryByOrganization(rw http.ResponseWriter, r *http
82106
return
83107
}
84108

109+
apiKey := httpmw.APIKey(r)
85110
project := httpmw.ProjectParam(r)
86-
history, err := api.Database.InsertProjectHistory(r.Context(), database.InsertProjectHistoryParams{
87-
ID: uuid.New(),
88-
ProjectID: project.ID,
89-
CreatedAt: database.Now(),
90-
UpdatedAt: database.Now(),
91-
Name: namesgenerator.GetRandomName(1),
92-
StorageMethod: createProjectVersion.StorageMethod,
93-
StorageSource: createProjectVersion.StorageSource,
94-
// TODO: Make this do something!
95-
ImportJobID: uuid.New(),
111+
112+
var provisionerJob database.ProvisionerJob
113+
var projectHistory database.ProjectHistory
114+
err := api.Database.InTx(func(db database.Store) error {
115+
projectHistoryID := uuid.New()
116+
input, err := json.Marshal(projectImportJob{
117+
ProjectHistoryID: projectHistoryID,
118+
})
119+
if err != nil {
120+
return xerrors.Errorf("marshal import job: %w", err)
121+
}
122+
123+
provisionerJob, err = db.InsertProvisionerJob(r.Context(), database.InsertProvisionerJobParams{
124+
ID: uuid.New(),
125+
CreatedAt: database.Now(),
126+
UpdatedAt: database.Now(),
127+
InitiatorID: apiKey.UserID,
128+
Provisioner: project.Provisioner,
129+
Type: database.ProvisionerJobTypeProjectImport,
130+
ProjectID: project.ID,
131+
Input: input,
132+
})
133+
if err != nil {
134+
return xerrors.Errorf("insert provisioner job: %w", err)
135+
}
136+
137+
projectHistory, err = api.Database.InsertProjectHistory(r.Context(), database.InsertProjectHistoryParams{
138+
ID: projectHistoryID,
139+
ProjectID: project.ID,
140+
CreatedAt: database.Now(),
141+
UpdatedAt: database.Now(),
142+
Name: namesgenerator.GetRandomName(1),
143+
StorageMethod: createProjectVersion.StorageMethod,
144+
StorageSource: createProjectVersion.StorageSource,
145+
ImportJobID: provisionerJob.ID,
146+
})
147+
if err != nil {
148+
return xerrors.Errorf("insert project history: %s", err)
149+
}
150+
return nil
96151
})
97152
if err != nil {
98153
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
99-
Message: fmt.Sprintf("insert project history: %s", err),
154+
Message: err.Error(),
100155
})
101156
return
102157
}
103158

104-
// TODO: A job to process the new version should occur here.
105-
106159
render.Status(r, http.StatusCreated)
107-
render.JSON(rw, r, convertProjectHistory(history))
160+
render.JSON(rw, r, convertProjectHistory(projectHistory, provisionerJob))
108161
}
109162

110-
func convertProjectHistory(history database.ProjectHistory) ProjectHistory {
163+
func convertProjectHistory(history database.ProjectHistory, job database.ProvisionerJob) ProjectHistory {
111164
return ProjectHistory{
112165
ID: history.ID,
113166
ProjectID: history.ProjectID,
114167
CreatedAt: history.CreatedAt,
115168
UpdatedAt: history.UpdatedAt,
116169
Name: history.Name,
170+
Import: convertProvisionerJob(job),
117171
}
118172
}
173+
174+
func projectHistoryLogsChannel(projectHistoryID uuid.UUID) string {
175+
return fmt.Sprintf("project-history-logs:%s", projectHistoryID)
176+
}

coderd/projecthistory_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestProjectHistory(t *testing.T) {
2525
Provisioner: database.ProvisionerTypeTerraform,
2626
})
2727
require.NoError(t, err)
28-
versions, err := server.Client.ProjectHistory(context.Background(), user.Organization, project.Name)
28+
versions, err := server.Client.ListProjectHistory(context.Background(), user.Organization, project.Name)
2929
require.NoError(t, err)
3030
require.Len(t, versions, 0)
3131
})
@@ -48,14 +48,17 @@ func TestProjectHistory(t *testing.T) {
4848
require.NoError(t, err)
4949
_, err = writer.Write(make([]byte, 1<<10))
5050
require.NoError(t, err)
51-
_, err = server.Client.CreateProjectHistory(context.Background(), user.Organization, project.Name, coderd.CreateProjectHistoryRequest{
51+
history, err := server.Client.CreateProjectHistory(context.Background(), user.Organization, project.Name, coderd.CreateProjectHistoryRequest{
5252
StorageMethod: database.ProjectStorageMethodInlineArchive,
5353
StorageSource: buffer.Bytes(),
5454
})
5555
require.NoError(t, err)
56-
versions, err := server.Client.ProjectHistory(context.Background(), user.Organization, project.Name)
56+
versions, err := server.Client.ListProjectHistory(context.Background(), user.Organization, project.Name)
5757
require.NoError(t, err)
5858
require.Len(t, versions, 1)
59+
60+
_, err = server.Client.ProjectHistory(context.Background(), user.Organization, project.Name, history.Name)
61+
require.NoError(t, err)
5962
})
6063

6164
t.Run("CreateHistoryArchiveTooBig", func(t *testing.T) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy