diff --git a/coderd/coderd.go b/coderd/coderd.go index a3e1c28d3a..0aedb1d0c6 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -72,6 +72,7 @@ func New(options *Options) http.Handler { r.Route("/{projecthistory}", func(r chi.Router) { r.Use(httpmw.ExtractProjectHistoryParam(api.Database)) r.Get("/", api.projectHistoryByOrganizationAndName) + r.Get("/parameters", api.projectHistoryParametersByOrganizationAndName) }) }) }) @@ -96,6 +97,7 @@ func New(options *Options) http.Handler { r.Route("/{workspacehistory}", func(r chi.Router) { r.Use(httpmw.ExtractWorkspaceHistoryParam(options.Database)) r.Get("/", api.workspaceHistoryByName) + r.Get("/logs", api.workspaceHistoryLogsByName) }) }) }) diff --git a/coderd/parameters.go b/coderd/parameters.go index bc0ed4e665..b3aa1d4967 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -16,11 +16,11 @@ import ( // CreateParameterValueRequest is used to create a new parameter value for a scope. type CreateParameterValueRequest struct { - Name string `json:"name"` - SourceValue string `json:"source_value"` - SourceScheme database.ParameterSourceScheme `json:"source_scheme"` - DestinationScheme database.ParameterDestinationScheme `json:"destination_scheme"` - DestinationValue string `json:"destination_value"` + Name string `json:"name" validate:"required"` + SourceValue string `json:"source_value" validate:"required"` + SourceScheme database.ParameterSourceScheme `json:"source_scheme" validate:"oneof=data,required"` + DestinationScheme database.ParameterDestinationScheme `json:"destination_scheme" validate:"oneof=environment_variable provisioner_variable,required"` + DestinationValue string `json:"destination_value" validate:"required"` } // ParameterValue represents a set value for the scope. diff --git a/coderd/projecthistory.go b/coderd/projecthistory.go index 55c4cae55e..36d4a38f95 100644 --- a/coderd/projecthistory.go +++ b/coderd/projecthistory.go @@ -31,6 +31,27 @@ type ProjectHistory struct { Import ProvisionerJob `json:"import"` } +// ProjectParameter represents a parameter parsed from project history source on creation. +type ProjectParameter struct { + ID uuid.UUID `json:"id"` + CreatedAt time.Time `json:"created_at"` + ProjectHistoryID uuid.UUID `json:"project_history_id"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + DefaultSourceScheme database.ParameterSourceScheme `json:"default_source_scheme,omitempty"` + DefaultSourceValue string `json:"default_source_value,omitempty"` + AllowOverrideSource bool `json:"allow_override_source"` + DefaultDestinationScheme database.ParameterDestinationScheme `json:"default_destination_scheme,omitempty"` + DefaultDestinationValue string `json:"default_destination_value,omitempty"` + AllowOverrideDestination bool `json:"allow_override_destination"` + DefaultRefresh string `json:"default_refresh"` + RedisplayValue bool `json:"redisplay_value"` + ValidationError string `json:"validation_error,omitempty"` + ValidationCondition string `json:"validation_condition,omitempty"` + ValidationTypeSystem database.ParameterTypeSystem `json:"validation_type_system,omitempty"` + ValidationValueType string `json:"validation_value_type,omitempty"` +} + // CreateProjectHistoryRequest enables callers to create a new Project Version. type CreateProjectHistoryRequest struct { StorageMethod database.ProjectStorageMethod `json:"storage_method" validate:"oneof=inline-archive,required"` @@ -160,14 +181,81 @@ func (api *api) postProjectHistoryByOrganization(rw http.ResponseWriter, r *http render.JSON(rw, r, convertProjectHistory(projectHistory, provisionerJob)) } +func (api *api) projectHistoryParametersByOrganizationAndName(rw http.ResponseWriter, r *http.Request) { + projectHistory := httpmw.ProjectHistoryParam(r) + job, err := api.Database.GetProvisionerJobByID(r.Context(), projectHistory.ImportJobID) + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: fmt.Sprintf("get provisioner job: %s", err), + }) + return + } + apiJob := convertProvisionerJob(job) + if !apiJob.Status.Completed() { + httpapi.Write(rw, http.StatusPreconditionRequired, httpapi.Response{ + Message: fmt.Sprintf("import job hasn't completed: %s", apiJob.Status), + }) + return + } + if apiJob.Status != ProvisionerJobStatusSucceeded { + httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ + Message: "import job wasn't successful. no parameters were parsed", + }) + return + } + + parameters, err := api.Database.GetProjectParametersByHistoryID(r.Context(), projectHistory.ID) + if errors.Is(err, sql.ErrNoRows) { + err = nil + parameters = []database.ProjectParameter{} + } + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: fmt.Sprintf("get project parameters: %s", err), + }) + return + } + + apiParameters := make([]ProjectParameter, 0, len(parameters)) + for _, parameter := range parameters { + apiParameters = append(apiParameters, convertProjectParameter(parameter)) + } + + render.Status(r, http.StatusOK) + render.JSON(rw, r, apiParameters) +} + func convertProjectHistory(history database.ProjectHistory, job database.ProvisionerJob) ProjectHistory { return ProjectHistory{ - ID: history.ID, - ProjectID: history.ProjectID, - CreatedAt: history.CreatedAt, - UpdatedAt: history.UpdatedAt, - Name: history.Name, - Import: convertProvisionerJob(job), + ID: history.ID, + ProjectID: history.ProjectID, + CreatedAt: history.CreatedAt, + UpdatedAt: history.UpdatedAt, + Name: history.Name, + StorageMethod: history.StorageMethod, + Import: convertProvisionerJob(job), + } +} + +func convertProjectParameter(parameter database.ProjectParameter) ProjectParameter { + return ProjectParameter{ + ID: parameter.ID, + CreatedAt: parameter.CreatedAt, + ProjectHistoryID: parameter.ProjectHistoryID, + Name: parameter.Name, + Description: parameter.Description, + DefaultSourceScheme: parameter.DefaultSourceScheme, + DefaultSourceValue: parameter.DefaultSourceValue.String, + AllowOverrideSource: parameter.AllowOverrideSource, + DefaultDestinationScheme: parameter.DefaultDestinationScheme, + DefaultDestinationValue: parameter.DefaultDestinationValue.String, + AllowOverrideDestination: parameter.AllowOverrideDestination, + DefaultRefresh: parameter.DefaultRefresh, + RedisplayValue: parameter.RedisplayValue, + ValidationError: parameter.ValidationError, + ValidationCondition: parameter.ValidationCondition, + ValidationTypeSystem: parameter.ValidationTypeSystem, + ValidationValueType: parameter.ValidationValueType, } } diff --git a/coderd/projects_test.go b/coderd/projects_test.go index 46dc7b2058..5e96b78aad 100644 --- a/coderd/projects_test.go +++ b/coderd/projects_test.go @@ -1,8 +1,11 @@ package coderd_test import ( + "archive/tar" + "bytes" "context" "testing" + "time" "github.com/stretchr/testify/require" @@ -124,4 +127,42 @@ func TestProjects(t *testing.T) { }) require.NoError(t, err) }) + + t.Run("Import", func(t *testing.T) { + t.Parallel() + server := coderdtest.New(t) + user := server.RandomInitialUser(t) + _ = server.AddProvisionerd(t) + project, err := server.Client.CreateProject(context.Background(), user.Organization, coderd.CreateProjectRequest{ + Name: "someproject", + Provisioner: database.ProvisionerTypeTerraform, + }) + require.NoError(t, err) + var buffer bytes.Buffer + writer := tar.NewWriter(&buffer) + content := `variable "example" { + default = "hi" +}` + err = writer.WriteHeader(&tar.Header{ + Name: "main.tf", + Size: int64(len(content)), + }) + require.NoError(t, err) + _, err = writer.Write([]byte(content)) + require.NoError(t, err) + history, err := server.Client.CreateProjectHistory(context.Background(), user.Organization, project.Name, coderd.CreateProjectHistoryRequest{ + StorageMethod: database.ProjectStorageMethodInlineArchive, + StorageSource: buffer.Bytes(), + }) + require.NoError(t, err) + require.Eventually(t, func() bool { + projectHistory, err := server.Client.ProjectHistory(context.Background(), user.Organization, project.Name, history.Name) + require.NoError(t, err) + return projectHistory.Import.Status.Completed() + }, 15*time.Second, 10*time.Millisecond) + params, err := server.Client.ProjectHistoryParameters(context.Background(), user.Organization, project.Name, history.Name) + require.NoError(t, err) + require.Len(t, params, 1) + require.Equal(t, "example", params[0].Name) + }) } diff --git a/coderd/provisionerdaemons.go b/coderd/provisionerdaemons.go index 4318dd2cde..ac9cb7f3cb 100644 --- a/coderd/provisionerdaemons.go +++ b/coderd/provisionerdaemons.go @@ -451,6 +451,9 @@ func (server *provisionerdServer) CompleteJob(ctx context.Context, completed *pr ValidationValueType: protoParameter.ValidationValueType, ValidationTypeSystem: validationTypeSystem, + DefaultSourceScheme: database.ParameterSourceSchemeNone, + DefaultDestinationScheme: database.ParameterDestinationSchemeNone, + AllowOverrideDestination: protoParameter.AllowOverrideDestination, AllowOverrideSource: protoParameter.AllowOverrideSource, } @@ -574,6 +577,8 @@ func (server *provisionerdServer) CompleteJob(ctx context.Context, completed *pr func convertValidationTypeSystem(typeSystem sdkproto.ParameterSchema_TypeSystem) (database.ParameterTypeSystem, error) { switch typeSystem { + case sdkproto.ParameterSchema_None: + return database.ParameterTypeSystemNone, nil case sdkproto.ParameterSchema_HCL: return database.ParameterTypeSystemHCL, nil default: diff --git a/coderd/workspacehistory.go b/coderd/workspacehistory.go index e5ea22d4b6..59ba0ed9e7 100644 --- a/coderd/workspacehistory.go +++ b/coderd/workspacehistory.go @@ -10,6 +10,7 @@ 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" @@ -155,6 +156,7 @@ func (api *api) postWorkspaceHistoryByUser(rw http.ResponseWriter, r *http.Reque WorkspaceID: workspace.ID, ProjectHistoryID: projectHistory.ID, BeforeID: priorHistoryID, + Name: namesgenerator.GetRandomName(1), Initiator: user.ID, Transition: createBuild.Transition, ProvisionJobID: provisionerJob.ID, @@ -253,7 +255,3 @@ func convertWorkspaceHistory(workspaceHistory database.WorkspaceHistory, provisi Provision: convertProvisionerJob(provisionerJob), }) } - -func workspaceHistoryLogsChannel(workspaceHistoryID uuid.UUID) string { - return fmt.Sprintf("workspace-history-logs:%s", workspaceHistoryID) -} diff --git a/coderd/workspacehistorylogs.go b/coderd/workspacehistorylogs.go new file mode 100644 index 0000000000..ecf8e1fda9 --- /dev/null +++ b/coderd/workspacehistorylogs.go @@ -0,0 +1,203 @@ +package coderd + +import ( + "context" + "database/sql" + "encoding/json" + "errors" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/go-chi/render" + "github.com/google/uuid" + + "cdr.dev/slog" + + "github.com/coder/coder/database" + "github.com/coder/coder/httpapi" + "github.com/coder/coder/httpmw" +) + +// WorkspaceHistoryLog represents a single log from workspace history. +type WorkspaceHistoryLog struct { + ID uuid.UUID + CreatedAt time.Time `json:"created_at"` + Source database.LogSource `json:"log_source"` + Level database.LogLevel `json:"log_level"` + Output string `json:"output"` +} + +// Returns workspace history logs based on query parameters. +// The intended usage for a client to stream all logs (with JS API): +// const timestamp = new Date().getTime(); +// 1. GET /logs?before= +// 2. GET /logs?after=&follow +// The combination of these responses should provide all current logs +// to the consumer, and future logs are streamed in the follow request. +func (api *api) workspaceHistoryLogsByName(rw http.ResponseWriter, r *http.Request) { + follow := r.URL.Query().Has("follow") + afterRaw := r.URL.Query().Get("after") + beforeRaw := r.URL.Query().Get("before") + if beforeRaw != "" && follow { + httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ + Message: "before cannot be used with follow", + }) + return + } + + var after time.Time + // Only fetch logs created after the time provided. + if afterRaw != "" { + afterMS, err := strconv.ParseInt(afterRaw, 10, 64) + if err != nil { + httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ + Message: fmt.Sprintf("unable to parse after %q: %s", afterRaw, err), + }) + return + } + after = time.UnixMilli(afterMS) + } else { + if follow { + after = database.Now() + } + } + var before time.Time + // Only fetch logs created before the time provided. + if beforeRaw != "" { + beforeMS, err := strconv.ParseInt(beforeRaw, 10, 64) + if err != nil { + httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ + Message: fmt.Sprintf("unable to parse before %q: %s", beforeRaw, err), + }) + return + } + before = time.UnixMilli(beforeMS) + } else { + before = database.Now() + } + + history := httpmw.WorkspaceHistoryParam(r) + if !follow { + logs, err := api.Database.GetWorkspaceHistoryLogsByIDBetween(r.Context(), database.GetWorkspaceHistoryLogsByIDBetweenParams{ + WorkspaceHistoryID: history.ID, + CreatedAfter: after, + CreatedBefore: before, + }) + if errors.Is(err, sql.ErrNoRows) { + err = nil + logs = []database.WorkspaceHistoryLog{} + } + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: fmt.Sprintf("get workspace history: %s", err), + }) + return + } + render.Status(r, http.StatusOK) + render.JSON(rw, r, logs) + return + } + + bufferedLogs := make(chan database.WorkspaceHistoryLog, 128) + closeSubscribe, err := api.Pubsub.Subscribe(workspaceHistoryLogsChannel(history.ID), func(ctx context.Context, message []byte) { + var logs []database.WorkspaceHistoryLog + err := json.Unmarshal(message, &logs) + if err != nil { + api.Logger.Warn(r.Context(), fmt.Sprintf("invalid workspace log on channel %q: %s", workspaceHistoryLogsChannel(history.ID), err.Error())) + return + } + + for _, log := range logs { + select { + case bufferedLogs <- log: + default: + // This is a case that shouldn't happen, but totally could. + // There's no way to stream data from the database, so we'll + // need to maintain some level of internal buffer. + // + // If this overflows users could miss logs when streaming. + // We warn to make sure we know when it happens! + api.Logger.Warn(r.Context(), "workspace history log overflowing channel") + } + } + }) + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: fmt.Sprintf("subscribe to workspace history logs: %s", err), + }) + return + } + defer closeSubscribe() + + workspaceHistoryLogs, err := api.Database.GetWorkspaceHistoryLogsByIDBetween(r.Context(), database.GetWorkspaceHistoryLogsByIDBetweenParams{ + WorkspaceHistoryID: history.ID, + CreatedAfter: after, + CreatedBefore: before, + }) + if errors.Is(err, sql.ErrNoRows) { + err = nil + workspaceHistoryLogs = []database.WorkspaceHistoryLog{} + } + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: fmt.Sprint("get workspace history logs: %w", err), + }) + return + } + + // "follow" uses the ndjson format to stream data. + // See: https://canjs.com/doc/can-ndjson-stream.html + rw.Header().Set("Content-Type", "application/stream+json") + rw.WriteHeader(http.StatusOK) + rw.(http.Flusher).Flush() + + // The Go stdlib JSON encoder appends a newline character after message write. + encoder := json.NewEncoder(rw) + + for _, workspaceHistoryLog := range workspaceHistoryLogs { + err = encoder.Encode(convertWorkspaceHistoryLog(workspaceHistoryLog)) + if err != nil { + return + } + } + + ticker := time.NewTicker(250 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-r.Context().Done(): + return + case log := <-bufferedLogs: + err = encoder.Encode(convertWorkspaceHistoryLog(log)) + if err != nil { + return + } + rw.(http.Flusher).Flush() + case <-ticker.C: + job, err := api.Database.GetProvisionerJobByID(r.Context(), history.ProvisionJobID) + if err != nil { + api.Logger.Warn(r.Context(), "streaming workspace logs; checking if job completed", slog.Error(err), slog.F("job_id", history.ProvisionJobID)) + continue + } + if convertProvisionerJob(job).Status.Completed() { + return + } + } + } +} + +func convertWorkspaceHistoryLog(workspaceHistoryLog database.WorkspaceHistoryLog) WorkspaceHistoryLog { + return WorkspaceHistoryLog{ + ID: workspaceHistoryLog.ID, + CreatedAt: workspaceHistoryLog.CreatedAt, + Source: workspaceHistoryLog.Source, + Level: workspaceHistoryLog.Level, + Output: workspaceHistoryLog.Output, + } +} + +func workspaceHistoryLogsChannel(workspaceHistoryID uuid.UUID) string { + return fmt.Sprintf("workspace-history-logs:%s", workspaceHistoryID) +} diff --git a/coderd/workspacehistorylogs_test.go b/coderd/workspacehistorylogs_test.go new file mode 100644 index 0000000000..bbaa1e6be6 --- /dev/null +++ b/coderd/workspacehistorylogs_test.go @@ -0,0 +1,102 @@ +package coderd_test + +import ( + "archive/tar" + "bytes" + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/coderd" + "github.com/coder/coder/coderd/coderdtest" + "github.com/coder/coder/codersdk" + "github.com/coder/coder/database" +) + +func TestWorkspaceHistoryLogs(t *testing.T) { + t.Parallel() + + setupProjectAndWorkspace := func(t *testing.T, client *codersdk.Client, user coderd.CreateInitialUserRequest) (coderd.Project, coderd.Workspace) { + project, err := client.CreateProject(context.Background(), user.Organization, coderd.CreateProjectRequest{ + Name: "banana", + Provisioner: database.ProvisionerTypeTerraform, + }) + require.NoError(t, err) + workspace, err := client.CreateWorkspace(context.Background(), "", coderd.CreateWorkspaceRequest{ + Name: "example", + ProjectID: project.ID, + }) + require.NoError(t, err) + return project, workspace + } + + setupProjectHistory := func(t *testing.T, client *codersdk.Client, user coderd.CreateInitialUserRequest, project coderd.Project, files map[string]string) coderd.ProjectHistory { + var buffer bytes.Buffer + writer := tar.NewWriter(&buffer) + for path, content := range files { + err := writer.WriteHeader(&tar.Header{ + Name: path, + Size: int64(len(content)), + }) + require.NoError(t, err) + _, err = writer.Write([]byte(content)) + require.NoError(t, err) + } + err := writer.Flush() + require.NoError(t, err) + + projectHistory, err := client.CreateProjectHistory(context.Background(), user.Organization, project.Name, coderd.CreateProjectHistoryRequest{ + StorageMethod: database.ProjectStorageMethodInlineArchive, + StorageSource: buffer.Bytes(), + }) + require.NoError(t, err) + require.Eventually(t, func() bool { + hist, err := client.ProjectHistory(context.Background(), user.Organization, project.Name, projectHistory.Name) + require.NoError(t, err) + return hist.Import.Status.Completed() + }, 15*time.Second, 50*time.Millisecond) + return projectHistory + } + + server := coderdtest.New(t) + user := server.RandomInitialUser(t) + _ = server.AddProvisionerd(t) + project, workspace := setupProjectAndWorkspace(t, server.Client, user) + projectHistory := setupProjectHistory(t, server.Client, user, project, map[string]string{ + "main.tf": `resource "null_resource" "test" {}`, + }) + + workspaceHistory, err := server.Client.CreateWorkspaceHistory(context.Background(), "", workspace.Name, coderd.CreateWorkspaceHistoryRequest{ + ProjectHistoryID: projectHistory.ID, + Transition: database.WorkspaceTransitionCreate, + }) + require.NoError(t, err) + + now := database.Now() + logChan, err := server.Client.FollowWorkspaceHistoryLogsAfter(context.Background(), "", workspace.Name, workspaceHistory.Name, now) + require.NoError(t, err) + + for { + log, more := <-logChan + if !more { + break + } + t.Logf("Output: %s", log.Output) + } + + t.Run("ReturnAll", func(t *testing.T) { + t.Parallel() + + _, err = server.Client.WorkspaceHistoryLogs(context.Background(), "", workspace.Name, workspaceHistory.Name) + require.NoError(t, err) + }) + + t.Run("Between", func(t *testing.T) { + t.Parallel() + + _, err = server.Client.WorkspaceHistoryLogsBetween(context.Background(), "", workspace.Name, workspaceHistory.Name, time.Time{}, database.Now()) + require.NoError(t, err) + }) +} diff --git a/codersdk/projects.go b/codersdk/projects.go index 6a1304893b..7b43e5d604 100644 --- a/codersdk/projects.go +++ b/codersdk/projects.go @@ -99,6 +99,20 @@ func (c *Client) CreateProjectHistory(ctx context.Context, organization, project return projectVersion, json.NewDecoder(res.Body).Decode(&projectVersion) } +// ProjectHistoryParameters returns project parameters for history by name. +func (c *Client) ProjectHistoryParameters(ctx context.Context, organization, project, history string) ([]coderd.ProjectParameter, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/projects/%s/%s/history/%s/parameters", organization, project, history), nil) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return nil, readBodyAsError(res) + } + var params []coderd.ProjectParameter + return params, json.NewDecoder(res.Body).Decode(¶ms) +} + // ProjectParameters returns parameters scoped to a project. func (c *Client) ProjectParameters(ctx context.Context, organization, project string) ([]coderd.ParameterValue, error) { res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/projects/%s/%s/parameters", organization, project), nil) diff --git a/codersdk/projects_test.go b/codersdk/projects_test.go index 0b66b12fd1..9ccc211e2d 100644 --- a/codersdk/projects_test.go +++ b/codersdk/projects_test.go @@ -163,4 +163,12 @@ func TestProjects(t *testing.T) { require.NoError(t, err) require.Equal(t, "hi", param.Name) }) + + t.Run("HistoryParametersError", func(t *testing.T) { + t.Parallel() + server := coderdtest.New(t) + user := server.RandomInitialUser(t) + _, err := server.Client.ProjectHistoryParameters(context.Background(), user.Organization, "nothing", "nope") + require.Error(t, err) + }) } diff --git a/codersdk/workspaces.go b/codersdk/workspaces.go index 122f66cdea..79878bf407 100644 --- a/codersdk/workspaces.go +++ b/codersdk/workspaces.go @@ -5,6 +5,9 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" + "strconv" + "time" "github.com/coder/coder/coderd" ) @@ -131,3 +134,74 @@ func (c *Client) CreateWorkspaceHistory(ctx context.Context, owner, workspace st var workspaceHistory coderd.WorkspaceHistory return workspaceHistory, json.NewDecoder(res.Body).Decode(&workspaceHistory) } + +// WorkspaceHistoryLogs returns all logs for workspace history. +// To stream logs, use the FollowWorkspaceHistoryLogs function. +func (c *Client) WorkspaceHistoryLogs(ctx context.Context, owner, workspace, history string) ([]coderd.WorkspaceHistoryLog, error) { + return c.WorkspaceHistoryLogsBetween(ctx, owner, workspace, history, time.Time{}, time.Time{}) +} + +// WorkspaceHistoryLogsBetween returns logs between a specific time. +func (c *Client) WorkspaceHistoryLogsBetween(ctx context.Context, owner, workspace, history string, after, before time.Time) ([]coderd.WorkspaceHistoryLog, error) { + if owner == "" { + owner = "me" + } + values := url.Values{} + if !after.IsZero() { + values["after"] = []string{strconv.FormatInt(after.UTC().UnixMilli(), 10)} + } + if !before.IsZero() { + values["before"] = []string{strconv.FormatInt(before.UTC().UnixMilli(), 10)} + } + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/%s/history/%s/logs?%s", owner, workspace, history, values.Encode()), nil) + if err != nil { + return nil, err + } + if res.StatusCode != http.StatusOK { + defer res.Body.Close() + return nil, readBodyAsError(res) + } + + var logs []coderd.WorkspaceHistoryLog + return logs, json.NewDecoder(res.Body).Decode(&logs) +} + +// FollowWorkspaceHistoryLogsAfter returns a stream of workspace history logs. +// The channel will close when the workspace history job is no longer active. +func (c *Client) FollowWorkspaceHistoryLogsAfter(ctx context.Context, owner, workspace, history string, after time.Time) (<-chan coderd.WorkspaceHistoryLog, error) { + afterQuery := "" + if !after.IsZero() { + afterQuery = fmt.Sprintf("&after=%d", after.UTC().UnixMilli()) + } + if owner == "" { + owner = "me" + } + + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/%s/history/%s/logs?follow%s", owner, workspace, history, afterQuery), nil) + if err != nil { + return nil, err + } + if res.StatusCode != http.StatusOK { + defer res.Body.Close() + return nil, readBodyAsError(res) + } + + logs := make(chan coderd.WorkspaceHistoryLog) + decoder := json.NewDecoder(res.Body) + go func() { + defer close(logs) + var log coderd.WorkspaceHistoryLog + for { + err = decoder.Decode(&log) + if err != nil { + return + } + select { + case <-ctx.Done(): + return + case logs <- log: + } + } + }() + return logs, nil +} diff --git a/database/databasefake/databasefake.go b/database/databasefake/databasefake.go index cba5e5a3ec..36a8671c64 100644 --- a/database/databasefake/databasefake.go +++ b/database/databasefake/databasefake.go @@ -224,7 +224,7 @@ func (q *fakeQuerier) GetWorkspaceHistoryByWorkspaceIDWithoutAfter(_ context.Con return database.WorkspaceHistory{}, sql.ErrNoRows } -func (q *fakeQuerier) GetWorkspaceHistoryLogsByIDBefore(_ context.Context, arg database.GetWorkspaceHistoryLogsByIDBeforeParams) ([]database.WorkspaceHistoryLog, error) { +func (q *fakeQuerier) GetWorkspaceHistoryLogsByIDBetween(_ context.Context, arg database.GetWorkspaceHistoryLogsByIDBetweenParams) ([]database.WorkspaceHistoryLog, error) { q.mutex.Lock() defer q.mutex.Unlock() @@ -233,7 +233,10 @@ func (q *fakeQuerier) GetWorkspaceHistoryLogsByIDBefore(_ context.Context, arg d if workspaceHistoryLog.WorkspaceHistoryID.String() != arg.WorkspaceHistoryID.String() { continue } - if workspaceHistoryLog.CreatedAt.After(arg.CreatedAt) { + if workspaceHistoryLog.CreatedAt.After(arg.CreatedBefore) { + continue + } + if workspaceHistoryLog.CreatedAt.Before(arg.CreatedAfter) { continue } logs = append(logs, workspaceHistoryLog) @@ -440,7 +443,7 @@ func (q *fakeQuerier) GetProjectHistoryByProjectIDAndName(_ context.Context, arg return database.ProjectHistory{}, sql.ErrNoRows } -func (q *fakeQuerier) GetProjectHistoryLogsByIDBefore(_ context.Context, arg database.GetProjectHistoryLogsByIDBeforeParams) ([]database.ProjectHistoryLog, error) { +func (q *fakeQuerier) GetProjectHistoryLogsByIDBetween(_ context.Context, arg database.GetProjectHistoryLogsByIDBetweenParams) ([]database.ProjectHistoryLog, error) { q.mutex.Lock() defer q.mutex.Unlock() @@ -449,7 +452,10 @@ func (q *fakeQuerier) GetProjectHistoryLogsByIDBefore(_ context.Context, arg dat if projectHistoryLog.ProjectHistoryID.String() != arg.ProjectHistoryID.String() { continue } - if projectHistoryLog.CreatedAt.After(arg.CreatedAt) { + if projectHistoryLog.CreatedAt.After(arg.CreatedBefore) { + continue + } + if projectHistoryLog.CreatedAt.Before(arg.CreatedAfter) { continue } logs = append(logs, projectHistoryLog) diff --git a/database/dump.sql b/database/dump.sql index bbbc346584..2aa3ae2792 100644 --- a/database/dump.sql +++ b/database/dump.sql @@ -20,6 +20,7 @@ CREATE TYPE login_type AS ENUM ( ); CREATE TYPE parameter_destination_scheme AS ENUM ( + 'none', 'environment_variable', 'provisioner_variable' ); @@ -32,10 +33,12 @@ CREATE TYPE parameter_scope AS ENUM ( ); CREATE TYPE parameter_source_scheme AS ENUM ( + 'none', 'data' ); CREATE TYPE parameter_type_system AS ENUM ( + 'none', 'hcl' ); diff --git a/database/migrations/000002_projects.up.sql b/database/migrations/000002_projects.up.sql index 6a021cc988..62b7468558 100644 --- a/database/migrations/000002_projects.up.sql +++ b/database/migrations/000002_projects.up.sql @@ -46,13 +46,13 @@ CREATE TABLE project_history ( ); -- Types of parameters the automator supports. -CREATE TYPE parameter_type_system AS ENUM ('hcl'); +CREATE TYPE parameter_type_system AS ENUM ('none', 'hcl'); -- Supported schemes for a parameter source. -CREATE TYPE parameter_source_scheme AS ENUM('data'); +CREATE TYPE parameter_source_scheme AS ENUM('none', 'data'); -- Supported schemes for a parameter destination. -CREATE TYPE parameter_destination_scheme AS ENUM('environment_variable', 'provisioner_variable'); +CREATE TYPE parameter_destination_scheme AS ENUM('none', 'environment_variable', 'provisioner_variable'); -- Stores project version parameters parsed on import. -- No secrets are stored here. diff --git a/database/models.go b/database/models.go index 440e11dd71..dd7005a6c1 100644 --- a/database/models.go +++ b/database/models.go @@ -75,6 +75,7 @@ func (e *LoginType) Scan(src interface{}) error { type ParameterDestinationScheme string const ( + ParameterDestinationSchemeNone ParameterDestinationScheme = "none" ParameterDestinationSchemeEnvironmentVariable ParameterDestinationScheme = "environment_variable" ParameterDestinationSchemeProvisionerVariable ParameterDestinationScheme = "provisioner_variable" ) @@ -115,6 +116,7 @@ func (e *ParameterScope) Scan(src interface{}) error { type ParameterSourceScheme string const ( + ParameterSourceSchemeNone ParameterSourceScheme = "none" ParameterSourceSchemeData ParameterSourceScheme = "data" ) @@ -133,7 +135,8 @@ func (e *ParameterSourceScheme) Scan(src interface{}) error { type ParameterTypeSystem string const ( - ParameterTypeSystemHCL ParameterTypeSystem = "hcl" + ParameterTypeSystemNone ParameterTypeSystem = "none" + ParameterTypeSystemHCL ParameterTypeSystem = "hcl" ) func (e *ParameterTypeSystem) Scan(src interface{}) error { diff --git a/database/querier.go b/database/querier.go index 3db5795f9b..49793672fa 100644 --- a/database/querier.go +++ b/database/querier.go @@ -21,7 +21,7 @@ type querier interface { GetProjectHistoryByID(ctx context.Context, id uuid.UUID) (ProjectHistory, error) GetProjectHistoryByProjectID(ctx context.Context, projectID uuid.UUID) ([]ProjectHistory, error) GetProjectHistoryByProjectIDAndName(ctx context.Context, arg GetProjectHistoryByProjectIDAndNameParams) (ProjectHistory, error) - GetProjectHistoryLogsByIDBefore(ctx context.Context, arg GetProjectHistoryLogsByIDBeforeParams) ([]ProjectHistoryLog, error) + GetProjectHistoryLogsByIDBetween(ctx context.Context, arg GetProjectHistoryLogsByIDBetweenParams) ([]ProjectHistoryLog, error) GetProjectParametersByHistoryID(ctx context.Context, projectHistoryID uuid.UUID) ([]ProjectParameter, error) GetProjectsByOrganizationIDs(ctx context.Context, ids []string) ([]Project, error) GetProvisionerDaemonByID(ctx context.Context, id uuid.UUID) (ProvisionerDaemon, error) @@ -37,7 +37,7 @@ type querier interface { GetWorkspaceHistoryByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) ([]WorkspaceHistory, error) GetWorkspaceHistoryByWorkspaceIDAndName(ctx context.Context, arg GetWorkspaceHistoryByWorkspaceIDAndNameParams) (WorkspaceHistory, error) GetWorkspaceHistoryByWorkspaceIDWithoutAfter(ctx context.Context, workspaceID uuid.UUID) (WorkspaceHistory, error) - GetWorkspaceHistoryLogsByIDBefore(ctx context.Context, arg GetWorkspaceHistoryLogsByIDBeforeParams) ([]WorkspaceHistoryLog, error) + GetWorkspaceHistoryLogsByIDBetween(ctx context.Context, arg GetWorkspaceHistoryLogsByIDBetweenParams) ([]WorkspaceHistoryLog, error) GetWorkspaceResourcesByHistoryID(ctx context.Context, workspaceHistoryID uuid.UUID) ([]WorkspaceResource, error) GetWorkspacesByProjectAndUserID(ctx context.Context, arg GetWorkspacesByProjectAndUserIDParams) ([]Workspace, error) GetWorkspacesByUserID(ctx context.Context, ownerID string) ([]Workspace, error) diff --git a/database/query.sql b/database/query.sql index c2a8fcb579..93943326f7 100644 --- a/database/query.sql +++ b/database/query.sql @@ -188,14 +188,17 @@ FROM WHERE id = $1; --- name: GetProjectHistoryLogsByIDBefore :many +-- name: GetProjectHistoryLogsByIDBetween :many SELECT * FROM project_history_log WHERE - project_history_id = $1 - AND created_at <= $2 + project_history_id = @project_history_id + AND ( + created_at >= @created_after + OR created_at <= @created_before + ) ORDER BY created_at; @@ -295,14 +298,17 @@ WHERE LIMIT 1; --- name: GetWorkspaceHistoryLogsByIDBefore :many +-- name: GetWorkspaceHistoryLogsByIDBetween :many SELECT * FROM workspace_history_log WHERE - workspace_history_id = $1 - AND created_at <= $2 + workspace_history_id = @workspace_history_id + AND ( + created_at >= @created_after + OR created_at <= @created_before + ) ORDER BY created_at; diff --git a/database/query.sql.go b/database/query.sql.go index 366e156132..0da3e8cfba 100644 --- a/database/query.sql.go +++ b/database/query.sql.go @@ -450,25 +450,29 @@ func (q *sqlQuerier) GetProjectHistoryByProjectIDAndName(ctx context.Context, ar return i, err } -const getProjectHistoryLogsByIDBefore = `-- name: GetProjectHistoryLogsByIDBefore :many +const getProjectHistoryLogsByIDBetween = `-- name: GetProjectHistoryLogsByIDBetween :many SELECT id, project_history_id, created_at, source, level, output FROM project_history_log WHERE project_history_id = $1 - AND created_at <= $2 + AND ( + created_at >= $2 + OR created_at <= $3 + ) ORDER BY created_at ` -type GetProjectHistoryLogsByIDBeforeParams struct { +type GetProjectHistoryLogsByIDBetweenParams struct { ProjectHistoryID uuid.UUID `db:"project_history_id" json:"project_history_id"` - CreatedAt time.Time `db:"created_at" json:"created_at"` + CreatedAfter time.Time `db:"created_after" json:"created_after"` + CreatedBefore time.Time `db:"created_before" json:"created_before"` } -func (q *sqlQuerier) GetProjectHistoryLogsByIDBefore(ctx context.Context, arg GetProjectHistoryLogsByIDBeforeParams) ([]ProjectHistoryLog, error) { - rows, err := q.db.QueryContext(ctx, getProjectHistoryLogsByIDBefore, arg.ProjectHistoryID, arg.CreatedAt) +func (q *sqlQuerier) GetProjectHistoryLogsByIDBetween(ctx context.Context, arg GetProjectHistoryLogsByIDBetweenParams) ([]ProjectHistoryLog, error) { + rows, err := q.db.QueryContext(ctx, getProjectHistoryLogsByIDBetween, arg.ProjectHistoryID, arg.CreatedAfter, arg.CreatedBefore) if err != nil { return nil, err } @@ -1007,25 +1011,29 @@ func (q *sqlQuerier) GetWorkspaceHistoryByWorkspaceIDWithoutAfter(ctx context.Co return i, err } -const getWorkspaceHistoryLogsByIDBefore = `-- name: GetWorkspaceHistoryLogsByIDBefore :many +const getWorkspaceHistoryLogsByIDBetween = `-- name: GetWorkspaceHistoryLogsByIDBetween :many SELECT id, workspace_history_id, created_at, source, level, output FROM workspace_history_log WHERE workspace_history_id = $1 - AND created_at <= $2 + AND ( + created_at >= $2 + OR created_at <= $3 + ) ORDER BY created_at ` -type GetWorkspaceHistoryLogsByIDBeforeParams struct { +type GetWorkspaceHistoryLogsByIDBetweenParams struct { WorkspaceHistoryID uuid.UUID `db:"workspace_history_id" json:"workspace_history_id"` - CreatedAt time.Time `db:"created_at" json:"created_at"` + CreatedAfter time.Time `db:"created_after" json:"created_after"` + CreatedBefore time.Time `db:"created_before" json:"created_before"` } -func (q *sqlQuerier) GetWorkspaceHistoryLogsByIDBefore(ctx context.Context, arg GetWorkspaceHistoryLogsByIDBeforeParams) ([]WorkspaceHistoryLog, error) { - rows, err := q.db.QueryContext(ctx, getWorkspaceHistoryLogsByIDBefore, arg.WorkspaceHistoryID, arg.CreatedAt) +func (q *sqlQuerier) GetWorkspaceHistoryLogsByIDBetween(ctx context.Context, arg GetWorkspaceHistoryLogsByIDBetweenParams) ([]WorkspaceHistoryLog, error) { + rows, err := q.db.QueryContext(ctx, getWorkspaceHistoryLogsByIDBetween, arg.WorkspaceHistoryID, arg.CreatedAfter, arg.CreatedBefore) if err != nil { return nil, err } diff --git a/provisioner/terraform/parse_test.go b/provisioner/terraform/parse_test.go index 68f43acf23..f1221de20e 100644 --- a/provisioner/terraform/parse_test.go +++ b/provisioner/terraform/parse_test.go @@ -95,8 +95,9 @@ func TestParse(t *testing.T) { Type: &proto.Parse_Response_Complete{ Complete: &proto.Parse_Complete{ ParameterSchemas: []*proto.ParameterSchema{{ - Name: "A", - ValidationCondition: `var.A == "value"`, + Name: "A", + ValidationCondition: `var.A == "value"`, + ValidationTypeSystem: proto.ParameterSchema_HCL, }, }, }, diff --git a/provisionerd/provisionerd.go b/provisionerd/provisionerd.go index 4cc5f5a2c4..f751847b6a 100644 --- a/provisionerd/provisionerd.go +++ b/provisionerd/provisionerd.go @@ -94,6 +94,9 @@ func (p *provisionerDaemon) connect(ctx context.Context) { if errors.Is(err, context.Canceled) { return } + if p.isClosed() { + return + } p.opts.Logger.Warn(context.Background(), "failed to dial", slog.Error(err)) continue } @@ -102,6 +105,9 @@ func (p *provisionerDaemon) connect(ctx context.Context) { if errors.Is(err, context.Canceled) { return } + if p.isClosed() { + return + } p.opts.Logger.Warn(context.Background(), "create update job stream", slog.Error(err)) continue } diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index e3b16c832a..b0868ff17a 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -168,16 +168,19 @@ func (ParameterDestination_Scheme) EnumDescriptor() ([]byte, []int) { type ParameterSchema_TypeSystem int32 const ( - ParameterSchema_HCL ParameterSchema_TypeSystem = 0 + ParameterSchema_None ParameterSchema_TypeSystem = 0 + ParameterSchema_HCL ParameterSchema_TypeSystem = 1 ) // Enum value maps for ParameterSchema_TypeSystem. var ( ParameterSchema_TypeSystem_name = map[int32]string{ - 0: "HCL", + 0: "None", + 1: "HCL", } ParameterSchema_TypeSystem_value = map[string]int32{ - "HCL": 0, + "None": 0, + "HCL": 1, } ) @@ -488,7 +491,7 @@ func (x *ParameterSchema) GetValidationTypeSystem() ParameterSchema_TypeSystem { if x != nil { return x.ValidationTypeSystem } - return ParameterSchema_HCL + return ParameterSchema_None } func (x *ParameterSchema) GetValidationValueType() string { @@ -1108,7 +1111,7 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x83, 0x05, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8d, 0x05, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, @@ -1147,72 +1150,73 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x12, 0x31, 0x0a, 0x14, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x12, 0x07, 0x0a, 0x03, 0x48, 0x43, 0x4c, 0x10, 0x00, 0x22, 0x4a, 0x0a, 0x03, 0x4c, 0x6f, - 0x67, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, - 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x16, - 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0xfc, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, - 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x1a, 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, - 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, - 0x1a, 0x73, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, + 0x69, 0x6f, 0x6e, 0x22, 0x1f, 0x0a, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x48, + 0x43, 0x4c, 0x10, 0x01, 0x22, 0x4a, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2b, 0x0a, 0x05, 0x6c, + 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x22, 0xfc, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x79, 0x1a, 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, + 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x1a, 0x73, 0x0a, 0x08, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x39, 0x0a, 0x08, + 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, + 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, + 0x32, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x22, 0xe3, 0x02, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x1a, 0x85, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, + 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, - 0x6f, 0x67, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xe3, 0x02, 0x0a, 0x09, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x85, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x79, 0x12, 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, - 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, - 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, - 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, - 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, - 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, - 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, - 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, - 0x32, 0xa1, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x67, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, + 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, + 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, + 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x32, 0xa1, 0x01, 0x0a, 0x0b, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, + 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, + 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4e, + 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x2d, + 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, + 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index 9150c7d9df..78855c5d6e 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -41,7 +41,8 @@ message ParameterSchema { bool redisplay_value = 7; enum TypeSystem { - HCL = 0; + None = 0; + HCL = 1; } TypeSystem validation_type_system = 8; string validation_value_type = 9;