mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
test: add unit test helper to create templates in second organizations (#13628)
* chore: add coderdtest helpers
This commit is contained in:
@@ -600,6 +600,18 @@ func NewTaggedProvisionerDaemon(t testing.TB, coderAPI *coderd.API, name string,
|
||||
}
|
||||
|
||||
func NewExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uuid.UUID, tags map[string]string) io.Closer {
|
||||
t.Helper()
|
||||
|
||||
// Without this check, the provisioner will silently fail.
|
||||
entitlements, err := client.Entitlements(context.Background())
|
||||
if err == nil {
|
||||
feature := entitlements.Features[codersdk.FeatureExternalProvisionerDaemons]
|
||||
if !feature.Enabled || feature.Entitlement != codersdk.EntitlementEntitled {
|
||||
require.NoError(t, xerrors.Errorf("external provisioner daemons require an entitled license"))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
echoClient, echoServer := drpc.MemTransportPipe()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
serveDone := make(chan struct{})
|
||||
@@ -638,6 +650,7 @@ func NewExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uui
|
||||
t.Cleanup(func() {
|
||||
_ = closer.Close()
|
||||
})
|
||||
|
||||
return closer
|
||||
}
|
||||
|
||||
@@ -790,6 +803,37 @@ func createAnotherUserRetry(t testing.TB, client *codersdk.Client, organizationI
|
||||
return other, user
|
||||
}
|
||||
|
||||
type CreateOrganizationOptions struct {
|
||||
// IncludeProvisionerDaemon will spin up an external provisioner for the organization.
|
||||
// This requires enterprise and the feature 'codersdk.FeatureExternalProvisionerDaemons'
|
||||
IncludeProvisionerDaemon bool
|
||||
}
|
||||
|
||||
func CreateOrganization(t *testing.T, client *codersdk.Client, opts CreateOrganizationOptions, mutators ...func(*codersdk.CreateOrganizationRequest)) codersdk.Organization {
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
req := codersdk.CreateOrganizationRequest{
|
||||
Name: strings.ReplaceAll(strings.ToLower(namesgenerator.GetRandomName(0)), "_", "-"),
|
||||
DisplayName: namesgenerator.GetRandomName(1),
|
||||
Description: namesgenerator.GetRandomName(1),
|
||||
Icon: "",
|
||||
}
|
||||
for _, mutator := range mutators {
|
||||
mutator(&req)
|
||||
}
|
||||
|
||||
org, err := client.CreateOrganization(ctx, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
if opts.IncludeProvisionerDaemon {
|
||||
closer := NewExternalProvisionerDaemon(t, client, org.ID, map[string]string{})
|
||||
t.Cleanup(func() {
|
||||
_ = closer.Close()
|
||||
})
|
||||
}
|
||||
|
||||
return org
|
||||
}
|
||||
|
||||
// CreateTemplateVersion creates a template import provisioner job
|
||||
// with the responses provided. It uses the "echo" provisioner for compatibility
|
||||
// with testing.
|
||||
|
||||
@@ -134,4 +134,71 @@ func TestTemplateCreate(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "your license is not entitled to use enterprise access control, so you cannot set --require-active-version")
|
||||
})
|
||||
|
||||
// Create a template in a second organization via custom role
|
||||
t.Run("SecondOrganization", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dv := coderdtest.DeploymentValues(t)
|
||||
dv.Experiments = []string{string(codersdk.ExperimentCustomRoles)}
|
||||
ownerClient, _ := coderdenttest.New(t, &coderdenttest.Options{
|
||||
Options: &coderdtest.Options{
|
||||
DeploymentValues: dv,
|
||||
// This only affects the first org.
|
||||
IncludeProvisionerDaemon: false,
|
||||
},
|
||||
LicenseOptions: &coderdenttest.LicenseOptions{
|
||||
Features: license.Features{
|
||||
codersdk.FeatureAccessControl: 1,
|
||||
codersdk.FeatureCustomRoles: 1,
|
||||
codersdk.FeatureExternalProvisionerDaemons: 1,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// Create the second organization
|
||||
secondOrg := coderdtest.CreateOrganization(t, ownerClient, coderdtest.CreateOrganizationOptions{
|
||||
IncludeProvisionerDaemon: true,
|
||||
})
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
//nolint:gocritic // owner required to make custom roles
|
||||
orgTemplateAdminRole, err := ownerClient.PatchOrganizationRole(ctx, secondOrg.ID, codersdk.Role{
|
||||
Name: "org-template-admin",
|
||||
OrganizationID: secondOrg.ID.String(),
|
||||
OrganizationPermissions: codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
|
||||
codersdk.ResourceTemplate: codersdk.RBACResourceActions[codersdk.ResourceTemplate],
|
||||
}),
|
||||
})
|
||||
require.NoError(t, err, "create admin role")
|
||||
|
||||
orgTemplateAdmin, _ := coderdtest.CreateAnotherUser(t, ownerClient, secondOrg.ID, rbac.RoleIdentifier{
|
||||
Name: orgTemplateAdminRole.Name,
|
||||
OrganizationID: secondOrg.ID,
|
||||
})
|
||||
|
||||
source := clitest.CreateTemplateVersionSource(t, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionApply: echo.ApplyComplete,
|
||||
})
|
||||
|
||||
const templateName = "new-template"
|
||||
inv, conf := newCLI(t, "templates",
|
||||
"push", templateName,
|
||||
"--directory", source,
|
||||
"--test.provisioner", string(database.ProvisionerTypeEcho),
|
||||
"-y",
|
||||
)
|
||||
|
||||
clitest.SetupConfig(t, orgTemplateAdmin, conf)
|
||||
|
||||
err = inv.Run()
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx = testutil.Context(t, testutil.WaitMedium)
|
||||
template, err := orgTemplateAdmin.TemplateByName(ctx, secondOrg.ID, templateName)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, template.OrganizationID, secondOrg.ID)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -717,6 +717,57 @@ func TestTemplates(t *testing.T) {
|
||||
_, err = owner.Template(ctx, template.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
// Create a template in a second organization via custom role
|
||||
t.Run("SecondOrganization", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dv := coderdtest.DeploymentValues(t)
|
||||
dv.Experiments = []string{string(codersdk.ExperimentCustomRoles)}
|
||||
ownerClient, _ := coderdenttest.New(t, &coderdenttest.Options{
|
||||
Options: &coderdtest.Options{
|
||||
DeploymentValues: dv,
|
||||
IncludeProvisionerDaemon: false,
|
||||
},
|
||||
LicenseOptions: &coderdenttest.LicenseOptions{
|
||||
Features: license.Features{
|
||||
codersdk.FeatureAccessControl: 1,
|
||||
codersdk.FeatureCustomRoles: 1,
|
||||
codersdk.FeatureExternalProvisionerDaemons: 1,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
secondOrg := coderdtest.CreateOrganization(t, ownerClient, coderdtest.CreateOrganizationOptions{
|
||||
IncludeProvisionerDaemon: true,
|
||||
})
|
||||
|
||||
//nolint:gocritic // owner required to make custom roles
|
||||
orgTemplateAdminRole, err := ownerClient.PatchOrganizationRole(ctx, secondOrg.ID, codersdk.Role{
|
||||
Name: "org-template-admin",
|
||||
OrganizationID: secondOrg.ID.String(),
|
||||
OrganizationPermissions: codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
|
||||
codersdk.ResourceTemplate: codersdk.RBACResourceActions[codersdk.ResourceTemplate],
|
||||
}),
|
||||
})
|
||||
require.NoError(t, err, "create admin role")
|
||||
|
||||
orgTemplateAdmin, _ := coderdtest.CreateAnotherUser(t, ownerClient, secondOrg.ID, rbac.RoleIdentifier{
|
||||
Name: orgTemplateAdminRole.Name,
|
||||
OrganizationID: secondOrg.ID,
|
||||
})
|
||||
|
||||
version := coderdtest.CreateTemplateVersion(t, orgTemplateAdmin, secondOrg.ID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionApply: echo.ApplyComplete,
|
||||
ProvisionPlan: echo.PlanComplete,
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, orgTemplateAdmin, version.ID)
|
||||
|
||||
template := coderdtest.CreateTemplate(t, orgTemplateAdmin, secondOrg.ID, version.ID)
|
||||
require.Equal(t, template.OrganizationID, secondOrg.ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplateACL(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user