diff --git a/cli/cliui/gitauth.go b/cli/cliui/gitauth.go
new file mode 100644
index 0000000000000..7b4bd6f30e264
--- /dev/null
+++ b/cli/cliui/gitauth.go
@@ -0,0 +1,72 @@
+package cliui
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "time"
+
+ "github.com/briandowns/spinner"
+
+ "github.com/coder/coder/codersdk"
+)
+
+type GitAuthOptions struct {
+ Fetch func(context.Context) ([]codersdk.TemplateVersionGitAuth, error)
+ FetchInterval time.Duration
+}
+
+func GitAuth(ctx context.Context, writer io.Writer, opts GitAuthOptions) error {
+ if opts.FetchInterval == 0 {
+ opts.FetchInterval = 500 * time.Millisecond
+ }
+ gitAuth, err := opts.Fetch(ctx)
+ if err != nil {
+ return err
+ }
+
+ spin := spinner.New(spinner.CharSets[78], 100*time.Millisecond, spinner.WithColor("fgHiGreen"))
+ spin.Writer = writer
+ spin.ForceOutput = true
+ spin.Suffix = " Waiting for Git authentication..."
+ defer spin.Stop()
+
+ ticker := time.NewTicker(opts.FetchInterval)
+ defer ticker.Stop()
+ for _, auth := range gitAuth {
+ if auth.Authenticated {
+ return nil
+ }
+
+ _, _ = fmt.Fprintf(writer, "You must authenticate with %s to create a workspace with this template. Visit:\n\n\t%s\n\n", auth.Type.Pretty(), auth.AuthenticateURL)
+
+ ticker.Reset(opts.FetchInterval)
+ spin.Start()
+ for {
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-ticker.C:
+ }
+ gitAuth, err := opts.Fetch(ctx)
+ if err != nil {
+ return err
+ }
+ var authed bool
+ for _, a := range gitAuth {
+ if !a.Authenticated || a.ID != auth.ID {
+ continue
+ }
+ authed = true
+ break
+ }
+ // The user authenticated with the provider!
+ if authed {
+ break
+ }
+ }
+ spin.Stop()
+ _, _ = fmt.Fprintf(writer, "Successfully authenticated with %s!\n\n", auth.Type.Pretty())
+ }
+ return nil
+}
diff --git a/cli/cliui/gitauth_test.go b/cli/cliui/gitauth_test.go
new file mode 100644
index 0000000000000..de2198798e8d3
--- /dev/null
+++ b/cli/cliui/gitauth_test.go
@@ -0,0 +1,55 @@
+package cliui_test
+
+import (
+ "context"
+ "net/url"
+ "sync/atomic"
+ "testing"
+ "time"
+
+ "github.com/spf13/cobra"
+ "github.com/stretchr/testify/assert"
+
+ "github.com/coder/coder/cli/cliui"
+ "github.com/coder/coder/codersdk"
+ "github.com/coder/coder/pty/ptytest"
+ "github.com/coder/coder/testutil"
+)
+
+func TestGitAuth(t *testing.T) {
+ t.Parallel()
+
+ ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
+ defer cancel()
+
+ ptty := ptytest.New(t)
+ cmd := &cobra.Command{
+ RunE: func(cmd *cobra.Command, args []string) error {
+ var fetched atomic.Bool
+ return cliui.GitAuth(cmd.Context(), cmd.OutOrStdout(), cliui.GitAuthOptions{
+ Fetch: func(ctx context.Context) ([]codersdk.TemplateVersionGitAuth, error) {
+ defer fetched.Store(true)
+ return []codersdk.TemplateVersionGitAuth{{
+ ID: "github",
+ Type: codersdk.GitProviderGitHub,
+ Authenticated: fetched.Load(),
+ AuthenticateURL: "https://example.com/gitauth/github?redirect=" + url.QueryEscape("/gitauth?notify"),
+ }}, nil
+ },
+ FetchInterval: time.Millisecond,
+ })
+ },
+ }
+ cmd.SetOutput(ptty.Output())
+ cmd.SetIn(ptty.Input())
+ done := make(chan struct{})
+ go func() {
+ defer close(done)
+ err := cmd.Execute()
+ assert.NoError(t, err)
+ }()
+ ptty.ExpectMatchContext(ctx, "You must authenticate with")
+ ptty.ExpectMatchContext(ctx, "https://example.com/gitauth/github")
+ ptty.ExpectMatchContext(ctx, "Successfully authenticated with GitHub")
+ <-done
+}
diff --git a/cli/create.go b/cli/create.go
index 4b1f306267e81..72f84d123a3a4 100644
--- a/cli/create.go
+++ b/cli/create.go
@@ -1,6 +1,7 @@
package cli
import (
+ "context"
"fmt"
"io"
"time"
@@ -324,6 +325,15 @@ PromptRichParamLoop:
_, _ = fmt.Fprintln(cmd.OutOrStdout())
}
+ err = cliui.GitAuth(ctx, cmd.OutOrStdout(), cliui.GitAuthOptions{
+ Fetch: func(ctx context.Context) ([]codersdk.TemplateVersionGitAuth, error) {
+ return client.TemplateVersionGitAuth(ctx, templateVersion.ID)
+ },
+ })
+ if err != nil {
+ return nil, xerrors.Errorf("template version git auth: %w", err)
+ }
+
// Run a dry-run with the given parameters to check correctness
dryRun, err := client.CreateTemplateVersionDryRun(cmd.Context(), templateVersion.ID, codersdk.CreateTemplateVersionDryRunRequest{
WorkspaceName: args.NewWorkspaceName,
diff --git a/cli/create_test.go b/cli/create_test.go
index 5445db51cdd38..0cdbf45839bcf 100644
--- a/cli/create_test.go
+++ b/cli/create_test.go
@@ -3,15 +3,21 @@ package cli_test
import (
"context"
"fmt"
+ "net/http"
+ "net/url"
"os"
+ "regexp"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "golang.org/x/oauth2"
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
+ "github.com/coder/coder/coderd/database"
+ "github.com/coder/coder/coderd/gitauth"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/provisioner/echo"
"github.com/coder/coder/provisionersdk/proto"
@@ -603,6 +609,61 @@ func TestCreateValidateRichParameters(t *testing.T) {
})
}
+func TestCreateWithGitAuth(t *testing.T) {
+ t.Parallel()
+ echoResponses := &echo.Responses{
+ Parse: echo.ParseComplete,
+ ProvisionPlan: []*proto.Provision_Response{
+ {
+ Type: &proto.Provision_Response_Complete{
+ Complete: &proto.Provision_Complete{
+ GitAuthProviders: []string{"github"},
+ },
+ },
+ },
+ },
+ ProvisionApply: []*proto.Provision_Response{{
+ Type: &proto.Provision_Response_Complete{
+ Complete: &proto.Provision_Complete{},
+ },
+ }},
+ }
+
+ client := coderdtest.New(t, &coderdtest.Options{
+ GitAuthConfigs: []*gitauth.Config{{
+ OAuth2Config: &oauth2Config{},
+ ID: "github",
+ Regex: regexp.MustCompile(`github\.com`),
+ Type: codersdk.GitProviderGitHub,
+ }},
+ IncludeProvisionerDaemon: true,
+ })
+ user := coderdtest.CreateFirstUser(t, client)
+ version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, echoResponses)
+ coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
+ template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
+
+ cmd, root := clitest.New(t, "create", "my-workspace", "--template", template.Name)
+ clitest.SetupConfig(t, client, root)
+ doneChan := make(chan struct{})
+ pty := ptytest.New(t)
+ cmd.SetIn(pty.Input())
+ cmd.SetOut(pty.Output())
+ go func() {
+ defer close(doneChan)
+ err := cmd.Execute()
+ assert.NoError(t, err)
+ }()
+
+ pty.ExpectMatch("You must authenticate with GitHub to create a workspace")
+ resp := coderdtest.RequestGitAuthCallback(t, "github", client)
+ _ = resp.Body.Close()
+ require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
+ pty.ExpectMatch("Confirm create?")
+ pty.WriteLine("yes")
+ <-doneChan
+}
+
func createTestParseResponseWithDefault(defaultValue string) []*proto.Parse_Response {
return []*proto.Parse_Response{{
Type: &proto.Parse_Response_Complete{
@@ -638,3 +699,31 @@ func createTestParseResponseWithDefault(defaultValue string) []*proto.Parse_Resp
},
}}
}
+
+type oauth2Config struct{}
+
+func (*oauth2Config) AuthCodeURL(state string, _ ...oauth2.AuthCodeOption) string {
+ return "/?state=" + url.QueryEscape(state)
+}
+
+func (*oauth2Config) Exchange(context.Context, string, ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
+ return &oauth2.Token{
+ AccessToken: "token",
+ RefreshToken: "refresh",
+ Expiry: database.Now().Add(time.Hour),
+ }, nil
+}
+
+func (*oauth2Config) TokenSource(context.Context, *oauth2.Token) oauth2.TokenSource {
+ return &oauth2TokenSource{}
+}
+
+type oauth2TokenSource struct{}
+
+func (*oauth2TokenSource) Token() (*oauth2.Token, error) {
+ return &oauth2.Token{
+ AccessToken: "token",
+ RefreshToken: "refresh",
+ Expiry: database.Now().Add(time.Hour),
+ }, nil
+}
diff --git a/cmd/cliui/main.go b/cmd/cliui/main.go
index b7a8e004ce31d..c25da0a84d660 100644
--- a/cmd/cliui/main.go
+++ b/cmd/cliui/main.go
@@ -5,8 +5,10 @@ import (
"errors"
"fmt"
"io"
+ "net/url"
"os"
"strings"
+ "sync/atomic"
"time"
"github.com/spf13/cobra"
@@ -235,6 +237,41 @@ func main() {
},
})
+ root.AddCommand(&cobra.Command{
+ Use: "git-auth",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ var count atomic.Int32
+ var githubAuthed atomic.Bool
+ var gitlabAuthed atomic.Bool
+ go func() {
+ // Sleep to display the loading indicator.
+ time.Sleep(time.Second)
+ // Swap to true to display success and move onto GitLab.
+ githubAuthed.Store(true)
+ // Show the loading indicator again...
+ time.Sleep(time.Second * 2)
+ // Complete the auth!
+ gitlabAuthed.Store(true)
+ }()
+ return cliui.GitAuth(cmd.Context(), cmd.OutOrStdout(), cliui.GitAuthOptions{
+ Fetch: func(ctx context.Context) ([]codersdk.TemplateVersionGitAuth, error) {
+ count.Add(1)
+ return []codersdk.TemplateVersionGitAuth{{
+ ID: "github",
+ Type: codersdk.GitProviderGitHub,
+ Authenticated: githubAuthed.Load(),
+ AuthenticateURL: "https://example.com/gitauth/github?redirect=" + url.QueryEscape("/gitauth?notify"),
+ }, {
+ ID: "gitlab",
+ Type: codersdk.GitProviderGitLab,
+ Authenticated: gitlabAuthed.Load(),
+ AuthenticateURL: "https://example.com/gitauth/gitlab?redirect=" + url.QueryEscape("/gitauth?notify"),
+ }}, nil
+ },
+ })
+ },
+ })
+
err := root.Execute()
if err != nil {
_, _ = fmt.Println(err.Error())
diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go
index d4e1236849534..aa281e9195c09 100644
--- a/coderd/apidoc/docs.go
+++ b/coderd/apidoc/docs.go
@@ -2485,6 +2485,44 @@ const docTemplate = `{
}
}
},
+ "/templateversions/{templateversion}/gitauth": {
+ "get": {
+ "security": [
+ {
+ "CoderSessionToken": []
+ }
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "Templates"
+ ],
+ "summary": "Get git auth by template version",
+ "operationId": "get-git-auth-by-template-version",
+ "parameters": [
+ {
+ "type": "string",
+ "format": "uuid",
+ "description": "Template version ID",
+ "name": "templateversion",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/codersdk.TemplateVersionGitAuth"
+ }
+ }
+ }
+ }
+ }
+ },
"/templateversions/{templateversion}/logs": {
"get": {
"security": [
@@ -6565,6 +6603,21 @@ const docTemplate = `{
}
}
},
+ "codersdk.GitProvider": {
+ "type": "string",
+ "enum": [
+ "azure-devops",
+ "github",
+ "gitlab",
+ "bitbucket"
+ ],
+ "x-enum-varnames": [
+ "GitProviderAzureDevops",
+ "GitProviderGitHub",
+ "GitProviderGitLab",
+ "GitProviderBitBucket"
+ ]
+ },
"codersdk.GitSSHKey": {
"type": "object",
"properties": {
@@ -7648,6 +7701,23 @@ const docTemplate = `{
}
}
},
+ "codersdk.TemplateVersionGitAuth": {
+ "type": "object",
+ "properties": {
+ "authenticate_url": {
+ "type": "string"
+ },
+ "authenticated": {
+ "type": "boolean"
+ },
+ "id": {
+ "type": "string"
+ },
+ "type": {
+ "$ref": "#/definitions/codersdk.GitProvider"
+ }
+ }
+ },
"codersdk.TemplateVersionParameter": {
"type": "object",
"properties": {
diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json
index 894a2d0b6cafd..0f57dc755d0e9 100644
--- a/coderd/apidoc/swagger.json
+++ b/coderd/apidoc/swagger.json
@@ -2183,6 +2183,40 @@
}
}
},
+ "/templateversions/{templateversion}/gitauth": {
+ "get": {
+ "security": [
+ {
+ "CoderSessionToken": []
+ }
+ ],
+ "produces": ["application/json"],
+ "tags": ["Templates"],
+ "summary": "Get git auth by template version",
+ "operationId": "get-git-auth-by-template-version",
+ "parameters": [
+ {
+ "type": "string",
+ "format": "uuid",
+ "description": "Template version ID",
+ "name": "templateversion",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/codersdk.TemplateVersionGitAuth"
+ }
+ }
+ }
+ }
+ }
+ },
"/templateversions/{templateversion}/logs": {
"get": {
"security": [
@@ -5875,6 +5909,16 @@
}
}
},
+ "codersdk.GitProvider": {
+ "type": "string",
+ "enum": ["azure-devops", "github", "gitlab", "bitbucket"],
+ "x-enum-varnames": [
+ "GitProviderAzureDevops",
+ "GitProviderGitHub",
+ "GitProviderGitLab",
+ "GitProviderBitBucket"
+ ]
+ },
"codersdk.GitSSHKey": {
"type": "object",
"properties": {
@@ -6877,6 +6921,23 @@
}
}
},
+ "codersdk.TemplateVersionGitAuth": {
+ "type": "object",
+ "properties": {
+ "authenticate_url": {
+ "type": "string"
+ },
+ "authenticated": {
+ "type": "boolean"
+ },
+ "id": {
+ "type": "string"
+ },
+ "type": {
+ "$ref": "#/definitions/codersdk.GitProvider"
+ }
+ }
+ },
"codersdk.TemplateVersionParameter": {
"type": "object",
"properties": {
diff --git a/coderd/coderd.go b/coderd/coderd.go
index bc8d39bb587fd..79306dcd03481 100644
--- a/coderd/coderd.go
+++ b/coderd/coderd.go
@@ -489,6 +489,7 @@ func New(options *Options) *API {
r.Get("/schema", api.templateVersionSchema)
r.Get("/parameters", api.templateVersionParameters)
r.Get("/rich-parameters", api.templateVersionRichParameters)
+ r.Get("/gitauth", api.templateVersionGitAuth)
r.Get("/variables", api.templateVersionVariables)
r.Get("/resources", api.templateVersionResources)
r.Get("/logs", api.templateVersionLogs)
@@ -805,12 +806,18 @@ func (api *API) CreateInMemoryProvisionerDaemon(ctx context.Context, debounce ti
}
mux := drpcmux.New()
+
+ gitAuthProviders := make([]string, 0, len(api.GitAuthConfigs))
+ for _, cfg := range api.GitAuthConfigs {
+ gitAuthProviders = append(gitAuthProviders, cfg.ID)
+ }
err = proto.DRPCRegisterProvisionerDaemon(mux, &provisionerdserver.Server{
AccessURL: api.AccessURL,
ID: daemon.ID,
Database: api.Database,
Pubsub: api.Pubsub,
Provisioners: daemon.Provisioners,
+ GitAuthProviders: gitAuthProviders,
Telemetry: api.Telemetry,
Tags: tags,
QuotaCommitter: &api.QuotaCommitter,
diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go
index 405c060bf8d3c..2fda13ca03aa5 100644
--- a/coderd/coderdtest/coderdtest.go
+++ b/coderd/coderdtest/coderdtest.go
@@ -717,6 +717,33 @@ func MustWorkspace(t *testing.T, client *codersdk.Client, workspaceID uuid.UUID)
return ws
}
+// RequestGitAuthCallback makes a request with the proper OAuth2 state cookie
+// to the git auth callback endpoint.
+func RequestGitAuthCallback(t *testing.T, providerID string, client *codersdk.Client) *http.Response {
+ client.HTTPClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
+ return http.ErrUseLastResponse
+ }
+ state := "somestate"
+ oauthURL, err := client.URL.Parse(fmt.Sprintf("/gitauth/%s/callback?code=asd&state=%s", providerID, state))
+ require.NoError(t, err)
+ req, err := http.NewRequestWithContext(context.Background(), "GET", oauthURL.String(), nil)
+ require.NoError(t, err)
+ req.AddCookie(&http.Cookie{
+ Name: codersdk.OAuth2StateCookie,
+ Value: state,
+ })
+ req.AddCookie(&http.Cookie{
+ Name: codersdk.SessionTokenCookie,
+ Value: client.SessionToken(),
+ })
+ res, err := client.HTTPClient.Do(req)
+ require.NoError(t, err)
+ t.Cleanup(func() {
+ _ = res.Body.Close()
+ })
+ return res
+}
+
// NewGoogleInstanceIdentity returns a metadata client and ID token validator for faking
// instance authentication for Google Cloud.
// nolint:revive
diff --git a/coderd/database/dbauthz/querier.go b/coderd/database/dbauthz/querier.go
index ca2610e52ed63..691f680e42feb 100644
--- a/coderd/database/dbauthz/querier.go
+++ b/coderd/database/dbauthz/querier.go
@@ -889,6 +889,28 @@ func (q *querier) UpdateTemplateVersionDescriptionByJobID(ctx context.Context, a
return q.db.UpdateTemplateVersionDescriptionByJobID(ctx, arg)
}
+func (q *querier) UpdateTemplateVersionGitAuthProvidersByJobID(ctx context.Context, arg database.UpdateTemplateVersionGitAuthProvidersByJobIDParams) error {
+ // An actor is allowed to update the template version git auth providers if they are authorized to update the template.
+ tv, err := q.db.GetTemplateVersionByJobID(ctx, arg.JobID)
+ if err != nil {
+ return err
+ }
+ var obj rbac.Objecter
+ if !tv.TemplateID.Valid {
+ obj = rbac.ResourceTemplate.InOrg(tv.OrganizationID)
+ } else {
+ tpl, err := q.db.GetTemplateByID(ctx, tv.TemplateID.UUID)
+ if err != nil {
+ return err
+ }
+ obj = tpl
+ }
+ if err := q.authorizeContext(ctx, rbac.ActionUpdate, obj); err != nil {
+ return err
+ }
+ return q.db.UpdateTemplateVersionGitAuthProvidersByJobID(ctx, arg)
+}
+
func (q *querier) GetTemplateGroupRoles(ctx context.Context, id uuid.UUID) ([]database.TemplateGroup, error) {
// An actor is authorized to read template group roles if they are authorized to read the template.
template, err := q.db.GetTemplateByID(ctx, id)
@@ -1103,11 +1125,11 @@ func (q *querier) InsertGitAuthLink(ctx context.Context, arg database.InsertGitA
return insert(q.log, q.auth, rbac.ResourceUserData.WithOwner(arg.UserID.String()).WithID(arg.UserID), q.db.InsertGitAuthLink)(ctx, arg)
}
-func (q *querier) UpdateGitAuthLink(ctx context.Context, arg database.UpdateGitAuthLinkParams) error {
+func (q *querier) UpdateGitAuthLink(ctx context.Context, arg database.UpdateGitAuthLinkParams) (database.GitAuthLink, error) {
fetch := func(ctx context.Context, arg database.UpdateGitAuthLinkParams) (database.GitAuthLink, error) {
return q.db.GetGitAuthLink(ctx, database.GetGitAuthLinkParams{UserID: arg.UserID, ProviderID: arg.ProviderID})
}
- return update(q.log, q.auth, fetch, q.db.UpdateGitAuthLink)(ctx, arg)
+ return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateGitAuthLink)(ctx, arg)
}
func (q *querier) UpdateUserLink(ctx context.Context, arg database.UpdateUserLinkParams) (database.UserLink, error) {
diff --git a/coderd/database/dbauthz/querier_test.go b/coderd/database/dbauthz/querier_test.go
index 11d03c9be3718..0f7e7c4ffa45d 100644
--- a/coderd/database/dbauthz/querier_test.go
+++ b/coderd/database/dbauthz/querier_test.go
@@ -736,6 +736,18 @@ func (s *MethodTestSuite) TestTemplate() {
Readme: "foo",
}).Asserts(t1, rbac.ActionUpdate).Returns()
}))
+ s.Run("UpdateTemplateVersionGitAuthProvidersByJobID", s.Subtest(func(db database.Store, check *expects) {
+ jobID := uuid.New()
+ t1 := dbgen.Template(s.T(), db, database.Template{})
+ _ = dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
+ TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true},
+ JobID: jobID,
+ })
+ check.Args(database.UpdateTemplateVersionGitAuthProvidersByJobIDParams{
+ JobID: jobID,
+ GitAuthProviders: []string{},
+ }).Asserts(t1, rbac.ActionUpdate).Returns()
+ }))
}
func (s *MethodTestSuite) TestUser() {
@@ -881,9 +893,13 @@ func (s *MethodTestSuite) TestUser() {
s.Run("UpdateGitAuthLink", s.Subtest(func(db database.Store, check *expects) {
link := dbgen.GitAuthLink(s.T(), db, database.GitAuthLink{})
check.Args(database.UpdateGitAuthLinkParams{
- ProviderID: link.ProviderID,
- UserID: link.UserID,
- }).Asserts(link, rbac.ActionUpdate).Returns()
+ ProviderID: link.ProviderID,
+ UserID: link.UserID,
+ OAuthAccessToken: link.OAuthAccessToken,
+ OAuthRefreshToken: link.OAuthRefreshToken,
+ OAuthExpiry: link.OAuthExpiry,
+ UpdatedAt: link.UpdatedAt,
+ }).Asserts(link, rbac.ActionUpdate).Returns(link)
}))
s.Run("UpdateUserLink", s.Subtest(func(db database.Store, check *expects) {
link := dbgen.UserLink(s.T(), db, database.UserLink{})
diff --git a/coderd/database/dbfake/databasefake.go b/coderd/database/dbfake/databasefake.go
index 45cf402a98ac3..16c0fbe5bd3ba 100644
--- a/coderd/database/dbfake/databasefake.go
+++ b/coderd/database/dbfake/databasefake.go
@@ -3273,6 +3273,26 @@ func (q *fakeQuerier) UpdateTemplateVersionDescriptionByJobID(_ context.Context,
return sql.ErrNoRows
}
+func (q *fakeQuerier) UpdateTemplateVersionGitAuthProvidersByJobID(_ context.Context, arg database.UpdateTemplateVersionGitAuthProvidersByJobIDParams) error {
+ if err := validateDatabaseType(arg); err != nil {
+ return err
+ }
+
+ q.mutex.Lock()
+ defer q.mutex.Unlock()
+
+ for index, templateVersion := range q.templateVersions {
+ if templateVersion.JobID != arg.JobID {
+ continue
+ }
+ templateVersion.GitAuthProviders = arg.GitAuthProviders
+ templateVersion.UpdatedAt = arg.UpdatedAt
+ q.templateVersions[index] = templateVersion
+ return nil
+ }
+ return sql.ErrNoRows
+}
+
func (q *fakeQuerier) UpdateWorkspaceAgentConnectionByID(_ context.Context, arg database.UpdateWorkspaceAgentConnectionByIDParams) error {
if err := validateDatabaseType(arg); err != nil {
return err
@@ -4287,9 +4307,9 @@ func (q *fakeQuerier) InsertGitAuthLink(_ context.Context, arg database.InsertGi
return gitAuthLink, nil
}
-func (q *fakeQuerier) UpdateGitAuthLink(_ context.Context, arg database.UpdateGitAuthLinkParams) error {
+func (q *fakeQuerier) UpdateGitAuthLink(_ context.Context, arg database.UpdateGitAuthLinkParams) (database.GitAuthLink, error) {
if err := validateDatabaseType(arg); err != nil {
- return err
+ return database.GitAuthLink{}, err
}
q.mutex.Lock()
@@ -4306,8 +4326,10 @@ func (q *fakeQuerier) UpdateGitAuthLink(_ context.Context, arg database.UpdateGi
gitAuthLink.OAuthRefreshToken = arg.OAuthRefreshToken
gitAuthLink.OAuthExpiry = arg.OAuthExpiry
q.gitAuthLinks[index] = gitAuthLink
+
+ return gitAuthLink, nil
}
- return nil
+ return database.GitAuthLink{}, sql.ErrNoRows
}
func (q *fakeQuerier) GetQuotaAllowanceForUser(_ context.Context, userID uuid.UUID) (int64, error) {
diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql
index 2137be816ef84..29316b88633c6 100644
--- a/coderd/database/dump.sql
+++ b/coderd/database/dump.sql
@@ -417,9 +417,12 @@ CREATE TABLE template_versions (
name character varying(64) NOT NULL,
readme character varying(1048576) NOT NULL,
job_id uuid NOT NULL,
- created_by uuid NOT NULL
+ created_by uuid NOT NULL,
+ git_auth_providers text[]
);
+COMMENT ON COLUMN template_versions.git_auth_providers IS 'IDs of Git auth providers for a specific template version';
+
CREATE TABLE templates (
id uuid NOT NULL,
created_at timestamp with time zone NOT NULL,
diff --git a/coderd/database/migrations/000100_template_version_gitauth.down.sql b/coderd/database/migrations/000100_template_version_gitauth.down.sql
new file mode 100644
index 0000000000000..099f9bdefc54c
--- /dev/null
+++ b/coderd/database/migrations/000100_template_version_gitauth.down.sql
@@ -0,0 +1,2 @@
+ALTER TABLE template_versions
+ DROP COLUMN git_auth_providers;
diff --git a/coderd/database/migrations/000100_template_version_gitauth.up.sql b/coderd/database/migrations/000100_template_version_gitauth.up.sql
new file mode 100644
index 0000000000000..883190f979782
--- /dev/null
+++ b/coderd/database/migrations/000100_template_version_gitauth.up.sql
@@ -0,0 +1,4 @@
+ALTER TABLE template_versions
+ ADD COLUMN git_auth_providers text[];
+
+COMMENT ON COLUMN template_versions.git_auth_providers IS 'IDs of Git auth providers for a specific template version';
diff --git a/coderd/database/models.go b/coderd/database/models.go
index 18276551a488e..21e22566fc40b 100644
--- a/coderd/database/models.go
+++ b/coderd/database/models.go
@@ -1433,6 +1433,8 @@ type TemplateVersion struct {
Readme string `db:"readme" json:"readme"`
JobID uuid.UUID `db:"job_id" json:"job_id"`
CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
+ // IDs of Git auth providers for a specific template version
+ GitAuthProviders []string `db:"git_auth_providers" json:"git_auth_providers"`
}
type TemplateVersionParameter struct {
diff --git a/coderd/database/querier.go b/coderd/database/querier.go
index 4c2c9da79ab4a..a2849211b60be 100644
--- a/coderd/database/querier.go
+++ b/coderd/database/querier.go
@@ -176,7 +176,7 @@ type sqlcQuerier interface {
ParameterValue(ctx context.Context, id uuid.UUID) (ParameterValue, error)
ParameterValues(ctx context.Context, arg ParameterValuesParams) ([]ParameterValue, error)
UpdateAPIKeyByID(ctx context.Context, arg UpdateAPIKeyByIDParams) error
- UpdateGitAuthLink(ctx context.Context, arg UpdateGitAuthLinkParams) error
+ UpdateGitAuthLink(ctx context.Context, arg UpdateGitAuthLinkParams) (GitAuthLink, error)
UpdateGitSSHKey(ctx context.Context, arg UpdateGitSSHKeyParams) (GitSSHKey, error)
UpdateGroupByID(ctx context.Context, arg UpdateGroupByIDParams) (Group, error)
UpdateMemberRoles(ctx context.Context, arg UpdateMemberRolesParams) (OrganizationMember, error)
@@ -190,6 +190,7 @@ type sqlcQuerier interface {
UpdateTemplateMetaByID(ctx context.Context, arg UpdateTemplateMetaByIDParams) (Template, error)
UpdateTemplateVersionByID(ctx context.Context, arg UpdateTemplateVersionByIDParams) error
UpdateTemplateVersionDescriptionByJobID(ctx context.Context, arg UpdateTemplateVersionDescriptionByJobIDParams) error
+ UpdateTemplateVersionGitAuthProvidersByJobID(ctx context.Context, arg UpdateTemplateVersionGitAuthProvidersByJobIDParams) error
UpdateUserDeletedByID(ctx context.Context, arg UpdateUserDeletedByIDParams) error
UpdateUserHashedPassword(ctx context.Context, arg UpdateUserHashedPasswordParams) error
UpdateUserLastSeenAt(ctx context.Context, arg UpdateUserLastSeenAtParams) (User, error)
diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go
index 354a6ee04c963..c2022fa98f502 100644
--- a/coderd/database/queries.sql.go
+++ b/coderd/database/queries.sql.go
@@ -880,13 +880,13 @@ func (q *sqlQuerier) InsertGitAuthLink(ctx context.Context, arg InsertGitAuthLin
return i, err
}
-const updateGitAuthLink = `-- name: UpdateGitAuthLink :exec
+const updateGitAuthLink = `-- name: UpdateGitAuthLink :one
UPDATE git_auth_links SET
updated_at = $3,
oauth_access_token = $4,
oauth_refresh_token = $5,
oauth_expiry = $6
-WHERE provider_id = $1 AND user_id = $2
+WHERE provider_id = $1 AND user_id = $2 RETURNING provider_id, user_id, created_at, updated_at, oauth_access_token, oauth_refresh_token, oauth_expiry
`
type UpdateGitAuthLinkParams struct {
@@ -898,8 +898,8 @@ type UpdateGitAuthLinkParams struct {
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
}
-func (q *sqlQuerier) UpdateGitAuthLink(ctx context.Context, arg UpdateGitAuthLinkParams) error {
- _, err := q.db.ExecContext(ctx, updateGitAuthLink,
+func (q *sqlQuerier) UpdateGitAuthLink(ctx context.Context, arg UpdateGitAuthLinkParams) (GitAuthLink, error) {
+ row := q.db.QueryRowContext(ctx, updateGitAuthLink,
arg.ProviderID,
arg.UserID,
arg.UpdatedAt,
@@ -907,7 +907,17 @@ func (q *sqlQuerier) UpdateGitAuthLink(ctx context.Context, arg UpdateGitAuthLin
arg.OAuthRefreshToken,
arg.OAuthExpiry,
)
- return err
+ var i GitAuthLink
+ err := row.Scan(
+ &i.ProviderID,
+ &i.UserID,
+ &i.CreatedAt,
+ &i.UpdatedAt,
+ &i.OAuthAccessToken,
+ &i.OAuthRefreshToken,
+ &i.OAuthExpiry,
+ )
+ return i, err
}
const deleteGitSSHKey = `-- name: DeleteGitSSHKey :exec
@@ -3715,7 +3725,7 @@ func (q *sqlQuerier) InsertTemplateVersionParameter(ctx context.Context, arg Ins
const getPreviousTemplateVersion = `-- name: GetPreviousTemplateVersion :one
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers
FROM
template_versions
WHERE
@@ -3749,13 +3759,14 @@ func (q *sqlQuerier) GetPreviousTemplateVersion(ctx context.Context, arg GetPrev
&i.Readme,
&i.JobID,
&i.CreatedBy,
+ pq.Array(&i.GitAuthProviders),
)
return i, err
}
const getTemplateVersionByID = `-- name: GetTemplateVersionByID :one
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers
FROM
template_versions
WHERE
@@ -3775,13 +3786,14 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (
&i.Readme,
&i.JobID,
&i.CreatedBy,
+ pq.Array(&i.GitAuthProviders),
)
return i, err
}
const getTemplateVersionByJobID = `-- name: GetTemplateVersionByJobID :one
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers
FROM
template_versions
WHERE
@@ -3801,13 +3813,14 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U
&i.Readme,
&i.JobID,
&i.CreatedBy,
+ pq.Array(&i.GitAuthProviders),
)
return i, err
}
const getTemplateVersionByTemplateIDAndName = `-- name: GetTemplateVersionByTemplateIDAndName :one
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers
FROM
template_versions
WHERE
@@ -3833,13 +3846,14 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context,
&i.Readme,
&i.JobID,
&i.CreatedBy,
+ pq.Array(&i.GitAuthProviders),
)
return i, err
}
const getTemplateVersionsByIDs = `-- name: GetTemplateVersionsByIDs :many
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers
FROM
template_versions
WHERE
@@ -3865,6 +3879,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU
&i.Readme,
&i.JobID,
&i.CreatedBy,
+ pq.Array(&i.GitAuthProviders),
); err != nil {
return nil, err
}
@@ -3881,7 +3896,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU
const getTemplateVersionsByTemplateID = `-- name: GetTemplateVersionsByTemplateID :many
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers
FROM
template_versions
WHERE
@@ -3945,6 +3960,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
&i.Readme,
&i.JobID,
&i.CreatedBy,
+ pq.Array(&i.GitAuthProviders),
); err != nil {
return nil, err
}
@@ -3960,7 +3976,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
}
const getTemplateVersionsCreatedAfter = `-- name: GetTemplateVersionsCreatedAfter :many
-SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by FROM template_versions WHERE created_at > $1
+SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers FROM template_versions WHERE created_at > $1
`
func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]TemplateVersion, error) {
@@ -3982,6 +3998,7 @@ func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, create
&i.Readme,
&i.JobID,
&i.CreatedBy,
+ pq.Array(&i.GitAuthProviders),
); err != nil {
return nil, err
}
@@ -4010,7 +4027,7 @@ INSERT INTO
created_by
)
VALUES
- ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
+ ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers
`
type InsertTemplateVersionParams struct {
@@ -4048,6 +4065,7 @@ func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTempla
&i.Readme,
&i.JobID,
&i.CreatedBy,
+ pq.Array(&i.GitAuthProviders),
)
return i, err
}
@@ -4094,6 +4112,27 @@ func (q *sqlQuerier) UpdateTemplateVersionDescriptionByJobID(ctx context.Context
return err
}
+const updateTemplateVersionGitAuthProvidersByJobID = `-- name: UpdateTemplateVersionGitAuthProvidersByJobID :exec
+UPDATE
+ template_versions
+SET
+ git_auth_providers = $2,
+ updated_at = $3
+WHERE
+ job_id = $1
+`
+
+type UpdateTemplateVersionGitAuthProvidersByJobIDParams struct {
+ JobID uuid.UUID `db:"job_id" json:"job_id"`
+ GitAuthProviders []string `db:"git_auth_providers" json:"git_auth_providers"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+}
+
+func (q *sqlQuerier) UpdateTemplateVersionGitAuthProvidersByJobID(ctx context.Context, arg UpdateTemplateVersionGitAuthProvidersByJobIDParams) error {
+ _, err := q.db.ExecContext(ctx, updateTemplateVersionGitAuthProvidersByJobID, arg.JobID, pq.Array(arg.GitAuthProviders), arg.UpdatedAt)
+ return err
+}
+
const getTemplateVersionVariables = `-- name: GetTemplateVersionVariables :many
SELECT template_version_id, name, description, type, value, default_value, required, sensitive FROM template_version_variables WHERE template_version_id = $1
`
diff --git a/coderd/database/queries/gitauth.sql b/coderd/database/queries/gitauth.sql
index 52a6fa76c48f4..a35de98a08908 100644
--- a/coderd/database/queries/gitauth.sql
+++ b/coderd/database/queries/gitauth.sql
@@ -20,10 +20,10 @@ INSERT INTO git_auth_links (
$7
) RETURNING *;
--- name: UpdateGitAuthLink :exec
+-- name: UpdateGitAuthLink :one
UPDATE git_auth_links SET
updated_at = $3,
oauth_access_token = $4,
oauth_refresh_token = $5,
oauth_expiry = $6
-WHERE provider_id = $1 AND user_id = $2;
+WHERE provider_id = $1 AND user_id = $2 RETURNING *;
diff --git a/coderd/database/queries/templateversions.sql b/coderd/database/queries/templateversions.sql
index 78dcff44e2d30..e4efc7f46ab90 100644
--- a/coderd/database/queries/templateversions.sql
+++ b/coderd/database/queries/templateversions.sql
@@ -102,6 +102,15 @@ SET
WHERE
job_id = $1;
+-- name: UpdateTemplateVersionGitAuthProvidersByJobID :exec
+UPDATE
+ template_versions
+SET
+ git_auth_providers = $2,
+ updated_at = $3
+WHERE
+ job_id = $1;
+
-- name: GetPreviousTemplateVersion :one
SELECT
*
diff --git a/coderd/gitauth/config.go b/coderd/gitauth/config.go
index 91fe41ee51db5..69062a1801e1f 100644
--- a/coderd/gitauth/config.go
+++ b/coderd/gitauth/config.go
@@ -34,14 +34,14 @@ type Config struct {
ValidateURL string
}
-// ConvertConfig converts the YAML configuration entry to the
-// parsed and ready-to-consume provider type.
+// ConvertConfig converts the SDK configuration entry format
+// to the parsed and ready-to-consume in coderd provider type.
func ConvertConfig(entries []codersdk.GitAuthConfig, accessURL *url.URL) ([]*Config, error) {
ids := map[string]struct{}{}
configs := []*Config{}
for _, entry := range entries {
var typ codersdk.GitProvider
- switch entry.Type {
+ switch codersdk.GitProvider(entry.Type) {
case codersdk.GitProviderAzureDevops:
typ = codersdk.GitProviderAzureDevops
case codersdk.GitProviderBitBucket:
diff --git a/coderd/gitauth/config_test.go b/coderd/gitauth/config_test.go
index 0ae1d579d4896..db41fb64a0b24 100644
--- a/coderd/gitauth/config_test.go
+++ b/coderd/gitauth/config_test.go
@@ -26,37 +26,37 @@ func TestConvertYAML(t *testing.T) {
}, {
Name: "InvalidID",
Input: []codersdk.GitAuthConfig{{
- Type: codersdk.GitProviderGitHub,
+ Type: string(codersdk.GitProviderGitHub),
ID: "$hi$",
}},
Error: "doesn't have a valid id",
}, {
Name: "NoClientID",
Input: []codersdk.GitAuthConfig{{
- Type: codersdk.GitProviderGitHub,
+ Type: string(codersdk.GitProviderGitHub),
}},
Error: "client_id must be provided",
}, {
Name: "NoClientSecret",
Input: []codersdk.GitAuthConfig{{
- Type: codersdk.GitProviderGitHub,
+ Type: string(codersdk.GitProviderGitHub),
ClientID: "example",
}},
Error: "client_secret must be provided",
}, {
Name: "DuplicateType",
Input: []codersdk.GitAuthConfig{{
- Type: codersdk.GitProviderGitHub,
+ Type: string(codersdk.GitProviderGitHub),
ClientID: "example",
ClientSecret: "example",
}, {
- Type: codersdk.GitProviderGitHub,
+ Type: string(codersdk.GitProviderGitHub),
}},
Error: "multiple github git auth providers provided",
}, {
Name: "InvalidRegex",
Input: []codersdk.GitAuthConfig{{
- Type: codersdk.GitProviderGitHub,
+ Type: string(codersdk.GitProviderGitHub),
ClientID: "example",
ClientSecret: "example",
Regex: `\K`,
@@ -79,7 +79,7 @@ func TestConvertYAML(t *testing.T) {
t.Run("CustomScopesAndEndpoint", func(t *testing.T) {
t.Parallel()
config, err := gitauth.ConvertConfig([]codersdk.GitAuthConfig{{
- Type: codersdk.GitProviderGitLab,
+ Type: string(codersdk.GitProviderGitLab),
ClientID: "id",
ClientSecret: "secret",
AuthURL: "https://auth.com",
diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go
index c1f7045921baa..9ca1da8bf8372 100644
--- a/coderd/provisionerdserver/provisionerdserver.go
+++ b/coderd/provisionerdserver/provisionerdserver.go
@@ -29,6 +29,7 @@ import (
"github.com/coder/coder/coderd/database/dbauthz"
"github.com/coder/coder/coderd/parameter"
"github.com/coder/coder/coderd/telemetry"
+ "github.com/coder/coder/coderd/util/slice"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/provisioner"
"github.com/coder/coder/provisionerd/proto"
@@ -42,16 +43,17 @@ var (
)
type Server struct {
- AccessURL *url.URL
- ID uuid.UUID
- Logger slog.Logger
- Provisioners []database.ProvisionerType
- Tags json.RawMessage
- Database database.Store
- Pubsub database.Pubsub
- Telemetry telemetry.Reporter
- QuotaCommitter *atomic.Pointer[proto.QuotaCommitter]
- Auditor *atomic.Pointer[audit.Auditor]
+ AccessURL *url.URL
+ ID uuid.UUID
+ Logger slog.Logger
+ Provisioners []database.ProvisionerType
+ GitAuthProviders []string
+ Tags json.RawMessage
+ Database database.Store
+ Pubsub database.Pubsub
+ Telemetry telemetry.Reporter
+ QuotaCommitter *atomic.Pointer[proto.QuotaCommitter]
+ Auditor *atomic.Pointer[audit.Auditor]
AcquireJobDebounce time.Duration
}
@@ -307,7 +309,7 @@ func (server *Server) includeLastVariableValues(ctx context.Context, templateVer
templateVersion, err := server.Database.GetTemplateVersionByID(ctx, templateVersionID)
if err != nil {
- return nil, fmt.Errorf("get template version: %w", err)
+ return nil, xerrors.Errorf("get template version: %w", err)
}
if templateVersion.TemplateID.UUID == uuid.Nil {
@@ -316,7 +318,7 @@ func (server *Server) includeLastVariableValues(ctx context.Context, templateVer
template, err := server.Database.GetTemplateByID(ctx, templateVersion.TemplateID.UUID)
if err != nil {
- return nil, fmt.Errorf("get template: %w", err)
+ return nil, xerrors.Errorf("get template: %w", err)
}
if template.ActiveVersionID == uuid.Nil {
@@ -325,7 +327,7 @@ func (server *Server) includeLastVariableValues(ctx context.Context, templateVer
templateVariables, err := server.Database.GetTemplateVersionVariables(ctx, template.ActiveVersionID)
if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
- return nil, fmt.Errorf("get template version variables: %w", err)
+ return nil, xerrors.Errorf("get template version variables: %w", err)
}
for _, templateVariable := range templateVariables {
@@ -812,6 +814,27 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
}
}
+ var completedError sql.NullString
+
+ for _, gitAuthProvider := range jobType.TemplateImport.GitAuthProviders {
+ if !slice.Contains(server.GitAuthProviders, gitAuthProvider) {
+ completedError = sql.NullString{
+ String: fmt.Sprintf("git auth provider %q is not configured", gitAuthProvider),
+ Valid: true,
+ }
+ break
+ }
+ }
+
+ err = server.Database.UpdateTemplateVersionGitAuthProvidersByJobID(ctx, database.UpdateTemplateVersionGitAuthProvidersByJobIDParams{
+ JobID: jobID,
+ GitAuthProviders: jobType.TemplateImport.GitAuthProviders,
+ UpdatedAt: database.Now(),
+ })
+ if err != nil {
+ return nil, xerrors.Errorf("update template version git auth providers: %w", err)
+ }
+
err = server.Database.UpdateProvisionerJobWithCompleteByID(ctx, database.UpdateProvisionerJobWithCompleteByIDParams{
ID: jobID,
UpdatedAt: database.Now(),
@@ -819,6 +842,7 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
Time: database.Now(),
Valid: true,
},
+ Error: completedError,
})
if err != nil {
return nil, xerrors.Errorf("update provisioner job: %w", err)
diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go
index 83f661563f60d..bcc0d6b0ad93a 100644
--- a/coderd/provisionerdserver/provisionerdserver_test.go
+++ b/coderd/provisionerdserver/provisionerdserver_test.go
@@ -736,10 +736,16 @@ func TestCompleteJob(t *testing.T) {
t.Run("TemplateImport", func(t *testing.T) {
t.Parallel()
srv := setup(t, false)
+ jobID := uuid.New()
+ version, err := srv.Database.InsertTemplateVersion(ctx, database.InsertTemplateVersionParams{
+ ID: uuid.New(),
+ JobID: jobID,
+ })
+ require.NoError(t, err)
job, err := srv.Database.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
- ID: uuid.New(),
+ ID: jobID,
Provisioner: database.ProvisionerTypeEcho,
- Input: []byte(`{"template_version_id": "` + uuid.NewString() + `"}`),
+ Input: []byte(`{"template_version_id": "` + version.ID.String() + `"}`),
StorageMethod: database.ProvisionerStorageMethodFile,
Type: database.ProvisionerJobTypeWorkspaceBuild,
})
@@ -752,19 +758,31 @@ func TestCompleteJob(t *testing.T) {
Types: []database.ProvisionerType{database.ProvisionerTypeEcho},
})
require.NoError(t, err)
- _, err = srv.CompleteJob(ctx, &proto.CompletedJob{
- JobId: job.ID.String(),
- Type: &proto.CompletedJob_TemplateImport_{
- TemplateImport: &proto.CompletedJob_TemplateImport{
- StartResources: []*sdkproto.Resource{{
- Name: "hello",
- Type: "aws_instance",
- }},
- StopResources: []*sdkproto.Resource{},
+ completeJob := func() {
+ _, err = srv.CompleteJob(ctx, &proto.CompletedJob{
+ JobId: job.ID.String(),
+ Type: &proto.CompletedJob_TemplateImport_{
+ TemplateImport: &proto.CompletedJob_TemplateImport{
+ StartResources: []*sdkproto.Resource{{
+ Name: "hello",
+ Type: "aws_instance",
+ }},
+ StopResources: []*sdkproto.Resource{},
+ GitAuthProviders: []string{"github"},
+ },
},
- },
- })
+ })
+ require.NoError(t, err)
+ }
+ completeJob()
+ job, err = srv.Database.GetProvisionerJobByID(ctx, job.ID)
+ require.NoError(t, err)
+ require.Contains(t, job.Error.String, `git auth provider "github" is not configured`)
+ srv.GitAuthProviders = []string{"github"}
+ completeJob()
+ job, err = srv.Database.GetProvisionerJobByID(ctx, job.ID)
require.NoError(t, err)
+ require.False(t, job.Error.Valid)
})
t.Run("WorkspaceBuild", func(t *testing.T) {
t.Parallel()
diff --git a/coderd/templateversions.go b/coderd/templateversions.go
index 04d7e25070e1f..160f56e18b30a 100644
--- a/coderd/templateversions.go
+++ b/coderd/templateversions.go
@@ -19,6 +19,7 @@ import (
"github.com/coder/coder/coderd/audit"
"github.com/coder/coder/coderd/database"
+ "github.com/coder/coder/coderd/gitauth"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/coderd/parameter"
@@ -243,6 +244,107 @@ func (api *API) templateVersionRichParameters(rw http.ResponseWriter, r *http.Re
httpapi.Write(ctx, rw, http.StatusOK, templateVersionParameters)
}
+// @Summary Get git auth by template version
+// @ID get-git-auth-by-template-version
+// @Security CoderSessionToken
+// @Produce json
+// @Tags Templates
+// @Param templateversion path string true "Template version ID" format(uuid)
+// @Success 200 {array} codersdk.TemplateVersionGitAuth
+// @Router /templateversions/{templateversion}/gitauth [get]
+func (api *API) templateVersionGitAuth(rw http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+ var (
+ apiKey = httpmw.APIKey(r)
+ templateVersion = httpmw.TemplateVersionParam(r)
+ template = httpmw.TemplateParam(r)
+ )
+
+ if !api.Authorize(r, rbac.ActionRead, templateVersion.RBACObject(template)) {
+ httpapi.ResourceNotFound(rw)
+ return
+ }
+
+ rawProviders := templateVersion.GitAuthProviders
+ providers := make([]codersdk.TemplateVersionGitAuth, 0)
+ for _, rawProvider := range rawProviders {
+ var config *gitauth.Config
+ for _, provider := range api.GitAuthConfigs {
+ if provider.ID == rawProvider {
+ config = provider
+ break
+ }
+ }
+ if config == nil {
+ 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),
+ Detail: "You'll need to update the template version to use a different provider.",
+ })
+ return
+ }
+
+ // This is the URL that will redirect the user with a state token.
+ redirectURL, err := api.AccessURL.Parse(fmt.Sprintf("/gitauth/%s", config.ID))
+ if err != nil {
+ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
+ Message: "Failed to parse access URL.",
+ Detail: err.Error(),
+ })
+ return
+ }
+ query := redirectURL.Query()
+ // The frontend uses a BroadcastChannel to notify listening pages for
+ // Git auth updates if the "notify" query parameter is set.
+ //
+ // It's important we do this in the backend, because the same endpoint
+ // is used for CLI authentication.
+ query.Add("redirect", "/gitauth?notify")
+ redirectURL.RawQuery = query.Encode()
+
+ provider := codersdk.TemplateVersionGitAuth{
+ ID: config.ID,
+ Type: config.Type,
+ AuthenticateURL: redirectURL.String(),
+ }
+
+ authLink, err := api.Database.GetGitAuthLink(ctx, database.GetGitAuthLinkParams{
+ ProviderID: config.ID,
+ UserID: apiKey.UserID,
+ })
+ // If there isn't an auth link, then the user just isn't authenticated.
+ if errors.Is(err, sql.ErrNoRows) {
+ providers = append(providers, provider)
+ continue
+ }
+ if err != nil {
+ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
+ Message: "Internal error fetching git auth link.",
+ Detail: err.Error(),
+ })
+ return
+ }
+
+ _, updated, err := refreshGitToken(ctx, api.Database, apiKey.UserID, config, authLink)
+ if err != nil {
+ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
+ Message: "Failed to refresh git auth token.",
+ Detail: err.Error(),
+ })
+ return
+ }
+ // If the token couldn't be validated, then we assume the user isn't
+ // authenticated and return early.
+ if !updated {
+ providers = append(providers, provider)
+ continue
+ }
+ provider.Authenticated = true
+ providers = append(providers, provider)
+ }
+
+ httpapi.Write(ctx, rw, http.StatusOK, providers)
+}
+
// @Summary Get template variables by template version
// @ID get-template-variables-by-template-version
// @Security CoderSessionToken
diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go
index 9e7a7d46bda9f..7f9aecbf8e3b1 100644
--- a/coderd/templateversions_test.go
+++ b/coderd/templateversions_test.go
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"net/http"
+ "regexp"
"testing"
"github.com/google/uuid"
@@ -14,6 +15,7 @@ import (
"github.com/coder/coder/coderd/audit"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/coderd/database"
+ "github.com/coder/coder/coderd/gitauth"
"github.com/coder/coder/coderd/provisionerdserver"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/examples"
@@ -434,6 +436,67 @@ func TestTemplateVersionParameters(t *testing.T) {
})
}
+func TestTemplateVersionsGitAuth(t *testing.T) {
+ t.Parallel()
+ t.Run("Empty", func(t *testing.T) {
+ t.Parallel()
+ client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
+ user := coderdtest.CreateFirstUser(t, client)
+ version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
+ coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
+
+ ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
+ defer cancel()
+
+ _, err := client.TemplateVersionGitAuth(ctx, version.ID)
+ require.NoError(t, err)
+ })
+ t.Run("Authenticated", func(t *testing.T) {
+ t.Parallel()
+ client := coderdtest.New(t, &coderdtest.Options{
+ IncludeProvisionerDaemon: true,
+ GitAuthConfigs: []*gitauth.Config{{
+ OAuth2Config: &oauth2Config{},
+ ID: "github",
+ Regex: regexp.MustCompile(`github\.com`),
+ Type: codersdk.GitProviderGitHub,
+ }},
+ })
+ user := coderdtest.CreateFirstUser(t, client)
+ version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
+ Parse: echo.ParseComplete,
+ ProvisionPlan: []*proto.Provision_Response{{
+ Type: &proto.Provision_Response_Complete{
+ Complete: &proto.Provision_Complete{
+ GitAuthProviders: []string{"github"},
+ },
+ },
+ }},
+ })
+ version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
+ require.Empty(t, version.Job.Error)
+ ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
+ defer cancel()
+
+ // Not authenticated to start!
+ providers, err := client.TemplateVersionGitAuth(ctx, version.ID)
+ require.NoError(t, err)
+ require.Len(t, providers, 1)
+ require.False(t, providers[0].Authenticated)
+
+ // Perform the Git auth callback to authenticate the user...
+ resp := coderdtest.RequestGitAuthCallback(t, "github", client)
+ _ = resp.Body.Close()
+ require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
+
+ // Ensure that the returned Git auth for the template is authenticated!
+ providers, err = client.TemplateVersionGitAuth(ctx, version.ID)
+ require.NoError(t, err)
+ require.Len(t, providers, 1)
+ require.True(t, providers[0].Authenticated)
+ })
+}
+
func TestTemplateVersionResources(t *testing.T) {
t.Parallel()
t.Run("ListRunning", func(t *testing.T) {
diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go
index 649fb37f0664d..41d084b2bf865 100644
--- a/coderd/workspaceagents.go
+++ b/coderd/workspaceagents.go
@@ -1313,14 +1313,29 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request)
return
}
- // If the token is expired and refresh is disabled, we prompt
- // the user to authenticate again.
- if gitAuthConfig.NoRefresh && gitAuthLink.OAuthExpiry.Before(database.Now()) {
+ gitAuthLink, updated, err := refreshGitToken(ctx, api.Database, workspace.OwnerID, gitAuthConfig, gitAuthLink)
+ if err != nil {
+ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
+ Message: "Failed to refresh git auth token.",
+ Detail: err.Error(),
+ })
+ return
+ }
+ if !updated {
httpapi.Write(ctx, rw, http.StatusOK, agentsdk.GitAuthResponse{
URL: redirectURL.String(),
})
return
}
+ httpapi.Write(ctx, rw, http.StatusOK, formatGitAuthAccessToken(gitAuthConfig.Type, gitAuthLink.OAuthAccessToken))
+}
+
+func refreshGitToken(ctx context.Context, db database.Store, owner uuid.UUID, gitAuthConfig *gitauth.Config, gitAuthLink database.GitAuthLink) (database.GitAuthLink, bool, error) {
+ // If the token is expired and refresh is disabled, we prompt
+ // the user to authenticate again.
+ if gitAuthConfig.NoRefresh && gitAuthLink.OAuthExpiry.Before(database.Now()) {
+ return gitAuthLink, false, nil
+ }
token, err := gitAuthConfig.TokenSource(ctx, &oauth2.Token{
AccessToken: gitAuthLink.OAuthAccessToken,
@@ -1328,49 +1343,35 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request)
Expiry: gitAuthLink.OAuthExpiry,
}).Token()
if err != nil {
- httpapi.Write(ctx, rw, http.StatusOK, agentsdk.GitAuthResponse{
- URL: redirectURL.String(),
- })
- return
+ return gitAuthLink, false, nil
}
if gitAuthConfig.ValidateURL != "" {
valid, err := validateGitToken(ctx, gitAuthConfig.ValidateURL, token.AccessToken)
if err != nil {
- httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
- Message: "Failed to validate Git authentication token.",
- Detail: err.Error(),
- })
- return
+ return gitAuthLink, false, xerrors.Errorf("validate git auth token: %w", err)
}
if !valid {
// The token is no longer valid!
- httpapi.Write(ctx, rw, http.StatusOK, agentsdk.GitAuthResponse{
- URL: redirectURL.String(),
- })
- return
+ return gitAuthLink, false, nil
}
}
if token.AccessToken != gitAuthLink.OAuthAccessToken {
// Update it
- err = api.Database.UpdateGitAuthLink(ctx, database.UpdateGitAuthLinkParams{
+ gitAuthLink, err = db.UpdateGitAuthLink(ctx, database.UpdateGitAuthLinkParams{
ProviderID: gitAuthConfig.ID,
- UserID: workspace.OwnerID,
+ UserID: owner,
UpdatedAt: database.Now(),
OAuthAccessToken: token.AccessToken,
OAuthRefreshToken: token.RefreshToken,
OAuthExpiry: token.Expiry,
})
if err != nil {
- httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
- Message: "Failed to update git auth link.",
- Detail: err.Error(),
- })
- return
+ return gitAuthLink, false, xerrors.Errorf("update git auth link: %w", err)
}
}
- httpapi.Write(ctx, rw, http.StatusOK, formatGitAuthAccessToken(gitAuthConfig.Type, token.AccessToken))
+ return gitAuthLink, true, nil
}
// validateGitToken ensures the git token provided is valid
@@ -1392,7 +1393,7 @@ func validateGitToken(ctx context.Context, validateURL, token string) (bool, err
}
if res.StatusCode != http.StatusOK {
data, _ := io.ReadAll(res.Body)
- return false, xerrors.Errorf("git token validation failed: status %d: body: %s", res.StatusCode, data)
+ return false, xerrors.Errorf("status %d: body: %s", res.StatusCode, data)
}
return true, nil
}
@@ -1459,7 +1460,7 @@ func (api *API) gitAuthCallback(gitAuthConfig *gitauth.Config) http.HandlerFunc
return
}
} else {
- err = api.Database.UpdateGitAuthLink(ctx, database.UpdateGitAuthLinkParams{
+ _, err = api.Database.UpdateGitAuthLink(ctx, database.UpdateGitAuthLinkParams{
ProviderID: gitAuthConfig.ID,
UserID: apiKey.UserID,
UpdatedAt: database.Now(),
@@ -1485,8 +1486,12 @@ func (api *API) gitAuthCallback(gitAuthConfig *gitauth.Config) http.HandlerFunc
return
}
+ redirect := state.Redirect
+ if redirect == "" {
+ redirect = "/gitauth"
+ }
// This is a nicely rendered screen on the frontend
- http.Redirect(rw, r, "/gitauth", http.StatusTemporaryRedirect)
+ http.Redirect(rw, r, redirect, http.StatusTemporaryRedirect)
}
}
diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go
index b4ac803e08c19..6ccea696b514f 100644
--- a/coderd/workspaceagents_test.go
+++ b/coderd/workspaceagents_test.go
@@ -911,7 +911,7 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
Type: codersdk.GitProviderGitHub,
}},
})
- resp := gitAuthCallback(t, "github", client)
+ resp := coderdtest.RequestGitAuthCallback(t, "github", client)
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("AuthorizedCallback", func(t *testing.T) {
@@ -926,14 +926,14 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
}},
})
_ = coderdtest.CreateFirstUser(t, client)
- resp := gitAuthCallback(t, "github", client)
+ resp := coderdtest.RequestGitAuthCallback(t, "github", client)
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
location, err := resp.Location()
require.NoError(t, err)
require.Equal(t, "/gitauth", location.Path)
// Callback again to simulate updating the token.
- resp = gitAuthCallback(t, "github", client)
+ resp = coderdtest.RequestGitAuthCallback(t, "github", client)
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
})
t.Run("ValidateURL", func(t *testing.T) {
@@ -983,7 +983,7 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
agentClient := agentsdk.New(client.URL)
agentClient.SetSessionToken(authToken)
- resp := gitAuthCallback(t, "github", client)
+ resp := coderdtest.RequestGitAuthCallback(t, "github", client)
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
// If the validation URL says unauthorized, the callback
@@ -1005,7 +1005,7 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
var apiError *codersdk.Error
require.ErrorAs(t, err, &apiError)
require.Equal(t, http.StatusInternalServerError, apiError.StatusCode())
- require.Equal(t, "git token validation failed: status 403: body: Something went wrong!", apiError.Detail)
+ require.Equal(t, "validate git auth token: status 403: body: Something went wrong!", apiError.Detail)
})
t.Run("ExpiredNoRefresh", func(t *testing.T) {
@@ -1063,7 +1063,7 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
// In the configuration, we set our OAuth provider
// to return an expired token. Coder consumes this
// and stores it.
- resp := gitAuthCallback(t, "github", client)
+ resp := coderdtest.RequestGitAuthCallback(t, "github", client)
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
// Because the token is expired and `NoRefresh` is specified,
@@ -1128,7 +1128,7 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
time.Sleep(250 * time.Millisecond)
- resp := gitAuthCallback(t, "github", client)
+ resp := coderdtest.RequestGitAuthCallback(t, "github", client)
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
token = <-tokenChan
require.Equal(t, "token", token.Username)
@@ -1197,31 +1197,6 @@ func TestWorkspaceAgentReportStats(t *testing.T) {
})
}
-func gitAuthCallback(t *testing.T, id string, client *codersdk.Client) *http.Response {
- client.HTTPClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
- return http.ErrUseLastResponse
- }
- state := "somestate"
- oauthURL, err := client.URL.Parse(fmt.Sprintf("/gitauth/%s/callback?code=asd&state=%s", id, state))
- require.NoError(t, err)
- req, err := http.NewRequestWithContext(context.Background(), "GET", oauthURL.String(), nil)
- require.NoError(t, err)
- req.AddCookie(&http.Cookie{
- Name: codersdk.OAuth2StateCookie,
- Value: state,
- })
- req.AddCookie(&http.Cookie{
- Name: codersdk.SessionTokenCookie,
- Value: client.SessionToken(),
- })
- res, err := client.HTTPClient.Do(req)
- require.NoError(t, err)
- t.Cleanup(func() {
- _ = res.Body.Close()
- })
- return res
-}
-
func TestWorkspaceAgent_LifecycleState(t *testing.T) {
t.Parallel()
diff --git a/codersdk/templateversions.go b/codersdk/templateversions.go
index 18b7a43f37ae4..a915f7e218615 100644
--- a/codersdk/templateversions.go
+++ b/codersdk/templateversions.go
@@ -24,6 +24,13 @@ type TemplateVersion struct {
CreatedBy User `json:"created_by"`
}
+type TemplateVersionGitAuth struct {
+ ID string `json:"id"`
+ Type GitProvider `json:"type"`
+ AuthenticateURL string `json:"authenticate_url"`
+ Authenticated bool `json:"authenticated"`
+}
+
type ValidationMonotonicOrder string
const (
@@ -108,6 +115,20 @@ func (c *Client) TemplateVersionRichParameters(ctx context.Context, version uuid
return params, json.NewDecoder(res.Body).Decode(¶ms)
}
+// TemplateVersionGitAuth returns git authentication for the requested template version.
+func (c *Client) TemplateVersionGitAuth(ctx context.Context, version uuid.UUID) ([]TemplateVersionGitAuth, error) {
+ res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/gitauth", version), nil)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return nil, ReadBodyAsError(res)
+ }
+ var gitAuth []TemplateVersionGitAuth
+ return gitAuth, json.NewDecoder(res.Body).Decode(&gitAuth)
+}
+
// TemplateVersionSchema returns schemas for a template version by ID.
func (c *Client) TemplateVersionSchema(ctx context.Context, version uuid.UUID) ([]ParameterSchema, error) {
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/schema", version), nil)
diff --git a/codersdk/workspaceagents.go b/codersdk/workspaceagents.go
index 9364783d29953..6dd1c1d178f17 100644
--- a/codersdk/workspaceagents.go
+++ b/codersdk/workspaceagents.go
@@ -291,12 +291,26 @@ func (c *Client) WorkspaceAgentListeningPorts(ctx context.Context, agentID uuid.
// GitProvider is a constant that represents the
// type of providers that are supported within Coder.
-// @typescript-ignore GitProvider
type GitProvider string
+func (g GitProvider) Pretty() string {
+ switch g {
+ case GitProviderAzureDevops:
+ return "Azure DevOps"
+ case GitProviderGitHub:
+ return "GitHub"
+ case GitProviderGitLab:
+ return "GitLab"
+ case GitProviderBitBucket:
+ return "Bitbucket"
+ default:
+ return string(g)
+ }
+}
+
const (
- GitProviderAzureDevops = "azure-devops"
- GitProviderGitHub = "github"
- GitProviderGitLab = "gitlab"
- GitProviderBitBucket = "bitbucket"
+ GitProviderAzureDevops GitProvider = "azure-devops"
+ GitProviderGitHub GitProvider = "github"
+ GitProviderGitLab GitProvider = "gitlab"
+ GitProviderBitBucket GitProvider = "bitbucket"
)
diff --git a/docs/admin/audit-logs.md b/docs/admin/audit-logs.md
index 762b2f3762ca7..5b9355b391e3d 100644
--- a/docs/admin/audit-logs.md
+++ b/docs/admin/audit-logs.md
@@ -16,7 +16,7 @@ We track the following resources:
| GitSSHKey
create |
Field | Tracked |
---|
created_at | false |
private_key | true |
public_key | true |
updated_at | false |
user_id | true |
|
| License
create, delete | Field | Tracked |
---|
exp | true |
id | false |
jwt | false |
uploaded_at | true |
uuid | true |
|
| Template
write, delete | Field | Tracked |
---|
active_version_id | true |
allow_user_cancel_workspace_jobs | true |
created_at | false |
created_by | true |
default_ttl | true |
deleted | false |
description | true |
display_name | true |
group_acl | true |
icon | true |
id | true |
is_private | true |
min_autostart_interval | true |
name | true |
organization_id | false |
provisioner | true |
updated_at | false |
user_acl | true |
|
-| TemplateVersion
create, write | Field | Tracked |
---|
created_at | false |
created_by | true |
id | true |
job_id | false |
name | true |
organization_id | false |
readme | true |
template_id | true |
updated_at | false |
|
+| TemplateVersion
create, write | Field | Tracked |
---|
created_at | false |
created_by | true |
git_auth_providers | false |
id | true |
job_id | false |
name | true |
organization_id | false |
readme | true |
template_id | true |
updated_at | false |
|
| User
create, write, delete | Field | Tracked |
---|
avatar_url | false |
created_at | false |
deleted | true |
email | true |
hashed_password | true |
id | true |
last_seen_at | false |
login_type | false |
rbac_roles | true |
status | true |
updated_at | false |
username | true |
|
| Workspace
create, write, delete | Field | Tracked |
---|
autostart_schedule | true |
created_at | false |
deleted | false |
id | true |
last_used_at | false |
name | true |
organization_id | false |
owner_id | true |
template_id | true |
ttl | true |
updated_at | false |
|
| WorkspaceBuild
start, stop | Field | Tracked |
---|
build_number | false |
created_at | false |
daily_cost | false |
deadline | false |
id | false |
initiator_id | false |
job_id | false |
provisioner_state | false |
reason | false |
template_version_id | true |
transition | false |
updated_at | false |
workspace_id | false |
|
diff --git a/docs/api/schemas.md b/docs/api/schemas.md
index 948a0e6304197..cad32370ad2c5 100644
--- a/docs/api/schemas.md
+++ b/docs/api/schemas.md
@@ -2944,6 +2944,23 @@ CreateParameterRequest is a structure used to create a new parameter value for a
| `type` | string | false | | |
| `validate_url` | string | false | | |
+## codersdk.GitProvider
+
+```json
+"azure-devops"
+```
+
+### Properties
+
+#### Enumerated Values
+
+| Value |
+| -------------- |
+| `azure-devops` |
+| `github` |
+| `gitlab` |
+| `bitbucket` |
+
## codersdk.GitSSHKey
```json
@@ -4570,6 +4587,26 @@ Parameter represents a set value for the scope.
| `template_id` | string | false | | |
| `updated_at` | string | false | | |
+## codersdk.TemplateVersionGitAuth
+
+```json
+{
+ "authenticate_url": "string",
+ "authenticated": true,
+ "id": "string",
+ "type": "azure-devops"
+}
+```
+
+### Properties
+
+| Name | Type | Required | Restrictions | Description |
+| ------------------ | -------------------------------------------- | -------- | ------------ | ----------- |
+| `authenticate_url` | string | false | | |
+| `authenticated` | boolean | false | | |
+| `id` | string | false | | |
+| `type` | [codersdk.GitProvider](#codersdkgitprovider) | false | | |
+
## codersdk.TemplateVersionParameter
```json
diff --git a/docs/api/templates.md b/docs/api/templates.md
index b48b805d7c58e..acdd8df3abab2 100644
--- a/docs/api/templates.md
+++ b/docs/api/templates.md
@@ -1722,6 +1722,69 @@ Status Code **200**
To perform this operation, you must be authenticated. [Learn more](authentication.md).
+## Get git auth by template version
+
+### Code samples
+
+```shell
+# Example request using curl
+curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/gitauth \
+ -H 'Accept: application/json' \
+ -H 'Coder-Session-Token: API_KEY'
+```
+
+`GET /templateversions/{templateversion}/gitauth`
+
+### Parameters
+
+| Name | In | Type | Required | Description |
+| ----------------- | ---- | ------------ | -------- | ------------------- |
+| `templateversion` | path | string(uuid) | true | Template version ID |
+
+### Example responses
+
+> 200 Response
+
+```json
+[
+ {
+ "authenticate_url": "string",
+ "authenticated": true,
+ "id": "string",
+ "type": "azure-devops"
+ }
+]
+```
+
+### Responses
+
+| Status | Meaning | Description | Schema |
+| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------- |
+| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | array of [codersdk.TemplateVersionGitAuth](schemas.md#codersdktemplateversiongitauth) |
+
+Response Schema
+
+Status Code **200**
+
+| Name | Type | Required | Restrictions | Description |
+| -------------------- | ------------------------------------------------------ | -------- | ------------ | ----------- |
+| `[array item]` | array | false | | |
+| `» authenticate_url` | string | false | | |
+| `» authenticated` | boolean | false | | |
+| `» id` | string | false | | |
+| `» type` | [codersdk.GitProvider](schemas.md#codersdkgitprovider) | false | | |
+
+#### Enumerated Values
+
+| Property | Value |
+| -------- | -------------- |
+| `type` | `azure-devops` |
+| `type` | `github` |
+| `type` | `gitlab` |
+| `type` | `bitbucket` |
+
+To perform this operation, you must be authenticated. [Learn more](authentication.md).
+
## Get logs by template version
### Code samples
diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go
index 239aecfd3017e..ce47a56e40273 100644
--- a/enterprise/audit/table.go
+++ b/enterprise/audit/table.go
@@ -72,15 +72,16 @@ var AuditableResources = auditMap(map[any]map[string]Action{
"allow_user_cancel_workspace_jobs": ActionTrack,
},
&database.TemplateVersion{}: {
- "id": ActionTrack,
- "template_id": ActionTrack,
- "organization_id": ActionIgnore, // Never changes.
- "created_at": ActionIgnore, // Never changes, but is implicit and not helpful in a diff.
- "updated_at": ActionIgnore, // Changes, but is implicit and not helpful in a diff.
- "name": ActionTrack,
- "readme": ActionTrack,
- "job_id": ActionIgnore, // Not helpful in a diff because jobs aren't tracked in audit logs.
- "created_by": ActionTrack,
+ "id": ActionTrack,
+ "template_id": ActionTrack,
+ "organization_id": ActionIgnore, // Never changes.
+ "created_at": ActionIgnore, // Never changes, but is implicit and not helpful in a diff.
+ "updated_at": ActionIgnore, // Changes, but is implicit and not helpful in a diff.
+ "name": ActionTrack,
+ "readme": ActionTrack,
+ "job_id": ActionIgnore, // Not helpful in a diff because jobs aren't tracked in audit logs.
+ "created_by": ActionTrack,
+ "git_auth_providers": ActionIgnore, // Not helpful because this can only change when new versions are added.
},
&database.User{}: {
"id": ActionTrack,
diff --git a/provisioner/terraform/executor.go b/provisioner/terraform/executor.go
index 7d2335beb071f..f273e5245df4f 100644
--- a/provisioner/terraform/executor.go
+++ b/provisioner/terraform/executor.go
@@ -223,7 +223,7 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
if err != nil {
return nil, xerrors.Errorf("terraform plan: %w", err)
}
- resources, parameters, err := e.planResources(ctx, killCtx, planfilePath)
+ state, err := e.planResources(ctx, killCtx, planfilePath)
if err != nil {
return nil, err
}
@@ -234,31 +234,32 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
return &proto.Provision_Response{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{
- Parameters: parameters,
- Resources: resources,
- Plan: planFileByt,
+ Parameters: state.Parameters,
+ Resources: state.Resources,
+ GitAuthProviders: state.GitAuthProviders,
+ Plan: planFileByt,
},
},
}, nil
}
// planResources must only be called while the lock is held.
-func (e *executor) planResources(ctx, killCtx context.Context, planfilePath string) ([]*proto.Resource, []*proto.RichParameter, error) {
+func (e *executor) planResources(ctx, killCtx context.Context, planfilePath string) (*State, error) {
plan, err := e.showPlan(ctx, killCtx, planfilePath)
if err != nil {
- return nil, nil, xerrors.Errorf("show terraform plan file: %w", err)
+ return nil, xerrors.Errorf("show terraform plan file: %w", err)
}
rawGraph, err := e.graph(ctx, killCtx)
if err != nil {
- return nil, nil, xerrors.Errorf("graph: %w", err)
+ return nil, xerrors.Errorf("graph: %w", err)
}
modules := []*tfjson.StateModule{}
if plan.PriorState != nil {
modules = append(modules, plan.PriorState.Values.RootModule)
}
modules = append(modules, plan.PlannedValues.RootModule)
- return ConvertResourcesAndParameters(modules, rawGraph)
+ return ConvertState(modules, rawGraph)
}
// showPlan must only be called while the lock is held.
@@ -332,7 +333,7 @@ func (e *executor) apply(
if err != nil {
return nil, xerrors.Errorf("terraform apply: %w", err)
}
- resources, parameters, err := e.stateResources(ctx, killCtx)
+ state, err := e.stateResources(ctx, killCtx)
if err != nil {
return nil, err
}
@@ -344,35 +345,35 @@ func (e *executor) apply(
return &proto.Provision_Response{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{
- Parameters: parameters,
- Resources: resources,
- State: stateContent,
+ Parameters: state.Parameters,
+ Resources: state.Resources,
+ GitAuthProviders: state.GitAuthProviders,
+ State: stateContent,
},
},
}, nil
}
// stateResources must only be called while the lock is held.
-func (e *executor) stateResources(ctx, killCtx context.Context) ([]*proto.Resource, []*proto.RichParameter, error) {
+func (e *executor) stateResources(ctx, killCtx context.Context) (*State, error) {
state, err := e.state(ctx, killCtx)
if err != nil {
- return nil, nil, err
+ return nil, err
}
rawGraph, err := e.graph(ctx, killCtx)
if err != nil {
- return nil, nil, xerrors.Errorf("get terraform graph: %w", err)
+ return nil, xerrors.Errorf("get terraform graph: %w", err)
}
- var resources []*proto.Resource
- var parameters []*proto.RichParameter
+ converted := &State{}
if state.Values != nil {
- resources, parameters, err = ConvertResourcesAndParameters([]*tfjson.StateModule{
+ converted, err = ConvertState([]*tfjson.StateModule{
state.Values.RootModule,
}, rawGraph)
if err != nil {
- return nil, nil, err
+ return nil, err
}
}
- return resources, parameters, nil
+ return converted, nil
}
// state must only be called while the lock is held.
diff --git a/provisioner/terraform/resources.go b/provisioner/terraform/resources.go
index 69e235adb4ec6..e370d7371541c 100644
--- a/provisioner/terraform/resources.go
+++ b/provisioner/terraform/resources.go
@@ -72,17 +72,23 @@ type metadataItem struct {
IsNull bool `mapstructure:"is_null"`
}
-// ConvertResourcesAndParameters consumes Terraform state and a GraphViz representation
+type State struct {
+ Resources []*proto.Resource
+ Parameters []*proto.RichParameter
+ GitAuthProviders []string
+}
+
+// ConvertState consumes Terraform state and a GraphViz representation
// produced by `terraform graph` to produce resources consumable by Coder.
// nolint:gocyclo
-func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph string) ([]*proto.Resource, []*proto.RichParameter, error) {
+func ConvertState(modules []*tfjson.StateModule, rawGraph string) (*State, error) {
parsedGraph, err := gographviz.ParseString(rawGraph)
if err != nil {
- return nil, nil, xerrors.Errorf("parse graph: %w", err)
+ return nil, xerrors.Errorf("parse graph: %w", err)
}
graph, err := gographviz.NewAnalysedGraph(parsedGraph)
if err != nil {
- return nil, nil, xerrors.Errorf("analyze graph: %w", err)
+ return nil, xerrors.Errorf("analyze graph: %w", err)
}
resources := make([]*proto.Resource, 0)
@@ -118,11 +124,11 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
var attrs agentAttributes
err = mapstructure.Decode(tfResource.AttributeValues, &attrs)
if err != nil {
- return nil, nil, xerrors.Errorf("decode agent attributes: %w", err)
+ return nil, xerrors.Errorf("decode agent attributes: %w", err)
}
if _, ok := agentNames[tfResource.Name]; ok {
- return nil, nil, xerrors.Errorf("duplicate agent name: %s", tfResource.Name)
+ return nil, xerrors.Errorf("duplicate agent name: %s", tfResource.Name)
}
agentNames[tfResource.Name] = struct{}{}
@@ -171,7 +177,7 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
break
}
if agentNode == nil {
- return nil, nil, xerrors.Errorf("couldn't find node on graph: %q", agentLabel)
+ return nil, xerrors.Errorf("couldn't find node on graph: %q", agentLabel)
}
var agentResource *graphResource
@@ -260,7 +266,7 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
var attrs agentAppAttributes
err = mapstructure.Decode(resource.AttributeValues, &attrs)
if err != nil {
- return nil, nil, xerrors.Errorf("decode app attributes: %w", err)
+ return nil, xerrors.Errorf("decode app attributes: %w", err)
}
// Default to the resource name if none is set!
@@ -277,11 +283,11 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
}
if !provisioner.AppSlugRegex.MatchString(attrs.Slug) {
- return nil, nil, xerrors.Errorf("invalid app slug %q, please update your coder/coder provider to the latest version and specify the slug property on each coder_app", attrs.Slug)
+ return nil, xerrors.Errorf("invalid app slug %q, please update your coder/coder provider to the latest version and specify the slug property on each coder_app", attrs.Slug)
}
if _, exists := appSlugs[attrs.Slug]; exists {
- return nil, nil, xerrors.Errorf("duplicate app slug, they must be unique per template: %q", attrs.Slug)
+ return nil, xerrors.Errorf("duplicate app slug, they must be unique per template: %q", attrs.Slug)
}
appSlugs[attrs.Slug] = struct{}{}
@@ -341,7 +347,7 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
var attrs metadataAttributes
err = mapstructure.Decode(resource.AttributeValues, &attrs)
if err != nil {
- return nil, nil, xerrors.Errorf("decode metadata attributes: %w", err)
+ return nil, xerrors.Errorf("decode metadata attributes: %w", err)
}
resourceLabel := convertAddressToLabel(resource.Address)
@@ -432,7 +438,7 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
var param provider.Parameter
err = mapstructure.Decode(resource.AttributeValues, ¶m)
if err != nil {
- return nil, nil, xerrors.Errorf("decode map values for coder_parameter.%s: %w", resource.Name, err)
+ return nil, xerrors.Errorf("decode map values for coder_parameter.%s: %w", resource.Name, err)
}
protoParam := &proto.RichParameter{
Name: param.Name,
@@ -464,7 +470,30 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
}
}
- return resources, parameters, nil
+ // A map is used to ensure we don't have duplicates!
+ gitAuthProvidersMap := map[string]struct{}{}
+ for _, tfResources := range tfResourcesByLabel {
+ for _, resource := range tfResources {
+ if resource.Type != "coder_git_auth" {
+ continue
+ }
+ id, ok := resource.AttributeValues["id"].(string)
+ if !ok {
+ return nil, xerrors.Errorf("git auth id is not a string")
+ }
+ gitAuthProvidersMap[id] = struct{}{}
+ }
+ }
+ gitAuthProviders := make([]string, 0, len(gitAuthProvidersMap))
+ for id := range gitAuthProvidersMap {
+ gitAuthProviders = append(gitAuthProviders, id)
+ }
+
+ return &State{
+ Resources: resources,
+ Parameters: parameters,
+ GitAuthProviders: gitAuthProviders,
+ }, nil
}
// convertAddressToLabel returns the Terraform address without the count
diff --git a/provisioner/terraform/resources_test.go b/provisioner/terraform/resources_test.go
index cd2acb923df52..ef95ef5154ff8 100644
--- a/provisioner/terraform/resources_test.go
+++ b/provisioner/terraform/resources_test.go
@@ -22,8 +22,9 @@ func TestConvertResources(t *testing.T) {
// nolint:dogsled
_, filename, _, _ := runtime.Caller(0)
type testCase struct {
- resources []*proto.Resource
- parameters []*proto.RichParameter
+ resources []*proto.Resource
+ parameters []*proto.RichParameter
+ gitAuthProviders []string
}
// nolint:paralleltest
for folderName, expected := range map[string]testCase{
@@ -294,6 +295,22 @@ func TestConvertResources(t *testing.T) {
}},
}},
},
+ "git-auth-providers": {
+ resources: []*proto.Resource{{
+ Name: "dev",
+ Type: "null_resource",
+ Agents: []*proto.Agent{{
+ Name: "main",
+ OperatingSystem: "linux",
+ Architecture: "amd64",
+ Auth: &proto.Agent_Token{},
+ LoginBeforeReady: true,
+ ConnectionTimeoutSeconds: 120,
+ StartupScriptTimeoutSeconds: 300,
+ }},
+ }},
+ gitAuthProviders: []string{"github", "gitlab"},
+ },
} {
folderName := folderName
expected := expected
@@ -319,10 +336,11 @@ func TestConvertResources(t *testing.T) {
// and that no errors occur!
modules = append(modules, tfPlan.PlannedValues.RootModule)
}
- resources, parameters, err := terraform.ConvertResourcesAndParameters(modules, string(tfPlanGraph))
+ state, err := terraform.ConvertState(modules, string(tfPlanGraph))
require.NoError(t, err)
- sortResources(resources)
- sortParameters(parameters)
+ sortResources(state.Resources)
+ sortParameters(state.Parameters)
+ sort.Strings(state.GitAuthProviders)
expectedNoMetadata := make([]*proto.Resource, 0)
for _, resource := range expected.resources {
@@ -342,7 +360,7 @@ func TestConvertResources(t *testing.T) {
err = json.Unmarshal(data, &expectedNoMetadataMap)
require.NoError(t, err)
- data, err = json.Marshal(resources)
+ data, err = json.Marshal(state.Resources)
require.NoError(t, err)
var resourcesMap []map[string]interface{}
err = json.Unmarshal(data, &resourcesMap)
@@ -354,10 +372,12 @@ func TestConvertResources(t *testing.T) {
}
parametersWant, err := json.Marshal(expected.parameters)
require.NoError(t, err)
- parametersGot, err := json.Marshal(parameters)
+ parametersGot, err := json.Marshal(state.Parameters)
require.NoError(t, err)
require.Equal(t, string(parametersWant), string(parametersGot))
require.Equal(t, expectedNoMetadataMap, resourcesMap)
+
+ require.ElementsMatch(t, expected.gitAuthProviders, state.GitAuthProviders)
})
t.Run("Provision", func(t *testing.T) {
@@ -370,11 +390,12 @@ func TestConvertResources(t *testing.T) {
tfStateGraph, err := os.ReadFile(filepath.Join(dir, folderName+".tfstate.dot"))
require.NoError(t, err)
- resources, parameters, err := terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{tfState.Values.RootModule}, string(tfStateGraph))
+ state, err := terraform.ConvertState([]*tfjson.StateModule{tfState.Values.RootModule}, string(tfStateGraph))
require.NoError(t, err)
- sortResources(resources)
- sortParameters(parameters)
- for _, resource := range resources {
+ sortResources(state.Resources)
+ sortParameters(state.Parameters)
+ sort.Strings(state.GitAuthProviders)
+ for _, resource := range state.Resources {
for _, agent := range resource.Agents {
agent.Id = ""
if agent.GetToken() != "" {
@@ -393,13 +414,14 @@ func TestConvertResources(t *testing.T) {
err = json.Unmarshal(data, &expectedMap)
require.NoError(t, err)
- data, err = json.Marshal(resources)
+ data, err = json.Marshal(state.Resources)
require.NoError(t, err)
var resourcesMap []map[string]interface{}
err = json.Unmarshal(data, &resourcesMap)
require.NoError(t, err)
require.Equal(t, expectedMap, resourcesMap)
+ require.ElementsMatch(t, expected.gitAuthProviders, state.GitAuthProviders)
})
})
}
@@ -428,8 +450,8 @@ func TestAppSlugValidation(t *testing.T) {
}
}
- resources, _, err := terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{tfPlan.PlannedValues.RootModule}, string(tfPlanGraph))
- require.Nil(t, resources)
+ state, err := terraform.ConvertState([]*tfjson.StateModule{tfPlan.PlannedValues.RootModule}, string(tfPlanGraph))
+ require.Nil(t, state)
require.Error(t, err)
require.ErrorContains(t, err, "invalid app slug")
@@ -440,8 +462,8 @@ func TestAppSlugValidation(t *testing.T) {
}
}
- resources, _, err = terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{tfPlan.PlannedValues.RootModule}, string(tfPlanGraph))
- require.Nil(t, resources)
+ state, err = terraform.ConvertState([]*tfjson.StateModule{tfPlan.PlannedValues.RootModule}, string(tfPlanGraph))
+ require.Nil(t, state)
require.Error(t, err)
require.ErrorContains(t, err, "duplicate app slug")
}
@@ -473,7 +495,7 @@ func TestInstanceTypeAssociation(t *testing.T) {
t.Parallel()
instanceType, err := cryptorand.String(12)
require.NoError(t, err)
- resources, _, err := terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{{
+ state, err := terraform.ConvertState([]*tfjson.StateModule{{
Resources: []*tfjson.StateResource{{
Address: tc.ResourceType + ".dev",
Type: tc.ResourceType,
@@ -492,8 +514,8 @@ func TestInstanceTypeAssociation(t *testing.T) {
}
}`)
require.NoError(t, err)
- require.Len(t, resources, 1)
- require.Equal(t, resources[0].GetInstanceType(), instanceType)
+ require.Len(t, state.Resources, 1)
+ require.Equal(t, state.Resources[0].GetInstanceType(), instanceType)
})
}
}
@@ -531,7 +553,7 @@ func TestInstanceIDAssociation(t *testing.T) {
t.Parallel()
instanceID, err := cryptorand.String(12)
require.NoError(t, err)
- resources, _, err := terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{{
+ state, err := terraform.ConvertState([]*tfjson.StateModule{{
Resources: []*tfjson.StateResource{{
Address: "coder_agent.dev",
Type: "coder_agent",
@@ -563,9 +585,9 @@ func TestInstanceIDAssociation(t *testing.T) {
}
`)
require.NoError(t, err)
- require.Len(t, resources, 1)
- require.Len(t, resources[0].Agents, 1)
- require.Equal(t, resources[0].Agents[0].GetInstanceId(), instanceID)
+ require.Len(t, state.Resources, 1)
+ require.Len(t, state.Resources[0].Agents, 1)
+ require.Equal(t, state.Resources[0].Agents[0].GetInstanceId(), instanceID)
})
}
}
diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tf b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tf
new file mode 100644
index 0000000000000..e76479c459043
--- /dev/null
+++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tf
@@ -0,0 +1,27 @@
+terraform {
+ required_providers {
+ coder = {
+ source = "coder/coder"
+ version = "0.6.13"
+ }
+ }
+}
+
+data "coder_git_auth" "github" {
+ id = "github"
+}
+
+data "coder_git_auth" "gitlab" {
+ id = "gitlab"
+}
+
+resource "coder_agent" "main" {
+ os = "linux"
+ arch = "amd64"
+}
+
+resource "null_resource" "dev" {
+ depends_on = [
+ coder_agent.main
+ ]
+}
diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.dot b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.dot
new file mode 100644
index 0000000000000..3d0775104e9c8
--- /dev/null
+++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.dot
@@ -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_git_auth.github (expand)" [label = "data.coder_git_auth.github", shape = "box"]
+ "[root] data.coder_git_auth.gitlab (expand)" [label = "data.coder_git_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_git_auth.github (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
+ "[root] data.coder_git_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_git_auth.github (expand)"
+ "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_git_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)"
+ }
+}
+
diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.json b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.json
new file mode 100644
index 0000000000000..05d34d9265d50
--- /dev/null
+++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfplan.json
@@ -0,0 +1,212 @@
+{
+ "format_version": "1.1",
+ "terraform_version": "1.3.7",
+ "planned_values": {
+ "root_module": {
+ "resources": [
+ {
+ "address": "coder_agent.main",
+ "mode": "managed",
+ "type": "coder_agent",
+ "name": "main",
+ "provider_name": "registry.terraform.io/coder/coder",
+ "schema_version": 0,
+ "values": {
+ "arch": "amd64",
+ "auth": "token",
+ "connection_timeout": 120,
+ "dir": null,
+ "env": null,
+ "login_before_ready": true,
+ "motd_file": null,
+ "os": "linux",
+ "shutdown_script": null,
+ "shutdown_script_timeout": 300,
+ "startup_script": null,
+ "startup_script_timeout": 300,
+ "troubleshooting_url": null
+ },
+ "sensitive_values": {}
+ },
+ {
+ "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,
+ "motd_file": null,
+ "os": "linux",
+ "shutdown_script": null,
+ "shutdown_script_timeout": 300,
+ "startup_script": null,
+ "startup_script_timeout": 300,
+ "troubleshooting_url": null
+ },
+ "after_unknown": {
+ "id": true,
+ "init_script": true,
+ "token": true
+ },
+ "before_sensitive": false,
+ "after_sensitive": {
+ "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.3.7",
+ "values": {
+ "root_module": {
+ "resources": [
+ {
+ "address": "data.coder_git_auth.github",
+ "mode": "data",
+ "type": "coder_git_auth",
+ "name": "github",
+ "provider_name": "registry.terraform.io/coder/coder",
+ "schema_version": 0,
+ "values": {
+ "access_token": "",
+ "id": "github"
+ },
+ "sensitive_values": {}
+ },
+ {
+ "address": "data.coder_git_auth.gitlab",
+ "mode": "data",
+ "type": "coder_git_auth",
+ "name": "gitlab",
+ "provider_name": "registry.terraform.io/coder/coder",
+ "schema_version": 0,
+ "values": {
+ "access_token": "",
+ "id": "gitlab"
+ },
+ "sensitive_values": {}
+ }
+ ]
+ }
+ }
+ },
+ "configuration": {
+ "provider_config": {
+ "coder": {
+ "name": "coder",
+ "full_name": "registry.terraform.io/coder/coder",
+ "version_constraint": "0.6.13"
+ },
+ "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_git_auth.github",
+ "mode": "data",
+ "type": "coder_git_auth",
+ "name": "github",
+ "provider_config_key": "coder",
+ "expressions": {
+ "id": {
+ "constant_value": "github"
+ }
+ },
+ "schema_version": 0
+ },
+ {
+ "address": "data.coder_git_auth.gitlab",
+ "mode": "data",
+ "type": "coder_git_auth",
+ "name": "gitlab",
+ "provider_config_key": "coder",
+ "expressions": {
+ "id": {
+ "constant_value": "gitlab"
+ }
+ },
+ "schema_version": 0
+ }
+ ]
+ }
+ }
+}
diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.dot b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.dot
new file mode 100644
index 0000000000000..3d0775104e9c8
--- /dev/null
+++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.dot
@@ -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_git_auth.github (expand)" [label = "data.coder_git_auth.github", shape = "box"]
+ "[root] data.coder_git_auth.gitlab (expand)" [label = "data.coder_git_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_git_auth.github (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
+ "[root] data.coder_git_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_git_auth.github (expand)"
+ "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_git_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)"
+ }
+}
+
diff --git a/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.json b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.json
new file mode 100644
index 0000000000000..268ed84b45ae3
--- /dev/null
+++ b/provisioner/terraform/testdata/git-auth-providers/git-auth-providers.tfstate.json
@@ -0,0 +1,79 @@
+{
+ "format_version": "1.0",
+ "terraform_version": "1.3.7",
+ "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,
+ "id": "78b29f93-097d-403b-ab56-0bc943d427cc",
+ "init_script": "",
+ "login_before_ready": true,
+ "motd_file": null,
+ "os": "linux",
+ "shutdown_script": null,
+ "shutdown_script_timeout": 300,
+ "startup_script": null,
+ "startup_script_timeout": 300,
+ "token": "a57838e5-355c-471a-9a85-f81314fbaec6",
+ "troubleshooting_url": null
+ },
+ "sensitive_values": {}
+ },
+ {
+ "address": "data.coder_git_auth.github",
+ "mode": "data",
+ "type": "coder_git_auth",
+ "name": "github",
+ "provider_name": "registry.terraform.io/coder/coder",
+ "schema_version": 0,
+ "values": {
+ "access_token": "",
+ "id": "github"
+ },
+ "sensitive_values": {}
+ },
+ {
+ "address": "data.coder_git_auth.gitlab",
+ "mode": "data",
+ "type": "coder_git_auth",
+ "name": "gitlab",
+ "provider_name": "registry.terraform.io/coder/coder",
+ "schema_version": 0,
+ "values": {
+ "access_token": "",
+ "id": "gitlab"
+ },
+ "sensitive_values": {}
+ },
+ {
+ "address": "null_resource.dev",
+ "mode": "managed",
+ "type": "null_resource",
+ "name": "dev",
+ "provider_name": "registry.terraform.io/hashicorp/null",
+ "schema_version": 0,
+ "values": {
+ "id": "1416347524569828366",
+ "triggers": null
+ },
+ "sensitive_values": {},
+ "depends_on": [
+ "coder_agent.main"
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go
index e39e7c9ca27a8..f41912a1fa239 100644
--- a/provisionerd/proto/provisionerd.pb.go
+++ b/provisionerd/proto/provisionerd.pb.go
@@ -1213,9 +1213,10 @@ type CompletedJob_TemplateImport struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- 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"`
- RichParameters []*proto.RichParameter `protobuf:"bytes,3,rep,name=rich_parameters,json=richParameters,proto3" json:"rich_parameters,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"`
+ RichParameters []*proto.RichParameter `protobuf:"bytes,3,rep,name=rich_parameters,json=richParameters,proto3" json:"rich_parameters,omitempty"`
+ GitAuthProviders []string `protobuf:"bytes,4,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"`
}
func (x *CompletedJob_TemplateImport) Reset() {
@@ -1271,6 +1272,13 @@ func (x *CompletedJob_TemplateImport) GetRichParameters() []*proto.RichParameter
return nil
}
+func (x *CompletedJob_TemplateImport) GetGitAuthProviders() []string {
+ if x != nil {
+ return x.GitAuthProviders
+ }
+ return nil
+}
+
type CompletedJob_TemplateDryRun struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1435,7 +1443,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c,
0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70,
- 0x65, 0x22, 0xaa, 0x05, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a,
+ 0x65, 0x22, 0xd8, 0x05, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a,
0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x77, 0x6f, 0x72,
0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01,
@@ -1459,7 +1467,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x74, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09,
- 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0xd3, 0x01, 0x0a, 0x0e, 0x54, 0x65,
+ 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x81, 0x02, 0x0a, 0x0e, 0x54, 0x65,
0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3e, 0x0a, 0x0f,
0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
@@ -1472,98 +1480,100 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52,
- 0x0e, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x1a,
- 0x45, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75,
- 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
- 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb0,
- 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
- 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52,
- 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
- 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c,
- 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f,
- 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
- 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74,
- 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75,
- 0x74, 0x22, 0xcf, 0x02, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52,
+ 0x0e, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12,
+ 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74,
+ 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x45, 0x0a,
+ 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12,
+ 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
+ 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb0, 0x01, 0x0a,
+ 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
+ 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
+ 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76,
+ 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41,
+ 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75,
+ 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22,
+ 0xcf, 0x02, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x6c,
+ 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f,
+ 0x67, 0x73, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f,
+ 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
+ 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61,
+ 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, 0x70, 0x61, 0x72,
+ 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x4c, 0x0a,
+ 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61,
+ 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x14, 0x75,
+ 0x73, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x56, 0x61, 0x72, 0x69, 0x61,
+ 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61,
+ 0x64, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d,
+ 0x65, 0x22, 0xbc, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65,
+ 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65,
+ 0x6c, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
+ 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+ 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61,
+ 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61,
+ 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
+ 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73,
+ 0x22, 0x4a, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x25, 0x0a,
- 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72,
- 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04,
- 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
- 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61,
- 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, 0x70,
- 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12,
- 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69,
- 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72,
- 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61,
- 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70,
- 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x4c, 0x0a,
- 0x14, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72,
- 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
- 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x56, 0x61, 0x72,
- 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72,
- 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61,
- 0x64, 0x6d, 0x65, 0x22, 0xbc, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f,
- 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e,
- 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e,
- 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
- 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61,
- 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61,
- 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a,
- 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73,
- 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
- 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x73, 0x22, 0x4a, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74,
- 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f,
- 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12,
- 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x68,
- 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73,
- 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x0f, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64,
- 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
- 0x52, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x2a, 0x34, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49,
- 0x4f, 0x4e, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a,
- 0x0b, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x10, 0x01, 0x32, 0xec,
- 0x02, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61,
- 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0a, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a,
- 0x6f, 0x62, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
- 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
- 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a,
- 0x6f, 0x62, 0x12, 0x52, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74,
- 0x61, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64,
- 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
- 0x4a, 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12,
- 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46,
- 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
- 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a,
- 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70,
- 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
- 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
- 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x2b, 0x5a,
- 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65,
- 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
- 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x33,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x68, 0x0a, 0x13,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x02, 0x6f, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x5f, 0x63,
+ 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63,
+ 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x16,
+ 0x0a, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06,
+ 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x2a, 0x34, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e,
+ 0x45, 0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50,
+ 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x10, 0x01, 0x32, 0xec, 0x02, 0x0a,
+ 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x65, 0x6d,
+ 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0a, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62,
+ 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e,
+ 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
+ 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62,
+ 0x12, 0x52, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x12,
+ 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64,
+ 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f,
+ 0x62, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64,
+ 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64,
+ 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e,
+ 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69,
+ 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0b, 0x43,
+ 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f,
+ 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
+ 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x2b, 0x5a, 0x29, 0x67,
+ 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f,
+ 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
+ 0x72, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/provisionerd/proto/provisionerd.proto b/provisionerd/proto/provisionerd.proto
index 90ea7443ff5a2..e7f0d1924aee9 100644
--- a/provisionerd/proto/provisionerd.proto
+++ b/provisionerd/proto/provisionerd.proto
@@ -69,6 +69,7 @@ message CompletedJob {
repeated provisioner.Resource start_resources = 1;
repeated provisioner.Resource stop_resources = 2;
repeated provisioner.RichParameter rich_parameters = 3;
+ repeated string git_auth_providers = 4;
}
message TemplateDryRun {
repeated provisioner.Resource resources = 1;
diff --git a/provisionerd/provisionerd.go b/provisionerd/provisionerd.go
index 78dcb121da7cd..dd11099e2de0f 100644
--- a/provisionerd/provisionerd.go
+++ b/provisionerd/provisionerd.go
@@ -172,6 +172,11 @@ func (p *Server) connect(ctx context.Context) {
// An exponential back-off occurs when the connection is failing to dial.
// This is to prevent server spam in case of a coderd outage.
for retrier := retry.New(50*time.Millisecond, 10*time.Second); retrier.Wait(ctx); {
+ // It's possible for the provisioner daemon to be shut down
+ // before the wait is complete!
+ if p.isClosed() {
+ return
+ }
client, err := p.clientDialer(ctx)
if err != nil {
if errors.Is(err, context.Canceled) {
diff --git a/provisionerd/runner/runner.go b/provisionerd/runner/runner.go
index b1914c2247835..0b0f837607994 100644
--- a/provisionerd/runner/runner.go
+++ b/provisionerd/runner/runner.go
@@ -600,7 +600,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
Stage: "Detecting persistent resources",
CreatedAt: time.Now().UnixMilli(),
})
- startResources, parameters, err := r.runTemplateImportProvision(ctx, updateResponse.ParameterValues, updateResponse.VariableValues, &sdkproto.Provision_Metadata{
+ startProvision, err := r.runTemplateImportProvision(ctx, updateResponse.ParameterValues, updateResponse.VariableValues, &sdkproto.Provision_Metadata{
CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl,
WorkspaceTransition: sdkproto.WorkspaceTransition_START,
})
@@ -615,7 +615,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
Stage: "Detecting ephemeral resources",
CreatedAt: time.Now().UnixMilli(),
})
- stopResources, _, err := r.runTemplateImportProvision(ctx, updateResponse.ParameterValues, updateResponse.VariableValues, &sdkproto.Provision_Metadata{
+ stopProvision, err := r.runTemplateImportProvision(ctx, updateResponse.ParameterValues, updateResponse.VariableValues, &sdkproto.Provision_Metadata{
CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl,
WorkspaceTransition: sdkproto.WorkspaceTransition_STOP,
})
@@ -627,9 +627,10 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
JobId: r.job.JobId,
Type: &proto.CompletedJob_TemplateImport_{
TemplateImport: &proto.CompletedJob_TemplateImport{
- StartResources: startResources,
- StopResources: stopResources,
- RichParameters: parameters,
+ StartResources: startProvision.Resources,
+ StopResources: stopProvision.Resources,
+ RichParameters: startProvision.Parameters,
+ GitAuthProviders: startProvision.GitAuthProviders,
},
},
}, nil
@@ -680,16 +681,22 @@ func (r *Runner) runTemplateImportParse(ctx context.Context) ([]*sdkproto.Parame
}
}
+type templateImportProvision struct {
+ Resources []*sdkproto.Resource
+ Parameters []*sdkproto.RichParameter
+ GitAuthProviders []string
+}
+
// Performs a dry-run provision when importing a template.
// This is used to detect resources that would be provisioned for a workspace in various states.
// It doesn't define values for rich parameters as they're unknown during template import.
-func (r *Runner) runTemplateImportProvision(ctx context.Context, values []*sdkproto.ParameterValue, variableValues []*sdkproto.VariableValue, metadata *sdkproto.Provision_Metadata) ([]*sdkproto.Resource, []*sdkproto.RichParameter, error) {
+func (r *Runner) runTemplateImportProvision(ctx context.Context, values []*sdkproto.ParameterValue, variableValues []*sdkproto.VariableValue, metadata *sdkproto.Provision_Metadata) (*templateImportProvision, error) {
return r.runTemplateImportProvisionWithRichParameters(ctx, values, variableValues, nil, metadata)
}
// Performs a dry-run provision with provided rich parameters.
// This is used to detect resources that would be provisioned for a workspace in various states.
-func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Context, values []*sdkproto.ParameterValue, variableValues []*sdkproto.VariableValue, richParameterValues []*sdkproto.RichParameterValue, metadata *sdkproto.Provision_Metadata) ([]*sdkproto.Resource, []*sdkproto.RichParameter, error) {
+func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Context, values []*sdkproto.ParameterValue, variableValues []*sdkproto.VariableValue, richParameterValues []*sdkproto.RichParameterValue, metadata *sdkproto.Provision_Metadata) (*templateImportProvision, error) {
ctx, span := r.startTrace(ctx, tracing.FuncName())
defer span.End()
@@ -704,7 +711,7 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Contex
// to send the cancel to the provisioner
stream, err := r.provisioner.Provision(ctx)
if err != nil {
- return nil, nil, xerrors.Errorf("provision: %w", err)
+ return nil, xerrors.Errorf("provision: %w", err)
}
defer stream.Close()
go func() {
@@ -733,13 +740,13 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Contex
},
})
if err != nil {
- return nil, nil, xerrors.Errorf("start provision: %w", err)
+ return nil, xerrors.Errorf("start provision: %w", err)
}
for {
msg, err := stream.Recv()
if err != nil {
- return nil, nil, xerrors.Errorf("recv import provision: %w", err)
+ return nil, xerrors.Errorf("recv import provision: %w", err)
}
switch msgType := msg.Type.(type) {
case *sdkproto.Provision_Response_Log:
@@ -760,11 +767,11 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Contex
slog.F("error", msgType.Complete.Error),
)
- return nil, nil, xerrors.New(msgType.Complete.Error)
+ return nil, xerrors.New(msgType.Complete.Error)
}
if len(msgType.Complete.Parameters) > 0 && len(values) > 0 {
- return nil, nil, xerrors.Errorf(`rich parameters can't be used together with legacy parameters, set the coder provider flag "feature_use_managed_variables = true" to enable managed variables`)
+ return nil, xerrors.Errorf(`rich parameters can't be used together with legacy parameters, set the coder provider flag "feature_use_managed_variables = true" to enable managed variables`)
}
r.logger.Info(context.Background(), "parse dry-run provision successful",
@@ -773,9 +780,13 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters(ctx context.Contex
slog.F("state_length", len(msgType.Complete.State)),
)
- return msgType.Complete.Resources, msgType.Complete.Parameters, nil
+ return &templateImportProvision{
+ Resources: msgType.Complete.Resources,
+ Parameters: msgType.Complete.Parameters,
+ GitAuthProviders: msgType.Complete.GitAuthProviders,
+ }, nil
default:
- return nil, nil, xerrors.Errorf("invalid message type %q received from provisioner",
+ return nil, xerrors.Errorf("invalid message type %q received from provisioner",
reflect.TypeOf(msg.Type).String())
}
}
@@ -814,7 +825,7 @@ func (r *Runner) runTemplateDryRun(ctx context.Context) (*proto.CompletedJob, *p
}
// Run the template import provision task since it's already a dry run.
- resources, _, err := r.runTemplateImportProvisionWithRichParameters(ctx,
+ provision, err := r.runTemplateImportProvisionWithRichParameters(ctx,
r.job.GetTemplateDryRun().GetParameterValues(),
r.job.GetTemplateDryRun().GetVariableValues(),
r.job.GetTemplateDryRun().GetRichParameterValues(),
@@ -828,7 +839,7 @@ func (r *Runner) runTemplateDryRun(ctx context.Context) (*proto.CompletedJob, *p
JobId: r.job.JobId,
Type: &proto.CompletedJob_TemplateDryRun_{
TemplateDryRun: &proto.CompletedJob_TemplateDryRun{
- Resources: resources,
+ Resources: provision.Resources,
},
},
}, nil
diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go
index b30dd23392485..51f3a475f6022 100644
--- a/provisionersdk/proto/provisioner.pb.go
+++ b/provisionersdk/proto/provisioner.pb.go
@@ -1163,6 +1163,61 @@ func (x *InstanceIdentityAuth) GetInstanceId() string {
return ""
}
+type GitAuthProvider struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ AccessToken string `protobuf:"bytes,2,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
+}
+
+func (x *GitAuthProvider) Reset() {
+ *x = GitAuthProvider{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GitAuthProvider) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GitAuthProvider) ProtoMessage() {}
+
+func (x *GitAuthProvider) ProtoReflect() protoreflect.Message {
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[12]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GitAuthProvider.ProtoReflect.Descriptor instead.
+func (*GitAuthProvider) Descriptor() ([]byte, []int) {
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *GitAuthProvider) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *GitAuthProvider) GetAccessToken() string {
+ if x != nil {
+ return x.AccessToken
+ }
+ return ""
+}
+
// Agent represents a running agent on the workspace.
type Agent struct {
state protoimpl.MessageState
@@ -1192,7 +1247,7 @@ type Agent struct {
func (x *Agent) Reset() {
*x = Agent{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[12]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1205,7 +1260,7 @@ func (x *Agent) String() string {
func (*Agent) ProtoMessage() {}
func (x *Agent) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[12]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1218,7 +1273,7 @@ func (x *Agent) ProtoReflect() protoreflect.Message {
// Deprecated: Use Agent.ProtoReflect.Descriptor instead.
func (*Agent) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{12}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{13}
}
func (x *Agent) GetId() string {
@@ -1371,7 +1426,7 @@ type App struct {
func (x *App) Reset() {
*x = App{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1384,7 +1439,7 @@ func (x *App) String() string {
func (*App) ProtoMessage() {}
func (x *App) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[13]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1397,7 +1452,7 @@ func (x *App) ProtoReflect() protoreflect.Message {
// Deprecated: Use App.ProtoReflect.Descriptor instead.
func (*App) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{13}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14}
}
func (x *App) GetSlug() string {
@@ -1477,7 +1532,7 @@ type Healthcheck struct {
func (x *Healthcheck) Reset() {
*x = Healthcheck{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1490,7 +1545,7 @@ func (x *Healthcheck) String() string {
func (*Healthcheck) ProtoMessage() {}
func (x *Healthcheck) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[14]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1503,7 +1558,7 @@ func (x *Healthcheck) ProtoReflect() protoreflect.Message {
// Deprecated: Use Healthcheck.ProtoReflect.Descriptor instead.
func (*Healthcheck) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{14}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{15}
}
func (x *Healthcheck) GetUrl() string {
@@ -1546,7 +1601,7 @@ type Resource struct {
func (x *Resource) Reset() {
*x = Resource{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1559,7 +1614,7 @@ func (x *Resource) String() string {
func (*Resource) ProtoMessage() {}
func (x *Resource) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[15]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1572,7 +1627,7 @@ func (x *Resource) ProtoReflect() protoreflect.Message {
// Deprecated: Use Resource.ProtoReflect.Descriptor instead.
func (*Resource) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{15}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{16}
}
func (x *Resource) GetName() string {
@@ -1641,7 +1696,7 @@ type Parse struct {
func (x *Parse) Reset() {
*x = Parse{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1654,7 +1709,7 @@ func (x *Parse) String() string {
func (*Parse) ProtoMessage() {}
func (x *Parse) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[16]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1667,7 +1722,7 @@ func (x *Parse) ProtoReflect() protoreflect.Message {
// Deprecated: Use Parse.ProtoReflect.Descriptor instead.
func (*Parse) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{16}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17}
}
// Provision consumes source-code from a directory to produce resources.
@@ -1681,7 +1736,7 @@ type Provision struct {
func (x *Provision) Reset() {
*x = Provision{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1694,7 +1749,7 @@ func (x *Provision) String() string {
func (*Provision) ProtoMessage() {}
func (x *Provision) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[17]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1707,7 +1762,7 @@ func (x *Provision) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision.ProtoReflect.Descriptor instead.
func (*Provision) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18}
}
type Resource_Metadata struct {
@@ -1724,7 +1779,7 @@ type Resource_Metadata struct {
func (x *Resource_Metadata) Reset() {
*x = Resource_Metadata{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1737,7 +1792,7 @@ func (x *Resource_Metadata) String() string {
func (*Resource_Metadata) ProtoMessage() {}
func (x *Resource_Metadata) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[19]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1750,7 +1805,7 @@ func (x *Resource_Metadata) ProtoReflect() protoreflect.Message {
// Deprecated: Use Resource_Metadata.ProtoReflect.Descriptor instead.
func (*Resource_Metadata) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{15, 0}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{16, 0}
}
func (x *Resource_Metadata) GetKey() string {
@@ -1792,7 +1847,7 @@ type Parse_Request struct {
func (x *Parse_Request) Reset() {
*x = Parse_Request{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1805,7 +1860,7 @@ func (x *Parse_Request) String() string {
func (*Parse_Request) ProtoMessage() {}
func (x *Parse_Request) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[20]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1818,7 +1873,7 @@ func (x *Parse_Request) ProtoReflect() protoreflect.Message {
// Deprecated: Use Parse_Request.ProtoReflect.Descriptor instead.
func (*Parse_Request) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{16, 0}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 0}
}
func (x *Parse_Request) GetDirectory() string {
@@ -1840,7 +1895,7 @@ type Parse_Complete struct {
func (x *Parse_Complete) Reset() {
*x = Parse_Complete{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1853,7 +1908,7 @@ func (x *Parse_Complete) String() string {
func (*Parse_Complete) ProtoMessage() {}
func (x *Parse_Complete) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[21]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1866,7 +1921,7 @@ func (x *Parse_Complete) ProtoReflect() protoreflect.Message {
// Deprecated: Use Parse_Complete.ProtoReflect.Descriptor instead.
func (*Parse_Complete) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{16, 1}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 1}
}
func (x *Parse_Complete) GetTemplateVariables() []*TemplateVariable {
@@ -1898,7 +1953,7 @@ type Parse_Response struct {
func (x *Parse_Response) Reset() {
*x = Parse_Response{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1911,7 +1966,7 @@ func (x *Parse_Response) String() string {
func (*Parse_Response) ProtoMessage() {}
func (x *Parse_Response) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[22]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[23]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1924,7 +1979,7 @@ func (x *Parse_Response) ProtoReflect() protoreflect.Message {
// Deprecated: Use Parse_Response.ProtoReflect.Descriptor instead.
func (*Parse_Response) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{16, 2}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 2}
}
func (m *Parse_Response) GetType() isParse_Response_Type {
@@ -1983,7 +2038,7 @@ type Provision_Metadata struct {
func (x *Provision_Metadata) Reset() {
*x = Provision_Metadata{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[23]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1996,7 +2051,7 @@ func (x *Provision_Metadata) String() string {
func (*Provision_Metadata) ProtoMessage() {}
func (x *Provision_Metadata) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[23]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[24]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2009,7 +2064,7 @@ func (x *Provision_Metadata) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision_Metadata.ProtoReflect.Descriptor instead.
func (*Provision_Metadata) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 0}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18, 0}
}
func (x *Provision_Metadata) GetCoderUrl() string {
@@ -2090,7 +2145,7 @@ type Provision_Config struct {
func (x *Provision_Config) Reset() {
*x = Provision_Config{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[24]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2103,7 +2158,7 @@ func (x *Provision_Config) String() string {
func (*Provision_Config) ProtoMessage() {}
func (x *Provision_Config) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[24]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2116,7 +2171,7 @@ func (x *Provision_Config) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision_Config.ProtoReflect.Descriptor instead.
func (*Provision_Config) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 1}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18, 1}
}
func (x *Provision_Config) GetDirectory() string {
@@ -2149,12 +2204,13 @@ type Provision_Plan struct {
ParameterValues []*ParameterValue `protobuf:"bytes,2,rep,name=parameter_values,json=parameterValues,proto3" json:"parameter_values,omitempty"`
RichParameterValues []*RichParameterValue `protobuf:"bytes,3,rep,name=rich_parameter_values,json=richParameterValues,proto3" json:"rich_parameter_values,omitempty"`
VariableValues []*VariableValue `protobuf:"bytes,4,rep,name=variable_values,json=variableValues,proto3" json:"variable_values,omitempty"`
+ GitAuthProviders []*GitAuthProvider `protobuf:"bytes,5,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"`
}
func (x *Provision_Plan) Reset() {
*x = Provision_Plan{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2167,7 +2223,7 @@ func (x *Provision_Plan) String() string {
func (*Provision_Plan) ProtoMessage() {}
func (x *Provision_Plan) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[25]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2180,7 +2236,7 @@ func (x *Provision_Plan) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision_Plan.ProtoReflect.Descriptor instead.
func (*Provision_Plan) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 2}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18, 2}
}
func (x *Provision_Plan) GetConfig() *Provision_Config {
@@ -2211,6 +2267,13 @@ func (x *Provision_Plan) GetVariableValues() []*VariableValue {
return nil
}
+func (x *Provision_Plan) GetGitAuthProviders() []*GitAuthProvider {
+ if x != nil {
+ return x.GitAuthProviders
+ }
+ return nil
+}
+
type Provision_Apply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -2223,7 +2286,7 @@ type Provision_Apply struct {
func (x *Provision_Apply) Reset() {
*x = Provision_Apply{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2236,7 +2299,7 @@ func (x *Provision_Apply) String() string {
func (*Provision_Apply) ProtoMessage() {}
func (x *Provision_Apply) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[26]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2249,7 +2312,7 @@ func (x *Provision_Apply) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision_Apply.ProtoReflect.Descriptor instead.
func (*Provision_Apply) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 3}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18, 3}
}
func (x *Provision_Apply) GetConfig() *Provision_Config {
@@ -2275,7 +2338,7 @@ type Provision_Cancel struct {
func (x *Provision_Cancel) Reset() {
*x = Provision_Cancel{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2288,7 +2351,7 @@ func (x *Provision_Cancel) String() string {
func (*Provision_Cancel) ProtoMessage() {}
func (x *Provision_Cancel) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[27]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2301,7 +2364,7 @@ func (x *Provision_Cancel) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision_Cancel.ProtoReflect.Descriptor instead.
func (*Provision_Cancel) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 4}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18, 4}
}
type Provision_Request struct {
@@ -2320,7 +2383,7 @@ type Provision_Request struct {
func (x *Provision_Request) Reset() {
*x = Provision_Request{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2333,7 +2396,7 @@ func (x *Provision_Request) String() string {
func (*Provision_Request) ProtoMessage() {}
func (x *Provision_Request) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[28]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[29]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2346,7 +2409,7 @@ func (x *Provision_Request) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision_Request.ProtoReflect.Descriptor instead.
func (*Provision_Request) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 5}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18, 5}
}
func (m *Provision_Request) GetType() isProvision_Request_Type {
@@ -2404,17 +2467,18 @@ type Provision_Complete struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
- Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
- Resources []*Resource `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"`
- Parameters []*RichParameter `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty"`
- Plan []byte `protobuf:"bytes,5,opt,name=plan,proto3" json:"plan,omitempty"`
+ State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
+ Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
+ Resources []*Resource `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"`
+ Parameters []*RichParameter `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty"`
+ GitAuthProviders []string `protobuf:"bytes,5,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"`
+ Plan []byte `protobuf:"bytes,6,opt,name=plan,proto3" json:"plan,omitempty"`
}
func (x *Provision_Complete) Reset() {
*x = Provision_Complete{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[29]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[30]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2427,7 +2491,7 @@ func (x *Provision_Complete) String() string {
func (*Provision_Complete) ProtoMessage() {}
func (x *Provision_Complete) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[29]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[30]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2440,7 +2504,7 @@ func (x *Provision_Complete) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision_Complete.ProtoReflect.Descriptor instead.
func (*Provision_Complete) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 6}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18, 6}
}
func (x *Provision_Complete) GetState() []byte {
@@ -2471,6 +2535,13 @@ func (x *Provision_Complete) GetParameters() []*RichParameter {
return nil
}
+func (x *Provision_Complete) GetGitAuthProviders() []string {
+ if x != nil {
+ return x.GitAuthProviders
+ }
+ return nil
+}
+
func (x *Provision_Complete) GetPlan() []byte {
if x != nil {
return x.Plan
@@ -2493,7 +2564,7 @@ type Provision_Response struct {
func (x *Provision_Response) Reset() {
*x = Provision_Response{}
if protoimpl.UnsafeEnabled {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[30]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[31]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2506,7 +2577,7 @@ func (x *Provision_Response) String() string {
func (*Provision_Response) ProtoMessage() {}
func (x *Provision_Response) ProtoReflect() protoreflect.Message {
- mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[30]
+ mi := &file_provisionersdk_proto_provisioner_proto_msgTypes[31]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2519,7 +2590,7 @@ func (x *Provision_Response) ProtoReflect() protoreflect.Message {
// Deprecated: Use Provision_Response.ProtoReflect.Descriptor instead.
func (*Provision_Response) Descriptor() ([]byte, []int) {
- return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{17, 7}
+ return file_provisionersdk_proto_provisioner_proto_rawDescGZIP(), []int{18, 7}
}
func (m *Provision_Response) GetType() isProvision_Response_Type {
@@ -2698,199 +2769,211 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{
0x70, 0x75, 0x74, 0x22, 0x37, 0x0a, 0x14, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x75, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x69,
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x8e, 0x05, 0x0a,
- 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6e,
- 0x76, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
- 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x76, 0x45,
- 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x74, 0x61,
- 0x72, 0x74, 0x75, 0x70, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x79,
- 0x73, 0x74, 0x65, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72,
- 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x22, 0x0a, 0x0c, 0x61,
- 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12,
- 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a,
- 0x04, 0x61, 0x70, 0x70, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72,
- 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x04, 0x61,
- 0x70, 0x70, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01,
- 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x21, 0x0a, 0x0b, 0x69,
- 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09,
- 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x3c,
- 0x0a, 0x1a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d,
- 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x01,
- 0x28, 0x05, 0x52, 0x18, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69,
- 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x13,
- 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x73, 0x68, 0x6f, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f,
- 0x75, 0x72, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x74, 0x72, 0x6f, 0x75, 0x62,
- 0x6c, 0x65, 0x73, 0x68, 0x6f, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a,
- 0x09, 0x6d, 0x6f, 0x74, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x6d, 0x6f, 0x74, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f,
- 0x67, 0x69, 0x6e, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79,
- 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x65, 0x66,
- 0x6f, 0x72, 0x65, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x43, 0x0a, 0x1e, 0x73, 0x74, 0x61, 0x72,
- 0x74, 0x75, 0x70, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f,
- 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05,
- 0x52, 0x1b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54,
- 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x1a, 0x36, 0x0a,
- 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x22, 0xb5, 0x02,
- 0x0a, 0x03, 0x41, 0x70, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73,
- 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07,
- 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63,
- 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e,
- 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09,
- 0x73, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x09, 0x73, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x0b, 0x68, 0x65,
- 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x48, 0x65,
- 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74,
- 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x41, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e,
- 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x53,
- 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x0c, 0x73, 0x68, 0x61,
- 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74,
- 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74,
- 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x22, 0x59, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63,
- 0x68, 0x65, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
- 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
- 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64,
- 0x22, 0xf1, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18,
- 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
- 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74,
- 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
- 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a,
- 0x04, 0x68, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x68, 0x69, 0x64,
- 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
- 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e,
- 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61,
- 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
- 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x1a, 0x69, 0x0a, 0x08, 0x4d, 0x65, 0x74,
- 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a,
- 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69,
- 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73,
- 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0xcb, 0x02, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27,
- 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72,
- 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69,
- 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x1a, 0xa3, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70,
- 0x6c, 0x65, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
- 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54,
- 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52,
- 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c,
- 0x65, 0x73, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f,
- 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61,
- 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, 0x70, 0x61, 0x72,
- 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x1a, 0x73, 0x0a,
- 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
- 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12,
- 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
- 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00,
- 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79,
- 0x70, 0x65, 0x22, 0x97, 0x0b, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
- 0x1a, 0xa1, 0x03, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a,
- 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a, 0x14, 0x77, 0x6f,
- 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
- 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
- 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
- 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b,
- 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12,
- 0x25, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
- 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
- 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12,
- 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18,
- 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
- 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f,
- 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10,
- 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64,
- 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77,
- 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x45,
- 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
- 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d,
- 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6d,
- 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72,
- 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x79, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c,
- 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05,
- 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61,
- 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
- 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74,
- 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a,
- 0x9f, 0x02, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x35, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
- 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
- 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
- 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76,
- 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
- 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
- 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x53, 0x0a, 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f,
- 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73,
- 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
- 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
- 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72,
- 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f,
- 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18,
- 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
- 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65,
- 0x73, 0x1a, 0x52, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x35, 0x0a, 0x06, 0x63, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f,
+ 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x44, 0x0a, 0x0f,
+ 0x47, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12,
+ 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12,
+ 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b,
+ 0x65, 0x6e, 0x22, 0x8e, 0x05, 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+ 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+ 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e,
+ 0x74, 0x2e, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12,
+ 0x25, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
+ 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72,
+ 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f,
+ 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x04, 0x61, 0x70, 0x70, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
+ 0x41, 0x70, 0x70, 0x52, 0x04, 0x61, 0x70, 0x70, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b,
+ 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65,
+ 0x6e, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64,
+ 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e,
+ 0x63, 0x65, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x18, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x73, 0x68, 0x6f,
+ 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x12, 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x73, 0x68, 0x6f, 0x6f, 0x74, 0x69, 0x6e, 0x67,
+ 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x6f, 0x74, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65,
+ 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x6f, 0x74, 0x64, 0x46, 0x69, 0x6c, 0x65,
+ 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6c, 0x6f,
+ 0x67, 0x69, 0x6e, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x43,
+ 0x0a, 0x1e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73,
+ 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x53,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x73, 0x1a, 0x36, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+ 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+ 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61,
+ 0x75, 0x74, 0x68, 0x22, 0xb5, 0x02, 0x0a, 0x03, 0x41, 0x70, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x73,
+ 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12,
+ 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61,
+ 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03,
+ 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12,
+ 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63,
+ 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
+ 0x12, 0x3a, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
+ 0x6e, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52,
+ 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x41, 0x0a, 0x0d,
+ 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x08, 0x20,
+ 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
+ 0x72, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65,
+ 0x6c, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12,
+ 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x22, 0x59, 0x0a, 0x0b, 0x48,
+ 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72,
+ 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65,
+ 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x68, 0x72,
+ 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0xf1, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x61,
+ 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72,
+ 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52,
+ 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
+ 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
+ 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x04, 0x68, 0x69, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69,
+ 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x08,
+ 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x1a,
+ 0x69, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b,
+ 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76,
+ 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0xcb, 0x02, 0x0a, 0x05, 0x50,
+ 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+ 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x1a, 0xa3, 0x01,
+ 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x12, 0x74, 0x65,
+ 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61,
+ 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
+ 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d,
+ 0x61, 0x52, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65,
+ 0x6d, 0x61, 0x73, 0x1a, 0x73, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+ 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00,
+ 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
+ 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
+ 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65,
+ 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x91, 0x0c, 0x0a, 0x09, 0x50, 0x72, 0x6f,
+ 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xa1, 0x03, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64,
+ 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c,
+ 0x12, 0x53, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20,
+ 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72,
+ 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
+ 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77,
+ 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f,
+ 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
+ 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
+ 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72,
+ 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f,
+ 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
+ 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65,
+ 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+ 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c,
+ 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x79, 0x0a, 0x06, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f,
+ 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f,
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
- 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
- 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x1a, 0x08, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x1a,
- 0xb3, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x70,
- 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76,
- 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
- 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x34,
- 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76,
- 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x48, 0x00, 0x52, 0x05, 0x61,
- 0x70, 0x70, 0x6c, 0x79, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
- 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x6e,
- 0x63, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a,
- 0x04, 0x74, 0x79, 0x70, 0x65, 0x1a, 0xbb, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
- 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f,
- 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33,
- 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
- 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
- 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
- 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65,
- 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12,
- 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70,
+ 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0xeb, 0x02, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x35,
+ 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d,
+ 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f,
+ 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
+ 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61,
+ 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61,
+ 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x53, 0x0a,
+ 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50,
+ 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x72,
+ 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72,
+ 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61,
+ 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
+ 0x72, 0x2e, 0x47, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x72, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64,
+ 0x65, 0x72, 0x73, 0x1a, 0x52, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x35, 0x0a, 0x06,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69,
+ 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x1a, 0x08, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65,
+ 0x6c, 0x1a, 0xb3, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a,
+ 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72,
+ 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73,
+ 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e,
+ 0x12, 0x34, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72,
+ 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x48, 0x00, 0x52,
+ 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
+ 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43,
+ 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42,
+ 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x1a, 0xe9, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70,
+ 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
+ 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
+ 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61,
+ 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
+ 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72,
+ 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67,
+ 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12,
+ 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70,
0x6c, 0x61, 0x6e, 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70,
0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00,
@@ -2939,7 +3022,7 @@ func file_provisionersdk_proto_provisioner_proto_rawDescGZIP() []byte {
}
var file_provisionersdk_proto_provisioner_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
-var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 31)
+var file_provisionersdk_proto_provisioner_proto_msgTypes = make([]protoimpl.MessageInfo, 32)
var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{
(LogLevel)(0), // 0: provisioner.LogLevel
(AppSharingLevel)(0), // 1: provisioner.AppSharingLevel
@@ -2959,25 +3042,26 @@ var file_provisionersdk_proto_provisioner_proto_goTypes = []interface{}{
(*VariableValue)(nil), // 15: provisioner.VariableValue
(*Log)(nil), // 16: provisioner.Log
(*InstanceIdentityAuth)(nil), // 17: provisioner.InstanceIdentityAuth
- (*Agent)(nil), // 18: provisioner.Agent
- (*App)(nil), // 19: provisioner.App
- (*Healthcheck)(nil), // 20: provisioner.Healthcheck
- (*Resource)(nil), // 21: provisioner.Resource
- (*Parse)(nil), // 22: provisioner.Parse
- (*Provision)(nil), // 23: provisioner.Provision
- nil, // 24: provisioner.Agent.EnvEntry
- (*Resource_Metadata)(nil), // 25: provisioner.Resource.Metadata
- (*Parse_Request)(nil), // 26: provisioner.Parse.Request
- (*Parse_Complete)(nil), // 27: provisioner.Parse.Complete
- (*Parse_Response)(nil), // 28: provisioner.Parse.Response
- (*Provision_Metadata)(nil), // 29: provisioner.Provision.Metadata
- (*Provision_Config)(nil), // 30: provisioner.Provision.Config
- (*Provision_Plan)(nil), // 31: provisioner.Provision.Plan
- (*Provision_Apply)(nil), // 32: provisioner.Provision.Apply
- (*Provision_Cancel)(nil), // 33: provisioner.Provision.Cancel
- (*Provision_Request)(nil), // 34: provisioner.Provision.Request
- (*Provision_Complete)(nil), // 35: provisioner.Provision.Complete
- (*Provision_Response)(nil), // 36: provisioner.Provision.Response
+ (*GitAuthProvider)(nil), // 18: provisioner.GitAuthProvider
+ (*Agent)(nil), // 19: provisioner.Agent
+ (*App)(nil), // 20: provisioner.App
+ (*Healthcheck)(nil), // 21: provisioner.Healthcheck
+ (*Resource)(nil), // 22: provisioner.Resource
+ (*Parse)(nil), // 23: provisioner.Parse
+ (*Provision)(nil), // 24: provisioner.Provision
+ nil, // 25: provisioner.Agent.EnvEntry
+ (*Resource_Metadata)(nil), // 26: provisioner.Resource.Metadata
+ (*Parse_Request)(nil), // 27: provisioner.Parse.Request
+ (*Parse_Complete)(nil), // 28: provisioner.Parse.Complete
+ (*Parse_Response)(nil), // 29: provisioner.Parse.Response
+ (*Provision_Metadata)(nil), // 30: provisioner.Provision.Metadata
+ (*Provision_Config)(nil), // 31: provisioner.Provision.Config
+ (*Provision_Plan)(nil), // 32: provisioner.Provision.Plan
+ (*Provision_Apply)(nil), // 33: provisioner.Provision.Apply
+ (*Provision_Cancel)(nil), // 34: provisioner.Provision.Cancel
+ (*Provision_Request)(nil), // 35: provisioner.Provision.Request
+ (*Provision_Complete)(nil), // 36: provisioner.Provision.Complete
+ (*Provision_Response)(nil), // 37: provisioner.Provision.Response
}
var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{
3, // 0: provisioner.ParameterSource.scheme:type_name -> provisioner.ParameterSource.Scheme
@@ -2988,39 +3072,40 @@ var file_provisionersdk_proto_provisioner_proto_depIdxs = []int32{
5, // 5: provisioner.ParameterSchema.validation_type_system:type_name -> provisioner.ParameterSchema.TypeSystem
12, // 6: provisioner.RichParameter.options:type_name -> provisioner.RichParameterOption
0, // 7: provisioner.Log.level:type_name -> provisioner.LogLevel
- 24, // 8: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry
- 19, // 9: provisioner.Agent.apps:type_name -> provisioner.App
- 20, // 10: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck
+ 25, // 8: provisioner.Agent.env:type_name -> provisioner.Agent.EnvEntry
+ 20, // 9: provisioner.Agent.apps:type_name -> provisioner.App
+ 21, // 10: provisioner.App.healthcheck:type_name -> provisioner.Healthcheck
1, // 11: provisioner.App.sharing_level:type_name -> provisioner.AppSharingLevel
- 18, // 12: provisioner.Resource.agents:type_name -> provisioner.Agent
- 25, // 13: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata
+ 19, // 12: provisioner.Resource.agents:type_name -> provisioner.Agent
+ 26, // 13: provisioner.Resource.metadata:type_name -> provisioner.Resource.Metadata
11, // 14: provisioner.Parse.Complete.template_variables:type_name -> provisioner.TemplateVariable
10, // 15: provisioner.Parse.Complete.parameter_schemas:type_name -> provisioner.ParameterSchema
16, // 16: provisioner.Parse.Response.log:type_name -> provisioner.Log
- 27, // 17: provisioner.Parse.Response.complete:type_name -> provisioner.Parse.Complete
+ 28, // 17: provisioner.Parse.Response.complete:type_name -> provisioner.Parse.Complete
2, // 18: provisioner.Provision.Metadata.workspace_transition:type_name -> provisioner.WorkspaceTransition
- 29, // 19: provisioner.Provision.Config.metadata:type_name -> provisioner.Provision.Metadata
- 30, // 20: provisioner.Provision.Plan.config:type_name -> provisioner.Provision.Config
+ 30, // 19: provisioner.Provision.Config.metadata:type_name -> provisioner.Provision.Metadata
+ 31, // 20: provisioner.Provision.Plan.config:type_name -> provisioner.Provision.Config
9, // 21: provisioner.Provision.Plan.parameter_values:type_name -> provisioner.ParameterValue
14, // 22: provisioner.Provision.Plan.rich_parameter_values:type_name -> provisioner.RichParameterValue
15, // 23: provisioner.Provision.Plan.variable_values:type_name -> provisioner.VariableValue
- 30, // 24: provisioner.Provision.Apply.config:type_name -> provisioner.Provision.Config
- 31, // 25: provisioner.Provision.Request.plan:type_name -> provisioner.Provision.Plan
- 32, // 26: provisioner.Provision.Request.apply:type_name -> provisioner.Provision.Apply
- 33, // 27: provisioner.Provision.Request.cancel:type_name -> provisioner.Provision.Cancel
- 21, // 28: provisioner.Provision.Complete.resources:type_name -> provisioner.Resource
- 13, // 29: provisioner.Provision.Complete.parameters:type_name -> provisioner.RichParameter
- 16, // 30: provisioner.Provision.Response.log:type_name -> provisioner.Log
- 35, // 31: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete
- 26, // 32: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request
- 34, // 33: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request
- 28, // 34: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response
- 36, // 35: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response
- 34, // [34:36] is the sub-list for method output_type
- 32, // [32:34] is the sub-list for method input_type
- 32, // [32:32] is the sub-list for extension type_name
- 32, // [32:32] is the sub-list for extension extendee
- 0, // [0:32] is the sub-list for field type_name
+ 18, // 24: provisioner.Provision.Plan.git_auth_providers:type_name -> provisioner.GitAuthProvider
+ 31, // 25: provisioner.Provision.Apply.config:type_name -> provisioner.Provision.Config
+ 32, // 26: provisioner.Provision.Request.plan:type_name -> provisioner.Provision.Plan
+ 33, // 27: provisioner.Provision.Request.apply:type_name -> provisioner.Provision.Apply
+ 34, // 28: provisioner.Provision.Request.cancel:type_name -> provisioner.Provision.Cancel
+ 22, // 29: provisioner.Provision.Complete.resources:type_name -> provisioner.Resource
+ 13, // 30: provisioner.Provision.Complete.parameters:type_name -> provisioner.RichParameter
+ 16, // 31: provisioner.Provision.Response.log:type_name -> provisioner.Log
+ 36, // 32: provisioner.Provision.Response.complete:type_name -> provisioner.Provision.Complete
+ 27, // 33: provisioner.Provisioner.Parse:input_type -> provisioner.Parse.Request
+ 35, // 34: provisioner.Provisioner.Provision:input_type -> provisioner.Provision.Request
+ 29, // 35: provisioner.Provisioner.Parse:output_type -> provisioner.Parse.Response
+ 37, // 36: provisioner.Provisioner.Provision:output_type -> provisioner.Provision.Response
+ 35, // [35:37] is the sub-list for method output_type
+ 33, // [33:35] is the sub-list for method input_type
+ 33, // [33:33] is the sub-list for extension type_name
+ 33, // [33:33] is the sub-list for extension extendee
+ 0, // [0:33] is the sub-list for field type_name
}
func init() { file_provisionersdk_proto_provisioner_proto_init() }
@@ -3174,7 +3259,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
}
}
file_provisionersdk_proto_provisioner_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Agent); i {
+ switch v := v.(*GitAuthProvider); i {
case 0:
return &v.state
case 1:
@@ -3186,7 +3271,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
}
}
file_provisionersdk_proto_provisioner_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*App); i {
+ switch v := v.(*Agent); i {
case 0:
return &v.state
case 1:
@@ -3198,7 +3283,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
}
}
file_provisionersdk_proto_provisioner_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Healthcheck); i {
+ switch v := v.(*App); i {
case 0:
return &v.state
case 1:
@@ -3210,7 +3295,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
}
}
file_provisionersdk_proto_provisioner_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Resource); i {
+ switch v := v.(*Healthcheck); i {
case 0:
return &v.state
case 1:
@@ -3222,7 +3307,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
}
}
file_provisionersdk_proto_provisioner_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Parse); i {
+ switch v := v.(*Resource); i {
case 0:
return &v.state
case 1:
@@ -3234,6 +3319,18 @@ func file_provisionersdk_proto_provisioner_proto_init() {
}
}
file_provisionersdk_proto_provisioner_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Parse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_provisionersdk_proto_provisioner_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision); i {
case 0:
return &v.state
@@ -3245,7 +3342,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Resource_Metadata); i {
case 0:
return &v.state
@@ -3257,7 +3354,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Parse_Request); i {
case 0:
return &v.state
@@ -3269,7 +3366,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Parse_Complete); i {
case 0:
return &v.state
@@ -3281,7 +3378,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Parse_Response); i {
case 0:
return &v.state
@@ -3293,7 +3390,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Metadata); i {
case 0:
return &v.state
@@ -3305,7 +3402,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Config); i {
case 0:
return &v.state
@@ -3317,7 +3414,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Plan); i {
case 0:
return &v.state
@@ -3329,7 +3426,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Apply); i {
case 0:
return &v.state
@@ -3341,7 +3438,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Cancel); i {
case 0:
return &v.state
@@ -3353,7 +3450,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Request); i {
case 0:
return &v.state
@@ -3365,7 +3462,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Complete); i {
case 0:
return &v.state
@@ -3377,7 +3474,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
return nil
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} {
+ file_provisionersdk_proto_provisioner_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Provision_Response); i {
case 0:
return &v.state
@@ -3390,20 +3487,20 @@ func file_provisionersdk_proto_provisioner_proto_init() {
}
}
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[12].OneofWrappers = []interface{}{
+ file_provisionersdk_proto_provisioner_proto_msgTypes[13].OneofWrappers = []interface{}{
(*Agent_Token)(nil),
(*Agent_InstanceId)(nil),
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[22].OneofWrappers = []interface{}{
+ file_provisionersdk_proto_provisioner_proto_msgTypes[23].OneofWrappers = []interface{}{
(*Parse_Response_Log)(nil),
(*Parse_Response_Complete)(nil),
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[28].OneofWrappers = []interface{}{
+ file_provisionersdk_proto_provisioner_proto_msgTypes[29].OneofWrappers = []interface{}{
(*Provision_Request_Plan)(nil),
(*Provision_Request_Apply)(nil),
(*Provision_Request_Cancel)(nil),
}
- file_provisionersdk_proto_provisioner_proto_msgTypes[30].OneofWrappers = []interface{}{
+ file_provisionersdk_proto_provisioner_proto_msgTypes[31].OneofWrappers = []interface{}{
(*Provision_Response_Log)(nil),
(*Provision_Response_Complete)(nil),
}
@@ -3413,7 +3510,7 @@ func file_provisionersdk_proto_provisioner_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_provisionersdk_proto_provisioner_proto_rawDesc,
NumEnums: 6,
- NumMessages: 31,
+ NumMessages: 32,
NumExtensions: 0,
NumServices: 1,
},
diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto
index 6b935f27db531..826b5ef5f11e8 100644
--- a/provisionersdk/proto/provisioner.proto
+++ b/provisionersdk/proto/provisioner.proto
@@ -118,6 +118,11 @@ message InstanceIdentityAuth {
string instance_id = 1;
}
+message GitAuthProvider {
+ string id = 1;
+ string access_token = 2;
+}
+
// Agent represents a running agent on the workspace.
message Agent {
string id = 1;
@@ -235,8 +240,9 @@ message Provision {
message Plan {
Config config = 1;
repeated ParameterValue parameter_values = 2;
- repeated RichParameterValue rich_parameter_values = 3;
- repeated VariableValue variable_values = 4;
+ repeated RichParameterValue rich_parameter_values = 3;
+ repeated VariableValue variable_values = 4;
+ repeated GitAuthProvider git_auth_providers = 5;
}
message Apply {
@@ -257,7 +263,8 @@ message Provision {
string error = 2;
repeated Resource resources = 3;
repeated RichParameter parameters = 4;
- bytes plan = 5;
+ repeated string git_auth_providers = 5;
+ bytes plan = 6;
}
message Response {
oneof type {
diff --git a/site/package.json b/site/package.json
index bacd0fde6198d..4f5487e551404 100644
--- a/site/package.json
+++ b/site/package.json
@@ -136,6 +136,6 @@
"chrome 66",
"firefox 63",
"edge 79",
- "safari 13.1"
+ "safari 15.4"
]
}
diff --git a/site/src/api/api.ts b/site/src/api/api.ts
index 303042f2ccf5e..ac99f7b3eb2b5 100644
--- a/site/src/api/api.ts
+++ b/site/src/api/api.ts
@@ -295,6 +295,15 @@ export const createTemplateVersion = async (
return response.data
}
+export const getTemplateVersionGitAuth = async (
+ versionId: string,
+): Promise => {
+ const response = await axios.get(
+ `/api/v2/templateversions/${versionId}/gitauth`,
+ )
+ return response.data
+}
+
export const getTemplateVersionParameters = async (
versionId: string,
): Promise => {
diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts
index cf36bd98bff3b..8dab0662f63e2 100644
--- a/site/src/api/typesGenerated.ts
+++ b/site/src/api/typesGenerated.ts
@@ -754,6 +754,14 @@ export interface TemplateVersion {
readonly created_by: User
}
+// From codersdk/templateversions.go
+export interface TemplateVersionGitAuth {
+ readonly id: string
+ readonly type: GitProvider
+ readonly authenticate_url: string
+ readonly authenticated: boolean
+}
+
// From codersdk/templateversions.go
export interface TemplateVersionParameter {
readonly name: string
@@ -1138,6 +1146,15 @@ export const FeatureNames: FeatureName[] = [
"user_limit",
]
+// From codersdk/workspaceagents.go
+export type GitProvider = "azure-devops" | "bitbucket" | "github" | "gitlab"
+export const GitProviders: GitProvider[] = [
+ "azure-devops",
+ "bitbucket",
+ "github",
+ "gitlab",
+]
+
// From codersdk/provisionerdaemons.go
export type LogLevel = "debug" | "error" | "info" | "trace" | "warn"
export const LogLevels: LogLevel[] = ["debug", "error", "info", "trace", "warn"]
diff --git a/site/src/components/GitAuth/GitAuth.stories.tsx b/site/src/components/GitAuth/GitAuth.stories.tsx
new file mode 100644
index 0000000000000..cda012212d14d
--- /dev/null
+++ b/site/src/components/GitAuth/GitAuth.stories.tsx
@@ -0,0 +1,57 @@
+import { Story } from "@storybook/react"
+import { GitAuth, GitAuthProps } from "./GitAuth"
+
+export default {
+ title: "components/GitAuth",
+ component: GitAuth,
+}
+
+const Template: Story = (args) =>
+
+export const GithubNotAuthenticated = Template.bind({})
+GithubNotAuthenticated.args = {
+ type: "github",
+ authenticated: false,
+}
+
+export const GithubAuthenticated = Template.bind({})
+GithubAuthenticated.args = {
+ type: "github",
+ authenticated: true,
+}
+
+export const GitlabNotAuthenticated = Template.bind({})
+GitlabNotAuthenticated.args = {
+ type: "gitlab",
+ authenticated: false,
+}
+
+export const GitlabAuthenticated = Template.bind({})
+GitlabAuthenticated.args = {
+ type: "gitlab",
+ authenticated: true,
+}
+
+export const AzureDevOpsNotAuthenticated = Template.bind({})
+AzureDevOpsNotAuthenticated.args = {
+ type: "azure-devops",
+ authenticated: false,
+}
+
+export const AzureDevOpsAuthenticated = Template.bind({})
+AzureDevOpsAuthenticated.args = {
+ type: "azure-devops",
+ authenticated: true,
+}
+
+export const BitbucketNotAuthenticated = Template.bind({})
+BitbucketNotAuthenticated.args = {
+ type: "bitbucket",
+ authenticated: false,
+}
+
+export const BitbucketAuthenticated = Template.bind({})
+BitbucketAuthenticated.args = {
+ type: "bitbucket",
+ authenticated: true,
+}
diff --git a/site/src/components/GitAuth/GitAuth.tsx b/site/src/components/GitAuth/GitAuth.tsx
new file mode 100644
index 0000000000000..7998044677771
--- /dev/null
+++ b/site/src/components/GitAuth/GitAuth.tsx
@@ -0,0 +1,115 @@
+import Button from "@material-ui/core/Button"
+import FormHelperText from "@material-ui/core/FormHelperText"
+import { makeStyles, Theme } from "@material-ui/core/styles"
+import { SvgIconProps } from "@material-ui/core/SvgIcon"
+import Tooltip from "@material-ui/core/Tooltip"
+import GitHub from "@material-ui/icons/GitHub"
+import * as TypesGen from "api/typesGenerated"
+import { AzureDevOpsIcon } from "components/Icons/AzureDevOpsIcon"
+import { BitbucketIcon } from "components/Icons/BitbucketIcon"
+import { GitlabIcon } from "components/Icons/GitlabIcon"
+import { Typography } from "components/Typography/Typography"
+import { FC } from "react"
+
+export interface GitAuthProps {
+ type: TypesGen.GitProvider
+ authenticated: boolean
+ authenticateURL: string
+ error?: string
+}
+
+export const GitAuth: FC = ({
+ type,
+ authenticated,
+ authenticateURL,
+ error,
+}) => {
+ const styles = useStyles({
+ error: typeof error !== "undefined",
+ })
+
+ let prettyName: string
+ let Icon: (props: SvgIconProps) => JSX.Element
+ switch (type) {
+ case "azure-devops":
+ prettyName = "Azure DevOps"
+ Icon = AzureDevOpsIcon
+ break
+ case "bitbucket":
+ prettyName = "Bitbucket"
+ Icon = BitbucketIcon
+ break
+ case "github":
+ prettyName = "GitHub"
+ Icon = GitHub
+ break
+ case "gitlab":
+ prettyName = "GitLab"
+ Icon = GitlabIcon
+ break
+ default:
+ throw new Error("invalid git provider: " + type)
+ }
+
+ return (
+
+
+
+ )
+}
+
+const useStyles = makeStyles<
+ Theme,
+ {
+ error: boolean
+ }
+>((theme) => ({
+ link: {
+ textDecoration: "none",
+ },
+ root: {
+ padding: 4,
+ display: "flex",
+ gap: 12,
+ alignItems: "center",
+ textAlign: "left",
+ },
+ button: {
+ height: "unset",
+ border: ({ error }) =>
+ error ? `1px solid ${theme.palette.error.main}` : "unset",
+ },
+ icon: {
+ width: 32,
+ height: 32,
+ },
+}))
diff --git a/site/src/components/Icons/AzureDevOpsIcon.tsx b/site/src/components/Icons/AzureDevOpsIcon.tsx
new file mode 100644
index 0000000000000..5ac7b453b17f3
--- /dev/null
+++ b/site/src/components/Icons/AzureDevOpsIcon.tsx
@@ -0,0 +1,25 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon"
+
+export const AzureDevOpsIcon = (props: SvgIconProps): JSX.Element => (
+
+
+
+
+
+
+
+
+
+
+
+
+)
diff --git a/site/src/components/Icons/BitbucketIcon.tsx b/site/src/components/Icons/BitbucketIcon.tsx
new file mode 100644
index 0000000000000..f3b436baa2462
--- /dev/null
+++ b/site/src/components/Icons/BitbucketIcon.tsx
@@ -0,0 +1,32 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon"
+
+export const BitbucketIcon = (props: SvgIconProps): JSX.Element => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)
diff --git a/site/src/components/Icons/GitlabIcon.tsx b/site/src/components/Icons/GitlabIcon.tsx
new file mode 100644
index 0000000000000..6a99d63fae0fa
--- /dev/null
+++ b/site/src/components/Icons/GitlabIcon.tsx
@@ -0,0 +1,29 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon"
+
+export const GitlabIcon = (props: SvgIconProps): JSX.Element => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+)
diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx
index 0cabc3e6ed271..c2f8e24fdba75 100644
--- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx
+++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx
@@ -12,6 +12,7 @@ import {
MockTemplateVersionParameter1,
MockTemplateVersionParameter2,
MockTemplateVersionParameter3,
+ MockTemplateVersionGitAuth,
} from "testHelpers/entities"
import { renderWithAuth } from "testHelpers/renderHelpers"
import CreateWorkspacePage from "./CreateWorkspacePage"
@@ -38,6 +39,17 @@ const renderCreateWorkspacePage = () => {
})
}
+Object.defineProperty(window, "BroadcastChannel", {
+ value: class {
+ addEventListener() {
+ // noop
+ }
+ close() {
+ // noop
+ }
+ },
+})
+
describe("CreateWorkspacePage", () => {
it("renders", async () => {
jest
@@ -210,4 +222,24 @@ describe("CreateWorkspacePage", () => {
const validationError = await screen.findByText(validationPatternNotMatched)
expect(validationError).toBeInTheDocument()
})
+
+ it("gitauth: errors if unauthenticated and submits", async () => {
+ jest
+ .spyOn(API, "getTemplateVersionGitAuth")
+ .mockResolvedValueOnce([MockTemplateVersionGitAuth])
+
+ await waitFor(() => renderCreateWorkspacePage())
+
+ const nameField = await screen.findByLabelText(nameLabelText)
+
+ // have to use fireEvent b/c userEvent isn't cleaning up properly between tests
+ fireEvent.change(nameField, {
+ target: { value: "test" },
+ })
+
+ const submitButton = screen.getByText(createWorkspaceText)
+ await userEvent.click(submitButton)
+
+ await screen.findByText("You must authenticate to create a workspace!")
+ })
})
diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx
index 0dc0f65482548..5a9e63edac6cb 100644
--- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx
+++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx
@@ -33,8 +33,10 @@ const CreateWorkspacePage: FC = () => {
templates,
templateParameters,
templateSchema,
+ templateGitAuth,
selectedTemplate,
getTemplateSchemaError,
+ getTemplateGitAuthError,
getTemplatesError,
createWorkspaceError,
permissions,
@@ -61,11 +63,14 @@ const CreateWorkspacePage: FC = () => {
selectedTemplate={selectedTemplate}
templateParameters={orderedTemplateParameters(templateParameters)}
templateSchema={templateSchema}
+ templateGitAuth={templateGitAuth}
createWorkspaceErrors={{
[CreateWorkspaceErrors.GET_TEMPLATES_ERROR]: getTemplatesError,
[CreateWorkspaceErrors.GET_TEMPLATE_SCHEMA_ERROR]:
getTemplateSchemaError,
[CreateWorkspaceErrors.CREATE_WORKSPACE_ERROR]: createWorkspaceError,
+ [CreateWorkspaceErrors.GET_TEMPLATE_GITAUTH_ERROR]:
+ getTemplateGitAuthError,
}}
canCreateForUser={permissions?.createWorkspaceForUser}
owner={owner}
diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx
index 35b0bead3320b..be8f907ea7f64 100644
--- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx
+++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx
@@ -169,3 +169,25 @@ RichParameters.args = {
],
createWorkspaceErrors: {},
}
+
+export const GitAuth = Template.bind({})
+GitAuth.args = {
+ templates: [MockTemplate],
+ selectedTemplate: MockTemplate,
+ createWorkspaceErrors: {},
+ templateParameters: [],
+ templateGitAuth: [
+ {
+ id: "github",
+ type: "github",
+ authenticated: false,
+ authenticate_url: "",
+ },
+ {
+ id: "gitlab",
+ type: "gitlab",
+ authenticated: true,
+ authenticate_url: "",
+ },
+ ],
+}
diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx
index 959252a1b9140..e4876bff3e28b 100644
--- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx
+++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx
@@ -6,7 +6,7 @@ import { RichParameterInput } from "components/RichParameterInput/RichParameterI
import { Stack } from "components/Stack/Stack"
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"
import { FormikContextType, FormikTouched, useFormik } from "formik"
-import { FC, useState } from "react"
+import { FC, useEffect, useState } from "react"
import { useTranslation } from "react-i18next"
import { getFormHelpers, nameValidator, onChangeTrimmed } from "util/formUtils"
import * as Yup from "yup"
@@ -15,10 +15,12 @@ import { makeStyles } from "@material-ui/core/styles"
import { FullPageHorizontalForm } from "components/FullPageForm/FullPageHorizontalForm"
import { SelectedTemplate } from "./SelectedTemplate"
import { Loader } from "components/Loader/Loader"
+import { GitAuth } from "components/GitAuth/GitAuth"
export enum CreateWorkspaceErrors {
GET_TEMPLATES_ERROR = "getTemplatesError",
GET_TEMPLATE_SCHEMA_ERROR = "getTemplateSchemaError",
+ GET_TEMPLATE_GITAUTH_ERROR = "getTemplateGitAuthError",
CREATE_WORKSPACE_ERROR = "createWorkspaceError",
}
@@ -32,6 +34,7 @@ export interface CreateWorkspacePageViewProps {
selectedTemplate?: TypesGen.Template
templateParameters?: TypesGen.TemplateVersionParameter[]
templateSchema?: TypesGen.ParameterSchema[]
+ templateGitAuth?: TypesGen.TemplateVersionGitAuth[]
createWorkspaceErrors: Partial>
canCreateForUser?: boolean
owner: TypesGen.User | null
@@ -55,6 +58,15 @@ export const CreateWorkspacePageView: FC<
props.templateParameters,
props.defaultParameterValues,
)
+ const [gitAuthErrors, setGitAuthErrors] = useState>({})
+ useEffect(() => {
+ // templateGitAuth is refreshed automatically using a BroadcastChannel
+ // which may change the `authenticated` property.
+ //
+ // If the provider becomes authenticated, we want the error message
+ // to disappear.
+ setGitAuthErrors({})
+ }, [props.templateGitAuth])
const { t } = useTranslation("createWorkspacePage")
@@ -75,6 +87,20 @@ export const CreateWorkspacePageView: FC<
enableReinitialize: true,
initialTouched: props.initialTouched,
onSubmit: (request) => {
+ for (let i = 0; i < (props.templateGitAuth?.length || 0); i++) {
+ const auth = props.templateGitAuth?.[i]
+ if (!auth) {
+ continue
+ }
+ if (!auth.authenticated) {
+ setGitAuthErrors({
+ [auth.id]: "You must authenticate to create a workspace!",
+ })
+ form.setSubmitting(false)
+ return
+ }
+ }
+
if (!props.templateSchema) {
throw new Error("No template schema loaded")
}
@@ -142,6 +168,20 @@ export const CreateWorkspacePageView: FC<
}
/>
)}
+ {Boolean(
+ props.createWorkspaceErrors[
+ CreateWorkspaceErrors.GET_TEMPLATE_GITAUTH_ERROR
+ ],
+ ) && (
+
+ )}
)
}
@@ -220,6 +260,37 @@ export const CreateWorkspacePageView: FC<
)}
+ {/* Template git auth */}
+ {props.templateGitAuth && props.templateGitAuth.length > 0 && (
+
+
+
+ Git Authentication
+
+
+ This template requires authentication to automatically perform
+ Git operations on create.
+
+
+
+
+ {props.templateGitAuth.map((auth, index) => (
+
+ ))}
+
+
+ )}
+
{/* Template params */}
{props.templateSchema && props.templateSchema.length > 0 && (
diff --git a/site/src/pages/GitAuthPage/GitAuthPage.tsx b/site/src/pages/GitAuthPage/GitAuthPage.tsx
index 27eacef1bd257..063f7c6b97ff9 100644
--- a/site/src/pages/GitAuthPage/GitAuthPage.tsx
+++ b/site/src/pages/GitAuthPage/GitAuthPage.tsx
@@ -2,11 +2,21 @@ import Button from "@material-ui/core/Button"
import { makeStyles } from "@material-ui/core/styles"
import { SignInLayout } from "components/SignInLayout/SignInLayout"
import { Welcome } from "components/Welcome/Welcome"
-import { FC } from "react"
+import { FC, useEffect } from "react"
import { Link as RouterLink } from "react-router-dom"
+import { REFRESH_GITAUTH_BROADCAST_CHANNEL } from "xServices/createWorkspace/createWorkspaceXService"
const GitAuthPage: FC = () => {
const styles = useStyles()
+ useEffect(() => {
+ // This is used to notify the parent window that the Git auth token has been refreshed.
+ // It's critical in the create workspace flow!
+ // eslint-disable-next-line compat/compat -- It actually is supported... not sure why it's complaining.
+ const bc = new BroadcastChannel(REFRESH_GITAUTH_BROADCAST_CHANNEL)
+ // The message doesn't matter, any message refreshes the page!
+ bc.postMessage("noop")
+ window.close()
+ }, [])
return (
diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts
index 8876bd169a7a2..a541f5cbc3ea5 100644
--- a/site/src/testHelpers/entities.ts
+++ b/site/src/testHelpers/entities.ts
@@ -1390,3 +1390,10 @@ export const mockParameterSchema = (
...partial,
}
}
+
+export const MockTemplateVersionGitAuth: TypesGen.TemplateVersionGitAuth = {
+ id: "github",
+ type: "github",
+ authenticate_url: "https://example.com/gitauth/github",
+ authenticated: false,
+}
diff --git a/site/src/testHelpers/handlers.ts b/site/src/testHelpers/handlers.ts
index 0dd0f2d0fe848..53de504fca3df 100644
--- a/site/src/testHelpers/handlers.ts
+++ b/site/src/testHelpers/handlers.ts
@@ -89,6 +89,18 @@ export const handlers = [
)
},
),
+ rest.get(
+ "/api/v2/templateversions/:templateVersionId/rich-parameters",
+ async (req, res, ctx) => {
+ return res(ctx.status(200), ctx.json([]))
+ },
+ ),
+ rest.get(
+ "/api/v2/templateversions/:templateVersionId/gitauth",
+ async (req, res, ctx) => {
+ return res(ctx.status(200), ctx.json([]))
+ },
+ ),
rest.get(
"api/v2/organizations/:organizationId/templates/:templateName/versions/:templateVersionName",
async (req, res, ctx) => {
diff --git a/site/src/xServices/createWorkspace/createWorkspaceXService.ts b/site/src/xServices/createWorkspace/createWorkspaceXService.ts
index 433c341b3c41c..1c8ea33dff7e4 100644
--- a/site/src/xServices/createWorkspace/createWorkspaceXService.ts
+++ b/site/src/xServices/createWorkspace/createWorkspaceXService.ts
@@ -2,6 +2,7 @@ import {
checkAuthorization,
createWorkspace,
getTemplates,
+ getTemplateVersionGitAuth,
getTemplateVersionRichParameters,
getTemplateVersionSchema,
} from "api/api"
@@ -9,12 +10,15 @@ import {
CreateWorkspaceRequest,
ParameterSchema,
Template,
+ TemplateVersionGitAuth,
TemplateVersionParameter,
User,
Workspace,
} from "api/typesGenerated"
import { assign, createMachine } from "xstate"
+export const REFRESH_GITAUTH_BROADCAST_CHANNEL = "gitauth_refresh"
+
type CreateWorkspaceContext = {
organizationId: string
owner: User | null
@@ -23,11 +27,13 @@ type CreateWorkspaceContext = {
selectedTemplate?: Template
templateParameters?: TemplateVersionParameter[]
templateSchema?: ParameterSchema[]
+ templateGitAuth?: TemplateVersionGitAuth[]
createWorkspaceRequest?: CreateWorkspaceRequest
createdWorkspace?: Workspace
createWorkspaceError?: Error | unknown
getTemplatesError?: Error | unknown
getTemplateParametersError?: Error | unknown
+ getTemplateGitAuthError?: Error | unknown
getTemplateSchemaError?: Error | unknown
permissions?: Record
checkPermissionsError?: Error | unknown
@@ -44,247 +50,305 @@ type SelectOwnerEvent = {
owner: User | null
}
-export const createWorkspaceMachine = createMachine(
- {
- id: "createWorkspaceState",
- predictableActionArguments: true,
- tsTypes: {} as import("./createWorkspaceXService.typegen").Typegen0,
- schema: {
- context: {} as CreateWorkspaceContext,
- events: {} as CreateWorkspaceEvent | SelectOwnerEvent,
- services: {} as {
- getTemplates: {
- data: Template[]
- }
- getTemplateParameters: {
- data: TemplateVersionParameter[]
- }
- getTemplateSchema: {
- data: ParameterSchema[]
- }
- createWorkspace: {
- data: Workspace
- }
+type RefreshGitAuthEvent = {
+ type: "REFRESH_GITAUTH"
+}
+
+export const createWorkspaceMachine =
+ /** @xstate-layout N4IgpgJg5mDOIC5QGMBOYCGAXMB1A9qgNawAOGyYAyltmAHQxZYCWAdlACpgC2pANnVgBiCPjYN2AN3xEGaTDgLEyFarRyMwzdl14ChCafmTYW4gNoAGALrWbiUKXywWrcY5AAPRABYATAA0IACeiACMvgCs9ADssQBsVgDM-v5JyQnJUQkAvrnBCnTKJOSUNHRaOhzcfII4ImIS9MZy9EVKhKVqFZpMrDX69XBGbDKm7mz2FuEOSCDOrpOePgjJAJzr9AAcVr4J677bCeFWB3vBYQgBvvQJB-5R6+GxVulPUfmF6MVdquUaBj9XS1AwNYRgVCoQj0MEAM0IPHaP06KjK6kqwMGdUMxgm5imtnsnkWbgJK0QGy2u32h2Op3OvkuiH8vis9HCDxO0XC2z5CX8XxAHTwf3RvSB2gGehxOCoyAAFrwMKJxJIxrJ5CjRWieoCqtLQcN5UqeBhRuMzJYibYSS4yR55qtTv52bFeYlfPEor4XuFmddwlscqz1mdfMlfZlfEKRSV-hi+lKQUM6CblRCoTD4YjkYodd0AZjk9iwdRFcqLSYrYS7Lb5qTlk6Im83R6El7Yj6-QH4gl6M8ctsoht7skrJ8CsLtfHxfqsTKywAFDCoDA8bSQxpqloatpxsV64vVRfDFdrjc4VCwKv4611uZOe1N0DOgXhOKRjZf-axR4Btl2XWWJngSKJtgCHJwnSWMZ0PIskxPI06HPddN2vTNoVQWF6gRVAkQPXUEMlJDUxwVDLy3W8a2mesnyWclmwQTl-A-WIv3WH8Ej-KIAyyW4Em2Z5XV5fx1m48JYPzWcj0Qw0yLAABxNwAEEAFcsAVVVmlaLVpPgxMSPk2UlNUjSFWoyZaMfBZn0Y18WSDfsfUEvlfEHViA2SbZ-HoDZwPSe4omCwUp0IwtDINFMTOUrB1M0zDs1w3NwoTCUotLYZYviiy8Rom0bMbezvEc8T6BcvkII8-1Qj8dZfP2R4fXEziUliKTfiIyKK2QIhdCXSEeBYWBXHEbcdL3eQlV6gb8OG0a2FgYkGzsx0HIQfwfJiKJXmSZJoO88IRwAqwP22aD3OeLshP2DrUQi9Ker6jhZqGkaCRESEsJw7A8II6aiFe+aPuW+iHTYCkNqiKxtgHVi+XWYK2SZWqNr5HZslAiNoJSSdvn0rr0rhFh+H4frV3XEQAGEACUAFEVM4OmAH1cAAeRpgBpKglxUqm6dB2yGLWkq0cecrdv2-xDuO1GXluRH9s5H1wKObi7oLNL9WJ0nyYvEQqDpgAZOmqc4Zm2dwAA5OmacFoqRdWcd0asSWkZuoJUbSftpc2vZ6rZDsXg1mTiLzMwOFDsBtPVGR9zgwn9Q6XQo8sglrLtYWIaYzbxZ2lIpZl5IA3O+hLvWeleSiVj6pDgzHpRFODMS7Cc3w8P7q1ypk8jgy0-ve3Vuz9bc+2yWDvO2WrjE2HMcybZYiOHJYm2fIpzYfAIDgTxUrnOhM-ByGAFoEgDE-6CsS+3n8d0nl9aW8enAmHvnEtTyEA+X1F4cOWryM0k5JyTiAZWS3DSKBdIC9zjZDronY8xkyzpjNJ-YqqxXjORXuEfaEYAh9gAtLO4aQNgenqkdSMsCX7wOisuCmlFrwoMdhETazl9hCQ2NLKwFd1gnRiCkMM51og8k2BQruclqFZTMppBhw9RZBldvQTa0FzgdnuF5Y4ZdgrumyI8JyC8RF700E9fqg1gZjWkZDUBWwDgjjElgnawE1GxAUUJPYglwIjjeDGMKCdKGaB1mTF6tD4ArSzpDfabwdiXxApseqtjT6o1SE4txrVXTpHSF4-GnVfF6QjlAKO5ic5RCOn5LsbwjpHWeJyAMZVThHUgvcCSvp9GyRyTgCABT1rhN8rsV2MTYmgQDC6BR7xuznByCcZpYcvqEA6aLSxdxFa2OyCBWIAYimwxXvwoMrp3GrzXkAA */
+ createMachine(
+ {
+ id: "createWorkspaceState",
+ predictableActionArguments: true,
+ tsTypes: {} as import("./createWorkspaceXService.typegen").Typegen0,
+ schema: {
+ context: {} as CreateWorkspaceContext,
+ events: {} as
+ | CreateWorkspaceEvent
+ | SelectOwnerEvent
+ | RefreshGitAuthEvent,
+ services: {} as {
+ getTemplates: {
+ data: Template[]
+ }
+ getTemplateGitAuth: {
+ data: TemplateVersionGitAuth[]
+ }
+ getTemplateParameters: {
+ data: TemplateVersionParameter[]
+ }
+ getTemplateSchema: {
+ data: ParameterSchema[]
+ }
+ createWorkspace: {
+ data: Workspace
+ }
+ },
},
- },
- initial: "gettingTemplates",
- states: {
- gettingTemplates: {
- entry: "clearGetTemplatesError",
- invoke: {
- src: "getTemplates",
- onDone: [
- {
- actions: ["assignTemplates"],
- cond: "areTemplatesEmpty",
- },
- {
- actions: ["assignTemplates", "assignSelectedTemplate"],
- target: "gettingTemplateSchema",
+ initial: "gettingTemplates",
+ states: {
+ gettingTemplates: {
+ entry: "clearGetTemplatesError",
+ invoke: {
+ src: "getTemplates",
+ onDone: [
+ {
+ actions: ["assignTemplates"],
+ cond: "areTemplatesEmpty",
+ },
+ {
+ actions: ["assignTemplates", "assignSelectedTemplate"],
+ target: "gettingTemplateSchema",
+ },
+ ],
+ onError: {
+ actions: ["assignGetTemplatesError"],
+ target: "error",
},
- ],
- onError: {
- actions: ["assignGetTemplatesError"],
- target: "error",
},
},
- },
- gettingTemplateSchema: {
- entry: "clearGetTemplateSchemaError",
- invoke: {
- src: "getTemplateSchema",
- onDone: {
- actions: ["assignTemplateSchema"],
- target: "gettingTemplateParameters",
- },
- onError: {
- actions: ["assignGetTemplateSchemaError"],
- target: "error",
+ gettingTemplateSchema: {
+ entry: "clearGetTemplateSchemaError",
+ invoke: {
+ src: "getTemplateSchema",
+ onDone: {
+ actions: ["assignTemplateSchema"],
+ target: "gettingTemplateParameters",
+ },
+ onError: {
+ actions: ["assignGetTemplateSchemaError"],
+ target: "error",
+ },
},
},
- },
- gettingTemplateParameters: {
- entry: "clearGetTemplateParametersError",
- invoke: {
- src: "getTemplateParameters",
- onDone: {
- actions: ["assignTemplateParameters"],
- target: "checkingPermissions",
- },
- onError: {
- actions: ["assignGetTemplateParametersError"],
- target: "error",
+ gettingTemplateParameters: {
+ entry: "clearGetTemplateParametersError",
+ invoke: {
+ src: "getTemplateParameters",
+ onDone: {
+ actions: ["assignTemplateParameters"],
+ target: "checkingPermissions",
+ },
+ onError: {
+ actions: ["assignGetTemplateParametersError"],
+ target: "error",
+ },
},
},
- },
- checkingPermissions: {
- entry: "clearCheckPermissionsError",
- invoke: {
- src: "checkPermissions",
- id: "checkPermissions",
- onDone: {
- actions: "assignPermissions",
- target: "fillingParams",
+ checkingPermissions: {
+ entry: "clearCheckPermissionsError",
+ invoke: {
+ src: "checkPermissions",
+ id: "checkPermissions",
+ onDone: {
+ actions: "assignPermissions",
+ target: "gettingTemplateGitAuth",
+ },
+ onError: {
+ actions: ["assignCheckPermissionsError"],
+ },
},
- onError: {
- actions: ["assignCheckPermissionsError"],
+ },
+ gettingTemplateGitAuth: {
+ entry: "clearTemplateGitAuthError",
+ invoke: {
+ src: "getTemplateGitAuth",
+ onDone: {
+ actions: ["assignTemplateGitAuth"],
+ target: "fillingParams",
+ },
+ onError: {
+ actions: ["assignTemplateGitAuthError"],
+ target: "error",
+ },
},
},
- },
- fillingParams: {
- on: {
- CREATE_WORKSPACE: {
- actions: ["assignCreateWorkspaceRequest", "assignOwner"],
- target: "creatingWorkspace",
+ fillingParams: {
+ invoke: {
+ id: "listenForRefreshGitAuth",
+ src: () => (callback) => {
+ // eslint-disable-next-line compat/compat -- It actually is supported... not sure why eslint is complaining.
+ const bc = new BroadcastChannel(REFRESH_GITAUTH_BROADCAST_CHANNEL)
+ bc.addEventListener("message", () => {
+ callback("REFRESH_GITAUTH")
+ })
+ return () => bc.close()
+ },
},
- SELECT_OWNER: {
- actions: ["assignOwner"],
- target: ["fillingParams"],
+ on: {
+ CREATE_WORKSPACE: {
+ actions: ["assignCreateWorkspaceRequest", "assignOwner"],
+ target: "creatingWorkspace",
+ },
+ SELECT_OWNER: {
+ actions: ["assignOwner"],
+ target: ["fillingParams"],
+ },
+ REFRESH_GITAUTH: {
+ target: "gettingTemplateGitAuth",
+ },
},
},
- },
- creatingWorkspace: {
- entry: "clearCreateWorkspaceError",
- invoke: {
- src: "createWorkspace",
- onDone: {
- actions: ["onCreateWorkspace"],
- target: "created",
- },
- onError: {
- actions: ["assignCreateWorkspaceError"],
- target: "fillingParams",
+ creatingWorkspace: {
+ entry: "clearCreateWorkspaceError",
+ invoke: {
+ src: "createWorkspace",
+ onDone: {
+ actions: ["onCreateWorkspace"],
+ target: "created",
+ },
+ onError: {
+ actions: ["assignCreateWorkspaceError"],
+ target: "fillingParams",
+ },
},
},
+ created: {
+ type: "final",
+ },
+ error: {},
},
- created: {
- type: "final",
- },
- error: {},
},
- },
- {
- services: {
- getTemplates: (context) => getTemplates(context.organizationId),
- getTemplateParameters: (context) => {
- const { selectedTemplate } = context
+ {
+ services: {
+ getTemplates: (context) => getTemplates(context.organizationId),
+ getTemplateGitAuth: (context) => {
+ const { selectedTemplate } = context
- if (!selectedTemplate) {
- throw new Error("No selected template")
- }
+ if (!selectedTemplate) {
+ throw new Error("No selected template")
+ }
- return getTemplateVersionRichParameters(
- selectedTemplate.active_version_id,
- )
- },
- getTemplateSchema: (context) => {
- const { selectedTemplate } = context
+ return getTemplateVersionGitAuth(selectedTemplate.active_version_id)
+ },
+ getTemplateParameters: (context) => {
+ const { selectedTemplate } = context
- if (!selectedTemplate) {
- throw new Error("No selected template")
- }
+ if (!selectedTemplate) {
+ throw new Error("No selected template")
+ }
- return getTemplateVersionSchema(selectedTemplate.active_version_id)
- },
- checkPermissions: async (context) => {
- if (!context.organizationId) {
- throw new Error("No organization ID")
- }
+ return getTemplateVersionRichParameters(
+ selectedTemplate.active_version_id,
+ )
+ },
+ getTemplateSchema: (context) => {
+ const { selectedTemplate } = context
+
+ if (!selectedTemplate) {
+ throw new Error("No selected template")
+ }
- // HACK: below, we pass in * for the owner_id, which is a hacky way of checking if the
- // current user can create a workspace on behalf of anyone within the org (only org owners should be able to do this).
- // This pattern should not be replicated outside of this narrow use case.
- const permissionsToCheck = {
- createWorkspaceForUser: {
- object: {
- resource_type: "workspace",
- organization_id: `${context.organizationId}`,
- owner_id: "*",
+ return getTemplateVersionSchema(selectedTemplate.active_version_id)
+ },
+ checkPermissions: async (context) => {
+ if (!context.organizationId) {
+ throw new Error("No organization ID")
+ }
+
+ // HACK: below, we pass in * for the owner_id, which is a hacky way of checking if the
+ // current user can create a workspace on behalf of anyone within the org (only org owners should be able to do this).
+ // This pattern should not be replicated outside of this narrow use case.
+ const permissionsToCheck = {
+ createWorkspaceForUser: {
+ object: {
+ resource_type: "workspace",
+ organization_id: `${context.organizationId}`,
+ owner_id: "*",
+ },
+ action: "create",
},
- action: "create",
- },
- }
+ }
- return checkAuthorization({
- checks: permissionsToCheck,
- })
- },
- createWorkspace: (context) => {
- const { createWorkspaceRequest, organizationId, owner } = context
+ return checkAuthorization({
+ checks: permissionsToCheck,
+ })
+ },
+ createWorkspace: (context) => {
+ const { createWorkspaceRequest, organizationId, owner } = context
- if (!createWorkspaceRequest) {
- throw new Error("No create workspace request")
- }
+ if (!createWorkspaceRequest) {
+ throw new Error("No create workspace request")
+ }
- return createWorkspace(
- organizationId,
- owner?.id ?? "me",
- createWorkspaceRequest,
- )
- },
- },
- guards: {
- areTemplatesEmpty: (_, event) => event.data.length === 0,
- },
- actions: {
- assignTemplates: assign({
- templates: (_, event) => event.data,
- }),
- assignSelectedTemplate: assign({
- selectedTemplate: (ctx, event) => {
- const templates = event.data.filter(
- (template) => template.name === ctx.templateName,
+ return createWorkspace(
+ organizationId,
+ owner?.id ?? "me",
+ createWorkspaceRequest,
)
- return templates.length > 0 ? templates[0] : undefined
},
- }),
- assignTemplateParameters: assign({
- templateParameters: (_, event) => event.data,
- }),
- assignTemplateSchema: assign({
- // Only show parameters that are allowed to be overridden.
- // CLI code: https://github.com/coder/coder/blob/main/cli/create.go#L152-L155
- templateSchema: (_, event) => event.data,
- }),
- assignPermissions: assign({
- permissions: (_, event) => event.data as Record,
- }),
- assignCheckPermissionsError: assign({
- checkPermissionsError: (_, event) => event.data,
- }),
- clearCheckPermissionsError: assign({
- checkPermissionsError: (_) => undefined,
- }),
- assignCreateWorkspaceRequest: assign({
- createWorkspaceRequest: (_, event) => event.request,
- }),
- assignOwner: assign({
- owner: (_, event) => event.owner,
- }),
- assignCreateWorkspaceError: assign({
- createWorkspaceError: (_, event) => event.data,
- }),
- clearCreateWorkspaceError: assign({
- createWorkspaceError: (_) => undefined,
- }),
- assignGetTemplatesError: assign({
- getTemplatesError: (_, event) => event.data,
- }),
- clearGetTemplatesError: assign({
- getTemplatesError: (_) => undefined,
- }),
- assignGetTemplateParametersError: assign({
- getTemplateParametersError: (_, event) => event.data,
- }),
- clearGetTemplateParametersError: assign({
- getTemplateParametersError: (_) => undefined,
- }),
- assignGetTemplateSchemaError: assign({
- getTemplateSchemaError: (_, event) => event.data,
- }),
- clearGetTemplateSchemaError: assign({
- getTemplateSchemaError: (_) => undefined,
- }),
+ },
+ guards: {
+ areTemplatesEmpty: (_, event) => event.data.length === 0,
+ },
+ actions: {
+ assignTemplates: assign({
+ templates: (_, event) => event.data,
+ }),
+ assignSelectedTemplate: assign({
+ selectedTemplate: (ctx, event) => {
+ const templates = event.data.filter(
+ (template) => template.name === ctx.templateName,
+ )
+ return templates.length > 0 ? templates[0] : undefined
+ },
+ }),
+ assignTemplateParameters: assign({
+ templateParameters: (_, event) => event.data,
+ }),
+ assignTemplateSchema: assign({
+ // Only show parameters that are allowed to be overridden.
+ // CLI code: https://github.com/coder/coder/blob/main/cli/create.go#L152-L155
+ templateSchema: (_, event) => event.data,
+ }),
+ assignPermissions: assign({
+ permissions: (_, event) => event.data as Record,
+ }),
+ assignCheckPermissionsError: assign({
+ checkPermissionsError: (_, event) => event.data,
+ }),
+ clearCheckPermissionsError: assign({
+ checkPermissionsError: (_) => undefined,
+ }),
+ assignCreateWorkspaceRequest: assign({
+ createWorkspaceRequest: (_, event) => event.request,
+ }),
+ assignOwner: assign({
+ owner: (_, event) => event.owner,
+ }),
+ assignCreateWorkspaceError: assign({
+ createWorkspaceError: (_, event) => event.data,
+ }),
+ clearCreateWorkspaceError: assign({
+ createWorkspaceError: (_) => undefined,
+ }),
+ assignGetTemplatesError: assign({
+ getTemplatesError: (_, event) => event.data,
+ }),
+ clearGetTemplatesError: assign({
+ getTemplatesError: (_) => undefined,
+ }),
+ assignGetTemplateParametersError: assign({
+ getTemplateParametersError: (_, event) => event.data,
+ }),
+ clearGetTemplateParametersError: assign({
+ getTemplateParametersError: (_) => undefined,
+ }),
+ assignGetTemplateSchemaError: assign({
+ getTemplateSchemaError: (_, event) => event.data,
+ }),
+ clearGetTemplateSchemaError: assign({
+ getTemplateSchemaError: (_) => undefined,
+ }),
+ clearTemplateGitAuthError: assign({
+ getTemplateGitAuthError: (_) => undefined,
+ }),
+ assignTemplateGitAuthError: assign({
+ getTemplateGitAuthError: (_, event) => event.data,
+ }),
+ assignTemplateGitAuth: assign({
+ templateGitAuth: (_, event) => event.data,
+ }),
+ },
},
- },
-)
+ )