feat: Add backend API support for resource metadata (#3242)

* Initial support for metadata in provisioner API and Terraform provisioner

* add support for nullable metadata fields

* handle metadata fields in provisionerd and API
This commit is contained in:
David Wahler
2022-08-01 16:53:05 -05:00
committed by GitHub
parent 877519232c
commit 8a2811210a
24 changed files with 1231 additions and 214 deletions

View File

@ -35,6 +35,7 @@ func New() database.Store {
provisionerJobAgents: make([]database.WorkspaceAgent, 0), provisionerJobAgents: make([]database.WorkspaceAgent, 0),
provisionerJobLogs: make([]database.ProvisionerJobLog, 0), provisionerJobLogs: make([]database.ProvisionerJobLog, 0),
provisionerJobResources: make([]database.WorkspaceResource, 0), provisionerJobResources: make([]database.WorkspaceResource, 0),
provisionerJobResourceMetadata: make([]database.WorkspaceResourceMetadatum, 0),
provisionerJobs: make([]database.ProvisionerJob, 0), provisionerJobs: make([]database.ProvisionerJob, 0),
templateVersions: make([]database.TemplateVersion, 0), templateVersions: make([]database.TemplateVersion, 0),
templates: make([]database.Template, 0), templates: make([]database.Template, 0),
@ -83,6 +84,7 @@ type data struct {
provisionerJobAgents []database.WorkspaceAgent provisionerJobAgents []database.WorkspaceAgent
provisionerJobLogs []database.ProvisionerJobLog provisionerJobLogs []database.ProvisionerJobLog
provisionerJobResources []database.WorkspaceResource provisionerJobResources []database.WorkspaceResource
provisionerJobResourceMetadata []database.WorkspaceResourceMetadatum
provisionerJobs []database.ProvisionerJob provisionerJobs []database.ProvisionerJob
templateVersions []database.TemplateVersion templateVersions []database.TemplateVersion
templates []database.Template templates []database.Template
@ -1331,6 +1333,34 @@ func (q *fakeQuerier) GetWorkspaceResourcesCreatedAfter(_ context.Context, after
return resources, nil return resources, nil
} }
func (q *fakeQuerier) GetWorkspaceResourceMetadataByResourceID(_ context.Context, id uuid.UUID) ([]database.WorkspaceResourceMetadatum, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
metadata := make([]database.WorkspaceResourceMetadatum, 0)
for _, metadatum := range q.provisionerJobResourceMetadata {
if metadatum.WorkspaceResourceID.String() == id.String() {
metadata = append(metadata, metadatum)
}
}
return metadata, nil
}
func (q *fakeQuerier) GetWorkspaceResourceMetadataByResourceIDs(_ context.Context, ids []uuid.UUID) ([]database.WorkspaceResourceMetadatum, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
metadata := make([]database.WorkspaceResourceMetadatum, 0)
for _, metadatum := range q.provisionerJobResourceMetadata {
for _, id := range ids {
if metadatum.WorkspaceResourceID.String() == id.String() {
metadata = append(metadata, metadatum)
}
}
}
return metadata, nil
}
func (q *fakeQuerier) GetProvisionerJobsByIDs(_ context.Context, ids []uuid.UUID) ([]database.ProvisionerJob, error) { func (q *fakeQuerier) GetProvisionerJobsByIDs(_ context.Context, ids []uuid.UUID) ([]database.ProvisionerJob, error) {
q.mutex.RLock() q.mutex.RLock()
defer q.mutex.RUnlock() defer q.mutex.RUnlock()
@ -1659,6 +1689,21 @@ func (q *fakeQuerier) InsertWorkspaceResource(_ context.Context, arg database.In
return resource, nil return resource, nil
} }
func (q *fakeQuerier) InsertWorkspaceResourceMetadata(_ context.Context, arg database.InsertWorkspaceResourceMetadataParams) (database.WorkspaceResourceMetadatum, error) {
q.mutex.Lock()
defer q.mutex.Unlock()
//nolint:gosimple
metadatum := database.WorkspaceResourceMetadatum{
WorkspaceResourceID: arg.WorkspaceResourceID,
Key: arg.Key,
Value: arg.Value,
Sensitive: arg.Sensitive,
}
q.provisionerJobResourceMetadata = append(q.provisionerJobResourceMetadata, metadatum)
return metadatum, nil
}
func (q *fakeQuerier) InsertUser(_ context.Context, arg database.InsertUserParams) (database.User, error) { func (q *fakeQuerier) InsertUser(_ context.Context, arg database.InsertUserParams) (database.User, error) {
q.mutex.Lock() q.mutex.Lock()
defer q.mutex.Unlock() defer q.mutex.Unlock()

View File

@ -328,6 +328,13 @@ CREATE TABLE workspace_builds (
reason build_reason DEFAULT 'initiator'::public.build_reason NOT NULL reason build_reason DEFAULT 'initiator'::public.build_reason NOT NULL
); );
CREATE TABLE workspace_resource_metadata (
workspace_resource_id uuid NOT NULL,
key character varying(1024) NOT NULL,
value character varying(65536),
sensitive boolean NOT NULL
);
CREATE TABLE workspace_resources ( CREATE TABLE workspace_resources (
id uuid NOT NULL, id uuid NOT NULL,
created_at timestamp with time zone NOT NULL, created_at timestamp with time zone NOT NULL,
@ -433,6 +440,9 @@ ALTER TABLE ONLY workspace_builds
ALTER TABLE ONLY workspace_builds ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_workspace_id_name_key UNIQUE (workspace_id, name); ADD CONSTRAINT workspace_builds_workspace_id_name_key UNIQUE (workspace_id, name);
ALTER TABLE ONLY workspace_resource_metadata
ADD CONSTRAINT workspace_resource_metadata_pkey PRIMARY KEY (workspace_resource_id, key);
ALTER TABLE ONLY workspace_resources ALTER TABLE ONLY workspace_resources
ADD CONSTRAINT workspace_resources_pkey PRIMARY KEY (id); ADD CONSTRAINT workspace_resources_pkey PRIMARY KEY (id);
@ -518,6 +528,9 @@ ALTER TABLE ONLY workspace_builds
ALTER TABLE ONLY workspace_builds ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE; ADD CONSTRAINT workspace_builds_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_resource_metadata
ADD CONSTRAINT workspace_resource_metadata_workspace_resource_id_fkey FOREIGN KEY (workspace_resource_id) REFERENCES workspace_resources(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_resources ALTER TABLE ONLY workspace_resources
ADD CONSTRAINT workspace_resources_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; ADD CONSTRAINT workspace_resources_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE IF EXISTS workspace_resource_metadata;

View File

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS workspace_resource_metadata (
workspace_resource_id uuid NOT NULL,
key varchar(1024) NOT NULL,
value varchar(65536),
sensitive boolean NOT NULL,
PRIMARY KEY (workspace_resource_id, key),
FOREIGN KEY (workspace_resource_id) REFERENCES workspace_resources (id) ON DELETE CASCADE
);

View File

@ -564,3 +564,10 @@ type WorkspaceResource struct {
Type string `db:"type" json:"type"` Type string `db:"type" json:"type"`
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
} }
type WorkspaceResourceMetadatum struct {
WorkspaceResourceID uuid.UUID `db:"workspace_resource_id" json:"workspace_resource_id"`
Key string `db:"key" json:"key"`
Value sql.NullString `db:"value" json:"value"`
Sensitive bool `db:"sensitive" json:"sensitive"`
}

View File

@ -84,6 +84,8 @@ type querier interface {
GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWorkspaceByOwnerIDAndNameParams) (Workspace, error) GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWorkspaceByOwnerIDAndNameParams) (Workspace, error)
GetWorkspaceOwnerCountsByTemplateIDs(ctx context.Context, ids []uuid.UUID) ([]GetWorkspaceOwnerCountsByTemplateIDsRow, error) GetWorkspaceOwnerCountsByTemplateIDs(ctx context.Context, ids []uuid.UUID) ([]GetWorkspaceOwnerCountsByTemplateIDsRow, error)
GetWorkspaceResourceByID(ctx context.Context, id uuid.UUID) (WorkspaceResource, error) GetWorkspaceResourceByID(ctx context.Context, id uuid.UUID) (WorkspaceResource, error)
GetWorkspaceResourceMetadataByResourceID(ctx context.Context, workspaceResourceID uuid.UUID) ([]WorkspaceResourceMetadatum, error)
GetWorkspaceResourceMetadataByResourceIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceResourceMetadatum, error)
GetWorkspaceResourcesByJobID(ctx context.Context, jobID uuid.UUID) ([]WorkspaceResource, error) GetWorkspaceResourcesByJobID(ctx context.Context, jobID uuid.UUID) ([]WorkspaceResource, error)
GetWorkspaceResourcesCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceResource, error) GetWorkspaceResourcesCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceResource, error)
GetWorkspaces(ctx context.Context, arg GetWorkspacesParams) ([]Workspace, error) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams) ([]Workspace, error)
@ -108,6 +110,7 @@ type querier interface {
InsertWorkspaceApp(ctx context.Context, arg InsertWorkspaceAppParams) (WorkspaceApp, error) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspaceAppParams) (WorkspaceApp, error)
InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspaceBuildParams) (WorkspaceBuild, error) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspaceBuildParams) (WorkspaceBuild, error)
InsertWorkspaceResource(ctx context.Context, arg InsertWorkspaceResourceParams) (WorkspaceResource, error) InsertWorkspaceResource(ctx context.Context, arg InsertWorkspaceResourceParams) (WorkspaceResource, error)
InsertWorkspaceResourceMetadata(ctx context.Context, arg InsertWorkspaceResourceMetadataParams) (WorkspaceResourceMetadatum, error)
ParameterValue(ctx context.Context, id uuid.UUID) (ParameterValue, error) ParameterValue(ctx context.Context, id uuid.UUID) (ParameterValue, error)
ParameterValues(ctx context.Context, arg ParameterValuesParams) ([]ParameterValue, error) ParameterValues(ctx context.Context, arg ParameterValuesParams) ([]ParameterValue, error)
UpdateAPIKeyByID(ctx context.Context, arg UpdateAPIKeyByIDParams) error UpdateAPIKeyByID(ctx context.Context, arg UpdateAPIKeyByIDParams) error

View File

@ -3895,6 +3895,80 @@ func (q *sqlQuerier) GetWorkspaceResourceByID(ctx context.Context, id uuid.UUID)
return i, err return i, err
} }
const getWorkspaceResourceMetadataByResourceID = `-- name: GetWorkspaceResourceMetadataByResourceID :many
SELECT
workspace_resource_id, key, value, sensitive
FROM
workspace_resource_metadata
WHERE
workspace_resource_id = $1
`
func (q *sqlQuerier) GetWorkspaceResourceMetadataByResourceID(ctx context.Context, workspaceResourceID uuid.UUID) ([]WorkspaceResourceMetadatum, error) {
rows, err := q.db.QueryContext(ctx, getWorkspaceResourceMetadataByResourceID, workspaceResourceID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []WorkspaceResourceMetadatum
for rows.Next() {
var i WorkspaceResourceMetadatum
if err := rows.Scan(
&i.WorkspaceResourceID,
&i.Key,
&i.Value,
&i.Sensitive,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getWorkspaceResourceMetadataByResourceIDs = `-- name: GetWorkspaceResourceMetadataByResourceIDs :many
SELECT
workspace_resource_id, key, value, sensitive
FROM
workspace_resource_metadata
WHERE
workspace_resource_id = ANY($1 :: uuid [ ])
`
func (q *sqlQuerier) GetWorkspaceResourceMetadataByResourceIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceResourceMetadatum, error) {
rows, err := q.db.QueryContext(ctx, getWorkspaceResourceMetadataByResourceIDs, pq.Array(ids))
if err != nil {
return nil, err
}
defer rows.Close()
var items []WorkspaceResourceMetadatum
for rows.Next() {
var i WorkspaceResourceMetadatum
if err := rows.Scan(
&i.WorkspaceResourceID,
&i.Key,
&i.Value,
&i.Sensitive,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getWorkspaceResourcesByJobID = `-- name: GetWorkspaceResourcesByJobID :many const getWorkspaceResourcesByJobID = `-- name: GetWorkspaceResourcesByJobID :many
SELECT SELECT
id, created_at, job_id, transition, type, name id, created_at, job_id, transition, type, name
@ -4005,6 +4079,37 @@ func (q *sqlQuerier) InsertWorkspaceResource(ctx context.Context, arg InsertWork
return i, err return i, err
} }
const insertWorkspaceResourceMetadata = `-- name: InsertWorkspaceResourceMetadata :one
INSERT INTO
workspace_resource_metadata (workspace_resource_id, key, value, sensitive)
VALUES
($1, $2, $3, $4) RETURNING workspace_resource_id, key, value, sensitive
`
type InsertWorkspaceResourceMetadataParams struct {
WorkspaceResourceID uuid.UUID `db:"workspace_resource_id" json:"workspace_resource_id"`
Key string `db:"key" json:"key"`
Value sql.NullString `db:"value" json:"value"`
Sensitive bool `db:"sensitive" json:"sensitive"`
}
func (q *sqlQuerier) InsertWorkspaceResourceMetadata(ctx context.Context, arg InsertWorkspaceResourceMetadataParams) (WorkspaceResourceMetadatum, error) {
row := q.db.QueryRowContext(ctx, insertWorkspaceResourceMetadata,
arg.WorkspaceResourceID,
arg.Key,
arg.Value,
arg.Sensitive,
)
var i WorkspaceResourceMetadatum
err := row.Scan(
&i.WorkspaceResourceID,
&i.Key,
&i.Value,
&i.Sensitive,
)
return i, err
}
const getWorkspaceByID = `-- name: GetWorkspaceByID :one const getWorkspaceByID = `-- name: GetWorkspaceByID :one
SELECT SELECT
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl

View File

@ -22,3 +22,25 @@ INSERT INTO
workspace_resources (id, created_at, job_id, transition, type, name) workspace_resources (id, created_at, job_id, transition, type, name)
VALUES VALUES
($1, $2, $3, $4, $5, $6) RETURNING *; ($1, $2, $3, $4, $5, $6) RETURNING *;
-- name: GetWorkspaceResourceMetadataByResourceID :many
SELECT
*
FROM
workspace_resource_metadata
WHERE
workspace_resource_id = $1;
-- name: GetWorkspaceResourceMetadataByResourceIDs :many
SELECT
*
FROM
workspace_resource_metadata
WHERE
workspace_resource_id = ANY(@ids :: uuid [ ]);
-- name: InsertWorkspaceResourceMetadata :one
INSERT INTO
workspace_resource_metadata (workspace_resource_id, key, value, sensitive)
VALUES
($1, $2, $3, $4) RETURNING *;

View File

@ -829,6 +829,25 @@ func insertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
snapshot.WorkspaceApps = append(snapshot.WorkspaceApps, telemetry.ConvertWorkspaceApp(dbApp)) snapshot.WorkspaceApps = append(snapshot.WorkspaceApps, telemetry.ConvertWorkspaceApp(dbApp))
} }
} }
for _, metadatum := range protoResource.Metadata {
var value sql.NullString
if !metadatum.IsNull {
value.String = metadatum.Value
value.Valid = true
}
_, err := db.InsertWorkspaceResourceMetadata(ctx, database.InsertWorkspaceResourceMetadataParams{
WorkspaceResourceID: resource.ID,
Key: metadatum.Key,
Value: value,
Sensitive: metadatum.Sensitive,
})
if err != nil {
return xerrors.Errorf("insert metadata: %w", err)
}
}
return nil return nil
} }

View File

@ -241,6 +241,14 @@ func (api *API) provisionerJobResources(rw http.ResponseWriter, r *http.Request,
}) })
return return
} }
resourceMetadata, err := api.Database.GetWorkspaceResourceMetadataByResourceIDs(r.Context(), resourceIDs)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace metadata.",
Detail: err.Error(),
})
return
}
apiResources := make([]codersdk.WorkspaceResource, 0) apiResources := make([]codersdk.WorkspaceResource, 0)
for _, resource := range resources { for _, resource := range resources {
@ -266,7 +274,13 @@ func (api *API) provisionerJobResources(rw http.ResponseWriter, r *http.Request,
} }
agents = append(agents, apiAgent) agents = append(agents, apiAgent)
} }
apiResources = append(apiResources, convertWorkspaceResource(resource, agents)) metadata := make([]database.WorkspaceResourceMetadatum, 0)
for _, field := range resourceMetadata {
if field.WorkspaceResourceID == resource.ID {
metadata = append(metadata, field)
}
}
apiResources = append(apiResources, convertWorkspaceResource(resource, agents, metadata))
} }
httpapi.Write(rw, http.StatusOK, apiResources) httpapi.Write(rw, http.StatusOK, apiResources)

View File

@ -11,6 +11,7 @@ import (
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/moby/moby/pkg/namesgenerator" "github.com/moby/moby/pkg/namesgenerator"
"golang.org/x/exp/slices"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
@ -681,7 +682,35 @@ func convertWorkspaceBuild(
} }
} }
func convertWorkspaceResource(resource database.WorkspaceResource, agents []codersdk.WorkspaceAgent) codersdk.WorkspaceResource { func convertWorkspaceResource(resource database.WorkspaceResource, agents []codersdk.WorkspaceAgent, metadata []database.WorkspaceResourceMetadatum) codersdk.WorkspaceResource {
metadataMap := map[string]database.WorkspaceResourceMetadatum{}
// implicit metadata fields come first
metadataMap["type"] = database.WorkspaceResourceMetadatum{
Key: "type",
Value: sql.NullString{String: resource.Type, Valid: true},
Sensitive: false,
}
// explicit metadata fields come afterward, and can override implicit ones
for _, field := range metadata {
metadataMap[field.Key] = field
}
var convertedMetadata []codersdk.WorkspaceResourceMetadata
for _, field := range metadataMap {
if field.Value.Valid {
convertedField := codersdk.WorkspaceResourceMetadata{
Key: field.Key,
Value: field.Value.String,
Sensitive: field.Sensitive,
}
convertedMetadata = append(convertedMetadata, convertedField)
}
}
slices.SortFunc(convertedMetadata, func(a, b codersdk.WorkspaceResourceMetadata) bool {
return a.Key < b.Key
})
return codersdk.WorkspaceResource{ return codersdk.WorkspaceResource{
ID: resource.ID, ID: resource.ID,
CreatedAt: resource.CreatedAt, CreatedAt: resource.CreatedAt,
@ -690,5 +719,6 @@ func convertWorkspaceResource(resource database.WorkspaceResource, agents []code
Type: resource.Type, Type: resource.Type,
Name: resource.Name, Name: resource.Name,
Agents: agents, Agents: agents,
Metadata: convertedMetadata,
} }
} }

View File

@ -80,5 +80,14 @@ func (api *API) workspaceResource(rw http.ResponseWriter, r *http.Request) {
apiAgents = append(apiAgents, convertedAgent) apiAgents = append(apiAgents, convertedAgent)
} }
httpapi.Write(rw, http.StatusOK, convertWorkspaceResource(workspaceResource, apiAgents)) metadata, err := api.Database.GetWorkspaceResourceMetadataByResourceID(r.Context(), workspaceResource.ID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resource metadata.",
Detail: err.Error(),
})
return
}
httpapi.Write(rw, http.StatusOK, convertWorkspaceResource(workspaceResource, apiAgents, metadata))
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/coder/coder/coderd/coderdtest" "github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/provisioner/echo" "github.com/coder/coder/provisioner/echo"
"github.com/coder/coder/provisionersdk/proto" "github.com/coder/coder/provisionersdk/proto"
) )
@ -90,4 +91,64 @@ func TestWorkspaceResource(t *testing.T) {
require.Equal(t, app.Icon, got.Icon) require.Equal(t, app.Icon, got.Icon)
require.Equal(t, app.Name, got.Name) require.Equal(t, app.Name, got.Name)
}) })
t.Run("Metadata", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerD: true,
})
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
Provision: []*proto.Provision_Response{{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{
Resources: []*proto.Resource{{
Name: "some",
Type: "example",
Agents: []*proto.Agent{{
Id: "something",
Auth: &proto.Agent_Token{},
}},
Metadata: []*proto.Resource_Metadata{{
Key: "foo",
Value: "bar",
}, {
Key: "null",
IsNull: true,
}, {
Key: "empty",
}, {
Key: "secret",
Value: "squirrel",
Sensitive: true,
}},
}},
},
},
}},
})
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
require.NoError(t, err)
resource, err := client.WorkspaceResource(context.Background(), resources[0].ID)
require.NoError(t, err)
metadata := resource.Metadata
require.Equal(t, []codersdk.WorkspaceResourceMetadata{{
Key: "empty",
}, {
Key: "foo",
Value: "bar",
}, {
Key: "secret",
Value: "squirrel",
Sensitive: true,
}, {
Key: "type",
Value: "example",
}}, metadata)
})
} }

View File

@ -28,6 +28,13 @@ type WorkspaceResource struct {
Type string `json:"type"` Type string `json:"type"`
Name string `json:"name"` Name string `json:"name"`
Agents []WorkspaceAgent `json:"agents,omitempty"` Agents []WorkspaceAgent `json:"agents,omitempty"`
Metadata []WorkspaceResourceMetadata `json:"metadata,omitempty"`
}
type WorkspaceResourceMetadata struct {
Key string `json:"key"`
Value string `json:"value"`
Sensitive bool `json:"sensitive"`
} }
type WorkspaceAgent struct { type WorkspaceAgent struct {

View File

@ -33,6 +33,19 @@ type agentAppAttributes struct {
RelativePath bool `mapstructure:"relative_path"` RelativePath bool `mapstructure:"relative_path"`
} }
// A mapping of attributes on the "coder_metadata" resource.
type metadataAttributes struct {
ResourceID string `mapstructure:"resource_id"`
Items []metadataItem `mapstructure:"item"`
}
type metadataItem struct {
Key string `mapstructure:"key"`
Value string `mapstructure:"value"`
Sensitive bool `mapstructure:"sensitive"`
IsNull bool `mapstructure:"is_null"`
}
// ConvertResources consumes Terraform state and a GraphViz representation produced by // ConvertResources consumes Terraform state and a GraphViz representation produced by
// `terraform graph` to produce resources consumable by Coder. // `terraform graph` to produce resources consumable by Coder.
func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Resource, error) { func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Resource, error) {
@ -48,16 +61,30 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
resources := make([]*proto.Resource, 0) resources := make([]*proto.Resource, 0)
resourceAgents := map[string][]*proto.Agent{} resourceAgents := map[string][]*proto.Agent{}
// Indexes Terraform resources by it's label. The label // Indexes Terraform resources by their label and ID.
// is what "terraform graph" uses to reference nodes. // The label is what "terraform graph" uses to reference nodes, and the ID
// is used by "coder_metadata" resources to refer to their targets. (The ID
// field is only available when reading a state file, and not when reading a
// plan file.)
tfResourceByLabel := map[string]*tfjson.StateResource{} tfResourceByLabel := map[string]*tfjson.StateResource{}
resourceLabelByID := map[string]string{}
var findTerraformResources func(mod *tfjson.StateModule) var findTerraformResources func(mod *tfjson.StateModule)
findTerraformResources = func(mod *tfjson.StateModule) { findTerraformResources = func(mod *tfjson.StateModule) {
for _, module := range mod.ChildModules { for _, module := range mod.ChildModules {
findTerraformResources(module) findTerraformResources(module)
} }
for _, resource := range mod.Resources { for _, resource := range mod.Resources {
tfResourceByLabel[convertAddressToLabel(resource.Address)] = resource label := convertAddressToLabel(resource.Address)
// index by label
tfResourceByLabel[label] = resource
// index by ID, if it exists
id, ok := resource.AttributeValues["id"]
if ok {
idString, ok := id.(string)
if ok {
resourceLabelByID[idString] = label
}
}
} }
} }
findTerraformResources(module) findTerraformResources(module)
@ -205,15 +232,50 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
} }
} }
// Associate metadata blocks with resources.
resourceMetadata := map[string][]*proto.Resource_Metadata{}
for label, resource := range tfResourceByLabel {
if resource.Type != "coder_metadata" {
continue
}
var attrs metadataAttributes
err = mapstructure.Decode(resource.AttributeValues, &attrs)
if err != nil {
return nil, xerrors.Errorf("decode metadata attributes: %w", err)
}
if attrs.ResourceID == "" {
// TODO: detect this as an error
// At plan time, change.after_unknown.resource_id should be "true".
// At provision time, values.resource_id should be set.
continue
}
targetLabel, ok := resourceLabelByID[attrs.ResourceID]
if !ok {
return nil, xerrors.Errorf("attribute %s.resource_id = %q does not refer to a valid resource", label, attrs.ResourceID)
}
for _, item := range attrs.Items {
resourceMetadata[targetLabel] = append(resourceMetadata[targetLabel],
&proto.Resource_Metadata{
Key: item.Key,
Value: item.Value,
Sensitive: item.Sensitive,
IsNull: item.IsNull,
})
}
}
for _, resource := range tfResourceByLabel { for _, resource := range tfResourceByLabel {
if resource.Mode == tfjson.DataResourceMode { if resource.Mode == tfjson.DataResourceMode {
continue continue
} }
if resource.Type == "coder_agent" || resource.Type == "coder_agent_instance" || resource.Type == "coder_app" { if resource.Type == "coder_agent" || resource.Type == "coder_agent_instance" || resource.Type == "coder_app" || resource.Type == "coder_metadata" {
continue continue
} }
label := convertAddressToLabel(resource.Address)
agents, exists := resourceAgents[convertAddressToLabel(resource.Address)] agents, exists := resourceAgents[label]
if exists { if exists {
applyAutomaticInstanceID(resource, agents) applyAutomaticInstanceID(resource, agents)
} }
@ -222,6 +284,7 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
Name: resource.Name, Name: resource.Name,
Type: resource.Type, Type: resource.Type,
Agents: agents, Agents: agents,
Metadata: resourceMetadata[label],
}) })
} }

View File

@ -14,6 +14,8 @@ import (
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
"github.com/coder/coder/provisioner/terraform" "github.com/coder/coder/provisioner/terraform"
"github.com/coder/coder/provisionersdk/proto" "github.com/coder/coder/provisionersdk/proto"
protobuf "github.com/golang/protobuf/proto"
) )
func TestConvertResources(t *testing.T) { func TestConvertResources(t *testing.T) {
@ -114,6 +116,24 @@ func TestConvertResources(t *testing.T) {
Auth: &proto.Agent_Token{}, Auth: &proto.Agent_Token{},
}}, }},
}}, }},
// Tests fetching metadata about workspace resources.
"resource-metadata": {{
Name: "about",
Type: "null_resource",
Metadata: []*proto.Resource_Metadata{{
Key: "hello",
Value: "world",
}, {
Key: "null",
IsNull: true,
}, {
Key: "empty",
}, {
Key: "secret",
Value: "squirrel",
Sensitive: true,
}},
}},
} { } {
folderName := folderName folderName := folderName
expected := expected expected := expected
@ -134,7 +154,16 @@ func TestConvertResources(t *testing.T) {
resources, err := terraform.ConvertResources(tfPlan.PlannedValues.RootModule, string(tfPlanGraph)) resources, err := terraform.ConvertResources(tfPlan.PlannedValues.RootModule, string(tfPlanGraph))
require.NoError(t, err) require.NoError(t, err)
sortResources(resources) sortResources(resources)
resourcesWant, err := json.Marshal(expected)
// plan does not contain metadata, so clone expected and remove it
var expectedNoMetadata []*proto.Resource
for _, resource := range expected {
resourceCopy, _ := protobuf.Clone(resource).(*proto.Resource)
resourceCopy.Metadata = nil
expectedNoMetadata = append(expectedNoMetadata, resourceCopy)
}
resourcesWant, err := json.Marshal(expectedNoMetadata)
require.NoError(t, err) require.NoError(t, err)
resourcesGot, err := json.Marshal(resources) resourcesGot, err := json.Marshal(resources)
require.NoError(t, err) require.NoError(t, err)

View File

@ -0,0 +1,35 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
version = "0.4.4"
}
}
}
resource "coder_agent" "main" {
os = "linux"
arch = "amd64"
}
resource "null_resource" "about" {}
resource "coder_metadata" "about_info" {
resource_id = null_resource.about.id
item {
key = "hello"
value = "world"
}
item {
key = "null"
}
item {
key = "empty"
value = ""
}
item {
key = "secret"
value = "squirrel"
sensitive = true
}
}

View File

@ -0,0 +1,21 @@
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"]
"[root] coder_metadata.about_info (expand)" [label = "coder_metadata.about_info", shape = "box"]
"[root] null_resource.about (expand)" [label = "null_resource.about", shape = "box"]
"[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"]
"[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"]
"[root] coder_agent.main (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] coder_metadata.about_info (expand)" -> "[root] null_resource.about (expand)"
"[root] coder_metadata.about_info (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] null_resource.about (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.main (expand)"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_metadata.about_info (expand)"
"[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.about (expand)"
"[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)"
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)"
}
}

View File

@ -0,0 +1,293 @@
{
"format_version": "1.1",
"terraform_version": "1.2.6",
"planned_values": {
"root_module": {
"resources": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"arch": "amd64",
"auth": "token",
"dir": null,
"env": null,
"os": "linux",
"startup_script": null
},
"sensitive_values": {}
},
{
"address": "coder_metadata.about_info",
"mode": "managed",
"type": "coder_metadata",
"name": "about_info",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"item": [
{
"key": "hello",
"sensitive": false,
"value": "world"
},
{
"key": "null",
"sensitive": false,
"value": null
},
{
"key": "empty",
"sensitive": false,
"value": ""
},
{
"key": "secret",
"sensitive": true,
"value": "squirrel"
}
]
},
"sensitive_values": {
"item": [
{},
{},
{},
{}
]
}
},
{
"address": "null_resource.about",
"mode": "managed",
"type": "null_resource",
"name": "about",
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"triggers": null
},
"sensitive_values": {}
}
]
}
},
"resource_changes": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"arch": "amd64",
"auth": "token",
"dir": null,
"env": null,
"os": "linux",
"startup_script": null
},
"after_unknown": {
"id": true,
"init_script": true,
"token": true
},
"before_sensitive": false,
"after_sensitive": {}
}
},
{
"address": "coder_metadata.about_info",
"mode": "managed",
"type": "coder_metadata",
"name": "about_info",
"provider_name": "registry.terraform.io/coder/coder",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"item": [
{
"key": "hello",
"sensitive": false,
"value": "world"
},
{
"key": "null",
"sensitive": false,
"value": null
},
{
"key": "empty",
"sensitive": false,
"value": ""
},
{
"key": "secret",
"sensitive": true,
"value": "squirrel"
}
]
},
"after_unknown": {
"id": true,
"item": [
{
"is_null": true
},
{
"is_null": true
},
{
"is_null": true
},
{
"is_null": true
}
],
"resource_id": true
},
"before_sensitive": false,
"after_sensitive": {
"item": [
{},
{},
{},
{}
]
}
}
},
{
"address": "null_resource.about",
"mode": "managed",
"type": "null_resource",
"name": "about",
"provider_name": "registry.terraform.io/hashicorp/null",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"triggers": null
},
"after_unknown": {
"id": true
},
"before_sensitive": false,
"after_sensitive": {}
}
}
],
"configuration": {
"provider_config": {
"coder": {
"name": "coder",
"full_name": "registry.terraform.io/coder/coder",
"version_constraint": "0.4.4"
},
"null": {
"name": "null",
"full_name": "registry.terraform.io/hashicorp/null"
}
},
"root_module": {
"resources": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_config_key": "coder",
"expressions": {
"arch": {
"constant_value": "amd64"
},
"os": {
"constant_value": "linux"
}
},
"schema_version": 0
},
{
"address": "coder_metadata.about_info",
"mode": "managed",
"type": "coder_metadata",
"name": "about_info",
"provider_config_key": "coder",
"expressions": {
"item": [
{
"key": {
"constant_value": "hello"
},
"value": {
"constant_value": "world"
}
},
{
"key": {
"constant_value": "null"
}
},
{
"key": {
"constant_value": "empty"
},
"value": {
"constant_value": ""
}
},
{
"key": {
"constant_value": "secret"
},
"sensitive": {
"constant_value": true
},
"value": {
"constant_value": "squirrel"
}
}
],
"resource_id": {
"references": [
"null_resource.about.id",
"null_resource.about"
]
}
},
"schema_version": 0
},
{
"address": "null_resource.about",
"mode": "managed",
"type": "null_resource",
"name": "about",
"provider_config_key": "null",
"schema_version": 0
}
]
}
},
"relevant_attributes": [
{
"resource": "null_resource.about",
"attribute": [
"id"
]
}
]
}

View File

@ -0,0 +1,21 @@
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"]
"[root] coder_metadata.about_info (expand)" [label = "coder_metadata.about_info", shape = "box"]
"[root] null_resource.about (expand)" [label = "null_resource.about", shape = "box"]
"[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"]
"[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"]
"[root] coder_agent.main (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] coder_metadata.about_info (expand)" -> "[root] null_resource.about (expand)"
"[root] coder_metadata.about_info (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] null_resource.about (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.main (expand)"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_metadata.about_info (expand)"
"[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.about (expand)"
"[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)"
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)"
}
}

View File

@ -0,0 +1,92 @@
{
"format_version": "1.0",
"terraform_version": "1.2.6",
"values": {
"root_module": {
"resources": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"arch": "amd64",
"auth": "token",
"dir": null,
"env": null,
"id": "33d1fa51-2987-43da-8f07-53131af520f2",
"init_script": "",
"os": "linux",
"startup_script": null,
"token": "5acee40a-6f4f-4e38-92a8-98b057d4945f"
},
"sensitive_values": {}
},
{
"address": "coder_metadata.about_info",
"mode": "managed",
"type": "coder_metadata",
"name": "about_info",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"id": "5b828eb0-938f-4fba-8599-701dce975627",
"item": [
{
"is_null": false,
"key": "hello",
"sensitive": false,
"value": "world"
},
{
"is_null": true,
"key": "null",
"sensitive": false,
"value": ""
},
{
"is_null": false,
"key": "empty",
"sensitive": false,
"value": ""
},
{
"is_null": false,
"key": "secret",
"sensitive": true,
"value": "squirrel"
}
],
"resource_id": "6511007151682544728"
},
"sensitive_values": {
"item": [
{},
{},
{},
{}
]
},
"depends_on": [
"null_resource.about"
]
},
{
"address": "null_resource.about",
"mode": "managed",
"type": "null_resource",
"name": "about",
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "6511007151682544728",
"triggers": null
},
"sensitive_values": {}
}
]
}
}
}

View File

@ -932,6 +932,7 @@ type Resource struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
Agents []*Agent `protobuf:"bytes,3,rep,name=agents,proto3" json:"agents,omitempty"` Agents []*Agent `protobuf:"bytes,3,rep,name=agents,proto3" json:"agents,omitempty"`
Metadata []*Resource_Metadata `protobuf:"bytes,4,rep,name=metadata,proto3" json:"metadata,omitempty"`
} }
func (x *Resource) Reset() { func (x *Resource) Reset() {
@ -987,6 +988,13 @@ func (x *Resource) GetAgents() []*Agent {
return nil return nil
} }
func (x *Resource) GetMetadata() []*Resource_Metadata {
if x != nil {
return x.Metadata
}
return nil
}
// Parse consumes source-code from a directory to produce inputs. // Parse consumes source-code from a directory to produce inputs.
type Parse struct { type Parse struct {
state protoimpl.MessageState state protoimpl.MessageState
@ -1065,6 +1073,77 @@ func (*Provision) Descriptor() ([]byte, []int) {
return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{11} return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{11}
} }
type Resource_Metadata struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
Sensitive bool `protobuf:"varint,3,opt,name=sensitive,proto3" json:"sensitive,omitempty"`
IsNull bool `protobuf:"varint,4,opt,name=is_null,json=isNull,proto3" json:"is_null,omitempty"`
}
func (x *Resource_Metadata) Reset() {
*x = Resource_Metadata{}
if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Resource_Metadata) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Resource_Metadata) ProtoMessage() {}
func (x *Resource_Metadata) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Resource_Metadata.ProtoReflect.Descriptor instead.
func (*Resource_Metadata) Descriptor() ([]byte, []int) {
return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{9, 0}
}
func (x *Resource_Metadata) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *Resource_Metadata) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
func (x *Resource_Metadata) GetSensitive() bool {
if x != nil {
return x.Sensitive
}
return false
}
func (x *Resource_Metadata) GetIsNull() bool {
if x != nil {
return x.IsNull
}
return false
}
type Parse_Request struct { type Parse_Request struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -1076,7 +1155,7 @@ type Parse_Request struct {
func (x *Parse_Request) Reset() { func (x *Parse_Request) Reset() {
*x = Parse_Request{} *x = Parse_Request{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1089,7 +1168,7 @@ func (x *Parse_Request) String() string {
func (*Parse_Request) ProtoMessage() {} func (*Parse_Request) ProtoMessage() {}
func (x *Parse_Request) ProtoReflect() protoreflect.Message { func (x *Parse_Request) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1123,7 +1202,7 @@ type Parse_Complete struct {
func (x *Parse_Complete) Reset() { func (x *Parse_Complete) Reset() {
*x = Parse_Complete{} *x = Parse_Complete{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1136,7 +1215,7 @@ func (x *Parse_Complete) String() string {
func (*Parse_Complete) ProtoMessage() {} func (*Parse_Complete) ProtoMessage() {}
func (x *Parse_Complete) ProtoReflect() protoreflect.Message { func (x *Parse_Complete) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1173,7 +1252,7 @@ type Parse_Response struct {
func (x *Parse_Response) Reset() { func (x *Parse_Response) Reset() {
*x = Parse_Response{} *x = Parse_Response{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1186,7 +1265,7 @@ func (x *Parse_Response) String() string {
func (*Parse_Response) ProtoMessage() {} func (*Parse_Response) ProtoMessage() {}
func (x *Parse_Response) ProtoReflect() protoreflect.Message { func (x *Parse_Response) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1256,7 +1335,7 @@ type Provision_Metadata struct {
func (x *Provision_Metadata) Reset() { func (x *Provision_Metadata) Reset() {
*x = Provision_Metadata{} *x = Provision_Metadata{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1269,7 +1348,7 @@ func (x *Provision_Metadata) String() string {
func (*Provision_Metadata) ProtoMessage() {} func (*Provision_Metadata) ProtoMessage() {}
func (x *Provision_Metadata) ProtoReflect() protoreflect.Message { func (x *Provision_Metadata) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1349,7 +1428,7 @@ type Provision_Start struct {
func (x *Provision_Start) Reset() { func (x *Provision_Start) Reset() {
*x = Provision_Start{} *x = Provision_Start{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1362,7 +1441,7 @@ func (x *Provision_Start) String() string {
func (*Provision_Start) ProtoMessage() {} func (*Provision_Start) ProtoMessage() {}
func (x *Provision_Start) ProtoReflect() protoreflect.Message { func (x *Provision_Start) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1422,7 +1501,7 @@ type Provision_Cancel struct {
func (x *Provision_Cancel) Reset() { func (x *Provision_Cancel) Reset() {
*x = Provision_Cancel{} *x = Provision_Cancel{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1435,7 +1514,7 @@ func (x *Provision_Cancel) String() string {
func (*Provision_Cancel) ProtoMessage() {} func (*Provision_Cancel) ProtoMessage() {}
func (x *Provision_Cancel) ProtoReflect() protoreflect.Message { func (x *Provision_Cancel) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1465,7 +1544,7 @@ type Provision_Request struct {
func (x *Provision_Request) Reset() { func (x *Provision_Request) Reset() {
*x = Provision_Request{} *x = Provision_Request{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1478,7 +1557,7 @@ func (x *Provision_Request) String() string {
func (*Provision_Request) ProtoMessage() {} func (*Provision_Request) ProtoMessage() {}
func (x *Provision_Request) ProtoReflect() protoreflect.Message { func (x *Provision_Request) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1544,7 +1623,7 @@ type Provision_Complete struct {
func (x *Provision_Complete) Reset() { func (x *Provision_Complete) Reset() {
*x = Provision_Complete{} *x = Provision_Complete{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1557,7 +1636,7 @@ func (x *Provision_Complete) String() string {
func (*Provision_Complete) ProtoMessage() {} func (*Provision_Complete) ProtoMessage() {}
func (x *Provision_Complete) ProtoReflect() protoreflect.Message { func (x *Provision_Complete) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1608,7 +1687,7 @@ type Provision_Response struct {
func (x *Provision_Response) Reset() { func (x *Provision_Response) Reset() {
*x = Provision_Response{} *x = Provision_Response{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1621,7 +1700,7 @@ func (x *Provision_Response) String() string {
func (*Provision_Response) ProtoMessage() {} func (*Provision_Response) ProtoMessage() {}
func (x *Provision_Response) ProtoReflect() protoreflect.Message { func (x *Provision_Response) ProtoReflect() protoreflect.Message {
mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21] mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1789,110 +1868,120 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{
0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c,
0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, 0x5e, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, 0x85,
0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74,
0x70, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20,
0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xfc, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x12,
0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x3a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28,
0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
0x79, 0x1a, 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x49, 0x0a, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x69, 0x0a, 0x08, 0x4d,
0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12,
0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01,
0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x1a, 0x73, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x17, 0x0a,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06,
0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0xfc, 0x01, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65,
0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64,
0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x1a, 0x55, 0x0a, 0x08, 0x43, 0x6f, 0x6d,
0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xae, 0x07, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xd1, 0x02, 0x0a, 0x08,
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x64, 0x65,
0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x64,
0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x72, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x6f,
0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f,
0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b,
0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f,
0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a,
0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72,
0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73,
0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x77,
0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x65,
0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b,
0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x1a,
0xd9, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72, 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,
0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 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, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05,
0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61,
0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x05, 0x20,
0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x08, 0x0a, 0x06, 0x43,
0x61, 0x6e, 0x63, 0x65, 0x6c, 0x1a, 0x80, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x34, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50,
0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x48, 0x00, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10,
0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73,
0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x1a, 0x73, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03,
0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76,
0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c,
0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x1a, 0x6b, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x67, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02,
0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a,
0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xae, 0x07, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x69, 0x6f, 0x6e, 0x1a, 0xd1, 0x02, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20,
0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a,
0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73,
0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x72,
0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70,
0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77,
0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b,
0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72,
0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e,
0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f,
0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65,
0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01,
0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e,
0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x1a, 0xd9, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72,
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, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
0x61, 0x74, 0x61, 0x18, 0x03, 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, 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, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61,
0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20,
0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72,
0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79,
0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x75, 0x6e, 0x1a, 0x08, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x1a, 0x80, 0x01,
0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x2a, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x05, 0x73, 0x74, 0x61,
0x37, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12,
0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x10, 0x02, 0x32, 0xa3, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72,
0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x48, 0x00,
0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x1a, 0x6b, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x50, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61,
0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f,
0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x2d, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x77, 0x0a,
0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67,
0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12,
0x72, 0x6f, 0x74, 0x6f, 0x33, 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, 0x2a, 0x37, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73,
0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09,
0x0a, 0x05, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f,
0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x10, 0x02,
0x32, 0xa3, 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, 0x50, 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, 0x28, 0x01, 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 ( var (
@ -1908,7 +1997,7 @@ func file_provisionersdk_proto_provisioner_proto_rawDescGZIP() []byte {
} }
var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 5) var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{ var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{
(LogLevel)(0), // 0: provisioner.LogLevel (LogLevel)(0), // 0: provisioner.LogLevel
(WorkspaceTransition)(0), // 1: provisioner.WorkspaceTransition (WorkspaceTransition)(0), // 1: provisioner.WorkspaceTransition
@ -1928,15 +2017,16 @@ var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{
(*Parse)(nil), // 15: provisioner.Parse (*Parse)(nil), // 15: provisioner.Parse
(*Provision)(nil), // 16: provisioner.Provision (*Provision)(nil), // 16: provisioner.Provision
nil, // 17: provisioner.Agent.EnvEntry nil, // 17: provisioner.Agent.EnvEntry
(*Parse_Request)(nil), // 18: provisioner.Parse.Request (*Resource_Metadata)(nil), // 18: provisioner.Resource.Metadata
(*Parse_Complete)(nil), // 19: provisioner.Parse.Complete (*Parse_Request)(nil), // 19: provisioner.Parse.Request
(*Parse_Response)(nil), // 20: provisioner.Parse.Response (*Parse_Complete)(nil), // 20: provisioner.Parse.Complete
(*Provision_Metadata)(nil), // 21: provisioner.Provision.Metadata (*Parse_Response)(nil), // 21: provisioner.Parse.Response
(*Provision_Start)(nil), // 22: provisioner.Provision.Start (*Provision_Metadata)(nil), // 22: provisioner.Provision.Metadata
(*Provision_Cancel)(nil), // 23: provisioner.Provision.Cancel (*Provision_Start)(nil), // 23: provisioner.Provision.Start
(*Provision_Request)(nil), // 24: provisioner.Provision.Request (*Provision_Cancel)(nil), // 24: provisioner.Provision.Cancel
(*Provision_Complete)(nil), // 25: provisioner.Provision.Complete (*Provision_Request)(nil), // 25: provisioner.Provision.Request
(*Provision_Response)(nil), // 26: provisioner.Provision.Response (*Provision_Complete)(nil), // 26: provisioner.Provision.Complete
(*Provision_Response)(nil), // 27: provisioner.Provision.Response
} }
var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{ var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{
2, // 0: provisioner.ParameterSource.scheme:type_name -> provisioner.ParameterSource.Scheme 2, // 0: provisioner.ParameterSource.scheme:type_name -> provisioner.ParameterSource.Scheme
@ -1949,26 +2039,27 @@ var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{
17, // 7: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry 17, // 7: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry
13, // 8: provisioner.Agent.apps:type_name -> provisioner.App 13, // 8: provisioner.Agent.apps:type_name -> provisioner.App
12, // 9: provisioner.Resource.agents:type_name -> provisioner.Agent 12, // 9: provisioner.Resource.agents:type_name -> provisioner.Agent
9, // 10: provisioner.Parse.Complete.parameter_schemas:type_name -> provisioner.ParameterSchema 18, // 10: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata
10, // 11: provisioner.Parse.Response.log:type_name -> provisioner.Log 9, // 11: provisioner.Parse.Complete.parameter_schemas:type_name -> provisioner.ParameterSchema
19, // 12: provisioner.Parse.Response.complete:type_name -> provisioner.Parse.Complete 10, // 12: provisioner.Parse.Response.log:type_name -> provisioner.Log
1, // 13: provisioner.Provision.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition 20, // 13: provisioner.Parse.Response.complete:type_name -> provisioner.Parse.Complete
8, // 14: provisioner.Provision.Start.parameter_values:type_name -> provisioner.ParameterValue 1, // 14: provisioner.Provision.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition
21, // 15: provisioner.Provision.Start.metadata:type_name -> provisioner.Provision.Metadata 8, // 15: provisioner.Provision.Start.parameter_values:type_name -> provisioner.ParameterValue
22, // 16: provisioner.Provision.Request.start:type_name -> provisioner.Provision.Start 22, // 16: provisioner.Provision.Start.metadata:type_name -> provisioner.Provision.Metadata
23, // 17: provisioner.Provision.Request.cancel:type_name -> provisioner.Provision.Cancel 23, // 17: provisioner.Provision.Request.start:type_name -> provisioner.Provision.Start
14, // 18: provisioner.Provision.Complete.resources:type_name -> provisioner.Resource 24, // 18: provisioner.Provision.Request.cancel:type_name -> provisioner.Provision.Cancel
10, // 19: provisioner.Provision.Response.log:type_name -> provisioner.Log 14, // 19: provisioner.Provision.Complete.resources:type_name -> provisioner.Resource
25, // 20: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete 10, // 20: provisioner.Provision.Response.log:type_name -> provisioner.Log
18, // 21: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request 26, // 21: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete
24, // 22: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request 19, // 22: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request
20, // 23: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response 25, // 23: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request
26, // 24: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response 21, // 24: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response
23, // [23:25] is the sub-list for method output_type 27, // 25: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response
21, // [21:23] is the sub-list for method input_type 24, // [24:26] is the sub-list for method output_type
21, // [21:21] is the sub-list for extension type_name 22, // [22:24] is the sub-list for method input_type
21, // [21:21] is the sub-list for extension extendee 22, // [22:22] is the sub-list for extension type_name
0, // [0:21] is the sub-list for field type_name 22, // [22:22] is the sub-list for extension extendee
0, // [0:22] is the sub-list for field type_name
} }
func init() { file_provisionersdk_proto_provisioner_proto_init() } func init() { file_provisionersdk_proto_provisioner_proto_init() }
@ -2122,7 +2213,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Parse_Request); i { switch v := v.(*Resource_Metadata); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -2134,7 +2225,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Parse_Complete); i { switch v := v.(*Parse_Request); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -2146,7 +2237,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Parse_Response); i { switch v := v.(*Parse_Complete); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -2158,7 +2249,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Metadata); i { switch v := v.(*Parse_Response); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -2170,7 +2261,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Start); i { switch v := v.(*Provision_Metadata); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -2182,7 +2273,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Cancel); i { switch v := v.(*Provision_Start); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -2194,7 +2285,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Request); i { switch v := v.(*Provision_Cancel); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -2206,7 +2297,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Complete); i { switch v := v.(*Provision_Request); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -2218,6 +2309,18 @@ func file_provisionersdk_proto_provisioner_proto_init() {
} }
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { file_provisionersdk_proto_provisioner_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Complete); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_provisionersdk_proto_provisioner_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Response); i { switch v := v.(*Provision_Response); i {
case 0: case 0:
return &v.state return &v.state
@ -2234,15 +2337,15 @@ func file_provisionersdk_proto_provisioner_proto_init() {
(*Agent_Token)(nil), (*Agent_Token)(nil),
(*Agent_InstanceId)(nil), (*Agent_InstanceId)(nil),
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[15].OneofWrappers = []interface{}{ file_provisionersdk_proto_provisioner_proto_msgTypes[16].OneofWrappers = []interface{}{
(*Parse_Response_Log)(nil), (*Parse_Response_Log)(nil),
(*Parse_Response_Complete)(nil), (*Parse_Response_Complete)(nil),
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[19].OneofWrappers = []interface{}{ file_provisionersdk_proto_provisioner_proto_msgTypes[20].OneofWrappers = []interface{}{
(*Provision_Request_Start)(nil), (*Provision_Request_Start)(nil),
(*Provision_Request_Cancel)(nil), (*Provision_Request_Cancel)(nil),
} }
file_provisionersdk_proto_provisioner_proto_msgTypes[21].OneofWrappers = []interface{}{ file_provisionersdk_proto_provisioner_proto_msgTypes[22].OneofWrappers = []interface{}{
(*Provision_Response_Log)(nil), (*Provision_Response_Log)(nil),
(*Provision_Response_Complete)(nil), (*Provision_Response_Complete)(nil),
} }
@ -2252,7 +2355,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_provisionersdk_proto_provisioner_proto_rawDesc, RawDescriptor: file_provisionersdk_proto_provisioner_proto_rawDesc,
NumEnums: 5, NumEnums: 5,
NumMessages: 22, NumMessages: 23,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },

View File

@ -101,6 +101,14 @@ message Resource {
string name = 1; string name = 1;
string type = 2; string type = 2;
repeated Agent agents = 3; repeated Agent agents = 3;
message Metadata {
string key = 1;
string value = 2;
bool sensitive = 3;
bool is_null = 4;
}
repeated Metadata metadata = 4;
} }
// Parse consumes source-code from a directory to produce inputs. // Parse consumes source-code from a directory to produce inputs.

View File

@ -517,6 +517,14 @@ export interface WorkspaceResource {
readonly type: string readonly type: string
readonly name: string readonly name: string
readonly agents?: WorkspaceAgent[] readonly agents?: WorkspaceAgent[]
readonly metadata?: WorkspaceResourceMetadata[]
}
// From codersdk/workspaceresources.go
export interface WorkspaceResourceMetadata {
readonly key: string
readonly value: string
readonly sensitive: boolean
} }
// From codersdk/workspacebuilds.go // From codersdk/workspacebuilds.go