From 728236ff985e516b8642741d7866365a7f5414b0 Mon Sep 17 00:00:00 2001 From: sreya Date: Thu, 23 Jun 2022 16:28:11 +0000 Subject: [PATCH 01/11] feat: unexpose coderdtest.NewWithAPI --- coderd/coderd.go | 6 +- coderd/coderd_test.go | 114 +++++++++++++++++++++++-- coderd/gitsshkey_test.go | 6 +- coderd/templateversions_test.go | 83 +++++++++---------- coderd/users.go | 41 +++++++++ coderd/users_test.go | 133 +++--------------------------- coderd/workspaceagents_test.go | 33 ++++---- coderd/workspaceapps_test.go | 5 +- coderd/workspacebuilds_test.go | 6 +- coderd/workspaceresources_test.go | 5 +- coderd/workspaces_test.go | 25 ++++-- codersdk/users.go | 31 +++++++ provisioner/echo/serve.go | 22 +++++ 13 files changed, 307 insertions(+), 203 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index acf39fd8bbead..79b0766f11842 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -287,7 +287,11 @@ func New(options *Options) *API { r.Post("/authorization", api.checkPermissions) - r.Post("/keys", api.postAPIKey) + r.Route("/keys", func(r chi.Router) { + r.Post("/", api.postAPIKey) + r.Get("/{keyid}", api.apiKey) + }) + r.Route("/organizations", func(r chi.Router) { r.Get("/", api.organizationsByUser) r.Get("/{organizationname}", api.organizationByUserAndName) diff --git a/coderd/coderd_test.go b/coderd/coderd_test.go index 1a211f6bd69b2..448d6d04a3524 100644 --- a/coderd/coderd_test.go +++ b/coderd/coderd_test.go @@ -2,8 +2,14 @@ package coderd_test import ( "context" + "crypto/x509" + "database/sql" "io" + "net" "net/http" + "net/http/httptest" + "net/url" + "os" "strconv" "strings" "testing" @@ -14,10 +20,23 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/goleak" "golang.org/x/xerrors" + "google.golang.org/api/idtoken" + "google.golang.org/api/option" + + "cdr.dev/slog" + "cdr.dev/slog/sloggers/slogtest" "github.com/coder/coder/buildinfo" + "github.com/coder/coder/coderd" + "github.com/coder/coder/coderd/autobuild/executor" "github.com/coder/coder/coderd/coderdtest" + "github.com/coder/coder/coderd/database" + "github.com/coder/coder/coderd/database/databasefake" + "github.com/coder/coder/coderd/database/postgres" + "github.com/coder/coder/coderd/gitsshkey" "github.com/coder/coder/coderd/rbac" + "github.com/coder/coder/coderd/telemetry" + "github.com/coder/coder/coderd/turnconn" "github.com/coder/coder/codersdk" "github.com/coder/coder/provisioner/echo" "github.com/coder/coder/provisionersdk/proto" @@ -39,13 +58,96 @@ func TestBuildInfo(t *testing.T) { // TestAuthorizeAllEndpoints will check `authorize` is called on every endpoint registered. func TestAuthorizeAllEndpoints(t *testing.T) { t.Parallel() - ctx := context.Background() + var ( + ctx = context.Background() + authorizer = &fakeAuthorizer{} + ) - authorizer := &fakeAuthorizer{} - client, api := coderdtest.NewWithAPI(t, &coderdtest.Options{ - Authorizer: authorizer, - IncludeProvisionerD: true, - }) + // This function was taken from coderdtest.newWithAPI. It is intentionally + // copied to avoid exposing the API to other tests in coderd. Tests should + // not need a reference to coderd.API...this test is an exception. + newClient := func(authorizer rbac.Authorizer) (*codersdk.Client, *coderd.API) { + // This can be hotswapped for a live database instance. + db := databasefake.New() + pubsub := database.NewPubsubInMemory() + if os.Getenv("DB") != "" { + connectionURL, closePg, err := postgres.Open() + require.NoError(t, err) + t.Cleanup(closePg) + sqlDB, err := sql.Open("postgres", connectionURL) + require.NoError(t, err) + t.Cleanup(func() { + _ = sqlDB.Close() + }) + err = database.MigrateUp(sqlDB) + require.NoError(t, err) + db = database.New(sqlDB) + + pubsub, err = database.NewPubsub(context.Background(), sqlDB, connectionURL) + require.NoError(t, err) + t.Cleanup(func() { + _ = pubsub.Close() + }) + } + + tickerCh := make(chan time.Time) + t.Cleanup(func() { close(tickerCh) }) + + ctx, cancelFunc := context.WithCancel(context.Background()) + lifecycleExecutor := executor.New( + ctx, + db, + slogtest.Make(t, nil).Named("autobuild.executor").Leveled(slog.LevelDebug), + tickerCh, + ).WithStatsChannel(nil) + lifecycleExecutor.Run() + + srv := httptest.NewUnstartedServer(nil) + srv.Config.BaseContext = func(_ net.Listener) context.Context { + return ctx + } + srv.Start() + serverURL, err := url.Parse(srv.URL) + require.NoError(t, err) + + turnServer, err := turnconn.New(nil) + require.NoError(t, err) + + validator, err := idtoken.NewValidator(ctx, option.WithoutAuthentication()) + require.NoError(t, err) + + // We set the handler after server creation for the access URL. + coderAPI := coderd.New(&coderd.Options{ + AgentConnectionUpdateFrequency: 150 * time.Millisecond, + AccessURL: serverURL, + Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug), + Database: db, + Pubsub: pubsub, + + AWSCertificates: nil, + AzureCertificates: x509.VerifyOptions{}, + GithubOAuth2Config: nil, + GoogleTokenValidator: validator, + SSHKeygenAlgorithm: gitsshkey.AlgorithmEd25519, + TURNServer: turnServer, + APIRateLimit: 0, + Authorizer: authorizer, + Telemetry: telemetry.NewNoop(), + }) + srv.Config.Handler = coderAPI.Handler + + _ = coderdtest.NewProvisionerDaemon(t, coderAPI) + t.Cleanup(func() { + cancelFunc() + _ = turnServer.Close() + srv.Close() + _ = coderAPI.Close() + }) + + return codersdk.New(serverURL), coderAPI + } + + client, api := newClient(authorizer) admin := coderdtest.CreateFirstUser(t, client) // The provisioner will call to coderd and register itself. This is async, // so we wait for it to occur. diff --git a/coderd/gitsshkey_test.go b/coderd/gitsshkey_test.go index 9f767c0d66e73..dbbcc824074f1 100644 --- a/coderd/gitsshkey_test.go +++ b/coderd/gitsshkey_test.go @@ -79,9 +79,10 @@ func TestGitSSHKey(t *testing.T) { func TestAgentGitSSHKey(t *testing.T) { t.Parallel() - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - daemonCloser := coderdtest.NewProvisionerDaemon(t, coderAPI) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, @@ -107,7 +108,6 @@ func TestAgentGitSSHKey(t *testing.T) { coderdtest.AwaitTemplateVersionJob(t, client, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) - daemonCloser.Close() agentClient := codersdk.New(client.URL) agentClient.SessionToken = authToken diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index c868cc65ac7fc..28f6bd7d016d3 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -2,7 +2,6 @@ package coderd_test import ( "context" - "database/sql" "net/http" "testing" "time" @@ -12,7 +11,6 @@ import ( "github.com/stretchr/testify/require" "github.com/coder/coder/coderd/coderdtest" - "github.com/coder/coder/coderd/database" "github.com/coder/coder/codersdk" "github.com/coder/coder/provisioner/echo" "github.com/coder/coder/provisionersdk/proto" @@ -555,21 +553,34 @@ func TestTemplateVersionDryRun(t *testing.T) { t.Run("OK", func(t *testing.T) { t.Parallel() - client, api := coderdtest.NewWithAPI(t, &coderdtest.Options{IncludeProvisionerD: true}) + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) user := coderdtest.CreateFirstUser(t, client) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - Provision: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ - Log: &proto.Log{}, + Provision: []*proto.Provision_Response{ + { + Type: &proto.Provision_Response_Log{ + Log: &proto.Log{}, + }}, + { + Type: &proto.Provision_Response_Complete{ + Complete: &proto.Provision_Complete{}, + }, }, - }}, + }, }) - forceCompleteTemplateVersionJob(t, api.Database, client, version) + + version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) // Create the dry-run job, err := client.CreateTemplateVersionDryRun(context.Background(), version.ID, codersdk.CreateTemplateVersionDryRunRequest{ - ParameterValues: []codersdk.CreateParameterRequest{}, + ParameterValues: []codersdk.CreateParameterRequest{ + { + Name: echo.ParameterExecKey, + SourceValue: "tail -f /dev/null", + }, + }, }) require.NoError(t, err) @@ -606,13 +617,7 @@ func TestTemplateVersionDryRun(t *testing.T) { }) require.NoError(t, err) - require.Eventually(t, func() bool { - job, err := client.TemplateVersionDryRun(context.Background(), version.ID, job.ID) - assert.NoError(t, err) - - t.Logf("Status: %s", job.Status) - return job.Status == codersdk.ProvisionerJobSucceeded - }, 5*time.Second, 25*time.Millisecond) + _ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) err = client.CancelTemplateVersionDryRun(context.Background(), version.ID, job.ID) var apiErr *codersdk.Error @@ -622,21 +627,33 @@ func TestTemplateVersionDryRun(t *testing.T) { t.Run("AlreadyCanceled", func(t *testing.T) { t.Parallel() - client, api := coderdtest.NewWithAPI(t, &coderdtest.Options{IncludeProvisionerD: true}) + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, - Provision: []*proto.Provision_Response{{ - Type: &proto.Provision_Response_Log{ - Log: &proto.Log{}, + Provision: []*proto.Provision_Response{ + { + Type: &proto.Provision_Response_Log{ + Log: &proto.Log{}, + }}, + { + Type: &proto.Provision_Response_Complete{ + Complete: &proto.Provision_Complete{}, + }, }, - }}, + }, }) - forceCompleteTemplateVersionJob(t, api.Database, client, version) + + version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) // Create the dry-run job, err := client.CreateTemplateVersionDryRun(context.Background(), version.ID, codersdk.CreateTemplateVersionDryRunRequest{ - ParameterValues: []codersdk.CreateParameterRequest{}, + ParameterValues: []codersdk.CreateParameterRequest{ + { + Name: echo.ParameterExecKey, + SourceValue: "tail -f /dev/null", + }, + }, }) require.NoError(t, err) @@ -753,23 +770,3 @@ func TestPaginatedTemplateVersions(t *testing.T) { }) } } - -func forceCompleteTemplateVersionJob(t *testing.T, db database.Store, client *codersdk.Client, version codersdk.TemplateVersion) { - t.Helper() - - // HACK: we need the template version job to be finished so the dry-run job - // can be created. We do this by canceling the job and then marking it as - // successful. - err := client.CancelTemplateVersion(context.Background(), version.ID) - require.NoError(t, err) - err = db.UpdateProvisionerJobWithCompleteByID(context.Background(), database.UpdateProvisionerJobWithCompleteByIDParams{ - ID: version.Job.ID, - UpdatedAt: time.Now(), - CompletedAt: sql.NullTime{ - Time: time.Now(), - Valid: true, - }, - Error: sql.NullString{}, - }) - require.NoError(t, err) -} diff --git a/coderd/users.go b/coderd/users.go index 9cf13dcdb780b..c8ac9aa27c1d1 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -719,6 +719,34 @@ func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) { httpapi.Write(rw, http.StatusCreated, codersdk.GenerateAPIKeyResponse{Key: sessionToken}) } +func (api *API) apiKey(rw http.ResponseWriter, r *http.Request) { + var ( + ctx = r.Context() + user = httpmw.UserParam(r) + ) + + if !api.Authorize(r, rbac.ActionRead, rbac.ResourceAPIKey.WithOwner(user.ID.String())) { + httpapi.ResourceNotFound(rw) + return + } + + keyID := chi.URLParam(r, "keyid") + key, err := api.Database.GetAPIKeyByID(ctx, keyID) + if errors.Is(err, sql.ErrNoRows) { + httpapi.ResourceNotFound(rw) + return + } + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: "Internal error fetching API key.", + Detail: err.Error(), + }) + return + } + + httpapi.Write(rw, http.StatusOK, convertAPIKey(key)) +} + // Clear the user's session cookie. func (api *API) postLogout(rw http.ResponseWriter, r *http.Request) { // Get a blank token cookie. @@ -1008,3 +1036,16 @@ func parseUserStatus(v string) ([]database.UserStatus, error) { } return statuses, nil } + +func convertAPIKey(k database.APIKey) codersdk.APIKey { + return codersdk.APIKey{ + ID: k.ID, + UserID: k.UserID, + LastUsed: k.LastUsed, + ExpiresAt: k.ExpiresAt, + CreatedAt: k.CreatedAt, + UpdatedAt: k.UpdatedAt, + LoginType: codersdk.LoginType(k.LoginType), + LifetimeSeconds: k.LifetimeSeconds, + } +} diff --git a/coderd/users_test.go b/coderd/users_test.go index 56f5c5efa55d9..e20593704fa6f 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -2,7 +2,6 @@ package coderd_test import ( "context" - "database/sql" "fmt" "net/http" "sort" @@ -14,8 +13,6 @@ import ( "github.com/stretchr/testify/require" "github.com/coder/coder/coderd/coderdtest" - "github.com/coder/coder/coderd/database" - "github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/rbac" "github.com/coder/coder/codersdk" @@ -138,94 +135,24 @@ func TestPostLogin(t *testing.T) { var ( ctx = context.Background() ) - client, api := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, nil) admin := coderdtest.CreateFirstUser(t, client) split := strings.Split(client.SessionToken, "-") - loginKey, err := api.Database.GetAPIKeyByID(ctx, split[0]) + key, err := client.GetAPIKey(ctx, admin.UserID.String(), split[0]) require.NoError(t, err, "fetch login key") - require.Equal(t, int64(86400), loginKey.LifetimeSeconds, "default should be 86400") + require.Equal(t, int64(86400), key.LifetimeSeconds, "default should be 86400") // Generated tokens have a longer life token, err := client.CreateAPIKey(ctx, admin.UserID.String()) require.NoError(t, err, "make new api key") split = strings.Split(token.Key, "-") - apiKey, err := api.Database.GetAPIKeyByID(ctx, split[0]) + apiKey, err := client.GetAPIKey(ctx, admin.UserID.String(), split[0]) require.NoError(t, err, "fetch api key") require.True(t, apiKey.ExpiresAt.After(time.Now().Add(time.Hour*24*6)), "api key lasts more than 6 days") - require.True(t, apiKey.ExpiresAt.After(loginKey.ExpiresAt.Add(time.Hour)), "api key should be longer expires") - require.Greater(t, apiKey.LifetimeSeconds, loginKey.LifetimeSeconds, "api key should have longer lifetime") - }) - - t.Run("APIKeyExtend", func(t *testing.T) { - t.Parallel() - var ( - ctx = context.Background() - ) - client, api := coderdtest.NewWithAPI(t, nil) - admin := coderdtest.CreateFirstUser(t, client) - - token, err := client.CreateAPIKey(ctx, admin.UserID.String()) - require.NoError(t, err, "make new api key") - client.SessionToken = token.Key - split := strings.Split(token.Key, "-") - - apiKey, err := api.Database.GetAPIKeyByID(ctx, split[0]) - require.NoError(t, err, "fetch api key") - - err = api.Database.UpdateAPIKeyByID(ctx, database.UpdateAPIKeyByIDParams{ - ID: apiKey.ID, - LastUsed: apiKey.LastUsed, - IPAddress: apiKey.IPAddress, - // This should cause a refresh - ExpiresAt: apiKey.ExpiresAt.Add(time.Hour * -2), - OAuthAccessToken: apiKey.OAuthAccessToken, - OAuthRefreshToken: apiKey.OAuthRefreshToken, - OAuthExpiry: apiKey.OAuthExpiry, - }) - require.NoError(t, err, "update api key") - - _, err = client.User(ctx, codersdk.Me) - require.NoError(t, err, "fetch user") - - apiKey, err = api.Database.GetAPIKeyByID(ctx, split[0]) - require.NoError(t, err, "fetch refreshed api key") - // 1 minute tolerance - require.True(t, apiKey.ExpiresAt.After(time.Now().Add(time.Hour*24*7).Add(time.Minute*-1)), "api key lasts 7 days") - }) - - t.Run("LoginKeyExtend", func(t *testing.T) { - t.Parallel() - var ( - ctx = context.Background() - ) - client, api := coderdtest.NewWithAPI(t, nil) - _ = coderdtest.CreateFirstUser(t, client) - split := strings.Split(client.SessionToken, "-") - - apiKey, err := api.Database.GetAPIKeyByID(ctx, split[0]) - require.NoError(t, err, "fetch login key") - - err = api.Database.UpdateAPIKeyByID(ctx, database.UpdateAPIKeyByIDParams{ - ID: apiKey.ID, - LastUsed: apiKey.LastUsed, - IPAddress: apiKey.IPAddress, - // This should cause a refresh - ExpiresAt: apiKey.ExpiresAt.Add(time.Hour * -2), - OAuthAccessToken: apiKey.OAuthAccessToken, - OAuthRefreshToken: apiKey.OAuthRefreshToken, - OAuthExpiry: apiKey.OAuthExpiry, - }) - require.NoError(t, err, "update login key") - - _, err = client.User(ctx, codersdk.Me) - require.NoError(t, err, "fetch user") - - apiKey, err = api.Database.GetAPIKeyByID(ctx, split[0]) - require.NoError(t, err, "fetch refreshed login key") - // 1 minute tolerance - require.True(t, apiKey.ExpiresAt.After(time.Now().Add(time.Hour*24).Add(time.Minute*-1)), "login key lasts 24 hrs") + require.True(t, apiKey.ExpiresAt.After(key.ExpiresAt.Add(time.Hour)), "api key should be longer expires") + require.Greater(t, apiKey.LifetimeSeconds, key.LifetimeSeconds, "api key should have longer lifetime") }) } @@ -237,11 +164,11 @@ func TestPostLogout(t *testing.T) { t.Parallel() ctx := context.Background() - client, api := coderdtest.NewWithAPI(t, nil) - _ = coderdtest.CreateFirstUser(t, client) + client := coderdtest.New(t, nil) + admin := coderdtest.CreateFirstUser(t, client) keyID := strings.Split(client.SessionToken, "-")[0] - apiKey, err := api.Database.GetAPIKeyByID(ctx, keyID) + apiKey, err := client.GetAPIKey(ctx, admin.UserID.String(), keyID) require.NoError(t, err) require.Equal(t, keyID, apiKey.ID, "API key should exist in the database") @@ -259,44 +186,10 @@ func TestPostLogout(t *testing.T) { require.Equal(t, httpmw.SessionTokenKey, cookies[0].Name, "Cookie should be the auth cookie") require.Equal(t, -1, cookies[0].MaxAge, "Cookie should be set to delete") - apiKey, err = api.Database.GetAPIKeyByID(ctx, keyID) - require.ErrorIs(t, err, sql.ErrNoRows, "API key should not exist in the database") - }) - - t.Run("LogoutWithoutKey", func(t *testing.T) { - t.Parallel() - - ctx := context.Background() - client, api := coderdtest.NewWithAPI(t, nil) - _ = coderdtest.CreateFirstUser(t, client) - keyID := strings.Split(client.SessionToken, "-")[0] - - apiKey, err := api.Database.GetAPIKeyByID(ctx, keyID) - require.NoError(t, err) - require.Equal(t, keyID, apiKey.ID, "API key should exist in the database") - - // Setting a fake database without the API Key to be used by the API. - // The middleware that extracts the API key is already set to read - // from the original database. - dbWithoutKey := databasefake.New() - api.Database = dbWithoutKey - - fullURL, err := client.URL.Parse("/api/v2/users/logout") - require.NoError(t, err, "Server URL should parse successfully") - - res, err := client.Request(ctx, http.MethodPost, fullURL.String(), nil) - require.NoError(t, err, "/logout request should succeed") - res.Body.Close() - require.Equal(t, http.StatusInternalServerError, res.StatusCode) - - cookies := res.Cookies() - require.Len(t, cookies, 1, "Exactly one cookie should be returned") - - require.Equal(t, httpmw.SessionTokenKey, cookies[0].Name, "Cookie should be the auth cookie") - require.Equal(t, -1, cookies[0].MaxAge, "Cookie should be set to delete") - - apiKey, err = api.Database.GetAPIKeyByID(ctx, keyID) - require.ErrorIs(t, err, sql.ErrNoRows, "API key should not exist in the database") + apiKey, err = client.GetAPIKey(ctx, admin.UserID.String(), keyID) + var sdkErr = &codersdk.Error{} + require.ErrorAs(t, err, &sdkErr) + require.Equal(t, http.StatusForbidden, sdkErr.StatusCode(), "Expecting Forbidden") }) } diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index c658791f93941..049001136577b 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -27,9 +27,10 @@ func TestWorkspaceAgent(t *testing.T) { t.Parallel() t.Run("Connect", func(t *testing.T) { t.Parallel() - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - daemonCloser := coderdtest.NewProvisionerDaemon(t, coderAPI) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, @@ -56,7 +57,6 @@ func TestWorkspaceAgent(t *testing.T) { coderdtest.AwaitTemplateVersionJob(t, client, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) - daemonCloser.Close() resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID) require.NoError(t, err) @@ -72,9 +72,10 @@ func TestWorkspaceAgentListen(t *testing.T) { t.Run("Connect", func(t *testing.T) { t.Parallel() - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - daemonCloser := coderdtest.NewProvisionerDaemon(t, coderAPI) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, @@ -100,7 +101,6 @@ func TestWorkspaceAgentListen(t *testing.T) { coderdtest.AwaitTemplateVersionJob(t, client, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) - daemonCloser.Close() agentClient := codersdk.New(client.URL) agentClient.SessionToken = authToken @@ -124,11 +124,11 @@ func TestWorkspaceAgentListen(t *testing.T) { t.Parallel() ctx := context.Background() - client, coderAPI := coderdtest.NewWithAPI(t, nil) - user := coderdtest.CreateFirstUser(t, client) - daemonCloser := coderdtest.NewProvisionerDaemon(t, coderAPI) - defer daemonCloser.Close() + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) + user := coderdtest.CreateFirstUser(t, client) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, @@ -196,9 +196,11 @@ func TestWorkspaceAgentListen(t *testing.T) { func TestWorkspaceAgentTURN(t *testing.T) { t.Parallel() - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) + user := coderdtest.CreateFirstUser(t, client) - daemonCloser := coderdtest.NewProvisionerDaemon(t, coderAPI) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, @@ -224,7 +226,6 @@ func TestWorkspaceAgentTURN(t *testing.T) { coderdtest.AwaitTemplateVersionJob(t, client, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) - daemonCloser.Close() agentClient := codersdk.New(client.URL) agentClient.SessionToken = authToken @@ -257,9 +258,10 @@ func TestWorkspaceAgentPTY(t *testing.T) { // it seems like it could be either. t.Skip("ConPTY appears to be inconsistent on Windows.") } - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - daemonCloser := coderdtest.NewProvisionerDaemon(t, coderAPI) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, @@ -285,7 +287,6 @@ func TestWorkspaceAgentPTY(t *testing.T) { coderdtest.AwaitTemplateVersionJob(t, client, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) - daemonCloser.Close() agentClient := codersdk.New(client.URL) agentClient.SessionToken = authToken diff --git a/coderd/workspaceapps_test.go b/coderd/workspaceapps_test.go index 399b1874dc6aa..6c875ed052cd7 100644 --- a/coderd/workspaceapps_test.go +++ b/coderd/workspaceapps_test.go @@ -36,9 +36,10 @@ func TestWorkspaceAppsProxyPath(t *testing.T) { go server.Serve(ln) tcpAddr, _ := ln.Addr().(*net.TCPAddr) - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - coderdtest.NewProvisionerDaemon(t, coderAPI) authToken := uuid.NewString() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, diff --git a/coderd/workspacebuilds_test.go b/coderd/workspacebuilds_test.go index 1893e768d6e70..9ee40a6460525 100644 --- a/coderd/workspacebuilds_test.go +++ b/coderd/workspacebuilds_test.go @@ -237,12 +237,12 @@ func TestWorkspaceBuildResources(t *testing.T) { t.Parallel() t.Run("ListRunning", func(t *testing.T) { t.Parallel() - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - closeDaemon := coderdtest.NewProvisionerDaemon(t, coderAPI) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) - closeDaemon.Close() template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) _, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID) diff --git a/coderd/workspaceresources_test.go b/coderd/workspaceresources_test.go index a1a941f355386..7ecc96f50f3b2 100644 --- a/coderd/workspaceresources_test.go +++ b/coderd/workspaceresources_test.go @@ -46,9 +46,10 @@ func TestWorkspaceResource(t *testing.T) { t.Run("Apps", func(t *testing.T) { t.Parallel() - client, coderd := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - coderdtest.NewProvisionerDaemon(t, coderd) app := &proto.App{ Name: "code-server", Command: "some-command", diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index 9f60bf816339d..0daa939d77ac2 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -656,15 +656,26 @@ func TestPostWorkspaceBuild(t *testing.T) { t.Run("AlreadyActive", func(t *testing.T) { t.Parallel() - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) + user := coderdtest.CreateFirstUser(t, client) - closeDaemon := coderdtest.NewProvisionerDaemon(t, coderAPI) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) // Close here so workspace build doesn't process! - closeDaemon.Close() - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) + workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID, + // Provide a parameter that will cause the workspace build to + // hang. + func(req *codersdk.CreateWorkspaceRequest) { + req.ParameterValues = []codersdk.CreateParameterRequest{ + { + Name: echo.ParameterExecKey, + SourceValue: "tail -f /dev/null", + }, + } + }) _, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{ TemplateVersionID: template.ActiveVersionID, Transition: codersdk.WorkspaceTransitionStart, @@ -694,15 +705,15 @@ func TestPostWorkspaceBuild(t *testing.T) { t.Run("WithState", func(t *testing.T) { t.Parallel() - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - closeDaemon := coderdtest.NewProvisionerDaemon(t, coderAPI) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) - _ = closeDaemon.Close() wantState := []byte("something") build, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{ TemplateVersionID: template.ActiveVersionID, diff --git a/codersdk/users.go b/codersdk/users.go index 7e8c607661ec1..7396cd9a97d3f 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -22,6 +22,13 @@ const ( UserStatusSuspended UserStatus = "suspended" ) +type LoginType string + +const ( + LoginTypePassword LoginType = "password" + LoginTypeGithub LoginType = "github" +) + type UsersRequest struct { Search string `json:"search,omitempty" typescript:"-"` // Filter users by status. @@ -44,6 +51,17 @@ type User struct { Roles []Role `json:"roles"` } +type APIKey struct { + ID string `json:"id" validate:"required"` + UserID uuid.UUID `json:"user_id" validate:"required"` + LastUsed time.Time `json:"last_used" validate:"required"` + ExpiresAt time.Time `json:"expires_at" validate:"required"` + CreatedAt time.Time `json:"created_at" validate:"required"` + UpdatedAt time.Time `json:"updated_at" validate:"required"` + LoginType LoginType `json:"login_type" validate:"required"` + LifetimeSeconds int64 `json:"lifetime_seconds" validate:"required"` +} + type CreateFirstUserRequest struct { Email string `json:"email" validate:"required,email"` Username string `json:"username" validate:"required,username"` @@ -314,6 +332,19 @@ func (c *Client) CreateAPIKey(ctx context.Context, user string) (*GenerateAPIKey return apiKey, json.NewDecoder(res.Body).Decode(apiKey) } +func (c *Client) GetAPIKey(ctx context.Context, user string, id string) (*APIKey, error) { + res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/keys/%s", user, id), nil) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode > http.StatusCreated { + return nil, readBodyAsError(res) + } + apiKey := &APIKey{} + return apiKey, json.NewDecoder(res.Body).Decode(apiKey) +} + // LoginWithPassword creates a session token authenticating with an email and password. // Call `SetSessionToken()` to apply the newly acquired token to the client. func (c *Client) LoginWithPassword(ctx context.Context, req LoginWithPasswordRequest) (LoginWithPasswordResponse, error) { diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 70c10b548b4ce..c8766858912b1 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -5,7 +5,9 @@ import ( "bytes" "context" "fmt" + "os/exec" "path/filepath" + "strings" "golang.org/x/xerrors" protobuf "google.golang.org/protobuf/proto" @@ -16,6 +18,10 @@ import ( "github.com/coder/coder/provisionersdk/proto" ) +const ( + ParameterExecKey = "echo.exec" +) + var ( // ParseComplete is a helper to indicate an empty parse completion. ParseComplete = []*proto.Parse_Response{{ @@ -86,6 +92,22 @@ func (e *echo) Provision(stream proto.DRPCProvisioner_ProvisionStream) error { // A cancel could occur here! return nil } + + for _, param := range request.ParameterValues { + if param.Name == ParameterExecKey { + // #nosec G204 + cmd := exec.Command("/bin/sh", "-c", param.Value) + out, err := cmd.CombinedOutput() + if err != nil { + return xerrors.Errorf("exec %q returned %q: %w", + strings.Join(cmd.Args, " "), + string(out), + err, + ) + } + } + } + for index := 0; ; index++ { extension := ".protobuf" if request.DryRun { From 011432051fdea1f5ddf5c6bdd378f1516e0f2f66 Mon Sep 17 00:00:00 2001 From: sreya Date: Thu, 23 Jun 2022 17:31:00 +0000 Subject: [PATCH 02/11] fix remaining tests --- cli/create_test.go | 49 ++++++++++-------- coderd/coderdtest/coderdtest.go | 6 +-- coderd/coderdtest/coderdtest_test.go | 6 +-- coderd/out.txt | 74 ++++++++++++++++++++++++++++ coderd/templateversions_test.go | 8 ++- coderd/users_test.go | 2 +- 6 files changed, 117 insertions(+), 28 deletions(-) create mode 100644 coderd/out.txt diff --git a/cli/create_test.go b/cli/create_test.go index cd069706ea71e..752501b4f951b 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -2,7 +2,6 @@ package cli_test import ( "context" - "database/sql" "fmt" "os" "testing" @@ -13,7 +12,6 @@ import ( "github.com/coder/coder/cli/clitest" "github.com/coder/coder/coderd/coderdtest" - "github.com/coder/coder/coderd/database" "github.com/coder/coder/codersdk" "github.com/coder/coder/provisioner/echo" "github.com/coder/coder/provisionersdk/proto" @@ -255,44 +253,55 @@ func TestCreate(t *testing.T) { t.Run("FailedDryRun", func(t *testing.T) { t.Parallel() - client, api := coderdtest.NewWithAPI(t, &coderdtest.Options{IncludeProvisionerD: true}) + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, + Parse: []*proto.Parse_Response{{ + Type: &proto.Parse_Response_Complete{ + Complete: &proto.Parse_Complete{ + ParameterSchemas: []*proto.ParameterSchema{ + { + AllowOverrideSource: true, + Name: echo.ParameterExecKey, + Description: "description 1", + DefaultSource: &proto.ParameterSource{ + Scheme: proto.ParameterSource_DATA, + Value: "exit 0", + }, + DefaultDestination: &proto.ParameterDestination{ + Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE, + }, + }, + }, + }, + }, + }}, ProvisionDryRun: []*proto.Provision_Response{ { Type: &proto.Provision_Response_Complete{ - Complete: &proto.Provision_Complete{ - Error: "test error", - }, + Complete: &proto.Provision_Complete{}, }, }, }, }) + tempDir := t.TempDir() + parameterFile, _ := os.CreateTemp(tempDir, "testParameterFile*.yaml") + _, _ = parameterFile.WriteString(fmt.Sprintf("%s: %q", echo.ParameterExecKey, "exit 1")) + // The template import job should end up failed, but we need it to be // succeeded so the dry-run can begin. version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) - require.Equal(t, codersdk.ProvisionerJobFailed, version.Job.Status, "job is not failed") - err := api.Database.UpdateProvisionerJobWithCompleteByID(context.Background(), database.UpdateProvisionerJobWithCompleteByIDParams{ - ID: version.Job.ID, - CompletedAt: sql.NullTime{ - Time: time.Now(), - Valid: true, - }, - UpdatedAt: time.Now(), - Error: sql.NullString{}, - }) - require.NoError(t, err, "update provisioner job") + require.Equal(t, codersdk.ProvisionerJobSucceeded, version.Job.Status, "job is not failed") _ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - cmd, root := clitest.New(t, "create", "test") + cmd, root := clitest.New(t, "create", "test", "--parameter-file", parameterFile.Name()) clitest.SetupConfig(t, client, root) pty := ptytest.New(t) cmd.SetIn(pty.Input()) cmd.SetOut(pty.Output()) - err = cmd.Execute() + err := cmd.Execute() require.Error(t, err) require.ErrorContains(t, err, "dry-run workspace") }) diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 6a25395688508..6f4751a5ec4f6 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -74,12 +74,12 @@ type Options struct { // New constructs a codersdk client connected to an in-memory API instance. func New(t *testing.T, options *Options) *codersdk.Client { - client, _ := NewWithAPI(t, options) + client, _ := newWithAPI(t, options) return client } -// NewWithAPI constructs a codersdk client connected to the returned in-memory API instance. -func NewWithAPI(t *testing.T, options *Options) (*codersdk.Client, *coderd.API) { +// newWithAPI constructs a codersdk client connected to the returned in-memory API instance. +func newWithAPI(t *testing.T, options *Options) (*codersdk.Client, *coderd.API) { if options == nil { options = &Options{} } diff --git a/coderd/coderdtest/coderdtest_test.go b/coderd/coderdtest/coderdtest_test.go index 633f3f906ba8e..c9577e039210f 100644 --- a/coderd/coderdtest/coderdtest_test.go +++ b/coderd/coderdtest/coderdtest_test.go @@ -14,9 +14,10 @@ func TestMain(m *testing.M) { func TestNew(t *testing.T) { t.Parallel() - client, coderAPI := coderdtest.NewWithAPI(t, nil) + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerD: true, + }) user := coderdtest.CreateFirstUser(t, client) - closer := coderdtest.NewProvisionerDaemon(t, coderAPI) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) @@ -25,5 +26,4 @@ func TestNew(t *testing.T) { coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID) _, _ = coderdtest.NewGoogleInstanceIdentity(t, "example", false) _, _ = coderdtest.NewAWSInstanceIdentity(t, "an-instance") - closer.Close() } diff --git a/coderd/out.txt b/coderd/out.txt new file mode 100644 index 0000000000000..6585d7ffad365 --- /dev/null +++ b/coderd/out.txt @@ -0,0 +1,74 @@ +=== RUN TestTemplateVersionDryRun +=== PAUSE TestTemplateVersionDryRun +=== CONT TestTemplateVersionDryRun +=== RUN TestTemplateVersionDryRun/OK +=== PAUSE TestTemplateVersionDryRun/OK +=== CONT TestTemplateVersionDryRun/OK + t.go:81: 2022-06-22 23:22:14.354 [DEBUG] debugLogRequest.func1.1 POST /api/v2/users/first + t.go:81: 2022-06-22 23:22:14.357 [DEBUG] debugLogRequest.func1.1 POST /api/v2/users/login + t.go:81: 2022-06-22 23:22:14.358 [DEBUG] debugLogRequest.func1.1 POST /api/v2/files + t.go:81: 2022-06-22 23:22:14.359 [DEBUG] debugLogRequest.func1.1 POST /api/v2/organizations/7aa01787-2231-4ddd-9332-0086223719a3/templateversions + t.go:81: 2022-06-22 23:22:14.386 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa + t.go:81: 2022-06-22 23:22:14.412 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa + t.go:81: 2022-06-22 23:22:14.436 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa + t.go:81: 2022-06-22 23:22:14.455 [DEBUG] (provisionerd) (*Server).connect connected + t.go:81: 2022-06-22 23:22:14.461 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa + t.go:81: 2022-06-22 23:22:14.466 [DEBUG] (provisionerd-brave_borg8) (*provisionerdServer).AcquireJob locked job from database {"id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c"} + t.go:81: 2022-06-22 23:22:14.466 [INFO] (provisionerd) (*Server).acquireJob acquired job {"initiator_username": "testuser", "provisioner": "echo", "id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c"} + t.go:81: 2022-06-22 23:22:14.467 [INFO] (provisionerd) (*Server).runJob unpacking template source archive {"size_bytes": 5120} + t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.parse.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.provision.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 39, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/1.provision.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.provision.dry.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 39, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/1.provision.dry.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob acquired job is template import + t.go:81: 2022-06-22 23:22:14.468 [INFO] (provisionerd) (*Server).runTemplateImportParse parse complete {"parameter_schemas": null} + t.go:81: 2022-06-22 23:22:14.470 [DEBUG] (provisionerd) (*Server).runTemplateImportProvision template import provision job logged {"level": "TRACE", "output": ""} + t.go:81: 2022-06-22 23:22:14.470 [INFO] (provisionerd) (*Server).runTemplateImportProvision parse dry-run provision successful {"resource_count": 1, "resources": [{"name": "cool-resource", "type": "cool_resource_type"}], "state_length": 0} + t.go:81: 2022-06-22 23:22:14.471 [DEBUG] (provisionerd) (*Server).runTemplateImportProvision template import provision job logged {"level": "TRACE", "output": ""} + t.go:81: 2022-06-22 23:22:14.472 [INFO] (provisionerd) (*Server).runTemplateImportProvision parse dry-run provision successful {"resource_count": 1, "resources": [{"name": "cool-resource", "type": "cool_resource_type"}], "state_length": 0} + t.go:81: 2022-06-22 23:22:14.475 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.486 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.486 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa + t.go:81: 2022-06-22 23:22:14.495 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.505 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.511 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa + t.go:81: 2022-06-22 23:22:14.516 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.522 [INFO] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob inserting template import job resource {"job_id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c", "resource_name": "cool-resource", "resource_type": "cool_resource_type", "transition": "start"} + t.go:81: 2022-06-22 23:22:14.523 [INFO] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob inserting template import job resource {"job_id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c", "resource_name": "cool-resource", "resource_type": "cool_resource_type", "transition": "stop"} + t.go:81: 2022-06-22 23:22:14.523 [DEBUG] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob marked import job as completed {"job_id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c"} + t.go:81: 2022-06-22 23:22:14.523 [INFO] (provisionerd) (*Server).runJob completed job {"id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c"} + t.go:81: 2022-06-22 23:22:14.524 [DEBUG] (provisionerd) (*Server).runJob.func2 cleaned up work directory {"error": null} + t.go:81: 2022-06-22 23:22:14.536 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa + t.go:81: 2022-06-22 23:22:14.537 [DEBUG] debugLogRequest.func1.1 POST /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run + t.go:81: 2022-06-22 23:22:14.539 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e + t.go:81: 2022-06-22 23:22:14.544 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e/logs + t.go:81: 2022-06-22 23:22:14.545 [DEBUG] (provisionerd-brave_borg8) (*provisionerdServer).AcquireJob locked job from database {"id": "b5e90a3f-0aab-4479-ab11-3b278804e81e"} + t.go:81: 2022-06-22 23:22:14.546 [INFO] (provisionerd) (*Server).acquireJob acquired job {"initiator_username": "testuser", "provisioner": "echo", "id": "b5e90a3f-0aab-4479-ab11-3b278804e81e"} + t.go:81: 2022-06-22 23:22:14.547 [INFO] (provisionerd) (*Server).runJob unpacking template source archive {"size_bytes": 5120} + t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.parse.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.provision.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 39, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/1.provision.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.provision.dry.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 39, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/1.provision.dry.protobuf", "mode": "-rw-------"} + t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob acquired job is template dry-run {"workspace_name": "", "parameters": null} + t.go:81: 2022-06-22 23:22:14.548 [DEBUG] (provisionerd) (*Server).runTemplateImportProvision template import provision job logged {"level": "TRACE", "output": ""} + t.go:81: 2022-06-22 23:22:14.548 [INFO] (provisionerd) (*Server).runTemplateImportProvision parse dry-run provision successful {"resource_count": 1, "resources": [{"name": "cool-resource", "type": "cool_resource_type"}], "state_length": 0} + t.go:81: 2022-06-22 23:22:14.555 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.566 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.573 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e + t.go:81: 2022-06-22 23:22:14.575 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.585 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.596 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running + t.go:81: 2022-06-22 23:22:14.597 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e + t.go:81: 2022-06-22 23:22:14.600 [INFO] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob inserting template dry-run job resource {"job_id": "b5e90a3f-0aab-4479-ab11-3b278804e81e", "resource_name": "cool-resource", "resource_type": "cool_resource_type"} + t.go:81: 2022-06-22 23:22:14.600 [DEBUG] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob marked template dry-run job as completed {"job_id": "b5e90a3f-0aab-4479-ab11-3b278804e81e"} + t.go:81: 2022-06-22 23:22:14.601 [INFO] (provisionerd) (*Server).runJob completed job {"id": "b5e90a3f-0aab-4479-ab11-3b278804e81e"} + t.go:81: 2022-06-22 23:22:14.602 [DEBUG] (provisionerd) (*Server).runJob.func2 cleaned up work directory {"error": null} + t.go:81: 2022-06-22 23:22:14.623 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e + t.go:81: 2022-06-22 23:22:14.798 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e/resources + t.go:81: 2022-06-22 23:22:14.800 [DEBUG] (provisionerd) (*Server).closeWithError closing server with error {"error": null} +--- PASS: TestTemplateVersionDryRun (0.00s) + --- PASS: TestTemplateVersionDryRun/OK (0.46s) +PASS +ok github.com/coder/coder/coderd 0.828s diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index 28f6bd7d016d3..c9077bcbe512d 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -617,7 +617,13 @@ func TestTemplateVersionDryRun(t *testing.T) { }) require.NoError(t, err) - _ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + require.Eventually(t, func() bool { + job, err := client.TemplateVersionDryRun(context.Background(), version.ID, job.ID) + assert.NoError(t, err) + + t.Logf("Status: %s", job.Status) + return job.Status == codersdk.ProvisionerJobSucceeded + }, 5*time.Second, 25*time.Millisecond) err = client.CancelTemplateVersionDryRun(context.Background(), version.ID, job.ID) var apiErr *codersdk.Error diff --git a/coderd/users_test.go b/coderd/users_test.go index e20593704fa6f..88193484ddf6e 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -189,7 +189,7 @@ func TestPostLogout(t *testing.T) { apiKey, err = client.GetAPIKey(ctx, admin.UserID.String(), keyID) var sdkErr = &codersdk.Error{} require.ErrorAs(t, err, &sdkErr) - require.Equal(t, http.StatusForbidden, sdkErr.StatusCode(), "Expecting Forbidden") + require.Equal(t, http.StatusUnauthorized, sdkErr.StatusCode(), "Expecting Forbidden") }) } From 3e82608581491947eb74722de0893b0de4367f35 Mon Sep 17 00:00:00 2001 From: sreya Date: Thu, 23 Jun 2022 18:49:40 +0000 Subject: [PATCH 03/11] stuff --- coderd/templateversions_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index c9077bcbe512d..0b5739999730d 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -572,6 +572,7 @@ func TestTemplateVersionDryRun(t *testing.T) { }) version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + require.Equal(t, codersdk.ProvisionerJobSucceeded, version.Job.Status) // Create the dry-run job, err := client.CreateTemplateVersionDryRun(context.Background(), version.ID, codersdk.CreateTemplateVersionDryRunRequest{ From 4a6ce0ac7afb49038a57aed24cea1dc5c8ddee74 Mon Sep 17 00:00:00 2001 From: sreya Date: Thu, 23 Jun 2022 19:01:36 +0000 Subject: [PATCH 04/11] make gen --- coderd/out.txt | 74 --------------------------- coderd/templateversions_test.go | 1 + coderd/users_test.go | 2 +- site/src/api/typesGenerated.ts | 90 +++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 75 deletions(-) delete mode 100644 coderd/out.txt diff --git a/coderd/out.txt b/coderd/out.txt deleted file mode 100644 index 6585d7ffad365..0000000000000 --- a/coderd/out.txt +++ /dev/null @@ -1,74 +0,0 @@ -=== RUN TestTemplateVersionDryRun -=== PAUSE TestTemplateVersionDryRun -=== CONT TestTemplateVersionDryRun -=== RUN TestTemplateVersionDryRun/OK -=== PAUSE TestTemplateVersionDryRun/OK -=== CONT TestTemplateVersionDryRun/OK - t.go:81: 2022-06-22 23:22:14.354 [DEBUG] debugLogRequest.func1.1 POST /api/v2/users/first - t.go:81: 2022-06-22 23:22:14.357 [DEBUG] debugLogRequest.func1.1 POST /api/v2/users/login - t.go:81: 2022-06-22 23:22:14.358 [DEBUG] debugLogRequest.func1.1 POST /api/v2/files - t.go:81: 2022-06-22 23:22:14.359 [DEBUG] debugLogRequest.func1.1 POST /api/v2/organizations/7aa01787-2231-4ddd-9332-0086223719a3/templateversions - t.go:81: 2022-06-22 23:22:14.386 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa - t.go:81: 2022-06-22 23:22:14.412 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa - t.go:81: 2022-06-22 23:22:14.436 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa - t.go:81: 2022-06-22 23:22:14.455 [DEBUG] (provisionerd) (*Server).connect connected - t.go:81: 2022-06-22 23:22:14.461 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa - t.go:81: 2022-06-22 23:22:14.466 [DEBUG] (provisionerd-brave_borg8) (*provisionerdServer).AcquireJob locked job from database {"id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c"} - t.go:81: 2022-06-22 23:22:14.466 [INFO] (provisionerd) (*Server).acquireJob acquired job {"initiator_username": "testuser", "provisioner": "echo", "id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c"} - t.go:81: 2022-06-22 23:22:14.467 [INFO] (provisionerd) (*Server).runJob unpacking template source archive {"size_bytes": 5120} - t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.parse.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.provision.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 39, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/1.provision.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.provision.dry.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 39, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/1.provision.dry.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.467 [DEBUG] (provisionerd) (*Server).runJob acquired job is template import - t.go:81: 2022-06-22 23:22:14.468 [INFO] (provisionerd) (*Server).runTemplateImportParse parse complete {"parameter_schemas": null} - t.go:81: 2022-06-22 23:22:14.470 [DEBUG] (provisionerd) (*Server).runTemplateImportProvision template import provision job logged {"level": "TRACE", "output": ""} - t.go:81: 2022-06-22 23:22:14.470 [INFO] (provisionerd) (*Server).runTemplateImportProvision parse dry-run provision successful {"resource_count": 1, "resources": [{"name": "cool-resource", "type": "cool_resource_type"}], "state_length": 0} - t.go:81: 2022-06-22 23:22:14.471 [DEBUG] (provisionerd) (*Server).runTemplateImportProvision template import provision job logged {"level": "TRACE", "output": ""} - t.go:81: 2022-06-22 23:22:14.472 [INFO] (provisionerd) (*Server).runTemplateImportProvision parse dry-run provision successful {"resource_count": 1, "resources": [{"name": "cool-resource", "type": "cool_resource_type"}], "state_length": 0} - t.go:81: 2022-06-22 23:22:14.475 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.486 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.486 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa - t.go:81: 2022-06-22 23:22:14.495 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.505 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.511 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa - t.go:81: 2022-06-22 23:22:14.516 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.522 [INFO] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob inserting template import job resource {"job_id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c", "resource_name": "cool-resource", "resource_type": "cool_resource_type", "transition": "start"} - t.go:81: 2022-06-22 23:22:14.523 [INFO] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob inserting template import job resource {"job_id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c", "resource_name": "cool-resource", "resource_type": "cool_resource_type", "transition": "stop"} - t.go:81: 2022-06-22 23:22:14.523 [DEBUG] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob marked import job as completed {"job_id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c"} - t.go:81: 2022-06-22 23:22:14.523 [INFO] (provisionerd) (*Server).runJob completed job {"id": "d3e7db15-a63a-4fc0-a48a-8fffe1d0c89c"} - t.go:81: 2022-06-22 23:22:14.524 [DEBUG] (provisionerd) (*Server).runJob.func2 cleaned up work directory {"error": null} - t.go:81: 2022-06-22 23:22:14.536 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa - t.go:81: 2022-06-22 23:22:14.537 [DEBUG] debugLogRequest.func1.1 POST /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run - t.go:81: 2022-06-22 23:22:14.539 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e - t.go:81: 2022-06-22 23:22:14.544 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e/logs - t.go:81: 2022-06-22 23:22:14.545 [DEBUG] (provisionerd-brave_borg8) (*provisionerdServer).AcquireJob locked job from database {"id": "b5e90a3f-0aab-4479-ab11-3b278804e81e"} - t.go:81: 2022-06-22 23:22:14.546 [INFO] (provisionerd) (*Server).acquireJob acquired job {"initiator_username": "testuser", "provisioner": "echo", "id": "b5e90a3f-0aab-4479-ab11-3b278804e81e"} - t.go:81: 2022-06-22 23:22:14.547 [INFO] (provisionerd) (*Server).runJob unpacking template source archive {"size_bytes": 5120} - t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.parse.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.provision.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 39, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/1.provision.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 2, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/0.provision.dry.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob extracted file {"size_bytes": 39, "path": "/tmp/TestTemplateVersionDryRunOK238154715/001/1.provision.dry.protobuf", "mode": "-rw-------"} - t.go:81: 2022-06-22 23:22:14.547 [DEBUG] (provisionerd) (*Server).runJob acquired job is template dry-run {"workspace_name": "", "parameters": null} - t.go:81: 2022-06-22 23:22:14.548 [DEBUG] (provisionerd) (*Server).runTemplateImportProvision template import provision job logged {"level": "TRACE", "output": ""} - t.go:81: 2022-06-22 23:22:14.548 [INFO] (provisionerd) (*Server).runTemplateImportProvision parse dry-run provision successful {"resource_count": 1, "resources": [{"name": "cool-resource", "type": "cool_resource_type"}], "state_length": 0} - t.go:81: 2022-06-22 23:22:14.555 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.566 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.573 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e - t.go:81: 2022-06-22 23:22:14.575 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.585 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.596 [DEBUG] (provisionerd) (*Server).acquireJob skipping acquire; job is already running - t.go:81: 2022-06-22 23:22:14.597 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e - t.go:81: 2022-06-22 23:22:14.600 [INFO] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob inserting template dry-run job resource {"job_id": "b5e90a3f-0aab-4479-ab11-3b278804e81e", "resource_name": "cool-resource", "resource_type": "cool_resource_type"} - t.go:81: 2022-06-22 23:22:14.600 [DEBUG] (provisionerd-brave_borg8) (*provisionerdServer).CompleteJob marked template dry-run job as completed {"job_id": "b5e90a3f-0aab-4479-ab11-3b278804e81e"} - t.go:81: 2022-06-22 23:22:14.601 [INFO] (provisionerd) (*Server).runJob completed job {"id": "b5e90a3f-0aab-4479-ab11-3b278804e81e"} - t.go:81: 2022-06-22 23:22:14.602 [DEBUG] (provisionerd) (*Server).runJob.func2 cleaned up work directory {"error": null} - t.go:81: 2022-06-22 23:22:14.623 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e - t.go:81: 2022-06-22 23:22:14.798 [DEBUG] debugLogRequest.func1.1 GET /api/v2/templateversions/2970435c-f7ce-48c6-81a7-73735baf6afa/dry-run/b5e90a3f-0aab-4479-ab11-3b278804e81e/resources - t.go:81: 2022-06-22 23:22:14.800 [DEBUG] (provisionerd) (*Server).closeWithError closing server with error {"error": null} ---- PASS: TestTemplateVersionDryRun (0.00s) - --- PASS: TestTemplateVersionDryRun/OK (0.46s) -PASS -ok github.com/coder/coder/coderd 0.828s diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index 0b5739999730d..ea18b3d1a1c4f 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -652,6 +652,7 @@ func TestTemplateVersionDryRun(t *testing.T) { }) version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + require.Equal(t, codersdk.ProvisionerJobSucceeded, version.Job.Status) // Create the dry-run job, err := client.CreateTemplateVersionDryRun(context.Background(), version.ID, codersdk.CreateTemplateVersionDryRunRequest{ diff --git a/coderd/users_test.go b/coderd/users_test.go index 88193484ddf6e..9668434da3f4a 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -189,7 +189,7 @@ func TestPostLogout(t *testing.T) { apiKey, err = client.GetAPIKey(ctx, admin.UserID.String(), keyID) var sdkErr = &codersdk.Error{} require.ErrorAs(t, err, &sdkErr) - require.Equal(t, http.StatusUnauthorized, sdkErr.StatusCode(), "Expecting Forbidden") + require.Equal(t, http.StatusUnauthorized, sdkErr.StatusCode(), "Expecting 401") }) } diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 5721d1d50a93e..83d8f71123426 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1,6 +1,22 @@ // Code generated by 'make coder/scripts/apitypings/main.go'. DO NOT EDIT. +<<<<<<< HEAD // From codersdk/workspaceagents.go:36:6 +======= +// From codersdk/users.go:49:6 +export interface APIKey { + readonly id: string + readonly user_id: string + readonly last_used: string + readonly expires_at: string + readonly created_at: string + readonly updated_at: string + readonly login_type: LoginType + readonly lifetime_seconds: number +} + +// From codersdk/workspaceagents.go:35:6 +>>>>>>> make gen export interface AWSInstanceIdentityToken { readonly signature: string readonly document: string @@ -12,7 +28,11 @@ export interface AgentGitSSHKey { readonly private_key: string } +<<<<<<< HEAD // From codersdk/users.go:156:6 +======= +// From codersdk/users.go:169:6 +>>>>>>> make gen export interface AuthMethods { readonly password: boolean readonly github: boolean @@ -37,7 +57,11 @@ export interface ComputedParameter extends Parameter { readonly default_source_value: boolean } +<<<<<<< HEAD // From codersdk/users.go:47:6 +======= +// From codersdk/users.go:60:6 +>>>>>>> make gen export interface CreateFirstUserRequest { readonly email: string readonly username: string @@ -45,13 +69,21 @@ export interface CreateFirstUserRequest { readonly organization: string } +<<<<<<< HEAD // From codersdk/users.go:55:6 +======= +// From codersdk/users.go:68:6 +>>>>>>> make gen export interface CreateFirstUserResponse { readonly user_id: string readonly organization_id: string } +<<<<<<< HEAD // From codersdk/users.go:151:6 +======= +// From codersdk/users.go:164:6 +>>>>>>> make gen export interface CreateOrganizationRequest { readonly name: string } @@ -90,7 +122,11 @@ export interface CreateTemplateVersionRequest { readonly parameter_values?: CreateParameterRequest[] } +<<<<<<< HEAD // From codersdk/users.go:60:6 +======= +// From codersdk/users.go:73:6 +>>>>>>> make gen export interface CreateUserRequest { readonly email: string readonly username: string @@ -116,7 +152,11 @@ export interface CreateWorkspaceRequest { readonly parameter_values?: CreateParameterRequest[] } +<<<<<<< HEAD // From codersdk/users.go:147:6 +======= +// From codersdk/users.go:160:6 +>>>>>>> make gen export interface GenerateAPIKeyResponse { readonly key: string } @@ -134,13 +174,21 @@ export interface GoogleInstanceIdentityToken { readonly json_web_token: string } +<<<<<<< HEAD // From codersdk/users.go:136:6 +======= +// From codersdk/users.go:149:6 +>>>>>>> make gen export interface LoginWithPasswordRequest { readonly email: string readonly password: string } +<<<<<<< HEAD // From codersdk/users.go:142:6 +======= +// From codersdk/users.go:155:6 +>>>>>>> make gen export interface LoginWithPasswordResponse { readonly session_token: string } @@ -283,7 +331,11 @@ export interface UpdateActiveTemplateVersion { readonly id: string } +<<<<<<< HEAD // From codersdk/users.go:76:6 +======= +// From codersdk/users.go:89:6 +>>>>>>> make gen export interface UpdateRoles { readonly roles: string[] } @@ -295,13 +347,21 @@ export interface UpdateTemplateMeta { readonly min_autostart_interval_ms?: number } +<<<<<<< HEAD // From codersdk/users.go:71:6 +======= +// From codersdk/users.go:84:6 +>>>>>>> make gen export interface UpdateUserPasswordRequest { readonly old_password: string readonly password: string } +<<<<<<< HEAD // From codersdk/users.go:67:6 +======= +// From codersdk/users.go:80:6 +>>>>>>> make gen export interface UpdateUserProfileRequest { readonly username: string } @@ -321,7 +381,11 @@ export interface UploadResponse { readonly hash: string } +<<<<<<< HEAD // From codersdk/users.go:37:6 +======= +// From codersdk/users.go:39:6 +>>>>>>> make gen export interface User { readonly id: string readonly email: string @@ -332,13 +396,21 @@ export interface User { readonly roles: Role[] } +<<<<<<< HEAD // From codersdk/users.go:101:6 +======= +// From codersdk/users.go:114:6 +>>>>>>> make gen export interface UserAuthorization { readonly object: UserAuthorizationObject readonly action: string } +<<<<<<< HEAD // From codersdk/users.go:117:6 +======= +// From codersdk/users.go:130:6 +>>>>>>> make gen export interface UserAuthorizationObject { readonly resource_type: string readonly owner_id?: string @@ -346,21 +418,36 @@ export interface UserAuthorizationObject { readonly resource_id?: string } +<<<<<<< HEAD // From codersdk/users.go:90:6 +======= +// From codersdk/users.go:103:6 +>>>>>>> make gen export interface UserAuthorizationRequest { readonly checks: Record } +<<<<<<< HEAD // From codersdk/users.go:85:6 export type UserAuthorizationResponse = Record // From codersdk/users.go:80:6 +======= +// From codersdk/users.go:98:6 +export type UserAuthorizationResponse = Record + +// From codersdk/users.go:93:6 +>>>>>>> make gen export interface UserRoles { readonly roles: string[] readonly organization_roles: Record } +<<<<<<< HEAD // From codersdk/users.go:25:6 +======= +// From codersdk/users.go:31:6 +>>>>>>> make gen export interface UsersRequest extends Pagination { readonly q?: string } @@ -500,6 +587,9 @@ export type LogLevel = "debug" | "error" | "info" | "trace" | "warn" // From codersdk/provisionerdaemons.go:21:6 export type LogSource = "provisioner" | "provisioner_daemon" +// From codersdk/users.go:24:6 +export type LoginType = "github" | "password" + // From codersdk/parameters.go:29:6 export type ParameterDestinationScheme = "environment_variable" | "none" | "provisioner_variable" From 4972840561da3ae145523a45ec44eafd32a0bfce Mon Sep 17 00:00:00 2001 From: sreya Date: Thu, 23 Jun 2022 19:05:56 +0000 Subject: [PATCH 05/11] lint --- coderd/users_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/users_test.go b/coderd/users_test.go index 9668434da3f4a..d8bd106127a81 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -186,7 +186,7 @@ func TestPostLogout(t *testing.T) { require.Equal(t, httpmw.SessionTokenKey, cookies[0].Name, "Cookie should be the auth cookie") require.Equal(t, -1, cookies[0].MaxAge, "Cookie should be set to delete") - apiKey, err = client.GetAPIKey(ctx, admin.UserID.String(), keyID) + _, err = client.GetAPIKey(ctx, admin.UserID.String(), keyID) var sdkErr = &codersdk.Error{} require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusUnauthorized, sdkErr.StatusCode(), "Expecting 401") From b12736736d40437bbd44243851bba1521b294660 Mon Sep 17 00:00:00 2001 From: sreya Date: Fri, 24 Jun 2022 15:56:55 +0000 Subject: [PATCH 06/11] some different jank --- cli/create_test.go | 4 +-- coderd/templateversions_test.go | 8 +++--- coderd/workspaces_test.go | 6 +++-- provisioner/echo/serve.go | 47 ++++++++++++++++++++++++++------- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/cli/create_test.go b/cli/create_test.go index 752501b4f951b..35f3ae2e4fcfd 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -266,7 +266,7 @@ func TestCreate(t *testing.T) { Description: "description 1", DefaultSource: &proto.ParameterSource{ Scheme: proto.ParameterSource_DATA, - Value: "exit 0", + Value: echo.ParameterSucceed(), }, DefaultDestination: &proto.ParameterDestination{ Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE, @@ -287,7 +287,7 @@ func TestCreate(t *testing.T) { tempDir := t.TempDir() parameterFile, _ := os.CreateTemp(tempDir, "testParameterFile*.yaml") - _, _ = parameterFile.WriteString(fmt.Sprintf("%s: %q", echo.ParameterExecKey, "exit 1")) + _, _ = parameterFile.WriteString(fmt.Sprintf("%s: %q", echo.ParameterExecKey, echo.ParameterError("fail"))) // The template import job should end up failed, but we need it to be // succeeded so the dry-run can begin. diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index ea18b3d1a1c4f..406b6ddf5d996 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -578,8 +578,10 @@ func TestTemplateVersionDryRun(t *testing.T) { job, err := client.CreateTemplateVersionDryRun(context.Background(), version.ID, codersdk.CreateTemplateVersionDryRunRequest{ ParameterValues: []codersdk.CreateParameterRequest{ { - Name: echo.ParameterExecKey, - SourceValue: "tail -f /dev/null", + Name: echo.ParameterExecKey, + // Sleep for a ridiculously long time so we don't accidentally complete + // before we successfully cancel the job. + SourceValue: echo.ParameterSleep(time.Minute * 5), }, }, }) @@ -659,7 +661,7 @@ func TestTemplateVersionDryRun(t *testing.T) { ParameterValues: []codersdk.CreateParameterRequest{ { Name: echo.ParameterExecKey, - SourceValue: "tail -f /dev/null", + SourceValue: echo.ParameterSleep(time.Minute * 5), }, }, }) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index 0daa939d77ac2..9989cbc8b40df 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -671,8 +671,10 @@ func TestPostWorkspaceBuild(t *testing.T) { func(req *codersdk.CreateWorkspaceRequest) { req.ParameterValues = []codersdk.CreateParameterRequest{ { - Name: echo.ParameterExecKey, - SourceValue: "tail -f /dev/null", + Name: echo.ParameterExecKey, + SourceValue: echo.ParameterSleep(time.Minute * 5), + SourceScheme: codersdk.ParameterSourceSchemeData, + DestinationScheme: codersdk.ParameterDestinationSchemeProvisionerVariable, }, } }) diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index c8766858912b1..f81a78005341e 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -5,9 +5,9 @@ import ( "bytes" "context" "fmt" - "os/exec" "path/filepath" "strings" + "time" "golang.org/x/xerrors" protobuf "google.golang.org/protobuf/proto" @@ -20,8 +20,28 @@ import ( const ( ParameterExecKey = "echo.exec" + + sleepKey = "sleep" + errorKey = "error" + successKey = "success" ) +func ParameterError(s string) string { + return formatExecValue(errorKey, s) +} + +func ParameterSleep(dur time.Duration) string { + return formatExecValue(sleepKey, dur.String()) +} + +func ParameterSucceed() string { + return formatExecValue(successKey, "") +} + +func formatExecValue(key, value string) string { + return fmt.Sprintf("%s=%s", key, value) +} + var ( // ParseComplete is a helper to indicate an empty parse completion. ParseComplete = []*proto.Parse_Response{{ @@ -95,15 +115,22 @@ func (e *echo) Provision(stream proto.DRPCProvisioner_ProvisionStream) error { for _, param := range request.ParameterValues { if param.Name == ParameterExecKey { - // #nosec G204 - cmd := exec.Command("/bin/sh", "-c", param.Value) - out, err := cmd.CombinedOutput() - if err != nil { - return xerrors.Errorf("exec %q returned %q: %w", - strings.Join(cmd.Args, " "), - string(out), - err, - ) + toks := strings.Split(param.Value, "=") + if len(toks) < 2 { + break + } + + switch toks[0] { + case sleepKey: + dur, err := time.ParseDuration(toks[1]) + if err != nil { + return xerrors.Errorf("parse duration: %w", err) + } + time.Sleep(dur) + case errorKey: + return xerrors.Errorf("returning error: %v", toks[1]) + default: + // Do nothing } } } From 3cae236d70ef5adbe19854aa6a7fb3d55711b144 Mon Sep 17 00:00:00 2001 From: sreya Date: Fri, 24 Jun 2022 19:45:14 +0000 Subject: [PATCH 07/11] some small revisions --- coderd/coderdtest/coderdtest.go | 30 ++++++++++++++++++++++++++---- coderd/templateversions_test.go | 31 +++++++++++++------------------ coderd/workspaces_test.go | 20 ++++---------------- provisioner/echo/serve.go | 12 ------------ 4 files changed, 43 insertions(+), 50 deletions(-) diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 6f4751a5ec4f6..fec5d8b4b445a 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -78,8 +78,22 @@ func New(t *testing.T, options *Options) *codersdk.Client { return client } -// newWithAPI constructs a codersdk client connected to the returned in-memory API instance. -func newWithAPI(t *testing.T, options *Options) (*codersdk.Client, *coderd.API) { +// NewWithProvisionerCloser returns a client as well as a handle to close +// the provisioner. This is a temporary function while work is done to +// standardize how provisioners are registered with coderd. The option +// to include a provisioner is set to true for convenience. +func NewWithProvisionerCloser(t *testing.T, options *Options) (*codersdk.Client, io.Closer) { + if options == nil { + options = &Options{} + } + options.IncludeProvisionerD = true + client, close := newWithAPI(t, options) + return client, close +} + +// newWithAPI constructs a codersdk client connected to an in-memory API instance. +// The returned closer closes a provisioner if it was provided +func newWithAPI(t *testing.T, options *Options) (*codersdk.Client, io.Closer) { if options == nil { options = &Options{} } @@ -169,17 +183,21 @@ func newWithAPI(t *testing.T, options *Options) (*codersdk.Client, *coderd.API) Telemetry: telemetry.NewNoop(), }) srv.Config.Handler = coderAPI.Handler + + var provisionerCloser io.Closer = nopcloser{} if options.IncludeProvisionerD { - _ = NewProvisionerDaemon(t, coderAPI) + provisionerCloser = NewProvisionerDaemon(t, coderAPI) } + t.Cleanup(func() { cancelFunc() _ = turnServer.Close() srv.Close() _ = coderAPI.Close() + _ = provisionerCloser.Close() }) - return codersdk.New(serverURL), coderAPI + return codersdk.New(serverURL), provisionerCloser } // NewProvisionerDaemon launches a provisionerd instance configured to work @@ -648,3 +666,7 @@ type roundTripper func(req *http.Request) (*http.Response, error) func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return r(req) } + +type nopcloser struct{} + +func (nopcloser) Close() error { return nil } diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index 406b6ddf5d996..a2cc37fc49931 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -553,7 +553,9 @@ func TestTemplateVersionDryRun(t *testing.T) { t.Run("OK", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) + client, closer := coderdtest.NewWithProvisionerCloser(t, nil) + defer closer.Close() + user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ @@ -574,16 +576,10 @@ func TestTemplateVersionDryRun(t *testing.T) { version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) require.Equal(t, codersdk.ProvisionerJobSucceeded, version.Job.Status) + closer.Close() // Create the dry-run job, err := client.CreateTemplateVersionDryRun(context.Background(), version.ID, codersdk.CreateTemplateVersionDryRunRequest{ - ParameterValues: []codersdk.CreateParameterRequest{ - { - Name: echo.ParameterExecKey, - // Sleep for a ridiculously long time so we don't accidentally complete - // before we successfully cancel the job. - SourceValue: echo.ParameterSleep(time.Minute * 5), - }, - }, + ParameterValues: []codersdk.CreateParameterRequest{}, }) require.NoError(t, err) @@ -592,7 +588,7 @@ func TestTemplateVersionDryRun(t *testing.T) { assert.NoError(t, err) t.Logf("Status: %s", job.Status) - return job.Status == codersdk.ProvisionerJobRunning + return job.Status == codersdk.ProvisionerJobPending }, 5*time.Second, 25*time.Millisecond) err = client.CancelTemplateVersionDryRun(context.Background(), version.ID, job.ID) @@ -603,7 +599,7 @@ func TestTemplateVersionDryRun(t *testing.T) { assert.NoError(t, err) t.Logf("Status: %s", job.Status) - return job.Status == codersdk.ProvisionerJobCanceled + return job.Status == codersdk.ProvisionerJobCanceling }, 5*time.Second, 25*time.Millisecond) }) @@ -636,7 +632,9 @@ func TestTemplateVersionDryRun(t *testing.T) { t.Run("AlreadyCanceled", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) + client, closer := coderdtest.NewWithProvisionerCloser(t, nil) + defer closer.Close() + user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, @@ -656,14 +654,11 @@ func TestTemplateVersionDryRun(t *testing.T) { version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) require.Equal(t, codersdk.ProvisionerJobSucceeded, version.Job.Status) + closer.Close() + // Create the dry-run job, err := client.CreateTemplateVersionDryRun(context.Background(), version.ID, codersdk.CreateTemplateVersionDryRunRequest{ - ParameterValues: []codersdk.CreateParameterRequest{ - { - Name: echo.ParameterExecKey, - SourceValue: echo.ParameterSleep(time.Minute * 5), - }, - }, + ParameterValues: []codersdk.CreateParameterRequest{}, }) require.NoError(t, err) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index 9989cbc8b40df..fe5fb02ca3b8d 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -656,28 +656,16 @@ func TestPostWorkspaceBuild(t *testing.T) { t.Run("AlreadyActive", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerD: true, - }) + client, closer := coderdtest.NewWithProvisionerCloser(t, nil) + defer closer.Close() user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + closer.Close() // Close here so workspace build doesn't process! - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID, - // Provide a parameter that will cause the workspace build to - // hang. - func(req *codersdk.CreateWorkspaceRequest) { - req.ParameterValues = []codersdk.CreateParameterRequest{ - { - Name: echo.ParameterExecKey, - SourceValue: echo.ParameterSleep(time.Minute * 5), - SourceScheme: codersdk.ParameterSourceSchemeData, - DestinationScheme: codersdk.ParameterDestinationSchemeProvisionerVariable, - }, - } - }) + workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) _, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{ TemplateVersionID: template.ActiveVersionID, Transition: codersdk.WorkspaceTransitionStart, diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index f81a78005341e..27dd35b92500b 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -7,7 +7,6 @@ import ( "fmt" "path/filepath" "strings" - "time" "golang.org/x/xerrors" protobuf "google.golang.org/protobuf/proto" @@ -21,7 +20,6 @@ import ( const ( ParameterExecKey = "echo.exec" - sleepKey = "sleep" errorKey = "error" successKey = "success" ) @@ -30,10 +28,6 @@ func ParameterError(s string) string { return formatExecValue(errorKey, s) } -func ParameterSleep(dur time.Duration) string { - return formatExecValue(sleepKey, dur.String()) -} - func ParameterSucceed() string { return formatExecValue(successKey, "") } @@ -121,12 +115,6 @@ func (e *echo) Provision(stream proto.DRPCProvisioner_ProvisionStream) error { } switch toks[0] { - case sleepKey: - dur, err := time.ParseDuration(toks[1]) - if err != nil { - return xerrors.Errorf("parse duration: %w", err) - } - time.Sleep(dur) case errorKey: return xerrors.Errorf("returning error: %v", toks[1]) default: From 3557eeb42b9d4737a77855c5f76fca9172c163b2 Mon Sep 17 00:00:00 2001 From: sreya Date: Fri, 24 Jun 2022 19:49:15 +0000 Subject: [PATCH 08/11] add a comment to dissuade exposing API --- coderd/coderdtest/coderdtest.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index fec5d8b4b445a..de1e361fa7453 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -74,7 +74,7 @@ type Options struct { // New constructs a codersdk client connected to an in-memory API instance. func New(t *testing.T, options *Options) *codersdk.Client { - client, _ := newWithAPI(t, options) + client, _ := newWithCloser(t, options) return client } @@ -87,13 +87,18 @@ func NewWithProvisionerCloser(t *testing.T, options *Options) (*codersdk.Client, options = &Options{} } options.IncludeProvisionerD = true - client, close := newWithAPI(t, options) + client, close := newWithCloser(t, options) return client, close } -// newWithAPI constructs a codersdk client connected to an in-memory API instance. +// newWithCloser constructs a codersdk client connected to an in-memory API instance. // The returned closer closes a provisioner if it was provided -func newWithAPI(t *testing.T, options *Options) (*codersdk.Client, io.Closer) { +// The API is intentionally not returned here because coderd tests should not +// require a handle to the API. Do not expose the API or wrath shall descend +// upon thee. Even the io.Closer that is exposed here shouldn't be exposed +// and is a temporary measure while the API to register provisioners is ironed +// out. +func newWithCloser(t *testing.T, options *Options) (*codersdk.Client, io.Closer) { if options == nil { options = &Options{} } From a2fcb790099ca4f506ca0dbfe1aea1b588b41f77 Mon Sep 17 00:00:00 2001 From: sreya Date: Fri, 24 Jun 2022 19:54:34 +0000 Subject: [PATCH 09/11] add a gitignore --- cmd/coder/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 cmd/coder/.gitignore diff --git a/cmd/coder/.gitignore b/cmd/coder/.gitignore new file mode 100644 index 0000000000000..972bf968c8cdd --- /dev/null +++ b/cmd/coder/.gitignore @@ -0,0 +1 @@ +coder From a54a322d440366d63903af672862d4e516bd576a Mon Sep 17 00:00:00 2001 From: sreya Date: Fri, 24 Jun 2022 23:09:11 +0000 Subject: [PATCH 10/11] lint --- coderd/coderdtest/coderdtest.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index de1e361fa7453..d06007c50c3e4 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -87,8 +87,8 @@ func NewWithProvisionerCloser(t *testing.T, options *Options) (*codersdk.Client, options = &Options{} } options.IncludeProvisionerD = true - client, close := newWithCloser(t, options) - return client, close + client, closer := newWithCloser(t, options) + return client, closer } // newWithCloser constructs a codersdk client connected to an in-memory API instance. From 10127b2b1bff39e1bb849ce396bf8deb2d2327b4 Mon Sep 17 00:00:00 2001 From: sreya Date: Mon, 27 Jun 2022 18:36:58 +0000 Subject: [PATCH 11/11] pr comments --- cli/create_test.go | 15 +---- provisioner/echo/serve.go | 15 +++++ site/src/api/typesGenerated.ts | 115 ++++++--------------------------- 3 files changed, 36 insertions(+), 109 deletions(-) diff --git a/cli/create_test.go b/cli/create_test.go index 35f3ae2e4fcfd..453bdbfbd1b9e 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -259,20 +259,7 @@ func TestCreate(t *testing.T) { Parse: []*proto.Parse_Response{{ Type: &proto.Parse_Response_Complete{ Complete: &proto.Parse_Complete{ - ParameterSchemas: []*proto.ParameterSchema{ - { - AllowOverrideSource: true, - Name: echo.ParameterExecKey, - Description: "description 1", - DefaultSource: &proto.ParameterSource{ - Scheme: proto.ParameterSource_DATA, - Value: echo.ParameterSucceed(), - }, - DefaultDestination: &proto.ParameterDestination{ - Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE, - }, - }, - }, + ParameterSchemas: echo.ParameterSuccess, }, }, }}, diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 27dd35b92500b..934c715211675 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -49,6 +49,21 @@ var ( Complete: &proto.Provision_Complete{}, }, }} + + ParameterSuccess = []*proto.ParameterSchema{ + { + AllowOverrideSource: true, + Name: ParameterExecKey, + Description: "description 1", + DefaultSource: &proto.ParameterSource{ + Scheme: proto.ParameterSource_DATA, + Value: formatExecValue(successKey, ""), + }, + DefaultDestination: &proto.ParameterDestination{ + Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE, + }, + }, + } ) // Serve starts the echo provisioner. diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 83d8f71123426..96afeb66799f7 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1,9 +1,6 @@ // Code generated by 'make coder/scripts/apitypings/main.go'. DO NOT EDIT. -<<<<<<< HEAD -// From codersdk/workspaceagents.go:36:6 -======= -// From codersdk/users.go:49:6 +// From codersdk/users.go:54:6 export interface APIKey { readonly id: string readonly user_id: string @@ -15,8 +12,7 @@ export interface APIKey { readonly lifetime_seconds: number } -// From codersdk/workspaceagents.go:35:6 ->>>>>>> make gen +// From codersdk/workspaceagents.go:36:6 export interface AWSInstanceIdentityToken { readonly signature: string readonly document: string @@ -28,11 +24,7 @@ export interface AgentGitSSHKey { readonly private_key: string } -<<<<<<< HEAD -// From codersdk/users.go:156:6 -======= -// From codersdk/users.go:169:6 ->>>>>>> make gen +// From codersdk/users.go:174:6 export interface AuthMethods { readonly password: boolean readonly github: boolean @@ -57,11 +49,7 @@ export interface ComputedParameter extends Parameter { readonly default_source_value: boolean } -<<<<<<< HEAD -// From codersdk/users.go:47:6 -======= -// From codersdk/users.go:60:6 ->>>>>>> make gen +// From codersdk/users.go:65:6 export interface CreateFirstUserRequest { readonly email: string readonly username: string @@ -69,21 +57,13 @@ export interface CreateFirstUserRequest { readonly organization: string } -<<<<<<< HEAD -// From codersdk/users.go:55:6 -======= -// From codersdk/users.go:68:6 ->>>>>>> make gen +// From codersdk/users.go:73:6 export interface CreateFirstUserResponse { readonly user_id: string readonly organization_id: string } -<<<<<<< HEAD -// From codersdk/users.go:151:6 -======= -// From codersdk/users.go:164:6 ->>>>>>> make gen +// From codersdk/users.go:169:6 export interface CreateOrganizationRequest { readonly name: string } @@ -122,11 +102,7 @@ export interface CreateTemplateVersionRequest { readonly parameter_values?: CreateParameterRequest[] } -<<<<<<< HEAD -// From codersdk/users.go:60:6 -======= -// From codersdk/users.go:73:6 ->>>>>>> make gen +// From codersdk/users.go:78:6 export interface CreateUserRequest { readonly email: string readonly username: string @@ -152,11 +128,7 @@ export interface CreateWorkspaceRequest { readonly parameter_values?: CreateParameterRequest[] } -<<<<<<< HEAD -// From codersdk/users.go:147:6 -======= -// From codersdk/users.go:160:6 ->>>>>>> make gen +// From codersdk/users.go:165:6 export interface GenerateAPIKeyResponse { readonly key: string } @@ -174,21 +146,13 @@ export interface GoogleInstanceIdentityToken { readonly json_web_token: string } -<<<<<<< HEAD -// From codersdk/users.go:136:6 -======= -// From codersdk/users.go:149:6 ->>>>>>> make gen +// From codersdk/users.go:154:6 export interface LoginWithPasswordRequest { readonly email: string readonly password: string } -<<<<<<< HEAD -// From codersdk/users.go:142:6 -======= -// From codersdk/users.go:155:6 ->>>>>>> make gen +// From codersdk/users.go:160:6 export interface LoginWithPasswordResponse { readonly session_token: string } @@ -331,11 +295,7 @@ export interface UpdateActiveTemplateVersion { readonly id: string } -<<<<<<< HEAD -// From codersdk/users.go:76:6 -======= -// From codersdk/users.go:89:6 ->>>>>>> make gen +// From codersdk/users.go:94:6 export interface UpdateRoles { readonly roles: string[] } @@ -347,21 +307,13 @@ export interface UpdateTemplateMeta { readonly min_autostart_interval_ms?: number } -<<<<<<< HEAD -// From codersdk/users.go:71:6 -======= -// From codersdk/users.go:84:6 ->>>>>>> make gen +// From codersdk/users.go:89:6 export interface UpdateUserPasswordRequest { readonly old_password: string readonly password: string } -<<<<<<< HEAD -// From codersdk/users.go:67:6 -======= -// From codersdk/users.go:80:6 ->>>>>>> make gen +// From codersdk/users.go:85:6 export interface UpdateUserProfileRequest { readonly username: string } @@ -381,11 +333,7 @@ export interface UploadResponse { readonly hash: string } -<<<<<<< HEAD -// From codersdk/users.go:37:6 -======= -// From codersdk/users.go:39:6 ->>>>>>> make gen +// From codersdk/users.go:44:6 export interface User { readonly id: string readonly email: string @@ -396,21 +344,13 @@ export interface User { readonly roles: Role[] } -<<<<<<< HEAD -// From codersdk/users.go:101:6 -======= -// From codersdk/users.go:114:6 ->>>>>>> make gen +// From codersdk/users.go:119:6 export interface UserAuthorization { readonly object: UserAuthorizationObject readonly action: string } -<<<<<<< HEAD -// From codersdk/users.go:117:6 -======= -// From codersdk/users.go:130:6 ->>>>>>> make gen +// From codersdk/users.go:135:6 export interface UserAuthorizationObject { readonly resource_type: string readonly owner_id?: string @@ -418,36 +358,21 @@ export interface UserAuthorizationObject { readonly resource_id?: string } -<<<<<<< HEAD -// From codersdk/users.go:90:6 -======= -// From codersdk/users.go:103:6 ->>>>>>> make gen +// From codersdk/users.go:108:6 export interface UserAuthorizationRequest { readonly checks: Record } -<<<<<<< HEAD -// From codersdk/users.go:85:6 +// From codersdk/users.go:103:6 export type UserAuthorizationResponse = Record -// From codersdk/users.go:80:6 -======= // From codersdk/users.go:98:6 -export type UserAuthorizationResponse = Record - -// From codersdk/users.go:93:6 ->>>>>>> make gen export interface UserRoles { readonly roles: string[] readonly organization_roles: Record } -<<<<<<< HEAD -// From codersdk/users.go:25:6 -======= -// From codersdk/users.go:31:6 ->>>>>>> make gen +// From codersdk/users.go:32:6 export interface UsersRequest extends Pagination { readonly q?: string } @@ -587,7 +512,7 @@ export type LogLevel = "debug" | "error" | "info" | "trace" | "warn" // From codersdk/provisionerdaemons.go:21:6 export type LogSource = "provisioner" | "provisioner_daemon" -// From codersdk/users.go:24:6 +// From codersdk/users.go:25:6 export type LoginType = "github" | "password" // From codersdk/parameters.go:29:6