Skip to content

Commit b74d578

Browse files
committed
fix: avoid sending template metadata update if max_port_share_level is default
1 parent aa3dbcd commit b74d578

File tree

2 files changed

+144
-111
lines changed

2 files changed

+144
-111
lines changed

internal/provider/template_resource.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,8 @@ func (r *TemplateResource) Create(ctx context.Context, req resource.CreateReques
573573
// deployment running `v2.15.0` or later.
574574
if data.MaxPortShareLevel.IsUnknown() {
575575
data.MaxPortShareLevel = types.StringValue(string(templateResp.MaxPortShareLevel))
576+
} else if data.MaxPortShareLevel.ValueString() == string(templateResp.MaxPortShareLevel) {
577+
tflog.Info(ctx, "max port share level set to default, not updating")
576578
} else {
577579
mpslReq := data.toUpdateRequest(ctx, &resp.Diagnostics)
578580
if resp.Diagnostics.HasError() {

internal/provider/template_resource_test.go

Lines changed: 142 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -657,129 +657,160 @@ func TestAccTemplateResourceEnterprise(t *testing.T) {
657657
err = cp.Copy("../../integration/template-test/example-template", exTemplateOne)
658658
require.NoError(t, err)
659659

660-
cfg1 := testAccTemplateResourceConfig{
661-
URL: client.URL.String(),
662-
Token: client.SessionToken(),
663-
Name: ptr.Ref("example-template"),
664-
Versions: []testAccTemplateVersionConfig{
665-
{
666-
// Auto-generated version name
667-
Directory: &exTemplateOne,
668-
Active: ptr.Ref(true),
669-
},
670-
},
671-
ACL: testAccTemplateACLConfig{
672-
GroupACL: []testAccTemplateKeyValueConfig{
673-
{
674-
Key: ptr.Ref(firstUser.OrganizationIDs[0].String()),
675-
Value: ptr.Ref("use"),
676-
},
660+
t.Run("BasicUsage", func(t *testing.T) {
661+
cfg1 := testAccTemplateResourceConfig{
662+
URL: client.URL.String(),
663+
Token: client.SessionToken(),
664+
Name: ptr.Ref("example-template"),
665+
Versions: []testAccTemplateVersionConfig{
677666
{
678-
Key: ptr.Ref(group.ID.String()),
679-
Value: ptr.Ref("admin"),
667+
// Auto-generated version name
668+
Directory: &exTemplateOne,
669+
Active: ptr.Ref(true),
680670
},
681671
},
682-
UserACL: []testAccTemplateKeyValueConfig{
683-
{
684-
Key: ptr.Ref(firstUser.ID.String()),
685-
Value: ptr.Ref("admin"),
672+
ACL: testAccTemplateACLConfig{
673+
GroupACL: []testAccTemplateKeyValueConfig{
674+
{
675+
Key: ptr.Ref(firstUser.OrganizationIDs[0].String()),
676+
Value: ptr.Ref("use"),
677+
},
678+
{
679+
Key: ptr.Ref(group.ID.String()),
680+
Value: ptr.Ref("admin"),
681+
},
682+
},
683+
UserACL: []testAccTemplateKeyValueConfig{
684+
{
685+
Key: ptr.Ref(firstUser.ID.String()),
686+
Value: ptr.Ref("admin"),
687+
},
686688
},
687689
},
688-
},
689-
}
690+
}
690691

691-
cfg2 := cfg1
692-
cfg2.ACL.GroupACL = slices.Clone(cfg2.ACL.GroupACL[1:])
693-
cfg2.MaxPortShareLevel = ptr.Ref("owner")
692+
cfg2 := cfg1
693+
cfg2.ACL.GroupACL = slices.Clone(cfg2.ACL.GroupACL[1:])
694+
cfg2.MaxPortShareLevel = ptr.Ref("owner")
694695

695-
cfg3 := cfg2
696-
cfg3.ACL.null = true
697-
cfg3.MaxPortShareLevel = ptr.Ref("public")
696+
cfg3 := cfg2
697+
cfg3.ACL.null = true
698+
cfg3.MaxPortShareLevel = ptr.Ref("public")
698699

699-
cfg4 := cfg3
700-
cfg4.AllowUserAutostart = ptr.Ref(false)
701-
cfg4.AutostopRequirement = testAccAutostopRequirementConfig{
702-
DaysOfWeek: ptr.Ref([]string{"monday", "tuesday"}),
703-
Weeks: ptr.Ref(int64(2)),
704-
}
700+
cfg4 := cfg3
701+
cfg4.AllowUserAutostart = ptr.Ref(false)
702+
cfg4.AutostopRequirement = testAccAutostopRequirementConfig{
703+
DaysOfWeek: ptr.Ref([]string{"monday", "tuesday"}),
704+
Weeks: ptr.Ref(int64(2)),
705+
}
705706

706-
resource.Test(t, resource.TestCase{
707-
PreCheck: func() { testAccPreCheck(t) },
708-
IsUnitTest: true,
709-
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
710-
Steps: []resource.TestStep{
711-
{
712-
Config: cfg1.String(t),
713-
Check: resource.ComposeAggregateTestCheckFunc(
714-
resource.TestCheckResourceAttr("coderd_template.test", "max_port_share_level", "owner"),
715-
resource.TestCheckResourceAttr("coderd_template.test", "acl.groups.#", "2"),
716-
resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "acl.groups.*", map[string]*regexp.Regexp{
717-
"id": regexp.MustCompile(firstUser.OrganizationIDs[0].String()),
718-
"role": regexp.MustCompile("^use$"),
719-
}),
720-
resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "acl.groups.*", map[string]*regexp.Regexp{
721-
"id": regexp.MustCompile(group.ID.String()),
722-
"role": regexp.MustCompile("^admin$"),
723-
}),
724-
resource.TestCheckResourceAttr("coderd_template.test", "acl.users.#", "1"),
725-
resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "acl.users.*", map[string]*regexp.Regexp{
726-
"id": regexp.MustCompile(firstUser.ID.String()),
727-
"role": regexp.MustCompile("^admin$"),
728-
}),
729-
),
730-
},
731-
{
732-
Config: cfg2.String(t),
733-
Check: resource.ComposeAggregateTestCheckFunc(
734-
resource.TestCheckResourceAttr("coderd_template.test", "max_port_share_level", "owner"),
735-
resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "acl.users.*", map[string]*regexp.Regexp{
736-
"id": regexp.MustCompile(firstUser.ID.String()),
737-
"role": regexp.MustCompile("^admin$"),
738-
}),
739-
),
707+
resource.Test(t, resource.TestCase{
708+
PreCheck: func() { testAccPreCheck(t) },
709+
IsUnitTest: true,
710+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
711+
Steps: []resource.TestStep{
712+
{
713+
Config: cfg1.String(t),
714+
Check: resource.ComposeAggregateTestCheckFunc(
715+
resource.TestCheckResourceAttr("coderd_template.test", "max_port_share_level", "owner"),
716+
resource.TestCheckResourceAttr("coderd_template.test", "acl.groups.#", "2"),
717+
resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "acl.groups.*", map[string]*regexp.Regexp{
718+
"id": regexp.MustCompile(firstUser.OrganizationIDs[0].String()),
719+
"role": regexp.MustCompile("^use$"),
720+
}),
721+
resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "acl.groups.*", map[string]*regexp.Regexp{
722+
"id": regexp.MustCompile(group.ID.String()),
723+
"role": regexp.MustCompile("^admin$"),
724+
}),
725+
resource.TestCheckResourceAttr("coderd_template.test", "acl.users.#", "1"),
726+
resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "acl.users.*", map[string]*regexp.Regexp{
727+
"id": regexp.MustCompile(firstUser.ID.String()),
728+
"role": regexp.MustCompile("^admin$"),
729+
}),
730+
),
731+
},
732+
{
733+
Config: cfg2.String(t),
734+
Check: resource.ComposeAggregateTestCheckFunc(
735+
resource.TestCheckResourceAttr("coderd_template.test", "max_port_share_level", "owner"),
736+
resource.TestMatchTypeSetElemNestedAttrs("coderd_template.test", "acl.users.*", map[string]*regexp.Regexp{
737+
"id": regexp.MustCompile(firstUser.ID.String()),
738+
"role": regexp.MustCompile("^admin$"),
739+
}),
740+
),
741+
},
742+
{
743+
Config: cfg3.String(t),
744+
Check: resource.ComposeAggregateTestCheckFunc(
745+
resource.TestCheckResourceAttr("coderd_template.test", "max_port_share_level", "public"),
746+
resource.TestCheckNoResourceAttr("coderd_template.test", "acl"),
747+
func(s *terraform.State) error {
748+
templates, err := client.Templates(ctx, codersdk.TemplateFilter{})
749+
if err != nil {
750+
return err
751+
}
752+
if len(templates) != 1 {
753+
return fmt.Errorf("expected 1 template, got %d", len(templates))
754+
}
755+
acl, err := client.TemplateACL(ctx, templates[0].ID)
756+
if err != nil {
757+
return err
758+
}
759+
if len(acl.Groups) != 1 {
760+
return fmt.Errorf("expected 1 group ACL, got %d", len(acl.Groups))
761+
}
762+
if acl.Groups[0].Role != "admin" && acl.Groups[0].ID != group.ID {
763+
return fmt.Errorf("expected group ACL to be 'use' for %s, got %s", firstUser.OrganizationIDs[0].String(), acl.Groups[0].Role)
764+
}
765+
if len(acl.Users) != 1 {
766+
return fmt.Errorf("expected 1 user ACL, got %d", len(acl.Users))
767+
}
768+
if acl.Users[0].Role != "admin" && acl.Users[0].ID != firstUser.ID {
769+
return fmt.Errorf("expected user ACL to be 'admin' for %s, got %s", firstUser.ID.String(), acl.Users[0].Role)
770+
}
771+
return nil
772+
},
773+
),
774+
},
775+
{
776+
Config: cfg4.String(t),
777+
Check: resource.ComposeAggregateTestCheckFunc(
778+
resource.TestCheckResourceAttr("coderd_template.test", "allow_user_auto_start", "false"),
779+
resource.TestCheckResourceAttr("coderd_template.test", "auto_stop_requirement.days_of_week.#", "2"),
780+
resource.TestCheckResourceAttr("coderd_template.test", "auto_stop_requirement.weeks", "2"),
781+
),
782+
},
740783
},
741-
{
742-
Config: cfg3.String(t),
743-
Check: resource.ComposeAggregateTestCheckFunc(
744-
resource.TestCheckResourceAttr("coderd_template.test", "max_port_share_level", "public"),
745-
resource.TestCheckNoResourceAttr("coderd_template.test", "acl"),
746-
func(s *terraform.State) error {
747-
templates, err := client.Templates(ctx, codersdk.TemplateFilter{})
748-
if err != nil {
749-
return err
750-
}
751-
if len(templates) != 1 {
752-
return fmt.Errorf("expected 1 template, got %d", len(templates))
753-
}
754-
acl, err := client.TemplateACL(ctx, templates[0].ID)
755-
if err != nil {
756-
return err
757-
}
758-
if len(acl.Groups) != 1 {
759-
return fmt.Errorf("expected 1 group ACL, got %d", len(acl.Groups))
760-
}
761-
if acl.Groups[0].Role != "admin" && acl.Groups[0].ID != group.ID {
762-
return fmt.Errorf("expected group ACL to be 'use' for %s, got %s", firstUser.OrganizationIDs[0].String(), acl.Groups[0].Role)
763-
}
764-
if len(acl.Users) != 1 {
765-
return fmt.Errorf("expected 1 user ACL, got %d", len(acl.Users))
766-
}
767-
if acl.Users[0].Role != "admin" && acl.Users[0].ID != firstUser.ID {
768-
return fmt.Errorf("expected user ACL to be 'admin' for %s, got %s", firstUser.ID.String(), acl.Users[0].Role)
769-
}
770-
return nil
771-
},
772-
),
784+
})
785+
})
786+
787+
// Verifies that when `max_port_share_level` is set to to the default value,
788+
// an update request that would return HTTP Not Modified is not sent.
789+
t.Run("DefaultMaxPortShareLevel", func(t *testing.T) {
790+
cfg1 := testAccTemplateResourceConfig{
791+
URL: client.URL.String(),
792+
Token: client.SessionToken(),
793+
Name: ptr.Ref("example-template"),
794+
Versions: []testAccTemplateVersionConfig{
795+
{
796+
Directory: &exTemplateOne,
797+
Active: ptr.Ref(true),
798+
},
773799
},
774-
{
775-
Config: cfg4.String(t),
776-
Check: resource.ComposeAggregateTestCheckFunc(
777-
resource.TestCheckResourceAttr("coderd_template.test", "allow_user_auto_start", "false"),
778-
resource.TestCheckResourceAttr("coderd_template.test", "auto_stop_requirement.days_of_week.#", "2"),
779-
resource.TestCheckResourceAttr("coderd_template.test", "auto_stop_requirement.weeks", "2"),
780-
),
800+
MaxPortShareLevel: ptr.Ref("owner"),
801+
}
802+
803+
resource.Test(t, resource.TestCase{
804+
PreCheck: func() { testAccPreCheck(t) },
805+
IsUnitTest: true,
806+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
807+
Steps: []resource.TestStep{
808+
{
809+
Config: cfg1.String(t),
810+
Check: resource.TestCheckResourceAttr("coderd_template.test", "max_port_share_level", "owner"),
811+
},
781812
},
782-
},
813+
})
783814
})
784815
}
785816

0 commit comments

Comments
 (0)