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

Commit599bb35

Browse files
authored
fix(coderd): list templates returns non-deprecated templates by default (#17747)
## DescriptionModifies the behaviour of the "list templates" API endpoints to returnnon-deprecated templates by default. Users can still query fordeprecated templates by specifying the `deprecated=true` queryparameter.**Note:** The deprecation feature is an enterprise-level feature## Affected Endpoints* /api/v2/organizations/{organization}/templates* /api/v2/templatesFixes#17565
1 parent7f056da commit599bb35

File tree

6 files changed

+329
-1
lines changed

6 files changed

+329
-1
lines changed

‎coderd/apidoc/docs.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dbmem/dbmem.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,12 @@ func (q *FakeQuerier) getProvisionerJobsByIDsWithQueuePositionLockedGlobalQueue(
13801380
returnjobs,nil
13811381
}
13821382

1383+
// isDeprecated returns true if the template is deprecated.
1384+
// A template is considered deprecated when it has a deprecation message.
1385+
funcisDeprecated(template database.Template)bool {
1386+
returntemplate.Deprecated!=""
1387+
}
1388+
13831389
func (*FakeQuerier)AcquireLock(_ context.Context,_int64)error {
13841390
returnxerrors.New("AcquireLock must only be called within a transaction")
13851391
}
@@ -13023,7 +13029,17 @@ func (q *FakeQuerier) GetAuthorizedTemplates(ctx context.Context, arg database.G
1302313029
ifarg.ExactName!=""&&!strings.EqualFold(template.Name,arg.ExactName) {
1302413030
continue
1302513031
}
13026-
ifarg.Deprecated.Valid&&arg.Deprecated.Bool== (template.Deprecated!="") {
13032+
// Filters templates based on the search query filter 'Deprecated' status
13033+
// Matching SQL logic:
13034+
// -- Filter by deprecated
13035+
// AND CASE
13036+
// WHEN :deprecated IS NOT NULL THEN
13037+
// CASE
13038+
// WHEN :deprecated THEN deprecated != ''
13039+
// ELSE deprecated = ''
13040+
// END
13041+
// ELSE true
13042+
ifarg.Deprecated.Valid&&arg.Deprecated.Bool!=isDeprecated(template) {
1302713043
continue
1302813044
}
1302913045
ifarg.FuzzyName!="" {

‎coderd/templates.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,9 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
487487
}
488488

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

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

549+
// By default, deprecated templates are excluded unless explicitly requested
550+
if!args.Deprecated.Valid {
551+
args.Deprecated= sql.NullBool{
552+
Bool:false,
553+
Valid:true,
554+
}
555+
}
556+
543557
// Filter templates based on rbac permissions
544558
templates,err:=api.Database.GetAuthorizedTemplates(ctx,args,prepared)
545559
iferrors.Is(err,sql.ErrNoRows) {

‎coderd/templates_test.go

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,250 @@ func TestPostTemplateByOrganization(t *testing.T) {
441441
})
442442
}
443443

444+
funcTestTemplates(t*testing.T) {
445+
t.Parallel()
446+
447+
t.Run("ListEmpty",func(t*testing.T) {
448+
t.Parallel()
449+
client:=coderdtest.New(t,nil)
450+
_=coderdtest.CreateFirstUser(t,client)
451+
452+
ctx:=testutil.Context(t,testutil.WaitLong)
453+
454+
templates,err:=client.Templates(ctx, codersdk.TemplateFilter{})
455+
require.NoError(t,err)
456+
require.NotNil(t,templates)
457+
require.Len(t,templates,0)
458+
})
459+
460+
// Should return only non-deprecated templates by default
461+
t.Run("ListMultiple non-deprecated",func(t*testing.T) {
462+
t.Parallel()
463+
464+
owner,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{IncludeProvisionerDaemon:false})
465+
user:=coderdtest.CreateFirstUser(t,owner)
466+
client,tplAdmin:=coderdtest.CreateAnotherUser(t,owner,user.OrganizationID,rbac.RoleTemplateAdmin())
467+
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
468+
version2:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
469+
foo:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID,func(request*codersdk.CreateTemplateRequest) {
470+
request.Name="foo"
471+
})
472+
bar:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version2.ID,func(request*codersdk.CreateTemplateRequest) {
473+
request.Name="bar"
474+
})
475+
476+
ctx:=testutil.Context(t,testutil.WaitLong)
477+
478+
// Deprecate bar template
479+
deprecationMessage:="Some deprecated message"
480+
err:=db.UpdateTemplateAccessControlByID(dbauthz.As(ctx,coderdtest.AuthzUserSubject(tplAdmin,user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
481+
ID:bar.ID,
482+
RequireActiveVersion:false,
483+
Deprecated:deprecationMessage,
484+
})
485+
require.NoError(t,err)
486+
487+
updatedBar,err:=client.Template(ctx,bar.ID)
488+
require.NoError(t,err)
489+
require.True(t,updatedBar.Deprecated)
490+
require.Equal(t,deprecationMessage,updatedBar.DeprecationMessage)
491+
492+
// Should return only the non-deprecated template (foo)
493+
templates,err:=client.Templates(ctx, codersdk.TemplateFilter{})
494+
require.NoError(t,err)
495+
require.Len(t,templates,1)
496+
497+
require.Equal(t,foo.ID,templates[0].ID)
498+
require.False(t,templates[0].Deprecated)
499+
require.Empty(t,templates[0].DeprecationMessage)
500+
})
501+
502+
// Should return only deprecated templates when filtering by deprecated:true
503+
t.Run("ListMultiple deprecated:true",func(t*testing.T) {
504+
t.Parallel()
505+
506+
owner,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{IncludeProvisionerDaemon:false})
507+
user:=coderdtest.CreateFirstUser(t,owner)
508+
client,tplAdmin:=coderdtest.CreateAnotherUser(t,owner,user.OrganizationID,rbac.RoleTemplateAdmin())
509+
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
510+
version2:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
511+
foo:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID,func(request*codersdk.CreateTemplateRequest) {
512+
request.Name="foo"
513+
})
514+
bar:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version2.ID,func(request*codersdk.CreateTemplateRequest) {
515+
request.Name="bar"
516+
})
517+
518+
ctx:=testutil.Context(t,testutil.WaitLong)
519+
520+
// Deprecate foo and bar templates
521+
deprecationMessage:="Some deprecated message"
522+
err:=db.UpdateTemplateAccessControlByID(dbauthz.As(ctx,coderdtest.AuthzUserSubject(tplAdmin,user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
523+
ID:foo.ID,
524+
RequireActiveVersion:false,
525+
Deprecated:deprecationMessage,
526+
})
527+
require.NoError(t,err)
528+
err=db.UpdateTemplateAccessControlByID(dbauthz.As(ctx,coderdtest.AuthzUserSubject(tplAdmin,user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
529+
ID:bar.ID,
530+
RequireActiveVersion:false,
531+
Deprecated:deprecationMessage,
532+
})
533+
require.NoError(t,err)
534+
535+
// Should have deprecation message set
536+
updatedFoo,err:=client.Template(ctx,foo.ID)
537+
require.NoError(t,err)
538+
require.True(t,updatedFoo.Deprecated)
539+
require.Equal(t,deprecationMessage,updatedFoo.DeprecationMessage)
540+
541+
updatedBar,err:=client.Template(ctx,bar.ID)
542+
require.NoError(t,err)
543+
require.True(t,updatedBar.Deprecated)
544+
require.Equal(t,deprecationMessage,updatedBar.DeprecationMessage)
545+
546+
// Should return only the deprecated templates (foo and bar)
547+
templates,err:=client.Templates(ctx, codersdk.TemplateFilter{
548+
SearchQuery:"deprecated:true",
549+
})
550+
require.NoError(t,err)
551+
require.Len(t,templates,2)
552+
553+
// Make sure all the deprecated templates are returned
554+
expectedTemplates:=map[uuid.UUID]codersdk.Template{
555+
updatedFoo.ID:updatedFoo,
556+
updatedBar.ID:updatedBar,
557+
}
558+
actualTemplates:=map[uuid.UUID]codersdk.Template{}
559+
for_,template:=rangetemplates {
560+
actualTemplates[template.ID]=template
561+
}
562+
563+
require.Equal(t,len(expectedTemplates),len(actualTemplates))
564+
forid,expectedTemplate:=rangeexpectedTemplates {
565+
actualTemplate,ok:=actualTemplates[id]
566+
require.True(t,ok)
567+
require.Equal(t,expectedTemplate.ID,actualTemplate.ID)
568+
require.Equal(t,true,actualTemplate.Deprecated)
569+
require.Equal(t,expectedTemplate.DeprecationMessage,actualTemplate.DeprecationMessage)
570+
}
571+
})
572+
573+
// Should return only non-deprecated templates when filtering by deprecated:false
574+
t.Run("ListMultiple deprecated:false",func(t*testing.T) {
575+
t.Parallel()
576+
577+
client:=coderdtest.New(t,nil)
578+
user:=coderdtest.CreateFirstUser(t,client)
579+
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
580+
version2:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
581+
foo:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID,func(request*codersdk.CreateTemplateRequest) {
582+
request.Name="foo"
583+
})
584+
bar:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version2.ID,func(request*codersdk.CreateTemplateRequest) {
585+
request.Name="bar"
586+
})
587+
588+
ctx:=testutil.Context(t,testutil.WaitLong)
589+
590+
// Should return only the non-deprecated templates
591+
templates,err:=client.Templates(ctx, codersdk.TemplateFilter{
592+
SearchQuery:"deprecated:false",
593+
})
594+
require.NoError(t,err)
595+
require.Len(t,templates,2)
596+
597+
// Make sure all the non-deprecated templates are returned
598+
expectedTemplates:=map[uuid.UUID]codersdk.Template{
599+
foo.ID:foo,
600+
bar.ID:bar,
601+
}
602+
actualTemplates:=map[uuid.UUID]codersdk.Template{}
603+
for_,template:=rangetemplates {
604+
actualTemplates[template.ID]=template
605+
}
606+
607+
require.Equal(t,len(expectedTemplates),len(actualTemplates))
608+
forid,expectedTemplate:=rangeexpectedTemplates {
609+
actualTemplate,ok:=actualTemplates[id]
610+
require.True(t,ok)
611+
require.Equal(t,expectedTemplate.ID,actualTemplate.ID)
612+
require.Equal(t,false,actualTemplate.Deprecated)
613+
require.Equal(t,expectedTemplate.DeprecationMessage,actualTemplate.DeprecationMessage)
614+
}
615+
})
616+
617+
// Should return a re-enabled template in the default (non-deprecated) list
618+
t.Run("ListMultiple re-enabled template",func(t*testing.T) {
619+
t.Parallel()
620+
621+
owner,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{IncludeProvisionerDaemon:false})
622+
user:=coderdtest.CreateFirstUser(t,owner)
623+
client,tplAdmin:=coderdtest.CreateAnotherUser(t,owner,user.OrganizationID,rbac.RoleTemplateAdmin())
624+
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
625+
version2:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
626+
foo:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID,func(request*codersdk.CreateTemplateRequest) {
627+
request.Name="foo"
628+
})
629+
bar:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version2.ID,func(request*codersdk.CreateTemplateRequest) {
630+
request.Name="bar"
631+
})
632+
633+
ctx:=testutil.Context(t,testutil.WaitLong)
634+
635+
// Deprecate bar template
636+
deprecationMessage:="Some deprecated message"
637+
err:=db.UpdateTemplateAccessControlByID(dbauthz.As(ctx,coderdtest.AuthzUserSubject(tplAdmin,user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
638+
ID:bar.ID,
639+
RequireActiveVersion:false,
640+
Deprecated:deprecationMessage,
641+
})
642+
require.NoError(t,err)
643+
644+
updatedBar,err:=client.Template(ctx,bar.ID)
645+
require.NoError(t,err)
646+
require.True(t,updatedBar.Deprecated)
647+
require.Equal(t,deprecationMessage,updatedBar.DeprecationMessage)
648+
649+
// Re-enable bar template
650+
err=db.UpdateTemplateAccessControlByID(dbauthz.As(ctx,coderdtest.AuthzUserSubject(tplAdmin,user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
651+
ID:bar.ID,
652+
RequireActiveVersion:false,
653+
Deprecated:"",
654+
})
655+
require.NoError(t,err)
656+
657+
reEnabledBar,err:=client.Template(ctx,bar.ID)
658+
require.NoError(t,err)
659+
require.False(t,reEnabledBar.Deprecated)
660+
require.Empty(t,reEnabledBar.DeprecationMessage)
661+
662+
// Should return only the non-deprecated templates (foo and bar)
663+
templates,err:=client.Templates(ctx, codersdk.TemplateFilter{})
664+
require.NoError(t,err)
665+
require.Len(t,templates,2)
666+
667+
// Make sure all the non-deprecated templates are returned
668+
expectedTemplates:=map[uuid.UUID]codersdk.Template{
669+
foo.ID:foo,
670+
bar.ID:bar,
671+
}
672+
actualTemplates:=map[uuid.UUID]codersdk.Template{}
673+
for_,template:=rangetemplates {
674+
actualTemplates[template.ID]=template
675+
}
676+
677+
require.Equal(t,len(expectedTemplates),len(actualTemplates))
678+
forid,expectedTemplate:=rangeexpectedTemplates {
679+
actualTemplate,ok:=actualTemplates[id]
680+
require.True(t,ok)
681+
require.Equal(t,expectedTemplate.ID,actualTemplate.ID)
682+
require.Equal(t,false,actualTemplate.Deprecated)
683+
require.Equal(t,expectedTemplate.DeprecationMessage,actualTemplate.DeprecationMessage)
684+
}
685+
})
686+
}
687+
444688
funcTestTemplatesByOrganization(t*testing.T) {
445689
t.Parallel()
446690
t.Run("ListEmpty",func(t*testing.T) {
@@ -525,6 +769,48 @@ func TestTemplatesByOrganization(t *testing.T) {
525769
require.Len(t,templates,1)
526770
require.Equal(t,bar.ID,templates[0].ID)
527771
})
772+
773+
// Should return only non-deprecated templates by default
774+
t.Run("ListMultiple non-deprecated",func(t*testing.T) {
775+
t.Parallel()
776+
777+
owner,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{IncludeProvisionerDaemon:false})
778+
user:=coderdtest.CreateFirstUser(t,owner)
779+
client,tplAdmin:=coderdtest.CreateAnotherUser(t,owner,user.OrganizationID,rbac.RoleTemplateAdmin())
780+
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
781+
version2:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
782+
foo:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID,func(request*codersdk.CreateTemplateRequest) {
783+
request.Name="foo"
784+
})
785+
bar:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version2.ID,func(request*codersdk.CreateTemplateRequest) {
786+
request.Name="bar"
787+
})
788+
789+
ctx:=testutil.Context(t,testutil.WaitLong)
790+
791+
// Deprecate bar template
792+
deprecationMessage:="Some deprecated message"
793+
err:=db.UpdateTemplateAccessControlByID(dbauthz.As(ctx,coderdtest.AuthzUserSubject(tplAdmin,user.OrganizationID)), database.UpdateTemplateAccessControlByIDParams{
794+
ID:bar.ID,
795+
RequireActiveVersion:false,
796+
Deprecated:deprecationMessage,
797+
})
798+
require.NoError(t,err)
799+
800+
updatedBar,err:=client.Template(ctx,bar.ID)
801+
require.NoError(t,err)
802+
require.True(t,updatedBar.Deprecated)
803+
require.Equal(t,deprecationMessage,updatedBar.DeprecationMessage)
804+
805+
// Should return only the non-deprecated template (foo)
806+
templates,err:=client.TemplatesByOrganization(ctx,user.OrganizationID)
807+
require.NoError(t,err)
808+
require.Len(t,templates,1)
809+
810+
require.Equal(t,foo.ID,templates[0].ID)
811+
require.False(t,templates[0].Deprecated)
812+
require.Empty(t,templates[0].DeprecationMessage)
813+
})
528814
}
529815

530816
funcTestTemplateByOrganizationAndName(t*testing.T) {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp