Skip to content

Commit

Permalink
backend/remote: add the run ID to associate state
Browse files Browse the repository at this point in the history
If a run ID is available, we need to make sure we pass that when creating a new state version so the state will be properly associated with the run.
  • Loading branch information
Sander van Harmelen committed Sep 8, 2018
1 parent 62ab84a commit a6f9d9f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 1 deletion.
4 changes: 4 additions & 0 deletions backend/remote/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net/url"
"os"
"sort"
"strings"
"sync"
Expand Down Expand Up @@ -278,6 +279,9 @@ func (b *Remote) State(workspace string) (state.State, error) {
client: b.client,
organization: b.organization,
workspace: workspace,

// This is optionally set during Terraform Enterprise runs.
runID: os.Getenv("TFE_RUN_ID"),
}

return &remote.State{Client: client}, nil
Expand Down
5 changes: 5 additions & 0 deletions backend/remote/backend_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,13 @@ func (m *mockStateVersions) List(ctx context.Context, options tfe.StateVersionLi

func (m *mockStateVersions) Create(ctx context.Context, workspaceID string, options tfe.StateVersionCreateOptions) (*tfe.StateVersion, error) {
id := generateID("sv-")
runID := os.Getenv("TFE_RUN_ID")
url := fmt.Sprintf("https://app.terraform.io/_archivist/%s", id)

if runID != "" && (options.Run == nil || runID != options.Run.ID) {
return nil, fmt.Errorf("option.Run.ID does not contain the ID exported by TFE_RUN_ID")
}

sv := &tfe.StateVersion{
ID: id,
DownloadURL: url,
Expand Down
9 changes: 8 additions & 1 deletion backend/remote/backend_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type remoteClient struct {
client *tfe.Client
organization string
runID string
workspace string
}

Expand Down Expand Up @@ -70,7 +71,7 @@ func (r *remoteClient) Put(state []byte) error {
return fmt.Errorf("Error retrieving workspace: %v", err)
}

// the state into a buffer.
// Read the raw state into a Terraform state.
tfState, err := terraform.ReadState(bytes.NewReader(state))
if err != nil {
return fmt.Errorf("Error reading state: %s", err)
Expand All @@ -83,6 +84,12 @@ func (r *remoteClient) Put(state []byte) error {
State: tfe.String(base64.StdEncoding.EncodeToString(state)),
}

// If we have a run ID, make sure to add it to the options
// so the state will be properly associated with the run.
if r.runID != "" {
options.Run = &tfe.Run{ID: r.runID}
}

// Create the new state.
_, err = r.client.StateVersions.Create(ctx, w.ID, options)
if err != nil {
Expand Down
24 changes: 24 additions & 0 deletions backend/remote/backend_state_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package remote

import (
"os"
"testing"

"github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/state/remote"
"github.com/hashicorp/terraform/terraform"
)

func TestRemoteClient_impl(t *testing.T) {
Expand All @@ -14,3 +17,24 @@ func TestRemoteClient(t *testing.T) {
client := testRemoteClient(t)
remote.TestClient(t, client)
}

func TestRemoteClient_withRunID(t *testing.T) {
b := testBackendDefault(t)

if err := os.Setenv("TFE_RUN_ID", generateID("run-")); err != nil {
t.Fatalf("error setting env var TFE_RUN_ID: %v", err)
}

client, err := b.State(backend.DefaultStateName)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}

if err = client.WriteState(terraform.NewState()); err != nil {
t.Fatalf("expected no error, got %v", err)
}

if err = client.PersistState(); err != nil {
t.Fatalf("expected no error, got %v", err)
}
}

0 comments on commit a6f9d9f

Please sign in to comment.