diff --git a/internal/provider/template_resource.go b/internal/provider/template_resource.go index d296df1..7c1bdd2 100644 --- a/internal/provider/template_resource.go +++ b/internal/provider/template_resource.go @@ -896,9 +896,27 @@ func (a *activeVersionValidator) ValidateList(ctx context.Context, req validator return } + // Check all versions have unique names + uniqueNames := make(map[string]struct{}) + for _, version := range data { + if version.Name.IsNull() || version.Name.IsUnknown() { + continue + } + if _, ok := uniqueNames[version.Name.ValueString()]; ok { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Template version names must be unique. `%s` appears twice.", version.Name.ValueString())) + return + } + uniqueNames[version.Name.ValueString()] = struct{}{} + } + // Check if only one item in Version has active set to true active := false for _, version := range data { + // `active` is required, so if it's null or unknown, this is Terraform + // requesting an early validation. + if version.Active.IsNull() || version.Active.IsUnknown() { + return + } if version.Active.ValueBool() { if active { resp.Diagnostics.AddError("Client Error", "Only one template version can be active at a time.") @@ -910,19 +928,6 @@ func (a *activeVersionValidator) ValidateList(ctx context.Context, req validator if !active { resp.Diagnostics.AddError("Client Error", "At least one template version must be active.") } - - // Check all versions have unique names - uniqueNames := make(map[string]struct{}) - for _, version := range data { - if version.Name.IsNull() { - continue - } - if _, ok := uniqueNames[version.Name.ValueString()]; ok { - resp.Diagnostics.AddError("Client Error", "Template version names must be unique.") - return - } - uniqueNames[version.Name.ValueString()] = struct{}{} - } } var _ validator.List = &activeVersionValidator{} diff --git a/internal/provider/template_resource_test.go b/internal/provider/template_resource_test.go index 82f19ac..acb07f2 100644 --- a/internal/provider/template_resource_test.go +++ b/internal/provider/template_resource_test.go @@ -648,6 +648,62 @@ func TestAccTemplateResourceAGPL(t *testing.T) { }) } +func TestAccTemplateResourceVariables(t *testing.T) { + cfg := ` +provider coderd { + url = "%s" + token = "%s" +} + +data "coderd_organization" "default" { + is_default = true +} + +variable "PRIOR_GIT_COMMIT_SHA" { + default = "abcdef" +} + +variable "CURRENT_GIT_COMMIT_SHA" { + default = "ghijkl" +} + +variable "ACTIVE" { + default = true +} + +resource "coderd_template" "sample" { + name = "example-template" + versions = [ + { + name = "${var.PRIOR_GIT_COMMIT_SHA}" + directory = "../../integration/template-test/example-template" + active = var.ACTIVE + }, + { + name = "${var.CURRENT_GIT_COMMIT_SHA}" + directory = "../../integration/template-test/example-template" + active = false + } + ] +}` + + ctx := context.Background() + client := integration.StartCoder(ctx, t, "template_acc", false) + + cfg = fmt.Sprintf(cfg, client.URL.String(), client.SessionToken()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IsUnitTest: true, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: cfg, + }, + }, + }) +} + type testAccTemplateResourceConfig struct { URL string Token string