Skip to content

Commit 05004e3

Browse files
authored
Merge branch 'hashicorp:main' into notificationConfiguration/deliveryResponses
2 parents a77efce + 8ecb40c commit 05004e3

7 files changed

+224
-6
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Unreleased
2+
3+
## Enhancements
4+
25
* 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)
6+
* Adds BETA support for listing `StackDeploymentGroups`, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users by @hwatkins05-hashicorp [#1128](https://github.com/hashicorp/go-tfe/pull/1128)
7+
* Adds BETA support for removing/adding VCS backing for a Stack, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users by @Maed223 [#1131](https://github.com/hashicorp/go-tfe/pull/1131)
38

49
## Enhancements
510

@@ -12,6 +17,10 @@
1217
* Adds BETA support for speculative runs with `Stacks` resources and removes VCS repo validity check on `Stack` creation, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users by @hwatkins05-hashicorp [#1119](https://github.com/hashicorp/go-tfe/pull/1119)
1318
* Adds support for listing team tokens, by @mkam [#1109](https://github.com/hashicorp/go-tfe/pull/1109)
1419

20+
## Bug Fixes
21+
22+
* Fixes hard coded public terraform registry URL for ReadTerraformRegistryModule, by @paladin-devops [#1126](https://github.com/hashicorp/go-tfe/pull/1126)
23+
1524
# v1.81.0
1625

1726
## Enhancements

registry_module.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -635,18 +635,17 @@ func (r *registryModules) Read(ctx context.Context, moduleID RegistryModuleID) (
635635
return rm, nil
636636
}
637637

638-
// ReadRegistry fetches a registry module from the Terraform Registry.
638+
// ReadTerraformRegistryModule fetches a registry module from the Terraform Registry.
639639
func (r *registryModules) ReadTerraformRegistryModule(ctx context.Context, moduleID RegistryModuleID, version string) (*TerraformRegistryModule, error) {
640-
u := fmt.Sprintf(
641-
"https://app.terraform.io/api/registry/v1/modules/%s/%s/%s/%s",
640+
u := fmt.Sprintf("api/registry/v1/modules/%s/%s/%s/%s",
642641
moduleID.Namespace,
643642
moduleID.Name,
644643
moduleID.Provider,
645644
version,
646645
)
646+
647647
if moduleID.RegistryName == PublicRegistry {
648-
u = fmt.Sprintf(
649-
"https://app.terraform.io/api/registry/public/v1/modules/%s/%s/%s/%s",
648+
u = fmt.Sprintf("api/registry/public/v1/modules/%s/%s/%s/%s",
650649
moduleID.Namespace,
651650
moduleID.Name,
652651
moduleID.Provider,

stack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ type StackCreateOptions struct {
191191
type StackUpdateOptions struct {
192192
Name *string `jsonapi:"attr,name,omitempty"`
193193
Description *string `jsonapi:"attr,description,omitempty"`
194-
VCSRepo *StackVCSRepoOptions `jsonapi:"attr,vcs-repo,omitempty"`
194+
VCSRepo *StackVCSRepoOptions `jsonapi:"attr,vcs-repo"`
195195
}
196196

197197
// WaitForStatusResult is the data structure that is sent over the channel

stack_deployment_groups.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package tfe
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/url"
7+
)
8+
9+
// StackDeploymentGroups describes all the stack-deployment-groups related methods that the HCP Terraform API supports.
10+
type StackDeploymentGroups interface {
11+
// List returns a list of Deployment Groups in a stack.
12+
List(ctx context.Context, stackConfigID string, options *StackDeploymentGroupListOptions) (*StackDeploymentGroupList, error)
13+
}
14+
15+
type DeploymentGroupStatus string
16+
17+
const (
18+
DeploymentGroupStatusPending DeploymentGroupStatus = "pending"
19+
DeploymentGroupStatusDeploying DeploymentGroupStatus = "deploying"
20+
DeploymentGroupStatusSucceeded DeploymentGroupStatus = "succeeded"
21+
DeploymentGroupStatusFailed DeploymentGroupStatus = "failed"
22+
DeploymentGroupStatusAbandoned DeploymentGroupStatus = "abandoned"
23+
)
24+
25+
// stackDeploymentGroups implements StackDeploymentGroups.
26+
type stackDeploymentGroups struct {
27+
client *Client
28+
}
29+
30+
var _ StackDeploymentGroups = &stackDeploymentGroups{}
31+
32+
// StackDeploymentGroup represents a stack deployment group.
33+
type StackDeploymentGroup struct {
34+
ID string `jsonapi:"primary,stacks-deployment-groups"`
35+
Name string `jsonapi:"attr,name"`
36+
Status DeploymentGroupStatus `jsonapi:"attr,status"`
37+
CreatedAt string `jsonapi:"attr,created-at"`
38+
UpdatedAt string `jsonapi:"attr,updated-at"`
39+
40+
// Relationships
41+
StackConfiguration StackConfiguration `jsonapi:"relation,stack-configurations"`
42+
}
43+
44+
// StackDeploymentGroupList represents a list of stack deployment groups.
45+
type StackDeploymentGroupList struct {
46+
*Pagination
47+
Items []*StackDeploymentGroup
48+
}
49+
50+
// StackDeploymentGroupListOptions represents additional options when listing stack deployment groups.
51+
type StackDeploymentGroupListOptions struct {
52+
ListOptions
53+
}
54+
55+
// List returns a list of Deployment Groups in a stack, optionally filtered by additional parameters.
56+
func (s stackDeploymentGroups) List(ctx context.Context, stackConfigID string, options *StackDeploymentGroupListOptions) (*StackDeploymentGroupList, error) {
57+
if !validStringID(&stackConfigID) {
58+
return nil, fmt.Errorf("invalid stack configuration ID: %s", stackConfigID)
59+
}
60+
61+
if options == nil {
62+
options = &StackDeploymentGroupListOptions{}
63+
}
64+
65+
req, err := s.client.NewRequest("GET", fmt.Sprintf("stack-configurations/%s/stack-deployment-groups", url.PathEscape(stackConfigID)), options)
66+
if err != nil {
67+
return nil, err
68+
}
69+
70+
sdgl := &StackDeploymentGroupList{}
71+
err = req.Do(ctx, sdgl)
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
return sdgl, nil
77+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package tfe
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestStackDeploymentGroupsList(t *testing.T) {
12+
skipUnlessBeta(t)
13+
client := testClient(t)
14+
ctx := context.Background()
15+
16+
orgTest, orgTestCleanup := createOrganization(t, client)
17+
t.Cleanup(orgTestCleanup)
18+
19+
oauthClient, cleanup := createOAuthClient(t, client, orgTest, nil)
20+
t.Cleanup(cleanup)
21+
22+
stack, err := client.Stacks.Create(ctx, StackCreateOptions{
23+
Name: "test-stack",
24+
VCSRepo: &StackVCSRepoOptions{
25+
Identifier: "hashicorp-guides/pet-nulls-stack",
26+
OAuthTokenID: oauthClient.OAuthTokens[0].ID,
27+
},
28+
Project: &Project{
29+
ID: orgTest.DefaultProject.ID,
30+
},
31+
})
32+
33+
require.NoError(t, err)
34+
require.NotNil(t, stack)
35+
36+
stackUpdated, err := client.Stacks.UpdateConfiguration(ctx, stack.ID)
37+
require.NoError(t, err)
38+
require.NotNil(t, stackUpdated)
39+
require.NotEmpty(t, stackUpdated.LatestStackConfiguration.ID)
40+
41+
stackUpdated = pollStackDeployments(t, ctx, client, stackUpdated.ID)
42+
require.NotNil(t, stackUpdated.LatestStackConfiguration)
43+
44+
t.Run("List with valid stack configuration ID", func(t *testing.T) {
45+
sdgl, err := client.StackDeploymentGroups.List(ctx, stackUpdated.LatestStackConfiguration.ID, nil)
46+
require.NoError(t, err)
47+
require.NotNil(t, sdgl)
48+
for _, item := range sdgl.Items {
49+
assert.NotNil(t, item.ID)
50+
assert.NotEmpty(t, item.Name)
51+
assert.NotEmpty(t, item.Status)
52+
assert.NotNil(t, item.CreatedAt)
53+
assert.NotNil(t, item.UpdatedAt)
54+
}
55+
require.Len(t, sdgl.Items, 2)
56+
})
57+
58+
t.Run("List with invalid stack configuration ID", func(t *testing.T) {
59+
_, err := client.StackDeploymentGroups.List(ctx, "", nil)
60+
require.Error(t, err)
61+
})
62+
63+
t.Run("List with pagination", func(t *testing.T) {
64+
options := &StackDeploymentGroupListOptions{
65+
ListOptions: ListOptions{
66+
PageNumber: 1,
67+
PageSize: 1,
68+
},
69+
}
70+
sdgl, err := client.StackDeploymentGroups.List(ctx, stackUpdated.LatestStackConfiguration.ID, options)
71+
require.NoError(t, err)
72+
require.NotNil(t, sdgl)
73+
require.Len(t, sdgl.Items, 1)
74+
})
75+
}

stack_integration_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ func TestStackReadUpdateDelete(t *testing.T) {
169169

170170
stackUpdated, err := client.Stacks.Update(ctx, stack.ID, StackUpdateOptions{
171171
Description: String("updated description"),
172+
VCSRepo: &StackVCSRepoOptions{
173+
Identifier: "brandonc/pet-nulls-stack",
174+
OAuthTokenID: oauthClient.OAuthTokens[0].ID,
175+
Branch: "main",
176+
},
172177
})
173178

174179
require.NoError(t, err)
@@ -186,6 +191,52 @@ func TestStackReadUpdateDelete(t *testing.T) {
186191
require.Nil(t, stackReadAfterDelete)
187192
}
188193

194+
func TestStackRemoveVCSBacking(t *testing.T) {
195+
skipUnlessBeta(t)
196+
197+
client := testClient(t)
198+
ctx := context.Background()
199+
200+
orgTest, orgTestCleanup := createOrganization(t, client)
201+
t.Cleanup(orgTestCleanup)
202+
203+
oauthClient, cleanup := createOAuthClient(t, client, orgTest, nil)
204+
t.Cleanup(cleanup)
205+
206+
stack, err := client.Stacks.Create(ctx, StackCreateOptions{
207+
Name: "test-stack",
208+
VCSRepo: &StackVCSRepoOptions{
209+
Identifier: "brandonc/pet-nulls-stack",
210+
OAuthTokenID: oauthClient.OAuthTokens[0].ID,
211+
Branch: "main",
212+
},
213+
Project: &Project{
214+
ID: orgTest.DefaultProject.ID,
215+
},
216+
})
217+
218+
require.NoError(t, err)
219+
require.NotNil(t, stack)
220+
require.NotEmpty(t, stack.VCSRepo.Identifier)
221+
require.NotEmpty(t, stack.VCSRepo.OAuthTokenID)
222+
require.NotEmpty(t, stack.VCSRepo.Branch)
223+
224+
stackRead, err := client.Stacks.Read(ctx, stack.ID, nil)
225+
require.NoError(t, err)
226+
require.Equal(t, stack.VCSRepo.Identifier, stackRead.VCSRepo.Identifier)
227+
require.Equal(t, stack.VCSRepo.OAuthTokenID, stackRead.VCSRepo.OAuthTokenID)
228+
require.Equal(t, stack.VCSRepo.Branch, stackRead.VCSRepo.Branch)
229+
230+
assert.Equal(t, stack, stackRead)
231+
232+
stackUpdated, err := client.Stacks.Update(ctx, stack.ID, StackUpdateOptions{
233+
VCSRepo: nil,
234+
})
235+
236+
require.NoError(t, err)
237+
require.Nil(t, stackUpdated.VCSRepo)
238+
}
239+
189240
func TestStackReadUpdateForceDelete(t *testing.T) {
190241
skipUnlessBeta(t)
191242

@@ -226,6 +277,11 @@ func TestStackReadUpdateForceDelete(t *testing.T) {
226277

227278
stackUpdated, err := client.Stacks.Update(ctx, stack.ID, StackUpdateOptions{
228279
Description: String("updated description"),
280+
VCSRepo: &StackVCSRepoOptions{
281+
Identifier: "brandonc/pet-nulls-stack",
282+
OAuthTokenID: oauthClient.OAuthTokens[0].ID,
283+
Branch: "main",
284+
},
229285
})
230286

231287
require.NoError(t, err)

tfe.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ type Client struct {
164164
Stacks Stacks
165165
StackConfigurations StackConfigurations
166166
StackDeployments StackDeployments
167+
StackDeploymentGroups StackDeploymentGroups
167168
StackPlans StackPlans
168169
StackPlanOperations StackPlanOperations
169170
StackSources StackSources
@@ -492,6 +493,7 @@ func NewClient(cfg *Config) (*Client, error) {
492493
client.Stacks = &stacks{client: client}
493494
client.StackConfigurations = &stackConfigurations{client: client}
494495
client.StackDeployments = &stackDeployments{client: client}
496+
client.StackDeploymentGroups = &stackDeploymentGroups{client: client}
495497
client.StackPlans = &stackPlans{client: client}
496498
client.StackPlanOperations = &stackPlanOperations{client: client}
497499
client.StackSources = &stackSources{client: client}

0 commit comments

Comments
 (0)