diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 5491cc020991b..8b16b72c6808e 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -2793,6 +2793,14 @@ func (q *querier) InsertProvisionerJobLogs(ctx context.Context, arg database.Ins return q.db.InsertProvisionerJobLogs(ctx, arg) } +// TODO: We need to create a ProvisionerJob resource type +func (q *querier) InsertProvisionerJobTimings(ctx context.Context, arg database.InsertProvisionerJobTimingsParams) ([]database.ProvisionerJobTiming, error) { + // if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { + // return nil, err + // } + return q.db.InsertProvisionerJobTimings(ctx, arg) +} + func (q *querier) InsertProvisionerKey(ctx context.Context, arg database.InsertProvisionerKeyParams) (database.ProvisionerKey, error) { return insert(q.log, q.auth, rbac.ResourceProvisionerKeys.InOrg(arg.OrganizationID).WithID(arg.ID), q.db.InsertProvisionerKey)(ctx, arg) } diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index 80f5665a3df87..85cae74b010bb 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -2470,6 +2470,13 @@ func (s *MethodTestSuite) TestSystemFunctions() { JobID: j.ID, }).Asserts( /*rbac.ResourceSystem, policy.ActionCreate*/ ) })) + s.Run("InsertProvisionerJobTimings", s.Subtest(func(db database.Store, check *expects) { + // TODO: we need to create a ProvisionerJob resource + j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{}) + check.Args(database.InsertProvisionerJobTimingsParams{ + JobID: j.ID, + }).Asserts( /*rbac.ResourceSystem, policy.ActionCreate*/ ) + })) s.Run("UpsertProvisionerDaemon", s.Subtest(func(db database.Store, check *expects) { org := dbgen.Organization(s.T(), db, database.Organization{}) pd := rbac.ResourceProvisionerDaemon.InOrg(org.ID) diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index 1676d3c13d986..c045839cd100f 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -6652,6 +6652,15 @@ func (q *FakeQuerier) InsertProvisionerJobLogs(_ context.Context, arg database.I return logs, nil } +func (*FakeQuerier) InsertProvisionerJobTimings(_ context.Context, arg database.InsertProvisionerJobTimingsParams) ([]database.ProvisionerJobTiming, error) { + err := validateDatabaseType(arg) + if err != nil { + return nil, err + } + + return nil, nil +} + func (q *FakeQuerier) InsertProvisionerKey(_ context.Context, arg database.InsertProvisionerKeyParams) (database.ProvisionerKey, error) { err := validateDatabaseType(arg) if err != nil { diff --git a/coderd/database/dbmetrics/dbmetrics.go b/coderd/database/dbmetrics/dbmetrics.go index 991c31617ac96..1ef22436acc9c 100644 --- a/coderd/database/dbmetrics/dbmetrics.go +++ b/coderd/database/dbmetrics/dbmetrics.go @@ -1712,6 +1712,13 @@ func (m metricsStore) InsertProvisionerJobLogs(ctx context.Context, arg database return logs, err } +func (m metricsStore) InsertProvisionerJobTimings(ctx context.Context, arg database.InsertProvisionerJobTimingsParams) ([]database.ProvisionerJobTiming, error) { + start := time.Now() + r0, r1 := m.s.InsertProvisionerJobTimings(ctx, arg) + m.queryLatencies.WithLabelValues("InsertProvisionerJobTimings").Observe(time.Since(start).Seconds()) + return r0, r1 +} + func (m metricsStore) InsertProvisionerKey(ctx context.Context, arg database.InsertProvisionerKeyParams) (database.ProvisionerKey, error) { start := time.Now() r0, r1 := m.s.InsertProvisionerKey(ctx, arg) diff --git a/coderd/database/dbmock/dbmock.go b/coderd/database/dbmock/dbmock.go index c3660c7bf7afd..d6a8be2b62985 100644 --- a/coderd/database/dbmock/dbmock.go +++ b/coderd/database/dbmock/dbmock.go @@ -3604,6 +3604,21 @@ func (mr *MockStoreMockRecorder) InsertProvisionerJobLogs(arg0, arg1 any) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertProvisionerJobLogs", reflect.TypeOf((*MockStore)(nil).InsertProvisionerJobLogs), arg0, arg1) } +// InsertProvisionerJobTimings mocks base method. +func (m *MockStore) InsertProvisionerJobTimings(arg0 context.Context, arg1 database.InsertProvisionerJobTimingsParams) ([]database.ProvisionerJobTiming, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InsertProvisionerJobTimings", arg0, arg1) + ret0, _ := ret[0].([]database.ProvisionerJobTiming) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// InsertProvisionerJobTimings indicates an expected call of InsertProvisionerJobTimings. +func (mr *MockStoreMockRecorder) InsertProvisionerJobTimings(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertProvisionerJobTimings", reflect.TypeOf((*MockStore)(nil).InsertProvisionerJobTimings), arg0, arg1) +} + // InsertProvisionerKey mocks base method. func (m *MockStore) InsertProvisionerKey(arg0 context.Context, arg1 database.InsertProvisionerKeyParams) (database.ProvisionerKey, error) { m.ctrl.T.Helper() diff --git a/coderd/database/dbtime/dbtime.go b/coderd/database/dbtime/dbtime.go index f242ccff6e0fe..4d740ba941345 100644 --- a/coderd/database/dbtime/dbtime.go +++ b/coderd/database/dbtime/dbtime.go @@ -9,6 +9,10 @@ func Now() time.Time { // Time returns a time compatible with Postgres. Postgres only stores dates with // microsecond precision. +// FIXME(dannyk): refactor all calls to Time() to expect the input time to be modified to UTC; there are currently a +// +// few calls whose behavior would change subtly. +// See https://github.com/coder/coder/pull/14274#discussion_r1718427461 func Time(t time.Time) time.Time { return t.Round(time.Microsecond) } diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index b34362a33432a..add50b1e023dd 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -136,6 +136,13 @@ CREATE TYPE provisioner_job_status AS ENUM ( COMMENT ON TYPE provisioner_job_status IS 'Computed status of a provisioner job. Jobs could be stuck in a hung state, these states do not guarantee any transition to another state.'; +CREATE TYPE provisioner_job_timing_stage AS ENUM ( + 'init', + 'plan', + 'graph', + 'apply' +); + CREATE TYPE provisioner_job_type AS ENUM ( 'template_version_import', 'workspace_build', @@ -828,6 +835,33 @@ CREATE SEQUENCE provisioner_job_logs_id_seq ALTER SEQUENCE provisioner_job_logs_id_seq OWNED BY provisioner_job_logs.id; +CREATE VIEW provisioner_job_stats AS +SELECT + NULL::uuid AS job_id, + NULL::provisioner_job_status AS job_status, + NULL::uuid AS workspace_id, + NULL::uuid AS worker_id, + NULL::text AS error, + NULL::text AS error_code, + NULL::timestamp with time zone AS updated_at, + NULL::double precision AS queued_secs, + NULL::double precision AS completion_secs, + NULL::double precision AS canceled_secs, + NULL::double precision AS init_secs, + NULL::double precision AS plan_secs, + NULL::double precision AS graph_secs, + NULL::double precision AS apply_secs; + +CREATE TABLE provisioner_job_timings ( + job_id uuid NOT NULL, + started_at timestamp with time zone NOT NULL, + ended_at timestamp with time zone NOT NULL, + stage provisioner_job_timing_stage NOT NULL, + source text NOT NULL, + action text NOT NULL, + resource text NOT NULL +); + CREATE TABLE provisioner_jobs ( id uuid NOT NULL, created_at timestamp with time zone NOT NULL, @@ -1892,6 +1926,58 @@ CREATE INDEX workspace_resources_job_id_idx ON workspace_resources USING btree ( CREATE UNIQUE INDEX workspaces_owner_id_lower_idx ON workspaces USING btree (owner_id, lower((name)::text)) WHERE (deleted = false); +CREATE OR REPLACE VIEW provisioner_job_stats AS + SELECT pj.id AS job_id, + pj.job_status, + wb.workspace_id, + pj.worker_id, + pj.error, + pj.error_code, + pj.updated_at, + GREATEST(date_part('epoch'::text, (pj.started_at - pj.created_at)), (0)::double precision) AS queued_secs, + GREATEST(date_part('epoch'::text, (pj.completed_at - pj.started_at)), (0)::double precision) AS completion_secs, + GREATEST(date_part('epoch'::text, (pj.canceled_at - pj.started_at)), (0)::double precision) AS canceled_secs, + GREATEST(date_part('epoch'::text, (max( + CASE + WHEN (pjt.stage = 'init'::provisioner_job_timing_stage) THEN pjt.ended_at + ELSE NULL::timestamp with time zone + END) - min( + CASE + WHEN (pjt.stage = 'init'::provisioner_job_timing_stage) THEN pjt.started_at + ELSE NULL::timestamp with time zone + END))), (0)::double precision) AS init_secs, + GREATEST(date_part('epoch'::text, (max( + CASE + WHEN (pjt.stage = 'plan'::provisioner_job_timing_stage) THEN pjt.ended_at + ELSE NULL::timestamp with time zone + END) - min( + CASE + WHEN (pjt.stage = 'plan'::provisioner_job_timing_stage) THEN pjt.started_at + ELSE NULL::timestamp with time zone + END))), (0)::double precision) AS plan_secs, + GREATEST(date_part('epoch'::text, (max( + CASE + WHEN (pjt.stage = 'graph'::provisioner_job_timing_stage) THEN pjt.ended_at + ELSE NULL::timestamp with time zone + END) - min( + CASE + WHEN (pjt.stage = 'graph'::provisioner_job_timing_stage) THEN pjt.started_at + ELSE NULL::timestamp with time zone + END))), (0)::double precision) AS graph_secs, + GREATEST(date_part('epoch'::text, (max( + CASE + WHEN (pjt.stage = 'apply'::provisioner_job_timing_stage) THEN pjt.ended_at + ELSE NULL::timestamp with time zone + END) - min( + CASE + WHEN (pjt.stage = 'apply'::provisioner_job_timing_stage) THEN pjt.started_at + ELSE NULL::timestamp with time zone + END))), (0)::double precision) AS apply_secs + FROM ((provisioner_jobs pj + JOIN workspace_builds wb ON ((wb.job_id = pj.id))) + LEFT JOIN provisioner_job_timings pjt ON ((pjt.job_id = pj.id))) + GROUP BY pj.id, wb.workspace_id; + CREATE TRIGGER inhibit_enqueue_if_disabled BEFORE INSERT ON notification_messages FOR EACH ROW EXECUTE FUNCTION inhibit_enqueue_if_disabled(); CREATE TRIGGER remove_organization_member_custom_role BEFORE DELETE ON custom_roles FOR EACH ROW EXECUTE FUNCTION remove_organization_member_role(); @@ -1987,6 +2073,9 @@ ALTER TABLE ONLY provisioner_daemons ALTER TABLE ONLY provisioner_job_logs ADD CONSTRAINT provisioner_job_logs_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; +ALTER TABLE ONLY provisioner_job_timings + ADD CONSTRAINT provisioner_job_timings_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; + ALTER TABLE ONLY provisioner_jobs ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; diff --git a/coderd/database/foreign_key_constraint.go b/coderd/database/foreign_key_constraint.go index 011d39bdc5b91..0c578255f091c 100644 --- a/coderd/database/foreign_key_constraint.go +++ b/coderd/database/foreign_key_constraint.go @@ -29,6 +29,7 @@ const ( ForeignKeyParameterSchemasJobID ForeignKeyConstraint = "parameter_schemas_job_id_fkey" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; ForeignKeyProvisionerDaemonsOrganizationID ForeignKeyConstraint = "provisioner_daemons_organization_id_fkey" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; ForeignKeyProvisionerJobLogsJobID ForeignKeyConstraint = "provisioner_job_logs_job_id_fkey" // ALTER TABLE ONLY provisioner_job_logs ADD CONSTRAINT provisioner_job_logs_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; + ForeignKeyProvisionerJobTimingsJobID ForeignKeyConstraint = "provisioner_job_timings_job_id_fkey" // ALTER TABLE ONLY provisioner_job_timings ADD CONSTRAINT provisioner_job_timings_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; ForeignKeyProvisionerJobsOrganizationID ForeignKeyConstraint = "provisioner_jobs_organization_id_fkey" // ALTER TABLE ONLY provisioner_jobs ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; ForeignKeyProvisionerKeysOrganizationID ForeignKeyConstraint = "provisioner_keys_organization_id_fkey" // ALTER TABLE ONLY provisioner_keys ADD CONSTRAINT provisioner_keys_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; ForeignKeyTailnetAgentsCoordinatorID ForeignKeyConstraint = "tailnet_agents_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_agents ADD CONSTRAINT tailnet_agents_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE; diff --git a/coderd/database/migrations/000245_provisioner_job_timings.down.sql b/coderd/database/migrations/000245_provisioner_job_timings.down.sql new file mode 100644 index 0000000000000..ab6caab5f60c7 --- /dev/null +++ b/coderd/database/migrations/000245_provisioner_job_timings.down.sql @@ -0,0 +1,5 @@ +DROP VIEW IF EXISTS provisioner_job_stats; + +DROP TYPE IF EXISTS provisioner_job_timing_stage CASCADE; + +DROP TABLE IF EXISTS provisioner_job_timings; diff --git a/coderd/database/migrations/000245_provisioner_job_timings.up.sql b/coderd/database/migrations/000245_provisioner_job_timings.up.sql new file mode 100644 index 0000000000000..26496232e9f1d --- /dev/null +++ b/coderd/database/migrations/000245_provisioner_job_timings.up.sql @@ -0,0 +1,45 @@ +CREATE TYPE provisioner_job_timing_stage AS ENUM ( + 'init', + 'plan', + 'graph', + 'apply' + ); + +CREATE TABLE provisioner_job_timings +( + job_id uuid NOT NULL REFERENCES provisioner_jobs (id) ON DELETE CASCADE, + started_at timestamp with time zone not null, + ended_at timestamp with time zone not null, + stage provisioner_job_timing_stage not null, + source text not null, + action text not null, + resource text not null +); + +CREATE VIEW provisioner_job_stats AS +SELECT pj.id AS job_id, + pj.job_status, + wb.workspace_id, + pj.worker_id, + pj.error, + pj.error_code, + pj.updated_at, + GREATEST(EXTRACT(EPOCH FROM (pj.started_at - pj.created_at)), 0) AS queued_secs, + GREATEST(EXTRACT(EPOCH FROM (pj.completed_at - pj.started_at)), 0) AS completion_secs, + GREATEST(EXTRACT(EPOCH FROM (pj.canceled_at - pj.started_at)), 0) AS canceled_secs, + GREATEST(EXTRACT(EPOCH FROM ( + MAX(CASE WHEN pjt.stage = 'init'::provisioner_job_timing_stage THEN pjt.ended_at END) - + MIN(CASE WHEN pjt.stage = 'init'::provisioner_job_timing_stage THEN pjt.started_at END))), 0) AS init_secs, + GREATEST(EXTRACT(EPOCH FROM ( + MAX(CASE WHEN pjt.stage = 'plan'::provisioner_job_timing_stage THEN pjt.ended_at END) - + MIN(CASE WHEN pjt.stage = 'plan'::provisioner_job_timing_stage THEN pjt.started_at END))), 0) AS plan_secs, + GREATEST(EXTRACT(EPOCH FROM ( + MAX(CASE WHEN pjt.stage = 'graph'::provisioner_job_timing_stage THEN pjt.ended_at END) - + MIN(CASE WHEN pjt.stage = 'graph'::provisioner_job_timing_stage THEN pjt.started_at END))), 0) AS graph_secs, + GREATEST(EXTRACT(EPOCH FROM ( + MAX(CASE WHEN pjt.stage = 'apply'::provisioner_job_timing_stage THEN pjt.ended_at END) - + MIN(CASE WHEN pjt.stage = 'apply'::provisioner_job_timing_stage THEN pjt.started_at END))), 0) AS apply_secs +FROM provisioner_jobs pj + JOIN workspace_builds wb ON wb.job_id = pj.id + LEFT JOIN provisioner_job_timings pjt ON pjt.job_id = pj.id +GROUP BY pj.id, wb.workspace_id; diff --git a/coderd/database/migrations/testdata/fixtures/000245_provisioner_job_timings.up.sql b/coderd/database/migrations/testdata/fixtures/000245_provisioner_job_timings.up.sql new file mode 100644 index 0000000000000..ef05eee51e807 --- /dev/null +++ b/coderd/database/migrations/testdata/fixtures/000245_provisioner_job_timings.up.sql @@ -0,0 +1,13 @@ +INSERT INTO provisioner_job_timings (job_id, started_at, ended_at, stage, source, action, resource) +VALUES + -- Job 1 - init stage + ('424a58cb-61d6-4627-9907-613c396c4a38', NOW() - INTERVAL '1 hour 55 minutes', NOW() - INTERVAL '1 hour 50 minutes', 'init', 'source1', 'action1', 'resource1'), + + -- Job 1 - plan stage + ('424a58cb-61d6-4627-9907-613c396c4a38', NOW() - INTERVAL '1 hour 50 minutes', NOW() - INTERVAL '1 hour 40 minutes', 'plan', 'source2', 'action2', 'resource2'), + + -- Job 1 - graph stage + ('424a58cb-61d6-4627-9907-613c396c4a38', NOW() - INTERVAL '1 hour 40 minutes', NOW() - INTERVAL '1 hour 30 minutes', 'graph', 'source3', 'action3', 'resource3'), + + -- Job 1 - apply stage + ('424a58cb-61d6-4627-9907-613c396c4a38', NOW() - INTERVAL '1 hour 30 minutes', NOW() - INTERVAL '1 hour 20 minutes', 'apply', 'source4', 'action4', 'resource4'); diff --git a/coderd/database/models.go b/coderd/database/models.go index a120d16cf9dc8..78e8a68fe20fc 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -1216,6 +1216,70 @@ func AllProvisionerJobStatusValues() []ProvisionerJobStatus { } } +type ProvisionerJobTimingStage string + +const ( + ProvisionerJobTimingStageInit ProvisionerJobTimingStage = "init" + ProvisionerJobTimingStagePlan ProvisionerJobTimingStage = "plan" + ProvisionerJobTimingStageGraph ProvisionerJobTimingStage = "graph" + ProvisionerJobTimingStageApply ProvisionerJobTimingStage = "apply" +) + +func (e *ProvisionerJobTimingStage) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = ProvisionerJobTimingStage(s) + case string: + *e = ProvisionerJobTimingStage(s) + default: + return fmt.Errorf("unsupported scan type for ProvisionerJobTimingStage: %T", src) + } + return nil +} + +type NullProvisionerJobTimingStage struct { + ProvisionerJobTimingStage ProvisionerJobTimingStage `json:"provisioner_job_timing_stage"` + Valid bool `json:"valid"` // Valid is true if ProvisionerJobTimingStage is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullProvisionerJobTimingStage) Scan(value interface{}) error { + if value == nil { + ns.ProvisionerJobTimingStage, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.ProvisionerJobTimingStage.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullProvisionerJobTimingStage) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.ProvisionerJobTimingStage), nil +} + +func (e ProvisionerJobTimingStage) Valid() bool { + switch e { + case ProvisionerJobTimingStageInit, + ProvisionerJobTimingStagePlan, + ProvisionerJobTimingStageGraph, + ProvisionerJobTimingStageApply: + return true + } + return false +} + +func AllProvisionerJobTimingStageValues() []ProvisionerJobTimingStage { + return []ProvisionerJobTimingStage{ + ProvisionerJobTimingStageInit, + ProvisionerJobTimingStagePlan, + ProvisionerJobTimingStageGraph, + ProvisionerJobTimingStageApply, + } +} + type ProvisionerJobType string const ( @@ -2280,6 +2344,33 @@ type ProvisionerJobLog struct { ID int64 `db:"id" json:"id"` } +type ProvisionerJobStat struct { + JobID uuid.UUID `db:"job_id" json:"job_id"` + JobStatus ProvisionerJobStatus `db:"job_status" json:"job_status"` + WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"` + WorkerID uuid.NullUUID `db:"worker_id" json:"worker_id"` + Error sql.NullString `db:"error" json:"error"` + ErrorCode sql.NullString `db:"error_code" json:"error_code"` + UpdatedAt time.Time `db:"updated_at" json:"updated_at"` + QueuedSecs float64 `db:"queued_secs" json:"queued_secs"` + CompletionSecs float64 `db:"completion_secs" json:"completion_secs"` + CanceledSecs float64 `db:"canceled_secs" json:"canceled_secs"` + InitSecs float64 `db:"init_secs" json:"init_secs"` + PlanSecs float64 `db:"plan_secs" json:"plan_secs"` + GraphSecs float64 `db:"graph_secs" json:"graph_secs"` + ApplySecs float64 `db:"apply_secs" json:"apply_secs"` +} + +type ProvisionerJobTiming struct { + JobID uuid.UUID `db:"job_id" json:"job_id"` + StartedAt time.Time `db:"started_at" json:"started_at"` + EndedAt time.Time `db:"ended_at" json:"ended_at"` + Stage ProvisionerJobTimingStage `db:"stage" json:"stage"` + Source string `db:"source" json:"source"` + Action string `db:"action" json:"action"` + Resource string `db:"resource" json:"resource"` +} + type ProvisionerKey struct { ID uuid.UUID `db:"id" json:"id"` CreatedAt time.Time `db:"created_at" json:"created_at"` diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 5fb44c3f2fbcd..7f3bc1c39a515 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -357,6 +357,7 @@ type sqlcQuerier interface { InsertOrganizationMember(ctx context.Context, arg InsertOrganizationMemberParams) (OrganizationMember, error) InsertProvisionerJob(ctx context.Context, arg InsertProvisionerJobParams) (ProvisionerJob, error) InsertProvisionerJobLogs(ctx context.Context, arg InsertProvisionerJobLogsParams) ([]ProvisionerJobLog, error) + InsertProvisionerJobTimings(ctx context.Context, arg InsertProvisionerJobTimingsParams) ([]ProvisionerJobTiming, error) InsertProvisionerKey(ctx context.Context, arg InsertProvisionerKeyParams) (ProvisionerKey, error) InsertReplica(ctx context.Context, arg InsertReplicaParams) (Replica, error) InsertTemplate(ctx context.Context, arg InsertTemplateParams) error diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 8927770dad4f8..d32c27852e0a5 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -5541,6 +5541,68 @@ func (q *sqlQuerier) InsertProvisionerJob(ctx context.Context, arg InsertProvisi return i, err } +const insertProvisionerJobTimings = `-- name: InsertProvisionerJobTimings :many +INSERT INTO provisioner_job_timings (job_id, started_at, ended_at, stage, source, action, resource) +SELECT + $1::uuid AS provisioner_job_id, + unnest($2::timestamptz[]), + unnest($3::timestamptz[]), + unnest($4::provisioner_job_timing_stage[]), + unnest($5::text[]), + unnest($6::text[]), + unnest($7::text[]) +RETURNING job_id, started_at, ended_at, stage, source, action, resource +` + +type InsertProvisionerJobTimingsParams struct { + JobID uuid.UUID `db:"job_id" json:"job_id"` + StartedAt []time.Time `db:"started_at" json:"started_at"` + EndedAt []time.Time `db:"ended_at" json:"ended_at"` + Stage []ProvisionerJobTimingStage `db:"stage" json:"stage"` + Source []string `db:"source" json:"source"` + Action []string `db:"action" json:"action"` + Resource []string `db:"resource" json:"resource"` +} + +func (q *sqlQuerier) InsertProvisionerJobTimings(ctx context.Context, arg InsertProvisionerJobTimingsParams) ([]ProvisionerJobTiming, error) { + rows, err := q.db.QueryContext(ctx, insertProvisionerJobTimings, + arg.JobID, + pq.Array(arg.StartedAt), + pq.Array(arg.EndedAt), + pq.Array(arg.Stage), + pq.Array(arg.Source), + pq.Array(arg.Action), + pq.Array(arg.Resource), + ) + if err != nil { + return nil, err + } + defer rows.Close() + var items []ProvisionerJobTiming + for rows.Next() { + var i ProvisionerJobTiming + if err := rows.Scan( + &i.JobID, + &i.StartedAt, + &i.EndedAt, + &i.Stage, + &i.Source, + &i.Action, + &i.Resource, + ); 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 updateProvisionerJobByID = `-- name: UpdateProvisionerJobByID :exec UPDATE provisioner_jobs diff --git a/coderd/database/queries/provisionerjobs.sql b/coderd/database/queries/provisionerjobs.sql index d1d5f68ce750e..687176d3c255b 100644 --- a/coderd/database/queries/provisionerjobs.sql +++ b/coderd/database/queries/provisionerjobs.sql @@ -144,3 +144,15 @@ WHERE updated_at < $1 AND started_at IS NOT NULL AND completed_at IS NULL; + +-- name: InsertProvisionerJobTimings :many +INSERT INTO provisioner_job_timings (job_id, started_at, ended_at, stage, source, action, resource) +SELECT + @job_id::uuid AS provisioner_job_id, + unnest(@started_at::timestamptz[]), + unnest(@ended_at::timestamptz[]), + unnest(@stage::provisioner_job_timing_stage[]), + unnest(@source::text[]), + unnest(@action::text[]), + unnest(@resource::text[]) +RETURNING *; diff --git a/coderd/database/sqlc.yaml b/coderd/database/sqlc.yaml index 9eeecd6b21d00..7ef860e0b36ce 100644 --- a/coderd/database/sqlc.yaml +++ b/coderd/database/sqlc.yaml @@ -73,6 +73,9 @@ sql: - column: "notification_messages.payload" go_type: type: "[]byte" + - column: "provisioner_job_stats.*_secs" + go_type: + type: "float64" rename: group_member: GroupMemberTable group_members_expanded: GroupMember diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 9a60aaa70ebde..9a1a1d45a5b85 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -1441,6 +1441,36 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob) return nil, xerrors.Errorf("complete job: %w", err) } + // Insert timings outside transaction since it is metadata. + // nolint:exhaustruct // The other fields are set further down. + params := database.InsertProvisionerJobTimingsParams{ + JobID: jobID, + } + for _, t := range completed.GetWorkspaceBuild().GetTimings() { + if t.Start == nil || t.End == nil { + s.Logger.Warn(ctx, "timings entry has nil start or end time", slog.F("entry", t.String())) + continue + } + + var stg database.ProvisionerJobTimingStage + if err := stg.Scan(t.Stage); err != nil { + s.Logger.Warn(ctx, "failed to parse timings stage, skipping", slog.F("value", t.Stage)) + continue + } + + params.Stage = append(params.Stage, stg) + params.Source = append(params.Source, t.Source) + params.Resource = append(params.Resource, t.Resource) + params.Action = append(params.Action, t.Action) + params.StartedAt = append(params.StartedAt, t.Start.AsTime()) + params.EndedAt = append(params.EndedAt, t.End.AsTime()) + } + _, err = s.Database.InsertProvisionerJobTimings(ctx, params) + if err != nil { + // Don't fail the transaction for non-critical data. + s.Logger.Warn(ctx, "failed to update provisioner job timings", slog.F("job_id", jobID), slog.Error(err)) + } + // audit the outcome of the workspace build if getWorkspaceError == nil { // If the workspace has been deleted, notify the owner about it. diff --git a/flake.nix b/flake.nix index 374c7fc89ed80..7b2c6644b89ed 100644 --- a/flake.nix +++ b/flake.nix @@ -117,7 +117,7 @@ name = "coder-${osArch}"; # Updated with ./scripts/update-flake.sh`. # This should be updated whenever go.mod changes! - vendorHash = "sha256-6K1Y61RaSXITD0tr6iW8PHGyf82lkgVQOSCs3K8YcsY="; + vendorHash = "sha256-I2YMiYXq8XrJd6jw8JZnOL5wugPTLsip9JGELEy5Uao="; proxyVendor = true; src = ./.; nativeBuildInputs = with pkgs; [ getopt openssl zstd ]; diff --git a/go.mod b/go.mod index d1bbafa713579..1ce0371f12cd0 100644 --- a/go.mod +++ b/go.mod @@ -196,6 +196,7 @@ require ( require go.uber.org/mock v0.4.0 require ( + github.com/cespare/xxhash v1.1.0 github.com/coder/serpent v0.7.1-0.20240815055535-d46fb20fa158 github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 github.com/emersion/go-smtp v0.21.2 diff --git a/go.sum b/go.sum index ccde33bbf4916..a6025515f9c07 100644 --- a/go.sum +++ b/go.sum @@ -51,6 +51,7 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63n github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg= @@ -856,6 +857,7 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= diff --git a/provisioner/terraform/executor.go b/provisioner/terraform/executor.go index b1a3ecadb5203..08231489f40a2 100644 --- a/provisioner/terraform/executor.go +++ b/provisioner/terraform/executor.go @@ -13,6 +13,7 @@ import ( "runtime" "strings" "sync" + "time" "github.com/hashicorp/go-version" tfjson "github.com/hashicorp/terraform-json" @@ -20,6 +21,8 @@ import ( "golang.org/x/xerrors" "cdr.dev/slog" + + "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/provisionersdk/proto" ) @@ -34,6 +37,8 @@ type executor struct { // cachePath and workdir must not be used by multiple processes at once. cachePath string workdir string + // used to capture execution times at various stages + timings *timingAggregator } func (e *executor) basicEnv() []string { @@ -252,7 +257,7 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l args = append(args, "-var", variable) } - outWriter, doneOut := provisionLogWriter(logr) + outWriter, doneOut := e.provisionLogWriter(logr) errWriter, doneErr := logWriter(logr, proto.LogLevel_ERROR) defer func() { _ = outWriter.Close() @@ -265,14 +270,24 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l if err != nil { return nil, xerrors.Errorf("terraform plan: %w", err) } + + // Capture the duration of the call to `terraform graph`. + graphTimings := newTimingAggregator(database.ProvisionerJobTimingStageGraph) + graphTimings.ingest(createGraphTimingsEvent(timingGraphStart)) + state, err := e.planResources(ctx, killCtx, planfilePath) if err != nil { + graphTimings.ingest(createGraphTimingsEvent(timingGraphErrored)) return nil, err } + + graphTimings.ingest(createGraphTimingsEvent(timingGraphComplete)) + return &proto.PlanComplete{ Parameters: state.Parameters, Resources: state.Resources, ExternalAuthProviders: state.ExternalAuthProviders, + Timings: append(e.timings.aggregate(), graphTimings.aggregate()...), }, nil } @@ -399,7 +414,7 @@ func (e *executor) apply( getPlanFilePath(e.workdir), } - outWriter, doneOut := provisionLogWriter(logr) + outWriter, doneOut := e.provisionLogWriter(logr) errWriter, doneErr := logWriter(logr, proto.LogLevel_ERROR) defer func() { _ = outWriter.Close() @@ -421,11 +436,13 @@ func (e *executor) apply( if err != nil { return nil, xerrors.Errorf("read statefile %q: %w", statefilePath, err) } + return &proto.ApplyComplete{ Parameters: state.Parameters, Resources: state.Resources, ExternalAuthProviders: state.ExternalAuthProviders, State: stateContent, + Timings: e.timings.aggregate(), }, nil } @@ -539,46 +556,42 @@ func readAndLog(sink logSink, r io.Reader, done chan<- any, level proto.LogLevel // provisionLogWriter creates a WriteCloser that will log each JSON formatted terraform log. The WriteCloser must be // closed by the caller to end logging, after which the returned channel will be closed to indicate that logging of the // written data has finished. Failure to close the WriteCloser will leak a goroutine. -func provisionLogWriter(sink logSink) (io.WriteCloser, <-chan any) { +func (e *executor) provisionLogWriter(sink logSink) (io.WriteCloser, <-chan any) { r, w := io.Pipe() done := make(chan any) - go provisionReadAndLog(sink, r, done) + + go e.provisionReadAndLog(sink, r, done) return w, done } -func provisionReadAndLog(sink logSink, r io.Reader, done chan<- any) { +func (e *executor) provisionReadAndLog(sink logSink, r io.Reader, done chan<- any) { defer close(done) + + errCount := 0 + scanner := bufio.NewScanner(r) for scanner.Scan() { - var log terraformProvisionLog - err := json.Unmarshal(scanner.Bytes(), &log) - if err != nil { - // Sometimes terraform doesn't log JSON, even though we asked it to. - // The terraform maintainers have said on the issue tracker that - // they don't guarantee that non-JSON lines won't get printed. - // https://github.com/hashicorp/terraform/issues/29252#issuecomment-887710001 - // - // > I think as a practical matter it isn't possible for us to - // > promise that the output will always be entirely JSON, because - // > there's plenty of code that runs before command line arguments - // > are parsed and thus before we even know we're in JSON mode. - // > Given that, I'd suggest writing code that consumes streaming - // > JSON output from Terraform in such a way that it can tolerate - // > the output not having JSON in it at all. - // - // Log lines such as: - // - Acquiring state lock. This may take a few moments... - // - Releasing state lock. This may take a few moments... - if strings.TrimSpace(scanner.Text()) == "" { - continue - } - log.Level = "info" - log.Message = scanner.Text() + log := parseTerraformLogLine(scanner.Bytes()) + if log == nil { + continue } logLevel := convertTerraformLogLevel(log.Level, sink) sink.ProvisionLog(logLevel, log.Message) + ts, span, err := extractTimingSpan(log) + if err != nil { + // It's too noisy to log all of these as timings are not an essential feature, but we do need to log *some*. + if errCount%10 == 0 { + e.logger.Warn(context.Background(), "(sampled) failed to extract timings entry from log line", + slog.F("line", log.Message), slog.Error(err)) + } + errCount++ + } else { + // Only ingest valid timings. + e.timings.ingest(ts, span) + } + // If the diagnostic is provided, let's provide a bit more info! if log.Diagnostic == nil { continue @@ -590,6 +603,60 @@ func provisionReadAndLog(sink logSink, r io.Reader, done chan<- any) { } } +func parseTerraformLogLine(line []byte) *terraformProvisionLog { + var log terraformProvisionLog + err := json.Unmarshal(line, &log) + if err != nil { + // Sometimes terraform doesn't log JSON, even though we asked it to. + // The terraform maintainers have said on the issue tracker that + // they don't guarantee that non-JSON lines won't get printed. + // https://github.com/hashicorp/terraform/issues/29252#issuecomment-887710001 + // + // > I think as a practical matter it isn't possible for us to + // > promise that the output will always be entirely JSON, because + // > there's plenty of code that runs before command line arguments + // > are parsed and thus before we even know we're in JSON mode. + // > Given that, I'd suggest writing code that consumes streaming + // > JSON output from Terraform in such a way that it can tolerate + // > the output not having JSON in it at all. + // + // Log lines such as: + // - Acquiring state lock. This may take a few moments... + // - Releasing state lock. This may take a few moments... + if len(bytes.TrimSpace(line)) == 0 { + return nil + } + log.Level = "info" + log.Message = string(line) + } + return &log +} + +func extractTimingSpan(log *terraformProvisionLog) (time.Time, *timingSpan, error) { + // Input is not well-formed, bail out. + if log.Type == "" { + return time.Time{}, nil, xerrors.Errorf("invalid timing kind: %q", log.Type) + } + + typ := timingKind(log.Type) + if !typ.Valid() { + return time.Time{}, nil, xerrors.Errorf("unexpected timing kind: %q", log.Type) + } + + ts, err := time.Parse("2006-01-02T15:04:05.000000Z07:00", log.Timestamp) + if err != nil { + // TODO: log + ts = time.Now() + } + + return ts, &timingSpan{ + kind: typ, + action: log.Hook.Action, + provider: log.Hook.Resource.Provider, + resource: log.Hook.Resource.Addr, + }, nil +} + func convertTerraformLogLevel(logLevel string, sink logSink) proto.LogLevel { switch strings.ToLower(logLevel) { case "trace": @@ -609,12 +676,25 @@ func convertTerraformLogLevel(logLevel string, sink logSink) proto.LogLevel { } type terraformProvisionLog struct { - Level string `json:"@level"` - Message string `json:"@message"` + Level string `json:"@level"` + Message string `json:"@message"` + Timestamp string `json:"@timestamp"` + Type string `json:"type"` + Hook terraformProvisionLogHook `json:"hook"` Diagnostic *tfjson.Diagnostic `json:"diagnostic,omitempty"` } +type terraformProvisionLogHook struct { + Action string `json:"action"` + Resource terraformProvisionLogHookResource `json:"resource"` +} + +type terraformProvisionLogHookResource struct { + Addr string `json:"addr"` + Provider string `json:"implied_provider"` +} + // syncWriter wraps an io.Writer in a sync.Mutex. type syncWriter struct { mut *sync.Mutex diff --git a/provisioner/terraform/internal/timings_test_utils.go b/provisioner/terraform/internal/timings_test_utils.go new file mode 100644 index 0000000000000..59582a1c4b750 --- /dev/null +++ b/provisioner/terraform/internal/timings_test_utils.go @@ -0,0 +1,114 @@ +package terraform + +import ( + "bufio" + "bytes" + "slices" + "testing" + + "github.com/cespare/xxhash" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/encoding/protojson" + protobuf "google.golang.org/protobuf/proto" + + "github.com/coder/coder/v2/provisionersdk/proto" +) + +func ParseTimingLines(t *testing.T, input []byte) []*proto.Timing { + t.Helper() + + // Parse the input into *proto.Timing structs. + var expected []*proto.Timing + scanner := bufio.NewScanner(bytes.NewBuffer(input)) + for scanner.Scan() { + line := scanner.Bytes() + + var msg proto.Timing + require.NoError(t, protojson.Unmarshal(line, &msg)) + + expected = append(expected, &msg) + } + require.NoError(t, scanner.Err()) + StableSortTimings(t, expected) // To reduce flakiness. + + return expected +} + +func TimingsAreEqual(t *testing.T, expected []*proto.Timing, actual []*proto.Timing) bool { + t.Helper() + + // Shortcut check. + if len(expected)+len(actual) == 0 { + t.Logf("both timings are empty") + return true + } + + // Shortcut check. + if len(expected) != len(actual) { + t.Logf("timings lengths are not equal: %d != %d", len(expected), len(actual)) + return false + } + + // Compare each element; both are expected to be sorted in a stable manner. + for i := 0; i < len(expected); i++ { + ex := expected[i] + ac := actual[i] + if !protobuf.Equal(ex, ac) { + t.Logf("timings are not equivalent: %q != %q", ex.String(), ac.String()) + return false + } + } + + return true +} + +func PrintTiming(t *testing.T, timing *proto.Timing) { + t.Helper() + + marshaler := protojson.MarshalOptions{ + Multiline: false, // Ensure it's set to false for single-line JSON + Indent: "", // No indentation + } + + out, err := marshaler.Marshal(timing) + assert.NoError(t, err) + t.Logf("%s", out) +} + +func StableSortTimings(t *testing.T, timings []*proto.Timing) { + t.Helper() + + slices.SortStableFunc(timings, func(a, b *proto.Timing) int { + if a == nil || b == nil || a.Start == nil || b.Start == nil { + return 0 + } + + if a.Start.AsTime().Equal(b.Start.AsTime()) { + // Special case: when start times are equal, we need to keep the ordering stable, so we hash both entries + // and sort based on that (since end times could be equal too, in principle). + ah := xxhash.Sum64String(a.String()) + bh := xxhash.Sum64String(b.String()) + + if ah == bh { + // WTF. + t.Logf("identical timings detected!") + PrintTiming(t, a) + PrintTiming(t, b) + return 0 + } + + if ah < bh { + return -1 + } + + return 1 + } + + if a.Start.AsTime().Before(b.Start.AsTime()) { + return -1 + } + + return 1 + }) +} diff --git a/provisioner/terraform/provision.go b/provisioner/terraform/provision.go index cd28f93854c0f..9ff56de111662 100644 --- a/provisioner/terraform/provision.go +++ b/provisioner/terraform/provision.go @@ -14,6 +14,7 @@ import ( "cdr.dev/slog" "github.com/coder/terraform-provider-coder/provider" + "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" @@ -71,7 +72,7 @@ func (s *server) Plan( defer cancel() defer kill() - e := s.executor(sess.WorkDirectory) + e := s.executor(sess.WorkDirectory, database.ProvisionerJobTimingStagePlan) if err := e.checkMinVersion(ctx); err != nil { return provisionersdk.PlanErrorf(err.Error()) } @@ -101,11 +102,22 @@ func (s *server) Plan( } s.logger.Debug(ctx, "running initialization") + + // The JSON output of `terraform init` doesn't include discrete fields for capturing timings of each plugin, + // so we capture the whole init process. + initTimings := newTimingAggregator(database.ProvisionerJobTimingStageInit) + initTimings.ingest(createInitTimingsEvent(timingInitStart)) + err = e.init(ctx, killCtx, sess) if err != nil { + initTimings.ingest(createInitTimingsEvent(timingInitErrored)) + s.logger.Debug(ctx, "init failed", slog.Error(err)) return provisionersdk.PlanErrorf("initialize terraform: %s", err) } + + initTimings.ingest(createInitTimingsEvent(timingInitComplete)) + s.logger.Debug(ctx, "ran initialization") env, err := provisionEnv(sess.Config, request.Metadata, request.RichParameterValues, request.ExternalAuthProviders) @@ -125,6 +137,10 @@ func (s *server) Plan( if err != nil { return provisionersdk.PlanErrorf(err.Error()) } + + // Prepend init timings since they occur prior to plan timings. + // Order is irrelevant; this is merely indicative. + resp.Timings = append(initTimings.aggregate(), resp.Timings...) return resp } @@ -137,7 +153,7 @@ func (s *server) Apply( defer cancel() defer kill() - e := s.executor(sess.WorkDirectory) + e := s.executor(sess.WorkDirectory, database.ProvisionerJobTimingStageApply) if err := e.checkMinVersion(ctx); err != nil { return provisionersdk.ApplyErrorf(err.Error()) } diff --git a/provisioner/terraform/serve.go b/provisioner/terraform/serve.go index 3a2dde7f809a7..7a3b033bf2bba 100644 --- a/provisioner/terraform/serve.go +++ b/provisioner/terraform/serve.go @@ -12,6 +12,8 @@ import ( "golang.org/x/xerrors" "cdr.dev/slog" + + "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/unhanger" "github.com/coder/coder/v2/provisionersdk" ) @@ -138,7 +140,7 @@ func (s *server) startTrace(ctx context.Context, name string, opts ...trace.Span ))...) } -func (s *server) executor(workdir string) *executor { +func (s *server) executor(workdir string, stage database.ProvisionerJobTimingStage) *executor { return &executor{ server: s, mut: s.execMut, @@ -146,5 +148,6 @@ func (s *server) executor(workdir string) *executor { cachePath: s.cachePath, workdir: workdir, logger: s.logger.Named("executor"), + timings: newTimingAggregator(stage), } } diff --git a/provisioner/terraform/testdata/timings-aggregation/complete.txtar b/provisioner/terraform/testdata/timings-aggregation/complete.txtar new file mode 100644 index 0000000000000..40acb9ae06a65 --- /dev/null +++ b/provisioner/terraform/testdata/timings-aggregation/complete.txtar @@ -0,0 +1,39 @@ +A successful build which results in successful plan and apply timings. + +-- plan -- +{"@level":"info","@message":"Terraform 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:38.097648+02:00","terraform":"1.9.2","type":"version","ui":"1.2"} +{"@level":"info","@message":"data.coder_workspace.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.194726+02:00","hook":{"resource":{"addr":"data.coder_workspace.me","module":"","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_parameter.memory_size: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.194726+02:00","hook":{"resource":{"addr":"data.coder_parameter.memory_size","module":"","resource":"data.coder_parameter.memory_size","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"memory_size","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_provisioner.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.194726+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_provisioner.me: Refresh complete after 0s [id=2470b3d2-32f4-4f95-ac70-0971efdb8338]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.195712+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"2470b3d2-32f4-4f95-ac70-0971efdb8338","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"data.coder_workspace.me: Refresh complete after 0s [id=feb06d32-3252-4cd8-b7db-ea0c5145747f]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.195820+02:00","hook":{"resource":{"addr":"data.coder_workspace.me","module":"","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"feb06d32-3252-4cd8-b7db-ea0c5145747f","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"data.coder_parameter.memory_size: Refresh complete after 0s [id=b136c86c-1be0-43b4-9d78-e492918c5de0]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.195836+02:00","hook":{"resource":{"addr":"data.coder_parameter.memory_size","module":"","resource":"data.coder_parameter.memory_size","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"memory_size","resource_key":null},"action":"read","id_key":"id","id_value":"b136c86c-1be0-43b4-9d78-e492918c5de0","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"coder_agent.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221555+02:00","change":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_image.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221574+02:00","change":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_volume.home_volume: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221580+02:00","change":{"resource":{"addr":"docker_volume.home_volume","module":"","resource":"docker_volume.home_volume","implied_provider":"docker","resource_type":"docker_volume","resource_name":"home_volume","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_container.workspace[0]: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221584+02:00","change":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"Plan: 4 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221589+02:00","changes":{"add":4,"change":0,"import":0,"remove":0,"operation":"plan"},"type":"change_summary"} +-- apply -- +{"@level":"info","@message":"Terraform 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.507006+02:00","terraform":"1.9.2","type":"version","ui":"1.2"} +{"@level":"info","@message":"coder_agent.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.572335+02:00","change":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_image.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.572411+02:00","change":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_volume.home_volume: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.572416+02:00","change":{"resource":{"addr":"docker_volume.home_volume","module":"","resource":"docker_volume.home_volume","implied_provider":"docker","resource_type":"docker_volume","resource_name":"home_volume","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_container.workspace[0]: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.572424+02:00","change":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"coder_agent.main: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.616546+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"coder_agent.main: Creation complete after 0s [id=a23083da-4679-4396-a306-f7b466237883]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.618045+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create","id_key":"id","id_value":"a23083da-4679-4396-a306-f7b466237883","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_image.main: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.626722+02:00","hook":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"docker_volume.home_volume: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.627335+02:00","hook":{"resource":{"addr":"docker_volume.home_volume","module":"","resource":"docker_volume.home_volume","implied_provider":"docker","resource_type":"docker_volume","resource_name":"home_volume","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"docker_volume.home_volume: Creation complete after 0s [id=coder-feb06d32-3252-4cd8-b7db-ea0c5145747f-home]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.660616+02:00","hook":{"resource":{"addr":"docker_volume.home_volume","module":"","resource":"docker_volume.home_volume","implied_provider":"docker","resource_type":"docker_volume","resource_name":"home_volume","resource_key":null},"action":"create","id_key":"id","id_value":"coder-feb06d32-3252-4cd8-b7db-ea0c5145747f-home","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_image.main: Creation complete after 0s [id=sha256:443d199e8bfcce69c2aa494b36b5f8b04c3b183277cd19190e9589fd8552d618nginx:latest]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.669954+02:00","hook":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create","id_key":"id","id_value":"sha256:443d199e8bfcce69c2aa494b36b5f8b04c3b183277cd19190e9589fd8552d618nginx:latest","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_container.workspace[0]: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.682223+02:00","hook":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"docker_container.workspace[0]: Creation complete after 0s [id=e39f34233fe1f6d18a33eaed8ad47ef1ae19ccf8cf6841858d5f2dafe4e3c8c9]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:40.186482+02:00","hook":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create","id_key":"id","id_value":"e39f34233fe1f6d18a33eaed8ad47ef1ae19ccf8cf6841858d5f2dafe4e3c8c9","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"Apply complete! Resources: 4 added, 0 changed, 0 destroyed.","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:40.204593+02:00","changes":{"add":4,"change":0,"import":0,"remove":0,"operation":"apply"},"type":"change_summary"} +{"@level":"info","@message":"Outputs: 0","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:40.205051+02:00","outputs":{},"type":"outputs"} +-- timings -- +{"start":"2024-08-15T08:26:39.194726Z","end":"2024-08-15T08:26:39.195820Z","action":"read","source":"coder","resource":"data.coder_workspace.me","stage":"plan","state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.194726Z","end":"2024-08-15T08:26:39.195712Z","action":"read","source":"coder","resource":"data.coder_provisioner.me","stage":"plan","state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.194726Z","end":"2024-08-15T08:26:39.195836Z","action":"read","source":"coder","resource":"data.coder_parameter.memory_size","stage":"plan","state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.616546Z","end":"2024-08-15T08:26:39.618045Z","action":"create","source":"coder","resource":"coder_agent.main","stage":"apply","state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.626722Z","end":"2024-08-15T08:26:39.669954Z","action":"create","source":"docker","resource":"docker_image.main","stage":"apply","state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.627335Z","end":"2024-08-15T08:26:39.660616Z","action":"create","source":"docker","resource":"docker_volume.home_volume","stage":"apply","state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.682223Z","end":"2024-08-15T08:26:40.186482Z","action":"create","source":"docker","resource":"docker_container.workspace[0]","stage":"apply","state":"COMPLETED"} \ No newline at end of file diff --git a/provisioner/terraform/testdata/timings-aggregation/error.txtar b/provisioner/terraform/testdata/timings-aggregation/error.txtar new file mode 100644 index 0000000000000..a71db9ca41e18 --- /dev/null +++ b/provisioner/terraform/testdata/timings-aggregation/error.txtar @@ -0,0 +1,113 @@ +Logs of an attempt to apply a resource which encounters an error. + +-- plan -- +{"@level":"info","@message":"Terraform 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:22.823175+02:00","terraform":"1.9.2","type":"version","ui":"1.2"} +{"@level":"info","@message":"data.coder_provisioner.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.209992+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_parameter.argument: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.210000+02:00","hook":{"resource":{"addr":"data.coder_parameter.argument","module":"","resource":"data.coder_parameter.argument","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"argument","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.210004+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide","module":"module.jetbrains_gateway","resource":"data.coder_parameter.jetbrains_ide","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"jetbrains_ide","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_workspace.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.210006+02:00","hook":{"resource":{"addr":"data.coder_workspace.me","module":"","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_workspace.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.210008+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_workspace.me","module":"module.jetbrains_gateway","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_provisioner.me: Refresh complete after 0s [id=3893952e-e5f2-4a98-a65d-3ee06e0e2f12]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.211454+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"3893952e-e5f2-4a98-a65d-3ee06e0e2f12","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_workspace.me: Refresh complete after 0s [id=82090a02-f4e3-46bd-9c84-7a1b2bd7f8c8]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.211697+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_workspace.me","module":"module.jetbrains_gateway","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"82090a02-f4e3-46bd-9c84-7a1b2bd7f8c8","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"data.coder_parameter.argument: Refresh complete after 0s [id=f2a0c8f2-527f-4b2a-b388-0c490d37e728]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.211745+02:00","hook":{"resource":{"addr":"data.coder_parameter.argument","module":"","resource":"data.coder_parameter.argument","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"argument","resource_key":null},"action":"read","id_key":"id","id_value":"f2a0c8f2-527f-4b2a-b388-0c490d37e728","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide: Refresh complete after 0s [id=228fd650-0c83-4b1a-82a7-d110e5ffa141]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.212438+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide","module":"module.jetbrains_gateway","resource":"data.coder_parameter.jetbrains_ide","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"jetbrains_ide","resource_key":null},"action":"read","id_key":"id","id_value":"228fd650-0c83-4b1a-82a7-d110e5ffa141","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"data.coder_workspace.me: Refresh complete after 0s [id=82090a02-f4e3-46bd-9c84-7a1b2bd7f8c8]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.212607+02:00","hook":{"resource":{"addr":"data.coder_workspace.me","module":"","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"82090a02-f4e3-46bd-9c84-7a1b2bd7f8c8","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"null_resource.force_apply: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.227631+02:00","change":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"coder_agent.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.227652+02:00","change":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"coder_script.oops: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.227655+02:00","change":{"resource":{"addr":"coder_script.oops","module":"","resource":"coder_script.oops","implied_provider":"coder","resource_type":"coder_script","resource_name":"oops","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"module.jetbrains_gateway.coder_app.gateway: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.227659+02:00","change":{"resource":{"addr":"module.jetbrains_gateway.coder_app.gateway","module":"module.jetbrains_gateway","resource":"coder_app.gateway","implied_provider":"coder","resource_type":"coder_app","resource_name":"gateway","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_image.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.227662+02:00","change":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_container.workspace[0]: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.227674+02:00","change":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"Plan: 6 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.227684+02:00","changes":{"add":6,"change":0,"import":0,"remove":0,"operation":"plan"},"type":"change_summary"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.228625+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":80,"column":42,"byte":1659},"end":{"line":80,"column":48,"byte":1665}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" name = \"coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}\"","start_line":80,"highlight_start_offset":41,"highlight_end_offset":47,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.229002+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":99,"column":36,"byte":2293},"end":{"line":99,"column":42,"byte":2299}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner","start_line":99,"highlight_start_offset":35,"highlight_end_offset":41,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.229350+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner_id\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":103,"column":36,"byte":2379},"end":{"line":103,"column":45,"byte":2388}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner_id","start_line":103,"highlight_start_offset":35,"highlight_end_offset":44,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.229687+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":80,"column":42,"byte":1659},"end":{"line":80,"column":48,"byte":1665}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" name = \"coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}\"","start_line":80,"highlight_start_offset":41,"highlight_end_offset":47,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.230027+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":99,"column":36,"byte":2293},"end":{"line":99,"column":42,"byte":2299}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner","start_line":99,"highlight_start_offset":35,"highlight_end_offset":41,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:24.230363+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner_id\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":103,"column":36,"byte":2379},"end":{"line":103,"column":45,"byte":2388}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner_id","start_line":103,"highlight_start_offset":35,"highlight_end_offset":44,"values":[]}},"type":"diagnostic"} +{"@level":"info","@message":"Terraform 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:34.917480+02:00","terraform":"1.9.2","type":"version","ui":"1.2"} +{"@level":"info","@message":"data.coder_parameter.argument: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.198205+02:00","hook":{"resource":{"addr":"data.coder_parameter.argument","module":"","resource":"data.coder_parameter.argument","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"argument","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_workspace.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.198207+02:00","hook":{"resource":{"addr":"data.coder_workspace.me","module":"","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_parameter.argument: Refresh complete after 0s [id=271583ea-f59b-4a41-81e7-81e4285de037]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.199241+02:00","hook":{"resource":{"addr":"data.coder_parameter.argument","module":"","resource":"data.coder_parameter.argument","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"argument","resource_key":null},"action":"read","id_key":"id","id_value":"271583ea-f59b-4a41-81e7-81e4285de037","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"data.coder_workspace.me: Refresh complete after 0s [id=e1a65799-9978-43e8-a752-bea95d15a68e]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.200058+02:00","hook":{"resource":{"addr":"data.coder_workspace.me","module":"","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"e1a65799-9978-43e8-a752-bea95d15a68e","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"data.coder_provisioner.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.200671+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_workspace.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.200993+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_workspace.me","module":"module.jetbrains_gateway","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_provisioner.me: Refresh complete after 0s [id=0465a592-aa80-49e9-b511-88ef42937f19]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.201032+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"0465a592-aa80-49e9-b511-88ef42937f19","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.201143+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide","module":"module.jetbrains_gateway","resource":"data.coder_parameter.jetbrains_ide","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"jetbrains_ide","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_workspace.me: Refresh complete after 0s [id=e1a65799-9978-43e8-a752-bea95d15a68e]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.201434+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_workspace.me","module":"module.jetbrains_gateway","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"e1a65799-9978-43e8-a752-bea95d15a68e","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide: Refresh complete after 0s [id=ab94c14a-e63e-40f9-9ac2-da9dd32dba69]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.201824+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide","module":"module.jetbrains_gateway","resource":"data.coder_parameter.jetbrains_ide","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"jetbrains_ide","resource_key":null},"action":"read","id_key":"id","id_value":"ab94c14a-e63e-40f9-9ac2-da9dd32dba69","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_image.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.212508+02:00","change":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"null_resource.force_apply: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.212529+02:00","change":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"coder_agent.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.212533+02:00","change":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"coder_script.oops: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.212539+02:00","change":{"resource":{"addr":"coder_script.oops","module":"","resource":"coder_script.oops","implied_provider":"coder","resource_type":"coder_script","resource_name":"oops","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"module.jetbrains_gateway.coder_app.gateway: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.212543+02:00","change":{"resource":{"addr":"module.jetbrains_gateway.coder_app.gateway","module":"module.jetbrains_gateway","resource":"coder_app.gateway","implied_provider":"coder","resource_type":"coder_app","resource_name":"gateway","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_container.workspace[0]: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.212548+02:00","change":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"Plan: 6 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.212554+02:00","changes":{"add":6,"change":0,"import":0,"remove":0,"operation":"plan"},"type":"change_summary"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.212995+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":80,"column":42,"byte":1659},"end":{"line":80,"column":48,"byte":1665}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" name = \"coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}\"","start_line":80,"highlight_start_offset":41,"highlight_end_offset":47,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.213403+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":99,"column":36,"byte":2293},"end":{"line":99,"column":42,"byte":2299}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner","start_line":99,"highlight_start_offset":35,"highlight_end_offset":41,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.213773+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner_id\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":103,"column":36,"byte":2379},"end":{"line":103,"column":45,"byte":2388}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner_id","start_line":103,"highlight_start_offset":35,"highlight_end_offset":44,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.214120+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":80,"column":42,"byte":1659},"end":{"line":80,"column":48,"byte":1665}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" name = \"coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}\"","start_line":80,"highlight_start_offset":41,"highlight_end_offset":47,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.214471+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":99,"column":36,"byte":2293},"end":{"line":99,"column":42,"byte":2299}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner","start_line":99,"highlight_start_offset":35,"highlight_end_offset":41,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.215417+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner_id\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":103,"column":36,"byte":2379},"end":{"line":103,"column":45,"byte":2388}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner_id","start_line":103,"highlight_start_offset":35,"highlight_end_offset":44,"values":[]}},"type":"diagnostic"} +-- apply -- +{"@level":"info","@message":"Terraform 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.551400+02:00","terraform":"1.9.2","type":"version","ui":"1.2"} +{"@level":"info","@message":"docker_image.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.657040+02:00","change":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"null_resource.force_apply: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.657084+02:00","change":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"coder_agent.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.657091+02:00","change":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"coder_script.oops: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.657102+02:00","change":{"resource":{"addr":"coder_script.oops","module":"","resource":"coder_script.oops","implied_provider":"coder","resource_type":"coder_script","resource_name":"oops","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"module.jetbrains_gateway.coder_app.gateway: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.657112+02:00","change":{"resource":{"addr":"module.jetbrains_gateway.coder_app.gateway","module":"module.jetbrains_gateway","resource":"coder_app.gateway","implied_provider":"coder","resource_type":"coder_app","resource_name":"gateway","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_container.workspace[0]: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.657117+02:00","change":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"null_resource.force_apply: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.733209+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"coder_agent.main: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.733249+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"null_resource.force_apply: Provisioning with 'local-exec'...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.734017+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec"},"type":"provision_start"} +{"@level":"info","@message":"coder_agent.main: Creation complete after 0s [id=ddf1ac02-0871-4ce6-8586-2ae40dedd108]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.734361+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create","id_key":"id","id_value":"ddf1ac02-0871-4ce6-8586-2ae40dedd108","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): Executing: [\"/bin/sh\" \"-c\" \"terraform refresh -target=data.http.example\"]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.734443+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"Executing: [\"/bin/sh\" \"-c\" \"terraform refresh -target=data.http.example\"]"},"type":"provision_progress"} +{"@level":"info","@message":"docker_image.main: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.743474+02:00","hook":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"coder_script.oops: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.743860+02:00","hook":{"resource":{"addr":"coder_script.oops","module":"","resource":"coder_script.oops","implied_provider":"coder","resource_type":"coder_script","resource_name":"oops","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"module.jetbrains_gateway.coder_app.gateway: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.744322+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.coder_app.gateway","module":"module.jetbrains_gateway","resource":"coder_app.gateway","implied_provider":"coder","resource_type":"coder_app","resource_name":"gateway","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"coder_script.oops: Creation complete after 0s [id=fbb33fcb-70b8-4c35-b8d9-0f861a4d94dc]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.744685+02:00","hook":{"resource":{"addr":"coder_script.oops","module":"","resource":"coder_script.oops","implied_provider":"coder","resource_type":"coder_script","resource_name":"oops","resource_key":null},"action":"create","id_key":"id","id_value":"fbb33fcb-70b8-4c35-b8d9-0f861a4d94dc","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"module.jetbrains_gateway.coder_app.gateway: Creation complete after 0s [id=b18ccb68-1b14-4b79-9711-2fd5231f0ea0]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.749897+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.coder_app.gateway","module":"module.jetbrains_gateway","resource":"coder_app.gateway","implied_provider":"coder","resource_type":"coder_app","resource_name":"gateway","resource_key":null},"action":"create","id_key":"id","id_value":"b18ccb68-1b14-4b79-9711-2fd5231f0ea0","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_image.main: Creation complete after 0s [id=sha256:3fba0c87fcc8ba126bf99e4ee205b43c91ffc6b15bb052315312e71bc6296551busybox]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.764011+02:00","hook":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create","id_key":"id","id_value":"sha256:3fba0c87fcc8ba126bf99e4ee205b43c91ffc6b15bb052315312e71bc6296551busybox","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_container.workspace[0]: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.772885+02:00","hook":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m╷\u001b[0m\u001b[0m","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.810643+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m╷\u001b[0m\u001b[0m"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m\u001b[1m\u001b[31mError: \u001b[0m\u001b[0m\u001b[1mError acquiring the state lock\u001b[0m","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.810824+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m\u001b[1m\u001b[31mError: \u001b[0m\u001b[0m\u001b[1mError acquiring the state lock\u001b[0m"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.810884+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m\u001b[0mError message: resource temporarily unavailable","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.810897+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m\u001b[0mError message: resource temporarily unavailable"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0mLock Info:","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.810931+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0mLock Info:"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m ID: ee05d38d-92ba-31b5-549c-9fb1da816f40","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.810988+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m ID: ee05d38d-92ba-31b5-549c-9fb1da816f40"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m Path: terraform.tfstate","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811118+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m Path: terraform.tfstate"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m Operation: OperationTypeApply","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811150+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m Operation: OperationTypeApply"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m Who: danny@Dannys-MBP.Dlink","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811189+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m Who: danny@Dannys-MBP.Dlink"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m Version: 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811205+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m Version: 1.9.2"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m Created: 2024-08-15 08:09:36.581953 +0000 UTC","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811244+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m Created: 2024-08-15 08:09:36.581953 +0000 UTC"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m Info:","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811270+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m Info:"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811372+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0m","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811438+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0m"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0mTerraform acquires a state lock to protect the state from being written","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811526+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0mTerraform acquires a state lock to protect the state from being written"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0mby multiple users at the same time. Please resolve the issue above and try","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811660+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0mby multiple users at the same time. Please resolve the issue above and try"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0magain. For most commands, you can disable locking with the \"-lock=false\"","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811756+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0magain. For most commands, you can disable locking with the \"-lock=false\""},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m│\u001b[0m \u001b[0mflag, but this is not recommended.","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811808+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m│\u001b[0m \u001b[0mflag, but this is not recommended."},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec): \u001b[31m╵\u001b[0m\u001b[0m","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811859+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec","output":"\u001b[31m╵\u001b[0m\u001b[0m"},"type":"provision_progress"} +{"@level":"info","@message":"null_resource.force_apply: (local-exec) Provisioning errored","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.811901+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"provisioner":"local-exec"},"type":"provision_errored"} +{"@level":"info","@message":"null_resource.force_apply: Creation errored after 0s","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:36.812108+02:00","hook":{"resource":{"addr":"null_resource.force_apply","module":"","resource":"null_resource.force_apply","implied_provider":"null","resource_type":"null_resource","resource_name":"force_apply","resource_key":null},"action":"create","elapsed_seconds":0},"type":"apply_errored"} +{"@level":"info","@message":"docker_container.workspace[0]: Creation complete after 0s [id=d1b7a49ed5999b9d04b9ccf399988906f39e8c760c9dd853f9bd0aac9c1c7676]","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:37.307787+02:00","hook":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create","id_key":"id","id_value":"d1b7a49ed5999b9d04b9ccf399988906f39e8c760c9dd853f9bd0aac9c1c7676","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:37.321624+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":80,"column":42,"byte":1659},"end":{"line":80,"column":48,"byte":1665}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" name = \"coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}\"","start_line":80,"highlight_start_offset":41,"highlight_end_offset":47,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:37.322400+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":99,"column":36,"byte":2293},"end":{"line":99,"column":42,"byte":2299}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner","start_line":99,"highlight_start_offset":35,"highlight_end_offset":41,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:37.322919+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner_id\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":103,"column":36,"byte":2379},"end":{"line":103,"column":45,"byte":2388}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner_id","start_line":103,"highlight_start_offset":35,"highlight_end_offset":44,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:37.323286+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":80,"column":42,"byte":1659},"end":{"line":80,"column":48,"byte":1665}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" name = \"coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}\"","start_line":80,"highlight_start_offset":41,"highlight_end_offset":47,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:37.323631+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":99,"column":36,"byte":2293},"end":{"line":99,"column":42,"byte":2299}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner","start_line":99,"highlight_start_offset":35,"highlight_end_offset":41,"values":[]}},"type":"diagnostic"} +{"@level":"warn","@message":"Warning: Deprecated attribute","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:37.323976+02:00","diagnostic":{"severity":"warning","summary":"Deprecated attribute","detail":"The attribute \"owner_id\" is deprecated. Refer to the provider documentation for details.","range":{"filename":"main.tf","start":{"line":103,"column":36,"byte":2379},"end":{"line":103,"column":45,"byte":2388}},"snippet":{"context":"resource \"docker_container\" \"workspace\"","code":" value = data.coder_workspace.me.owner_id","start_line":103,"highlight_start_offset":35,"highlight_end_offset":44,"values":[]}},"type":"diagnostic"} +{"@level":"error","@message":"Error: local-exec provisioner error","@module":"terraform.ui","@timestamp":"2024-08-15T10:09:37.324321+02:00","diagnostic":{"severity":"error","summary":"local-exec provisioner error","detail":"Error running command 'terraform refresh -target=data.http.example': exit status 1. Output: \u001b[31m╷\u001b[0m\u001b[0m\n\u001b[31m│\u001b[0m \u001b[0m\u001b[1m\u001b[31mError: \u001b[0m\u001b[0m\u001b[1mError acquiring the state lock\u001b[0m\n\u001b[31m│\u001b[0m \u001b[0m\n\u001b[31m│\u001b[0m \u001b[0m\u001b[0mError message: resource temporarily unavailable\n\u001b[31m│\u001b[0m \u001b[0mLock Info:\n\u001b[31m│\u001b[0m \u001b[0m ID: ee05d38d-92ba-31b5-549c-9fb1da816f40\n\u001b[31m│\u001b[0m \u001b[0m Path: terraform.tfstate\n\u001b[31m│\u001b[0m \u001b[0m Operation: OperationTypeApply\n\u001b[31m│\u001b[0m \u001b[0m Who: danny@Dannys-MBP.Dlink\n\u001b[31m│\u001b[0m \u001b[0m Version: 1.9.2\n\u001b[31m│\u001b[0m \u001b[0m Created: 2024-08-15 08:09:36.581953 +0000 UTC\n\u001b[31m│\u001b[0m \u001b[0m Info: \n\u001b[31m│\u001b[0m \u001b[0m\n\u001b[31m│\u001b[0m \u001b[0m\n\u001b[31m│\u001b[0m \u001b[0mTerraform acquires a state lock to protect the state from being written\n\u001b[31m│\u001b[0m \u001b[0mby multiple users at the same time. Please resolve the issue above and try\n\u001b[31m│\u001b[0m \u001b[0magain. For most commands, you can disable locking with the \"-lock=false\"\n\u001b[31m│\u001b[0m \u001b[0mflag, but this is not recommended.\n\u001b[31m╵\u001b[0m\u001b[0m\n","address":"null_resource.force_apply","range":{"filename":"main.tf","start":{"line":55,"column":28,"byte":1074},"end":{"line":55,"column":29,"byte":1075}},"snippet":{"context":"resource \"null_resource\" \"force_apply\"","code":" provisioner \"local-exec\" {","start_line":55,"highlight_start_offset":27,"highlight_end_offset":28,"values":[]}},"type":"diagnostic"} +-- timings -- +{"start":"2024-08-15T08:09:36.198205Z","end":"2024-08-15T08:09:36.199241Z","action":"read","source":"coder","resource":"data.coder_parameter.argument","stage":"plan","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.198207Z","end":"2024-08-15T08:09:36.200058Z","action":"read","source":"coder","resource":"data.coder_workspace.me","stage":"plan","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.200671Z","end":"2024-08-15T08:09:36.201032Z","action":"read","source":"coder","resource":"data.coder_provisioner.me","stage":"plan","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.200993Z","end":"2024-08-15T08:09:36.201434Z","action":"read","source":"coder","resource":"module.jetbrains_gateway.data.coder_workspace.me","stage":"plan","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.201143Z","end":"2024-08-15T08:09:36.201824Z","action":"read","source":"coder","resource":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide","stage":"plan","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.733209Z","end":"2024-08-15T08:09:36.812108Z","action":"create","source":"null","resource":"null_resource.force_apply","stage":"apply","state":"FAILED"} +{"start":"2024-08-15T08:09:36.733249Z","end":"2024-08-15T08:09:36.734361Z","action":"create","source":"coder","resource":"coder_agent.main","stage":"apply","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.734017Z","end":"2024-08-15T08:09:36.811901Z","action":"provision","source":"null","resource":"null_resource.force_apply","stage":"apply","state":"FAILED"} +{"start":"2024-08-15T08:09:36.743474Z","end":"2024-08-15T08:09:36.764011Z","action":"create","source":"docker","resource":"docker_image.main","stage":"apply","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.743860Z","end":"2024-08-15T08:09:36.744685Z","action":"create","source":"coder","resource":"coder_script.oops","stage":"apply","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.744322Z","end":"2024-08-15T08:09:36.749897Z","action":"create","source":"coder","resource":"module.jetbrains_gateway.coder_app.gateway","stage":"apply","state":"COMPLETED"} +{"start":"2024-08-15T08:09:36.772885Z","end":"2024-08-15T08:09:37.307787Z","action":"create","source":"docker","resource":"docker_container.workspace[0]","stage":"apply","state":"COMPLETED"} \ No newline at end of file diff --git a/provisioner/terraform/testdata/timings-aggregation/fake-terraform.sh b/provisioner/terraform/testdata/timings-aggregation/fake-terraform.sh new file mode 100755 index 0000000000000..4eb0d11ad0ec6 --- /dev/null +++ b/provisioner/terraform/testdata/timings-aggregation/fake-terraform.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +function terraform_version() { + cat <<'EOL' +{ + "terraform_version": "1.9.2", + "platform": "darwin_arm64", + "provider_selections": {}, + "terraform_outdated": true +} +EOL +} + +function terraform_show() { + cat <<'EOL' +{"format_version":"1.2","terraform_version":"1.5.7","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":1,"values":{"arch":"arm64","auth":"token","connection_timeout":120,"dir":null,"env":null,"login_before_ready":true,"metadata":[{"display_name":"CPU Usage","interval":10,"key":"0_cpu_usage","order":null,"script":"coder stat cpu","timeout":1},{"display_name":"RAM Usage","interval":10,"key":"1_ram_usage","order":null,"script":"coder stat mem","timeout":1}],"motd_file":null,"order":null,"os":"linux","shutdown_script":null,"shutdown_script_timeout":300,"startup_script":null,"startup_script_behavior":null,"startup_script_timeout":300,"troubleshooting_url":null},"sensitive_values":{"display_apps":[],"metadata":[{},{}]}},{"address":"docker_container.workspace[0]","mode":"managed","type":"docker_container","name":"workspace","index":0,"provider_name":"registry.terraform.io/kreuzwerker/docker","schema_version":2,"values":{"attach":false,"capabilities":[],"cgroupns_mode":null,"container_read_refresh_timeout_milliseconds":15000,"cpu_set":null,"cpu_shares":null,"destroy_grace_seconds":null,"devices":[],"dns":null,"dns_opts":null,"dns_search":null,"domainname":null,"gpus":null,"group_add":null,"host":[{"host":"host.docker.internal","ip":"host-gateway"}],"hostname":"barry1723722791","image":"nginx:latest","labels":[{"label":"coder.owner","value":"danny"},{"label":"coder.owner_id","value":"ec669dd6-ecf6-4da3-b1c6-fbc60c782e0e"},{"label":"coder.workspace_id","value":"1b0cd26b-9e35-4107-8aab-5827419bac68"},{"label":"coder.workspace_name","value":"barry1723722791"}],"log_opts":null,"logs":false,"max_retry_count":null,"memory":100,"memory_swap":null,"mounts":[],"must_run":true,"name":"coder-danny-barry1723722791","network_mode":null,"networks_advanced":[],"pid_mode":null,"ports":[],"privileged":null,"publish_all_ports":null,"read_only":false,"remove_volumes":true,"restart":"always","rm":false,"start":true,"stdin_open":false,"storage_opts":null,"sysctls":null,"tmpfs":null,"tty":false,"ulimit":[],"upload":[],"user":null,"userns_mode":null,"volumes":[{"container_path":"/home/danny","from_container":"","host_path":"","read_only":false,"volume_name":"coder-1b0cd26b-9e35-4107-8aab-5827419bac68-home"}],"wait":false,"wait_timeout":60,"working_dir":null},"sensitive_values":{"capabilities":[],"command":[],"devices":[],"entrypoint":[],"env":true,"healthcheck":[],"host":[{}],"labels":[{},{},{},{}],"mounts":[],"network_data":[],"networks_advanced":[],"ports":[],"security_opts":[],"ulimit":[],"upload":[],"volumes":[{}]}},{"address":"docker_image.main","mode":"managed","type":"docker_image","name":"main","provider_name":"registry.terraform.io/kreuzwerker/docker","schema_version":0,"values":{"build":[],"force_remove":null,"keep_locally":true,"name":"nginx:latest","platform":null,"pull_triggers":null,"triggers":null},"sensitive_values":{"build":[]}},{"address":"docker_volume.home_volume","mode":"managed","type":"docker_volume","name":"home_volume","provider_name":"registry.terraform.io/kreuzwerker/docker","schema_version":1,"values":{"driver_opts":null,"labels":[{"label":"coder.owner","value":"danny"},{"label":"coder.owner_id","value":"ec669dd6-ecf6-4da3-b1c6-fbc60c782e0e"},{"label":"coder.workspace_id","value":"1b0cd26b-9e35-4107-8aab-5827419bac68"},{"label":"coder.workspace_name_at_creation","value":"barry1723722791"}],"name":"coder-1b0cd26b-9e35-4107-8aab-5827419bac68-home"},"sensitive_values":{"labels":[{},{},{},{}]}}]}},"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":"arm64","auth":"token","connection_timeout":120,"dir":null,"env":null,"login_before_ready":true,"metadata":[{"display_name":"CPU Usage","interval":10,"key":"0_cpu_usage","order":null,"script":"coder stat cpu","timeout":1},{"display_name":"RAM Usage","interval":10,"key":"1_ram_usage","order":null,"script":"coder stat mem","timeout":1}],"motd_file":null,"order":null,"os":"linux","shutdown_script":null,"shutdown_script_timeout":300,"startup_script":null,"startup_script_behavior":null,"startup_script_timeout":300,"troubleshooting_url":null},"after_unknown":{"display_apps":true,"id":true,"init_script":true,"metadata":[{},{}],"token":true},"before_sensitive":false,"after_sensitive":{"display_apps":[],"metadata":[{},{}],"token":true}}},{"address":"docker_container.workspace[0]","mode":"managed","type":"docker_container","name":"workspace","index":0,"provider_name":"registry.terraform.io/kreuzwerker/docker","change":{"actions":["create"],"before":null,"after":{"attach":false,"capabilities":[],"cgroupns_mode":null,"container_read_refresh_timeout_milliseconds":15000,"cpu_set":null,"cpu_shares":null,"destroy_grace_seconds":null,"devices":[],"dns":null,"dns_opts":null,"dns_search":null,"domainname":null,"gpus":null,"group_add":null,"host":[{"host":"host.docker.internal","ip":"host-gateway"}],"hostname":"barry1723722791","image":"nginx:latest","labels":[{"label":"coder.owner","value":"danny"},{"label":"coder.owner_id","value":"ec669dd6-ecf6-4da3-b1c6-fbc60c782e0e"},{"label":"coder.workspace_id","value":"1b0cd26b-9e35-4107-8aab-5827419bac68"},{"label":"coder.workspace_name","value":"barry1723722791"}],"log_opts":null,"logs":false,"max_retry_count":null,"memory":100,"memory_swap":null,"mounts":[],"must_run":true,"name":"coder-danny-barry1723722791","network_mode":null,"networks_advanced":[],"pid_mode":null,"ports":[],"privileged":null,"publish_all_ports":null,"read_only":false,"remove_volumes":true,"restart":"always","rm":false,"start":true,"stdin_open":false,"storage_opts":null,"sysctls":null,"tmpfs":null,"tty":false,"ulimit":[],"upload":[],"user":null,"userns_mode":null,"volumes":[{"container_path":"/home/danny","from_container":"","host_path":"","read_only":false,"volume_name":"coder-1b0cd26b-9e35-4107-8aab-5827419bac68-home"}],"wait":false,"wait_timeout":60,"working_dir":null},"after_unknown":{"bridge":true,"capabilities":[],"command":true,"container_logs":true,"devices":[],"entrypoint":true,"env":true,"exit_code":true,"healthcheck":true,"host":[{}],"id":true,"init":true,"ipc_mode":true,"labels":[{},{},{},{}],"log_driver":true,"mounts":[],"network_data":true,"networks_advanced":[],"ports":[],"runtime":true,"security_opts":true,"shm_size":true,"stop_signal":true,"stop_timeout":true,"ulimit":[],"upload":[],"volumes":[{}]},"before_sensitive":false,"after_sensitive":{"capabilities":[],"command":[],"devices":[],"entrypoint":[],"env":true,"healthcheck":[],"host":[{}],"labels":[{},{},{},{}],"mounts":[],"network_data":[],"networks_advanced":[],"ports":[],"security_opts":[],"ulimit":[],"upload":[],"volumes":[{}]}}},{"address":"docker_image.main","mode":"managed","type":"docker_image","name":"main","provider_name":"registry.terraform.io/kreuzwerker/docker","change":{"actions":["create"],"before":null,"after":{"build":[],"force_remove":null,"keep_locally":true,"name":"nginx:latest","platform":null,"pull_triggers":null,"triggers":null},"after_unknown":{"build":[],"id":true,"image_id":true,"repo_digest":true},"before_sensitive":false,"after_sensitive":{"build":[]}}},{"address":"docker_volume.home_volume","mode":"managed","type":"docker_volume","name":"home_volume","provider_name":"registry.terraform.io/kreuzwerker/docker","change":{"actions":["create"],"before":null,"after":{"driver_opts":null,"labels":[{"label":"coder.owner","value":"danny"},{"label":"coder.owner_id","value":"ec669dd6-ecf6-4da3-b1c6-fbc60c782e0e"},{"label":"coder.workspace_id","value":"1b0cd26b-9e35-4107-8aab-5827419bac68"},{"label":"coder.workspace_name_at_creation","value":"barry1723722791"}],"name":"coder-1b0cd26b-9e35-4107-8aab-5827419bac68-home"},"after_unknown":{"driver":true,"id":true,"labels":[{},{},{},{}],"mountpoint":true},"before_sensitive":false,"after_sensitive":{"labels":[{},{},{},{}]}}}],"prior_state":{"format_version":"1.0","terraform_version":"1.5.7","values":{"root_module":{"resources":[{"address":"data.coder_parameter.memory_size","mode":"data","type":"coder_parameter","name":"memory_size","provider_name":"registry.terraform.io/coder/coder","schema_version":0,"values":{"default":"100","description":null,"display_name":null,"ephemeral":false,"icon":null,"id":"88f32e48-320b-4b67-a9ef-053150c3f6a7","mutable":true,"name":"Memory Allocation","option":null,"optional":true,"order":null,"type":"number","validation":[],"value":"100"},"sensitive_values":{"validation":[]}},{"address":"data.coder_provisioner.me","mode":"data","type":"coder_provisioner","name":"me","provider_name":"registry.terraform.io/coder/coder","schema_version":0,"values":{"arch":"arm64","id":"5e8c4561-b101-4c60-88e9-097c5c0f73de","os":"darwin"},"sensitive_values":{}},{"address":"data.coder_workspace.me","mode":"data","type":"coder_workspace","name":"me","provider_name":"registry.terraform.io/coder/coder","schema_version":0,"values":{"access_port":3000,"access_url":"http://localhost:3000","id":"1b0cd26b-9e35-4107-8aab-5827419bac68","name":"barry1723722791","owner":"danny","owner_email":"default@example.com","owner_groups":[],"owner_id":"ec669dd6-ecf6-4da3-b1c6-fbc60c782e0e","owner_name":"default","owner_oidc_access_token":"","owner_session_token":"","start_count":1,"template_id":"","template_name":"","template_version":"","transition":"start"},"sensitive_values":{"owner_groups":[]}}]}}},"configuration":{"provider_config":{"coder":{"name":"coder","full_name":"registry.terraform.io/coder/coder"},"docker":{"name":"docker","full_name":"registry.terraform.io/kreuzwerker/docker"}},"root_module":{"resources":[{"address":"coder_agent.main","mode":"managed","type":"coder_agent","name":"main","provider_config_key":"coder","expressions":{"arch":{"references":["data.coder_provisioner.me.arch","data.coder_provisioner.me"]},"metadata":[{"display_name":{"constant_value":"CPU Usage"},"interval":{"constant_value":10},"key":{"constant_value":"0_cpu_usage"},"script":{"constant_value":"coder stat cpu"},"timeout":{"constant_value":1}},{"display_name":{"constant_value":"RAM Usage"},"interval":{"constant_value":10},"key":{"constant_value":"1_ram_usage"},"script":{"constant_value":"coder stat mem"},"timeout":{"constant_value":1}}],"os":{"constant_value":"linux"}},"schema_version":1},{"address":"docker_container.workspace","mode":"managed","type":"docker_container","name":"workspace","provider_config_key":"docker","expressions":{"entrypoint":{"references":["coder_agent.main.init_script","coder_agent.main"]},"env":{"references":["coder_agent.main.token","coder_agent.main"]},"host":[{"host":{"constant_value":"host.docker.internal"},"ip":{"constant_value":"host-gateway"}}],"hostname":{"references":["data.coder_workspace.me.name","data.coder_workspace.me"]},"image":{"references":["docker_image.main.name","docker_image.main"]},"labels":[{"label":{"constant_value":"coder.owner"},"value":{"references":["data.coder_workspace.me.owner","data.coder_workspace.me"]}},{"label":{"constant_value":"coder.owner_id"},"value":{"references":["data.coder_workspace.me.owner_id","data.coder_workspace.me"]}},{"label":{"constant_value":"coder.workspace_id"},"value":{"references":["data.coder_workspace.me.id","data.coder_workspace.me"]}},{"label":{"constant_value":"coder.workspace_name"},"value":{"references":["data.coder_workspace.me.name","data.coder_workspace.me"]}}],"memory":{"references":["data.coder_parameter.memory_size.value","data.coder_parameter.memory_size"]},"name":{"references":["data.coder_workspace.me.owner","data.coder_workspace.me","data.coder_workspace.me.name","data.coder_workspace.me"]},"restart":{"constant_value":"always"},"volumes":[{"container_path":{"references":["local.username"]},"read_only":{"constant_value":false},"volume_name":{"references":["docker_volume.home_volume.name","docker_volume.home_volume"]}}]},"schema_version":2,"count_expression":{"references":["data.coder_workspace.me.start_count","data.coder_workspace.me"]}},{"address":"docker_image.main","mode":"managed","type":"docker_image","name":"main","provider_config_key":"docker","expressions":{"keep_locally":{"constant_value":true},"name":{"constant_value":"nginx:latest"}},"schema_version":0},{"address":"docker_volume.home_volume","mode":"managed","type":"docker_volume","name":"home_volume","provider_config_key":"docker","expressions":{"labels":[{"label":{"constant_value":"coder.owner"},"value":{"references":["data.coder_workspace.me.owner","data.coder_workspace.me"]}},{"label":{"constant_value":"coder.owner_id"},"value":{"references":["data.coder_workspace.me.owner_id","data.coder_workspace.me"]}},{"label":{"constant_value":"coder.workspace_id"},"value":{"references":["data.coder_workspace.me.id","data.coder_workspace.me"]}},{"label":{"constant_value":"coder.workspace_name_at_creation"},"value":{"references":["data.coder_workspace.me.name","data.coder_workspace.me"]}}],"name":{"references":["data.coder_workspace.me.id","data.coder_workspace.me"]}},"schema_version":1},{"address":"data.coder_parameter.memory_size","mode":"data","type":"coder_parameter","name":"memory_size","provider_config_key":"coder","expressions":{"default":{"constant_value":"100"},"mutable":{"constant_value":true},"name":{"constant_value":"Memory Allocation"},"type":{"constant_value":"number"}},"schema_version":0},{"address":"data.coder_provisioner.me","mode":"data","type":"coder_provisioner","name":"me","provider_config_key":"coder","schema_version":0},{"address":"data.coder_workspace.me","mode":"data","type":"coder_workspace","name":"me","provider_config_key":"coder","schema_version":0}]}},"relevant_attributes":[{"resource":"docker_volume.home_volume","attribute":["name"]},{"resource":"data.coder_workspace.me","attribute":["owner"]},{"resource":"data.coder_workspace.me","attribute":["owner_id"]},{"resource":"data.coder_workspace.me","attribute":["name"]},{"resource":"data.coder_parameter.memory_size","attribute":["value"]},{"resource":"coder_agent.main","attribute":["init_script"]},{"resource":"docker_image.main","attribute":["name"]},{"resource":"data.coder_provisioner.me","attribute":["arch"]},{"resource":"data.coder_workspace.me","attribute":["id"]},{"resource":"coder_agent.main","attribute":["token"]}],"timestamp":"2024-08-15T11:53:22Z"} +EOL +} + +function terraform_graph() { + cat <<'EOL' +digraph { + compound = "true" + newrank = "true" + subgraph "root" { + "[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"] + "[root] data.coder_parameter.memory_size (expand)" [label = "data.coder_parameter.memory_size", shape = "box"] + "[root] data.coder_provisioner.me (expand)" [label = "data.coder_provisioner.me", shape = "box"] + "[root] data.coder_workspace.me (expand)" [label = "data.coder_workspace.me", shape = "box"] + "[root] docker_container.workspace (expand)" [label = "docker_container.workspace", shape = "box"] + "[root] docker_image.main (expand)" [label = "docker_image.main", shape = "box"] + "[root] docker_volume.home_volume (expand)" [label = "docker_volume.home_volume", shape = "box"] + "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] + "[root] provider[\"registry.terraform.io/kreuzwerker/docker\"]" [label = "provider[\"registry.terraform.io/kreuzwerker/docker\"]", shape = "diamond"] + "[root] coder_agent.main (expand)" -> "[root] data.coder_provisioner.me (expand)" + "[root] data.coder_parameter.memory_size (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] data.coder_provisioner.me (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] data.coder_workspace.me (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] docker_container.workspace (expand)" -> "[root] coder_agent.main (expand)" + "[root] docker_container.workspace (expand)" -> "[root] data.coder_parameter.memory_size (expand)" + "[root] docker_container.workspace (expand)" -> "[root] docker_image.main (expand)" + "[root] docker_container.workspace (expand)" -> "[root] docker_volume.home_volume (expand)" + "[root] docker_container.workspace (expand)" -> "[root] local.username (expand)" + "[root] docker_image.main (expand)" -> "[root] provider[\"registry.terraform.io/kreuzwerker/docker\"]" + "[root] docker_volume.home_volume (expand)" -> "[root] data.coder_workspace.me (expand)" + "[root] docker_volume.home_volume (expand)" -> "[root] provider[\"registry.terraform.io/kreuzwerker/docker\"]" + "[root] local.username (expand)" -> "[root] data.coder_workspace.me (expand)" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.main (expand)" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_parameter.memory_size (expand)" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_workspace.me (expand)" + "[root] provider[\"registry.terraform.io/kreuzwerker/docker\"] (close)" -> "[root] docker_container.workspace (expand)" + "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" + "[root] root" -> "[root] provider[\"registry.terraform.io/kreuzwerker/docker\"] (close)" + } +} +EOL +} + +function terraform_init() { + cat <<'EOL' + +Initializing the backend... + +Initializing provider plugins... +- Reusing previous version of coder/coder from the dependency lock file +- Reusing previous version of kreuzwerker/docker from the dependency lock file +- Using previously-installed coder/coder v1.0.1 +- Using previously-installed kreuzwerker/docker v3.0.2 + +Terraform has been successfully initialized! + +You may now begin working with Terraform. Try running "terraform plan" to see +any changes that are required for your infrastructure. All Terraform commands +should now work. + +If you ever set or change modules or backend configuration for Terraform, +rerun this command to reinitialize your working directory. If you forget, other +commands will detect it and remind you to do so if necessary. +EOL +} + +function terraform_plan() { + cat <<'EOL' +{"@level":"info","@message":"Terraform 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:38.097648+02:00","terraform":"1.9.2","type":"version","ui":"1.2"} +{"@level":"info","@message":"data.coder_workspace.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.194726+02:00","hook":{"resource":{"addr":"data.coder_workspace.me","module":"","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_parameter.memory_size: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.194726+02:00","hook":{"resource":{"addr":"data.coder_parameter.memory_size","module":"","resource":"data.coder_parameter.memory_size","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"memory_size","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_provisioner.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.194726+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"data.coder_provisioner.me: Refresh complete after 0s [id=2470b3d2-32f4-4f95-ac70-0971efdb8338]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.195712+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"2470b3d2-32f4-4f95-ac70-0971efdb8338","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"data.coder_workspace.me: Refresh complete after 0s [id=feb06d32-3252-4cd8-b7db-ea0c5145747f]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.195820+02:00","hook":{"resource":{"addr":"data.coder_workspace.me","module":"","resource":"data.coder_workspace.me","implied_provider":"coder","resource_type":"coder_workspace","resource_name":"me","resource_key":null},"action":"read","id_key":"id","id_value":"feb06d32-3252-4cd8-b7db-ea0c5145747f","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"data.coder_parameter.memory_size: Refresh complete after 0s [id=b136c86c-1be0-43b4-9d78-e492918c5de0]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.195836+02:00","hook":{"resource":{"addr":"data.coder_parameter.memory_size","module":"","resource":"data.coder_parameter.memory_size","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"memory_size","resource_key":null},"action":"read","id_key":"id","id_value":"b136c86c-1be0-43b4-9d78-e492918c5de0","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"coder_agent.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221555+02:00","change":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_image.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221574+02:00","change":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_volume.home_volume: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221580+02:00","change":{"resource":{"addr":"docker_volume.home_volume","module":"","resource":"docker_volume.home_volume","implied_provider":"docker","resource_type":"docker_volume","resource_name":"home_volume","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_container.workspace[0]: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221584+02:00","change":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"Plan: 4 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.221589+02:00","changes":{"add":4,"change":0,"import":0,"remove":0,"operation":"plan"},"type":"change_summary"} +EOL + + # fake writing the state file + terraform_show >terraform.tfstate +} + +function terraform_apply() { + cat <<'EOL' +{"@level":"info","@message":"Terraform 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.507006+02:00","terraform":"1.9.2","type":"version","ui":"1.2"} +{"@level":"info","@message":"coder_agent.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.572335+02:00","change":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_image.main: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.572411+02:00","change":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_volume.home_volume: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.572416+02:00","change":{"resource":{"addr":"docker_volume.home_volume","module":"","resource":"docker_volume.home_volume","implied_provider":"docker","resource_type":"docker_volume","resource_name":"home_volume","resource_key":null},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"docker_container.workspace[0]: Plan to create","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.572424+02:00","change":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"planned_change"} +{"@level":"info","@message":"coder_agent.main: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.616546+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"coder_agent.main: Creation complete after 0s [id=a23083da-4679-4396-a306-f7b466237883]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.618045+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create","id_key":"id","id_value":"a23083da-4679-4396-a306-f7b466237883","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_image.main: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.626722+02:00","hook":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"docker_volume.home_volume: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.627335+02:00","hook":{"resource":{"addr":"docker_volume.home_volume","module":"","resource":"docker_volume.home_volume","implied_provider":"docker","resource_type":"docker_volume","resource_name":"home_volume","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"docker_volume.home_volume: Creation complete after 0s [id=coder-feb06d32-3252-4cd8-b7db-ea0c5145747f-home]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.660616+02:00","hook":{"resource":{"addr":"docker_volume.home_volume","module":"","resource":"docker_volume.home_volume","implied_provider":"docker","resource_type":"docker_volume","resource_name":"home_volume","resource_key":null},"action":"create","id_key":"id","id_value":"coder-feb06d32-3252-4cd8-b7db-ea0c5145747f-home","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_image.main: Creation complete after 0s [id=sha256:443d199e8bfcce69c2aa494b36b5f8b04c3b183277cd19190e9589fd8552d618nginx:latest]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.669954+02:00","hook":{"resource":{"addr":"docker_image.main","module":"","resource":"docker_image.main","implied_provider":"docker","resource_type":"docker_image","resource_name":"main","resource_key":null},"action":"create","id_key":"id","id_value":"sha256:443d199e8bfcce69c2aa494b36b5f8b04c3b183277cd19190e9589fd8552d618nginx:latest","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"docker_container.workspace[0]: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.682223+02:00","hook":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"docker_container.workspace[0]: Creation complete after 0s [id=e39f34233fe1f6d18a33eaed8ad47ef1ae19ccf8cf6841858d5f2dafe4e3c8c9]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:40.186482+02:00","hook":{"resource":{"addr":"docker_container.workspace[0]","module":"","resource":"docker_container.workspace[0]","implied_provider":"docker","resource_type":"docker_container","resource_name":"workspace","resource_key":0},"action":"create","id_key":"id","id_value":"e39f34233fe1f6d18a33eaed8ad47ef1ae19ccf8cf6841858d5f2dafe4e3c8c9","elapsed_seconds":0},"type":"apply_complete"} +{"@level":"info","@message":"Apply complete! Resources: 4 added, 0 changed, 0 destroyed.","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:40.204593+02:00","changes":{"add":4,"change":0,"import":0,"remove":0,"operation":"apply"},"type":"change_summary"} +{"@level":"info","@message":"Outputs: 0","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:40.205051+02:00","outputs":{},"type":"outputs"} +EOL +} + +# TODO: remove +echo "$@" >>/tmp/blah + +case "$1" in +version) + terraform_version + ;; +show) + terraform_show + ;; +graph) + terraform_graph + ;; +init) + terraform_init + ;; +plan) + terraform_plan + ;; +apply) + terraform_apply + ;; +*) + echo "Usage: $0 {version|show|graph|init|plan|apply}" + exit 1 + ;; +esac diff --git a/provisioner/terraform/testdata/timings-aggregation/faster-than-light.txtar b/provisioner/terraform/testdata/timings-aggregation/faster-than-light.txtar new file mode 100644 index 0000000000000..3f9d9b2355cf5 --- /dev/null +++ b/provisioner/terraform/testdata/timings-aggregation/faster-than-light.txtar @@ -0,0 +1,7 @@ +A provisioning which appears to complete before it started has its start and end times aligned. + +-- apply -- +{"@level":"info","@message":"coder_agent.main: Creating...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.616546+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create"},"type":"apply_start"} +{"@level":"info","@message":"coder_agent.main: Creation complete after 0s [id=a23083da-4679-4396-a306-f7b466237883]","@module":"terraform.ui","@timestamp":"2024-08-15T10:21:39.618045+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create","id_key":"id","id_value":"a23083da-4679-4396-a306-f7b466237883","elapsed_seconds":0},"type":"apply_complete"} +-- timings -- +{"start":"2024-08-15T08:21:39.618045Z","end":"2024-08-15T08:21:39.618045Z","action":"create","source":"coder","resource":"coder_agent.main","stage":"apply","state":"COMPLETED"} \ No newline at end of file diff --git a/provisioner/terraform/testdata/timings-aggregation/incomplete.txtar b/provisioner/terraform/testdata/timings-aggregation/incomplete.txtar new file mode 100644 index 0000000000000..a1caeb9999f66 --- /dev/null +++ b/provisioner/terraform/testdata/timings-aggregation/incomplete.txtar @@ -0,0 +1,7 @@ +An apply_start without a corresponding apply_complete will not produce a timing (and vice-versa). + +-- plan -- +{"@level":"info","@message":"data.coder_provisioner.me: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.194726+02:00","hook":{"resource":{"addr":"data.coder_provisioner.me","module":"","resource":"data.coder_provisioner.me","implied_provider":"coder","resource_type":"coder_provisioner","resource_name":"me","resource_key":null},"action":"read"},"type":"apply_start"} +-- apply -- +{"@level":"info","@message":"coder_agent.main: Creation complete after 0s [id=a23083da-4679-4396-a306-f7b466237883]","@module":"terraform.ui","@timestamp":"2024-08-15T10:26:39.618045+02:00","hook":{"resource":{"addr":"coder_agent.main","module":"","resource":"coder_agent.main","implied_provider":"coder","resource_type":"coder_agent","resource_name":"main","resource_key":null},"action":"create","id_key":"id","id_value":"a23083da-4679-4396-a306-f7b466237883","elapsed_seconds":0},"type":"apply_complete"} +-- timings -- \ No newline at end of file diff --git a/provisioner/terraform/testdata/timings-aggregation/init.txtar b/provisioner/terraform/testdata/timings-aggregation/init.txtar new file mode 100644 index 0000000000000..df9db78255d51 --- /dev/null +++ b/provisioner/terraform/testdata/timings-aggregation/init.txtar @@ -0,0 +1,38 @@ +Init produces JSON logs, but not with discrete fields which we can parse. +It only gained the ability to output JSON logs in v1.9.0 (https://github.com/hashicorp/terraform/blob/v1.9/CHANGELOG.md#190-june-26-2024), +so I've included the non-JSON logs as well. + +Neither one produces any timings. + +-- init -- +# Before v1.9.0 +Initializing the backend... +Initializing modules... +Initializing provider plugins... +- Reusing previous version of hashicorp/http from the dependency lock file +- Reusing previous version of coder/coder from the dependency lock file +- Using previously-installed hashicorp/http v3.4.4 +- Using previously-installed coder/coder v1.0.1 + +Terraform has been successfully initialized! + +You may now begin working with Terraform. Try running "terraform plan" to see +any changes that are required for your infrastructure. All Terraform commands +should now work. + +If you ever set or change modules or backend configuration for Terraform, +rerun this command to reinitialize your working directory. If you forget, other +commands will detect it and remind you to do so if necessary. + +# After v1.9.0 +{"@level":"info","@message":"Terraform 1.9.2","@module":"terraform.ui","@timestamp":"2024-08-15T09:19:30.835464+02:00","terraform":"1.9.2","type":"version","ui":"1.2"} +{"@level":"info","@message":"Initializing the backend...","@module":"terraform.ui","@timestamp":"2024-08-15T07:19:30Z","message_code":"initializing_backend_message","type":"init_output"} +{"@level":"info","@message":"Initializing modules...","@module":"terraform.ui","@timestamp":"2024-08-15T07:19:30Z","message_code":"initializing_modules_message","type":"init_output"} +{"@level":"info","@message":"Initializing provider plugins...","@module":"terraform.ui","@timestamp":"2024-08-15T07:19:30Z","message_code":"initializing_provider_plugin_message","type":"init_output"} +{"@level":"info","@message":"coder/coder: Reusing previous version from the dependency lock file","@module":"terraform.ui","@timestamp":"2024-08-15T09:19:30.870861+02:00","type":"log"} +{"@level":"info","@message":"hashicorp/http: Reusing previous version from the dependency lock file","@module":"terraform.ui","@timestamp":"2024-08-15T09:19:31.282247+02:00","type":"log"} +{"@level":"info","@message":"coder/coder v1.0.1: Using previously-installed provider version","@module":"terraform.ui","@timestamp":"2024-08-15T09:19:31.466355+02:00","type":"log"} +{"@level":"info","@message":"hashicorp/http v3.4.4: Using previously-installed provider version","@module":"terraform.ui","@timestamp":"2024-08-15T09:19:31.479221+02:00","type":"log"} +{"@level":"info","@message":"Terraform has been successfully initialized!","@module":"terraform.ui","@timestamp":"2024-08-15T07:19:31Z","message_code":"output_init_success_message","type":"init_output"} +{"@level":"info","@message":"You may now begin working with Terraform. Try running \"terraform plan\" to see\nany changes that are required for your infrastructure. All Terraform commands\nshould now work.\n\nIf you ever set or change modules or backend configuration for Terraform,\nrerun this command to reinitialize your working directory. If you forget, other\ncommands will detect it and remind you to do so if necessary.","@module":"terraform.ui","@timestamp":"2024-08-15T07:19:31Z","message_code":"output_init_success_cli_message","type":"init_output"} +-- timings -- \ No newline at end of file diff --git a/provisioner/terraform/testdata/timings-aggregation/simple.txtar b/provisioner/terraform/testdata/timings-aggregation/simple.txtar new file mode 100644 index 0000000000000..79ed62de83dd1 --- /dev/null +++ b/provisioner/terraform/testdata/timings-aggregation/simple.txtar @@ -0,0 +1,7 @@ +The presence of an apply_start and apply_complete on the same resource results in a complete timing. + +-- plan -- +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide: Refreshing...","@module":"terraform.ui","@timestamp":"2024-08-14T16:29:29.953727+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide","module":"module.jetbrains_gateway","resource":"data.coder_parameter.jetbrains_ide","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"jetbrains_ide","resource_key":null},"action":"read"},"type":"apply_start"} +{"@level":"info","@message":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide: Refresh complete after 0s [id=60e62a98-97e4-459b-9af2-617ea9ccc385]","@module":"terraform.ui","@timestamp":"2024-08-14T16:29:29.955272+02:00","hook":{"resource":{"addr":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide","module":"module.jetbrains_gateway","resource":"data.coder_parameter.jetbrains_ide","implied_provider":"coder","resource_type":"coder_parameter","resource_name":"jetbrains_ide","resource_key":null},"action":"read","id_key":"id","id_value":"60e62a98-97e4-459b-9af2-617ea9ccc385","elapsed_seconds":0},"type":"apply_complete"} +-- timings -- +{"start":"2024-08-14T14:29:29.953727Z", "end":"2024-08-14T14:29:29.955272Z", "action":"read", "source":"coder", "resource":"module.jetbrains_gateway.data.coder_parameter.jetbrains_ide", "stage":"plan", "state":"COMPLETED"} \ No newline at end of file diff --git a/provisioner/terraform/timings.go b/provisioner/terraform/timings.go new file mode 100644 index 0000000000000..0bf6d537d4304 --- /dev/null +++ b/provisioner/terraform/timings.go @@ -0,0 +1,240 @@ +package terraform + +import ( + "fmt" + "slices" + "sync" + "time" + + "github.com/cespare/xxhash" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/coder/coder/v2/coderd/database" + "github.com/coder/coder/v2/coderd/database/dbtime" + "github.com/coder/coder/v2/provisionersdk/proto" +) + +type timingKind string + +// Copied from https://github.com/hashicorp/terraform/blob/01c0480e77263933b2b086dc8d600a69f80fad2d/internal/command/jsonformat/renderer.go +// We cannot reference these because they're in an internal package. +const ( + timingApplyStart timingKind = "apply_start" + timingApplyProgress timingKind = "apply_progress" + timingApplyComplete timingKind = "apply_complete" + timingApplyErrored timingKind = "apply_errored" + timingProvisionStart timingKind = "provision_start" + timingProvisionProgress timingKind = "provision_progress" + timingProvisionComplete timingKind = "provision_complete" + timingProvisionErrored timingKind = "provision_errored" + timingRefreshStart timingKind = "refresh_start" + timingRefreshComplete timingKind = "refresh_complete" + // Ignored. + timingChangeSummary timingKind = "change_summary" + timingDiagnostic timingKind = "diagnostic" + timingPlannedChange timingKind = "planned_change" + timingOutputs timingKind = "outputs" + timingResourceDrift timingKind = "resource_drift" + timingVersion timingKind = "version" + // These are not part of message_types, but we want to track init/graph timings as well. + timingInitStart timingKind = "init_start" + timingInitComplete timingKind = "init_complete" + timingInitErrored timingKind = "init_errored" + timingGraphStart timingKind = "graph_start" + timingGraphComplete timingKind = "graph_complete" + timingGraphErrored timingKind = "graph_errored" + // Other terraform log types which we ignore. + timingLog timingKind = "log" + timingInitOutput timingKind = "init_output" +) + +type timingAggregator struct { + stage database.ProvisionerJobTimingStage + + // Protects the stateLookup map. + lookupMu sync.Mutex + stateLookup map[uint64]*timingSpan +} + +type timingSpan struct { + kind timingKind + start, end time.Time + stage database.ProvisionerJobTimingStage + action, provider, resource string + state proto.TimingState +} + +// newTimingAggregator creates a new aggregator which measures the duration of resource init/plan/apply actions; stage +// represents the stage of provisioning the timings are occurring within. +func newTimingAggregator(stage database.ProvisionerJobTimingStage) *timingAggregator { + return &timingAggregator{ + stage: stage, + stateLookup: make(map[uint64]*timingSpan), + } +} + +// ingest accepts a timing span at a certain timestamp and assigns it a state according to the kind of timing event. +// We memoize start & completion events, and then calculate their total duration in aggregate. +// We ignore progress events because we only care about the full duration of the action (delta between *_start and *_complete events). +func (t *timingAggregator) ingest(ts time.Time, s *timingSpan) { + if s == nil { + return + } + + s.stage = t.stage + ts = dbtime.Time(ts.UTC()) + + switch s.kind { + case timingApplyStart, timingProvisionStart, timingRefreshStart, timingInitStart, timingGraphStart: + s.start = ts + s.state = proto.TimingState_STARTED + case timingApplyComplete, timingProvisionComplete, timingRefreshComplete, timingInitComplete, timingGraphComplete: + s.end = ts + s.state = proto.TimingState_COMPLETED + case timingApplyErrored, timingProvisionErrored, timingInitErrored, timingGraphErrored: + s.end = ts + s.state = proto.TimingState_FAILED + default: + // We just want start/end timings, ignore all other events. + return + } + + t.lookupMu.Lock() + // Memoize this span by its unique attributes and the determined state. + // This will be used in aggregate() to determine the duration of the resource action. + t.stateLookup[s.hashByState(s.state)] = s + t.lookupMu.Unlock() +} + +// aggregate performs a pass through all memoized events to build up a slice of *proto.Timing instances which represent +// the total time taken to perform a certain action. +// The resulting slice of *proto.Timing is NOT sorted. +func (t *timingAggregator) aggregate() []*proto.Timing { + t.lookupMu.Lock() + defer t.lookupMu.Unlock() + + // Pre-allocate len(measurements)/2 since each timing will have one STARTED and one FAILED/COMPLETED entry. + out := make([]*proto.Timing, 0, len(t.stateLookup)/2) + + for _, s := range t.stateLookup { + // We are only concerned here with failed or completed events. + if s.state != proto.TimingState_FAILED && s.state != proto.TimingState_COMPLETED { + continue + } + + // Look for a corresponding span for the STARTED state. + startSpan, ok := t.stateLookup[s.hashByState(proto.TimingState_STARTED)] + if !ok { + // Not found, we'll ignore this span. + continue + } + s.start = startSpan.start + + // Until faster-than-light travel is a possibility, let's prevent this. + // Better to capture a zero delta than a negative one. + if s.start.After(s.end) { + s.start = s.end + } + + // Let's only aggregate valid entries. + // Later we can add support for partial / failed applies, perhaps. + if s.start.IsZero() || s.end.IsZero() { + continue + } + + out = append(out, s.toProto()) + } + + return out +} + +func (l timingKind) Valid() bool { + return slices.Contains([]timingKind{ + timingApplyStart, + timingApplyProgress, + timingApplyComplete, + timingApplyErrored, + timingProvisionStart, + timingProvisionProgress, + timingProvisionComplete, + timingProvisionErrored, + timingRefreshStart, + timingRefreshComplete, + timingChangeSummary, + timingDiagnostic, + timingPlannedChange, + timingOutputs, + timingResourceDrift, + timingVersion, + timingInitStart, + timingInitComplete, + timingInitErrored, + timingGraphStart, + timingGraphComplete, + timingGraphErrored, + timingLog, + timingInitOutput, + }, l) +} + +// Category returns the category for a giving timing state so that timings can be aggregated by this category. +// We can't use the state itself because we need an `apply_start` and an `apply_complete` to both hash to the same entry +// if all other attributes are identical. +func (l timingKind) Category() string { + switch l { + case timingInitStart, timingInitComplete, timingInitErrored: + return "init" + case timingGraphStart, timingGraphComplete, timingGraphErrored: + return "graph" + case timingApplyStart, timingApplyProgress, timingApplyComplete, timingApplyErrored: + return "apply" + case timingProvisionStart, timingProvisionProgress, timingProvisionComplete, timingProvisionErrored: + return "provision" + case timingRefreshStart, timingRefreshComplete: + return "state refresh" + default: + return "?" + } +} + +// hashState computes a hash based on a timingSpan's unique properties and state. +// The combination of resource and provider names MUST be unique across entries. +func (e *timingSpan) hashByState(state proto.TimingState) uint64 { + id := fmt.Sprintf("%s:%s:%s:%s", e.kind.Category(), state.String(), e.resource, e.provider) + return xxhash.Sum64String(id) +} + +func (e *timingSpan) toProto() *proto.Timing { + // Some log entries, like state refreshes, don't have any "action" logged. + if e.action == "" { + e.action = e.kind.Category() + } + + return &proto.Timing{ + Start: timestamppb.New(e.start), + End: timestamppb.New(e.end), + Action: e.action, + Stage: string(e.stage), + Source: e.provider, + Resource: e.resource, + State: e.state, + } +} + +func createInitTimingsEvent(event timingKind) (time.Time, *timingSpan) { + return dbtime.Now(), &timingSpan{ + kind: event, + action: "initializing terraform", + provider: "terraform", + resource: "state file", + } +} + +func createGraphTimingsEvent(event timingKind) (time.Time, *timingSpan) { + return dbtime.Now(), &timingSpan{ + kind: event, + action: "building terraform dependency graph", + provider: "terraform", + resource: "state file", + } +} diff --git a/provisioner/terraform/timings_internal_test.go b/provisioner/terraform/timings_internal_test.go new file mode 100644 index 0000000000000..2dd19f7afbcf8 --- /dev/null +++ b/provisioner/terraform/timings_internal_test.go @@ -0,0 +1,143 @@ +//go:build linux || darwin + +package terraform + +import ( + "bufio" + "bytes" + _ "embed" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/tools/txtar" + + "github.com/coder/coder/v2/coderd/database" + terraform_internal "github.com/coder/coder/v2/provisioner/terraform/internal" + "github.com/coder/coder/v2/provisionersdk/proto" +) + +var ( + //go:embed testdata/timings-aggregation/simple.txtar + inputSimple []byte + //go:embed testdata/timings-aggregation/init.txtar + inputInit []byte + //go:embed testdata/timings-aggregation/error.txtar + inputError []byte + //go:embed testdata/timings-aggregation/complete.txtar + inputComplete []byte + //go:embed testdata/timings-aggregation/incomplete.txtar + inputIncomplete []byte + //go:embed testdata/timings-aggregation/faster-than-light.txtar + inputFasterThanLight []byte +) + +func TestAggregation(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + input []byte + }{ + { + name: "init", + input: inputInit, + }, + { + name: "simple", + input: inputSimple, + }, + { + name: "error", + input: inputError, + }, + { + name: "complete", + input: inputComplete, + }, + { + name: "incomplete", + input: inputIncomplete, + }, + { + name: "faster-than-light", + input: inputFasterThanLight, + }, + } + + // nolint:paralleltest // Not since go v1.22. + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + // txtar is a text-based archive format used in the stdlib for simple and elegant tests. + // + // We ALWAYS expect that the archive contains two or more "files": + // 1. JSON logs generated by a terraform execution, one per line, *one file per stage* + // N. Expected resulting timings in JSON form, one per line + arc := txtar.Parse(tc.input) + require.GreaterOrEqual(t, len(arc.Files), 2) + + t.Logf("%s: %s", t.Name(), arc.Comment) + + var actualTimings []*proto.Timing + + // The last "file" MUST contain the expected timings. + expectedTimings := arc.Files[len(arc.Files)-1] + + // Iterate over the initial "files" and extract their timings according to their stage. + for i := 0; i < len(arc.Files)-1; i++ { + file := arc.Files[i] + stage := database.ProvisionerJobTimingStage(file.Name) + require.Truef(t, stage.Valid(), "%q is not a valid stage name; acceptable values: %v", + file.Name, database.AllProvisionerJobTimingStageValues()) + + agg := newTimingAggregator(stage) + ingestAllSpans(t, file.Data, agg) + actualTimings = append(actualTimings, agg.aggregate()...) + } + + // Ensure that the expected timings were produced. + expected := terraform_internal.ParseTimingLines(t, expectedTimings.Data) + terraform_internal.StableSortTimings(t, actualTimings) // To reduce flakiness. + if !assert.True(t, terraform_internal.TimingsAreEqual(t, expected, actualTimings)) { + printExpectation(t, expected) + } + }) + } +} + +func ingestAllSpans(t *testing.T, input []byte, aggregator *timingAggregator) { + t.Helper() + + scanner := bufio.NewScanner(bytes.NewBuffer(input)) + for scanner.Scan() { + line := scanner.Bytes() + log := parseTerraformLogLine(line) + if log == nil { + continue + } + + ts, span, err := extractTimingSpan(log) + if err != nil { + // t.Logf("%s: failed span extraction on line: %q", err, line) + continue + } + + require.NotZerof(t, ts, "failed on line: %q", line) + require.NotNilf(t, span, "failed on line: %q", line) + + aggregator.ingest(ts, span) + } + + require.NoError(t, scanner.Err()) +} + +func printExpectation(t *testing.T, actual []*proto.Timing) { + t.Helper() + + t.Log("expected:") + for _, a := range actual { + terraform_internal.PrintTiming(t, a) + } +} diff --git a/provisioner/terraform/timings_test.go b/provisioner/terraform/timings_test.go new file mode 100644 index 0000000000000..0d11040db9bfc --- /dev/null +++ b/provisioner/terraform/timings_test.go @@ -0,0 +1,136 @@ +//go:build linux || darwin + +package terraform_test + +import ( + "context" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/v2/coderd/database" + terraform_internal "github.com/coder/coder/v2/provisioner/terraform/internal" + "github.com/coder/coder/v2/provisionersdk/proto" + "github.com/coder/coder/v2/testutil" +) + +// TestTimingsFromProvision uses a fake terraform binary which spits out expected log content. +// This log content is then used to usher the provisioning process along as if terraform has run, and consequently +// the timing data is extracted from the log content and validated against the expected values. +func TestTimingsFromProvision(t *testing.T) { + t.Parallel() + + cwd, err := os.Getwd() + require.NoError(t, err) + + // Given: a fake terraform bin that behaves as we expect it to. + fakeBin := filepath.Join(cwd, "testdata", "timings-aggregation/fake-terraform.sh") + + t.Logf(fakeBin) + + ctx, api := setupProvisioner(t, &provisionerServeOptions{ + binaryPath: fakeBin, + }) + sess := configure(ctx, t, api, &proto.Config{ + TemplateSourceArchive: makeTar(t, nil), + }) + + ctx, cancel := context.WithTimeout(ctx, testutil.WaitLong) + t.Cleanup(cancel) + + // When: a plan is executed in the provisioner, our fake terraform will be executed and will produce a + // state file and some log content. + err = sendPlan(sess, proto.WorkspaceTransition_START) + require.NoError(t, err) + + var timings []*proto.Timing + + for { + select { + case <-ctx.Done(): + t.Fatal(ctx.Err()) + default: + } + + msg, err := sess.Recv() + require.NoError(t, err) + + if log := msg.GetLog(); log != nil { + t.Logf("%s: %s: %s", "plan", log.Level.String(), log.Output) + } + if c := msg.GetPlan(); c != nil { + require.Empty(t, c.Error) + // Capture the timing information returned by the plan process. + timings = append(timings, c.GetTimings()...) + break + } + } + + // When: the plan has completed, let's trigger an apply. + err = sendApply(sess, proto.WorkspaceTransition_START) + require.NoError(t, err) + + for { + select { + case <-ctx.Done(): + t.Fatal(ctx.Err()) + default: + } + + msg, err := sess.Recv() + require.NoError(t, err) + + if log := msg.GetLog(); log != nil { + t.Logf("%s: %s: %s", "apply", log.Level.String(), log.Output) + } + if c := msg.GetApply(); c != nil { + require.Empty(t, c.Error) + // Capture the timing information returned by the apply process. + timings = append(timings, c.GetTimings()...) + break + } + } + + // Sort the timings stably to keep reduce flakiness. + terraform_internal.StableSortTimings(t, timings) + + // Then: the received timings should match the expected values below. + // NOTE: These timings have been encoded to JSON format to make the tests more readable. + planTimings := terraform_internal.ParseTimingLines(t, []byte(`{"start":"2024-08-15T08:26:39.194726Z", "end":"2024-08-15T08:26:39.195836Z", "action":"read", "source":"coder", "resource":"data.coder_parameter.memory_size", "stage":"plan", "state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.194726Z", "end":"2024-08-15T08:26:39.195712Z", "action":"read", "source":"coder", "resource":"data.coder_provisioner.me", "stage":"plan", "state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.194726Z", "end":"2024-08-15T08:26:39.195820Z", "action":"read", "source":"coder", "resource":"data.coder_workspace.me", "stage":"plan", "state":"COMPLETED"}`)) + applyTimings := terraform_internal.ParseTimingLines(t, []byte(`{"start":"2024-08-15T08:26:39.616546Z", "end":"2024-08-15T08:26:39.618045Z", "action":"create", "source":"coder", "resource":"coder_agent.main", "stage":"apply", "state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.626722Z", "end":"2024-08-15T08:26:39.669954Z", "action":"create", "source":"docker", "resource":"docker_image.main", "stage":"apply", "state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.627335Z", "end":"2024-08-15T08:26:39.660616Z", "action":"create", "source":"docker", "resource":"docker_volume.home_volume", "stage":"apply", "state":"COMPLETED"} +{"start":"2024-08-15T08:26:39.682223Z", "end":"2024-08-15T08:26:40.186482Z", "action":"create", "source":"docker", "resource":"docker_container.workspace[0]", "stage":"apply", "state":"COMPLETED"}`)) + initTiming := terraform_internal.ParseTimingLines(t, []byte(`{"start":"2000-01-01T01:01:01.123456Z", "end":"2000-01-01T01:01:01.123456Z", "action":"initializing terraform", "source":"terraform", "resource":"state file", "stage":"init", "state":"COMPLETED"}`))[0] + graphTiming := terraform_internal.ParseTimingLines(t, []byte(`{"start":"2000-01-01T01:01:01.123456Z", "end":"2000-01-01T01:01:01.123456Z", "action":"building terraform dependency graph", "source":"terraform", "resource":"state file", "stage":"graph", "state":"COMPLETED"}`))[0] + + require.Len(t, timings, len(planTimings)+len(applyTimings)+2) + + // init/graph timings are computed dynamically during provisioning whereas plan/apply come from the logs (fixtures) in + // provisioner/terraform/testdata/timings-aggregation/fake-terraform.sh. + // + // This walks the timings, keeping separate cursors for plan and apply. + // We manually override the init/graph timings' timestamps so that the equality check works (all other fields should be as expected). + pCursor := 0 + aCursor := 0 + for _, tim := range timings { + switch tim.Stage { + case string(database.ProvisionerJobTimingStageInit): + tim.Start, tim.End = initTiming.Start, initTiming.End + require.True(t, terraform_internal.TimingsAreEqual(t, []*proto.Timing{initTiming}, []*proto.Timing{tim})) + case string(database.ProvisionerJobTimingStageGraph): + tim.Start, tim.End = graphTiming.Start, graphTiming.End + require.True(t, terraform_internal.TimingsAreEqual(t, []*proto.Timing{graphTiming}, []*proto.Timing{tim})) + case string(database.ProvisionerJobTimingStagePlan): + require.True(t, terraform_internal.TimingsAreEqual(t, []*proto.Timing{planTimings[pCursor]}, []*proto.Timing{tim})) + pCursor++ + case string(database.ProvisionerJobTimingStageApply): + require.True(t, terraform_internal.TimingsAreEqual(t, []*proto.Timing{applyTimings[aCursor]}, []*proto.Timing{tim})) + aCursor++ + } + } +} diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index f2a8123ff780d..d026167eed757 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -1081,7 +1081,8 @@ type FailedJob_WorkspaceBuild struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + Timings []*proto.Timing `protobuf:"bytes,2,rep,name=timings,proto3" json:"timings,omitempty"` } func (x *FailedJob_WorkspaceBuild) Reset() { @@ -1123,6 +1124,13 @@ func (x *FailedJob_WorkspaceBuild) GetState() []byte { return nil } +func (x *FailedJob_WorkspaceBuild) GetTimings() []*proto.Timing { + if x != nil { + return x.Timings + } + return nil +} + type FailedJob_TemplateImport struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1206,6 +1214,7 @@ type CompletedJob_WorkspaceBuild struct { State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` Resources []*proto.Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` + Timings []*proto.Timing `protobuf:"bytes,3,rep,name=timings,proto3" json:"timings,omitempty"` } func (x *CompletedJob_WorkspaceBuild) Reset() { @@ -1254,6 +1263,13 @@ func (x *CompletedJob_WorkspaceBuild) GetResources() []*proto.Resource { return nil } +func (x *CompletedJob_WorkspaceBuild) GetTimings() []*proto.Timing { + if x != nil { + return x.Timings + } + return nil +} + type CompletedJob_TemplateImport struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1479,7 +1495,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{ 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xa5, 0x03, 0x0a, 0x09, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xd4, 0x03, 0x0a, 0x09, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, @@ -1500,159 +1516,165 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{ 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0x26, 0x0a, 0x0e, 0x57, 0x6f, 0x72, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0x55, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, - 0x6f, 0x72, 0x74, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, - 0x72, 0x79, 0x52, 0x75, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xd0, 0x06, - 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x15, - 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, - 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x48, - 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x12, 0x55, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x72, - 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x5b, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, + 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, + 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, + 0x72, 0x74, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, + 0x79, 0x52, 0x75, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x80, 0x07, 0x0a, + 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, + 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, + 0x6f, 0x62, 0x49, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x74, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, + 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x12, 0x55, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x72, 0x79, + 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, + 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x8a, 0x01, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 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, 0xf9, 0x02, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3e, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 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, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0e, 0x73, 0x74, 0x6f, 0x70, - 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, + 0x69, 0x6e, 0x67, 0x73, 0x1a, 0xf9, 0x02, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3e, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 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, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, - 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0e, 0x72, 0x69, 0x63, - 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x41, 0x0a, 0x1d, 0x65, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x1a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x61, - 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x73, 0x1a, 0x45, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, - 0x52, 0x75, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x18, 0x01, 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, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x22, 0xb0, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x18, 0x02, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x22, 0xa6, 0x03, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, - 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, - 0x25, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, - 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x14, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x72, - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, - 0x75, 0x73, 0x65, 0x72, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x77, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0e, 0x73, 0x74, 0x6f, 0x70, 0x5f, + 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, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, + 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0e, 0x72, 0x69, 0x63, 0x68, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x41, 0x0a, 0x1d, 0x65, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x1a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x61, 0x0a, + 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, + 0x1a, 0x45, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, + 0x75, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, + 0x01, 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, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, + 0xb0, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x18, 0x02, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x22, 0xa6, 0x03, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x25, + 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x52, + 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, + 0x6c, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x14, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x72, 0x69, + 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x75, + 0x73, 0x65, 0x72, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, + 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x7a, 0x0a, 0x11, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x0f, + 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x4a, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, + 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, + 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, + 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, + 0x6f, 0x73, 0x74, 0x22, 0x68, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, + 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x72, + 0x65, 0x64, 0x69, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x22, 0x0f, 0x0a, + 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x2a, 0x34, + 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, + 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, + 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, + 0x45, 0x52, 0x10, 0x01, 0x32, 0xc5, 0x03, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0a, 0x41, 0x63, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x52, 0x0a, + 0x14, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x57, 0x69, 0x74, 0x68, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x01, 0x30, + 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, + 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, + 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x7a, 0x0a, 0x11, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a, - 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x4a, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, - 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, - 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, - 0x43, 0x6f, 0x73, 0x74, 0x22, 0x68, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, - 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, - 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x63, - 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x22, 0x0f, - 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x2a, - 0x34, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, - 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, - 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, - 0x4e, 0x45, 0x52, 0x10, 0x01, 0x32, 0xc5, 0x03, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0a, 0x41, - 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x52, - 0x0a, 0x14, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x57, 0x69, 0x74, 0x68, - 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x01, - 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, - 0x61, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, - 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4a, 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, - 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, - 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x2e, 0x5a, - 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, - 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x17, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0b, + 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x2e, 0x5a, 0x2c, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, + 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1698,9 +1720,10 @@ var file_provisionerd_proto_provisionerd_proto_goTypes = []interface{}{ (*proto.RichParameterValue)(nil), // 25: provisioner.RichParameterValue (*proto.ExternalAuthProvider)(nil), // 26: provisioner.ExternalAuthProvider (*proto.Metadata)(nil), // 27: provisioner.Metadata - (*proto.Resource)(nil), // 28: provisioner.Resource - (*proto.RichParameter)(nil), // 29: provisioner.RichParameter - (*proto.ExternalAuthProviderResource)(nil), // 30: provisioner.ExternalAuthProviderResource + (*proto.Timing)(nil), // 28: provisioner.Timing + (*proto.Resource)(nil), // 29: provisioner.Resource + (*proto.RichParameter)(nil), // 30: provisioner.RichParameter + (*proto.ExternalAuthProviderResource)(nil), // 31: provisioner.ExternalAuthProviderResource } var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{ 11, // 0: provisionerd.AcquiredJob.workspace_build:type_name -> provisionerd.AcquiredJob.WorkspaceBuild @@ -1729,29 +1752,31 @@ var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{ 25, // 23: provisionerd.AcquiredJob.TemplateDryRun.rich_parameter_values:type_name -> provisioner.RichParameterValue 24, // 24: provisionerd.AcquiredJob.TemplateDryRun.variable_values:type_name -> provisioner.VariableValue 27, // 25: provisionerd.AcquiredJob.TemplateDryRun.metadata:type_name -> provisioner.Metadata - 28, // 26: provisionerd.CompletedJob.WorkspaceBuild.resources:type_name -> provisioner.Resource - 28, // 27: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource - 28, // 28: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource - 29, // 29: provisionerd.CompletedJob.TemplateImport.rich_parameters:type_name -> provisioner.RichParameter - 30, // 30: provisionerd.CompletedJob.TemplateImport.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource - 28, // 31: provisionerd.CompletedJob.TemplateDryRun.resources:type_name -> provisioner.Resource - 1, // 32: provisionerd.ProvisionerDaemon.AcquireJob:input_type -> provisionerd.Empty - 10, // 33: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:input_type -> provisionerd.CancelAcquire - 8, // 34: provisionerd.ProvisionerDaemon.CommitQuota:input_type -> provisionerd.CommitQuotaRequest - 6, // 35: provisionerd.ProvisionerDaemon.UpdateJob:input_type -> provisionerd.UpdateJobRequest - 3, // 36: provisionerd.ProvisionerDaemon.FailJob:input_type -> provisionerd.FailedJob - 4, // 37: provisionerd.ProvisionerDaemon.CompleteJob:input_type -> provisionerd.CompletedJob - 2, // 38: provisionerd.ProvisionerDaemon.AcquireJob:output_type -> provisionerd.AcquiredJob - 2, // 39: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:output_type -> provisionerd.AcquiredJob - 9, // 40: provisionerd.ProvisionerDaemon.CommitQuota:output_type -> provisionerd.CommitQuotaResponse - 7, // 41: provisionerd.ProvisionerDaemon.UpdateJob:output_type -> provisionerd.UpdateJobResponse - 1, // 42: provisionerd.ProvisionerDaemon.FailJob:output_type -> provisionerd.Empty - 1, // 43: provisionerd.ProvisionerDaemon.CompleteJob:output_type -> provisionerd.Empty - 38, // [38:44] is the sub-list for method output_type - 32, // [32:38] is the sub-list for method input_type - 32, // [32:32] is the sub-list for extension type_name - 32, // [32:32] is the sub-list for extension extendee - 0, // [0:32] is the sub-list for field type_name + 28, // 26: provisionerd.FailedJob.WorkspaceBuild.timings:type_name -> provisioner.Timing + 29, // 27: provisionerd.CompletedJob.WorkspaceBuild.resources:type_name -> provisioner.Resource + 28, // 28: provisionerd.CompletedJob.WorkspaceBuild.timings:type_name -> provisioner.Timing + 29, // 29: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource + 29, // 30: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource + 30, // 31: provisionerd.CompletedJob.TemplateImport.rich_parameters:type_name -> provisioner.RichParameter + 31, // 32: provisionerd.CompletedJob.TemplateImport.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource + 29, // 33: provisionerd.CompletedJob.TemplateDryRun.resources:type_name -> provisioner.Resource + 1, // 34: provisionerd.ProvisionerDaemon.AcquireJob:input_type -> provisionerd.Empty + 10, // 35: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:input_type -> provisionerd.CancelAcquire + 8, // 36: provisionerd.ProvisionerDaemon.CommitQuota:input_type -> provisionerd.CommitQuotaRequest + 6, // 37: provisionerd.ProvisionerDaemon.UpdateJob:input_type -> provisionerd.UpdateJobRequest + 3, // 38: provisionerd.ProvisionerDaemon.FailJob:input_type -> provisionerd.FailedJob + 4, // 39: provisionerd.ProvisionerDaemon.CompleteJob:input_type -> provisionerd.CompletedJob + 2, // 40: provisionerd.ProvisionerDaemon.AcquireJob:output_type -> provisionerd.AcquiredJob + 2, // 41: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:output_type -> provisionerd.AcquiredJob + 9, // 42: provisionerd.ProvisionerDaemon.CommitQuota:output_type -> provisionerd.CommitQuotaResponse + 7, // 43: provisionerd.ProvisionerDaemon.UpdateJob:output_type -> provisionerd.UpdateJobResponse + 1, // 44: provisionerd.ProvisionerDaemon.FailJob:output_type -> provisionerd.Empty + 1, // 45: provisionerd.ProvisionerDaemon.CompleteJob:output_type -> provisionerd.Empty + 40, // [40:46] is the sub-list for method output_type + 34, // [34:40] is the sub-list for method input_type + 34, // [34:34] is the sub-list for extension type_name + 34, // [34:34] is the sub-list for extension extendee + 0, // [0:34] is the sub-list for field type_name } func init() { file_provisionerd_proto_provisionerd_proto_init() } diff --git a/provisionerd/proto/provisionerd.proto b/provisionerd/proto/provisionerd.proto index 426ba63e2f98e..f061ae801efd7 100644 --- a/provisionerd/proto/provisionerd.proto +++ b/provisionerd/proto/provisionerd.proto @@ -53,6 +53,7 @@ message AcquiredJob { message FailedJob { message WorkspaceBuild { bytes state = 1; + repeated provisioner.Timing timings = 2; } message TemplateImport {} message TemplateDryRun {} @@ -72,6 +73,7 @@ message CompletedJob { message WorkspaceBuild { bytes state = 1; repeated provisioner.Resource resources = 2; + repeated provisioner.Timing timings = 3; } message TemplateImport { repeated provisioner.Resource start_resources = 1; diff --git a/provisionerd/runner/runner.go b/provisionerd/runner/runner.go index 08230a80051d0..edeb5d80f3194 100644 --- a/provisionerd/runner/runner.go +++ b/provisionerd/runner/runner.go @@ -19,6 +19,7 @@ import ( "golang.org/x/xerrors" "cdr.dev/slog" + "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/coderd/util/ptr" "github.com/coder/coder/v2/provisionerd/proto" @@ -996,6 +997,10 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p if applyComplete == nil { return nil, r.failedWorkspaceBuildf("invalid message type %T received from provisioner", resp.Type) } + + // Prepend the plan timings (since they occurred first). + applyComplete.Timings = append(planComplete.Timings, applyComplete.Timings...) + if applyComplete.Error != "" { r.logger.Warn(context.Background(), "apply failed; updating state", slog.F("error", applyComplete.Error), @@ -1007,7 +1012,8 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p Error: applyComplete.Error, Type: &proto.FailedJob_WorkspaceBuild_{ WorkspaceBuild: &proto.FailedJob_WorkspaceBuild{ - State: applyComplete.State, + State: applyComplete.State, + Timings: applyComplete.Timings, }, }, } @@ -1026,6 +1032,7 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p WorkspaceBuild: &proto.CompletedJob_WorkspaceBuild{ State: applyComplete.State, Resources: applyComplete.Resources, + Timings: applyComplete.Timings, }, }, }, nil diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index 39fe557ae43e1..c53abebe67fc8 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -9,6 +9,7 @@ package proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -175,6 +176,55 @@ func (WorkspaceTransition) EnumDescriptor() ([]byte, []int) { return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{2} } +type TimingState int32 + +const ( + TimingState_STARTED TimingState = 0 + TimingState_COMPLETED TimingState = 1 + TimingState_FAILED TimingState = 2 +) + +// Enum value maps for TimingState. +var ( + TimingState_name = map[int32]string{ + 0: "STARTED", + 1: "COMPLETED", + 2: "FAILED", + } + TimingState_value = map[string]int32{ + "STARTED": 0, + "COMPLETED": 1, + "FAILED": 2, + } +) + +func (x TimingState) Enum() *TimingState { + p := new(TimingState) + *p = x + return p +} + +func (x TimingState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TimingState) Descriptor() protoreflect.EnumDescriptor { + return file_provisionersdk_proto_provisioner_proto_enumTypes[3].Descriptor() +} + +func (TimingState) Type() protoreflect.EnumType { + return &file_provisionersdk_proto_provisioner_proto_enumTypes[3] +} + +func (x TimingState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TimingState.Descriptor instead. +func (TimingState) EnumDescriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{3} +} + // Empty indicates a successful request/response. type Empty struct { state protoimpl.MessageState @@ -2053,6 +2103,7 @@ type PlanComplete struct { Resources []*Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` Parameters []*RichParameter `protobuf:"bytes,3,rep,name=parameters,proto3" json:"parameters,omitempty"` ExternalAuthProviders []*ExternalAuthProviderResource `protobuf:"bytes,4,rep,name=external_auth_providers,json=externalAuthProviders,proto3" json:"external_auth_providers,omitempty"` + Timings []*Timing `protobuf:"bytes,6,rep,name=timings,proto3" json:"timings,omitempty"` } func (x *PlanComplete) Reset() { @@ -2115,6 +2166,13 @@ func (x *PlanComplete) GetExternalAuthProviders() []*ExternalAuthProviderResourc return nil } +func (x *PlanComplete) GetTimings() []*Timing { + if x != nil { + return x.Timings + } + return nil +} + // ApplyRequest asks the provisioner to apply the changes. Apply MUST be preceded by a successful plan request/response // in the same Session. The plan data is not transmitted over the wire and is cached by the provisioner in the Session. type ApplyRequest struct { @@ -2175,6 +2233,7 @@ type ApplyComplete struct { Resources []*Resource `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"` Parameters []*RichParameter `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty"` ExternalAuthProviders []*ExternalAuthProviderResource `protobuf:"bytes,5,rep,name=external_auth_providers,json=externalAuthProviders,proto3" json:"external_auth_providers,omitempty"` + Timings []*Timing `protobuf:"bytes,6,rep,name=timings,proto3" json:"timings,omitempty"` } func (x *ApplyComplete) Reset() { @@ -2244,6 +2303,108 @@ func (x *ApplyComplete) GetExternalAuthProviders() []*ExternalAuthProviderResour return nil } +func (x *ApplyComplete) GetTimings() []*Timing { + if x != nil { + return x.Timings + } + return nil +} + +type Timing struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Start *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=start,proto3" json:"start,omitempty"` + End *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=end,proto3" json:"end,omitempty"` + Action string `protobuf:"bytes,3,opt,name=action,proto3" json:"action,omitempty"` + Source string `protobuf:"bytes,4,opt,name=source,proto3" json:"source,omitempty"` + Resource string `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty"` + Stage string `protobuf:"bytes,6,opt,name=stage,proto3" json:"stage,omitempty"` + State TimingState `protobuf:"varint,7,opt,name=state,proto3,enum=provisioner.TimingState" json:"state,omitempty"` +} + +func (x *Timing) Reset() { + *x = Timing{} + if protoimpl.UnsafeEnabled { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Timing) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Timing) ProtoMessage() {} + +func (x *Timing) ProtoReflect() protoreflect.Message { + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25] + 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 Timing.ProtoReflect.Descriptor instead. +func (*Timing) Descriptor() ([]byte, []int) { + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{25} +} + +func (x *Timing) GetStart() *timestamppb.Timestamp { + if x != nil { + return x.Start + } + return nil +} + +func (x *Timing) GetEnd() *timestamppb.Timestamp { + if x != nil { + return x.End + } + return nil +} + +func (x *Timing) GetAction() string { + if x != nil { + return x.Action + } + return "" +} + +func (x *Timing) GetSource() string { + if x != nil { + return x.Source + } + return "" +} + +func (x *Timing) GetResource() string { + if x != nil { + return x.Resource + } + return "" +} + +func (x *Timing) GetStage() string { + if x != nil { + return x.Stage + } + return "" +} + +func (x *Timing) GetState() TimingState { + if x != nil { + return x.State + } + return TimingState_STARTED +} + // CancelRequest requests that the previous request be canceled gracefully. type CancelRequest struct { state protoimpl.MessageState @@ -2254,7 +2415,7 @@ type CancelRequest struct { func (x *CancelRequest) Reset() { *x = CancelRequest{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2267,7 +2428,7 @@ func (x *CancelRequest) String() string { func (*CancelRequest) ProtoMessage() {} func (x *CancelRequest) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2280,7 +2441,7 @@ func (x *CancelRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CancelRequest.ProtoReflect.Descriptor instead. func (*CancelRequest) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{25} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{26} } type Request struct { @@ -2301,7 +2462,7 @@ type Request struct { func (x *Request) Reset() { *x = Request{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2314,7 +2475,7 @@ func (x *Request) String() string { func (*Request) ProtoMessage() {} func (x *Request) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2327,7 +2488,7 @@ func (x *Request) ProtoReflect() protoreflect.Message { // Deprecated: Use Request.ProtoReflect.Descriptor instead. func (*Request) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{26} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{27} } func (m *Request) GetType() isRequest_Type { @@ -2423,7 +2584,7 @@ type Response struct { func (x *Response) Reset() { *x = Response{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2436,7 +2597,7 @@ func (x *Response) String() string { func (*Response) ProtoMessage() {} func (x *Response) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2449,7 +2610,7 @@ func (x *Response) ProtoReflect() protoreflect.Message { // Deprecated: Use Response.ProtoReflect.Descriptor instead. func (*Response) Descriptor() ([]byte, []int) { - return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{27} + return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{28} } func (m *Response) GetType() isResponse_Type { @@ -2531,7 +2692,7 @@ type Agent_Metadata struct { func (x *Agent_Metadata) Reset() { *x = Agent_Metadata{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2544,7 +2705,7 @@ func (x *Agent_Metadata) String() string { func (*Agent_Metadata) ProtoMessage() {} func (x *Agent_Metadata) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2616,7 +2777,7 @@ type Resource_Metadata struct { func (x *Resource_Metadata) Reset() { *x = Resource_Metadata{} if protoimpl.UnsafeEnabled { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[30] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2629,7 +2790,7 @@ func (x *Resource_Metadata) String() string { func (*Resource_Metadata) ProtoMessage() {} func (x *Resource_Metadata) ProtoReflect() protoreflect.Message { - mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[30] + mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2679,359 +2840,364 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x0a, 0x26, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xbb, - 0x01, 0x0a, 0x10, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 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, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x22, 0x75, 0x0a, 0x13, - 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 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, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, - 0x63, 0x6f, 0x6e, 0x22, 0xfe, 0x04, 0x0a, 0x0d, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 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, 0x09, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, - 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, - 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x67, - 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x0d, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x88, 0x01, 0x01, - 0x12, 0x2a, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, - 0x61, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x0d, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x14, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x6e, 0x6f, 0x74, - 0x6f, 0x6e, 0x69, 0x63, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x6e, 0x6f, 0x74, 0x6f, 0x6e, 0x69, 0x63, 0x12, - 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6f, - 0x72, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, - 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, - 0x61, 0x6c, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x52, 0x14, - 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x0a, 0x12, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x57, 0x0a, 0x0d, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, + 0xbb, 0x01, 0x0a, 0x10, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, + 0x61, 0x62, 0x6c, 0x65, 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, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, + 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, + 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x22, 0x75, 0x0a, + 0x13, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 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, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x69, 0x63, 0x6f, 0x6e, 0x22, 0xfe, 0x04, 0x0a, 0x0d, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 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, 0x09, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, + 0x63, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x29, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, + 0x67, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, + 0x0d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x88, 0x01, + 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x6d, 0x61, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x0d, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, + 0x14, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x6e, 0x6f, + 0x74, 0x6f, 0x6e, 0x69, 0x63, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x6e, 0x6f, 0x74, 0x6f, 0x6e, 0x69, 0x63, + 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, + 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, + 0x61, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, + 0x72, 0x61, 0x6c, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x52, + 0x14, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x0a, 0x12, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x57, 0x0a, 0x0d, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 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, 0x37, 0x0a, 0x14, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x75, + 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x49, 0x64, 0x22, 0x4a, 0x0a, 0x1c, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, + 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, + 0x49, 0x0a, 0x14, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xa0, 0x07, 0x0a, 0x05, 0x41, + 0x67, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, + 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x04, 0x61, 0x70, 0x70, 0x73, 0x18, 0x08, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x2e, 0x41, 0x70, 0x70, 0x52, 0x04, 0x61, 0x70, 0x70, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x18, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x73, 0x68, + 0x6f, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x12, 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x73, 0x68, 0x6f, 0x6f, 0x74, 0x69, 0x6e, + 0x67, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x6f, 0x74, 0x64, 0x5f, 0x66, 0x69, 0x6c, + 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x6f, 0x74, 0x64, 0x46, 0x69, 0x6c, + 0x65, 0x12, 0x37, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x12, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3b, 0x0a, 0x0c, 0x64, 0x69, + 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x44, + 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x41, 0x70, 0x70, 0x73, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, + 0x6c, 0x61, 0x79, 0x41, 0x70, 0x70, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x73, 0x18, 0x15, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x07, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, + 0x65, 0x6e, 0x76, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x6e, 0x76, 0x52, 0x09, 0x65, 0x78, + 0x74, 0x72, 0x61, 0x45, 0x6e, 0x76, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x18, 0x17, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x1a, 0xa3, 0x01, + 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, + 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x76, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x1a, 0x36, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, + 0x75, 0x74, 0x68, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x52, 0x12, 0x6c, 0x6f, 0x67, 0x69, 0x6e, + 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x22, 0xc6, 0x01, + 0x0a, 0x0b, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x41, 0x70, 0x70, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x76, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, + 0x73, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x76, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x5f, + 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, + 0x76, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x77, 0x65, 0x62, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x77, 0x65, 0x62, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, + 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x73, 0x68, 0x5f, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x73, 0x68, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, + 0x12, 0x34, 0x0a, 0x16, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, + 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x14, 0x70, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x22, 0x2f, 0x0a, 0x03, 0x45, 0x6e, 0x76, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x9f, 0x02, 0x0a, 0x06, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, + 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x10, 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x12, 0x20, 0x0a, 0x0c, 0x72, 0x75, 0x6e, 0x5f, 0x6f, 0x6e, 0x5f, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x75, 0x6e, 0x4f, 0x6e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x75, 0x6e, 0x5f, 0x6f, 0x6e, 0x5f, + 0x73, 0x74, 0x6f, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x75, 0x6e, 0x4f, + 0x6e, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x19, + 0x0a, 0x08, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x50, 0x61, 0x74, 0x68, 0x22, 0xcb, 0x02, 0x0a, 0x03, 0x41, 0x70, + 0x70, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x64, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x75, 0x62, + 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x12, 0x41, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x65, + 0x76, 0x65, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, 0x69, + 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, + 0x6c, 0x64, 0x22, 0xf1, 0x02, 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, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x68, + 0x69, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x1a, 0x69, 0x0a, 0x08, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 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, 0x37, 0x0a, 0x14, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x75, 0x74, - 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x49, 0x64, 0x22, 0x4a, 0x0a, 0x1c, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, - 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x49, - 0x0a, 0x14, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xa0, 0x07, 0x0a, 0x05, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, - 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x04, 0x61, 0x70, 0x70, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x41, 0x70, 0x70, 0x52, 0x04, 0x61, 0x70, 0x70, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x18, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x73, 0x68, 0x6f, - 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x12, 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x73, 0x68, 0x6f, 0x6f, 0x74, 0x69, 0x6e, 0x67, - 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x6f, 0x74, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x6f, 0x74, 0x64, 0x46, 0x69, 0x6c, 0x65, - 0x12, 0x37, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x12, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, - 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3b, 0x0a, 0x0c, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x44, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x41, 0x70, 0x70, 0x73, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x41, 0x70, 0x70, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x73, 0x18, 0x15, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x07, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x65, - 0x6e, 0x76, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x6e, 0x76, 0x52, 0x09, 0x65, 0x78, 0x74, - 0x72, 0x61, 0x45, 0x6e, 0x76, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, - 0x17, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x1a, 0xa3, 0x01, 0x0a, - 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x1a, 0x36, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x75, - 0x74, 0x68, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x52, 0x12, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, - 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x22, 0xc6, 0x01, 0x0a, - 0x0b, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x41, 0x70, 0x70, 0x73, 0x12, 0x16, 0x0a, 0x06, - 0x76, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, 0x73, - 0x63, 0x6f, 0x64, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x76, 0x73, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, - 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x76, - 0x73, 0x63, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, - 0x0c, 0x77, 0x65, 0x62, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x77, 0x65, 0x62, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, - 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x73, 0x68, 0x5f, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x73, 0x68, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x12, - 0x34, 0x0a, 0x16, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x14, 0x70, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, - 0x65, 0x6c, 0x70, 0x65, 0x72, 0x22, 0x2f, 0x0a, 0x03, 0x45, 0x6e, 0x76, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x9f, 0x02, 0x0a, 0x06, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x63, 0x72, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x10, 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4c, 0x6f, 0x67, - 0x69, 0x6e, 0x12, 0x20, 0x0a, 0x0c, 0x72, 0x75, 0x6e, 0x5f, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x75, 0x6e, 0x4f, 0x6e, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x75, 0x6e, 0x5f, 0x6f, 0x6e, 0x5f, 0x73, - 0x74, 0x6f, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x75, 0x6e, 0x4f, 0x6e, - 0x53, 0x74, 0x6f, 0x70, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, - 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x19, 0x0a, - 0x08, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6c, 0x6f, 0x67, 0x50, 0x61, 0x74, 0x68, 0x22, 0xcb, 0x02, 0x0a, 0x03, 0x41, 0x70, 0x70, - 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x73, 0x6c, 0x75, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x75, 0x62, 0x64, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x12, 0x41, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, - 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, - 0x64, 0x22, 0xf1, 0x02, 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, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, - 0x0a, 0x04, 0x68, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x68, 0x69, - 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, - 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x1a, 0x69, 0x0a, 0x08, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x17, 0x0a, 0x07, - 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, - 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0xef, 0x06, 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, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, - 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x21, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6f, 0x69, 0x64, - 0x63, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, - 0x77, 0x6e, 0x65, 0x72, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, - 0x42, 0x0a, 0x1e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x73, 0x68, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x4b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x1f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x77, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x73, 0x68, 0x50, - 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, - 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x22, 0x8a, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x15, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x5f, - 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0xa3, 0x02, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x4c, 0x0a, 0x12, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, - 0x61, 0x64, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, - 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, - 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb5, 0x02, 0x0a, 0x0b, 0x50, - 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x53, 0x0a, - 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x72, - 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, - 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x59, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, - 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x15, 0x65, 0x78, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x22, 0xf8, 0x01, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 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, 0x12, 0x3a, - 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, - 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x61, 0x0a, 0x17, 0x65, 0x78, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x41, 0x0a, + 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x17, 0x0a, + 0x07, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0xef, 0x06, 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, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x21, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6f, 0x69, + 0x64, 0x63, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x12, 0x42, 0x0a, 0x1e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, + 0x65, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x73, 0x68, 0x50, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x1f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x73, 0x68, + 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x22, 0x8a, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa3, 0x02, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x4c, 0x0a, + 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, + 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, + 0x64, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb5, 0x02, 0x0a, 0x0b, + 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x53, + 0x0a, 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, + 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, + 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x59, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x15, 0x65, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x73, 0x22, 0xa7, 0x02, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 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, 0x12, + 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, + 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x61, 0x0a, 0x17, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x2d, + 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, + 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x41, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x22, 0x8f, 0x02, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x22, 0xbe, 0x02, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 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, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, @@ -3048,58 +3214,80 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x8c, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x2d, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x31, - 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, - 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, - 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, - 0x6e, 0x12, 0x31, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, - 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x61, - 0x70, 0x70, 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x22, 0xd1, 0x01, 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, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70, 0x6c, 0x61, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x61, 0x70, - 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 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, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x53, 0x68, - 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, - 0x4e, 0x45, 0x52, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, - 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, - 0x49, 0x43, 0x10, 0x02, 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, 0x49, 0x0a, - 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x07, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, - 0x65, 0x72, 0x2f, 0x76, 0x32, 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, + 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, + 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x06, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x05, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2c, + 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x2e, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x69, 0x6d, 0x69, + 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x0f, + 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, + 0x8c, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x31, 0x0a, 0x05, 0x70, 0x61, + 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2e, 0x0a, + 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x31, 0x0a, + 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x12, 0x34, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x06, + 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xd1, + 0x01, 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, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, + 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, + 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, + 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 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, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, + 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, + 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, + 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x02, + 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, 0x2a, 0x35, 0x0a, 0x0b, 0x54, 0x69, 0x6d, + 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x52, + 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, + 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, + 0x32, 0x49, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, + 0x3a, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x30, 0x5a, 0x2e, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 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 ( @@ -3114,88 +3302,96 @@ func file_provisionersdk_proto_provisioner_proto_rawDescGZIP() []byte { return file_provisionersdk_proto_provisioner_proto_rawDescData } -var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 32) +var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 33) var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{ (LogLevel)(0), // 0: provisioner.LogLevel (AppSharingLevel)(0), // 1: provisioner.AppSharingLevel (WorkspaceTransition)(0), // 2: provisioner.WorkspaceTransition - (*Empty)(nil), // 3: provisioner.Empty - (*TemplateVariable)(nil), // 4: provisioner.TemplateVariable - (*RichParameterOption)(nil), // 5: provisioner.RichParameterOption - (*RichParameter)(nil), // 6: provisioner.RichParameter - (*RichParameterValue)(nil), // 7: provisioner.RichParameterValue - (*VariableValue)(nil), // 8: provisioner.VariableValue - (*Log)(nil), // 9: provisioner.Log - (*InstanceIdentityAuth)(nil), // 10: provisioner.InstanceIdentityAuth - (*ExternalAuthProviderResource)(nil), // 11: provisioner.ExternalAuthProviderResource - (*ExternalAuthProvider)(nil), // 12: provisioner.ExternalAuthProvider - (*Agent)(nil), // 13: provisioner.Agent - (*DisplayApps)(nil), // 14: provisioner.DisplayApps - (*Env)(nil), // 15: provisioner.Env - (*Script)(nil), // 16: provisioner.Script - (*App)(nil), // 17: provisioner.App - (*Healthcheck)(nil), // 18: provisioner.Healthcheck - (*Resource)(nil), // 19: provisioner.Resource - (*Metadata)(nil), // 20: provisioner.Metadata - (*Config)(nil), // 21: provisioner.Config - (*ParseRequest)(nil), // 22: provisioner.ParseRequest - (*ParseComplete)(nil), // 23: provisioner.ParseComplete - (*PlanRequest)(nil), // 24: provisioner.PlanRequest - (*PlanComplete)(nil), // 25: provisioner.PlanComplete - (*ApplyRequest)(nil), // 26: provisioner.ApplyRequest - (*ApplyComplete)(nil), // 27: provisioner.ApplyComplete - (*CancelRequest)(nil), // 28: provisioner.CancelRequest - (*Request)(nil), // 29: provisioner.Request - (*Response)(nil), // 30: provisioner.Response - (*Agent_Metadata)(nil), // 31: provisioner.Agent.Metadata - nil, // 32: provisioner.Agent.EnvEntry - (*Resource_Metadata)(nil), // 33: provisioner.Resource.Metadata - nil, // 34: provisioner.ParseComplete.WorkspaceTagsEntry + (TimingState)(0), // 3: provisioner.TimingState + (*Empty)(nil), // 4: provisioner.Empty + (*TemplateVariable)(nil), // 5: provisioner.TemplateVariable + (*RichParameterOption)(nil), // 6: provisioner.RichParameterOption + (*RichParameter)(nil), // 7: provisioner.RichParameter + (*RichParameterValue)(nil), // 8: provisioner.RichParameterValue + (*VariableValue)(nil), // 9: provisioner.VariableValue + (*Log)(nil), // 10: provisioner.Log + (*InstanceIdentityAuth)(nil), // 11: provisioner.InstanceIdentityAuth + (*ExternalAuthProviderResource)(nil), // 12: provisioner.ExternalAuthProviderResource + (*ExternalAuthProvider)(nil), // 13: provisioner.ExternalAuthProvider + (*Agent)(nil), // 14: provisioner.Agent + (*DisplayApps)(nil), // 15: provisioner.DisplayApps + (*Env)(nil), // 16: provisioner.Env + (*Script)(nil), // 17: provisioner.Script + (*App)(nil), // 18: provisioner.App + (*Healthcheck)(nil), // 19: provisioner.Healthcheck + (*Resource)(nil), // 20: provisioner.Resource + (*Metadata)(nil), // 21: provisioner.Metadata + (*Config)(nil), // 22: provisioner.Config + (*ParseRequest)(nil), // 23: provisioner.ParseRequest + (*ParseComplete)(nil), // 24: provisioner.ParseComplete + (*PlanRequest)(nil), // 25: provisioner.PlanRequest + (*PlanComplete)(nil), // 26: provisioner.PlanComplete + (*ApplyRequest)(nil), // 27: provisioner.ApplyRequest + (*ApplyComplete)(nil), // 28: provisioner.ApplyComplete + (*Timing)(nil), // 29: provisioner.Timing + (*CancelRequest)(nil), // 30: provisioner.CancelRequest + (*Request)(nil), // 31: provisioner.Request + (*Response)(nil), // 32: provisioner.Response + (*Agent_Metadata)(nil), // 33: provisioner.Agent.Metadata + nil, // 34: provisioner.Agent.EnvEntry + (*Resource_Metadata)(nil), // 35: provisioner.Resource.Metadata + nil, // 36: provisioner.ParseComplete.WorkspaceTagsEntry + (*timestamppb.Timestamp)(nil), // 37: google.protobuf.Timestamp } var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{ - 5, // 0: provisioner.RichParameter.options:type_name -> provisioner.RichParameterOption + 6, // 0: provisioner.RichParameter.options:type_name -> provisioner.RichParameterOption 0, // 1: provisioner.Log.level:type_name -> provisioner.LogLevel - 32, // 2: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry - 17, // 3: provisioner.Agent.apps:type_name -> provisioner.App - 31, // 4: provisioner.Agent.metadata:type_name -> provisioner.Agent.Metadata - 14, // 5: provisioner.Agent.display_apps:type_name -> provisioner.DisplayApps - 16, // 6: provisioner.Agent.scripts:type_name -> provisioner.Script - 15, // 7: provisioner.Agent.extra_envs:type_name -> provisioner.Env - 18, // 8: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck + 34, // 2: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry + 18, // 3: provisioner.Agent.apps:type_name -> provisioner.App + 33, // 4: provisioner.Agent.metadata:type_name -> provisioner.Agent.Metadata + 15, // 5: provisioner.Agent.display_apps:type_name -> provisioner.DisplayApps + 17, // 6: provisioner.Agent.scripts:type_name -> provisioner.Script + 16, // 7: provisioner.Agent.extra_envs:type_name -> provisioner.Env + 19, // 8: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck 1, // 9: provisioner.App.sharing_level:type_name -> provisioner.AppSharingLevel - 13, // 10: provisioner.Resource.agents:type_name -> provisioner.Agent - 33, // 11: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata + 14, // 10: provisioner.Resource.agents:type_name -> provisioner.Agent + 35, // 11: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata 2, // 12: provisioner.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition - 4, // 13: provisioner.ParseComplete.template_variables:type_name -> provisioner.TemplateVariable - 34, // 14: provisioner.ParseComplete.workspace_tags:type_name -> provisioner.ParseComplete.WorkspaceTagsEntry - 20, // 15: provisioner.PlanRequest.metadata:type_name -> provisioner.Metadata - 7, // 16: provisioner.PlanRequest.rich_parameter_values:type_name -> provisioner.RichParameterValue - 8, // 17: provisioner.PlanRequest.variable_values:type_name -> provisioner.VariableValue - 12, // 18: provisioner.PlanRequest.external_auth_providers:type_name -> provisioner.ExternalAuthProvider - 19, // 19: provisioner.PlanComplete.resources:type_name -> provisioner.Resource - 6, // 20: provisioner.PlanComplete.parameters:type_name -> provisioner.RichParameter - 11, // 21: provisioner.PlanComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource - 20, // 22: provisioner.ApplyRequest.metadata:type_name -> provisioner.Metadata - 19, // 23: provisioner.ApplyComplete.resources:type_name -> provisioner.Resource - 6, // 24: provisioner.ApplyComplete.parameters:type_name -> provisioner.RichParameter - 11, // 25: provisioner.ApplyComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource - 21, // 26: provisioner.Request.config:type_name -> provisioner.Config - 22, // 27: provisioner.Request.parse:type_name -> provisioner.ParseRequest - 24, // 28: provisioner.Request.plan:type_name -> provisioner.PlanRequest - 26, // 29: provisioner.Request.apply:type_name -> provisioner.ApplyRequest - 28, // 30: provisioner.Request.cancel:type_name -> provisioner.CancelRequest - 9, // 31: provisioner.Response.log:type_name -> provisioner.Log - 23, // 32: provisioner.Response.parse:type_name -> provisioner.ParseComplete - 25, // 33: provisioner.Response.plan:type_name -> provisioner.PlanComplete - 27, // 34: provisioner.Response.apply:type_name -> provisioner.ApplyComplete - 29, // 35: provisioner.Provisioner.Session:input_type -> provisioner.Request - 30, // 36: provisioner.Provisioner.Session:output_type -> provisioner.Response - 36, // [36:37] is the sub-list for method output_type - 35, // [35:36] is the sub-list for method input_type - 35, // [35:35] is the sub-list for extension type_name - 35, // [35:35] is the sub-list for extension extendee - 0, // [0:35] is the sub-list for field type_name + 5, // 13: provisioner.ParseComplete.template_variables:type_name -> provisioner.TemplateVariable + 36, // 14: provisioner.ParseComplete.workspace_tags:type_name -> provisioner.ParseComplete.WorkspaceTagsEntry + 21, // 15: provisioner.PlanRequest.metadata:type_name -> provisioner.Metadata + 8, // 16: provisioner.PlanRequest.rich_parameter_values:type_name -> provisioner.RichParameterValue + 9, // 17: provisioner.PlanRequest.variable_values:type_name -> provisioner.VariableValue + 13, // 18: provisioner.PlanRequest.external_auth_providers:type_name -> provisioner.ExternalAuthProvider + 20, // 19: provisioner.PlanComplete.resources:type_name -> provisioner.Resource + 7, // 20: provisioner.PlanComplete.parameters:type_name -> provisioner.RichParameter + 12, // 21: provisioner.PlanComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource + 29, // 22: provisioner.PlanComplete.timings:type_name -> provisioner.Timing + 21, // 23: provisioner.ApplyRequest.metadata:type_name -> provisioner.Metadata + 20, // 24: provisioner.ApplyComplete.resources:type_name -> provisioner.Resource + 7, // 25: provisioner.ApplyComplete.parameters:type_name -> provisioner.RichParameter + 12, // 26: provisioner.ApplyComplete.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource + 29, // 27: provisioner.ApplyComplete.timings:type_name -> provisioner.Timing + 37, // 28: provisioner.Timing.start:type_name -> google.protobuf.Timestamp + 37, // 29: provisioner.Timing.end:type_name -> google.protobuf.Timestamp + 3, // 30: provisioner.Timing.state:type_name -> provisioner.TimingState + 22, // 31: provisioner.Request.config:type_name -> provisioner.Config + 23, // 32: provisioner.Request.parse:type_name -> provisioner.ParseRequest + 25, // 33: provisioner.Request.plan:type_name -> provisioner.PlanRequest + 27, // 34: provisioner.Request.apply:type_name -> provisioner.ApplyRequest + 30, // 35: provisioner.Request.cancel:type_name -> provisioner.CancelRequest + 10, // 36: provisioner.Response.log:type_name -> provisioner.Log + 24, // 37: provisioner.Response.parse:type_name -> provisioner.ParseComplete + 26, // 38: provisioner.Response.plan:type_name -> provisioner.PlanComplete + 28, // 39: provisioner.Response.apply:type_name -> provisioner.ApplyComplete + 31, // 40: provisioner.Provisioner.Session:input_type -> provisioner.Request + 32, // 41: provisioner.Provisioner.Session:output_type -> provisioner.Response + 41, // [41:42] is the sub-list for method output_type + 40, // [40:41] is the sub-list for method input_type + 40, // [40:40] is the sub-list for extension type_name + 40, // [40:40] is the sub-list for extension extendee + 0, // [0:40] is the sub-list for field type_name } func init() { file_provisionersdk_proto_provisioner_proto_init() } @@ -3505,7 +3701,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CancelRequest); i { + switch v := v.(*Timing); i { case 0: return &v.state case 1: @@ -3517,7 +3713,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Request); i { + switch v := v.(*CancelRequest); i { case 0: return &v.state case 1: @@ -3529,7 +3725,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Response); i { + switch v := v.(*Request); i { case 0: return &v.state case 1: @@ -3541,6 +3737,18 @@ func file_provisionersdk_proto_provisioner_proto_init() { } } file_provisionersdk_proto_provisioner_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Response); 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[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Agent_Metadata); i { case 0: return &v.state @@ -3552,7 +3760,7 @@ func file_provisionersdk_proto_provisioner_proto_init() { return nil } } - file_provisionersdk_proto_provisioner_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_provisionersdk_proto_provisioner_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Resource_Metadata); i { case 0: return &v.state @@ -3570,14 +3778,14 @@ func file_provisionersdk_proto_provisioner_proto_init() { (*Agent_Token)(nil), (*Agent_InstanceId)(nil), } - file_provisionersdk_proto_provisioner_proto_msgTypes[26].OneofWrappers = []interface{}{ + file_provisionersdk_proto_provisioner_proto_msgTypes[27].OneofWrappers = []interface{}{ (*Request_Config)(nil), (*Request_Parse)(nil), (*Request_Plan)(nil), (*Request_Apply)(nil), (*Request_Cancel)(nil), } - file_provisionersdk_proto_provisioner_proto_msgTypes[27].OneofWrappers = []interface{}{ + file_provisionersdk_proto_provisioner_proto_msgTypes[28].OneofWrappers = []interface{}{ (*Response_Log)(nil), (*Response_Parse)(nil), (*Response_Plan)(nil), @@ -3588,8 +3796,8 @@ func file_provisionersdk_proto_provisioner_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_provisionersdk_proto_provisioner_proto_rawDesc, - NumEnums: 3, - NumMessages: 32, + NumEnums: 4, + NumMessages: 33, NumExtensions: 0, NumServices: 1, }, diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index 71d8bd12e8d1e..9cfba2896b18d 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -2,6 +2,8 @@ syntax = "proto3"; option go_package = "github.com/coder/coder/v2/provisionersdk/proto"; +import "google/protobuf/timestamp.proto"; + package provisioner; // Empty indicates a successful request/response. @@ -266,6 +268,7 @@ message PlanComplete { repeated Resource resources = 2; repeated RichParameter parameters = 3; repeated ExternalAuthProviderResource external_auth_providers = 4; + repeated Timing timings = 6; } // ApplyRequest asks the provisioner to apply the changes. Apply MUST be preceded by a successful plan request/response @@ -281,6 +284,23 @@ message ApplyComplete { repeated Resource resources = 3; repeated RichParameter parameters = 4; repeated ExternalAuthProviderResource external_auth_providers = 5; + repeated Timing timings = 6; +} + +message Timing { + google.protobuf.Timestamp start = 1; + google.protobuf.Timestamp end = 2; + string action = 3; + string source = 4; + string resource = 5; + string stage = 6; + TimingState state = 7; +} + +enum TimingState { + STARTED = 0; + COMPLETED = 1; + FAILED = 2; } // CancelRequest requests that the previous request be canceled gracefully. diff --git a/site/e2e/google/protobuf/timestampGenerated.ts b/site/e2e/google/protobuf/timestampGenerated.ts new file mode 100644 index 0000000000000..6dd4b08e96087 --- /dev/null +++ b/site/e2e/google/protobuf/timestampGenerated.ts @@ -0,0 +1,123 @@ +/* eslint-disable */ +import * as _m0 from "protobufjs/minimal"; + +export const protobufPackage = "google.protobuf"; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * Example 6: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard + * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using + * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + * the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime() + * ) to obtain a formatter capable of generating timestamps in this format. + */ +export interface Timestamp { + /** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + */ + seconds: number; + /** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + */ + nanos: number; +} + +export const Timestamp = { + encode(message: Timestamp, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.seconds !== 0) { + writer.uint32(8).int64(message.seconds); + } + if (message.nanos !== 0) { + writer.uint32(16).int32(message.nanos); + } + return writer; + }, +}; diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 18ec3dd036dc2..15ba7788b1cfe 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -481,6 +481,7 @@ const createTemplateVersionTar = async ( resources: response.apply?.resources ?? [], parameters: response.apply?.parameters ?? [], externalAuthProviders: response.apply?.externalAuthProviders ?? [], + timings: response.apply?.timings ?? [], }, }; }); @@ -582,6 +583,7 @@ const createTemplateVersionTar = async ( resources: [], parameters: [], externalAuthProviders: [], + timings: [], ...response.apply, } as ApplyComplete; response.apply.resources = response.apply.resources?.map(fillResource); @@ -597,6 +599,7 @@ const createTemplateVersionTar = async ( resources: [], parameters: [], externalAuthProviders: [], + timings: [], ...response.plan, } as PlanComplete; response.plan.resources = response.plan.resources?.map(fillResource); diff --git a/site/e2e/provisionerGenerated.ts b/site/e2e/provisionerGenerated.ts index 9168d4b69bb3b..acea867faaae9 100644 --- a/site/e2e/provisionerGenerated.ts +++ b/site/e2e/provisionerGenerated.ts @@ -1,6 +1,7 @@ /* eslint-disable */ import * as _m0 from "protobufjs/minimal"; import { Observable } from "rxjs"; +import { Timestamp } from "./google/protobuf/timestampGenerated"; export const protobufPackage = "provisioner"; @@ -29,6 +30,13 @@ export enum WorkspaceTransition { UNRECOGNIZED = -1, } +export enum TimingState { + STARTED = 0, + COMPLETED = 1, + FAILED = 2, + UNRECOGNIZED = -1, +} + /** Empty indicates a successful request/response. */ export interface Empty {} @@ -275,6 +283,7 @@ export interface PlanComplete { resources: Resource[]; parameters: RichParameter[]; externalAuthProviders: ExternalAuthProviderResource[]; + timings: Timing[]; } /** @@ -292,6 +301,17 @@ export interface ApplyComplete { resources: Resource[]; parameters: RichParameter[]; externalAuthProviders: ExternalAuthProviderResource[]; + timings: Timing[]; +} + +export interface Timing { + start: Date | undefined; + end: Date | undefined; + action: string; + source: string; + resource: string; + stage: string; + state: TimingState; } /** CancelRequest requests that the previous request be canceled gracefully. */ @@ -965,6 +985,9 @@ export const PlanComplete = { writer.uint32(34).fork(), ).ldelim(); } + for (const v of message.timings) { + Timing.encode(v!, writer.uint32(50).fork()).ldelim(); + } return writer; }, }; @@ -1004,6 +1027,45 @@ export const ApplyComplete = { writer.uint32(42).fork(), ).ldelim(); } + for (const v of message.timings) { + Timing.encode(v!, writer.uint32(50).fork()).ldelim(); + } + return writer; + }, +}; + +export const Timing = { + encode( + message: Timing, + writer: _m0.Writer = _m0.Writer.create(), + ): _m0.Writer { + if (message.start !== undefined) { + Timestamp.encode( + toTimestamp(message.start), + writer.uint32(10).fork(), + ).ldelim(); + } + if (message.end !== undefined) { + Timestamp.encode( + toTimestamp(message.end), + writer.uint32(18).fork(), + ).ldelim(); + } + if (message.action !== "") { + writer.uint32(26).string(message.action); + } + if (message.source !== "") { + writer.uint32(34).string(message.source); + } + if (message.resource !== "") { + writer.uint32(42).string(message.resource); + } + if (message.stage !== "") { + writer.uint32(50).string(message.stage); + } + if (message.state !== 0) { + writer.uint32(56).int32(message.state); + } return writer; }, }; @@ -1077,3 +1139,9 @@ export interface Provisioner { */ Session(request: Observable): Observable; } + +function toTimestamp(date: Date): Timestamp { + const seconds = date.getTime() / 1_000; + const nanos = (date.getTime() % 1_000) * 1_000_000; + return { seconds, nanos }; +}