Skip to content

Commit 9f56096

Browse files
Merge branch 'main' into hw/approve-deployment-group
2 parents 436d5ce + 95b83f4 commit 9f56096

7 files changed

+326
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Enhancements
44

55
* Adds BETA support for approving all plans for a stack deployment run, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users by @ctrombley [#1136](https://github.com/hashicorp/go-tfe/pull/1136)
6+
* Adds BETA support for listing and reading `StackDeploymentSteps`, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users by @ctrombley [#1133](https://github.com/hashicorp/go-tfe/pull/1133)
67
* Adds BETA support for approving all plans in `StackDeploymentGroups`, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users by @hwatkins05-hashicorp [#1137](https://github.com/hashicorp/go-tfe/pull/1137)
78

89
# v1.83.0

stack_deployment_groups.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
14
package tfe
25

36
import (
@@ -38,6 +41,7 @@ var _ StackDeploymentGroups = &stackDeploymentGroups{}
3841

3942
// StackDeploymentGroup represents a stack deployment group.
4043
type StackDeploymentGroup struct {
44+
// Attributes
4145
ID string `jsonapi:"primary,stacks-deployment-groups"`
4246
Name string `jsonapi:"attr,name"`
4347
Status string `jsonapi:"attr,status"`

stack_deployment_runs.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
type StackDeploymentRuns interface {
1515
// List returns a list of stack deployment runs for a given deployment group.
1616
List(ctx context.Context, deploymentGroupID string, options *StackDeploymentRunListOptions) (*StackDeploymentRunList, error)
17+
Read(ctx context.Context, stackDeploymentRunID string) (*StackDeploymentRun, error)
1718
ApproveAllPlans(ctx context.Context, deploymentRunID string) error
1819
}
1920

@@ -62,6 +63,21 @@ func (s *stackDeploymentRuns) List(ctx context.Context, deploymentGroupID string
6263
return sdrl, nil
6364
}
6465

66+
func (s stackDeploymentRuns) Read(ctx context.Context, stackDeploymentRunID string) (*StackDeploymentRun, error) {
67+
req, err := s.client.NewRequest("GET", fmt.Sprintf("stack-deployment-runs/%s", url.PathEscape(stackDeploymentRunID)), nil)
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
run := StackDeploymentRun{}
73+
err = req.Do(ctx, &run)
74+
if err != nil {
75+
return nil, err
76+
}
77+
78+
return &run, nil
79+
}
80+
6581
func (s stackDeploymentRuns) ApproveAllPlans(ctx context.Context, stackDeploymentRunID string) error {
6682
req, err := s.client.NewRequest("POST", fmt.Sprintf("stack-deployment-runs/%s/approve-all-plans", url.PathEscape(stackDeploymentRunID)), nil)
6783
if err != nil {

stack_deployment_runs_integration_test.go

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestStackDeploymentRunsList(t *testing.T) {
7373
})
7474
}
7575

76-
func TestStackDeploymentRunsApproveAllPlans(t *testing.T) {
76+
func TestStackDeploymentRunsRead(t *testing.T) {
7777
skipUnlessBeta(t)
7878

7979
client := testClient(t)
@@ -86,15 +86,67 @@ func TestStackDeploymentRunsApproveAllPlans(t *testing.T) {
8686
t.Cleanup(cleanup)
8787

8888
stack, err := client.Stacks.Create(ctx, StackCreateOptions{
89-
Name: "test-stack",
89+
Project: orgTest.DefaultProject,
90+
Name: "test-stack",
9091
VCSRepo: &StackVCSRepoOptions{
91-
// Identifier: "hashicorp-guides/pet-nulls-stack",
92-
Identifier: "ctrombley/tf-stacks-pet-nulls",
92+
Identifier: "hashicorp-guides/pet-nulls-stack",
9393
OAuthTokenID: oauthClient.OAuthTokens[0].ID,
9494
Branch: "main",
9595
},
96-
Project: &Project{
97-
ID: orgTest.DefaultProject.ID,
96+
})
97+
require.NoError(t, err)
98+
require.NotNil(t, stack)
99+
100+
stackUpdated, err := client.Stacks.UpdateConfiguration(ctx, stack.ID)
101+
require.NoError(t, err)
102+
require.NotNil(t, stackUpdated)
103+
104+
stack = pollStackDeployments(t, ctx, client, stackUpdated.ID)
105+
require.NotNil(t, stack.LatestStackConfiguration)
106+
107+
stackDeploymentGroups, err := client.StackDeploymentGroups.List(ctx, stack.LatestStackConfiguration.ID, nil)
108+
require.NoError(t, err)
109+
require.NotEmpty(t, stackDeploymentGroups)
110+
111+
sdg := stackDeploymentGroups.Items[0]
112+
113+
stackDeploymentRuns, err := client.StackDeploymentRuns.List(ctx, sdg.ID, nil)
114+
require.NoError(t, err)
115+
require.NotEmpty(t, stackDeploymentRuns)
116+
117+
sdr := stackDeploymentGroups.Items[0]
118+
119+
t.Run("Read with valid ID", func(t *testing.T) {
120+
run, err := client.StackDeploymentRuns.Read(ctx, sdr.ID)
121+
assert.NoError(t, err)
122+
assert.NotNil(t, run)
123+
})
124+
125+
t.Run("Read with invalid ID", func(t *testing.T) {
126+
_, err := client.StackDeploymentRuns.Read(ctx, "")
127+
assert.Error(t, err)
128+
})
129+
}
130+
131+
func TestStackDeploymentRunsApproveAllPlans(t *testing.T) {
132+
skipUnlessBeta(t)
133+
134+
client := testClient(t)
135+
ctx := context.Background()
136+
137+
orgTest, orgTestCleanup := createOrganization(t, client)
138+
t.Cleanup(orgTestCleanup)
139+
140+
oauthClient, cleanup := createOAuthClient(t, client, orgTest, nil)
141+
t.Cleanup(cleanup)
142+
143+
stack, err := client.Stacks.Create(ctx, StackCreateOptions{
144+
Project: orgTest.DefaultProject,
145+
Name: "test-stack",
146+
VCSRepo: &StackVCSRepoOptions{
147+
Identifier: "hashicorp-guides/pet-nulls-stack",
148+
OAuthTokenID: oauthClient.OAuthTokens[0].ID,
149+
Branch: "main",
98150
},
99151
})
100152
require.NoError(t, err)

stack_deployment_steps.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package tfe
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"net/url"
10+
"time"
11+
)
12+
13+
// StackDeploymentSteps describes all the stacks deployment step-related methods that the
14+
// HCP Terraform API supports.
15+
// NOTE WELL: This is a beta feature and is subject to change until noted otherwise in the
16+
// release notes.
17+
type StackDeploymentSteps interface {
18+
// List returns the stack deployment steps for a stack deployment run.
19+
List(ctx context.Context, stackDeploymentRunID string, opts *StackDeploymentStepsListOptions) (*StackDeploymentStepList, error)
20+
Read(ctx context.Context, stackDeploymentStepID string) (*StackDeploymentStep, error)
21+
}
22+
23+
// StackDeploymentStep represents a step from a stack deployment
24+
type StackDeploymentStep struct {
25+
// Attributes
26+
ID string `jsonapi:"primary,stacks-deployment-steps"`
27+
Status string `jsonapi:"attr,status"`
28+
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
29+
UpdatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
30+
31+
// Relationships
32+
StackDeploymentRun *StackDeploymentRun `jsonapi:"relation,stack-deployment-run"`
33+
}
34+
35+
// StackDeploymentStepList represents a list of stack deployment steps
36+
type StackDeploymentStepList struct {
37+
*Pagination
38+
Items []*StackDeploymentStep
39+
}
40+
41+
type stackDeploymentSteps struct {
42+
client *Client
43+
}
44+
45+
// StackDeploymentStepsListOptions represents the options for listing stack
46+
// deployment steps.
47+
type StackDeploymentStepsListOptions struct {
48+
ListOptions
49+
}
50+
51+
func (s stackDeploymentSteps) List(ctx context.Context, stackDeploymentRunID string, opts *StackDeploymentStepsListOptions) (*StackDeploymentStepList, error) {
52+
req, err := s.client.NewRequest("GET", fmt.Sprintf("stack-deployment-runs/%s/stack-deployment-steps", url.PathEscape(stackDeploymentRunID)), opts)
53+
if err != nil {
54+
return nil, err
55+
}
56+
57+
steps := StackDeploymentStepList{}
58+
err = req.Do(ctx, &steps)
59+
if err != nil {
60+
return nil, err
61+
}
62+
63+
return &steps, nil
64+
}
65+
66+
func (s stackDeploymentSteps) Read(ctx context.Context, stackDeploymentStepID string) (*StackDeploymentStep, error) {
67+
req, err := s.client.NewRequest("GET", fmt.Sprintf("stack-deployment-steps/%s", url.PathEscape(stackDeploymentStepID)), nil)
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
step := StackDeploymentStep{}
73+
err = req.Do(ctx, &step)
74+
if err != nil {
75+
return nil, err
76+
}
77+
78+
return &step, nil
79+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package tfe
5+
6+
import (
7+
"context"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestStackDeploymentStepsList(t *testing.T) {
15+
skipUnlessBeta(t)
16+
17+
client := testClient(t)
18+
ctx := context.Background()
19+
20+
orgTest, orgTestCleanup := createOrganization(t, client)
21+
t.Cleanup(orgTestCleanup)
22+
23+
oauthClient, cleanup := createOAuthClient(t, client, orgTest, nil)
24+
t.Cleanup(cleanup)
25+
26+
stack, err := client.Stacks.Create(ctx, StackCreateOptions{
27+
Project: orgTest.DefaultProject,
28+
Name: "test-stack",
29+
VCSRepo: &StackVCSRepoOptions{
30+
Identifier: "hashicorp-guides/pet-nulls-stack",
31+
OAuthTokenID: oauthClient.OAuthTokens[0].ID,
32+
Branch: "main",
33+
},
34+
})
35+
require.NoError(t, err)
36+
require.NotNil(t, stack)
37+
38+
stackUpdated, err := client.Stacks.UpdateConfiguration(ctx, stack.ID)
39+
require.NoError(t, err)
40+
require.NotNil(t, stackUpdated)
41+
42+
stack = pollStackDeployments(t, ctx, client, stackUpdated.ID)
43+
require.NotNil(t, stack.LatestStackConfiguration)
44+
45+
stackDeploymentGroups, err := client.StackDeploymentGroups.List(ctx, stack.LatestStackConfiguration.ID, nil)
46+
require.NoError(t, err)
47+
require.NotEmpty(t, stackDeploymentGroups)
48+
49+
sdg := stackDeploymentGroups.Items[0]
50+
51+
stackDeploymentRuns, err := client.StackDeploymentRuns.List(ctx, sdg.ID, nil)
52+
require.NoError(t, err)
53+
require.NotEmpty(t, stackDeploymentRuns)
54+
55+
sdr := stackDeploymentRuns.Items[0]
56+
57+
t.Run("List with invalid stack deployment run ID", func(t *testing.T) {
58+
t.Parallel()
59+
60+
_, err := client.StackDeploymentSteps.List(ctx, "", nil)
61+
assert.Error(t, err)
62+
})
63+
64+
t.Run("List without options", func(t *testing.T) {
65+
t.Parallel()
66+
67+
steps, err := client.StackDeploymentSteps.List(ctx, sdr.ID, nil)
68+
assert.NoError(t, err)
69+
assert.NotEmpty(t, steps)
70+
71+
step := steps.Items[0]
72+
73+
assert.NotNil(t, step)
74+
assert.NotNil(t, step.ID)
75+
assert.NotNil(t, step.Status)
76+
77+
require.NotNil(t, step.StackDeploymentRun)
78+
assert.Equal(t, sdg.ID, step.StackDeploymentRun.ID)
79+
})
80+
81+
t.Run("List with pagination", func(t *testing.T) {
82+
t.Parallel()
83+
84+
steps, err := client.StackDeploymentSteps.List(ctx, sdr.ID, &StackDeploymentStepsListOptions{
85+
ListOptions: ListOptions{
86+
PageNumber: 1,
87+
PageSize: 10,
88+
},
89+
})
90+
assert.NoError(t, err)
91+
assert.NotEmpty(t, steps)
92+
93+
step := steps.Items[0]
94+
95+
assert.NotNil(t, step)
96+
assert.NotNil(t, step.ID)
97+
assert.NotNil(t, step.Status)
98+
99+
require.NotNil(t, step.StackDeploymentRun)
100+
assert.Equal(t, sdg.ID, step.StackDeploymentRun.ID)
101+
})
102+
}
103+
104+
func TestStackDeploymentStepsRead(t *testing.T) {
105+
skipUnlessBeta(t)
106+
107+
client := testClient(t)
108+
ctx := context.Background()
109+
110+
orgTest, orgTestCleanup := createOrganization(t, client)
111+
t.Cleanup(orgTestCleanup)
112+
113+
oauthClient, cleanup := createOAuthClient(t, client, orgTest, nil)
114+
t.Cleanup(cleanup)
115+
116+
stack, err := client.Stacks.Create(ctx, StackCreateOptions{
117+
Project: orgTest.DefaultProject,
118+
Name: "test-stack",
119+
VCSRepo: &StackVCSRepoOptions{
120+
Identifier: "hashicorp-guides/pet-nulls-stack",
121+
OAuthTokenID: oauthClient.OAuthTokens[0].ID,
122+
Branch: "main",
123+
},
124+
})
125+
require.NoError(t, err)
126+
require.NotNil(t, stack)
127+
128+
stackUpdated, err := client.Stacks.UpdateConfiguration(ctx, stack.ID)
129+
require.NoError(t, err)
130+
require.NotNil(t, stackUpdated)
131+
132+
stack = pollStackDeployments(t, ctx, client, stackUpdated.ID)
133+
require.NotNil(t, stack.LatestStackConfiguration)
134+
135+
stackDeploymentGroups, err := client.StackDeploymentGroups.List(ctx, stack.LatestStackConfiguration.ID, nil)
136+
require.NoError(t, err)
137+
require.NotEmpty(t, stackDeploymentGroups)
138+
139+
sdg := stackDeploymentGroups.Items[0]
140+
141+
stackDeploymentRuns, err := client.StackDeploymentRuns.List(ctx, sdg.ID, nil)
142+
require.NoError(t, err)
143+
require.NotEmpty(t, stackDeploymentRuns)
144+
145+
sdr := stackDeploymentRuns.Items[0]
146+
147+
steps, err := client.StackDeploymentSteps.List(ctx, sdr.ID, nil)
148+
assert.NoError(t, err)
149+
assert.NotEmpty(t, steps)
150+
151+
step := steps.Items[0]
152+
153+
t.Run("Read with valid ID", func(t *testing.T) {
154+
sds, err := client.StackDeploymentSteps.Read(ctx, step.ID)
155+
assert.NoError(t, err)
156+
assert.NotEmpty(t, sds.ID)
157+
assert.NotEmpty(t, sds.Status)
158+
})
159+
160+
t.Run("Read with invalid ID", func(t *testing.T) {
161+
_, err := client.StackDeploymentSteps.Read(ctx, "")
162+
require.Error(t, err)
163+
})
164+
}

0 commit comments

Comments
 (0)