Skip to content

Commit e74d4dc

Browse files
authored
Merge branch 'main' into feat-drift-remediation-#1011
2 parents 3a16d2f + 225db0e commit e74d4dc

File tree

6 files changed

+123
-20
lines changed

6 files changed

+123
-20
lines changed

client/environment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ type Environment struct {
118118
AutoDeployOnPathChangesOnly *bool `json:"autoDeployOnPathChangesOnly,omitempty" tfschema:",omitempty"`
119119
AutoDeployByCustomGlob string `json:"autoDeployByCustomGlob,omitempty"`
120120
Status string `json:"status"`
121-
LifespanEndAt string `json:"lifespanEndAt" tfschema:"ttl"`
121+
LifespanEndAt string `json:"lifespanEndAt" tfschema:"ttl,omitempty"`
122122
LatestDeploymentLogId string `json:"latestDeploymentLogId" tfschema:"deployment_id"`
123123
LatestDeploymentLog DeploymentLog `json:"latestDeploymentLog"`
124124
TerragruntWorkingDirectory string `json:"terragruntWorkingDirectory,omitempty"`

env0/data_environment.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,24 @@ func dataEnvironmentRead(ctx context.Context, d *schema.ResourceData, meta inter
150150
return diag.FromErr(err)
151151
}
152152

153+
// Set this explicitly because these are not set in setEnvironmentSchema due to possible project inheritance.
154+
155+
if environment.AutoDeployOnPathChangesOnly != nil {
156+
d.Set("auto_deploy_on_path_changes_only", *environment.AutoDeployOnPathChangesOnly)
157+
}
158+
159+
if environment.ContinuousDeployment != nil {
160+
d.Set("deploy_on_push", *environment.ContinuousDeployment)
161+
}
162+
163+
if environment.PullRequestPlanDeployments != nil {
164+
d.Set("run_plan_on_pull_requests", *environment.PullRequestPlanDeployments)
165+
}
166+
167+
if environment.LifespanEndAt != "" {
168+
d.Set("ttl", environment.LifespanEndAt)
169+
}
170+
153171
subEnvironments := []interface{}{}
154172

155173
if environment.LatestDeploymentLog.WorkflowFile != nil {

env0/resource_environment.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,26 @@ func resourceEnvironment() *schema.Resource {
385385
}
386386

387387
func setEnvironmentSchema(ctx context.Context, d *schema.ResourceData, environment client.Environment, configurationVariables client.ConfigurationChanges, variableSetsIds []string) error {
388+
// Some of the fields can be inherited from the project. Ignore them if not explicitly set.
389+
//nolint:staticcheck // https://github.com/hashicorp/terraform-plugin-sdk/issues/817
390+
if _, exists := d.GetOkExists("auto_deploy_on_path_changes_only"); !exists {
391+
environment.AutoDeployOnPathChangesOnly = nil
392+
}
393+
394+
//nolint:staticcheck // https://github.com/hashicorp/terraform-plugin-sdk/issues/817
395+
if _, exists := d.GetOkExists("deploy_on_push"); !exists {
396+
environment.ContinuousDeployment = nil
397+
}
398+
399+
//nolint:staticcheck // https://github.com/hashicorp/terraform-plugin-sdk/issues/817
400+
if _, exists := d.GetOkExists("run_plan_on_pull_requests"); !exists {
401+
environment.PullRequestPlanDeployments = nil
402+
}
403+
404+
if _, ok := d.GetOk("ttl"); !ok {
405+
environment.LifespanEndAt = ""
406+
}
407+
388408
if err := writeResourceData(&environment, d); err != nil {
389409
return fmt.Errorf("schema resource data serialization failed: %w", err)
390410
}
@@ -597,10 +617,6 @@ func resourceEnvironmentCreate(ctx context.Context, d *schema.ResourceData, meta
597617
d.SetId(environment.Id)
598618
d.Set("deployment_id", environment.LatestDeploymentLogId)
599619

600-
if environment.AutoDeployOnPathChangesOnly != nil {
601-
d.Set("auto_deploy_on_path_changes_only", *environment.AutoDeployOnPathChangesOnly)
602-
}
603-
604620
var environmentVariableSetIds []string
605621
if environmentPayload.ConfigurationSetChanges != nil {
606622
environmentVariableSetIds = environmentPayload.ConfigurationSetChanges.Assign

env0/resource_environment_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,6 +2011,75 @@ func TestUnitEnvironmentResource(t *testing.T) {
20112011
mock.EXPECT().EnvironmentDestroy(environment.Id).Times(1)
20122012
})
20132013
})
2014+
2015+
t.Run("No drift with unspecified fields", func(t *testing.T) {
2016+
truthyValue := true
2017+
falseyValue := false
2018+
2019+
// Environment with fields set by API
2020+
environmentWithAPIFields := client.Environment{
2021+
Id: uuid.New().String(),
2022+
Name: "my-environment",
2023+
ProjectId: "project-id",
2024+
WorkspaceName: "workspace-name",
2025+
LifespanEndAt: "2023-12-13T10:00:00Z", // TTL is set by API but not in schema
2026+
ContinuousDeployment: &truthyValue, // deploy_on_push set by API but not in schema
2027+
PullRequestPlanDeployments: &truthyValue, // run_plan_on_pull_requests set by API but not in schema
2028+
AutoDeployOnPathChangesOnly: &falseyValue, // auto_deploy_on_path_changes_only set by API but not in schema
2029+
LatestDeploymentLog: client.DeploymentLog{
2030+
BlueprintId: templateId,
2031+
BlueprintRevision: "revision",
2032+
Output: []byte(`{"a": "b"}`),
2033+
},
2034+
}
2035+
2036+
// Create a minimal config that does NOT specify the fields we're testing
2037+
minimalConfig := resourceConfigCreate(resourceType, resourceName, map[string]interface{}{
2038+
"name": environmentWithAPIFields.Name,
2039+
"project_id": environmentWithAPIFields.ProjectId,
2040+
"template_id": environmentWithAPIFields.LatestDeploymentLog.BlueprintId,
2041+
"force_destroy": true,
2042+
})
2043+
2044+
testCase := resource.TestCase{
2045+
Steps: []resource.TestStep{
2046+
{
2047+
Config: minimalConfig,
2048+
Check: resource.ComposeAggregateTestCheckFunc(
2049+
resource.TestCheckResourceAttr(accessor, "id", environmentWithAPIFields.Id),
2050+
resource.TestCheckResourceAttr(accessor, "name", environmentWithAPIFields.Name),
2051+
resource.TestCheckResourceAttr(accessor, "project_id", environmentWithAPIFields.ProjectId),
2052+
resource.TestCheckResourceAttr(accessor, "template_id", templateId),
2053+
2054+
// Fields that aren't set in schema but are returned by API shouldn't be in state
2055+
resource.TestCheckNoResourceAttr(accessor, "ttl"),
2056+
resource.TestCheckNoResourceAttr(accessor, "deploy_on_push"),
2057+
resource.TestCheckNoResourceAttr(accessor, "run_plan_on_pull_requests"),
2058+
resource.TestCheckNoResourceAttr(accessor, "auto_deploy_on_path_changes_only"),
2059+
),
2060+
},
2061+
},
2062+
}
2063+
2064+
runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
2065+
mock.EXPECT().Template(environmentWithAPIFields.LatestDeploymentLog.BlueprintId).Times(1).Return(template, nil)
2066+
2067+
// Expect environment create with minimal fields
2068+
mock.EXPECT().EnvironmentCreate(client.EnvironmentCreate{
2069+
Name: environmentWithAPIFields.Name,
2070+
ProjectId: environmentWithAPIFields.ProjectId,
2071+
DeployRequest: &client.DeployRequest{
2072+
BlueprintId: templateId,
2073+
},
2074+
}).Times(1).Return(environmentWithAPIFields, nil)
2075+
2076+
// API returns environment with the fields set
2077+
mock.EXPECT().Environment(environmentWithAPIFields.Id).Times(1).Return(environmentWithAPIFields, nil)
2078+
mock.EXPECT().ConfigurationVariablesByScope(client.ScopeEnvironment, environmentWithAPIFields.Id).Times(1).Return(client.ConfigurationChanges{}, nil)
2079+
mock.EXPECT().ConfigurationSetsAssignments("ENVIRONMENT", environmentWithAPIFields.Id).Times(1).Return(nil, nil)
2080+
mock.EXPECT().EnvironmentDestroy(environmentWithAPIFields.Id).Times(1)
2081+
})
2082+
})
20142083
}
20152084

20162085
testTTL := func() {

go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@ require (
7575
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
7676
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
7777
github.com/zclconf/go-cty v1.16.2 // indirect
78-
golang.org/x/crypto v0.32.0 // indirect
78+
golang.org/x/crypto v0.35.0 // indirect
7979
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb // indirect
8080
golang.org/x/mod v0.22.0 // indirect
81-
golang.org/x/net v0.34.0 // indirect
82-
golang.org/x/sync v0.10.0 // indirect
83-
golang.org/x/sys v0.29.0 // indirect
84-
golang.org/x/text v0.21.0 // indirect
81+
golang.org/x/net v0.36.0 // indirect
82+
golang.org/x/sync v0.11.0 // indirect
83+
golang.org/x/sys v0.30.0 // indirect
84+
golang.org/x/text v0.22.0 // indirect
8585
golang.org/x/tools v0.29.0 // indirect
8686
google.golang.org/appengine v1.6.8 // indirect
8787
google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287 // indirect

go.sum

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
266266
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
267267
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
268268
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
269-
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
270-
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
269+
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
270+
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
271271
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb h1:mIKbk8weKhSeLH2GmUTrvx8CjkyJmnU1wFmg59CUjFA=
272272
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
273273
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -282,14 +282,14 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
282282
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
283283
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
284284
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
285-
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
286-
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
285+
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
286+
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
287287
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
288288
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
289289
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
290290
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
291-
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
292-
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
291+
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
292+
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
293293
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
294294
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
295295
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -310,8 +310,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
310310
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
311311
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
312312
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
313-
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
314-
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
313+
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
314+
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
315315
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
316316
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
317317
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -321,8 +321,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
321321
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
322322
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
323323
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
324-
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
325-
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
324+
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
325+
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
326326
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
327327
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
328328
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

0 commit comments

Comments
 (0)