Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Unreleased

## Enhancements
* Exports the StackConfiguration UploadTarGzip receiver function[#1219](https://github.com/hashicorp/go-tfe/pull/1219)
* Exports the StackConfiguration UploadTarGzip receiver function [#1219](https://github.com/hashicorp/go-tfe/pull/1219)
* Updates BETA stacks resource schemas to match latest API spec by @ctrombley [#1220](https://github.com/hashicorp/go-tfe/pull/1220)

## Deprecations

Expand Down
84 changes: 40 additions & 44 deletions stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type Stacks interface {
List(ctx context.Context, organization string, options *StackListOptions) (*StackList, error)

// Read returns a stack by its ID.
Read(ctx context.Context, stackID string, options *StackReadOptions) (*Stack, error)
Read(ctx context.Context, stackID string) (*Stack, error)

// Create creates a new stack.
Create(ctx context.Context, options StackCreateOptions) (*Stack, error)
Expand All @@ -32,8 +32,8 @@ type Stacks interface {
// ForceDelete deletes a stack.
ForceDelete(ctx context.Context, stackID string) error

// UpdateConfiguration updates the configuration of a stack, triggering stack preparation.
UpdateConfiguration(ctx context.Context, stackID string) (*Stack, error)
// FetchLatestFromVcs updates the configuration of a stack, triggering stack preparation.
FetchLatestFromVcs(ctx context.Context, stackID string) (*Stack, error)
}

// stacks implements Stacks.
Expand Down Expand Up @@ -88,17 +88,18 @@ type Stack struct {
ID string `jsonapi:"primary,stacks"`
Name string `jsonapi:"attr,name"`
Description string `jsonapi:"attr,description"`
DeploymentNames []string `jsonapi:"attr,deployment-names"`
VCSRepo *StackVCSRepo `jsonapi:"attr,vcs-repo"`
ErrorsCount int `jsonapi:"attr,errors-count"`
WarningsCount int `jsonapi:"attr,warnings-count"`
SpeculativeEnabled bool `jsonapi:"attr,speculative-enabled"`
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
UpdatedAt time.Time `jsonapi:"attr,updated-at,iso8601"`
UpstreamCount int `jsonapi:"attr,upstream-count"`
DownstreamCount int `jsonapi:"attr,downstream-count"`
InputsCount int `jsonapi:"attr,inputs-count"`
OutputsCount int `jsonapi:"attr,outputs-count"`

// Relationships
AgentPool *AgentPool `jsonapi:"relation,agent-pool"`
Project *Project `jsonapi:"relation,project"`
AgentPool *AgentPool `jsonapi:"relation,agent-pool"`
LatestStackConfiguration *StackConfiguration `jsonapi:"relation,latest-stack-configuration"`
}

Expand All @@ -117,54 +118,49 @@ type StackComponent struct {
Name string `json:"name"`
Correlator string `json:"correlator"`
Expanded bool `json:"expanded"`
Removed bool `json:"removed"`
}

// StackConfiguration represents a stack configuration snapshot
type StackConfiguration struct {
// Attributes
ID string `jsonapi:"primary,stack-configurations"`
Status string `jsonapi:"attr,status"`
StatusTimestamps *StackConfigurationStatusTimestamps `jsonapi:"attr,status-timestamps"`
SequenceNumber int `jsonapi:"attr,sequence-number"`
DeploymentNames []string `jsonapi:"attr,deployment-names"`
ConvergedDeployments []string `jsonapi:"attr,converged-deployments"`
Components []*StackComponent `jsonapi:"attr,components"`
ErrorMessage *string `jsonapi:"attr,error-message"`
EventStreamURL string `jsonapi:"attr,event-stream-url"`
Diagnostics []*StackDiagnostic `jsonapi:"attr,diags"`
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
UpdatedAt time.Time `jsonapi:"attr,updated-at,iso8601"`

Stack *Stack `jsonapi:"relation,stack"`
ID string `jsonapi:"primary,stack-configurations"`
Status string `jsonapi:"attr,status"`
SequenceNumber int `jsonapi:"attr,sequence-number"`
Components []*StackComponent `jsonapi:"attr,components"`
PreparingEventStreamURL string `jsonapi:"attr,preparing-event-stream-url"`
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
UpdatedAt time.Time `jsonapi:"attr,updated-at,iso8601"`
Speculative bool `jsonapi:"attr,speculative"`

// Relationships
Stack *Stack `jsonapi:"relation,stack"`
IngressAttributes *IngressAttributes `jsonapi:"relation,ingress-attributes"`
}

// StackState represents a stack state
type StackState struct {
// Attributes
ID string `jsonapi:"primary,stack-states"`
}

// StackIncludeOpt represents the include options for a stack.
type StackIncludeOpt string
ID string `jsonapi:"primary,stack-states"`
Description string `jsonapi:"attr,description"`
Generation int `jsonapi:"attr,generation"`
Status string `jsonapi:"attr,status"`
Deployment string `jsonapi:"attr,deployment"`
Components string `jsonapi:"attr,components"`
IsCurrent bool `jsonapi:"attr,is-current"`
ResourceInstanceCount int `jsonapi:"attr,resource-instance-count"`

const (
StackIncludeOrganization StackIncludeOpt = "organization"
StackIncludeProject StackIncludeOpt = "project"
StackIncludeLatestStackConfiguration StackIncludeOpt = "latest_stack_configuration"
StackIncludeStackDiagnostics StackIncludeOpt = "stack_diagnostics"
)
// Relationships
Stack *Stack `jsonapi:"relation,stack"`
StackDeploymentRun *StackDeploymentRun `jsonapi:"relation,stack-deployment-run"`
}

// StackListOptions represents the options for listing stacks.
type StackListOptions struct {
ListOptions
ProjectID string `url:"filter[project[id]],omitempty"`
Sort StackSortColumn `url:"sort,omitempty"`
SearchByName string `url:"search[name],omitempty"`
Include []StackIncludeOpt `url:"include,omitempty"`
}

type StackReadOptions struct {
Include []StackIncludeOpt `url:"include,omitempty"`
ProjectID string `url:"filter[project[id]],omitempty"`
Sort StackSortColumn `url:"sort,omitempty"`
SearchByName string `url:"search[name],omitempty"`
}

// StackCreateOptions represents the options for creating a stack. The project
Expand Down Expand Up @@ -202,8 +198,8 @@ type WaitForStatusResult struct {
const minimumPollingIntervalMs = 3000
const maximumPollingIntervalMs = 5000

// UpdateConfiguration fetches the latest configuration of a stack from VCS, triggering stack operations
func (s *stacks) UpdateConfiguration(ctx context.Context, stackID string) (*Stack, error) {
// FetchLatestFromVcs fetches the latest configuration of a stack from VCS, triggering stack operations
func (s *stacks) FetchLatestFromVcs(ctx context.Context, stackID string) (*Stack, error) {
req, err := s.client.NewRequest("POST", fmt.Sprintf("stacks/%s/fetch-latest-from-vcs", url.PathEscape(stackID)), nil)
if err != nil {
return nil, err
Expand Down Expand Up @@ -239,8 +235,8 @@ func (s stacks) List(ctx context.Context, organization string, options *StackLis
}

// Read returns a stack by its ID.
func (s stacks) Read(ctx context.Context, stackID string, options *StackReadOptions) (*Stack, error) {
req, err := s.client.NewRequest("GET", fmt.Sprintf("stacks/%s", url.PathEscape(stackID)), options)
func (s stacks) Read(ctx context.Context, stackID string) (*Stack, error) {
req, err := s.client.NewRequest("GET", fmt.Sprintf("stacks/%s", url.PathEscape(stackID)), nil)
if err != nil {
return nil, err
}
Expand Down
4 changes: 1 addition & 3 deletions stack_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ const (
StackConfigurationStatusQueued StackConfigurationStatus = "queued"
StackConfigurationStatusPreparing StackConfigurationStatus = "preparing"
StackConfigurationStatusEnqueueing StackConfigurationStatus = "enqueueing"
StackConfigurationStatusConverged StackConfigurationStatus = "converged"
StackConfigurationStatusConverging StackConfigurationStatus = "converging"
StackConfigurationStatusErrored StackConfigurationStatus = "errored"
StackConfigurationStatusCanceled StackConfigurationStatus = "canceled"
StackConfigurationStatusCompleted StackConfigurationStatus = "completed"
Expand Down Expand Up @@ -117,7 +115,7 @@ func (s stackConfigurations) AwaitCompleted(ctx context.Context, stackConfigurat
}

return stackConfiguration.Status, nil
}, []string{StackConfigurationStatusConverged.String(), StackConfigurationStatusConverging.String(), StackConfigurationStatusCompleted.String(), StackConfigurationStatusErrored.String(), StackConfigurationStatusCanceled.String()})
}, []string{StackConfigurationStatusCompleted.String(), StackConfigurationStatusErrored.String(), StackConfigurationStatusCanceled.String()})
}

// AwaitStatus generates a channel that will receive the status of the stack configuration as it progresses.
Expand Down
4 changes: 2 additions & 2 deletions stack_configuration_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ func TestStackConfigurationList(t *testing.T) {
require.NoError(t, err)

// Trigger first stack configuration by updating configuration
_, err = client.Stacks.UpdateConfiguration(ctx, stack.ID)
_, err = client.Stacks.FetchLatestFromVcs(ctx, stack.ID)
require.NoError(t, err)

// Wait a bit and trigger second stack configuration
time.Sleep(2 * time.Second)
_, err = client.Stacks.UpdateConfiguration(ctx, stack.ID)
_, err = client.Stacks.FetchLatestFromVcs(ctx, stack.ID)
require.NoError(t, err)

list, err := client.StackConfigurations.List(ctx, stack.ID, nil)
Expand Down
4 changes: 2 additions & 2 deletions stack_configuration_summary_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ func TestStackConfigurationSummaryList(t *testing.T) {
require.NotNil(t, stack2)

// Trigger first stack configuration by updating configuration
_, err = client.Stacks.UpdateConfiguration(ctx, stack2.ID)
_, err = client.Stacks.FetchLatestFromVcs(ctx, stack2.ID)
require.NoError(t, err)

// Wait a bit and trigger second stack configuration
time.Sleep(2 * time.Second)
_, err = client.Stacks.UpdateConfiguration(ctx, stack2.ID)
_, err = client.Stacks.FetchLatestFromVcs(ctx, stack2.ID)
require.NoError(t, err)

t.Run("Successful empty list", func(t *testing.T) {
Expand Down
13 changes: 8 additions & 5 deletions stack_deployment_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ type StackDeploymentGroups interface {
type DeploymentGroupStatus string

const (
DeploymentGroupStatusPending DeploymentGroupStatus = "pending"
DeploymentGroupStatusDeploying DeploymentGroupStatus = "deploying"
DeploymentGroupStatusSucceeded DeploymentGroupStatus = "succeeded"
DeploymentGroupStatusFailed DeploymentGroupStatus = "failed"
DeploymentGroupStatusAbandoned DeploymentGroupStatus = "abandoned"
DeploymentGroupStatusPending DeploymentGroupStatus = "pending"
DeploymentGroupStatusPreDeploying DeploymentGroupStatus = "pre-deploying"
DeploymentGroupStatusPreDeployingPendingOperator DeploymentGroupStatus = "pending-operator"
DeploymentGroupStatusAcquiringLock DeploymentGroupStatus = "acquiring-lock"
DeploymentGroupStatusDeploying DeploymentGroupStatus = "deploying"
DeploymentGroupStatusSucceeded DeploymentGroupStatus = "succeeded"
DeploymentGroupStatusFailed DeploymentGroupStatus = "failed"
DeploymentGroupStatusAbandoned DeploymentGroupStatus = "abandoned"
)

// stackDeploymentGroups implements StackDeploymentGroups.
Expand Down
27 changes: 13 additions & 14 deletions stack_deployment_groups_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,12 @@ func TestStackDeploymentGroupsList(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, stack)

stackUpdated, err := client.Stacks.UpdateConfiguration(ctx, stack.ID)
stackUpdated, err := client.Stacks.FetchLatestFromVcs(ctx, stack.ID)
require.NoError(t, err)
require.NotNil(t, stackUpdated)
require.NotEmpty(t, stackUpdated.LatestStackConfiguration.ID)

stackUpdated = pollStackDeployments(t, ctx, client, stackUpdated.ID)
require.NotNil(t, stackUpdated.LatestStackConfiguration)
stackUpdated = pollStackDeploymentGroups(t, ctx, client, stackUpdated.ID)
require.NotEmpty(t, stackUpdated.LatestStackConfiguration.ID)

t.Run("List with valid stack configuration ID", func(t *testing.T) {
sdgl, err := client.StackDeploymentGroups.List(ctx, stackUpdated.LatestStackConfiguration.ID, nil)
Expand Down Expand Up @@ -102,11 +101,11 @@ func TestStackDeploymentGroupsRead(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, stack)

stackUpdated, err := client.Stacks.UpdateConfiguration(ctx, stack.ID)
stackUpdated, err := client.Stacks.FetchLatestFromVcs(ctx, stack.ID)
require.NoError(t, err)
require.NotNil(t, stackUpdated)

stackUpdated = pollStackDeployments(t, ctx, client, stackUpdated.ID)
stackUpdated = pollStackDeploymentGroups(t, ctx, client, stackUpdated.ID)
require.NotNil(t, stackUpdated.LatestStackConfiguration)

sdgl, err := client.StackDeploymentGroups.List(ctx, stackUpdated.LatestStackConfiguration.ID, nil)
Expand Down Expand Up @@ -154,15 +153,15 @@ func TestStackDeploymentGroupsApproveAllPlans(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, stack)

stackUpdated, err := client.Stacks.UpdateConfiguration(ctx, stack.ID)
stackUpdated, err := client.Stacks.FetchLatestFromVcs(ctx, stack.ID)
require.NoError(t, err)
require.NotNil(t, stackUpdated)

stack = pollStackDeployments(t, ctx, client, stackUpdated.ID)
require.NotNil(t, stack.LatestStackConfiguration)
stackUpdated = pollStackDeploymentGroups(t, ctx, client, stackUpdated.ID)
require.NotNil(t, stackUpdated.LatestStackConfiguration)

// Get the deployment group ID from the stack configuration
deploymentGroups, err := client.StackDeploymentGroups.List(ctx, stack.LatestStackConfiguration.ID, nil)
deploymentGroups, err := client.StackDeploymentGroups.List(ctx, stackUpdated.LatestStackConfiguration.ID, nil)
require.NoError(t, err)
require.NotNil(t, deploymentGroups)
require.NotEmpty(t, deploymentGroups.Items)
Expand Down Expand Up @@ -201,14 +200,14 @@ func TestStackDeploymentGroupsRerun(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, stack)

stackUpdated, err := client.Stacks.UpdateConfiguration(ctx, stack.ID)
stackUpdated, err := client.Stacks.FetchLatestFromVcs(ctx, stack.ID)
require.NoError(t, err)
require.NotNil(t, stackUpdated)

stack = pollStackDeployments(t, ctx, client, stackUpdated.ID)
require.NotNil(t, stack.LatestStackConfiguration)
stackUpdated = pollStackDeploymentGroups(t, ctx, client, stackUpdated.ID)
require.NotNil(t, stackUpdated.LatestStackConfiguration)

deploymentGroups, err := client.StackDeploymentGroups.List(ctx, stack.LatestStackConfiguration.ID, nil)
deploymentGroups, err := client.StackDeploymentGroups.List(ctx, stackUpdated.LatestStackConfiguration.ID, nil)
require.NoError(t, err)
require.NotNil(t, deploymentGroups)
require.NotEmpty(t, deploymentGroups.Items)
Expand Down
73 changes: 73 additions & 0 deletions stack_deployment_groups_summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package tfe

import (
"context"
"fmt"
"net/url"
)

type StackDeploymentGroupSummaries interface {
// List lists all the stack configuration summaries for a stack.
List(ctx context.Context, configurationID string, options *StackDeploymentGroupSummaryListOptions) (*StackDeploymentGroupSummaryList, error)
}

type stackDeploymentGroupSummaries struct {
client *Client
}

var _ StackDeploymentGroupSummaries = &stackDeploymentGroupSummaries{}

type StackDeploymentGroupSummaryList struct {
*Pagination
Items []*StackDeploymentGroupSummary
}

type StackDeploymentGroupSummaryListOptions struct {
ListOptions
}

type StackDeploymentGroupStatusCounts struct {
Pending int `jsonapi:"attr,pending"`
PreDeploying int `jsonapi:"attr,pre-deploying"`
PreDeployingPendingOperator int `jsonapi:"attr,pending-operator"`
AcquiringLock int `jsonapi:"attr,acquiring-lock"`
Deploying int `jsonapi:"attr,deploying"`
Succeeded int `jsonapi:"attr,succeeded"`
Failed int `jsonapi:"attr,failed"`
Abandoned int `jsonapi:"attr,abandoned"`
}

type StackDeploymentGroupSummary struct {
ID string `jsonapi:"primary,stack-deployment-group-summaries"`

// Attributes
Name string `jsonapi:"attr,name"`
Status string `jsonapi:"attr,status"`
StatusCounts *StackDeploymentGroupStatusCounts `jsonapi:"attr,status-counts"`

// Relationships
StackDeploymentGroup *StackDeploymentGroup `jsonapi:"relation,stack-deployment-group"`
}

func (s stackDeploymentGroupSummaries) List(ctx context.Context, stackID string, options *StackDeploymentGroupSummaryListOptions) (*StackDeploymentGroupSummaryList, error) {
if !validStringID(&stackID) {
return nil, fmt.Errorf("invalid stack ID: %s", stackID)
}

if options == nil {
options = &StackDeploymentGroupSummaryListOptions{}
}

req, err := s.client.NewRequest("GET", fmt.Sprintf("stack-configurations/%s/stack-deployment-group-summaries", url.PathEscape(stackID)), options)
if err != nil {
return nil, err
}

scl := &StackDeploymentGroupSummaryList{}
err = req.Do(ctx, scl)
if err != nil {
return nil, err
}

return scl, nil
}
Loading
Loading