mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
refactor: Allow provisioner jobs to be disconnected from projects (#194)
* Nest jobs under an organization * Rename project parameter to parameter schema * Update references when computing project parameters * Add files endpoint * Allow one-off project import jobs * Allow variables to be injected that are not defined by the schema * Update API to use jobs first * Fix CLI tests * Fix linting * Fix hex length for files table * Reduce memory allocation for windows
This commit is contained in:
@ -8,6 +8,8 @@ import (
|
||||
|
||||
"github.com/go-chi/render"
|
||||
"github.com/google/uuid"
|
||||
"github.com/moby/moby/pkg/namesgenerator"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/database"
|
||||
"github.com/coder/coder/httpapi"
|
||||
@ -21,8 +23,15 @@ type Project database.Project
|
||||
|
||||
// CreateProjectRequest enables callers to create a new Project.
|
||||
type CreateProjectRequest struct {
|
||||
Name string `json:"name" validate:"username,required"`
|
||||
Provisioner database.ProvisionerType `json:"provisioner" validate:"oneof=terraform echo,required"`
|
||||
Name string `json:"name" validate:"username,required"`
|
||||
|
||||
// VersionImportJobID is an in-progress or completed job to use as
|
||||
// an initial version of the project.
|
||||
//
|
||||
// This is required on creation to enable a user-flow of validating
|
||||
// the project works. There is no reason the data-model cannot support
|
||||
// empty projects, but it doesn't make sense for users.
|
||||
VersionImportJobID uuid.UUID `json:"import_job_id" validate:"required"`
|
||||
}
|
||||
|
||||
// Lists all projects the authenticated user has access to.
|
||||
@ -76,7 +85,7 @@ func (api *api) projectsByOrganization(rw http.ResponseWriter, r *http.Request)
|
||||
render.JSON(rw, r, projects)
|
||||
}
|
||||
|
||||
// Creates a new project in an organization.
|
||||
// Create a new project in an organization.
|
||||
func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
var createProject CreateProjectRequest
|
||||
if !httpapi.Read(rw, r, &createProject) {
|
||||
@ -99,25 +108,59 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project by name: %s", err.Error()),
|
||||
Message: fmt.Sprintf("get project by name: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
importJob, err := api.Database.GetProvisionerJobByID(r.Context(), createProject.VersionImportJobID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: "import job does not exist",
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get import job by id: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
project, err := api.Database.InsertProject(r.Context(), database.InsertProjectParams{
|
||||
ID: uuid.New(),
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
OrganizationID: organization.ID,
|
||||
Name: createProject.Name,
|
||||
Provisioner: createProject.Provisioner,
|
||||
var project Project
|
||||
err = api.Database.InTx(func(db database.Store) error {
|
||||
projectVersionID := uuid.New()
|
||||
dbProject, err := db.InsertProject(r.Context(), database.InsertProjectParams{
|
||||
ID: uuid.New(),
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
OrganizationID: organization.ID,
|
||||
Name: createProject.Name,
|
||||
Provisioner: importJob.Provisioner,
|
||||
ActiveVersionID: projectVersionID,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert project: %s", err)
|
||||
}
|
||||
_, err = db.InsertProjectVersion(r.Context(), database.InsertProjectVersionParams{
|
||||
ID: projectVersionID,
|
||||
ProjectID: dbProject.ID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
Name: namesgenerator.GetRandomName(1),
|
||||
ImportJobID: importJob.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert project version: %s", err)
|
||||
}
|
||||
project = Project(dbProject)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("insert project: %s", err),
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusCreated)
|
||||
render.JSON(rw, r, project)
|
||||
}
|
||||
|
Reference in New Issue
Block a user