2022-03-07 17:40:54 +00:00
|
|
|
package coderd_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net/http"
|
|
|
|
"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"
|
2022-11-16 22:34:06 +00:00
|
|
|
"github.com/coder/coder/coderd/provisionerdserver"
|
2022-03-07 17:40:54 +00:00
|
|
|
"github.com/coder/coder/codersdk"
|
|
|
|
"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()
|
|
|
|
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.TemplateVersion(ctx, version.ID)
|
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)
|
|
|
|
|
|
|
|
client1, _ := coderdtest.CreateAnotherUserWithUser(t, client, user.OrganizationID)
|
|
|
|
|
|
|
|
_, 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()
|
|
|
|
|
|
|
|
file, err := client.Upload(ctx, codersdk.ContentTypeTar, 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
|
|
|
|
|
|
|
require.Len(t, auditor.AuditLogs, 1)
|
|
|
|
assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs[0].Action)
|
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)
|
|
|
|
require.Equal(t, http.StatusPreconditionFailed, 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)
|
|
|
|
require.Equal(t, http.StatusPreconditionFailed, 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)
|
|
|
|
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
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)
|
|
|
|
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
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
|
|
|
})
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
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
|
|
|
|
|
|
|
require.Len(t, auditor.AuditLogs, 4)
|
|
|
|
assert.Equal(t, database.AuditActionWrite, auditor.AuditLogs[3].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",
|
|
|
|
}
|
|
|
|
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{APIRateLimit: -1, 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)
|
|
|
|
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
|
|
|
|
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)
|
|
|
|
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
|
|
|
|
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)
|
|
|
|
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-05-16 19:36:27 +00:00
|
|
|
// TestPaginatedTemplateVersions creates a list of template versions and paginate.
|
|
|
|
func TestPaginatedTemplateVersions(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2022-09-04 16:28:09 +00:00
|
|
|
client := coderdtest.New(t, &coderdtest.Options{APIRateLimit: -1})
|
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)
|
|
|
|
file, err := client.Upload(egCtx, codersdk.ContentTypeTar, data)
|
|
|
|
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
|
|
|
|
|
|
|
func TestTemplateVersionByOrganizationAndName(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)
|
|
|
|
coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.TemplateVersionByOrganizationAndName(ctx, user.OrganizationID, "nothing")
|
|
|
|
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)
|
|
|
|
coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.TemplateVersionByOrganizationAndName(ctx, user.OrganizationID, version.Name)
|
|
|
|
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()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
_, err := client.PreviousTemplateVersion(ctx, user.OrganizationID, version.Name)
|
|
|
|
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()
|
|
|
|
client := coderdtest.New(t, nil)
|
|
|
|
user := coderdtest.CreateFirstUser(t, client)
|
|
|
|
previousVersion := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
|
|
|
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, previousVersion.ID)
|
|
|
|
latestVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, nil, template.ID)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
result, err := client.PreviousTemplateVersion(ctx, user.OrganizationID, latestVersion.Name)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, previousVersion.ID, result.ID)
|
|
|
|
})
|
|
|
|
}
|