feat: add support for optional external auth providers (#12021)

This commit is contained in:
Kayla Washburn-Love 2024-02-21 11:18:38 -07:00 committed by GitHub
parent 78c9f82719
commit 475c3650ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 1495 additions and 727 deletions

2
.gitattributes vendored
View File

@ -6,10 +6,12 @@ coderd/apidoc/swagger.json linguist-generated=true
coderd/database/dump.sql linguist-generated=true coderd/database/dump.sql linguist-generated=true
peerbroker/proto/*.go linguist-generated=true peerbroker/proto/*.go linguist-generated=true
provisionerd/proto/*.go linguist-generated=true provisionerd/proto/*.go linguist-generated=true
provisionerd/proto/version.go linguist-generated=false
provisionersdk/proto/*.go linguist-generated=true provisionersdk/proto/*.go linguist-generated=true
*.tfplan.json linguist-generated=true *.tfplan.json linguist-generated=true
*.tfstate.json linguist-generated=true *.tfstate.json linguist-generated=true
*.tfstate.dot linguist-generated=true *.tfstate.dot linguist-generated=true
*.tfplan.dot linguist-generated=true *.tfplan.dot linguist-generated=true
site/e2e/provisionerGenerated.ts linguist-generated=true
site/src/api/typesGenerated.ts linguist-generated=true site/src/api/typesGenerated.ts linguist-generated=true
site/src/pages/SetupPage/countries.tsx linguist-generated=true site/src/pages/SetupPage/countries.tsx linguist-generated=true

View File

@ -803,7 +803,7 @@ func TestCreateWithGitAuth(t *testing.T) {
{ {
Type: &proto.Response_Plan{ Type: &proto.Response_Plan{
Plan: &proto.PlanComplete{ Plan: &proto.PlanComplete{
ExternalAuthProviders: []string{"github"}, ExternalAuthProviders: []*proto.ExternalAuthProviderResource{{Id: "github"}},
}, },
}, },
}, },

3
coderd/apidoc/docs.go generated
View File

@ -11828,6 +11828,9 @@ const docTemplate = `{
"id": { "id": {
"type": "string" "type": "string"
}, },
"optional": {
"type": "boolean"
},
"type": { "type": {
"type": "string" "type": "string"
} }

View File

@ -10709,6 +10709,9 @@
"id": { "id": {
"type": "string" "type": "string"
}, },
"optional": {
"type": "boolean"
},
"type": { "type": {
"type": "string" "type": "string"
} }

View File

@ -1247,7 +1247,7 @@ func (api *API) CreateInMemoryProvisionerDaemon(dialCtx context.Context, name st
Tags: provisionersdk.MutateTags(uuid.Nil, nil), Tags: provisionersdk.MutateTags(uuid.Nil, nil),
LastSeenAt: sql.NullTime{Time: dbtime.Now(), Valid: true}, LastSeenAt: sql.NullTime{Time: dbtime.Now(), Valid: true},
Version: buildinfo.Version(), Version: buildinfo.Version(),
APIVersion: proto.VersionCurrent.String(), APIVersion: proto.CurrentVersion.String(),
}) })
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to create in-memory provisioner daemon: %w", err) return nil, xerrors.Errorf("failed to create in-memory provisioner daemon: %w", err)

View File

@ -928,8 +928,7 @@ func (s *MethodTestSuite) TestTemplate() {
JobID: jobID, JobID: jobID,
}) })
check.Args(database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams{ check.Args(database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams{
JobID: jobID, JobID: jobID,
ExternalAuthProviders: []string{},
}).Asserts(t1, rbac.ActionUpdate).Returns() }).Asserts(t1, rbac.ActionUpdate).Returns()
})) }))
s.Run("GetTemplateInsights", s.Subtest(func(db database.Store, check *expects) { s.Run("GetTemplateInsights", s.Subtest(func(db database.Store, check *expects) {

View File

@ -219,7 +219,7 @@ func TestDeleteOldProvisionerDaemons(t *testing.T) {
CreatedAt: now.Add(-14 * 24 * time.Hour), CreatedAt: now.Add(-14 * 24 * time.Hour),
LastSeenAt: sql.NullTime{Valid: true, Time: now.Add(-7 * 24 * time.Hour).Add(time.Minute)}, LastSeenAt: sql.NullTime{Valid: true, Time: now.Add(-7 * 24 * time.Hour).Add(time.Minute)},
Version: "1.0.0", Version: "1.0.0",
APIVersion: proto.VersionCurrent.String(), APIVersion: proto.CurrentVersion.String(),
}) })
require.NoError(t, err) require.NoError(t, err)
_, err = db.UpsertProvisionerDaemon(ctx, database.UpsertProvisionerDaemonParams{ _, err = db.UpsertProvisionerDaemon(ctx, database.UpsertProvisionerDaemonParams{
@ -230,7 +230,7 @@ func TestDeleteOldProvisionerDaemons(t *testing.T) {
CreatedAt: now.Add(-8 * 24 * time.Hour), CreatedAt: now.Add(-8 * 24 * time.Hour),
LastSeenAt: sql.NullTime{Valid: true, Time: now.Add(-8 * 24 * time.Hour).Add(time.Hour)}, LastSeenAt: sql.NullTime{Valid: true, Time: now.Add(-8 * 24 * time.Hour).Add(time.Hour)},
Version: "1.0.0", Version: "1.0.0",
APIVersion: proto.VersionCurrent.String(), APIVersion: proto.CurrentVersion.String(),
}) })
require.NoError(t, err) require.NoError(t, err)
_, err = db.UpsertProvisionerDaemon(ctx, database.UpsertProvisionerDaemonParams{ _, err = db.UpsertProvisionerDaemon(ctx, database.UpsertProvisionerDaemonParams{
@ -243,7 +243,7 @@ func TestDeleteOldProvisionerDaemons(t *testing.T) {
}, },
CreatedAt: now.Add(-9 * 24 * time.Hour), CreatedAt: now.Add(-9 * 24 * time.Hour),
Version: "1.0.0", Version: "1.0.0",
APIVersion: proto.VersionCurrent.String(), APIVersion: proto.CurrentVersion.String(),
}) })
require.NoError(t, err) require.NoError(t, err)
_, err = db.UpsertProvisionerDaemon(ctx, database.UpsertProvisionerDaemonParams{ _, err = db.UpsertProvisionerDaemon(ctx, database.UpsertProvisionerDaemonParams{
@ -257,7 +257,7 @@ func TestDeleteOldProvisionerDaemons(t *testing.T) {
CreatedAt: now.Add(-6 * 24 * time.Hour), CreatedAt: now.Add(-6 * 24 * time.Hour),
LastSeenAt: sql.NullTime{Valid: true, Time: now.Add(-6 * 24 * time.Hour)}, LastSeenAt: sql.NullTime{Valid: true, Time: now.Add(-6 * 24 * time.Hour)},
Version: "1.0.0", Version: "1.0.0",
APIVersion: proto.VersionCurrent.String(), APIVersion: proto.CurrentVersion.String(),
}) })
require.NoError(t, err) require.NoError(t, err)

View File

@ -821,7 +821,7 @@ CREATE TABLE template_versions (
readme character varying(1048576) NOT NULL, readme character varying(1048576) NOT NULL,
job_id uuid NOT NULL, job_id uuid NOT NULL,
created_by uuid NOT NULL, created_by uuid NOT NULL,
external_auth_providers text[], external_auth_providers jsonb DEFAULT '[]'::jsonb NOT NULL,
message character varying(1048576) DEFAULT ''::character varying NOT NULL, message character varying(1048576) DEFAULT ''::character varying NOT NULL,
archived boolean DEFAULT false NOT NULL archived boolean DEFAULT false NOT NULL
); );

View File

@ -0,0 +1,61 @@
-- We cannot alter the column type while a view depends on it, so we drop it and recreate it.
DROP VIEW template_version_with_user;
-- Does the opposite of `migrate_external_auth_providers_to_jsonb`
-- eg. `'[{"id": "github"}, {"id": "gitlab"}]'::jsonb` would become `'{github,gitlab}'::text[]`
CREATE OR REPLACE FUNCTION revert_migrate_external_auth_providers_to_jsonb(jsonb)
RETURNS text[]
LANGUAGE plpgsql
AS $$
DECLARE
result text[];
BEGIN
SELECT
array_agg(id::text) INTO result
FROM (
SELECT
jsonb_array_elements($1) ->> 'id' AS id) AS external_auth_provider_ids;
RETURN result;
END;
$$;
-- Remove the non-null constraint and default
ALTER TABLE template_versions
ALTER COLUMN external_auth_providers DROP DEFAULT;
ALTER TABLE template_versions
ALTER COLUMN external_auth_providers DROP NOT NULL;
-- Update the column type and migrate the values
ALTER TABLE template_versions
ALTER COLUMN external_auth_providers TYPE text[]
USING revert_migrate_external_auth_providers_to_jsonb(external_auth_providers);
-- Recreate `template_version_with_user` as described in dump.sql
CREATE VIEW template_version_with_user AS
SELECT
template_versions.id,
template_versions.template_id,
template_versions.organization_id,
template_versions.created_at,
template_versions.updated_at,
template_versions.name,
template_versions.readme,
template_versions.job_id,
template_versions.created_by,
template_versions.external_auth_providers,
template_versions.message,
template_versions.archived,
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS created_by_username
FROM (public.template_versions
LEFT JOIN visible_users ON (template_versions.created_by = visible_users.id));
COMMENT ON VIEW template_version_with_user IS 'Joins in the username + avatar url of the created by user.';
-- Cleanup
DROP FUNCTION revert_migrate_external_auth_providers_to_jsonb;

View File

@ -0,0 +1,63 @@
-- We cannot alter the column type while a view depends on it, so we drop it and recreate it.
DROP VIEW template_version_with_user;
-- Turns the list of provider names into JSONB with the type `Array<{ id: string; optional?: boolean }>`
-- eg. `'{github,gitlab}'::text[]` would become `'[{"id": "github"}, {"id": "gitlab"}]'::jsonb`
CREATE OR REPLACE FUNCTION migrate_external_auth_providers_to_jsonb(text[])
RETURNS jsonb
LANGUAGE plpgsql
AS $$
DECLARE
result jsonb;
BEGIN
SELECT
jsonb_agg(jsonb_build_object('id', value::text)) INTO result
FROM
unnest($1) AS value;
RETURN result;
END;
$$;
-- Update the column type and migrate the values
ALTER TABLE template_versions
ALTER COLUMN external_auth_providers TYPE jsonb
USING migrate_external_auth_providers_to_jsonb(external_auth_providers);
-- Make the column non-nullable to make the types nicer on the Go side
UPDATE template_versions
SET external_auth_providers = '[]'::jsonb
WHERE external_auth_providers IS NULL;
ALTER TABLE template_versions
ALTER COLUMN external_auth_providers SET DEFAULT '[]'::jsonb;
ALTER TABLE template_versions
ALTER COLUMN external_auth_providers SET NOT NULL;
-- Recreate `template_version_with_user` as described in dump.sql
CREATE VIEW template_version_with_user AS
SELECT
template_versions.id,
template_versions.template_id,
template_versions.organization_id,
template_versions.created_at,
template_versions.updated_at,
template_versions.name,
template_versions.readme,
template_versions.job_id,
template_versions.created_by,
template_versions.external_auth_providers,
template_versions.message,
template_versions.archived,
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS created_by_username
FROM (public.template_versions
LEFT JOIN visible_users ON (template_versions.created_by = visible_users.id));
COMMENT ON VIEW template_version_with_user IS 'Joins in the username + avatar url of the created by user.';
-- Cleanup
DROP FUNCTION migrate_external_auth_providers_to_jsonb;

View File

@ -2080,20 +2080,20 @@ type TemplateTable struct {
// Joins in the username + avatar url of the created by user. // Joins in the username + avatar url of the created by user.
type TemplateVersion struct { type TemplateVersion struct {
ID uuid.UUID `db:"id" json:"id"` ID uuid.UUID `db:"id" json:"id"`
TemplateID uuid.NullUUID `db:"template_id" json:"template_id"` TemplateID uuid.NullUUID `db:"template_id" json:"template_id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
CreatedAt time.Time `db:"created_at" json:"created_at"` CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
Readme string `db:"readme" json:"readme"` Readme string `db:"readme" json:"readme"`
JobID uuid.UUID `db:"job_id" json:"job_id"` JobID uuid.UUID `db:"job_id" json:"job_id"`
CreatedBy uuid.UUID `db:"created_by" json:"created_by"` CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
ExternalAuthProviders []string `db:"external_auth_providers" json:"external_auth_providers"` ExternalAuthProviders json.RawMessage `db:"external_auth_providers" json:"external_auth_providers"`
Message string `db:"message" json:"message"` Message string `db:"message" json:"message"`
Archived bool `db:"archived" json:"archived"` Archived bool `db:"archived" json:"archived"`
CreatedByAvatarURL string `db:"created_by_avatar_url" json:"created_by_avatar_url"` CreatedByAvatarURL string `db:"created_by_avatar_url" json:"created_by_avatar_url"`
CreatedByUsername string `db:"created_by_username" json:"created_by_username"` CreatedByUsername string `db:"created_by_username" json:"created_by_username"`
} }
type TemplateVersionParameter struct { type TemplateVersionParameter struct {
@ -2143,7 +2143,7 @@ type TemplateVersionTable struct {
JobID uuid.UUID `db:"job_id" json:"job_id"` JobID uuid.UUID `db:"job_id" json:"job_id"`
CreatedBy uuid.UUID `db:"created_by" json:"created_by"` CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
// IDs of External auth providers for a specific template version // IDs of External auth providers for a specific template version
ExternalAuthProviders []string `db:"external_auth_providers" json:"external_auth_providers"` ExternalAuthProviders json.RawMessage `db:"external_auth_providers" json:"external_auth_providers"`
// Message describing the changes in this version of the template, similar to a Git commit message. Like a commit message, this should be a short, high-level description of the changes in this version of the template. This message is immutable and should not be updated after the fact. // Message describing the changes in this version of the template, similar to a Git commit message. Like a commit message, this should be a short, high-level description of the changes in this version of the template. This message is immutable and should not be updated after the fact.
Message string `db:"message" json:"message"` Message string `db:"message" json:"message"`
Archived bool `db:"archived" json:"archived"` Archived bool `db:"archived" json:"archived"`

View File

@ -6870,7 +6870,7 @@ func (q *sqlQuerier) GetPreviousTemplateVersion(ctx context.Context, arg GetPrev
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy, &i.CreatedBy,
pq.Array(&i.ExternalAuthProviders), &i.ExternalAuthProviders,
&i.Message, &i.Message,
&i.Archived, &i.Archived,
&i.CreatedByAvatarURL, &i.CreatedByAvatarURL,
@ -6901,7 +6901,7 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy, &i.CreatedBy,
pq.Array(&i.ExternalAuthProviders), &i.ExternalAuthProviders,
&i.Message, &i.Message,
&i.Archived, &i.Archived,
&i.CreatedByAvatarURL, &i.CreatedByAvatarURL,
@ -6932,7 +6932,7 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy, &i.CreatedBy,
pq.Array(&i.ExternalAuthProviders), &i.ExternalAuthProviders,
&i.Message, &i.Message,
&i.Archived, &i.Archived,
&i.CreatedByAvatarURL, &i.CreatedByAvatarURL,
@ -6969,7 +6969,7 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context,
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy, &i.CreatedBy,
pq.Array(&i.ExternalAuthProviders), &i.ExternalAuthProviders,
&i.Message, &i.Message,
&i.Archived, &i.Archived,
&i.CreatedByAvatarURL, &i.CreatedByAvatarURL,
@ -7006,7 +7006,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy, &i.CreatedBy,
pq.Array(&i.ExternalAuthProviders), &i.ExternalAuthProviders,
&i.Message, &i.Message,
&i.Archived, &i.Archived,
&i.CreatedByAvatarURL, &i.CreatedByAvatarURL,
@ -7100,7 +7100,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy, &i.CreatedBy,
pq.Array(&i.ExternalAuthProviders), &i.ExternalAuthProviders,
&i.Message, &i.Message,
&i.Archived, &i.Archived,
&i.CreatedByAvatarURL, &i.CreatedByAvatarURL,
@ -7142,7 +7142,7 @@ func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, create
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy, &i.CreatedBy,
pq.Array(&i.ExternalAuthProviders), &i.ExternalAuthProviders,
&i.Message, &i.Message,
&i.Archived, &i.Archived,
&i.CreatedByAvatarURL, &i.CreatedByAvatarURL,
@ -7292,13 +7292,13 @@ WHERE
` `
type UpdateTemplateVersionExternalAuthProvidersByJobIDParams struct { type UpdateTemplateVersionExternalAuthProvidersByJobIDParams struct {
JobID uuid.UUID `db:"job_id" json:"job_id"` JobID uuid.UUID `db:"job_id" json:"job_id"`
ExternalAuthProviders []string `db:"external_auth_providers" json:"external_auth_providers"` ExternalAuthProviders json.RawMessage `db:"external_auth_providers" json:"external_auth_providers"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
} }
func (q *sqlQuerier) UpdateTemplateVersionExternalAuthProvidersByJobID(ctx context.Context, arg UpdateTemplateVersionExternalAuthProvidersByJobIDParams) error { func (q *sqlQuerier) UpdateTemplateVersionExternalAuthProvidersByJobID(ctx context.Context, arg UpdateTemplateVersionExternalAuthProvidersByJobIDParams) error {
_, err := q.db.ExecContext(ctx, updateTemplateVersionExternalAuthProvidersByJobID, arg.JobID, pq.Array(arg.ExternalAuthProviders), arg.UpdatedAt) _, err := q.db.ExecContext(ctx, updateTemplateVersionExternalAuthProvidersByJobID, arg.JobID, arg.ExternalAuthProviders, arg.UpdatedAt)
return err return err
} }

View File

@ -64,6 +64,11 @@ func (t TemplateACL) Value() (driver.Value, error) {
return json.Marshal(t) return json.Marshal(t)
} }
type ExternalAuthProvider struct {
ID string `json:"id"`
Optional bool `json:"optional,omitempty"`
}
type StringMap map[string]string type StringMap map[string]string
func (m *StringMap) Scan(src interface{}) error { func (m *StringMap) Scan(src interface{}) error {

View File

@ -501,10 +501,16 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
return nil, failJob(fmt.Sprintf("get workspace build parameters: %s", err)) return nil, failJob(fmt.Sprintf("get workspace build parameters: %s", err))
} }
externalAuthProviders := []*sdkproto.ExternalAuthProvider{} dbExternalAuthProviders := []database.ExternalAuthProvider{}
for _, p := range templateVersion.ExternalAuthProviders { err = json.Unmarshal(templateVersion.ExternalAuthProviders, &dbExternalAuthProviders)
if err != nil {
return nil, xerrors.Errorf("failed to deserialize external_auth_providers value: %w", err)
}
externalAuthProviders := make([]*sdkproto.ExternalAuthProvider, 0, len(dbExternalAuthProviders))
for _, p := range dbExternalAuthProviders {
link, err := s.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ link, err := s.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{
ProviderID: p, ProviderID: p.ID,
UserID: owner.ID, UserID: owner.ID,
}) })
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
@ -515,7 +521,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
} }
var config *externalauth.Config var config *externalauth.Config
for _, c := range s.ExternalAuthConfigs { for _, c := range s.ExternalAuthConfigs {
if c.ID != p { if c.ID != p.ID {
continue continue
} }
config = c config = c
@ -524,7 +530,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
// We weren't able to find a matching config for the ID! // We weren't able to find a matching config for the ID!
if config == nil { if config == nil {
s.Logger.Warn(ctx, "workspace build job is missing external auth provider", s.Logger.Warn(ctx, "workspace build job is missing external auth provider",
slog.F("provider_id", p), slog.F("provider_id", p.ID),
slog.F("template_version_id", templateVersion.ID), slog.F("template_version_id", templateVersion.ID),
slog.F("workspace_id", workspaceBuild.WorkspaceID)) slog.F("workspace_id", workspaceBuild.WorkspaceID))
continue continue
@ -532,13 +538,13 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
link, valid, err := config.RefreshToken(ctx, s.Database, link) link, valid, err := config.RefreshToken(ctx, s.Database, link)
if err != nil { if err != nil {
return nil, failJob(fmt.Sprintf("refresh external auth link %q: %s", p, err)) return nil, failJob(fmt.Sprintf("refresh external auth link %q: %s", p.ID, err))
} }
if !valid { if !valid {
continue continue
} }
externalAuthProviders = append(externalAuthProviders, &sdkproto.ExternalAuthProvider{ externalAuthProviders = append(externalAuthProviders, &sdkproto.ExternalAuthProvider{
Id: p, Id: p.ID,
AccessToken: link.OAuthAccessToken, AccessToken: link.OAuthAccessToken,
}) })
} }
@ -1133,23 +1139,49 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob)
for _, externalAuthProvider := range jobType.TemplateImport.ExternalAuthProviders { for _, externalAuthProvider := range jobType.TemplateImport.ExternalAuthProviders {
contains := false contains := false
for _, configuredProvider := range s.ExternalAuthConfigs { for _, configuredProvider := range s.ExternalAuthConfigs {
if configuredProvider.ID == externalAuthProvider { if configuredProvider.ID == externalAuthProvider.Id {
contains = true contains = true
break break
} }
} }
if !contains { if !contains {
completedError = sql.NullString{ completedError = sql.NullString{
String: fmt.Sprintf("external auth provider %q is not configured", externalAuthProvider), String: fmt.Sprintf("external auth provider %q is not configured", externalAuthProvider.Id),
Valid: true, Valid: true,
} }
break break
} }
} }
// Fallback to `ExternalAuthProvidersNames` if it was specified and `ExternalAuthProviders`
// was not. Gives us backwards compatibility with custom provisioners that haven't been
// updated to use the new field yet.
var externalAuthProviders []database.ExternalAuthProvider
if providersLen := len(jobType.TemplateImport.ExternalAuthProviders); providersLen > 0 {
externalAuthProviders = make([]database.ExternalAuthProvider, 0, providersLen)
for _, provider := range jobType.TemplateImport.ExternalAuthProviders {
externalAuthProviders = append(externalAuthProviders, database.ExternalAuthProvider{
ID: provider.Id,
Optional: provider.Optional,
})
}
} else if namesLen := len(jobType.TemplateImport.ExternalAuthProvidersNames); namesLen > 0 {
externalAuthProviders = make([]database.ExternalAuthProvider, 0, namesLen)
for _, providerID := range jobType.TemplateImport.ExternalAuthProvidersNames {
externalAuthProviders = append(externalAuthProviders, database.ExternalAuthProvider{
ID: providerID,
})
}
}
externalAuthProvidersMessage, err := json.Marshal(externalAuthProviders)
if err != nil {
return nil, xerrors.Errorf("failed to serialize external_auth_providers value: %w", err)
}
err = s.Database.UpdateTemplateVersionExternalAuthProvidersByJobID(ctx, database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams{ err = s.Database.UpdateTemplateVersionExternalAuthProvidersByJobID(ctx, database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams{
JobID: jobID, JobID: jobID,
ExternalAuthProviders: jobType.TemplateImport.ExternalAuthProviders, ExternalAuthProviders: json.RawMessage(externalAuthProvidersMessage),
UpdatedAt: dbtime.Now(), UpdatedAt: dbtime.Now(),
}) })
if err != nil { if err != nil {

View File

@ -172,11 +172,14 @@ func TestAcquireJob(t *testing.T) {
// create an API key with an expiration within the bounds of the // create an API key with an expiration within the bounds of the
// deployment config. // deployment config.
dv := &codersdk.DeploymentValues{MaxTokenLifetime: clibase.Duration(time.Hour)} dv := &codersdk.DeploymentValues{MaxTokenLifetime: clibase.Duration(time.Hour)}
gitAuthProvider := "github" gitAuthProvider := &sdkproto.ExternalAuthProviderResource{
Id: "github",
}
srv, db, ps, _ := setup(t, false, &overrides{ srv, db, ps, _ := setup(t, false, &overrides{
deploymentValues: dv, deploymentValues: dv,
externalAuthConfigs: []*externalauth.Config{{ externalAuthConfigs: []*externalauth.Config{{
ID: gitAuthProvider, ID: gitAuthProvider.Id,
InstrumentedOAuth2Config: &testutil.OAuth2Config{}, InstrumentedOAuth2Config: &testutil.OAuth2Config{},
}}, }},
}) })
@ -191,7 +194,7 @@ func TestAcquireJob(t *testing.T) {
OAuthAccessToken: "access-token", OAuthAccessToken: "access-token",
}) })
dbgen.ExternalAuthLink(t, db, database.ExternalAuthLink{ dbgen.ExternalAuthLink(t, db, database.ExternalAuthLink{
ProviderID: gitAuthProvider, ProviderID: gitAuthProvider.Id,
UserID: user.ID, UserID: user.ID,
}) })
template := dbgen.Template(t, db, database.Template{ template := dbgen.Template(t, db, database.Template{
@ -207,9 +210,14 @@ func TestAcquireJob(t *testing.T) {
}, },
JobID: uuid.New(), JobID: uuid.New(),
}) })
err := db.UpdateTemplateVersionExternalAuthProvidersByJobID(ctx, database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams{ externalAuthProviders, err := json.Marshal([]database.ExternalAuthProvider{{
ID: gitAuthProvider.Id,
Optional: gitAuthProvider.Optional,
}})
require.NoError(t, err)
err = db.UpdateTemplateVersionExternalAuthProvidersByJobID(ctx, database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams{
JobID: version.JobID, JobID: version.JobID,
ExternalAuthProviders: []string{gitAuthProvider}, ExternalAuthProviders: json.RawMessage(externalAuthProviders),
UpdatedAt: dbtime.Now(), UpdatedAt: dbtime.Now(),
}) })
require.NoError(t, err) require.NoError(t, err)
@ -321,7 +329,7 @@ func TestAcquireJob(t *testing.T) {
}, },
}, },
ExternalAuthProviders: []*sdkproto.ExternalAuthProvider{{ ExternalAuthProviders: []*sdkproto.ExternalAuthProvider{{
Id: gitAuthProvider, Id: gitAuthProvider.Id,
AccessToken: "access_token", AccessToken: "access_token",
}}, }},
Metadata: &sdkproto.Metadata{ Metadata: &sdkproto.Metadata{
@ -949,8 +957,10 @@ func TestCompleteJob(t *testing.T) {
Name: "hello", Name: "hello",
Type: "aws_instance", Type: "aws_instance",
}}, }},
StopResources: []*sdkproto.Resource{}, StopResources: []*sdkproto.Resource{},
ExternalAuthProviders: []string{"github"}, ExternalAuthProviders: []*sdkproto.ExternalAuthProviderResource{{
Id: "github",
}},
}, },
}, },
}) })
@ -1002,7 +1012,7 @@ func TestCompleteJob(t *testing.T) {
Type: "aws_instance", Type: "aws_instance",
}}, }},
StopResources: []*sdkproto.Resource{}, StopResources: []*sdkproto.Resource{},
ExternalAuthProviders: []string{"github"}, ExternalAuthProviders: []*sdkproto.ExternalAuthProviderResource{{Id: "github"}},
}, },
}, },
}) })
@ -1776,7 +1786,7 @@ func setup(t *testing.T, ignoreLogErrors bool, ov *overrides) (proto.DRPCProvisi
Tags: database.StringMap{}, Tags: database.StringMap{},
LastSeenAt: sql.NullTime{}, LastSeenAt: sql.NullTime{},
Version: buildinfo.Version(), Version: buildinfo.Version(),
APIVersion: proto.VersionCurrent.String(), APIVersion: proto.CurrentVersion.String(),
}) })
require.NoError(t, err) require.NoError(t, err)

View File

@ -289,19 +289,28 @@ func (api *API) templateVersionExternalAuth(rw http.ResponseWriter, r *http.Requ
templateVersion = httpmw.TemplateVersionParam(r) templateVersion = httpmw.TemplateVersionParam(r)
) )
rawProviders := templateVersion.ExternalAuthProviders var rawProviders []database.ExternalAuthProvider
err := json.Unmarshal(templateVersion.ExternalAuthProviders, &rawProviders)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error reading auth config from database",
Detail: err.Error(),
})
return
}
providers := make([]codersdk.TemplateVersionExternalAuth, 0) providers := make([]codersdk.TemplateVersionExternalAuth, 0)
for _, rawProvider := range rawProviders { for _, rawProvider := range rawProviders {
var config *externalauth.Config var config *externalauth.Config
for _, provider := range api.ExternalAuthConfigs { for _, provider := range api.ExternalAuthConfigs {
if provider.ID == rawProvider { if provider.ID == rawProvider.ID {
config = provider config = provider
break break
} }
} }
if config == nil { if config == nil {
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("The template version references a Git auth provider %q that no longer exists.", rawProvider), Message: fmt.Sprintf("The template version references a Git auth provider %q that no longer exists.", rawProvider.ID),
Detail: "You'll need to update the template version to use a different provider.", Detail: "You'll need to update the template version to use a different provider.",
}) })
return return
@ -323,6 +332,7 @@ func (api *API) templateVersionExternalAuth(rw http.ResponseWriter, r *http.Requ
AuthenticateURL: redirectURL.String(), AuthenticateURL: redirectURL.String(),
DisplayName: config.DisplayName, DisplayName: config.DisplayName,
DisplayIcon: config.DisplayIcon, DisplayIcon: config.DisplayIcon,
Optional: rawProvider.Optional,
} }
authLink, err := api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ authLink, err := api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{

View File

@ -347,7 +347,7 @@ func TestTemplateVersionsExternalAuth(t *testing.T) {
ProvisionPlan: []*proto.Response{{ ProvisionPlan: []*proto.Response{{
Type: &proto.Response_Plan{ Type: &proto.Response_Plan{
Plan: &proto.PlanComplete{ Plan: &proto.PlanComplete{
ExternalAuthProviders: []string{"github"}, ExternalAuthProviders: []*proto.ExternalAuthProviderResource{{Id: "github", Optional: true}},
}, },
}, },
}}, }},
@ -373,6 +373,7 @@ func TestTemplateVersionsExternalAuth(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Len(t, providers, 1) require.Len(t, providers, 1)
require.True(t, providers[0].Authenticated) require.True(t, providers[0].Authenticated)
require.True(t, providers[0].Optional)
}) })
} }

View File

@ -199,9 +199,10 @@ func (c *Client) ServeProvisionerDaemon(ctx context.Context, req ServeProvisione
return nil, xerrors.Errorf("parse url: %w", err) return nil, xerrors.Errorf("parse url: %w", err)
} }
query := serverURL.Query() query := serverURL.Query()
query.Add("version", proto.CurrentVersion.String())
query.Add("id", req.ID.String()) query.Add("id", req.ID.String())
query.Add("name", req.Name) query.Add("name", req.Name)
query.Add("version", proto.VersionCurrent.String()) query.Add("version", proto.CurrentVersion.String())
for _, provisioner := range req.Provisioners { for _, provisioner := range req.Provisioners {
query.Add("provisioner", string(provisioner)) query.Add("provisioner", string(provisioner))

View File

@ -41,6 +41,7 @@ type TemplateVersionExternalAuth struct {
DisplayIcon string `json:"display_icon"` DisplayIcon string `json:"display_icon"`
AuthenticateURL string `json:"authenticate_url"` AuthenticateURL string `json:"authenticate_url"`
Authenticated bool `json:"authenticated"` Authenticated bool `json:"authenticated"`
Optional bool `json:"optional,omitempty"`
} }
type ValidationMonotonicOrder string type ValidationMonotonicOrder string

2
docs/api/schemas.md generated
View File

@ -5195,6 +5195,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"display_icon": "string", "display_icon": "string",
"display_name": "string", "display_name": "string",
"id": "string", "id": "string",
"optional": true,
"type": "string" "type": "string"
} }
``` ```
@ -5208,6 +5209,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
| `display_icon` | string | false | | | | `display_icon` | string | false | | |
| `display_name` | string | false | | | | `display_name` | string | false | | |
| `id` | string | false | | | | `id` | string | false | | |
| `optional` | boolean | false | | |
| `type` | string | false | | | | `type` | string | false | | |
## codersdk.TemplateVersionParameter ## codersdk.TemplateVersionParameter

2
docs/api/templates.md generated
View File

@ -2002,6 +2002,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/e
"display_icon": "string", "display_icon": "string",
"display_name": "string", "display_name": "string",
"id": "string", "id": "string",
"optional": true,
"type": "string" "type": "string"
} }
] ]
@ -2025,6 +2026,7 @@ Status Code **200**
| `» display_icon` | string | false | | | | `» display_icon` | string | false | | |
| `» display_name` | string | false | | | | `» display_name` | string | false | | |
| `» id` | string | false | | | | `» id` | string | false | | |
| `» optional` | boolean | false | | |
| `» type` | string | false | | | | `» type` | string | false | | |
To perform this operation, you must be authenticated. [Learn more](authentication.md). To perform this operation, you must be authenticated. [Learn more](authentication.md).

View File

@ -52,7 +52,7 @@ func TestProvisionerDaemon_PSK(t *testing.T) {
require.Equal(t, "matt-daemon", daemons[0].Name) require.Equal(t, "matt-daemon", daemons[0].Name)
require.Equal(t, provisionersdk.ScopeOrganization, daemons[0].Tags[provisionersdk.TagScope]) require.Equal(t, provisionersdk.ScopeOrganization, daemons[0].Tags[provisionersdk.TagScope])
require.Equal(t, buildinfo.Version(), daemons[0].Version) require.Equal(t, buildinfo.Version(), daemons[0].Version)
require.Equal(t, proto.VersionCurrent.String(), daemons[0].APIVersion) require.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion)
} }
func TestProvisionerDaemon_SessionToken(t *testing.T) { func TestProvisionerDaemon_SessionToken(t *testing.T) {
@ -89,7 +89,7 @@ func TestProvisionerDaemon_SessionToken(t *testing.T) {
assert.Equal(t, provisionersdk.ScopeUser, daemons[0].Tags[provisionersdk.TagScope]) assert.Equal(t, provisionersdk.ScopeUser, daemons[0].Tags[provisionersdk.TagScope])
assert.Equal(t, anotherUser.ID.String(), daemons[0].Tags[provisionersdk.TagOwner]) assert.Equal(t, anotherUser.ID.String(), daemons[0].Tags[provisionersdk.TagOwner])
assert.Equal(t, buildinfo.Version(), daemons[0].Version) assert.Equal(t, buildinfo.Version(), daemons[0].Version)
assert.Equal(t, proto.VersionCurrent.String(), daemons[0].APIVersion) assert.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion)
}) })
t.Run("ScopeAnotherUser", func(t *testing.T) { t.Run("ScopeAnotherUser", func(t *testing.T) {
@ -125,7 +125,7 @@ func TestProvisionerDaemon_SessionToken(t *testing.T) {
// This should get clobbered to the user who started the daemon. // This should get clobbered to the user who started the daemon.
assert.Equal(t, anotherUser.ID.String(), daemons[0].Tags[provisionersdk.TagOwner]) assert.Equal(t, anotherUser.ID.String(), daemons[0].Tags[provisionersdk.TagOwner])
assert.Equal(t, buildinfo.Version(), daemons[0].Version) assert.Equal(t, buildinfo.Version(), daemons[0].Version)
assert.Equal(t, proto.VersionCurrent.String(), daemons[0].APIVersion) assert.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion)
}) })
t.Run("ScopeOrg", func(t *testing.T) { t.Run("ScopeOrg", func(t *testing.T) {
@ -159,6 +159,6 @@ func TestProvisionerDaemon_SessionToken(t *testing.T) {
assert.Equal(t, "org-daemon", daemons[0].Name) assert.Equal(t, "org-daemon", daemons[0].Name)
assert.Equal(t, provisionersdk.ScopeOrganization, daemons[0].Tags[provisionersdk.TagScope]) assert.Equal(t, provisionersdk.ScopeOrganization, daemons[0].Tags[provisionersdk.TagScope])
assert.Equal(t, buildinfo.Version(), daemons[0].Version) assert.Equal(t, buildinfo.Version(), daemons[0].Version)
assert.Equal(t, proto.VersionCurrent.String(), daemons[0].APIVersion) assert.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion)
}) })
} }

View File

@ -209,7 +209,7 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request)
return return
} }
provisioners := make([]database.ProvisionerType, 0) provisioners := make([]database.ProvisionerType, 0, len(provisionersMap))
for p := range provisionersMap { for p := range provisionersMap {
switch p { switch p {
case codersdk.ProvisionerTypeTerraform: case codersdk.ProvisionerTypeTerraform:
@ -239,7 +239,7 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request)
apiVersion = qv apiVersion = qv
} }
if err := proto.VersionCurrent.Validate(apiVersion); err != nil { if err := proto.CurrentVersion.Validate(apiVersion); err != nil {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Incompatible or unparsable version", Message: "Incompatible or unparsable version",
Validations: []codersdk.ValidationError{ Validations: []codersdk.ValidationError{

View File

@ -26,9 +26,9 @@ import (
"github.com/coder/coder/v2/enterprise/coderd/license" "github.com/coder/coder/v2/enterprise/coderd/license"
"github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisioner/echo"
"github.com/coder/coder/v2/provisionerd" "github.com/coder/coder/v2/provisionerd"
provisionerdproto "github.com/coder/coder/v2/provisionerd/proto" "github.com/coder/coder/v2/provisionerd/proto"
"github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk"
"github.com/coder/coder/v2/provisionersdk/proto" sdkproto "github.com/coder/coder/v2/provisionersdk/proto"
"github.com/coder/coder/v2/testutil" "github.com/coder/coder/v2/testutil"
) )
@ -62,7 +62,7 @@ func TestProvisionerDaemonServe(t *testing.T) {
if assert.Len(t, daemons, 1) { if assert.Len(t, daemons, 1) {
assert.Equal(t, daemonName, daemons[0].Name) assert.Equal(t, daemonName, daemons[0].Name)
assert.Equal(t, buildinfo.Version(), daemons[0].Version) assert.Equal(t, buildinfo.Version(), daemons[0].Version)
assert.Equal(t, provisionerdproto.VersionCurrent.String(), daemons[0].APIVersion) assert.Equal(t, proto.CurrentVersion.String(), daemons[0].APIVersion)
} }
}) })
@ -149,7 +149,7 @@ func TestProvisionerDaemonServe(t *testing.T) {
q.Add("provisioner", "echo") q.Add("provisioner", "echo")
// Set a different (newer) version than the current. // Set a different (newer) version than the current.
v := apiversion.New(provisionerdproto.CurrentMajor+1, provisionerdproto.CurrentMinor+1) v := apiversion.New(proto.CurrentMajor+1, proto.CurrentMinor+1)
q.Add("version", v.String()) q.Add("version", v.String())
srvURL.RawQuery = q.Encode() srvURL.RawQuery = q.Encode()
@ -165,7 +165,7 @@ func TestProvisionerDaemonServe(t *testing.T) {
b, err := io.ReadAll(resp.Body) b, err := io.ReadAll(resp.Body)
require.NoError(t, err) require.NoError(t, err)
// The below means that provisionerd tried to serve us, checked our api version, and said nope. // The below means that provisionerd tried to serve us, checked our api version, and said nope.
require.Contains(t, string(b), "server is at version 1.0, behind requested major version 2.1") require.Contains(t, string(b), fmt.Sprintf("server is at version %s, behind requested major version %s", proto.CurrentVersion.String(), v.String()))
}) })
t.Run("NoLicense", func(t *testing.T) { t.Run("NoLicense", func(t *testing.T) {
@ -259,13 +259,13 @@ func TestProvisionerDaemonServe(t *testing.T) {
authToken := uuid.NewString() authToken := uuid.NewString()
data, err := echo.Tar(&echo.Responses{ data, err := echo.Tar(&echo.Responses{
Parse: echo.ParseComplete, Parse: echo.ParseComplete,
ProvisionPlan: []*proto.Response{{ ProvisionPlan: []*sdkproto.Response{{
Type: &proto.Response_Plan{ Type: &sdkproto.Response_Plan{
Plan: &proto.PlanComplete{ Plan: &sdkproto.PlanComplete{
Resources: []*proto.Resource{{ Resources: []*sdkproto.Resource{{
Name: "example", Name: "example",
Type: "aws_instance", Type: "aws_instance",
Agents: []*proto.Agent{{ Agents: []*sdkproto.Agent{{
Id: uuid.NewString(), Id: uuid.NewString(),
Name: "example", Name: "example",
}}, }},
@ -383,10 +383,10 @@ func TestProvisionerDaemonServe(t *testing.T) {
}() }()
connector := provisionerd.LocalProvisioners{ connector := provisionerd.LocalProvisioners{
string(database.ProvisionerTypeEcho): proto.NewDRPCProvisionerClient(terraformClient), string(database.ProvisionerTypeEcho): sdkproto.NewDRPCProvisionerClient(terraformClient),
} }
another := codersdk.New(client.URL) another := codersdk.New(client.URL)
pd := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) { pd := provisionerd.New(func(ctx context.Context) (proto.DRPCProvisionerDaemonClient, error) {
return another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{ return another.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
ID: uuid.New(), ID: uuid.New(),
Name: testutil.MustRandString(t, 63), Name: testutil.MustRandString(t, 63),
@ -415,17 +415,17 @@ func TestProvisionerDaemonServe(t *testing.T) {
authToken := uuid.NewString() authToken := uuid.NewString()
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete, Parse: echo.ParseComplete,
ProvisionApply: []*proto.Response{{ ProvisionApply: []*sdkproto.Response{{
Type: &proto.Response_Apply{ Type: &sdkproto.Response_Apply{
Apply: &proto.ApplyComplete{ Apply: &sdkproto.ApplyComplete{
Resources: []*proto.Resource{{ Resources: []*sdkproto.Resource{{
Name: "example", Name: "example",
Type: "aws_instance", Type: "aws_instance",
DailyCost: 1, DailyCost: 1,
Agents: []*proto.Agent{{ Agents: []*sdkproto.Agent{{
Id: uuid.NewString(), Id: uuid.NewString(),
Name: "example", Name: "example",
Auth: &proto.Agent_Token{ Auth: &sdkproto.Agent_Token{
Token: authToken, Token: authToken,
}, },
}}, }},

View File

@ -125,7 +125,7 @@ type resourceMetadataItem struct {
type State struct { type State struct {
Resources []*proto.Resource Resources []*proto.Resource
Parameters []*proto.RichParameter Parameters []*proto.RichParameter
ExternalAuthProviders []string ExternalAuthProviders []*proto.ExternalAuthProviderResource
} }
// ConvertState consumes Terraform state and a GraphViz representation // ConvertState consumes Terraform state and a GraphViz representation
@ -699,23 +699,33 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string) (*State, error
} }
// A map is used to ensure we don't have duplicates! // A map is used to ensure we don't have duplicates!
externalAuthProvidersMap := map[string]struct{}{} externalAuthProvidersMap := map[string]*proto.ExternalAuthProviderResource{}
for _, tfResources := range tfResourcesByLabel { for _, tfResources := range tfResourcesByLabel {
for _, resource := range tfResources { for _, resource := range tfResources {
// Checking for `coder_git_auth` is legacy! // Checking for `coder_git_auth` is legacy!
if resource.Type != "coder_external_auth" && resource.Type != "coder_git_auth" { if resource.Type != "coder_external_auth" && resource.Type != "coder_git_auth" {
continue continue
} }
id, ok := resource.AttributeValues["id"].(string) id, ok := resource.AttributeValues["id"].(string)
if !ok { if !ok {
return nil, xerrors.Errorf("external auth id is not a string") return nil, xerrors.Errorf("external auth id is not a string")
} }
externalAuthProvidersMap[id] = struct{}{} optional := false
optionalAttribute, ok := resource.AttributeValues["optional"].(bool)
if ok {
optional = optionalAttribute
}
externalAuthProvidersMap[id] = &proto.ExternalAuthProviderResource{
Id: id,
Optional: optional,
}
} }
} }
externalAuthProviders := make([]string, 0, len(externalAuthProvidersMap)) externalAuthProviders := make([]*proto.ExternalAuthProviderResource, 0, len(externalAuthProvidersMap))
for id := range externalAuthProvidersMap { for _, it := range externalAuthProvidersMap {
externalAuthProviders = append(externalAuthProviders, id) externalAuthProviders = append(externalAuthProviders, it)
} }
return &State{ return &State{

View File

@ -7,6 +7,7 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort" "sort"
"strings"
"testing" "testing"
tfjson "github.com/hashicorp/terraform-json" tfjson "github.com/hashicorp/terraform-json"
@ -23,9 +24,9 @@ func TestConvertResources(t *testing.T) {
// nolint:dogsled // nolint:dogsled
_, filename, _, _ := runtime.Caller(0) _, filename, _, _ := runtime.Caller(0)
type testCase struct { type testCase struct {
resources []*proto.Resource resources []*proto.Resource
parameters []*proto.RichParameter parameters []*proto.RichParameter
gitAuthProviders []string externalAuthProviders []*proto.ExternalAuthProviderResource
} }
// If a user doesn't specify 'display_apps' then they default // If a user doesn't specify 'display_apps' then they default
@ -486,7 +487,22 @@ func TestConvertResources(t *testing.T) {
DisplayApps: &displayApps, DisplayApps: &displayApps,
}}, }},
}}, }},
gitAuthProviders: []string{"github", "gitlab"}, externalAuthProviders: []*proto.ExternalAuthProviderResource{{Id: "github"}, {Id: "gitlab"}},
},
"external-auth-providers": {
resources: []*proto.Resource{{
Name: "dev",
Type: "null_resource",
Agents: []*proto.Agent{{
Name: "main",
OperatingSystem: "linux",
Architecture: "amd64",
Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
DisplayApps: &displayApps,
}},
}},
externalAuthProviders: []*proto.ExternalAuthProviderResource{{Id: "github"}, {Id: "gitlab", Optional: true}},
}, },
"display-apps": { "display-apps": {
resources: []*proto.Resource{{ resources: []*proto.Resource{{
@ -547,7 +563,7 @@ func TestConvertResources(t *testing.T) {
state, err := terraform.ConvertState(modules, string(tfPlanGraph)) state, err := terraform.ConvertState(modules, string(tfPlanGraph))
require.NoError(t, err) require.NoError(t, err)
sortResources(state.Resources) sortResources(state.Resources)
sort.Strings(state.ExternalAuthProviders) sortExternalAuthProviders(state.ExternalAuthProviders)
expectedNoMetadata := make([]*proto.Resource, 0) expectedNoMetadata := make([]*proto.Resource, 0)
for _, resource := range expected.resources { for _, resource := range expected.resources {
@ -585,7 +601,7 @@ func TestConvertResources(t *testing.T) {
require.Equal(t, string(parametersWant), string(parametersGot)) require.Equal(t, string(parametersWant), string(parametersGot))
require.Equal(t, expectedNoMetadataMap, resourcesMap) require.Equal(t, expectedNoMetadataMap, resourcesMap)
require.ElementsMatch(t, expected.gitAuthProviders, state.ExternalAuthProviders) require.ElementsMatch(t, expected.externalAuthProviders, state.ExternalAuthProviders)
}) })
t.Run("Provision", func(t *testing.T) { t.Run("Provision", func(t *testing.T) {
@ -601,7 +617,7 @@ func TestConvertResources(t *testing.T) {
state, err := terraform.ConvertState([]*tfjson.StateModule{tfState.Values.RootModule}, string(tfStateGraph)) state, err := terraform.ConvertState([]*tfjson.StateModule{tfState.Values.RootModule}, string(tfStateGraph))
require.NoError(t, err) require.NoError(t, err)
sortResources(state.Resources) sortResources(state.Resources)
sort.Strings(state.ExternalAuthProviders) sortExternalAuthProviders(state.ExternalAuthProviders)
for _, resource := range state.Resources { for _, resource := range state.Resources {
for _, agent := range resource.Agents { for _, agent := range resource.Agents {
agent.Id = "" agent.Id = ""
@ -628,7 +644,7 @@ func TestConvertResources(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expectedMap, resourcesMap) require.Equal(t, expectedMap, resourcesMap)
require.ElementsMatch(t, expected.gitAuthProviders, state.ExternalAuthProviders) require.ElementsMatch(t, expected.externalAuthProviders, state.ExternalAuthProviders)
}) })
}) })
} }
@ -901,3 +917,9 @@ func sortResources(resources []*proto.Resource) {
}) })
} }
} }
func sortExternalAuthProviders(providers []*proto.ExternalAuthProviderResource) {
sort.Slice(providers, func(i, j int) bool {
return strings.Compare(providers[i].Id, providers[j].Id) == -1
})
}

View File

@ -0,0 +1,28 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
version = "0.16.0"
}
}
}
data "coder_external_auth" "github" {
id = "github"
}
data "coder_external_auth" "gitlab" {
id = "gitlab"
optional = true
}
resource "coder_agent" "main" {
os = "linux"
arch = "amd64"
}
resource "null_resource" "dev" {
depends_on = [
coder_agent.main
]
}

View File

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

View File

@ -0,0 +1,230 @@
{
"format_version": "1.2",
"terraform_version": "1.6.6",
"planned_values": {
"root_module": {
"resources": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"arch": "amd64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"env": null,
"login_before_ready": true,
"metadata": [],
"motd_file": 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": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"triggers": null
},
"sensitive_values": {}
}
]
}
},
"resource_changes": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"arch": "amd64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"env": null,
"login_before_ready": true,
"metadata": [],
"motd_file": 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": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"triggers": null
},
"after_unknown": {
"id": true
},
"before_sensitive": false,
"after_sensitive": {}
}
}
],
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.6.6",
"values": {
"root_module": {
"resources": [
{
"address": "data.coder_external_auth.github",
"mode": "data",
"type": "coder_external_auth",
"name": "github",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"access_token": "",
"id": "github",
"optional": null
},
"sensitive_values": {}
},
{
"address": "data.coder_external_auth.gitlab",
"mode": "data",
"type": "coder_external_auth",
"name": "gitlab",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"access_token": "",
"id": "gitlab",
"optional": true
},
"sensitive_values": {}
}
]
}
}
},
"configuration": {
"provider_config": {
"coder": {
"name": "coder",
"full_name": "registry.terraform.io/coder/coder",
"version_constraint": "0.16.0"
},
"null": {
"name": "null",
"full_name": "registry.terraform.io/hashicorp/null"
}
},
"root_module": {
"resources": [
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_config_key": "coder",
"expressions": {
"arch": {
"constant_value": "amd64"
},
"os": {
"constant_value": "linux"
}
},
"schema_version": 0
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_config_key": "null",
"schema_version": 0,
"depends_on": [
"coder_agent.main"
]
},
{
"address": "data.coder_external_auth.github",
"mode": "data",
"type": "coder_external_auth",
"name": "github",
"provider_config_key": "coder",
"expressions": {
"id": {
"constant_value": "github"
}
},
"schema_version": 0
},
{
"address": "data.coder_external_auth.gitlab",
"mode": "data",
"type": "coder_external_auth",
"name": "gitlab",
"provider_config_key": "coder",
"expressions": {
"id": {
"constant_value": "gitlab"
},
"optional": {
"constant_value": true
}
},
"schema_version": 0
}
]
}
},
"timestamp": "2024-02-12T23:11:52Z",
"errored": false
}

View File

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

View File

@ -0,0 +1,98 @@
{
"format_version": "1.0",
"terraform_version": "1.6.6",
"values": {
"root_module": {
"resources": [
{
"address": "data.coder_external_auth.github",
"mode": "data",
"type": "coder_external_auth",
"name": "github",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"access_token": "",
"id": "github",
"optional": null
},
"sensitive_values": {}
},
{
"address": "data.coder_external_auth.gitlab",
"mode": "data",
"type": "coder_external_auth",
"name": "gitlab",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"access_token": "",
"id": "gitlab",
"optional": true
},
"sensitive_values": {}
},
{
"address": "coder_agent.main",
"mode": "managed",
"type": "coder_agent",
"name": "main",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"arch": "amd64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"display_apps": [
{
"port_forwarding_helper": true,
"ssh_helper": true,
"vscode": true,
"vscode_insiders": false,
"web_terminal": true
}
],
"env": null,
"id": "d1f23602-ef8e-4ecf-aa5a-df8aa476344e",
"init_script": "",
"login_before_ready": true,
"metadata": [],
"motd_file": null,
"os": "linux",
"shutdown_script": null,
"shutdown_script_timeout": 300,
"startup_script": null,
"startup_script_behavior": null,
"startup_script_timeout": 300,
"token": "90440015-11c8-442b-adba-9f2bd279b5c7",
"troubleshooting_url": null
},
"sensitive_values": {
"display_apps": [
{}
],
"metadata": [],
"token": true
}
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "8183284779544326910",
"triggers": null
},
"sensitive_values": {},
"depends_on": [
"coder_agent.main"
]
}
]
}
}
}

View File

@ -1251,10 +1251,11 @@ type CompletedJob_TemplateImport struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
StartResources []*proto.Resource `protobuf:"bytes,1,rep,name=start_resources,json=startResources,proto3" json:"start_resources,omitempty"` StartResources []*proto.Resource `protobuf:"bytes,1,rep,name=start_resources,json=startResources,proto3" json:"start_resources,omitempty"`
StopResources []*proto.Resource `protobuf:"bytes,2,rep,name=stop_resources,json=stopResources,proto3" json:"stop_resources,omitempty"` StopResources []*proto.Resource `protobuf:"bytes,2,rep,name=stop_resources,json=stopResources,proto3" json:"stop_resources,omitempty"`
RichParameters []*proto.RichParameter `protobuf:"bytes,3,rep,name=rich_parameters,json=richParameters,proto3" json:"rich_parameters,omitempty"` RichParameters []*proto.RichParameter `protobuf:"bytes,3,rep,name=rich_parameters,json=richParameters,proto3" json:"rich_parameters,omitempty"`
ExternalAuthProviders []string `protobuf:"bytes,4,rep,name=external_auth_providers,json=externalAuthProviders,proto3" json:"external_auth_providers,omitempty"` ExternalAuthProvidersNames []string `protobuf:"bytes,4,rep,name=external_auth_providers_names,json=externalAuthProvidersNames,proto3" json:"external_auth_providers_names,omitempty"`
ExternalAuthProviders []*proto.ExternalAuthProviderResource `protobuf:"bytes,5,rep,name=external_auth_providers,json=externalAuthProviders,proto3" json:"external_auth_providers,omitempty"`
} }
func (x *CompletedJob_TemplateImport) Reset() { func (x *CompletedJob_TemplateImport) Reset() {
@ -1310,7 +1311,14 @@ func (x *CompletedJob_TemplateImport) GetRichParameters() []*proto.RichParameter
return nil return nil
} }
func (x *CompletedJob_TemplateImport) GetExternalAuthProviders() []string { func (x *CompletedJob_TemplateImport) GetExternalAuthProvidersNames() []string {
if x != nil {
return x.ExternalAuthProvidersNames
}
return nil
}
func (x *CompletedJob_TemplateImport) GetExternalAuthProviders() []*proto.ExternalAuthProviderResource {
if x != nil { if x != nil {
return x.ExternalAuthProviders return x.ExternalAuthProviders
} }
@ -1489,7 +1497,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 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, 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, 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, 0xe2, 0x05, 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, 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, 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, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
@ -1514,7 +1522,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 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, 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, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x8b, 0x02, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 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, 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, 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, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
@ -1527,99 +1535,106 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 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, 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, 0x36, 0x0a, 0x17, 0x65, 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, 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, 0x09, 0x52, 0x15, 0x65, 0x78, 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, 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, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65,
0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x1a, 0x45, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79,
0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x52, 0x75, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
0x70, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72,
0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x22, 0xb0, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72,
0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76,
0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52,
0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61,
0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x04,
0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f,
0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74,
0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x70, 0x75, 0x74, 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f,
0x64, 0x12, 0x25, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f,
0x11, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12,
0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x25, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e,
0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61,
0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03,
0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x14, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x76, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c,
0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x14, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x72,
0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03,
0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
0x6c, 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x06, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x03, 0x75, 0x73, 0x65, 0x72, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75,
0x10, 0x04, 0x22, 0x7a, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04,
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x7a, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73,
0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65,
0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x64, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61,
0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f,
0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x4a, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c,
0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65,
0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x4a, 0x0a, 0x12,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65,
0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x68, 0x0a, 0x13, 0x43, 0x6f, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69,
0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x64,
0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x68, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x6d,
0x6b, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x12,
0x64, 0x69, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75,
0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x69,
0x64, 0x67, 0x65, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75,
0x71, 0x75, 0x69, 0x72, 0x65, 0x2a, 0x34, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x64, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x75, 0x64, 0x67,
0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x65, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x63, 0x71, 0x75,
0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x69, 0x72, 0x65, 0x2a, 0x34, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x10, 0x01, 0x32, 0xc5, 0x03, 0x0a, 0x11, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x5f,
0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x4f, 0x56,
0x6e, 0x12, 0x41, 0x0a, 0x0a, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x10, 0x01, 0x32, 0xc5, 0x03, 0x0a, 0x11, 0x50, 0x72,
0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12,
0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x0a, 0x0a, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x13, 0x2e,
0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x22, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70,
0x03, 0x88, 0x02, 0x01, 0x12, 0x52, 0x0a, 0x14, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
0x6f, 0x62, 0x57, 0x69, 0x74, 0x68, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x1b, 0x2e, 0x70, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x22, 0x03, 0x88,
0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x02, 0x01, 0x12, 0x52, 0x0a, 0x14, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62,
0x65, 0x6c, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x57, 0x69, 0x74, 0x68, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c,
0x64, 0x4a, 0x6f, 0x62, 0x28, 0x01, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x12, 0x20, 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, 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, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x70,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62,
0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x46, 0x61, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70,
0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x79, 0x12, 0x3e, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62,
0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e,
0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70,
0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x79, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x70,
0x70, 0x74, 0x79, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
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 ( var (
@ -1637,35 +1652,36 @@ func file_provisionerd_proto_provisionerd_proto_rawDescGZIP() []byte {
var file_provisionerd_proto_provisionerd_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_provisionerd_proto_provisionerd_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_provisionerd_proto_provisionerd_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_provisionerd_proto_provisionerd_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
var file_provisionerd_proto_provisionerd_proto_goTypes = []interface{}{ var file_provisionerd_proto_provisionerd_proto_goTypes = []interface{}{
(LogSource)(0), // 0: provisionerd.LogSource (LogSource)(0), // 0: provisionerd.LogSource
(*Empty)(nil), // 1: provisionerd.Empty (*Empty)(nil), // 1: provisionerd.Empty
(*AcquiredJob)(nil), // 2: provisionerd.AcquiredJob (*AcquiredJob)(nil), // 2: provisionerd.AcquiredJob
(*FailedJob)(nil), // 3: provisionerd.FailedJob (*FailedJob)(nil), // 3: provisionerd.FailedJob
(*CompletedJob)(nil), // 4: provisionerd.CompletedJob (*CompletedJob)(nil), // 4: provisionerd.CompletedJob
(*Log)(nil), // 5: provisionerd.Log (*Log)(nil), // 5: provisionerd.Log
(*UpdateJobRequest)(nil), // 6: provisionerd.UpdateJobRequest (*UpdateJobRequest)(nil), // 6: provisionerd.UpdateJobRequest
(*UpdateJobResponse)(nil), // 7: provisionerd.UpdateJobResponse (*UpdateJobResponse)(nil), // 7: provisionerd.UpdateJobResponse
(*CommitQuotaRequest)(nil), // 8: provisionerd.CommitQuotaRequest (*CommitQuotaRequest)(nil), // 8: provisionerd.CommitQuotaRequest
(*CommitQuotaResponse)(nil), // 9: provisionerd.CommitQuotaResponse (*CommitQuotaResponse)(nil), // 9: provisionerd.CommitQuotaResponse
(*CancelAcquire)(nil), // 10: provisionerd.CancelAcquire (*CancelAcquire)(nil), // 10: provisionerd.CancelAcquire
(*AcquiredJob_WorkspaceBuild)(nil), // 11: provisionerd.AcquiredJob.WorkspaceBuild (*AcquiredJob_WorkspaceBuild)(nil), // 11: provisionerd.AcquiredJob.WorkspaceBuild
(*AcquiredJob_TemplateImport)(nil), // 12: provisionerd.AcquiredJob.TemplateImport (*AcquiredJob_TemplateImport)(nil), // 12: provisionerd.AcquiredJob.TemplateImport
(*AcquiredJob_TemplateDryRun)(nil), // 13: provisionerd.AcquiredJob.TemplateDryRun (*AcquiredJob_TemplateDryRun)(nil), // 13: provisionerd.AcquiredJob.TemplateDryRun
nil, // 14: provisionerd.AcquiredJob.TraceMetadataEntry nil, // 14: provisionerd.AcquiredJob.TraceMetadataEntry
(*FailedJob_WorkspaceBuild)(nil), // 15: provisionerd.FailedJob.WorkspaceBuild (*FailedJob_WorkspaceBuild)(nil), // 15: provisionerd.FailedJob.WorkspaceBuild
(*FailedJob_TemplateImport)(nil), // 16: provisionerd.FailedJob.TemplateImport (*FailedJob_TemplateImport)(nil), // 16: provisionerd.FailedJob.TemplateImport
(*FailedJob_TemplateDryRun)(nil), // 17: provisionerd.FailedJob.TemplateDryRun (*FailedJob_TemplateDryRun)(nil), // 17: provisionerd.FailedJob.TemplateDryRun
(*CompletedJob_WorkspaceBuild)(nil), // 18: provisionerd.CompletedJob.WorkspaceBuild (*CompletedJob_WorkspaceBuild)(nil), // 18: provisionerd.CompletedJob.WorkspaceBuild
(*CompletedJob_TemplateImport)(nil), // 19: provisionerd.CompletedJob.TemplateImport (*CompletedJob_TemplateImport)(nil), // 19: provisionerd.CompletedJob.TemplateImport
(*CompletedJob_TemplateDryRun)(nil), // 20: provisionerd.CompletedJob.TemplateDryRun (*CompletedJob_TemplateDryRun)(nil), // 20: provisionerd.CompletedJob.TemplateDryRun
(proto.LogLevel)(0), // 21: provisioner.LogLevel (proto.LogLevel)(0), // 21: provisioner.LogLevel
(*proto.TemplateVariable)(nil), // 22: provisioner.TemplateVariable (*proto.TemplateVariable)(nil), // 22: provisioner.TemplateVariable
(*proto.VariableValue)(nil), // 23: provisioner.VariableValue (*proto.VariableValue)(nil), // 23: provisioner.VariableValue
(*proto.RichParameterValue)(nil), // 24: provisioner.RichParameterValue (*proto.RichParameterValue)(nil), // 24: provisioner.RichParameterValue
(*proto.ExternalAuthProvider)(nil), // 25: provisioner.ExternalAuthProvider (*proto.ExternalAuthProvider)(nil), // 25: provisioner.ExternalAuthProvider
(*proto.Metadata)(nil), // 26: provisioner.Metadata (*proto.Metadata)(nil), // 26: provisioner.Metadata
(*proto.Resource)(nil), // 27: provisioner.Resource (*proto.Resource)(nil), // 27: provisioner.Resource
(*proto.RichParameter)(nil), // 28: provisioner.RichParameter (*proto.RichParameter)(nil), // 28: provisioner.RichParameter
(*proto.ExternalAuthProviderResource)(nil), // 29: provisioner.ExternalAuthProviderResource
} }
var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{ var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{
11, // 0: provisionerd.AcquiredJob.workspace_build:type_name -> provisionerd.AcquiredJob.WorkspaceBuild 11, // 0: provisionerd.AcquiredJob.workspace_build:type_name -> provisionerd.AcquiredJob.WorkspaceBuild
@ -1697,24 +1713,25 @@ var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{
27, // 26: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource 27, // 26: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource
27, // 27: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource 27, // 27: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource
28, // 28: provisionerd.CompletedJob.TemplateImport.rich_parameters:type_name -> provisioner.RichParameter 28, // 28: provisionerd.CompletedJob.TemplateImport.rich_parameters:type_name -> provisioner.RichParameter
27, // 29: provisionerd.CompletedJob.TemplateDryRun.resources:type_name -> provisioner.Resource 29, // 29: provisionerd.CompletedJob.TemplateImport.external_auth_providers:type_name -> provisioner.ExternalAuthProviderResource
1, // 30: provisionerd.ProvisionerDaemon.AcquireJob:input_type -> provisionerd.Empty 27, // 30: provisionerd.CompletedJob.TemplateDryRun.resources:type_name -> provisioner.Resource
10, // 31: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:input_type -> provisionerd.CancelAcquire 1, // 31: provisionerd.ProvisionerDaemon.AcquireJob:input_type -> provisionerd.Empty
8, // 32: provisionerd.ProvisionerDaemon.CommitQuota:input_type -> provisionerd.CommitQuotaRequest 10, // 32: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:input_type -> provisionerd.CancelAcquire
6, // 33: provisionerd.ProvisionerDaemon.UpdateJob:input_type -> provisionerd.UpdateJobRequest 8, // 33: provisionerd.ProvisionerDaemon.CommitQuota:input_type -> provisionerd.CommitQuotaRequest
3, // 34: provisionerd.ProvisionerDaemon.FailJob:input_type -> provisionerd.FailedJob 6, // 34: provisionerd.ProvisionerDaemon.UpdateJob:input_type -> provisionerd.UpdateJobRequest
4, // 35: provisionerd.ProvisionerDaemon.CompleteJob:input_type -> provisionerd.CompletedJob 3, // 35: provisionerd.ProvisionerDaemon.FailJob:input_type -> provisionerd.FailedJob
2, // 36: provisionerd.ProvisionerDaemon.AcquireJob:output_type -> provisionerd.AcquiredJob 4, // 36: provisionerd.ProvisionerDaemon.CompleteJob:input_type -> provisionerd.CompletedJob
2, // 37: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:output_type -> provisionerd.AcquiredJob 2, // 37: provisionerd.ProvisionerDaemon.AcquireJob:output_type -> provisionerd.AcquiredJob
9, // 38: provisionerd.ProvisionerDaemon.CommitQuota:output_type -> provisionerd.CommitQuotaResponse 2, // 38: provisionerd.ProvisionerDaemon.AcquireJobWithCancel:output_type -> provisionerd.AcquiredJob
7, // 39: provisionerd.ProvisionerDaemon.UpdateJob:output_type -> provisionerd.UpdateJobResponse 9, // 39: provisionerd.ProvisionerDaemon.CommitQuota:output_type -> provisionerd.CommitQuotaResponse
1, // 40: provisionerd.ProvisionerDaemon.FailJob:output_type -> provisionerd.Empty 7, // 40: provisionerd.ProvisionerDaemon.UpdateJob:output_type -> provisionerd.UpdateJobResponse
1, // 41: provisionerd.ProvisionerDaemon.CompleteJob:output_type -> provisionerd.Empty 1, // 41: provisionerd.ProvisionerDaemon.FailJob:output_type -> provisionerd.Empty
36, // [36:42] is the sub-list for method output_type 1, // 42: provisionerd.ProvisionerDaemon.CompleteJob:output_type -> provisionerd.Empty
30, // [30:36] is the sub-list for method input_type 37, // [37:43] is the sub-list for method output_type
30, // [30:30] is the sub-list for extension type_name 31, // [31:37] is the sub-list for method input_type
30, // [30:30] is the sub-list for extension extendee 31, // [31:31] is the sub-list for extension type_name
0, // [0:30] is the sub-list for field type_name 31, // [31:31] is the sub-list for extension extendee
0, // [0:31] is the sub-list for field type_name
} }
func init() { file_provisionerd_proto_provisionerd_proto_init() } func init() { file_provisionerd_proto_provisionerd_proto_init() }

View File

@ -77,7 +77,8 @@ message CompletedJob {
repeated provisioner.Resource start_resources = 1; repeated provisioner.Resource start_resources = 1;
repeated provisioner.Resource stop_resources = 2; repeated provisioner.Resource stop_resources = 2;
repeated provisioner.RichParameter rich_parameters = 3; repeated provisioner.RichParameter rich_parameters = 3;
repeated string external_auth_providers = 4; repeated string external_auth_providers_names = 4;
repeated provisioner.ExternalAuthProviderResource external_auth_providers = 5;
} }
message TemplateDryRun { message TemplateDryRun {
repeated provisioner.Resource resources = 1; repeated provisioner.Resource resources = 1;

View File

@ -4,10 +4,10 @@ import "github.com/coder/coder/v2/apiversion"
const ( const (
CurrentMajor = 1 CurrentMajor = 1
CurrentMinor = 0 CurrentMinor = 1
) )
// VersionCurrent is the current provisionerd API version. // CurrentVersion is the current provisionerd API version.
// Breaking changes to the provisionerd API **MUST** increment // Breaking changes to the provisionerd API **MUST** increment
// CurrentMajor above. // CurrentMajor above.
var VersionCurrent = apiversion.New(CurrentMajor, CurrentMinor) var CurrentVersion = apiversion.New(CurrentMajor, CurrentMinor)

View File

@ -564,14 +564,21 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
return nil, r.failedJobf("template import provision for stop: %s", err) return nil, r.failedJobf("template import provision for stop: %s", err)
} }
// For backwards compatibility with older versions of coderd
externalAuthProviderNames := make([]string, 0, len(startProvision.ExternalAuthProviders))
for _, it := range startProvision.ExternalAuthProviders {
externalAuthProviderNames = append(externalAuthProviderNames, it.Id)
}
return &proto.CompletedJob{ return &proto.CompletedJob{
JobId: r.job.JobId, JobId: r.job.JobId,
Type: &proto.CompletedJob_TemplateImport_{ Type: &proto.CompletedJob_TemplateImport_{
TemplateImport: &proto.CompletedJob_TemplateImport{ TemplateImport: &proto.CompletedJob_TemplateImport{
StartResources: startProvision.Resources, StartResources: startProvision.Resources,
StopResources: stopProvision.Resources, StopResources: stopProvision.Resources,
RichParameters: startProvision.Parameters, RichParameters: startProvision.Parameters,
ExternalAuthProviders: startProvision.ExternalAuthProviders, ExternalAuthProvidersNames: externalAuthProviderNames,
ExternalAuthProviders: startProvision.ExternalAuthProviders,
}, },
}, },
}, nil }, nil
@ -629,7 +636,7 @@ func (r *Runner) runTemplateImportParse(ctx context.Context) (
type templateImportProvision struct { type templateImportProvision struct {
Resources []*sdkproto.Resource Resources []*sdkproto.Resource
Parameters []*sdkproto.RichParameter Parameters []*sdkproto.RichParameter
ExternalAuthProviders []string ExternalAuthProviders []*sdkproto.ExternalAuthProviderResource
} }
// Performs a dry-run provision when importing a template. // Performs a dry-run provision when importing a template.

File diff suppressed because it is too large Load Diff

View File

@ -81,6 +81,11 @@ message InstanceIdentityAuth {
string instance_id = 1; string instance_id = 1;
} }
message ExternalAuthProviderResource {
string id = 1;
bool optional = 2;
}
message ExternalAuthProvider { message ExternalAuthProvider {
string id = 1; string id = 1;
string access_token = 2; string access_token = 2;
@ -255,7 +260,7 @@ message PlanComplete {
string error = 1; string error = 1;
repeated Resource resources = 2; repeated Resource resources = 2;
repeated RichParameter parameters = 3; repeated RichParameter parameters = 3;
repeated string external_auth_providers = 4; repeated ExternalAuthProviderResource external_auth_providers = 4;
} }
// ApplyRequest asks the provisioner to apply the changes. Apply MUST be preceded by a successful plan request/response // ApplyRequest asks the provisioner to apply the changes. Apply MUST be preceded by a successful plan request/response
@ -270,7 +275,7 @@ message ApplyComplete {
string error = 2; string error = 2;
repeated Resource resources = 3; repeated Resource resources = 3;
repeated RichParameter parameters = 4; repeated RichParameter parameters = 4;
repeated string external_auth_providers = 5; repeated ExternalAuthProviderResource external_auth_providers = 5;
} }
// CancelRequest requests that the previous request be canceled gracefully. // CancelRequest requests that the previous request be canceled gracefully.

View File

@ -94,6 +94,11 @@ export interface InstanceIdentityAuth {
instanceId: string; instanceId: string;
} }
export interface ExternalAuthProviderResource {
id: string;
optional: boolean;
}
export interface ExternalAuthProvider { export interface ExternalAuthProvider {
id: string; id: string;
accessToken: string; accessToken: string;
@ -259,7 +264,7 @@ export interface PlanComplete {
error: string; error: string;
resources: Resource[]; resources: Resource[];
parameters: RichParameter[]; parameters: RichParameter[];
externalAuthProviders: string[]; externalAuthProviders: ExternalAuthProviderResource[];
} }
/** /**
@ -276,7 +281,7 @@ export interface ApplyComplete {
error: string; error: string;
resources: Resource[]; resources: Resource[];
parameters: RichParameter[]; parameters: RichParameter[];
externalAuthProviders: string[]; externalAuthProviders: ExternalAuthProviderResource[];
} }
/** CancelRequest requests that the previous request be canceled gracefully. */ /** CancelRequest requests that the previous request be canceled gracefully. */
@ -465,6 +470,21 @@ export const InstanceIdentityAuth = {
}, },
}; };
export const ExternalAuthProviderResource = {
encode(
message: ExternalAuthProviderResource,
writer: _m0.Writer = _m0.Writer.create(),
): _m0.Writer {
if (message.id !== "") {
writer.uint32(10).string(message.id);
}
if (message.optional === true) {
writer.uint32(16).bool(message.optional);
}
return writer;
},
};
export const ExternalAuthProvider = { export const ExternalAuthProvider = {
encode( encode(
message: ExternalAuthProvider, message: ExternalAuthProvider,
@ -897,7 +917,10 @@ export const PlanComplete = {
RichParameter.encode(v!, writer.uint32(26).fork()).ldelim(); RichParameter.encode(v!, writer.uint32(26).fork()).ldelim();
} }
for (const v of message.externalAuthProviders) { for (const v of message.externalAuthProviders) {
writer.uint32(34).string(v!); ExternalAuthProviderResource.encode(
v!,
writer.uint32(34).fork(),
).ldelim();
} }
return writer; return writer;
}, },
@ -933,7 +956,10 @@ export const ApplyComplete = {
RichParameter.encode(v!, writer.uint32(34).fork()).ldelim(); RichParameter.encode(v!, writer.uint32(34).fork()).ldelim();
} }
for (const v of message.externalAuthProviders) { for (const v of message.externalAuthProviders) {
writer.uint32(42).string(v!); ExternalAuthProviderResource.encode(
v!,
writer.uint32(42).fork(),
).ldelim();
} }
return writer; return writer;
}, },

View File

@ -1187,6 +1187,7 @@ export interface TemplateVersionExternalAuth {
readonly display_icon: string; readonly display_icon: string;
readonly authenticate_url: string; readonly authenticate_url: string;
readonly authenticated: boolean; readonly authenticated: boolean;
readonly optional?: boolean;
} }
// From codersdk/templateversions.go // From codersdk/templateversions.go