From 87207bba78f22bb7cd3d8a17e2e00eaaf9ecfa41 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Wed, 29 Mar 2023 20:46:09 +0200 Subject: [PATCH] Configure Terraform provider auth through env vars (#290) ## Changes Auth relied on setting a profile. In this change we enumerate all configuration properties and export all non-empty ones as a map with environment variables. We then pass this map to the Terraform execution wrapper. This results in Terraform using the bundle's authentication configuration. This change is needed to make #287 work. ## Tests Manually. --- bundle/bundle.go | 32 ++++++++++++++++++++++++++++++ bundle/deploy/terraform/convert.go | 1 - bundle/deploy/terraform/init.go | 14 +++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/bundle/bundle.go b/bundle/bundle.go index fd746824..e9ec55cc 100644 --- a/bundle/bundle.go +++ b/bundle/bundle.go @@ -17,6 +17,7 @@ import ( "github.com/databricks/bricks/libs/git" "github.com/databricks/bricks/libs/locker" "github.com/databricks/databricks-sdk-go" + sdkconfig "github.com/databricks/databricks-sdk-go/config" "github.com/hashicorp/terraform-exec/tfexec" ) @@ -127,3 +128,34 @@ func (b *Bundle) GitRepository() (*git.Repository, error) { return git.NewRepository(rootPath) } + +// AuthEnv returns a map with environment variables and their values +// derived from the workspace client configuration that was resolved +// in the context of this bundle. +// +// This map can be used to configure authentication for tools that +// we call into from this bundle context. +func (b *Bundle) AuthEnv() (map[string]string, error) { + if b.client == nil { + return nil, fmt.Errorf("workspace client not initialized yet") + } + + cfg := b.client.Config + out := make(map[string]string) + for _, attr := range sdkconfig.ConfigAttributes { + // Ignore profile so that downstream tools don't try and reload + // the profile even though we know the current configuration is valid. + if attr.Name == "profile" { + continue + } + if len(attr.EnvVars) == 0 { + continue + } + if attr.IsZero(cfg) { + continue + } + out[attr.EnvVars[0]] = attr.GetString(cfg) + } + + return out, nil +} diff --git a/bundle/deploy/terraform/convert.go b/bundle/deploy/terraform/convert.go index 1b1f9271..a9baa76b 100644 --- a/bundle/deploy/terraform/convert.go +++ b/bundle/deploy/terraform/convert.go @@ -52,7 +52,6 @@ func convPermission(ac resources.Permission) schema.ResourcePermissionsAccessCon func BundleToTerraform(config *config.Root) *schema.Root { tfroot := schema.NewRoot() tfroot.Provider = schema.NewProviders() - tfroot.Provider.Databricks.Profile = config.Workspace.Profile tfroot.Resource = schema.NewResources() for k, src := range config.Resources.Jobs { diff --git a/bundle/deploy/terraform/init.go b/bundle/deploy/terraform/init.go index f2f0a81e..6debcc69 100644 --- a/bundle/deploy/terraform/init.go +++ b/bundle/deploy/terraform/init.go @@ -6,6 +6,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" "github.com/databricks/bricks/bundle" "github.com/databricks/bricks/bundle/config" @@ -14,6 +15,7 @@ import ( "github.com/hashicorp/hc-install/product" "github.com/hashicorp/hc-install/releases" "github.com/hashicorp/terraform-exec/tfexec" + "golang.org/x/exp/maps" ) type initialize struct{} @@ -89,6 +91,18 @@ func (m *initialize) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Muta return nil, err } + env, err := b.AuthEnv() + if err != nil { + return nil, err + } + + // Configure environment variables for auth for Terraform to use. + log.Debugf(ctx, "Environment variables for Terraform: %s", strings.Join(maps.Keys(env), ", ")) + err = tf.SetEnv(env) + if err != nil { + return nil, err + } + b.Terraform = tf return nil, nil }