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

Skip to content

Commit aa2c852

Browse files
committed
Update API to use jobs first
1 parent 78055e4 commit aa2c852

28 files changed

+328
-329
lines changed

coderd/coderd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ func New(options *Options) http.Handler {
117117
httpmw.ExtractAPIKey(options.Database, nil),
118118
httpmw.ExtractOrganizationParam(options.Database),
119119
)
120-
r.Post("/", api.postProvisionerJobsByOrganization)
120+
r.Post("/import", api.postProvisionerImportJobByOrganization)
121121
r.Route("/{provisionerjob}", func(r chi.Router) {
122122
r.Use(httpmw.ExtractProvisionerJobParam(options.Database))
123+
r.Get("/", api.provisionerJobByOrganization)
123124
r.Get("/logs", api.provisionerJobLogsByID)
124-
r.Get("/resources", api.provisionerJobResourcesByOrganization)
125125
})
126126
})
127127
})

coderd/coderdtest/coderdtest.go

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -122,39 +122,44 @@ func CreateInitialUser(t *testing.T, client *codersdk.Client) coderd.CreateIniti
122122
return req
123123
}
124124

125-
// CreateProject creates a project with the "echo" provisioner for
126-
// compatibility with testing. The name assigned is randomly generated.
127-
func CreateProject(t *testing.T, client *codersdk.Client, organization string) coderd.Project {
128-
project, err := client.CreateProject(context.Background(), organization, coderd.CreateProjectRequest{
129-
Name: randomUsername(),
130-
Provisioner: database.ProvisionerTypeEcho,
125+
// CreateProjectImportProvisionerJob creates a project import provisioner job
126+
// with the responses provided. It uses the "echo" provisioner for compatibility
127+
// with testing.
128+
func CreateProjectImportProvisionerJob(t *testing.T, client *codersdk.Client, organization string, res *echo.Responses) coderd.ProvisionerJob {
129+
data, err := echo.Tar(res)
130+
require.NoError(t, err)
131+
file, err := client.UploadFile(context.Background(), codersdk.ContentTypeTar, data)
132+
require.NoError(t, err)
133+
job, err := client.CreateProjectVersionImportProvisionerJob(context.Background(), organization, coderd.CreateProjectImportJobRequest{
134+
StorageSource: file.Hash,
135+
StorageMethod: database.ProvisionerStorageMethodFile,
136+
Provisioner: database.ProvisionerTypeEcho,
131137
})
132138
require.NoError(t, err)
133-
return project
139+
return job
134140
}
135141

136-
// CreateProjectVersion creates a project version for the "echo" provisioner
137-
// for compatibility with testing.
138-
func CreateProjectVersion(t *testing.T, client *codersdk.Client, organization, project string, responses *echo.Responses) coderd.ProjectVersion {
139-
data, err := echo.Tar(responses)
140-
require.NoError(t, err)
141-
version, err := client.CreateProjectVersion(context.Background(), organization, project, coderd.CreateProjectVersionRequest{
142-
StorageSource: data,
142+
// CreateProject creates a project with the "echo" provisioner for
143+
// compatibility with testing. The name assigned is randomly generated.
144+
func CreateProject(t *testing.T, client *codersdk.Client, organization string, job uuid.UUID) coderd.Project {
145+
project, err := client.CreateProject(context.Background(), organization, coderd.CreateProjectRequest{
146+
Name: randomUsername(),
147+
VersionImportJobID: job,
143148
})
144149
require.NoError(t, err)
145-
return version
150+
return project
146151
}
147152

148-
// AwaitProjectVersionImported awaits for the project import job to reach completed status.
149-
func AwaitProjectVersionImported(t *testing.T, client *codersdk.Client, organization, project, version string) coderd.ProjectVersion {
150-
var projectVersion coderd.ProjectVersion
153+
// AwaitProvisionerJob awaits for a job to reach completed status.
154+
func AwaitProvisionerJob(t *testing.T, client *codersdk.Client, organization string, job uuid.UUID) coderd.ProvisionerJob {
155+
var provisionerJob coderd.ProvisionerJob
151156
require.Eventually(t, func() bool {
152157
var err error
153-
projectVersion, err = client.ProjectVersion(context.Background(), organization, project, version)
158+
provisionerJob, err = client.ProvisionerJob(context.Background(), organization, job)
154159
require.NoError(t, err)
155-
return projectVersion.Import.Status.Completed()
160+
return provisionerJob.Status.Completed()
156161
}, 3*time.Second, 25*time.Millisecond)
157-
return projectVersion
162+
return provisionerJob
158163
}
159164

160165
// CreateWorkspace creates a workspace for the user and project provided.
@@ -168,18 +173,6 @@ func CreateWorkspace(t *testing.T, client *codersdk.Client, user string, project
168173
return workspace
169174
}
170175

171-
// AwaitWorkspaceHistoryProvisioned awaits for the workspace provision job to reach completed status.
172-
func AwaitWorkspaceHistoryProvisioned(t *testing.T, client *codersdk.Client, user, workspace, history string) coderd.WorkspaceHistory {
173-
var workspaceHistory coderd.WorkspaceHistory
174-
require.Eventually(t, func() bool {
175-
var err error
176-
workspaceHistory, err = client.WorkspaceHistory(context.Background(), user, workspace, history)
177-
require.NoError(t, err)
178-
return workspaceHistory.Provision.Status.Completed()
179-
}, 3*time.Second, 25*time.Millisecond)
180-
return workspaceHistory
181-
}
182-
183176
func randomUsername() string {
184177
return strings.ReplaceAll(namesgenerator.GetRandomName(0), "_", "-")
185178
}

coderd/coderdtest/coderdtest_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ func TestNew(t *testing.T) {
2222
client := coderdtest.New(t)
2323
user := coderdtest.CreateInitialUser(t, client)
2424
closer := coderdtest.NewProvisionerDaemon(t, client)
25-
project := coderdtest.CreateProject(t, client, user.Organization)
26-
version := coderdtest.CreateProjectVersion(t, client, user.Organization, project.Name, nil)
27-
coderdtest.AwaitProjectVersionImported(t, client, user.Organization, project.Name, version.Name)
25+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
26+
coderdtest.AwaitProvisionerJob(t, client, user.Organization, job.ID)
27+
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
2828
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
2929
history, err := client.CreateWorkspaceHistory(context.Background(), "me", workspace.Name, coderd.CreateWorkspaceHistoryRequest{
30-
ProjectVersionID: version.ID,
30+
ProjectVersionID: project.ActiveVersionID,
3131
Transition: database.WorkspaceTransitionStart,
3232
})
3333
require.NoError(t, err)
34-
coderdtest.AwaitWorkspaceHistoryProvisioned(t, client, "me", workspace.Name, history.Name)
34+
coderdtest.AwaitProvisionerJob(t, client, user.Organization, history.ProvisionJobID)
3535
closer.Close()
3636
}

coderd/files_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestPostFiles(t *testing.T) {
1616
client := coderdtest.New(t)
1717
_ = coderdtest.CreateInitialUser(t, client)
1818
_, err := client.UploadFile(context.Background(), "bad", []byte{'a'})
19-
require.NoError(t, err)
19+
require.Error(t, err)
2020
})
2121

2222
t.Run("MassiveBody", func(t *testing.T) {

coderd/projects.go

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88

99
"github.com/go-chi/render"
1010
"github.com/google/uuid"
11+
"github.com/moby/moby/pkg/namesgenerator"
12+
"golang.org/x/xerrors"
1113

1214
"github.com/coder/coder/database"
1315
"github.com/coder/coder/httpapi"
@@ -21,8 +23,15 @@ type Project database.Project
2123

2224
// CreateProjectRequest enables callers to create a new Project.
2325
type CreateProjectRequest struct {
24-
Name string `json:"name" validate:"username,required"`
25-
Provisioner database.ProvisionerType `json:"provisioner" validate:"oneof=terraform echo,required"`
26+
Name string `json:"name" validate:"username,required"`
27+
28+
// VersionImportJobID is an in-progress or completed job to use as
29+
// an initial version of the project.
30+
//
31+
// This is required on creation to enable a user-flow of validating
32+
// the project works. There is no reason the data-model cannot support
33+
// empty projects, but it doesn't make sense for users.
34+
VersionImportJobID uuid.UUID `json:"import_job_id" validate:"required"`
2635
}
2736

2837
// Lists all projects the authenticated user has access to.
@@ -76,7 +85,7 @@ func (api *api) projectsByOrganization(rw http.ResponseWriter, r *http.Request)
7685
render.JSON(rw, r, projects)
7786
}
7887

79-
// Creates a new project in an organization.
88+
// Create a new project in an organization.
8089
func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Request) {
8190
var createProject CreateProjectRequest
8291
if !httpapi.Read(rw, r, &createProject) {
@@ -99,25 +108,59 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
99108
}
100109
if !errors.Is(err, sql.ErrNoRows) {
101110
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
102-
Message: fmt.Sprintf("get project by name: %s", err.Error()),
111+
Message: fmt.Sprintf("get project by name: %s", err),
112+
})
113+
return
114+
}
115+
importJob, err := api.Database.GetProvisionerJobByID(r.Context(), createProject.VersionImportJobID)
116+
if errors.Is(err, sql.ErrNoRows) {
117+
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
118+
Message: "import job does not exist",
119+
})
120+
}
121+
if err != nil {
122+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
123+
Message: fmt.Sprintf("get import job by id: %s", err),
103124
})
104125
return
105126
}
106127

107-
project, err := api.Database.InsertProject(r.Context(), database.InsertProjectParams{
108-
ID: uuid.New(),
109-
CreatedAt: database.Now(),
110-
UpdatedAt: database.Now(),
111-
OrganizationID: organization.ID,
112-
Name: createProject.Name,
113-
Provisioner: createProject.Provisioner,
128+
var project Project
129+
err = api.Database.InTx(func(db database.Store) error {
130+
projectVersionID := uuid.New()
131+
dbProject, err := db.InsertProject(r.Context(), database.InsertProjectParams{
132+
ID: uuid.New(),
133+
CreatedAt: database.Now(),
134+
UpdatedAt: database.Now(),
135+
OrganizationID: organization.ID,
136+
Name: createProject.Name,
137+
Provisioner: importJob.Provisioner,
138+
ActiveVersionID: projectVersionID,
139+
})
140+
if err != nil {
141+
return xerrors.Errorf("insert project: %s", err)
142+
}
143+
_, err = db.InsertProjectVersion(r.Context(), database.InsertProjectVersionParams{
144+
ID: projectVersionID,
145+
ProjectID: dbProject.ID,
146+
CreatedAt: database.Now(),
147+
UpdatedAt: database.Now(),
148+
Name: namesgenerator.GetRandomName(1),
149+
ImportJobID: importJob.ID,
150+
})
151+
if err != nil {
152+
return xerrors.Errorf("insert project version: %s", err)
153+
}
154+
project = Project(dbProject)
155+
return nil
114156
})
115157
if err != nil {
116158
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
117-
Message: fmt.Sprintf("insert project: %s", err),
159+
Message: err.Error(),
118160
})
119161
return
120162
}
163+
121164
render.Status(r, http.StatusCreated)
122165
render.JSON(rw, r, project)
123166
}

coderd/projects_test.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ func TestProjects(t *testing.T) {
3030
t.Parallel()
3131
client := coderdtest.New(t)
3232
user := coderdtest.CreateInitialUser(t, client)
33-
_ = coderdtest.CreateProject(t, client, user.Organization)
33+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
34+
_ = coderdtest.CreateProject(t, client, user.Organization, job.ID)
3435
projects, err := client.Projects(context.Background(), "")
3536
require.NoError(t, err)
3637
require.Len(t, projects, 1)
@@ -53,7 +54,8 @@ func TestProjectsByOrganization(t *testing.T) {
5354
t.Parallel()
5455
client := coderdtest.New(t)
5556
user := coderdtest.CreateInitialUser(t, client)
56-
_ = coderdtest.CreateProject(t, client, user.Organization)
57+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
58+
_ = coderdtest.CreateProject(t, client, user.Organization, job.ID)
5759
projects, err := client.Projects(context.Background(), "")
5860
require.NoError(t, err)
5961
require.Len(t, projects, 1)
@@ -66,17 +68,19 @@ func TestPostProjectsByOrganization(t *testing.T) {
6668
t.Parallel()
6769
client := coderdtest.New(t)
6870
user := coderdtest.CreateInitialUser(t, client)
69-
_ = coderdtest.CreateProject(t, client, user.Organization)
71+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
72+
_ = coderdtest.CreateProject(t, client, user.Organization, job.ID)
7073
})
7174

7275
t.Run("AlreadyExists", func(t *testing.T) {
7376
t.Parallel()
7477
client := coderdtest.New(t)
7578
user := coderdtest.CreateInitialUser(t, client)
76-
project := coderdtest.CreateProject(t, client, user.Organization)
79+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
80+
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
7781
_, err := client.CreateProject(context.Background(), user.Organization, coderd.CreateProjectRequest{
78-
Name: project.Name,
79-
Provisioner: database.ProvisionerTypeEcho,
82+
Name: project.Name,
83+
VersionImportJobID: job.ID,
8084
})
8185
var apiErr *codersdk.Error
8286
require.ErrorAs(t, err, &apiErr)
@@ -90,7 +94,8 @@ func TestProjectByOrganization(t *testing.T) {
9094
t.Parallel()
9195
client := coderdtest.New(t)
9296
user := coderdtest.CreateInitialUser(t, client)
93-
project := coderdtest.CreateProject(t, client, user.Organization)
97+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
98+
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
9499
_, err := client.Project(context.Background(), user.Organization, project.Name)
95100
require.NoError(t, err)
96101
})
@@ -102,7 +107,8 @@ func TestPostParametersByProject(t *testing.T) {
102107
t.Parallel()
103108
client := coderdtest.New(t)
104109
user := coderdtest.CreateInitialUser(t, client)
105-
project := coderdtest.CreateProject(t, client, user.Organization)
110+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
111+
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
106112
_, err := client.CreateProjectParameter(context.Background(), user.Organization, project.Name, coderd.CreateParameterValueRequest{
107113
Name: "somename",
108114
SourceValue: "tomato",
@@ -120,7 +126,8 @@ func TestParametersByProject(t *testing.T) {
120126
t.Parallel()
121127
client := coderdtest.New(t)
122128
user := coderdtest.CreateInitialUser(t, client)
123-
project := coderdtest.CreateProject(t, client, user.Organization)
129+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
130+
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
124131
params, err := client.ProjectParameters(context.Background(), user.Organization, project.Name)
125132
require.NoError(t, err)
126133
require.NotNil(t, params)
@@ -130,7 +137,8 @@ func TestParametersByProject(t *testing.T) {
130137
t.Parallel()
131138
client := coderdtest.New(t)
132139
user := coderdtest.CreateInitialUser(t, client)
133-
project := coderdtest.CreateProject(t, client, user.Organization)
140+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, nil)
141+
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
134142
_, err := client.CreateProjectParameter(context.Background(), user.Organization, project.Name, coderd.CreateParameterValueRequest{
135143
Name: "example",
136144
SourceValue: "source-value",

0 commit comments

Comments
 (0)