Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix: list templates returns non-deprecated templates by default#17747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ssncferreira merged 8 commits intomainfromssncferreira/fix-deprecated-templates
May 13, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
8 commits
Select commitHold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletionscoderd/apidoc/docs.go
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

2 changes: 2 additions & 0 deletionscoderd/apidoc/swagger.json
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

18 changes: 17 additions & 1 deletioncoderd/database/dbmem/dbmem.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1380,6 +1380,12 @@ func (q *FakeQuerier) getProvisionerJobsByIDsWithQueuePositionLockedGlobalQueue(
return jobs, nil
}

// isDeprecated returns true if the template is deprecated.
// A template is considered deprecated when it has a deprecation message.
func isDeprecated(template database.Template) bool {
return template.Deprecated != ""
}

func (*FakeQuerier) AcquireLock(_ context.Context, _ int64) error {
return xerrors.New("AcquireLock must only be called within a transaction")
}
Expand DownExpand Up@@ -13023,7 +13029,17 @@ func (q *FakeQuerier) GetAuthorizedTemplates(ctx context.Context, arg database.G
if arg.ExactName != "" && !strings.EqualFold(template.Name, arg.ExactName) {
continue
}
if arg.Deprecated.Valid && arg.Deprecated.Bool == (template.Deprecated != "") {
// Filters templates based on the search query filter 'Deprecated' status
// Matching SQL logic:
// -- Filter by deprecated
// AND CASE
// WHEN :deprecated IS NOT NULL THEN
// CASE
// WHEN :deprecated THEN deprecated != ''
// ELSE deprecated = ''
// END
// ELSE true
if arg.Deprecated.Valid && arg.Deprecated.Bool != isDeprecated(template) {
continue
}
if arg.FuzzyName != "" {
Expand Down
14 changes: 14 additions & 0 deletionscoderd/templates.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -487,6 +487,9 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
}

// @Summary Get templates by organization
// @Description Returns a list of templates for the specified organization.
// @Description By default, only non-deprecated templates are returned.
// @Description To include deprecated templates, specify `deprecated:true` in the search query.
// @ID get-templates-by-organization
// @Security CoderSessionToken
// @Produce json
Expand All@@ -506,6 +509,9 @@ func (api *API) templatesByOrganization() http.HandlerFunc {
}

// @Summary Get all templates
// @Description Returns a list of templates.
// @Description By default, only non-deprecated templates are returned.
// @Description To include deprecated templates, specify `deprecated:true` in the search query.
// @ID get-all-templates
// @Security CoderSessionToken
// @Produce json
Expand DownExpand Up@@ -540,6 +546,14 @@ func (api *API) fetchTemplates(mutate func(r *http.Request, arg *database.GetTem
mutate(r, &args)
}

// By default, deprecated templates are excluded unless explicitly requested
if !args.Deprecated.Valid {
args.Deprecated = sql.NullBool{
Bool: false,
Valid: true,
}
}

// Filter templates based on rbac permissions
templates, err := api.Database.GetAuthorizedTemplates(ctx, args, prepared)
if errors.Is(err, sql.ErrNoRows) {
Expand Down
286 changes: 286 additions & 0 deletionscoderd/templates_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -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) {
Expand DownExpand Up@@ -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) {
Expand Down
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp