mirror of https://github.com/databricks/cli.git
Add mutators to pull and push Terraform state (#288)
## Changes Pull state before deploying and push state after deploying. Note: the run command was missing mutators to initialize Terraform. This is necessary if the cache directory is removed between running "deploy" and "run" (which is valid now that we synchronize state). ## Tests Manually.
This commit is contained in:
parent
cb2eb7cad6
commit
04e77102c9
|
@ -2,8 +2,10 @@ package terraform
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/databricks/bricks/bundle"
|
||||
"github.com/hashicorp/terraform-exec/tfexec"
|
||||
)
|
||||
|
||||
type load struct{}
|
||||
|
@ -13,6 +15,16 @@ func (l *load) Name() string {
|
|||
}
|
||||
|
||||
func (l *load) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
||||
tf := b.Terraform
|
||||
if tf == nil {
|
||||
return nil, fmt.Errorf("terraform not initialized")
|
||||
}
|
||||
|
||||
err := tf.Init(ctx, tfexec.Upgrade(true))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("terraform init: %w", err)
|
||||
}
|
||||
|
||||
state, err := b.Terraform.Show(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
package terraform
|
||||
|
||||
const TerraformStateFileName = "terraform.tfstate"
|
|
@ -0,0 +1,62 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/databricks/bricks/bundle"
|
||||
"github.com/databricks/bricks/libs/filer"
|
||||
"github.com/databricks/bricks/libs/log"
|
||||
"github.com/databricks/databricks-sdk-go/apierr"
|
||||
)
|
||||
|
||||
type statePull struct{}
|
||||
|
||||
func (l *statePull) Name() string {
|
||||
return "terraform:state-pull"
|
||||
}
|
||||
|
||||
func (l *statePull) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
||||
f, err := filer.NewWorkspaceFilesClient(b.WorkspaceClient(), b.Config.Workspace.StatePath.Workspace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dir, err := Dir(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Download state file from filer to local cache directory.
|
||||
log.Infof(ctx, "Opening remote state file")
|
||||
remote, err := f.Read(ctx, TerraformStateFileName)
|
||||
if err != nil {
|
||||
// On first deploy this state file doesn't yet exist.
|
||||
if apierr.IsMissing(err) {
|
||||
log.Infof(ctx, "Remote state file does not exist")
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Expect the state file to live under dir.
|
||||
local, err := os.OpenFile(filepath.Join(dir, TerraformStateFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Write file to disk.
|
||||
log.Infof(ctx, "Writing remote state file to local cache directory")
|
||||
_, err = io.Copy(local, remote)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func StatePull() bundle.Mutator {
|
||||
return &statePull{}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/databricks/bricks/bundle"
|
||||
"github.com/databricks/bricks/libs/filer"
|
||||
"github.com/databricks/bricks/libs/log"
|
||||
)
|
||||
|
||||
type statePush struct{}
|
||||
|
||||
func (l *statePush) Name() string {
|
||||
return "terraform:state-push"
|
||||
}
|
||||
|
||||
func (l *statePush) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
||||
f, err := filer.NewWorkspaceFilesClient(b.WorkspaceClient(), b.Config.Workspace.StatePath.Workspace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dir, err := Dir(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Expect the state file to live under dir.
|
||||
local, err := os.Open(filepath.Join(dir, TerraformStateFileName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Upload state file from local cache directory to filer.
|
||||
log.Infof(ctx, "Writing local state file to remote state directory")
|
||||
err = f.Write(ctx, TerraformStateFileName, local, filer.CreateParentDirectories, filer.OverwriteIfExists)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func StatePush() bundle.Mutator {
|
||||
return &statePush{}
|
||||
}
|
|
@ -18,7 +18,9 @@ func Deploy() bundle.Mutator {
|
|||
artifacts.UploadAll(),
|
||||
terraform.Interpolate(),
|
||||
terraform.Write(),
|
||||
terraform.StatePull(),
|
||||
terraform.Apply(),
|
||||
terraform.StatePush(),
|
||||
lock.Release(),
|
||||
},
|
||||
)
|
||||
|
|
|
@ -25,6 +25,9 @@ var runCmd = &cobra.Command{
|
|||
b := bundle.Get(cmd.Context())
|
||||
err := bundle.Apply(cmd.Context(), b, []bundle.Mutator{
|
||||
phases.Initialize(),
|
||||
terraform.Interpolate(),
|
||||
terraform.Write(),
|
||||
terraform.StatePull(),
|
||||
terraform.Load(),
|
||||
})
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue