mirror of
https://github.com/coder/coder.git
synced 2025-07-06 15:41:45 +00:00
fix(coderd): list templates returns non-deprecated templates by default (#17747)
## Description Modifies the behaviour of the "list templates" API endpoints to return non-deprecated templates by default. Users can still query for deprecated templates by specifying the `deprecated=true` query parameter. **Note:** The deprecation feature is an enterprise-level feature ## Affected Endpoints * /api/v2/organizations/{organization}/templates * /api/v2/templates Fixes #17565
This commit is contained in:
@ -441,6 +441,250 @@ func TestPostTemplateByOrganization(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplates(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("ListEmpty", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
templates, err := client.Templates(ctx, codersdk.TemplateFilter{})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, templates)
|
||||
require.Len(t, templates, 0)
|
||||
})
|
||||
|
||||
// Should return only non-deprecated templates by default
|
||||
t.Run("ListMultiple non-deprecated", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
owner, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{IncludeProvisionerDaemon: false})
|
||||
user := coderdtest.CreateFirstUser(t, owner)
|
||||
client, tplAdmin := coderdtest.CreateAnotherUser(t, owner, user.OrganizationID, rbac.RoleTemplateAdmin())
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
version2 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
foo := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "foo"
|
||||
})
|
||||
bar := coderdtest.CreateTemplate(t, client, user.OrganizationID, version2.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "bar"
|
||||
})
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
// Deprecate bar template
|
||||
deprecationMessage := "Some deprecated message"
|
||||
err := db.UpdateTemplateAccessControlByID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(tplAdmin, user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
|
||||
ID: bar.ID,
|
||||
RequireActiveVersion: false,
|
||||
Deprecated: deprecationMessage,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedBar, err := client.Template(ctx, bar.ID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, updatedBar.Deprecated)
|
||||
require.Equal(t, deprecationMessage, updatedBar.DeprecationMessage)
|
||||
|
||||
// Should return only the non-deprecated template (foo)
|
||||
templates, err := client.Templates(ctx, codersdk.TemplateFilter{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, templates, 1)
|
||||
|
||||
require.Equal(t, foo.ID, templates[0].ID)
|
||||
require.False(t, templates[0].Deprecated)
|
||||
require.Empty(t, templates[0].DeprecationMessage)
|
||||
})
|
||||
|
||||
// Should return only deprecated templates when filtering by deprecated:true
|
||||
t.Run("ListMultiple deprecated:true", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
owner, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{IncludeProvisionerDaemon: false})
|
||||
user := coderdtest.CreateFirstUser(t, owner)
|
||||
client, tplAdmin := coderdtest.CreateAnotherUser(t, owner, user.OrganizationID, rbac.RoleTemplateAdmin())
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
version2 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
foo := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "foo"
|
||||
})
|
||||
bar := coderdtest.CreateTemplate(t, client, user.OrganizationID, version2.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "bar"
|
||||
})
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
// Deprecate foo and bar templates
|
||||
deprecationMessage := "Some deprecated message"
|
||||
err := db.UpdateTemplateAccessControlByID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(tplAdmin, user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
|
||||
ID: foo.ID,
|
||||
RequireActiveVersion: false,
|
||||
Deprecated: deprecationMessage,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
err = db.UpdateTemplateAccessControlByID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(tplAdmin, user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
|
||||
ID: bar.ID,
|
||||
RequireActiveVersion: false,
|
||||
Deprecated: deprecationMessage,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Should have deprecation message set
|
||||
updatedFoo, err := client.Template(ctx, foo.ID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, updatedFoo.Deprecated)
|
||||
require.Equal(t, deprecationMessage, updatedFoo.DeprecationMessage)
|
||||
|
||||
updatedBar, err := client.Template(ctx, bar.ID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, updatedBar.Deprecated)
|
||||
require.Equal(t, deprecationMessage, updatedBar.DeprecationMessage)
|
||||
|
||||
// Should return only the deprecated templates (foo and bar)
|
||||
templates, err := client.Templates(ctx, codersdk.TemplateFilter{
|
||||
SearchQuery: "deprecated:true",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, templates, 2)
|
||||
|
||||
// Make sure all the deprecated templates are returned
|
||||
expectedTemplates := map[uuid.UUID]codersdk.Template{
|
||||
updatedFoo.ID: updatedFoo,
|
||||
updatedBar.ID: updatedBar,
|
||||
}
|
||||
actualTemplates := map[uuid.UUID]codersdk.Template{}
|
||||
for _, template := range templates {
|
||||
actualTemplates[template.ID] = template
|
||||
}
|
||||
|
||||
require.Equal(t, len(expectedTemplates), len(actualTemplates))
|
||||
for id, expectedTemplate := range expectedTemplates {
|
||||
actualTemplate, ok := actualTemplates[id]
|
||||
require.True(t, ok)
|
||||
require.Equal(t, expectedTemplate.ID, actualTemplate.ID)
|
||||
require.Equal(t, true, actualTemplate.Deprecated)
|
||||
require.Equal(t, expectedTemplate.DeprecationMessage, actualTemplate.DeprecationMessage)
|
||||
}
|
||||
})
|
||||
|
||||
// Should return only non-deprecated templates when filtering by deprecated:false
|
||||
t.Run("ListMultiple deprecated:false", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
version2 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
foo := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "foo"
|
||||
})
|
||||
bar := coderdtest.CreateTemplate(t, client, user.OrganizationID, version2.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "bar"
|
||||
})
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
// Should return only the non-deprecated templates
|
||||
templates, err := client.Templates(ctx, codersdk.TemplateFilter{
|
||||
SearchQuery: "deprecated:false",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, templates, 2)
|
||||
|
||||
// Make sure all the non-deprecated templates are returned
|
||||
expectedTemplates := map[uuid.UUID]codersdk.Template{
|
||||
foo.ID: foo,
|
||||
bar.ID: bar,
|
||||
}
|
||||
actualTemplates := map[uuid.UUID]codersdk.Template{}
|
||||
for _, template := range templates {
|
||||
actualTemplates[template.ID] = template
|
||||
}
|
||||
|
||||
require.Equal(t, len(expectedTemplates), len(actualTemplates))
|
||||
for id, expectedTemplate := range expectedTemplates {
|
||||
actualTemplate, ok := actualTemplates[id]
|
||||
require.True(t, ok)
|
||||
require.Equal(t, expectedTemplate.ID, actualTemplate.ID)
|
||||
require.Equal(t, false, actualTemplate.Deprecated)
|
||||
require.Equal(t, expectedTemplate.DeprecationMessage, actualTemplate.DeprecationMessage)
|
||||
}
|
||||
})
|
||||
|
||||
// Should return a re-enabled template in the default (non-deprecated) list
|
||||
t.Run("ListMultiple re-enabled template", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
owner, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{IncludeProvisionerDaemon: false})
|
||||
user := coderdtest.CreateFirstUser(t, owner)
|
||||
client, tplAdmin := coderdtest.CreateAnotherUser(t, owner, user.OrganizationID, rbac.RoleTemplateAdmin())
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
version2 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
foo := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "foo"
|
||||
})
|
||||
bar := coderdtest.CreateTemplate(t, client, user.OrganizationID, version2.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "bar"
|
||||
})
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
// Deprecate bar template
|
||||
deprecationMessage := "Some deprecated message"
|
||||
err := db.UpdateTemplateAccessControlByID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(tplAdmin, user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
|
||||
ID: bar.ID,
|
||||
RequireActiveVersion: false,
|
||||
Deprecated: deprecationMessage,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedBar, err := client.Template(ctx, bar.ID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, updatedBar.Deprecated)
|
||||
require.Equal(t, deprecationMessage, updatedBar.DeprecationMessage)
|
||||
|
||||
// Re-enable bar template
|
||||
err = db.UpdateTemplateAccessControlByID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(tplAdmin, user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
|
||||
ID: bar.ID,
|
||||
RequireActiveVersion: false,
|
||||
Deprecated: "",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
reEnabledBar, err := client.Template(ctx, bar.ID)
|
||||
require.NoError(t, err)
|
||||
require.False(t, reEnabledBar.Deprecated)
|
||||
require.Empty(t, reEnabledBar.DeprecationMessage)
|
||||
|
||||
// Should return only the non-deprecated templates (foo and bar)
|
||||
templates, err := client.Templates(ctx, codersdk.TemplateFilter{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, templates, 2)
|
||||
|
||||
// Make sure all the non-deprecated templates are returned
|
||||
expectedTemplates := map[uuid.UUID]codersdk.Template{
|
||||
foo.ID: foo,
|
||||
bar.ID: bar,
|
||||
}
|
||||
actualTemplates := map[uuid.UUID]codersdk.Template{}
|
||||
for _, template := range templates {
|
||||
actualTemplates[template.ID] = template
|
||||
}
|
||||
|
||||
require.Equal(t, len(expectedTemplates), len(actualTemplates))
|
||||
for id, expectedTemplate := range expectedTemplates {
|
||||
actualTemplate, ok := actualTemplates[id]
|
||||
require.True(t, ok)
|
||||
require.Equal(t, expectedTemplate.ID, actualTemplate.ID)
|
||||
require.Equal(t, false, actualTemplate.Deprecated)
|
||||
require.Equal(t, expectedTemplate.DeprecationMessage, actualTemplate.DeprecationMessage)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplatesByOrganization(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("ListEmpty", func(t *testing.T) {
|
||||
@ -525,6 +769,48 @@ func TestTemplatesByOrganization(t *testing.T) {
|
||||
require.Len(t, templates, 1)
|
||||
require.Equal(t, bar.ID, templates[0].ID)
|
||||
})
|
||||
|
||||
// Should return only non-deprecated templates by default
|
||||
t.Run("ListMultiple non-deprecated", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
owner, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{IncludeProvisionerDaemon: false})
|
||||
user := coderdtest.CreateFirstUser(t, owner)
|
||||
client, tplAdmin := coderdtest.CreateAnotherUser(t, owner, user.OrganizationID, rbac.RoleTemplateAdmin())
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
version2 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
foo := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "foo"
|
||||
})
|
||||
bar := coderdtest.CreateTemplate(t, client, user.OrganizationID, version2.ID, func(request *codersdk.CreateTemplateRequest) {
|
||||
request.Name = "bar"
|
||||
})
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
// Deprecate bar template
|
||||
deprecationMessage := "Some deprecated message"
|
||||
err := db.UpdateTemplateAccessControlByID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(tplAdmin, user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
|
||||
ID: bar.ID,
|
||||
RequireActiveVersion: false,
|
||||
Deprecated: deprecationMessage,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedBar, err := client.Template(ctx, bar.ID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, updatedBar.Deprecated)
|
||||
require.Equal(t, deprecationMessage, updatedBar.DeprecationMessage)
|
||||
|
||||
// Should return only the non-deprecated template (foo)
|
||||
templates, err := client.TemplatesByOrganization(ctx, user.OrganizationID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, templates, 1)
|
||||
|
||||
require.Equal(t, foo.ID, templates[0].ID)
|
||||
require.False(t, templates[0].Deprecated)
|
||||
require.Empty(t, templates[0].DeprecationMessage)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplateByOrganizationAndName(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user