Skip to content

Commit 3b35abc

Browse files
debrin-hcdebrin-og
andauthored
[IPL-7725] Adding Support for Calls to /workspaces/{external_id}/all-vars API Endpoint on HCP Terraform (#1105)
* IPL-7725: Adding support for a new API to list all variables associated with a workspace including variables that inherited from organization and/or project variable sets. The List API does not include variables that are inherited from varsets but not overwritten in the workspace. * [IPL-7725] Adding support for calling the /api/v2/workspaces/{id}/all-vars API and adding integration tests * [IPL-7725] Adding changelog entry * [IPL-7725] Fixing lint issues - adding mock functions for ListAll API --------- Co-authored-by: Amartya Majumdar <[email protected]>
1 parent 7044c10 commit 3b35abc

File tree

5 files changed

+183
-9
lines changed

5 files changed

+183
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Unreleased
2+
* Add support for HCP Terraform `/api/v2/workspaces/{external_id}/all-vars` API endpoint to fetch the list of all variables available to a workspace (include inherited variables from varsets) by @debrin-hc [#1105](https://github.com/hashicorp/go-tfe/pull/1105)
23

34
# v1.82.0
45

helper_test.go

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,19 +2209,48 @@ func createTeamTokenWithOptions(t *testing.T, client *Client, tm *Team, options
22092209
}
22102210

22112211
func createVariable(t *testing.T, client *Client, w *Workspace) (*Variable, func()) {
2212+
options := VariableCreateOptions{
2213+
Key: String(randomString(t)),
2214+
Value: String(randomString(t)),
2215+
Category: Category(CategoryTerraform),
2216+
Description: String(randomString(t)),
2217+
}
2218+
return createVariableWithOptions(t, client, w, options)
2219+
}
2220+
2221+
func createVariableWithOptions(t *testing.T, client *Client, w *Workspace, options VariableCreateOptions) (*Variable, func()) {
22122222
var wCleanup func()
22132223

22142224
if w == nil {
22152225
w, wCleanup = createWorkspace(t, client, nil)
22162226
}
22172227

2228+
if options.Key == nil {
2229+
options.Key = String(randomString(t))
2230+
}
2231+
2232+
if options.Value == nil {
2233+
options.Value = String(randomString(t))
2234+
}
2235+
2236+
if options.Description == nil {
2237+
options.Description = String(randomString(t))
2238+
}
2239+
2240+
if options.Category == nil {
2241+
options.Category = Category(CategoryTerraform)
2242+
}
2243+
2244+
if options.HCL == nil {
2245+
options.HCL = Bool(false)
2246+
}
2247+
2248+
if options.Sensitive == nil {
2249+
options.Sensitive = Bool(false)
2250+
}
2251+
22182252
ctx := context.Background()
2219-
v, err := client.Variables.Create(ctx, w.ID, VariableCreateOptions{
2220-
Key: String(randomString(t)),
2221-
Value: String(randomString(t)),
2222-
Category: Category(CategoryTerraform),
2223-
Description: String(randomString(t)),
2224-
})
2253+
v, err := client.Variables.Create(ctx, w.ID, options)
22252254
if err != nil {
22262255
t.Fatal(err)
22272256
}

mocks/variable_mocks.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

variable.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ var _ Variables = (*variables)(nil)
1717
//
1818
// TFE API docs: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/workspace-variables
1919
type Variables interface {
20-
// List all the variables associated with the given workspace.
20+
// List all the variables associated with the given workspace (doesn't include variables inherited from varsets).
2121
List(ctx context.Context, workspaceID string, options *VariableListOptions) (*VariableList, error)
2222

23+
// ListAll all the variables associated with the given workspace including variables inherited from varsets.
24+
ListAll(ctx context.Context, workspaceID string, options *VariableListOptions) (*VariableList, error)
25+
2326
// Create is used to create a new variable.
2427
Create(ctx context.Context, workspaceID string, options VariableCreateOptions) (*Variable, error)
2528

@@ -128,13 +131,22 @@ type VariableUpdateOptions struct {
128131
Sensitive *bool `jsonapi:"attr,sensitive,omitempty"`
129132
}
130133

131-
// List all the variables associated with the given workspace.
134+
// List all the variables associated with the given workspace (doesn't include variables inherited from varsets).
132135
func (s *variables) List(ctx context.Context, workspaceID string, options *VariableListOptions) (*VariableList, error) {
136+
return s.getList(ctx, workspaceID, options, "workspaces/%s/vars")
137+
}
138+
139+
// ListAll the variables associated with the given workspace including variables inherited from varsets.
140+
func (s *variables) ListAll(ctx context.Context, workspaceID string, options *VariableListOptions) (*VariableList, error) {
141+
return s.getList(ctx, workspaceID, options, "workspaces/%s/all-vars")
142+
}
143+
144+
func (s *variables) getList(ctx context.Context, workspaceID string, options *VariableListOptions, path string) (*VariableList, error) {
133145
if !validStringID(&workspaceID) {
134146
return nil, ErrInvalidWorkspaceID
135147
}
136148

137-
u := fmt.Sprintf("workspaces/%s/vars", url.PathEscape(workspaceID))
149+
u := fmt.Sprintf(path, url.PathEscape(workspaceID))
138150
req, err := s.client.NewRequest("GET", u, options)
139151
if err != nil {
140152
return nil, err

variable_integration_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,123 @@ func TestVariablesList(t *testing.T) {
6161
})
6262
}
6363

64+
func TestVariablesListAll(t *testing.T) {
65+
client := testClient(t)
66+
ctx := context.Background()
67+
68+
orgTest, orgTestCleanup := createOrganization(t, client)
69+
t.Cleanup(orgTestCleanup)
70+
71+
prjTest, prjTestCleanup := createProject(t, client, orgTest)
72+
t.Cleanup(prjTestCleanup)
73+
74+
wTest, wTestCleanup := createWorkspaceWithOptions(t, client, orgTest, WorkspaceCreateOptions{
75+
Name: String(randomString(t)),
76+
Project: prjTest,
77+
})
78+
t.Cleanup(wTestCleanup)
79+
80+
orgVarset, orgVarsetCleanup := createVariableSet(t, client, orgTest, VariableSetCreateOptions{})
81+
t.Cleanup(orgVarsetCleanup)
82+
83+
prjVarset, prjVarsetCleanup := createVariableSet(t, client, orgTest, VariableSetCreateOptions{
84+
Parent: &Parent{
85+
Organization: orgTest,
86+
Project: prjTest,
87+
},
88+
})
89+
t.Cleanup(prjVarsetCleanup)
90+
91+
glVar, glVarCleanup := createVariableSetVariable(t, client, orgVarset, VariableSetVariableCreateOptions{
92+
Key: String("key1"),
93+
Value: String("gl_value1"),
94+
Category: Category(CategoryTerraform),
95+
Description: String(randomString(t)),
96+
})
97+
t.Cleanup(glVarCleanup)
98+
99+
glVarOverwrite, glVarOverwriteCleanup := createVariableSetVariable(t, client, orgVarset, VariableSetVariableCreateOptions{
100+
Key: String("key2"),
101+
Value: String("gl_value2"),
102+
Category: Category(CategoryTerraform),
103+
Description: String(randomString(t)),
104+
})
105+
t.Cleanup(glVarOverwriteCleanup)
106+
107+
prjVar, prjVarCleanup := createVariableSetVariable(t, client, prjVarset, VariableSetVariableCreateOptions{
108+
Key: String("key3"),
109+
Value: String("prj_value3"),
110+
Category: Category(CategoryTerraform),
111+
Description: String(randomString(t)),
112+
})
113+
t.Cleanup(prjVarCleanup)
114+
115+
prjVarOverwrite, prjVarOverwriteCleanup := createVariableSetVariable(t, client, prjVarset, VariableSetVariableCreateOptions{
116+
Key: String("key4"),
117+
Value: String("prj_value4"),
118+
Category: Category(CategoryTerraform),
119+
Description: String(randomString(t)),
120+
})
121+
t.Cleanup(prjVarOverwriteCleanup)
122+
123+
wsVar1, wsVar1Cleanup := createVariableWithOptions(t, client, wTest, VariableCreateOptions{
124+
Key: String("key2"),
125+
Value: String("ws_value2"),
126+
Category: Category(CategoryTerraform),
127+
Description: String(randomString(t)),
128+
})
129+
t.Cleanup(wsVar1Cleanup)
130+
131+
wsVar2, wsVar2Cleanup := createVariableWithOptions(t, client, wTest, VariableCreateOptions{
132+
Key: String("key4"),
133+
Value: String("ws_value4"),
134+
Category: Category(CategoryTerraform),
135+
Description: String(randomString(t)),
136+
})
137+
t.Cleanup(wsVar2Cleanup)
138+
139+
wsVar3, wsVar3Cleanup := createVariableWithOptions(t, client, wTest, VariableCreateOptions{
140+
Key: String("key5"),
141+
Value: String("ws_value5"),
142+
Category: Category(CategoryTerraform),
143+
Description: String(randomString(t)),
144+
})
145+
t.Cleanup(wsVar3Cleanup)
146+
147+
applyVariableSetToWorkspace(t, client, orgVarset.ID, wTest.ID)
148+
applyVariableSetToWorkspace(t, client, prjVarset.ID, wTest.ID)
149+
150+
t.Run("when /workspaces/{external_id}/all-vars API is called", func(t *testing.T) {
151+
vl, err := client.Variables.ListAll(ctx, wTest.ID, nil)
152+
require.NoError(t, err)
153+
assert.NotNilf(t, vl, "expected to get a non-empty variables list")
154+
155+
variableIDToValueMap := make(map[string]string)
156+
for _, variable := range vl.Items {
157+
variableIDToValueMap[variable.ID] = variable.Value
158+
}
159+
assert.Equal(t, len(vl.Items), 5)
160+
assert.NotContains(t, variableIDToValueMap, glVarOverwrite.ID)
161+
assert.NotContains(t, variableIDToValueMap, prjVarOverwrite.ID)
162+
assert.Contains(t, variableIDToValueMap, glVar.ID)
163+
assert.Contains(t, variableIDToValueMap, prjVar.ID)
164+
assert.Contains(t, variableIDToValueMap, wsVar1.ID)
165+
assert.Contains(t, variableIDToValueMap, wsVar2.ID)
166+
assert.Contains(t, variableIDToValueMap, wsVar3.ID)
167+
assert.Equal(t, glVar.Value, variableIDToValueMap[glVar.ID])
168+
assert.Equal(t, prjVar.Value, variableIDToValueMap[prjVar.ID])
169+
assert.Equal(t, wsVar1.Value, variableIDToValueMap[wsVar1.ID])
170+
assert.Equal(t, wsVar2.Value, variableIDToValueMap[wsVar2.ID])
171+
assert.Equal(t, wsVar3.Value, variableIDToValueMap[wsVar3.ID])
172+
})
173+
174+
t.Run("when workspace ID is invalid ID", func(t *testing.T) {
175+
vl, err := client.Variables.ListAll(ctx, badIdentifier, nil)
176+
assert.Nilf(t, vl, "expected variables list to be nil")
177+
assert.EqualError(t, err, ErrInvalidWorkspaceID.Error())
178+
})
179+
}
180+
64181
func TestVariablesCreate(t *testing.T) {
65182
client := testClient(t)
66183
ctx := context.Background()

0 commit comments

Comments
 (0)