Skip to content

Commit 7952a76

Browse files
authored
Merge pull request #1011 from hashicorp/sebasslash/tf-8382_tfe-version-constraints
2 parents 7de2508 + 20c9986 commit 7952a76

File tree

6 files changed

+106
-29
lines changed

6 files changed

+106
-29
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## Unreleased
22

3+
BUG FIXES:
4+
* `r/tfe_team_project_access`: Fixes a panic that occurs when the client is configured against an older TFE release, by @sebasslash [1011](https://github.com/hashicorp/terraform-provider-tfe/pull/1011)
5+
36
FEATURES:
47
* `d/tfe_organization_membership`: Add `organization_membership_id` attribute, by @laurenolivia [997](https://github.com/hashicorp/terraform-provider-tfe/pull/997)
58
* `d/tfe_variable_set`: Add `project_ids` attribute, by @Netra2104 [994](https://github.com/hashicorp/terraform-provider-tfe/pull/994)

docs/backwards-compatibility.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Maintaining Backwards Compatibility (Terraform Enterprise)
2+
3+
## Terraform Enterprise Version Checking
4+
5+
**Note:** If you are introducing a new resource that is only available at a certain TFE release, you do not need to perform any sort of checks.
6+
7+
### Implied Check (Recommended Approach)
8+
9+
The simplest solution when a particular attribute is not supported by a given TFE release is a `nil` check. These checks are TFE release agnostic and assume that if a field was not returned by the API, the TFE release does not support it. They are particularly important for fields that are structs, where attempting to dereference a nil pointer causes a panic.
10+
11+
You can use this implied checks when:
12+
13+
- The field is a pointer
14+
- When a `null` value is ignored by the API or by go-tfe (see if the struct tag has `omitempty`)
15+
16+
**Example:**
17+
18+
```go
19+
if tmAccess.ProjectAccess != nil {
20+
projectAccess := []map[string]interface{}{{
21+
"settings": tmAccess.ProjectAccess.ProjectSettingsPermission,
22+
"teams": tmAccess.ProjectAccess.ProjectTeamsPermission,
23+
}}
24+
// Write project access to state
25+
err := d.Set("project_access", projectAccess)
26+
}
27+
```
28+
29+
### Explicit Enterprise Checks
30+
31+
If a resource or attribute is **only** available in Terraform Enterprise, use the go-tfe helper [IsEnterprise()](https://pkg.go.dev/github.com/hashicorp/go-tfe#Client.IsEnterprise) to ensure the client is configured against a TFE instance. This check is derived from the `TFP-AppName` header that Terraform Cloud emits, of which if not present, indicates a Terraform Enterprise installation.
32+
33+
```go
34+
config := meta.(ConfiguredClient)
35+
36+
if config.Client.IsEnterprise() {
37+
// do something with TFE only behavior
38+
}
39+
```
40+
41+
### Documentation
42+
43+
It is important to communicate with practitioners which resources and fields are supported for a particular TFE release.
44+
45+
For a new resource, add the minimum release required to the top level documentation.
46+
47+
**Example:**
48+
49+
```md
50+
# my_new_resource
51+
52+
Provides a my new resource.
53+
54+
~> **NOTE:** Using this resource requires using the provider with Terraform Cloud or an instance of Terraform Enterprise at least as recent as v202302-1.
55+
```
56+
57+
58+
If an attribute has a TFE release constraint, add a second sentence to the attribute's description:
59+
60+
```md
61+
## Argument Reference
62+
63+
The following arguments are supported:
64+
65+
* `foo` - (Required) Foo is bar.
66+
* `bar` - (Optional) Bar is foo.
67+
* `foobar` - (Optional) Foobar is barfoo. This attribute requires Terraform Cloud or an instance of Terraform Enterprise at least as recent as `v202302-1`.
68+
```

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ require (
1111
github.com/hashicorp/go-hclog v1.5.0 // indirect
1212
github.com/hashicorp/go-multierror v1.1.1 // indirect
1313
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
14-
github.com/hashicorp/go-slug v0.12.0
15-
github.com/hashicorp/go-tfe v1.32.0
14+
github.com/hashicorp/go-slug v0.12.1
15+
github.com/hashicorp/go-tfe v1.32.1
1616
github.com/hashicorp/go-version v1.6.0
1717
github.com/hashicorp/hcl v1.0.0
1818
github.com/hashicorp/hcl/v2 v2.17.0 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ github.com/hashicorp/go-plugin v1.4.10 h1:xUbmA4jC6Dq163/fWcp8P3JuHilrHHMLNRxzGQ
5454
github.com/hashicorp/go-plugin v1.4.10/go.mod h1:6/1TEzT0eQznvI/gV2CM29DLSkAK/e58mUWKVsPaph0=
5555
github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA=
5656
github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
57-
github.com/hashicorp/go-slug v0.12.0 h1:y1ArGp5RFF85uvD8nq5VZug/bup/kGN5Ft4xFOQ5GPM=
58-
github.com/hashicorp/go-slug v0.12.0/go.mod h1:JZVtycnZZbiJ4oxpJ/zfhyfBD8XxT4f0uOSyjNLCqFY=
59-
github.com/hashicorp/go-tfe v1.32.0 h1:wyUQJHPrqF5IwD5Y4YJFTlU3A08LXoJ2PLF7x80febU=
60-
github.com/hashicorp/go-tfe v1.32.0/go.mod h1:vcfy2u52JQ4sYLFi941qcQXQYfUq2RjEW466tZ+m97Y=
57+
github.com/hashicorp/go-slug v0.12.1 h1:lYhmKXXonP4KGSz3JBmks6YpDRjP1cMA/yvcoPxoNw8=
58+
github.com/hashicorp/go-slug v0.12.1/go.mod h1:JZVtycnZZbiJ4oxpJ/zfhyfBD8XxT4f0uOSyjNLCqFY=
59+
github.com/hashicorp/go-tfe v1.32.1 h1:5G84t70g70xWK5U0WaYb8wLfbC5fR6dvawqCkmMN5X0=
60+
github.com/hashicorp/go-tfe v1.32.1/go.mod h1:Js4M/3kv14oTBlvLxqh0bbrWfosmNsEb9ad9YazsyfM=
6161
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
6262
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
6363
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ nav:
1515
- Testing: testing.md
1616
- Introducing Beta Features: beta.md
1717
- Debugging: debugging.md
18+
- Backwards Compatibility: backwards-compatibility.md
1819
- Acceptance Tests: writing-acceptance-tests.md
1920
- Changelog Process: changelog-process.md
2021

tfe/resource_tfe_team_project_access.go

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -310,29 +310,34 @@ func resourceTFETeamProjectAccessRead(ctx context.Context, d *schema.ResourceDat
310310
d.Set("project_id", "")
311311
}
312312

313-
project_access := []map[string]interface{}{{
314-
"settings": tmAccess.ProjectAccess.ProjectSettingsPermission,
315-
"teams": tmAccess.ProjectAccess.ProjectTeamsPermission,
316-
}}
317-
318-
workspace_access := []map[string]interface{}{{
319-
"state_versions": tmAccess.WorkspaceAccess.WorkspaceStateVersionsPermission,
320-
"sentinel_mocks": tmAccess.WorkspaceAccess.WorkspaceSentinelMocksPermission,
321-
"runs": tmAccess.WorkspaceAccess.WorkspaceRunsPermission,
322-
"variables": tmAccess.WorkspaceAccess.WorkspaceVariablesPermission,
323-
"create": tmAccess.WorkspaceAccess.WorkspaceCreatePermission,
324-
"locking": tmAccess.WorkspaceAccess.WorkspaceLockingPermission,
325-
"move": tmAccess.WorkspaceAccess.WorkspaceMovePermission,
326-
"delete": tmAccess.WorkspaceAccess.WorkspaceDeletePermission,
327-
"run_tasks": tmAccess.WorkspaceAccess.WorkspaceRunTasksPermission,
328-
}}
329-
330-
if err := d.Set("project_access", project_access); err != nil {
331-
return diag.Errorf("Error setting configuration of team project access %s: %v", d.Id(), err)
332-
}
333-
334-
if err := d.Set("workspace_access", workspace_access); err != nil {
335-
return diag.Errorf("Error setting configuration of team workspace access %s: %v", d.Id(), err)
313+
// These two fields are only available in TFC and TFE v202308-1 and later
314+
if tmAccess.ProjectAccess != nil {
315+
project_access := []map[string]interface{}{{
316+
"settings": tmAccess.ProjectAccess.ProjectSettingsPermission,
317+
"teams": tmAccess.ProjectAccess.ProjectTeamsPermission,
318+
}}
319+
320+
if err := d.Set("project_access", project_access); err != nil {
321+
return diag.Errorf("Error setting configuration of team project access %s: %v", d.Id(), err)
322+
}
323+
}
324+
325+
if tmAccess.WorkspaceAccess != nil {
326+
workspace_access := []map[string]interface{}{{
327+
"state_versions": tmAccess.WorkspaceAccess.WorkspaceStateVersionsPermission,
328+
"sentinel_mocks": tmAccess.WorkspaceAccess.WorkspaceSentinelMocksPermission,
329+
"runs": tmAccess.WorkspaceAccess.WorkspaceRunsPermission,
330+
"variables": tmAccess.WorkspaceAccess.WorkspaceVariablesPermission,
331+
"create": tmAccess.WorkspaceAccess.WorkspaceCreatePermission,
332+
"locking": tmAccess.WorkspaceAccess.WorkspaceLockingPermission,
333+
"move": tmAccess.WorkspaceAccess.WorkspaceMovePermission,
334+
"delete": tmAccess.WorkspaceAccess.WorkspaceDeletePermission,
335+
"run_tasks": tmAccess.WorkspaceAccess.WorkspaceRunTasksPermission,
336+
}}
337+
338+
if err := d.Set("workspace_access", workspace_access); err != nil {
339+
return diag.Errorf("Error setting configuration of team workspace access %s: %v", d.Id(), err)
340+
}
336341
}
337342

338343
return nil

0 commit comments

Comments
 (0)