Skip to content

Commit 9a7226a

Browse files
authored
Use workspace-level default for enable_serverless_compute if not specified in databricks_sql_global_config (#3279)
* work * test * computed * WIP * work * fix tests * Do not reset serverless when deleting * acquire lock in test * address feedback
1 parent f6ec7c8 commit 9a7226a

File tree

4 files changed

+222
-52
lines changed

4 files changed

+222
-52
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ require (
3333
github.com/google/go-cmp v0.6.0 // indirect
3434
github.com/google/go-querystring v1.1.0 // indirect
3535
github.com/google/s2a-go v0.1.7 // indirect
36+
github.com/google/uuid v1.6.0 // indirect
3637
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
3738
github.com/hashicorp/errwrap v1.1.0 // indirect
3839
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,83 @@
11
package acceptance
22

33
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"strconv"
8+
"strings"
49
"testing"
10+
11+
"github.com/databricks/databricks-sdk-go/qa/lock"
12+
"github.com/databricks/databricks-sdk-go/qa/lock/core"
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
14+
"github.com/stretchr/testify/assert"
15+
"github.com/stretchr/testify/require"
516
)
617

18+
type SqlGlobalConfigLock struct {
19+
WorkspaceHost string
20+
}
21+
22+
func (s SqlGlobalConfigLock) GetLockId() string {
23+
return fmt.Sprintf("WorkspaceHost:%s;type=SqlGlobalConfig", strings.ReplaceAll(s.WorkspaceHost, "/", "_"))
24+
}
25+
26+
func getSqlGlobalConfigLockable(t *testing.T) core.Lockable {
27+
return lock.NewLockable(SqlGlobalConfigLock{WorkspaceHost: GetEnvOrSkipTest(t, "DATABRICKS_HOST")})
28+
}
29+
30+
func makeSqlGlobalConfig(extraConfig string) string {
31+
return fmt.Sprintf(`
32+
resource "databricks_sql_global_config" "this" {
33+
data_access_config = {
34+
"spark.sql.session.timeZone": "UTC"
35+
}
36+
%s
37+
}`, extraConfig)
38+
}
39+
740
func TestAccSQLGlobalConfig(t *testing.T) {
41+
loadDebugEnvIfRunsFromIDE(t, "workspace")
42+
workspaceLevel(t, step{
43+
PreConfig: func() {
44+
ctx := context.Background()
45+
_, err := lock.Acquire(ctx, getSqlGlobalConfigLockable(t), lock.InTest(t))
46+
require.NoError(t, err)
47+
},
48+
Template: makeSqlGlobalConfig(""),
49+
})
50+
}
51+
52+
func TestAccSQLGlobalConfigServerless(t *testing.T) {
53+
loadDebugEnvIfRunsFromIDE(t, "workspace")
54+
if strings.Contains(os.Getenv("CLOUD_ENV"), "gcp") {
55+
skipf(t)("GCP does not support serverless compute")
56+
}
57+
58+
checkServerlessEnabled := func(enabled bool) func(state *terraform.State) error {
59+
return func(state *terraform.State) error {
60+
enableServerlessComputeStr := state.Modules[0].Resources["databricks_sql_global_config.this"].Primary.Attributes["enable_serverless_compute"]
61+
enableServerlessCompute, err := strconv.ParseBool(enableServerlessComputeStr)
62+
require.NoError(t, err)
63+
assert.Equal(t, enabled, enableServerlessCompute)
64+
return nil
65+
}
66+
}
67+
868
workspaceLevel(t, step{
9-
Template: `resource "databricks_sql_global_config" "this" {
10-
data_access_config = {
11-
"spark.sql.session.timeZone": "UTC"
12-
}
13-
}`,
69+
PreConfig: func() {
70+
ctx := context.Background()
71+
_, err := lock.Acquire(ctx, getSqlGlobalConfigLockable(t), lock.InTest(t))
72+
require.NoError(t, err)
73+
},
74+
Template: makeSqlGlobalConfig("enable_serverless_compute = true"),
75+
Check: checkServerlessEnabled(true),
76+
}, step{
77+
Template: makeSqlGlobalConfig(""),
78+
Check: checkServerlessEnabled(true),
79+
}, step{
80+
Template: makeSqlGlobalConfig("enable_serverless_compute = false"),
81+
Check: checkServerlessEnabled(false),
1482
})
1583
}

sql/resource_sql_global_config.go

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66

7+
"github.com/databricks/databricks-sdk-go/marshal"
78
"github.com/databricks/terraform-provider-databricks/common"
89

910
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -28,7 +29,7 @@ type GlobalConfig struct {
2829
DataAccessConfig map[string]string `json:"data_access_config,omitempty"`
2930
InstanceProfileARN string `json:"instance_profile_arn,omitempty"`
3031
GoogleServiceAccount string `json:"google_service_account,omitempty"`
31-
EnableServerlessCompute bool `json:"enable_serverless_compute,omitempty" tf:"default:false"`
32+
EnableServerlessCompute bool `json:"enable_serverless_compute,omitempty" tf:"computed"`
3233
SqlConfigParams map[string]string `json:"sql_config_params,omitempty"`
3334
}
3435

@@ -38,8 +39,17 @@ type GlobalConfigForRead struct {
3839
DataAccessConfig []confPair `json:"data_access_config"`
3940
InstanceProfileARN string `json:"instance_profile_arn,omitempty"`
4041
GoogleServiceAccount string `json:"google_service_account,omitempty"`
41-
EnableServerlessCompute bool `json:"enable_serverless_compute"`
42+
EnableServerlessCompute bool `json:"enable_serverless_compute,omitempty"`
4243
SqlConfigurationParameters *repeatedEndpointConfPairs `json:"sql_configuration_parameters,omitempty"`
44+
ForceSendFields []string `json:"-"`
45+
}
46+
47+
func (g GlobalConfigForRead) MarshalJSON() ([]byte, error) {
48+
return marshal.Marshal(g)
49+
}
50+
51+
func (g *GlobalConfigForRead) UnmarshalJSON(bs []byte) error {
52+
return marshal.Unmarshal(bs, g)
4353
}
4454

4555
func NewSqlGlobalConfigAPI(ctx context.Context, m any) globalConfigAPI {
@@ -51,10 +61,10 @@ type globalConfigAPI struct {
5161
context context.Context
5262
}
5363

54-
func (a globalConfigAPI) Set(gc GlobalConfig) error {
55-
data := map[string]any{
56-
"security_policy": gc.SecurityPolicy,
57-
"enable_serverless_compute": gc.EnableServerlessCompute,
64+
func (a globalConfigAPI) Set(gc GlobalConfig, d *schema.ResourceData) error {
65+
data := GlobalConfigForRead{
66+
SecurityPolicy: gc.SecurityPolicy,
67+
EnableServerlessCompute: gc.EnableServerlessCompute,
5868
}
5969
if a.client.Config.Host == "" {
6070
err := a.client.Config.EnsureResolved()
@@ -64,14 +74,14 @@ func (a globalConfigAPI) Set(gc GlobalConfig) error {
6474
}
6575
if gc.InstanceProfileARN != "" {
6676
if a.client.IsAws() {
67-
data["instance_profile_arn"] = gc.InstanceProfileARN
77+
data.InstanceProfileARN = gc.InstanceProfileARN
6878
} else {
6979
return fmt.Errorf("can't use instance_profile_arn outside of AWS")
7080
}
7181
}
7282
if gc.GoogleServiceAccount != "" {
7383
if a.client.IsGcp() {
74-
data["google_service_account"] = gc.GoogleServiceAccount
84+
data.GoogleServiceAccount = gc.GoogleServiceAccount
7585
} else {
7686
return fmt.Errorf("can't use google_service_account outside of GCP")
7787
}
@@ -80,15 +90,16 @@ func (a globalConfigAPI) Set(gc GlobalConfig) error {
8090
for k, v := range gc.DataAccessConfig {
8191
cfg = append(cfg, confPair{Key: k, Value: v})
8292
}
83-
data["data_access_config"] = cfg
93+
data.DataAccessConfig = cfg
8494
if len(gc.SqlConfigParams) > 0 {
8595
sql_params := repeatedEndpointConfPairs{}
8696
sql_params.ConfigPairs = make([]confPair, 0, len(gc.SqlConfigParams))
8797
for k, v := range gc.SqlConfigParams {
8898
sql_params.ConfigPairs = append(sql_params.ConfigPairs, confPair{Key: k, Value: v})
8999
}
90-
data["sql_configuration_parameters"] = sql_params
100+
data.SqlConfigurationParameters = &sql_params
91101
}
102+
common.SetForceSendFields(&data, d, []string{"enable_serverless_compute"})
92103

93104
return a.client.Put(a.context, "/sql/config/warehouses", data)
94105
}
@@ -121,14 +132,26 @@ func ResourceSqlGlobalConfig() common.Resource {
121132
setGlobalConfig := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error {
122133
var gc GlobalConfig
123134
common.DataToStructPointer(d, s, &gc)
124-
if err := NewSqlGlobalConfigAPI(ctx, c).Set(gc); err != nil {
135+
if err := NewSqlGlobalConfigAPI(ctx, c).Set(gc, d); err != nil {
125136
return err
126137
}
127138
d.SetId(GlobalSqlConfigResourceID)
128139
return nil
129140
}
130141
return common.Resource{
131-
Create: setGlobalConfig,
142+
Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error {
143+
// enable_serverless_compute is an optional boolean parameter which may be specified as `false`.
144+
if _, ok := d.GetOkExists("enable_serverless_compute"); !ok {
145+
// Read the current global config and use the current value of enable_serverless_compute as
146+
// the default value if not specified.
147+
gc, err := NewSqlGlobalConfigAPI(ctx, c).Get()
148+
if err != nil {
149+
return err
150+
}
151+
d.Set("enable_serverless_compute", gc.EnableServerlessCompute)
152+
}
153+
return setGlobalConfig(ctx, d, c)
154+
},
132155
Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error {
133156
gc, err := NewSqlGlobalConfigAPI(ctx, c).Get()
134157
if err != nil {
@@ -139,7 +162,10 @@ func ResourceSqlGlobalConfig() common.Resource {
139162
},
140163
Update: setGlobalConfig,
141164
Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error {
142-
return NewSqlGlobalConfigAPI(ctx, c).Set(GlobalConfig{SecurityPolicy: "DATA_ACCESS_CONTROL"})
165+
return NewSqlGlobalConfigAPI(ctx, c).Set(GlobalConfig{
166+
SecurityPolicy: "DATA_ACCESS_CONTROL",
167+
EnableServerlessCompute: d.Get("enable_serverless_compute").(bool),
168+
}, d)
143169
},
144170
Schema: s,
145171
}

0 commit comments

Comments
 (0)