Skip to content

Commit

Permalink
Merge branch 'main' into hashimoon/terraform-test-validations
Browse files Browse the repository at this point in the history
  • Loading branch information
hashimoon committed Nov 6, 2023
2 parents b9a7941 + a245d58 commit b3769d2
Show file tree
Hide file tree
Showing 13 changed files with 653 additions and 41 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# UNRELEASED
<!-- Add CHANGELOG entry to this section for any PR awaiting the next release -->
<!-- Please also include if this is a Bug Fix, Enhancement, or Feature -->

## Features
* New WorkspaceSettingOverwritesOptions field for allowing workspaces to defer some settings to a default from their organization or project by @SwiftEngineer [#762](https://github.com/hashicorp/go-tfe/pull/762)
* Added support for setting a default execution mode and agent pool at the organization level by @SwiftEngineer [#762](https://github.com/hashicorp/go-tfe/pull/762)

## Features
* Removed BETA labels for StateVersion Upload method, ConfigurationVersion `provisional` field, and `save-plan` runs by @brandonc [#800](https://github.com/hashicorp/go-tfe/pull/800)
* Allow soft deleting, restoring, and permanently deleting StateVersion and ConfigurationVersion backing data by @mwudka [#801](https://github.com/hashicorp/go-tfe/pull/801)

# v.1.38.0

Expand Down
38 changes: 38 additions & 0 deletions configuration_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ type ConfigurationVersions interface {

// Download a configuration version. Only configuration versions in the uploaded state may be downloaded.
Download(ctx context.Context, cvID string) ([]byte, error)

// SoftDeleteBackingData soft deletes the configuration version's backing data
// **Note: This functionality is only available in Terraform Enterprise.**
SoftDeleteBackingData(ctx context.Context, svID string) error

// RestoreBackingData restores a soft deleted configuration version's backing data
// **Note: This functionality is only available in Terraform Enterprise.**
RestoreBackingData(ctx context.Context, svID string) error

// PermanentlyDeleteBackingData permanently deletes a soft deleted configuration version's backing data
// **Note: This functionality is only available in Terraform Enterprise.**
PermanentlyDeleteBackingData(ctx context.Context, svID string) error
}

// configurationVersions implements ConfigurationVersions.
Expand Down Expand Up @@ -356,3 +368,29 @@ func (s *configurationVersions) Download(ctx context.Context, cvID string) ([]by

return buf.Bytes(), nil
}

func (s *configurationVersions) SoftDeleteBackingData(ctx context.Context, cvID string) error {
return s.manageBackingData(ctx, cvID, "soft_delete_backing_data")
}

func (s *configurationVersions) RestoreBackingData(ctx context.Context, cvID string) error {
return s.manageBackingData(ctx, cvID, "restore_backing_data")
}

func (s *configurationVersions) PermanentlyDeleteBackingData(ctx context.Context, cvID string) error {
return s.manageBackingData(ctx, cvID, "permanently_delete_backing_data")
}

func (s *configurationVersions) manageBackingData(ctx context.Context, cvID, action string) error {
if !validStringID(&cvID) {
return ErrInvalidConfigVersionID
}

u := fmt.Sprintf("configuration-versions/%s/actions/%s", cvID, action)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return err
}

return req.Do(ctx, nil)
}
46 changes: 46 additions & 0 deletions configuration_version_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,49 @@ func TestConfigurationVersions_Unmarshal(t *testing.T) {
assert.Equal(t, cv.Provisional, true)
assert.Equal(t, cv.Speculative, true)
}

func TestConfigurationVersions_ManageBackingData(t *testing.T) {
skipUnlessEnterprise(t)

client := testClient(t)
ctx := context.Background()

workspace, workspaceCleanup := createWorkspace(t, client, nil)
t.Cleanup(workspaceCleanup)

nonCurrentCv, uploadedCvCleanup := createUploadedConfigurationVersion(t, client, workspace)
defer uploadedCvCleanup()

_, uploadedCvCleanup = createUploadedConfigurationVersion(t, client, workspace)
defer uploadedCvCleanup()

t.Run("soft delete backing data", func(t *testing.T) {
err := client.ConfigurationVersions.SoftDeleteBackingData(ctx, nonCurrentCv.ID)
require.NoError(t, err)

_, err = client.ConfigurationVersions.Download(ctx, nonCurrentCv.ID)
assert.Equal(t, ErrResourceNotFound, err)
})

t.Run("restore backing data", func(t *testing.T) {
err := client.ConfigurationVersions.RestoreBackingData(ctx, nonCurrentCv.ID)
require.NoError(t, err)

_, err = client.ConfigurationVersions.Download(ctx, nonCurrentCv.ID)
require.NoError(t, err)
})

t.Run("permanently delete backing data", func(t *testing.T) {
err := client.ConfigurationVersions.SoftDeleteBackingData(ctx, nonCurrentCv.ID)
require.NoError(t, err)

err = client.ConfigurationVersions.PermanentlyDeleteBackingData(ctx, nonCurrentCv.ID)
require.NoError(t, err)

err = client.ConfigurationVersions.RestoreBackingData(ctx, nonCurrentCv.ID)
require.ErrorContainsf(t, err, "transition not allowed", "Restore backing data should fail")

_, err = client.ConfigurationVersions.Download(ctx, nonCurrentCv.ID)
assert.Equal(t, ErrResourceNotFound, err)
})
}
72 changes: 72 additions & 0 deletions examples/backing_data/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package main

import (
"context"
"flag"
"fmt"
tfe "github.com/hashicorp/go-tfe"
"log"
"strings"
)

func main() {
action := flag.String("action", "", "Action (soft-delete|restore|permanently-delete")
externalId := flag.String("external-id", "", "External ID of StateVersion or ConfigurationVersion")

flag.Parse()

if action == nil || *action == "" {
log.Fatal("No Action provided")
}

if externalId == nil || *externalId == "" {
log.Fatal("No external ID provided")
}

ctx := context.Background()
client, err := tfe.NewClient(&tfe.Config{
RetryServerErrors: true,
})
if err != nil {
log.Fatal(err)
}

err = performAction(ctx, client, *action, *externalId)
if err != nil {
log.Fatalf("Error performing action: %v", err)
}
}

func performAction(ctx context.Context, client *tfe.Client, action string, id string) error {
externalIdParts := strings.Split(id, "-")
switch externalIdParts[0] {
case "cv":
switch action {
case "soft-delete":
return client.ConfigurationVersions.SoftDeleteBackingData(ctx, id)
case "restore":
return client.ConfigurationVersions.RestoreBackingData(ctx, id)
case "permanently-delete":
return client.ConfigurationVersions.PermanentlyDeleteBackingData(ctx, id)
default:
return fmt.Errorf("unsupported action: %s", action)
}
case "sv":
switch action {
case "soft-delete":
return client.StateVersions.SoftDeleteBackingData(ctx, id)
case "restore":
return client.StateVersions.RestoreBackingData(ctx, id)
case "permanently-delete":
return client.StateVersions.PermanentlyDeleteBackingData(ctx, id)
default:
return fmt.Errorf("unsupported action: %s", action)
}
default:
return fmt.Errorf("unsupported external ID: %s", id)
}
return nil
}
24 changes: 24 additions & 0 deletions helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,30 @@ func createOrganizationWithOptions(t *testing.T, client *Client, options Organiz
}
}

func createOrganizationWithDefaultAgentPool(t *testing.T, client *Client) (*Organization, func()) {
ctx := context.Background()
org, orgCleanup := createOrganizationWithOptions(t, client, OrganizationCreateOptions{
Name: String("tst-" + randomString(t)),
Email: String(fmt.Sprintf("%s@tfe.local", randomString(t))),
CostEstimationEnabled: Bool(true),
})

agentPool, _ := createAgentPool(t, client, org)

org, err := client.Organizations.Update(ctx, org.Name, OrganizationUpdateOptions{
DefaultExecutionMode: String("agent"),
DefaultAgentPool: agentPool,
})

if err != nil {
t.Fatal(err)
}

return org, func() {
// delete the org
orgCleanup()
}
}
func createOrganizationMembership(t *testing.T, client *Client, org *Organization) (*OrganizationMembership, func()) {
var orgCleanup func()

Expand Down
42 changes: 42 additions & 0 deletions mocks/configuration_version_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions mocks/state_version_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ type Organization struct {
CollaboratorAuthPolicy AuthPolicyType `jsonapi:"attr,collaborator-auth-policy"`
CostEstimationEnabled bool `jsonapi:"attr,cost-estimation-enabled"`
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
DefaultExecutionMode string `jsonapi:"attr,default-execution-mode"`
Email string `jsonapi:"attr,email"`
ExternalID string `jsonapi:"attr,external-id"`
OwnersTeamSAMLRoleID string `jsonapi:"attr,owners-team-saml-role-id"`
Expand All @@ -90,7 +91,8 @@ type Organization struct {
AllowForceDeleteWorkspaces bool `jsonapi:"attr,allow-force-delete-workspaces"`

// Relations
DefaultProject *Project `jsonapi:"relation,default-project"`
DefaultProject *Project `jsonapi:"relation,default-project"`
DefaultAgentPool *AgentPool `jsonapi:"relation,default-agent-pool"`
}

// OrganizationIncludeOpt represents the available options for include query params.
Expand Down Expand Up @@ -198,6 +200,9 @@ type OrganizationCreateOptions struct {

// Optional: AllowForceDeleteWorkspaces toggles behavior of allowing workspace admins to delete workspaces with resources under management.
AllowForceDeleteWorkspaces *bool `jsonapi:"attr,allow-force-delete-workspaces,omitempty"`

// Optional: DefaultExecutionMode the default execution mode for workspaces
DefaultExecutionMode *string `jsonapi:"attr,default-execution-mode,omitempty"`
}

// OrganizationUpdateOptions represents the options for updating an organization.
Expand Down Expand Up @@ -237,6 +242,12 @@ type OrganizationUpdateOptions struct {

// Optional: AllowForceDeleteWorkspaces toggles behavior of allowing workspace admins to delete workspaces with resources under management.
AllowForceDeleteWorkspaces *bool `jsonapi:"attr,allow-force-delete-workspaces,omitempty"`

// Optional: DefaultExecutionMode the default execution mode for workspaces
DefaultExecutionMode *string `jsonapi:"attr,default-execution-mode,omitempty"`

// Optional: DefaultAgentPoolId default agent pool for workspaces, requires DefaultExecutionMode to be set to `agent`
DefaultAgentPool *AgentPool `jsonapi:"relation,default-agent-pool,omitempty"`
}

// ReadRunQueueOptions represents the options for showing the queue.
Expand Down
Loading

0 comments on commit b3769d2

Please sign in to comment.