Skip to content

Commit

Permalink
Feat: cannot change template id, instead return an error (#770)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomerHeber authored Dec 18, 2023
1 parent fc0e9e0 commit 936dbc4
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
14 changes: 6 additions & 8 deletions env0/resource_environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func resourceEnvironment() *schema.Resource {
},
"template_id": {
Type: schema.TypeString,
Description: "the template id the environment is to be created from.\nImportant note: the template must first be assigned to the same project as the environment (project_id). Use 'env0_template_project_assignment' to assign the template to the project. In addition, be sure to leverage 'depends_on' if applicable.",
Description: "the template id the environment is to be created from.\nImportant note: the template must first be assigned to the same project as the environment (project_id). Use 'env0_template_project_assignment' to assign the template to the project. In addition, be sure to leverage 'depends_on' if applicable.\nImportant note: After the environment is created, this field cannot be modified.",
Optional: true,
ExactlyOneOf: []string{"without_template_settings", "template_id"},
},
Expand Down Expand Up @@ -330,14 +330,12 @@ func resourceEnvironment() *schema.Resource {
Default: false,
},
},

CustomizeDiff: customdiff.ForceNewIf("template_id", func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) bool {
// For templateless: any changes in template_id, no need to do anything (template id can't change).
// This is done due to historical bugs/issues.
if _, ok := d.GetOk("without_template_settings.0"); ok {
return false
CustomizeDiff: customdiff.ValidateChange("template_id", func(ctx context.Context, oldValue, newValue, meta interface{}) error {
if oldValue != "" && oldValue != newValue {
return errors.New("template_id may not be modified, create a new environment instead")
}
return true

return nil
}),
}
}
Expand Down
62 changes: 62 additions & 0 deletions env0/resource_environment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,68 @@ func TestUnitEnvironmentResource(t *testing.T) {
})
})

t.Run("avoid modifying template id", func(t *testing.T) {
templateId := "template-id"
newTemplateId := "new-template-id"

environment := client.Environment{
Id: uuid.New().String(),
Name: "name",
ProjectId: "project-id",
LatestDeploymentLog: client.DeploymentLog{
BlueprintId: templateId,
},
}

testCase := resource.TestCase{
Steps: []resource.TestStep{
{
Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{
"name": environment.Name,
"project_id": environment.ProjectId,
"template_id": templateId,
"force_destroy": true,
}),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(accessor, "id", environment.Id),
resource.TestCheckResourceAttr(accessor, "name", environment.Name),
resource.TestCheckResourceAttr(accessor, "project_id", environment.ProjectId),
resource.TestCheckResourceAttr(accessor, "template_id", templateId),
),
},
{
Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{
"name": environment.Name,
"project_id": environment.ProjectId,
"template_id": newTemplateId,
"force_destroy": true,
}),
PlanOnly: true,
ExpectError: regexp.MustCompile("template_id may not be modified, create a new environment instead"),
},
},
}

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().Template(environment.LatestDeploymentLog.BlueprintId).Times(1).Return(template, nil),
mock.EXPECT().EnvironmentCreate(client.EnvironmentCreate{
Name: environment.Name,
ProjectId: environment.ProjectId,

DeployRequest: &client.DeployRequest{
BlueprintId: templateId,
},
}).Times(1).Return(environment, nil),
mock.EXPECT().Environment(environment.Id).Times(1).Return(environment, nil),
mock.EXPECT().ConfigurationVariablesByScope(client.ScopeEnvironment, environment.Id).Times(1).Return(client.ConfigurationChanges{}, nil),
mock.EXPECT().Environment(environment.Id).Times(1).Return(environment, nil),
mock.EXPECT().ConfigurationVariablesByScope(client.ScopeEnvironment, environment.Id).Times(1).Return(client.ConfigurationChanges{}, nil),
mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1),
)
})
})

t.Run("remote apply is enabled", func(t *testing.T) {
templateId := "template-id"

Expand Down

0 comments on commit 936dbc4

Please sign in to comment.