2022-03-07 17:40:54 +00:00
|
|
|
package coderd_test
|
|
|
|
|
|
|
|
import (
|
2023-02-04 20:07:09 +00:00
|
|
|
"bytes"
|
2022-03-07 17:40:54 +00:00
|
|
|
"context"
|
|
|
|
"net/http"
|
2023-02-27 16:18:19 +00:00
|
|
|
"regexp"
|
2022-03-07 17:40:54 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
2022-05-16 19:36:27 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2022-03-07 17:40:54 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2022-08-09 17:17:00 +00:00
|
|
|
"golang.org/x/sync/errgroup"
|
2022-03-07 17:40:54 +00:00
|
|
|
|
2022-09-09 16:34:23 +00:00
|
|
|
"github.com/coder/coder/coderd/audit"
|
2022-03-07 17:40:54 +00:00
|
|
|
"github.com/coder/coder/coderd/coderdtest"
|
2022-09-09 16:34:23 +00:00
|
|
|
"github.com/coder/coder/coderd/database"
|
2023-02-27 16:18:19 +00:00
|
|
|
"github.com/coder/coder/coderd/gitauth"
|
2022-11-16 22:34:06 +00:00
|
|
|
"github.com/coder/coder/coderd/provisionerdserver"
|
2023-03-21 14:10:22 +00:00
|
|
|
"github.com/coder/coder/coderd/rbac"
|
2022-03-07 17:40:54 +00:00
|
|
|
"github.com/coder/coder/codersdk"
|
2022-12-09 19:29:50 +00:00
|
|
|
"github.com/coder/coder/examples"
|
2022-03-07 17:40:54 +00:00
|
|
|
"github.com/coder/coder/provisioner/echo"
|
|
|
|
"github.com/coder/coder/provisionersdk/proto"
|
2022-08-01 12:45:05 +00:00
|
|
|
"github.com/coder/coder/testutil"
|
2022-03-07 17:40:54 +00:00
|
|
|
)
|
|
|
|
|
2022-04-06 17:42:40 +00:00
|
|
|
func TestTemplateVersion(t *testing.T) {
|
2022-03-07 17:40:54 +00:00
|
|
|
t.Parallel()
|
|
|
|
t.Run("Get", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2023-03-21 14:10:22 +00:00
|
|
|
client, _, api := coderdtest.NewWithAPI(t, nil)
|
2022-03-07 17:40:54 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2023-03-21 14:10:22 +00:00
|
|
|
authz := coderdtest.AssertRBAC(t, api, client).Reset()
|
|
|
|
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
2023-03-21 14:10:22 +00:00
|
|
|
authz.AssertChecked(t, rbac.ActionCreate, rbac.ResourceTemplate.InOrg(user.OrganizationID))
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-03-21 14:10:22 +00:00
|
|
|
authz.Reset()
|
|
|
|
tv, err := client.TemplateVersion(ctx, version.ID)
|
|
|
|
authz.AssertChecked(t, rbac.ActionRead, tv)
|
2022-03-07 17:40:54 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
2022-10-10 20:37:06 +00:00
|
|
|
|
|
|
|
t.Run("MemberCanRead", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
_ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
|
|
|
|
|
|
|
ctx, _ := testutil.Context(t)
|
|
|
|
|
2023-02-06 23:48:21 +00:00
|
|
|
client1, _ := coderdtest.CreateAnotherUser(t, client, user.OrganizationID)
|
2022-10-10 20:37:06 +00:00
|
|
|
|
|
|
|
_, err := client1.TemplateVersion(ctx, version.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
2022-03-07 17:40:54 +00:00
|
|
|
}
|
|
|
|
|
2022-05-16 19:36:27 +00:00
|
|
|
func TestPostTemplateVersionsByOrganization(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
t.Run("InvalidTemplate", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-05-16 19:36:27 +00:00
|
|
|
templateID := uuid.New()
|
2022-08-09 17:17:00 +00:00
|
|
|
_, err := client.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
2022-05-16 19:36:27 +00:00
|
|
|
TemplateID: templateID,
|
2022-05-19 18:04:44 +00:00
|
|
|
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
2022-10-13 23:02:52 +00:00
|
|
|
FileID: uuid.New(),
|
2022-05-19 18:04:44 +00:00
|
|
|
Provisioner: codersdk.ProvisionerTypeEcho,
|
2022-05-16 19:36:27 +00:00
|
|
|
})
|
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
|
|
|
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("FileNotFound", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
2022-05-19 18:04:44 +00:00
|
|
|
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
2022-10-13 23:02:52 +00:00
|
|
|
FileID: uuid.New(),
|
2022-05-19 18:04:44 +00:00
|
|
|
Provisioner: codersdk.ProvisionerTypeEcho,
|
2022-05-16 19:36:27 +00:00
|
|
|
})
|
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
|
|
|
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("WithParameters", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-09 16:34:23 +00:00
|
|
|
auditor := audit.NewMock()
|
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, Auditor: auditor})
|
2022-05-16 19:36:27 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
data, err := echo.Tar(&echo.Responses{
|
2022-11-11 22:45:58 +00:00
|
|
|
Parse: echo.ParseComplete,
|
|
|
|
ProvisionApply: echo.ProvisionComplete,
|
|
|
|
ProvisionPlan: echo.ProvisionComplete,
|
2022-05-16 19:36:27 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-02-04 20:07:09 +00:00
|
|
|
file, err := client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader(data))
|
2022-05-16 19:36:27 +00:00
|
|
|
require.NoError(t, err)
|
2022-09-24 01:17:36 +00:00
|
|
|
version, err := client.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
|
|
|
Name: "bananas",
|
2022-05-19 18:04:44 +00:00
|
|
|
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
2022-10-13 23:02:52 +00:00
|
|
|
FileID: file.ID,
|
2022-05-19 18:04:44 +00:00
|
|
|
Provisioner: codersdk.ProvisionerTypeEcho,
|
2022-05-16 19:36:27 +00:00
|
|
|
ParameterValues: []codersdk.CreateParameterRequest{{
|
|
|
|
Name: "example",
|
|
|
|
SourceValue: "value",
|
2022-05-19 18:04:44 +00:00
|
|
|
SourceScheme: codersdk.ParameterSourceSchemeData,
|
|
|
|
DestinationScheme: codersdk.ParameterDestinationSchemeProvisionerVariable,
|
2022-05-16 19:36:27 +00:00
|
|
|
}},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2022-09-24 01:17:36 +00:00
|
|
|
require.Equal(t, "bananas", version.Name)
|
2022-11-16 22:34:06 +00:00
|
|
|
require.Equal(t, provisionerdserver.ScopeOrganization, version.Job.Tags[provisionerdserver.TagScope])
|
2022-09-09 16:34:23 +00:00
|
|
|
|
2023-02-06 20:12:50 +00:00
|
|
|
require.Len(t, auditor.AuditLogs, 2)
|
|
|
|
assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs[1].Action)
|
2022-05-16 19:36:27 +00:00
|
|
|
})
|
2022-12-09 19:29:50 +00:00
|
|
|
t.Run("Example", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
ls, err := examples.List()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// try a bad example ID
|
|
|
|
_, err = client.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
|
|
|
Name: "my-example",
|
|
|
|
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
|
|
|
ExampleID: "not a real ID",
|
|
|
|
Provisioner: codersdk.ProvisionerTypeEcho,
|
|
|
|
})
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "not found")
|
|
|
|
|
|
|
|
// try file and example IDs
|
|
|
|
_, err = client.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
|
|
|
Name: "my-example",
|
|
|
|
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
|
|
|
ExampleID: ls[0].ID,
|
|
|
|
FileID: uuid.New(),
|
|
|
|
Provisioner: codersdk.ProvisionerTypeEcho,
|
|
|
|
})
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "example_id")
|
|
|
|
require.ErrorContains(t, err, "file_id")
|
|
|
|
|
|
|
|
// try a good example ID
|
|
|
|
tv, err := client.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
|
|
|
Name: "my-example",
|
|
|
|
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
|
|
|
ExampleID: ls[0].ID,
|
|
|
|
Provisioner: codersdk.ProvisionerTypeEcho,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "my-example", tv.Name)
|
|
|
|
|
|
|
|
// ensure the template tar was uploaded correctly
|
|
|
|
fl, ct, err := client.Download(ctx, tv.Job.FileID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "application/x-tar", ct)
|
|
|
|
tar, err := examples.Archive(ls[0].ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.EqualValues(t, tar, fl)
|
2022-12-13 16:27:37 +00:00
|
|
|
|
|
|
|
// ensure we don't get file conflicts on multiple uses of the same example
|
|
|
|
tv, err = client.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
|
|
|
Name: "my-example",
|
|
|
|
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
|
|
|
ExampleID: ls[0].ID,
|
|
|
|
Provisioner: codersdk.ProvisionerTypeEcho,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2022-12-09 19:29:50 +00:00
|
|
|
})
|
2022-05-16 19:36:27 +00:00
|
|
|
}
|
|
|
|
|
2022-04-06 17:42:40 +00:00
|
|
|
func TestPatchCancelTemplateVersion(t *testing.T) {
|
2022-03-22 19:17:50 +00:00
|
|
|
t.Parallel()
|
2022-03-23 15:03:28 +00:00
|
|
|
t.Run("AlreadyCompleted", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-03-23 15:03:28 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := client.CancelTemplateVersion(ctx, version.ID)
|
2022-03-23 15:03:28 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2023-01-13 14:30:48 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-03-22 19:17:50 +00:00
|
|
|
})
|
2022-03-23 15:03:28 +00:00
|
|
|
t.Run("AlreadyCanceled", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-03-23 15:03:28 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
2022-03-23 15:03:28 +00:00
|
|
|
Parse: echo.ParseComplete,
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: []*proto.Provision_Response{{
|
2022-03-23 15:03:28 +00:00
|
|
|
Type: &proto.Provision_Response_Log{
|
|
|
|
Log: &proto.Log{},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
})
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-03-23 15:03:28 +00:00
|
|
|
require.Eventually(t, func() bool {
|
|
|
|
var err error
|
2022-08-09 17:17:00 +00:00
|
|
|
version, err = client.TemplateVersion(ctx, version.ID)
|
2022-07-22 17:02:49 +00:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
return false
|
|
|
|
}
|
2022-03-23 15:03:28 +00:00
|
|
|
t.Logf("Status: %s", version.Job.Status)
|
|
|
|
return version.Job.Status == codersdk.ProvisionerJobRunning
|
2022-08-01 12:45:05 +00:00
|
|
|
}, testutil.WaitShort, testutil.IntervalFast)
|
2022-08-09 17:17:00 +00:00
|
|
|
err := client.CancelTemplateVersion(ctx, version.ID)
|
2022-03-22 19:17:50 +00:00
|
|
|
require.NoError(t, err)
|
2022-08-09 17:17:00 +00:00
|
|
|
err = client.CancelTemplateVersion(ctx, version.ID)
|
2022-03-23 15:03:28 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2023-01-13 14:30:48 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-07-21 20:47:06 +00:00
|
|
|
require.Eventually(t, func() bool {
|
|
|
|
var err error
|
2022-08-09 17:17:00 +00:00
|
|
|
version, err = client.TemplateVersion(ctx, version.ID)
|
2022-07-21 20:47:06 +00:00
|
|
|
return assert.NoError(t, err) && version.Job.Status == codersdk.ProvisionerJobFailed
|
2022-08-01 12:45:05 +00:00
|
|
|
}, testutil.WaitShort, testutil.IntervalFast)
|
2022-03-23 15:03:28 +00:00
|
|
|
})
|
2022-07-21 19:29:45 +00:00
|
|
|
// TODO(Cian): until we are able to test cancellation properly, validating
|
|
|
|
// Running -> Canceling is the best we can do for now.
|
|
|
|
t.Run("Canceling", func(t *testing.T) {
|
2022-03-23 15:03:28 +00:00
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-03-23 15:03:28 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
2022-03-23 15:03:28 +00:00
|
|
|
Parse: echo.ParseComplete,
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: []*proto.Provision_Response{{
|
2022-03-23 15:03:28 +00:00
|
|
|
Type: &proto.Provision_Response_Log{
|
|
|
|
Log: &proto.Log{},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
})
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-03-23 15:03:28 +00:00
|
|
|
require.Eventually(t, func() bool {
|
|
|
|
var err error
|
2022-08-09 17:17:00 +00:00
|
|
|
version, err = client.TemplateVersion(ctx, version.ID)
|
2022-07-22 17:02:49 +00:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
return false
|
|
|
|
}
|
2022-03-23 15:03:28 +00:00
|
|
|
t.Logf("Status: %s", version.Job.Status)
|
|
|
|
return version.Job.Status == codersdk.ProvisionerJobRunning
|
2022-08-01 12:45:05 +00:00
|
|
|
}, testutil.WaitShort, testutil.IntervalFast)
|
2022-08-09 17:17:00 +00:00
|
|
|
err := client.CancelTemplateVersion(ctx, version.ID)
|
2022-03-22 19:17:50 +00:00
|
|
|
require.NoError(t, err)
|
2022-03-23 15:03:28 +00:00
|
|
|
require.Eventually(t, func() bool {
|
|
|
|
var err error
|
2022-08-09 17:17:00 +00:00
|
|
|
version, err = client.TemplateVersion(ctx, version.ID)
|
2022-07-21 19:29:45 +00:00
|
|
|
return assert.NoError(t, err) &&
|
|
|
|
// The job will never actually cancel successfully because it will never send a
|
|
|
|
// provision complete response.
|
|
|
|
assert.Empty(t, version.Job.Error) &&
|
|
|
|
version.Job.Status == codersdk.ProvisionerJobCanceling
|
2022-08-01 12:45:05 +00:00
|
|
|
}, testutil.WaitShort, testutil.IntervalFast)
|
2022-03-23 15:03:28 +00:00
|
|
|
})
|
2022-03-22 19:17:50 +00:00
|
|
|
}
|
|
|
|
|
2022-04-06 17:42:40 +00:00
|
|
|
func TestTemplateVersionSchema(t *testing.T) {
|
2022-03-07 17:40:54 +00:00
|
|
|
t.Parallel()
|
|
|
|
t.Run("ListRunning", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.TemplateVersionSchema(ctx, version.ID)
|
2022-03-07 17:40:54 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2023-01-13 14:30:48 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-03-07 17:40:54 +00:00
|
|
|
})
|
|
|
|
t.Run("List", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-03-07 17:40:54 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
2022-03-07 17:40:54 +00:00
|
|
|
Parse: []*proto.Parse_Response{{
|
|
|
|
Type: &proto.Parse_Response_Complete{
|
|
|
|
Complete: &proto.Parse_Complete{
|
|
|
|
ParameterSchemas: []*proto.ParameterSchema{{
|
|
|
|
Name: "example",
|
|
|
|
DefaultDestination: &proto.ParameterDestination{
|
|
|
|
Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE,
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}},
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: echo.ProvisionComplete,
|
2022-03-07 17:40:54 +00:00
|
|
|
})
|
2022-04-06 17:42:40 +00:00
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
schemas, err := client.TemplateVersionSchema(ctx, version.ID)
|
2022-03-07 17:40:54 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, schemas)
|
|
|
|
require.Len(t, schemas, 1)
|
|
|
|
})
|
2022-05-19 13:29:36 +00:00
|
|
|
t.Run("ListContains", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-05-19 13:29:36 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
|
|
|
Parse: []*proto.Parse_Response{{
|
|
|
|
Type: &proto.Parse_Response_Complete{
|
|
|
|
Complete: &proto.Parse_Complete{
|
|
|
|
ParameterSchemas: []*proto.ParameterSchema{{
|
|
|
|
Name: "example",
|
|
|
|
ValidationTypeSystem: proto.ParameterSchema_HCL,
|
|
|
|
ValidationValueType: "string",
|
|
|
|
ValidationCondition: `contains(["first", "second"], var.example)`,
|
|
|
|
DefaultDestination: &proto.ParameterDestination{
|
|
|
|
Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE,
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}},
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: echo.ProvisionComplete,
|
2022-05-19 13:29:36 +00:00
|
|
|
})
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
schemas, err := client.TemplateVersionSchema(ctx, version.ID)
|
2022-05-19 13:29:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, schemas)
|
|
|
|
require.Len(t, schemas, 1)
|
|
|
|
require.Equal(t, []string{"first", "second"}, schemas[0].ValidationContains)
|
|
|
|
})
|
2022-03-07 17:40:54 +00:00
|
|
|
}
|
|
|
|
|
2022-04-06 17:42:40 +00:00
|
|
|
func TestTemplateVersionParameters(t *testing.T) {
|
2022-03-07 17:40:54 +00:00
|
|
|
t.Parallel()
|
|
|
|
t.Run("ListRunning", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.TemplateVersionParameters(ctx, version.ID)
|
2022-03-07 17:40:54 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2023-01-13 14:30:48 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-03-07 17:40:54 +00:00
|
|
|
})
|
|
|
|
t.Run("List", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-03-07 17:40:54 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
2022-03-07 17:40:54 +00:00
|
|
|
Parse: []*proto.Parse_Response{{
|
|
|
|
Type: &proto.Parse_Response_Complete{
|
|
|
|
Complete: &proto.Parse_Complete{
|
2022-07-13 20:29:34 +00:00
|
|
|
ParameterSchemas: []*proto.ParameterSchema{
|
|
|
|
{
|
|
|
|
Name: "example",
|
|
|
|
RedisplayValue: true,
|
|
|
|
DefaultSource: &proto.ParameterSource{
|
|
|
|
Scheme: proto.ParameterSource_DATA,
|
|
|
|
Value: "hello",
|
|
|
|
},
|
|
|
|
DefaultDestination: &proto.ParameterDestination{
|
|
|
|
Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE,
|
|
|
|
},
|
2022-03-07 17:40:54 +00:00
|
|
|
},
|
2022-07-13 20:29:34 +00:00
|
|
|
{
|
|
|
|
Name: "abcd",
|
|
|
|
RedisplayValue: true,
|
|
|
|
DefaultSource: &proto.ParameterSource{
|
|
|
|
Scheme: proto.ParameterSource_DATA,
|
|
|
|
Value: "world",
|
|
|
|
},
|
|
|
|
DefaultDestination: &proto.ParameterDestination{
|
|
|
|
Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE,
|
|
|
|
},
|
2022-03-07 17:40:54 +00:00
|
|
|
},
|
2022-07-13 20:29:34 +00:00
|
|
|
},
|
2022-03-07 17:40:54 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}},
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: echo.ProvisionComplete,
|
2022-03-07 17:40:54 +00:00
|
|
|
})
|
2022-04-06 17:42:40 +00:00
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
params, err := client.TemplateVersionParameters(ctx, version.ID)
|
2022-03-07 17:40:54 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, params)
|
2022-07-13 20:29:34 +00:00
|
|
|
require.Len(t, params, 2)
|
2022-03-07 17:40:54 +00:00
|
|
|
require.Equal(t, "hello", params[0].SourceValue)
|
2022-07-13 20:29:34 +00:00
|
|
|
require.Equal(t, "world", params[1].SourceValue)
|
2022-03-07 17:40:54 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-02-27 16:18:19 +00:00
|
|
|
func TestTemplateVersionsGitAuth(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
t.Run("Empty", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.TemplateVersionGitAuth(ctx, version.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("Authenticated", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, &coderdtest.Options{
|
|
|
|
IncludeProvisionerDaemon: true,
|
|
|
|
GitAuthConfigs: []*gitauth.Config{{
|
2023-03-22 19:37:08 +00:00
|
|
|
OAuth2Config: &testutil.OAuth2Config{},
|
2023-02-27 16:18:19 +00:00
|
|
|
ID: "github",
|
|
|
|
Regex: regexp.MustCompile(`github\.com`),
|
|
|
|
Type: codersdk.GitProviderGitHub,
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
|
|
|
Parse: echo.ParseComplete,
|
|
|
|
ProvisionPlan: []*proto.Provision_Response{{
|
|
|
|
Type: &proto.Provision_Response_Complete{
|
|
|
|
Complete: &proto.Provision_Complete{
|
|
|
|
GitAuthProviders: []string{"github"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
require.Empty(t, version.Job.Error)
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Not authenticated to start!
|
|
|
|
providers, err := client.TemplateVersionGitAuth(ctx, version.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, providers, 1)
|
|
|
|
require.False(t, providers[0].Authenticated)
|
|
|
|
|
|
|
|
// Perform the Git auth callback to authenticate the user...
|
|
|
|
resp := coderdtest.RequestGitAuthCallback(t, "github", client)
|
|
|
|
_ = resp.Body.Close()
|
|
|
|
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
|
|
|
|
|
|
|
|
// Ensure that the returned Git auth for the template is authenticated!
|
|
|
|
providers, err = client.TemplateVersionGitAuth(ctx, version.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, providers, 1)
|
|
|
|
require.True(t, providers[0].Authenticated)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-04-06 17:42:40 +00:00
|
|
|
func TestTemplateVersionResources(t *testing.T) {
|
2022-03-07 17:40:54 +00:00
|
|
|
t.Parallel()
|
|
|
|
t.Run("ListRunning", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.TemplateVersionResources(ctx, version.ID)
|
2022-03-07 17:40:54 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2023-01-13 14:30:48 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-03-07 17:40:54 +00:00
|
|
|
})
|
|
|
|
t.Run("List", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-03-07 17:40:54 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
2022-03-07 17:40:54 +00:00
|
|
|
Parse: echo.ParseComplete,
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: []*proto.Provision_Response{{
|
2022-03-07 17:40:54 +00:00
|
|
|
Type: &proto.Provision_Response_Complete{
|
|
|
|
Complete: &proto.Provision_Complete{
|
|
|
|
Resources: []*proto.Resource{{
|
|
|
|
Name: "some",
|
|
|
|
Type: "example",
|
2022-04-11 21:06:15 +00:00
|
|
|
Agents: []*proto.Agent{{
|
2022-03-07 17:40:54 +00:00
|
|
|
Id: "something",
|
|
|
|
Auth: &proto.Agent_Token{},
|
2022-04-11 21:06:15 +00:00
|
|
|
}},
|
2022-03-07 17:40:54 +00:00
|
|
|
}, {
|
|
|
|
Name: "another",
|
|
|
|
Type: "example",
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
})
|
2022-04-06 17:42:40 +00:00
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
resources, err := client.TemplateVersionResources(ctx, version.ID)
|
2022-03-07 17:40:54 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, resources)
|
|
|
|
require.Len(t, resources, 4)
|
2022-09-08 03:16:26 +00:00
|
|
|
require.Equal(t, "some", resources[2].Name)
|
|
|
|
require.Equal(t, "example", resources[2].Type)
|
|
|
|
require.Len(t, resources[2].Agents, 1)
|
2022-03-07 17:40:54 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-04-06 17:42:40 +00:00
|
|
|
func TestTemplateVersionLogs(t *testing.T) {
|
2022-03-07 17:40:54 +00:00
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-03-07 17:40:54 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-04-06 17:42:40 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
2022-11-11 22:45:58 +00:00
|
|
|
Parse: echo.ParseComplete,
|
|
|
|
ProvisionPlan: echo.ProvisionComplete,
|
|
|
|
ProvisionApply: []*proto.Provision_Response{{
|
2022-03-07 17:40:54 +00:00
|
|
|
Type: &proto.Provision_Response_Log{
|
|
|
|
Log: &proto.Log{
|
|
|
|
Level: proto.LogLevel_INFO,
|
|
|
|
Output: "example",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, {
|
|
|
|
Type: &proto.Provision_Response_Complete{
|
|
|
|
Complete: &proto.Provision_Complete{
|
|
|
|
Resources: []*proto.Resource{{
|
|
|
|
Name: "some",
|
|
|
|
Type: "example",
|
2022-04-11 21:06:15 +00:00
|
|
|
Agents: []*proto.Agent{{
|
2022-03-07 17:40:54 +00:00
|
|
|
Id: "something",
|
|
|
|
Auth: &proto.Agent_Token{
|
|
|
|
Token: uuid.NewString(),
|
|
|
|
},
|
2022-04-11 21:06:15 +00:00
|
|
|
}},
|
2022-03-07 17:40:54 +00:00
|
|
|
}, {
|
|
|
|
Name: "another",
|
|
|
|
Type: "example",
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
})
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-11-07 02:50:34 +00:00
|
|
|
logs, closer, err := client.TemplateVersionLogsAfter(ctx, version.ID, 0)
|
2022-03-07 17:40:54 +00:00
|
|
|
require.NoError(t, err)
|
2022-09-22 18:26:05 +00:00
|
|
|
defer closer.Close()
|
2022-03-28 18:43:22 +00:00
|
|
|
for {
|
|
|
|
_, ok := <-logs
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2022-03-07 17:40:54 +00:00
|
|
|
}
|
2022-05-16 19:36:27 +00:00
|
|
|
|
|
|
|
func TestTemplateVersionsByTemplate(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
t.Run("Get", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
versions, err := client.TemplateVersionsByTemplate(ctx, codersdk.TemplateVersionsByTemplateRequest{
|
2022-05-16 19:36:27 +00:00
|
|
|
TemplateID: template.ID,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, versions, 1)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTemplateVersionByName(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
t.Run("NotFound", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.TemplateVersionByName(ctx, template.ID, "nothing")
|
2022-05-16 19:36:27 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
|
|
|
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Found", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.TemplateVersionByName(ctx, template.ID, version.Name)
|
2022-05-16 19:36:27 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPatchActiveTemplateVersion(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
t.Run("NotFound", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := client.UpdateActiveTemplateVersion(ctx, template.ID, codersdk.UpdateActiveTemplateVersion{
|
2022-05-16 19:36:27 +00:00
|
|
|
ID: uuid.New(),
|
|
|
|
})
|
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
|
|
|
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("DoesNotBelong", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
|
|
|
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := client.UpdateActiveTemplateVersion(ctx, template.ID, codersdk.UpdateActiveTemplateVersion{
|
2022-05-16 19:36:27 +00:00
|
|
|
ID: version.ID,
|
|
|
|
})
|
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2022-09-09 16:34:23 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-05-16 19:36:27 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Found", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-09 16:34:23 +00:00
|
|
|
auditor := audit.NewMock()
|
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, Auditor: auditor})
|
2022-05-16 19:36:27 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := client.UpdateActiveTemplateVersion(ctx, template.ID, codersdk.UpdateActiveTemplateVersion{
|
2022-05-16 19:36:27 +00:00
|
|
|
ID: version.ID,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2022-09-09 16:34:23 +00:00
|
|
|
|
2023-02-06 20:12:50 +00:00
|
|
|
require.Len(t, auditor.AuditLogs, 5)
|
|
|
|
assert.Equal(t, database.AuditActionWrite, auditor.AuditLogs[4].Action)
|
2022-05-16 19:36:27 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-06-01 14:44:53 +00:00
|
|
|
func TestTemplateVersionDryRun(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
t.Run("OK", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
resource := &proto.Resource{
|
|
|
|
Name: "cool-resource",
|
|
|
|
Type: "cool_resource_type",
|
|
|
|
}
|
|
|
|
|
2023-01-05 18:05:20 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-06-01 14:44:53 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
|
|
|
Parse: echo.ParseComplete,
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: []*proto.Provision_Response{
|
2022-06-01 14:44:53 +00:00
|
|
|
{
|
|
|
|
Type: &proto.Provision_Response_Log{
|
|
|
|
Log: &proto.Log{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: &proto.Provision_Response_Complete{
|
|
|
|
Complete: &proto.Provision_Complete{
|
|
|
|
Resources: []*proto.Resource{resource},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
|
2022-08-09 17:17:00 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-06-01 14:44:53 +00:00
|
|
|
// Create template version dry-run
|
|
|
|
job, err := client.CreateTemplateVersionDryRun(ctx, version.ID, codersdk.CreateTemplateVersionDryRunRequest{
|
|
|
|
ParameterValues: []codersdk.CreateParameterRequest{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Fetch template version dry-run
|
|
|
|
newJob, err := client.TemplateVersionDryRun(ctx, version.ID, job.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, job.ID, newJob.ID)
|
|
|
|
|
|
|
|
// Stream logs
|
2022-11-07 02:50:34 +00:00
|
|
|
logs, closer, err := client.TemplateVersionDryRunLogsAfter(ctx, version.ID, job.ID, 0)
|
2022-06-01 14:44:53 +00:00
|
|
|
require.NoError(t, err)
|
2022-09-22 18:26:05 +00:00
|
|
|
defer closer.Close()
|
2022-06-01 14:44:53 +00:00
|
|
|
|
|
|
|
logsDone := make(chan struct{})
|
|
|
|
go func() {
|
|
|
|
defer close(logsDone)
|
|
|
|
|
|
|
|
logCount := 0
|
|
|
|
for range logs {
|
|
|
|
logCount++
|
|
|
|
}
|
|
|
|
assert.GreaterOrEqual(t, logCount, 1, "unexpected log count")
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Wait for the job to complete
|
|
|
|
require.Eventually(t, func() bool {
|
|
|
|
job, err := client.TemplateVersionDryRun(ctx, version.ID, job.ID)
|
2022-07-22 17:02:49 +00:00
|
|
|
return assert.NoError(t, err) && job.Status == codersdk.ProvisionerJobSucceeded
|
2022-08-01 12:45:05 +00:00
|
|
|
}, testutil.WaitShort, testutil.IntervalFast)
|
2022-06-01 14:44:53 +00:00
|
|
|
|
|
|
|
<-logsDone
|
|
|
|
|
|
|
|
resources, err := client.TemplateVersionDryRunResources(ctx, version.ID, job.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, resources, 1)
|
|
|
|
require.Equal(t, resource.Name, resources[0].Name)
|
|
|
|
require.Equal(t, resource.Type, resources[0].Type)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("ImportNotFinished", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-06-01 14:44:53 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
// This import job will never finish
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
|
|
|
Parse: echo.ParseComplete,
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: []*proto.Provision_Response{{
|
2022-06-01 14:44:53 +00:00
|
|
|
Type: &proto.Provision_Response_Log{
|
|
|
|
Log: &proto.Log{},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
|
2022-08-09 17:17:00 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.CreateTemplateVersionDryRun(ctx, version.ID, codersdk.CreateTemplateVersionDryRunRequest{
|
2022-06-01 14:44:53 +00:00
|
|
|
ParameterValues: []codersdk.CreateParameterRequest{},
|
|
|
|
})
|
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2023-01-13 14:30:48 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-06-01 14:44:53 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Cancel", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
t.Run("OK", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-06-27 18:50:52 +00:00
|
|
|
client, closer := coderdtest.NewWithProvisionerCloser(t, nil)
|
|
|
|
defer closer.Close()
|
|
|
|
|
2022-06-01 14:44:53 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-06-27 18:50:52 +00:00
|
|
|
|
2022-06-01 14:44:53 +00:00
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
|
|
|
Parse: echo.ParseComplete,
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: []*proto.Provision_Response{
|
2022-06-27 18:50:52 +00:00
|
|
|
{
|
|
|
|
Type: &proto.Provision_Response_Log{
|
|
|
|
Log: &proto.Log{},
|
2022-07-22 17:02:49 +00:00
|
|
|
},
|
|
|
|
},
|
2022-06-27 18:50:52 +00:00
|
|
|
{
|
|
|
|
Type: &proto.Provision_Response_Complete{
|
|
|
|
Complete: &proto.Provision_Complete{},
|
|
|
|
},
|
2022-06-01 14:44:53 +00:00
|
|
|
},
|
2022-06-27 18:50:52 +00:00
|
|
|
},
|
2022-06-01 14:44:53 +00:00
|
|
|
})
|
|
|
|
|
2022-06-27 18:50:52 +00:00
|
|
|
version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
require.Equal(t, codersdk.ProvisionerJobSucceeded, version.Job.Status)
|
|
|
|
|
|
|
|
closer.Close()
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-06-01 14:44:53 +00:00
|
|
|
// Create the dry-run
|
2022-08-09 17:17:00 +00:00
|
|
|
job, err := client.CreateTemplateVersionDryRun(ctx, version.ID, codersdk.CreateTemplateVersionDryRunRequest{
|
2022-06-01 14:44:53 +00:00
|
|
|
ParameterValues: []codersdk.CreateParameterRequest{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2022-10-03 16:43:11 +00:00
|
|
|
require.Equal(t, codersdk.ProvisionerJobPending, job.Status)
|
2022-08-09 17:17:00 +00:00
|
|
|
err = client.CancelTemplateVersionDryRun(ctx, version.ID, job.ID)
|
2022-06-01 14:44:53 +00:00
|
|
|
require.NoError(t, err)
|
2022-10-03 16:43:11 +00:00
|
|
|
job, err = client.TemplateVersionDryRun(ctx, version.ID, job.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, codersdk.ProvisionerJobCanceled, job.Status)
|
2022-06-01 14:44:53 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("AlreadyCompleted", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-06-01 14:44:53 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
|
2022-08-09 17:17:00 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-06-01 14:44:53 +00:00
|
|
|
// Create the dry-run
|
2022-08-09 17:17:00 +00:00
|
|
|
job, err := client.CreateTemplateVersionDryRun(ctx, version.ID, codersdk.CreateTemplateVersionDryRunRequest{
|
2022-06-01 14:44:53 +00:00
|
|
|
ParameterValues: []codersdk.CreateParameterRequest{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Eventually(t, func() bool {
|
2022-08-09 17:17:00 +00:00
|
|
|
job, err := client.TemplateVersionDryRun(ctx, version.ID, job.ID)
|
2022-07-22 17:02:49 +00:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
return false
|
|
|
|
}
|
2022-06-01 14:44:53 +00:00
|
|
|
|
|
|
|
t.Logf("Status: %s", job.Status)
|
|
|
|
return job.Status == codersdk.ProvisionerJobSucceeded
|
2022-08-01 12:45:05 +00:00
|
|
|
}, testutil.WaitShort, testutil.IntervalFast)
|
2022-06-01 14:44:53 +00:00
|
|
|
|
2022-08-09 17:17:00 +00:00
|
|
|
err = client.CancelTemplateVersionDryRun(ctx, version.ID, job.ID)
|
2022-06-01 14:44:53 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2023-01-13 14:30:48 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-06-01 14:44:53 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("AlreadyCanceled", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-06-27 18:50:52 +00:00
|
|
|
client, closer := coderdtest.NewWithProvisionerCloser(t, nil)
|
|
|
|
defer closer.Close()
|
|
|
|
|
2022-06-01 14:44:53 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
|
|
|
Parse: echo.ParseComplete,
|
2022-11-11 22:45:58 +00:00
|
|
|
ProvisionApply: []*proto.Provision_Response{
|
2022-06-27 18:50:52 +00:00
|
|
|
{
|
|
|
|
Type: &proto.Provision_Response_Log{
|
|
|
|
Log: &proto.Log{},
|
2022-07-22 17:02:49 +00:00
|
|
|
},
|
|
|
|
},
|
2022-06-27 18:50:52 +00:00
|
|
|
{
|
|
|
|
Type: &proto.Provision_Response_Complete{
|
|
|
|
Complete: &proto.Provision_Complete{},
|
|
|
|
},
|
2022-06-01 14:44:53 +00:00
|
|
|
},
|
2022-06-27 18:50:52 +00:00
|
|
|
},
|
2022-06-01 14:44:53 +00:00
|
|
|
})
|
2022-06-27 18:50:52 +00:00
|
|
|
|
|
|
|
version = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
require.Equal(t, codersdk.ProvisionerJobSucceeded, version.Job.Status)
|
|
|
|
|
|
|
|
closer.Close()
|
2022-06-01 14:44:53 +00:00
|
|
|
|
2022-08-09 17:17:00 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2022-06-01 14:44:53 +00:00
|
|
|
// Create the dry-run
|
2022-08-09 17:17:00 +00:00
|
|
|
job, err := client.CreateTemplateVersionDryRun(ctx, version.ID, codersdk.CreateTemplateVersionDryRunRequest{
|
2022-06-01 14:44:53 +00:00
|
|
|
ParameterValues: []codersdk.CreateParameterRequest{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-08-09 17:17:00 +00:00
|
|
|
err = client.CancelTemplateVersionDryRun(ctx, version.ID, job.ID)
|
2022-06-01 14:44:53 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-08-09 17:17:00 +00:00
|
|
|
err = client.CancelTemplateVersionDryRun(ctx, version.ID, job.ID)
|
2022-06-01 14:44:53 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
2023-01-13 14:30:48 +00:00
|
|
|
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
2022-06-01 14:44:53 +00:00
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-05-16 19:36:27 +00:00
|
|
|
// TestPaginatedTemplateVersions creates a list of template versions and paginate.
|
|
|
|
func TestPaginatedTemplateVersions(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2023-01-05 18:05:20 +00:00
|
|
|
client := coderdtest.New(t, nil)
|
2022-05-16 19:36:27 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
|
|
|
|
2022-09-04 16:28:09 +00:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
2022-08-21 22:32:53 +00:00
|
|
|
t.Cleanup(cancel)
|
2022-05-16 19:36:27 +00:00
|
|
|
// Populate database with template versions.
|
|
|
|
total := 9
|
2022-08-09 17:17:00 +00:00
|
|
|
eg, egCtx := errgroup.WithContext(ctx)
|
|
|
|
templateVersionIDs := make([]uuid.UUID, total)
|
2022-09-04 16:28:09 +00:00
|
|
|
data, err := echo.Tar(nil)
|
|
|
|
require.NoError(t, err)
|
2023-02-04 20:07:09 +00:00
|
|
|
file, err := client.Upload(egCtx, codersdk.ContentTypeTar, bytes.NewReader(data))
|
2022-09-04 16:28:09 +00:00
|
|
|
require.NoError(t, err)
|
2022-05-16 19:36:27 +00:00
|
|
|
for i := 0; i < total; i++ {
|
2022-08-09 17:17:00 +00:00
|
|
|
i := i
|
|
|
|
eg.Go(func() error {
|
|
|
|
templateVersion, err := client.CreateTemplateVersion(egCtx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
|
|
|
TemplateID: template.ID,
|
2022-10-13 23:02:52 +00:00
|
|
|
FileID: file.ID,
|
2022-08-09 17:17:00 +00:00
|
|
|
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
|
|
|
Provisioner: codersdk.ProvisionerTypeEcho,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
templateVersionIDs[i] = templateVersion.ID
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
2022-09-04 16:28:09 +00:00
|
|
|
err = eg.Wait()
|
2022-08-09 17:17:00 +00:00
|
|
|
require.NoError(t, err, "create templates failed")
|
|
|
|
|
2022-05-16 19:36:27 +00:00
|
|
|
templateVersions, err := client.TemplateVersionsByTemplate(ctx,
|
|
|
|
codersdk.TemplateVersionsByTemplateRequest{
|
|
|
|
TemplateID: template.ID,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, templateVersions, 10, "wrong number of template versions created")
|
|
|
|
|
|
|
|
type args struct {
|
|
|
|
pagination codersdk.Pagination
|
|
|
|
}
|
|
|
|
tests := []struct {
|
2022-06-02 14:01:45 +00:00
|
|
|
name string
|
|
|
|
args args
|
|
|
|
want []codersdk.TemplateVersion
|
|
|
|
expectedError string
|
2022-05-16 19:36:27 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Single result",
|
2022-08-09 17:17:00 +00:00
|
|
|
args: args{pagination: codersdk.Pagination{Limit: 1}},
|
2022-05-16 19:36:27 +00:00
|
|
|
want: templateVersions[:1],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Single result, second page",
|
2022-08-09 17:17:00 +00:00
|
|
|
args: args{pagination: codersdk.Pagination{Limit: 1, Offset: 1}},
|
2022-05-16 19:36:27 +00:00
|
|
|
want: templateVersions[1:2],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Last two results",
|
2022-08-09 17:17:00 +00:00
|
|
|
args: args{pagination: codersdk.Pagination{Limit: 2, Offset: 8}},
|
2022-05-16 19:36:27 +00:00
|
|
|
want: templateVersions[8:10],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "AfterID returns next two results",
|
2022-08-09 17:17:00 +00:00
|
|
|
args: args{pagination: codersdk.Pagination{Limit: 2, AfterID: templateVersions[1].ID}},
|
2022-05-16 19:36:27 +00:00
|
|
|
want: templateVersions[2:4],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "No result after last AfterID",
|
2022-08-09 17:17:00 +00:00
|
|
|
args: args{pagination: codersdk.Pagination{Limit: 2, AfterID: templateVersions[9].ID}},
|
2022-05-16 19:36:27 +00:00
|
|
|
want: []codersdk.TemplateVersion{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "No result after last Offset",
|
2022-08-09 17:17:00 +00:00
|
|
|
args: args{pagination: codersdk.Pagination{Limit: 2, Offset: 10}},
|
2022-05-16 19:36:27 +00:00
|
|
|
want: []codersdk.TemplateVersion{},
|
|
|
|
},
|
2022-06-02 14:01:45 +00:00
|
|
|
{
|
|
|
|
name: "After_id does not exist",
|
2022-08-09 17:17:00 +00:00
|
|
|
args: args{pagination: codersdk.Pagination{AfterID: uuid.New()}},
|
2022-06-02 14:01:45 +00:00
|
|
|
expectedError: "does not exist",
|
|
|
|
},
|
2022-05-16 19:36:27 +00:00
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
tt := tt
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-08-09 17:17:00 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
got, err := client.TemplateVersionsByTemplate(ctx, codersdk.TemplateVersionsByTemplateRequest{
|
2022-05-16 19:36:27 +00:00
|
|
|
TemplateID: template.ID,
|
|
|
|
Pagination: tt.args.pagination,
|
|
|
|
})
|
2022-06-02 14:01:45 +00:00
|
|
|
if tt.expectedError != "" {
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, tt.expectedError)
|
|
|
|
} else {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, tt.want, got)
|
|
|
|
}
|
2022-05-16 19:36:27 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-11-15 16:24:13 +00:00
|
|
|
|
2023-02-02 21:47:53 +00:00
|
|
|
func TestTemplateVersionByOrganizationTemplateAndName(t *testing.T) {
|
2022-11-15 16:24:13 +00:00
|
|
|
t.Parallel()
|
|
|
|
t.Run("NotFound", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
2023-02-02 21:47:53 +00:00
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
2022-11-15 16:24:13 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-02-02 21:47:53 +00:00
|
|
|
_, err := client.TemplateVersionByOrganizationAndName(ctx, user.OrganizationID, template.Name, "nothing")
|
2022-11-15 16:24:13 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
|
|
|
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Found", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
2023-02-02 21:47:53 +00:00
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
2022-11-15 16:24:13 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-02-02 21:47:53 +00:00
|
|
|
_, err := client.TemplateVersionByOrganizationAndName(ctx, user.OrganizationID, template.Name, version.Name)
|
2022-11-15 16:24:13 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
}
|
2022-12-06 14:15:03 +00:00
|
|
|
|
|
|
|
func TestPreviousTemplateVersion(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
t.Run("Previous version not found", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-12-07 13:19:18 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-12-06 14:15:03 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-12-08 15:24:15 +00:00
|
|
|
|
|
|
|
// Create two templates to be sure it is not returning a previous version
|
|
|
|
// from another template
|
|
|
|
templateAVersion1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
coderdtest.CreateTemplate(t, client, user.OrganizationID, templateAVersion1.ID)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, templateAVersion1.ID)
|
|
|
|
// Create two versions for the template B to be sure if we try to get the
|
|
|
|
// previous version of the first version it will returns a 404
|
|
|
|
templateBVersion1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
templateB := coderdtest.CreateTemplate(t, client, user.OrganizationID, templateBVersion1.ID)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, templateBVersion1.ID)
|
|
|
|
templateBVersion2 := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, nil, templateB.ID)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, templateBVersion2.ID)
|
2022-12-06 14:15:03 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-02-02 21:47:53 +00:00
|
|
|
_, err := client.PreviousTemplateVersion(ctx, user.OrganizationID, templateB.Name, templateBVersion1.Name)
|
2022-12-06 14:15:03 +00:00
|
|
|
var apiErr *codersdk.Error
|
|
|
|
require.ErrorAs(t, err, &apiErr)
|
|
|
|
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Previous version found", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2022-12-07 13:19:18 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
2022-12-06 14:15:03 +00:00
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
2022-12-08 15:24:15 +00:00
|
|
|
|
|
|
|
// Create two templates to be sure it is not returning a previous version
|
|
|
|
// from another template
|
|
|
|
templateAVersion1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
coderdtest.CreateTemplate(t, client, user.OrganizationID, templateAVersion1.ID)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, templateAVersion1.ID)
|
|
|
|
// Create two versions for the template B so we can try to get the previous
|
|
|
|
// version of version 2
|
|
|
|
templateBVersion1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
templateB := coderdtest.CreateTemplate(t, client, user.OrganizationID, templateBVersion1.ID)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, templateBVersion1.ID)
|
|
|
|
templateBVersion2 := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, nil, templateB.ID)
|
|
|
|
coderdtest.AwaitTemplateVersionJob(t, client, templateBVersion2.ID)
|
2022-12-06 14:15:03 +00:00
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-02-02 21:47:53 +00:00
|
|
|
result, err := client.PreviousTemplateVersion(ctx, user.OrganizationID, templateB.Name, templateBVersion2.Name)
|
2022-12-06 14:15:03 +00:00
|
|
|
require.NoError(t, err)
|
2022-12-08 15:24:15 +00:00
|
|
|
require.Equal(t, templateBVersion1.ID, result.ID)
|
2022-12-06 14:15:03 +00:00
|
|
|
})
|
|
|
|
}
|
2022-12-09 19:29:50 +00:00
|
|
|
|
|
|
|
func TestTemplateExamples(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
t.Run("OK", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
ex, err := client.TemplateExamples(ctx, user.OrganizationID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
ls, err := examples.List()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.EqualValues(t, ls, ex)
|
|
|
|
})
|
|
|
|
}
|
2023-02-15 17:24:15 +00:00
|
|
|
|
|
|
|
func TestTemplateVersionVariables(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
createEchoResponses := func(templateVariables []*proto.TemplateVariable) *echo.Responses {
|
|
|
|
return &echo.Responses{
|
|
|
|
Parse: []*proto.Parse_Response{
|
|
|
|
{
|
|
|
|
Type: &proto.Parse_Response_Complete{
|
|
|
|
Complete: &proto.Parse_Complete{
|
|
|
|
TemplateVariables: templateVariables,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ProvisionPlan: echo.ProvisionComplete,
|
|
|
|
ProvisionApply: []*proto.Provision_Response{{
|
|
|
|
Type: &proto.Provision_Response_Complete{
|
|
|
|
Complete: &proto.Provision_Complete{},
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("Pass value for required variable", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
templateVariables := []*proto.TemplateVariable{
|
|
|
|
{
|
|
|
|
Name: "first_variable",
|
|
|
|
Description: "This is the first variable",
|
|
|
|
Type: "string",
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const firstVariableValue = "foobar"
|
|
|
|
|
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID,
|
|
|
|
createEchoResponses(templateVariables),
|
|
|
|
func(ctvr *codersdk.CreateTemplateVersionRequest) {
|
|
|
|
ctvr.UserVariableValues = []codersdk.VariableValue{
|
|
|
|
{
|
|
|
|
Name: templateVariables[0].Name,
|
|
|
|
Value: firstVariableValue,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
templateVersion := coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
|
|
|
|
// As user passed the value for the first parameter, the job will succeed.
|
|
|
|
require.Empty(t, templateVersion.Job.Error)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
actualVariables, err := client.TemplateVersionVariables(ctx, templateVersion.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Len(t, actualVariables, 1)
|
|
|
|
require.Equal(t, templateVariables[0].Name, actualVariables[0].Name)
|
|
|
|
require.Equal(t, templateVariables[0].Description, actualVariables[0].Description)
|
|
|
|
require.Equal(t, templateVariables[0].Type, actualVariables[0].Type)
|
|
|
|
require.Equal(t, templateVariables[0].DefaultValue, actualVariables[0].DefaultValue)
|
|
|
|
require.Equal(t, templateVariables[0].Required, actualVariables[0].Required)
|
|
|
|
require.Equal(t, templateVariables[0].Sensitive, actualVariables[0].Sensitive)
|
|
|
|
require.Equal(t, firstVariableValue, actualVariables[0].Value)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Missing value for required variable", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
templateVariables := []*proto.TemplateVariable{
|
|
|
|
{
|
|
|
|
Name: "first_variable",
|
|
|
|
Description: "This is the first variable",
|
|
|
|
Type: "string",
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "second_variable",
|
|
|
|
Description: "This is the second variable",
|
|
|
|
DefaultValue: "123",
|
|
|
|
Type: "number",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, createEchoResponses(templateVariables))
|
|
|
|
templateVersion := coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
|
|
|
|
// As the first variable is marked as required and misses the default value,
|
|
|
|
// the job will fail, but will populate the template_version_variables table with existing variables.
|
|
|
|
require.Contains(t, templateVersion.Job.Error, "required template variables need values")
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
actualVariables, err := client.TemplateVersionVariables(ctx, templateVersion.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Len(t, actualVariables, 2)
|
|
|
|
for i := range templateVariables {
|
|
|
|
require.Equal(t, templateVariables[i].Name, actualVariables[i].Name)
|
|
|
|
require.Equal(t, templateVariables[i].Description, actualVariables[i].Description)
|
|
|
|
require.Equal(t, templateVariables[i].Type, actualVariables[i].Type)
|
|
|
|
require.Equal(t, templateVariables[i].DefaultValue, actualVariables[i].DefaultValue)
|
|
|
|
require.Equal(t, templateVariables[i].Required, actualVariables[i].Required)
|
|
|
|
require.Equal(t, templateVariables[i].Sensitive, actualVariables[i].Sensitive)
|
|
|
|
}
|
|
|
|
|
|
|
|
require.Equal(t, "", actualVariables[0].Value)
|
|
|
|
require.Equal(t, templateVariables[1].DefaultValue, actualVariables[1].Value)
|
|
|
|
})
|
2023-02-17 08:07:45 +00:00
|
|
|
|
|
|
|
t.Run("Redact sensitive variables", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
templateVariables := []*proto.TemplateVariable{
|
|
|
|
{
|
|
|
|
Name: "first_variable",
|
|
|
|
Description: "This is the first variable",
|
|
|
|
Type: "string",
|
|
|
|
Required: true,
|
|
|
|
Sensitive: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
const firstVariableValue = "foobar"
|
|
|
|
|
|
|
|
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID,
|
|
|
|
createEchoResponses(templateVariables),
|
|
|
|
func(ctvr *codersdk.CreateTemplateVersionRequest) {
|
|
|
|
ctvr.UserVariableValues = []codersdk.VariableValue{
|
|
|
|
{
|
|
|
|
Name: templateVariables[0].Name,
|
|
|
|
Value: firstVariableValue,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
templateVersion := coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
|
|
|
|
|
|
|
// As user passed the value for the first parameter, the job will succeed.
|
|
|
|
require.Empty(t, templateVersion.Job.Error)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
actualVariables, err := client.TemplateVersionVariables(ctx, templateVersion.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Len(t, actualVariables, 1)
|
|
|
|
require.Equal(t, templateVariables[0].Name, actualVariables[0].Name)
|
|
|
|
require.Equal(t, templateVariables[0].Description, actualVariables[0].Description)
|
|
|
|
require.Equal(t, templateVariables[0].Type, actualVariables[0].Type)
|
|
|
|
require.Equal(t, templateVariables[0].Required, actualVariables[0].Required)
|
|
|
|
require.Equal(t, templateVariables[0].Sensitive, actualVariables[0].Sensitive)
|
|
|
|
require.Equal(t, "*redacted*", actualVariables[0].DefaultValue)
|
|
|
|
require.Equal(t, "*redacted*", actualVariables[0].Value)
|
|
|
|
})
|
2023-02-15 17:24:15 +00:00
|
|
|
}
|