diff --git a/VERSION b/VERSION
index c678b02..e7ad390 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.18
\ No newline at end of file
+1.0.19
\ No newline at end of file
diff --git a/api/client.go b/api/client.go
index a561dfb..69d0b74 100644
--- a/api/client.go
+++ b/api/client.go
@@ -56,7 +56,7 @@ type Client interface {
// GetDatabase gets the database by instance resource id and the database name.
GetDatabase(ctx context.Context, databaseName string) (*v1pb.Database, error)
// ListDatabase list the databases.
- ListDatabase(ctx context.Context, instanceID, filter string) ([]*v1pb.Database, error)
+ ListDatabase(ctx context.Context, instanceID, filter string, listAll bool) ([]*v1pb.Database, error)
// UpdateDatabase patches the database.
UpdateDatabase(ctx context.Context, patch *v1pb.Database, updateMasks []string) (*v1pb.Database, error)
// BatchUpdateDatabases batch updates databases.
diff --git a/api/setting.go b/api/setting.go
index b1e9b08..b71ca0e 100644
--- a/api/setting.go
+++ b/api/setting.go
@@ -8,8 +8,6 @@ const (
SettingWorkspaceApproval SettingName = "bb.workspace.approval"
// SettingWorkspaceProfile is the setting name for workspace profile settings.
SettingWorkspaceProfile SettingName = "bb.workspace.profile"
- // SettingWorkspaceExternalApproval is the setting name for workspace external approval config.
- SettingWorkspaceExternalApproval SettingName = "bb.workspace.approval.external"
// SettingDataClassification is the setting name for data classification.
SettingDataClassification SettingName = "bb.workspace.data-classification"
// SettingSemanticTypes is the setting name for semantic types.
diff --git a/client/database.go b/client/database.go
index 65bb474..cc8c74c 100644
--- a/client/database.go
+++ b/client/database.go
@@ -29,7 +29,7 @@ func (c *client) GetDatabase(ctx context.Context, databaseName string) (*v1pb.Da
}
// ListDatabase list all databases.
-func (c *client) ListDatabase(ctx context.Context, parent, filter string) ([]*v1pb.Database, error) {
+func (c *client) ListDatabase(ctx context.Context, parent, filter string, listAll bool) ([]*v1pb.Database, error) {
res := []*v1pb.Database{}
pageToken := ""
startTime := time.Now()
@@ -47,7 +47,7 @@ func (c *client) ListDatabase(ctx context.Context, parent, filter string) ([]*v1
})
pageToken = resp.NextPageToken
- if pageToken == "" {
+ if pageToken == "" || !listAll {
break
}
}
diff --git a/docs/data-sources/instance.md b/docs/data-sources/instance.md
index 5c71752..90c7b43 100644
--- a/docs/data-sources/instance.md
+++ b/docs/data-sources/instance.md
@@ -19,8 +19,13 @@ The instance data source.
- `resource_id` (String) The instance unique resource id.
+### Optional
+
+- `list_all_databases` (Boolean) List all databases in this instance. If false, will only list 500 databases.
+
### Read-Only
+- `activation` (Boolean) Whether assign license for this instance or not.
- `data_sources` (Set of Object) (see [below for nested schema](#nestedatt--data_sources))
- `databases` (Set of String) The databases full name in the resource.
- `engine` (String) The instance engine. Support MYSQL, POSTGRES, TIDB, SNOWFLAKE, CLICKHOUSE, MONGODB, SQLITE, REDIS, ORACLE, SPANNER, MSSQL, REDSHIFT, MARIADB, OCEANBASE.
@@ -39,6 +44,7 @@ The instance data source.
Read-Only:
- `database` (String)
+- `external_secret` (List of Object) (see [below for nested schema](#nestedobjatt--data_sources--external_secret))
- `host` (String)
- `id` (String)
- `password` (String)
@@ -49,4 +55,51 @@ Read-Only:
- `type` (String)
- `username` (String)
+
+### Nested Schema for `data_sources.external_secret`
+
+Read-Only:
+
+- `aws_secrets_manager` (List of Object) (see [below for nested schema](#nestedobjatt--data_sources--external_secret--aws_secrets_manager))
+- `gcp_secret_manager` (List of Object) (see [below for nested schema](#nestedobjatt--data_sources--external_secret--gcp_secret_manager))
+- `vault` (List of Object) (see [below for nested schema](#nestedobjatt--data_sources--external_secret--vault))
+
+
+### Nested Schema for `data_sources.external_secret.aws_secrets_manager`
+
+Read-Only:
+
+- `password_key_name` (String)
+- `secret_name` (String)
+
+
+
+### Nested Schema for `data_sources.external_secret.gcp_secret_manager`
+
+Read-Only:
+
+- `secret_name` (String)
+
+
+
+### Nested Schema for `data_sources.external_secret.vault`
+
+Read-Only:
+
+- `app_role` (List of Object) (see [below for nested schema](#nestedobjatt--data_sources--external_secret--vault--app_role))
+- `engine_name` (String)
+- `password_key_name` (String)
+- `secret_name` (String)
+- `token` (String)
+- `url` (String)
+
+
+### Nested Schema for `data_sources.external_secret.vault.url`
+
+Read-Only:
+
+- `role_id` (String)
+- `secret` (String)
+- `secret_type` (String)
+
diff --git a/docs/data-sources/instance_list.md b/docs/data-sources/instance_list.md
index 22b4d2b..b5e5975 100644
--- a/docs/data-sources/instance_list.md
+++ b/docs/data-sources/instance_list.md
@@ -29,8 +29,8 @@ The instance data source list.
Read-Only:
+- `activation` (Boolean)
- `data_sources` (Set of Object) (see [below for nested schema](#nestedobjatt--instances--data_sources))
-- `databases` (Set of String)
- `engine` (String)
- `engine_version` (String)
- `environment` (String)
@@ -47,6 +47,7 @@ Read-Only:
Read-Only:
- `database` (String)
+- `external_secret` (List of Object) (see [below for nested schema](#nestedobjatt--instances--data_sources--external_secret))
- `host` (String)
- `id` (String)
- `password` (String)
@@ -57,4 +58,51 @@ Read-Only:
- `type` (String)
- `username` (String)
+
+### Nested Schema for `instances.data_sources.external_secret`
+
+Read-Only:
+
+- `aws_secrets_manager` (List of Object) (see [below for nested schema](#nestedobjatt--instances--data_sources--external_secret--aws_secrets_manager))
+- `gcp_secret_manager` (List of Object) (see [below for nested schema](#nestedobjatt--instances--data_sources--external_secret--gcp_secret_manager))
+- `vault` (List of Object) (see [below for nested schema](#nestedobjatt--instances--data_sources--external_secret--vault))
+
+
+### Nested Schema for `instances.data_sources.external_secret.vault`
+
+Read-Only:
+
+- `password_key_name` (String)
+- `secret_name` (String)
+
+
+
+### Nested Schema for `instances.data_sources.external_secret.vault`
+
+Read-Only:
+
+- `secret_name` (String)
+
+
+
+### Nested Schema for `instances.data_sources.external_secret.vault`
+
+Read-Only:
+
+- `app_role` (List of Object) (see [below for nested schema](#nestedobjatt--instances--data_sources--external_secret--vault--app_role))
+- `engine_name` (String)
+- `password_key_name` (String)
+- `secret_name` (String)
+- `token` (String)
+- `url` (String)
+
+
+### Nested Schema for `instances.data_sources.external_secret.vault.app_role`
+
+Read-Only:
+
+- `role_id` (String)
+- `secret` (String)
+- `secret_type` (String)
+
diff --git a/docs/data-sources/setting.md b/docs/data-sources/setting.md
index 920680d..a7b27cb 100644
--- a/docs/data-sources/setting.md
+++ b/docs/data-sources/setting.md
@@ -28,7 +28,6 @@ The setting data source.
### Read-Only
- `approval_flow` (Block List) Configure risk level and approval flow for different tasks. Require ENTERPRISE subscription. (see [below for nested schema](#nestedblock--approval_flow))
-- `external_approval_nodes` (Block List) Configure external nodes in the approval flow. Require ENTERPRISE subscription. (see [below for nested schema](#nestedblock--external_approval_nodes))
- `id` (String) The ID of this resource.
@@ -186,23 +185,3 @@ Read-Only:
- `type` (String)
-
-
-
-
-### Nested Schema for `external_approval_nodes`
-
-Read-Only:
-
-- `nodes` (Set of Object) (see [below for nested schema](#nestedatt--external_approval_nodes--nodes))
-
-
-### Nested Schema for `external_approval_nodes.nodes`
-
-Read-Only:
-
-- `endpoint` (String)
-- `id` (String)
-- `title` (String)
-
-
diff --git a/docs/resources/instance.md b/docs/resources/instance.md
index 435e187..030a61a 100644
--- a/docs/resources/instance.md
+++ b/docs/resources/instance.md
@@ -25,7 +25,9 @@ The instance resource.
### Optional
+- `activation` (Boolean) Whether assign license for this instance or not.
- `external_link` (String) The external console URL managing this instance (e.g. AWS RDS console, your in-house DB instance console)
+- `list_all_databases` (Boolean) List all databases in this instance. If false, will only list 500 databases.
- `maximum_connections` (Number) The maximum number of connections.
- `sync_interval` (Number) How often the instance is synced in seconds. Default 0, means never sync.
@@ -44,15 +46,66 @@ Required:
- `host` (String) Host or socket for your instance, or the account name if the instance type is Snowflake.
- `id` (String) The unique data source id in this instance.
- `port` (String) The port for your instance.
-- `type` (String) The data source type. Should be ADMIN or RO.
+- `type` (String) The data source type. Should be ADMIN or READ_ONLY.
Optional:
- `database` (String) The database for the instance, you can set this if the engine type is POSTGRES.
+- `external_secret` (Block List, Max: 1) The external secret to get the database password. Learn more: https://www.bytebase.com/docs/get-started/instance/#use-external-secret-manager (see [below for nested schema](#nestedblock--data_sources--external_secret))
- `password` (String, Sensitive) The connection user password used by Bytebase to perform DDL and DML operations.
- `ssl_ca` (String, Sensitive) The CA certificate. Optional, you can set this if the engine type is MYSQL, POSTGRES, TIDB or CLICKHOUSE.
- `ssl_cert` (String, Sensitive) The client certificate. Optional, you can set this if the engine type is MYSQL, POSTGRES, TIDB or CLICKHOUSE.
- `ssl_key` (String, Sensitive) The client key. Optional, you can set this if the engine type is MYSQL, POSTGRES, TIDB or CLICKHOUSE.
- `username` (String) The connection user name used by Bytebase to perform DDL and DML operations.
+
+### Nested Schema for `data_sources.external_secret`
+
+Optional:
+
+- `aws_secrets_manager` (Block List, Max: 1) The AWS Secrets Manager to get the database password. Reference doc https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html (see [below for nested schema](#nestedblock--data_sources--external_secret--aws_secrets_manager))
+- `gcp_secret_manager` (Block List, Max: 1) The GCP Secret Manager to get the database password. Reference doc https://cloud.google.com/secret-manager/docs (see [below for nested schema](#nestedblock--data_sources--external_secret--gcp_secret_manager))
+- `vault` (Block List, Max: 1) The Valut to get the database password. Reference doc https://developer.hashicorp.com/vault/api-docs/secret/kv/kv-v2 (see [below for nested schema](#nestedblock--data_sources--external_secret--vault))
+
+
+### Nested Schema for `data_sources.external_secret.aws_secrets_manager`
+
+Required:
+
+- `password_key_name` (String) The key name for the password.
+- `secret_name` (String) The secret name to store the password.
+
+
+
+### Nested Schema for `data_sources.external_secret.gcp_secret_manager`
+
+Required:
+
+- `secret_name` (String) The secret name should be like "projects/{project-id}/secrets/{secret-id}".
+
+
+
+### Nested Schema for `data_sources.external_secret.vault`
+
+Required:
+
+- `engine_name` (String) The name for secret engine.
+- `password_key_name` (String) The key name for the password.
+- `secret_name` (String) The secret name in the engine to store the password.
+- `url` (String) The Vault URL.
+
+Optional:
+
+- `app_role` (Block List, Max: 1) The Vault app role to get the password. (see [below for nested schema](#nestedblock--data_sources--external_secret--vault--app_role))
+- `token` (String, Sensitive) The root token without TTL. Learn more: https://developer.hashicorp.com/vault/docs/commands/operator/generate-root
+
+
+### Nested Schema for `data_sources.external_secret.vault.app_role`
+
+Required:
+
+- `role_id` (String, Sensitive) The app role id.
+- `secret` (String, Sensitive) The secret id for the role without ttl.
+- `secret_type` (String) The secret id type, can be PLAIN (plain text for the secret) or ENVIRONMENT (envirionment name for the secret).
+
diff --git a/docs/resources/setting.md b/docs/resources/setting.md
index 932c65a..da630a5 100644
--- a/docs/resources/setting.md
+++ b/docs/resources/setting.md
@@ -23,7 +23,6 @@ The setting resource.
- `approval_flow` (Block List) Configure risk level and approval flow for different tasks. Require ENTERPRISE subscription. (see [below for nested schema](#nestedblock--approval_flow))
- `classification` (Block List, Max: 1) Classification for data masking. Require ENTERPRISE subscription. (see [below for nested schema](#nestedblock--classification))
-- `external_approval_nodes` (Block List) Configure external nodes in the approval flow. Require ENTERPRISE subscription. (see [below for nested schema](#nestedblock--external_approval_nodes))
- `semantic_types` (Block Set) Semantic types for data masking. Require ENTERPRISE subscription. (see [below for nested schema](#nestedblock--semantic_types))
- `workspace_profile` (Block List, Max: 1) (see [below for nested schema](#nestedblock--workspace_profile))
@@ -119,24 +118,6 @@ Optional:
-
-### Nested Schema for `external_approval_nodes`
-
-Required:
-
-- `nodes` (Block Set, Min: 1) (see [below for nested schema](#nestedblock--external_approval_nodes--nodes))
-
-
-### Nested Schema for `external_approval_nodes.nodes`
-
-Required:
-
-- `endpoint` (String) The endpoint URL to receive the approval message. Learn more: https://www.bytebase.com/docs/api/external-approval
-- `id` (String) The unique external node id.
-- `title` (String) The external node title.
-
-
-
### Nested Schema for `semantic_types`
diff --git a/examples/environments/main.tf b/examples/environments/main.tf
index b254e47..288369d 100644
--- a/examples/environments/main.tf
+++ b/examples/environments/main.tf
@@ -2,7 +2,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/examples/groups/main.tf b/examples/groups/main.tf
index 2f29574..4c8764c 100644
--- a/examples/groups/main.tf
+++ b/examples/groups/main.tf
@@ -1,7 +1,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/examples/instances/main.tf b/examples/instances/main.tf
index 18eea87..b3626b6 100644
--- a/examples/instances/main.tf
+++ b/examples/instances/main.tf
@@ -2,7 +2,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
@@ -32,7 +32,8 @@ output "all_instances" {
# Find a specific instance by name
data "bytebase_instance" "test" {
- resource_id = local.instance_id_test
+ resource_id = local.instance_id_test
+ list_all_databases = true
}
output "test_instance" {
@@ -40,7 +41,8 @@ output "test_instance" {
}
data "bytebase_instance" "prod" {
- resource_id = local.instance_id_prod
+ resource_id = local.instance_id_prod
+ list_all_databases = false
}
output "prod_instance" {
diff --git a/examples/policies/main.tf b/examples/policies/main.tf
index ea6fb9b..6f45f4c 100644
--- a/examples/policies/main.tf
+++ b/examples/policies/main.tf
@@ -1,7 +1,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/examples/projects/main.tf b/examples/projects/main.tf
index 4ddb66c..d3d3f61 100644
--- a/examples/projects/main.tf
+++ b/examples/projects/main.tf
@@ -2,7 +2,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/examples/roles/main.tf b/examples/roles/main.tf
index a9b05bf..92b116c 100644
--- a/examples/roles/main.tf
+++ b/examples/roles/main.tf
@@ -1,7 +1,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/examples/settings/main.tf b/examples/settings/main.tf
index b3f6272..8f0d146 100644
--- a/examples/settings/main.tf
+++ b/examples/settings/main.tf
@@ -1,7 +1,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
@@ -21,10 +21,6 @@ data "bytebase_setting" "approval_flow" {
name = "bb.workspace.approval"
}
-data "bytebase_setting" "external_approval" {
- name = "bb.workspace.approval.external"
-}
-
data "bytebase_setting" "workspace_profile" {
name = "bb.workspace.profile"
}
@@ -41,10 +37,6 @@ output "approval_flow" {
value = data.bytebase_setting.approval_flow
}
-output "external_approval" {
- value = data.bytebase_setting.external_approval
-}
-
output "workspace_profile" {
value = data.bytebase_setting.workspace_profile
}
diff --git a/examples/setup/approval_flow.tf b/examples/setup/approval_flow.tf
index de0bce1..79201e9 100644
--- a/examples/setup/approval_flow.tf
+++ b/examples/setup/approval_flow.tf
@@ -1,22 +1,3 @@
-
-resource "bytebase_setting" "external_approval" {
- name = "bb.workspace.approval.external"
-
- external_approval_nodes {
- nodes {
- id = "9e150339-f014-4835-83d7-123aeb1895ba"
- title = "Example node"
- endpoint = "https://example.com"
- }
-
- nodes {
- id = "49a976be-50de-4541-b2d3-f2e32f8e41ef"
- title = "Example node 2"
- endpoint = "https://example.com"
- }
- }
-}
-
resource "bytebase_setting" "approval_flow" {
name = "bb.workspace.approval"
approval_flow {
diff --git a/examples/setup/instance.tf b/examples/setup/instance.tf
index 1a0b91b..de0ba67 100644
--- a/examples/setup/instance.tf
+++ b/examples/setup/instance.tf
@@ -9,23 +9,33 @@ resource "bytebase_instance" "test" {
environment = bytebase_environment.test.name
title = "test instance"
engine = "MYSQL"
+ activation = true
# You need to specific the data source
data_sources {
- id = "admin data source"
- type = "ADMIN"
- username = ""
- password = ""
- host = "127.0.0.1"
- port = "3366"
+ id = "admin data source"
+ type = "ADMIN"
+ host = "127.0.0.1"
+ port = "3366"
+
+ username = "bytebase"
+ external_secret {
+ vault {
+ url = "http://127.0.0.1:8200"
+ token = ""
+ engine_name = "secret"
+ secret_name = "bytebase"
+ key_name = "database_pwd"
+ }
+ }
}
# And you can add another data_sources with RO type
data_sources {
id = "read-only data source"
type = "READ_ONLY"
- username = ""
- password = ""
+ username = "bytebase"
+ password = "YOUR_DB_PWD"
host = "127.0.0.1"
port = "3366"
}
@@ -46,8 +56,8 @@ resource "bytebase_instance" "prod" {
data_sources {
id = "admin data source"
type = "ADMIN"
- username = ""
- password = ""
+ username = "bytebase"
+ password = "YOUR_DB_PWD"
host = "127.0.0.1"
port = "54321"
}
diff --git a/examples/setup/main.tf b/examples/setup/main.tf
index babe852..116af61 100644
--- a/examples/setup/main.tf
+++ b/examples/setup/main.tf
@@ -1,7 +1,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/examples/setup/project.tf b/examples/setup/project.tf
index d247e71..2cd13ff 100644
--- a/examples/setup/project.tf
+++ b/examples/setup/project.tf
@@ -4,7 +4,7 @@ resource "bytebase_project" "sample_project" {
bytebase_user.workspace_dba,
bytebase_user.project_developer,
bytebase_group.developers,
- bytebase_instance.prod
+ bytebase_instance.test
]
resource_id = local.project_id
@@ -31,5 +31,5 @@ resource "bytebase_project" "sample_project" {
}
}
- databases = bytebase_instance.prod.databases
+ databases = bytebase_instance.test.databases
}
diff --git a/examples/setup/users.tf b/examples/setup/users.tf
index 88c23e8..d8c178a 100644
--- a/examples/setup/users.tf
+++ b/examples/setup/users.tf
@@ -10,6 +10,7 @@ resource "bytebase_user" "workspace_dba" {
# Create or update the user.
resource "bytebase_user" "workspace_auditor" {
depends_on = [
+ bytebase_user.workspace_dba,
bytebase_role.auditor
]
title = "Auditor"
@@ -22,7 +23,7 @@ resource "bytebase_user" "workspace_auditor" {
# Create or update the user.
resource "bytebase_user" "project_developer" {
depends_on = [
- bytebase_user.workspace_dba
+ bytebase_user.workspace_auditor
]
title = "Developer"
diff --git a/examples/users/main.tf b/examples/users/main.tf
index dcc0340..4c2d7ed 100644
--- a/examples/users/main.tf
+++ b/examples/users/main.tf
@@ -1,7 +1,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/examples/vcs/main.tf b/examples/vcs/main.tf
index 907cd92..d72c644 100644
--- a/examples/vcs/main.tf
+++ b/examples/vcs/main.tf
@@ -1,7 +1,7 @@
terraform {
required_providers {
bytebase = {
- version = "1.0.18"
+ version = "1.0.19"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/provider/data_source_database_list.go b/provider/data_source_database_list.go
index 60e5154..d130d02 100644
--- a/provider/data_source_database_list.go
+++ b/provider/data_source_database_list.go
@@ -81,7 +81,7 @@ func dataSourceDatabaseListRead(ctx context.Context, d *schema.ResourceData, m i
client := m.(api.Client)
parent := d.Get("parent").(string)
- databases, err := client.ListDatabase(ctx, parent, "")
+ databases, err := client.ListDatabase(ctx, parent, "", true)
if err != nil {
return diag.FromErr(err)
}
diff --git a/provider/data_source_instance.go b/provider/data_source_instance.go
index 7993f9d..de69c71 100644
--- a/provider/data_source_instance.go
+++ b/provider/data_source_instance.go
@@ -37,6 +37,11 @@ func dataSourceInstance() *schema.Resource {
Computed: true,
Description: "The instance title.",
},
+ "activation": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "Whether assign license for this instance or not.",
+ },
"engine": {
Type: schema.TypeString,
Computed: true,
@@ -75,7 +80,7 @@ func dataSourceInstance() *schema.Resource {
"type": {
Type: schema.TypeString,
Computed: true,
- Description: "The data source type. Should be ADMIN or RO.",
+ Description: "The data source type. Should be ADMIN or READ_ONLY.",
},
"username": {
Type: schema.TypeString,
@@ -85,12 +90,12 @@ func dataSourceInstance() *schema.Resource {
"host": {
Type: schema.TypeString,
Computed: true,
- Description: "The Read-replica Host. Only works for RO type data source",
+ Description: "Host or socket for your instance, or the account name if the instance type is Snowflake.",
},
"port": {
Type: schema.TypeString,
Computed: true,
- Description: "The Read-replica Port. Only works for RO type data source",
+ Description: "The port for your instance.",
},
"database": {
Type: schema.TypeString,
@@ -103,6 +108,7 @@ func dataSourceInstance() *schema.Resource {
Sensitive: true,
Description: "The connection user password used by Bytebase to perform DDL and DML operations.",
},
+ "external_secret": getExternalSecretSchema(),
"ssl_ca": {
Type: schema.TypeString,
Computed: true,
@@ -125,11 +131,123 @@ func dataSourceInstance() *schema.Resource {
},
Set: dataSourceHash,
},
+ "list_all_databases": {
+ Type: schema.TypeBool,
+ Optional: true,
+ Default: false,
+ Description: "List all databases in this instance. If false, will only list 500 databases.",
+ },
"databases": getDatabasesSchema(true),
},
}
}
+func getExternalSecretSchema() *schema.Schema {
+ return &schema.Schema{
+ Type: schema.TypeList,
+ Computed: true,
+ Description: "The external secret to get the database password. Learn more: https://www.bytebase.com/docs/get-started/instance/#use-external-secret-manager",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "vault": {
+ Type: schema.TypeList,
+ Computed: true,
+ Description: "The Valut to get the database password. Reference doc https://developer.hashicorp.com/vault/api-docs/secret/kv/kv-v2",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The Vault URL.",
+ },
+ "token": {
+ Type: schema.TypeString,
+ Computed: true,
+ Sensitive: true,
+ Description: "The root token without TTL. Learn more: https://developer.hashicorp.com/vault/docs/commands/operator/generate-root",
+ },
+ "app_role": {
+ Type: schema.TypeList,
+ Computed: true,
+ Description: "The Vault app role to get the password.",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "role_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Sensitive: true,
+ Description: "The app role id.",
+ },
+ "secret": {
+ Type: schema.TypeString,
+ Computed: true,
+ Sensitive: true,
+ Description: "The secret id for the role without ttl.",
+ },
+ "secret_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The secret id type, can be PLAIN (plain text for the secret) or ENVIRONMENT (envirionment name for the secret).",
+ },
+ },
+ },
+ },
+ "engine_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The name for secret engine.",
+ },
+ "secret_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The secret name in the engine to store the password.",
+ },
+ "password_key_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The key name for the password.",
+ },
+ },
+ },
+ },
+ "aws_secrets_manager": {
+ Type: schema.TypeList,
+ Computed: true,
+ Description: "The AWS Secrets Manager to get the database password. Reference doc https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "secret_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The secret name to store the password.",
+ },
+ "password_key_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The key name for the password.",
+ },
+ },
+ },
+ },
+ "gcp_secret_manager": {
+ Type: schema.TypeList,
+ Computed: true,
+ Description: "The GCP Secret Manager to get the database password. Reference doc https://cloud.google.com/secret-manager/docs",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "secret_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The secret name should be like \"projects/{project-id}/secrets/{secret-id}\".",
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
func dataSourceInstanceRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(api.Client)
instanceName := fmt.Sprintf("%s%s", internal.InstanceNamePrefix, d.Get("resource_id").(string))
diff --git a/provider/data_source_instance_list.go b/provider/data_source_instance_list.go
index 342916d..cb5c2c8 100644
--- a/provider/data_source_instance_list.go
+++ b/provider/data_source_instance_list.go
@@ -48,6 +48,11 @@ func dataSourceInstanceList() *schema.Resource {
Computed: true,
Description: "The instance title.",
},
+ "activation": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "Whether assign license for this instance or not.",
+ },
"engine": {
Type: schema.TypeString,
Computed: true,
@@ -86,7 +91,7 @@ func dataSourceInstanceList() *schema.Resource {
"type": {
Type: schema.TypeString,
Computed: true,
- Description: "The data source type. Should be ADMIN or RO.",
+ Description: "The data source type. Should be ADMIN or READ_ONLY.",
},
"username": {
Type: schema.TypeString,
@@ -96,12 +101,12 @@ func dataSourceInstanceList() *schema.Resource {
"host": {
Type: schema.TypeString,
Computed: true,
- Description: "The Read-replica Host. Only works for RO type data source",
+ Description: "Host or socket for your instance, or the account name if the instance type is Snowflake.",
},
"port": {
Type: schema.TypeString,
Computed: true,
- Description: "The Read-replica Port. Only works for RO type data source",
+ Description: "The port for your instance.",
},
"database": {
Type: schema.TypeString,
@@ -114,6 +119,7 @@ func dataSourceInstanceList() *schema.Resource {
Sensitive: true,
Description: "The connection user password used by Bytebase to perform DDL and DML operations.",
},
+ "external_secret": getExternalSecretSchema(),
"ssl_ca": {
Type: schema.TypeString,
Computed: true,
@@ -136,7 +142,6 @@ func dataSourceInstanceList() *schema.Resource {
},
Set: dataSourceHash,
},
- "databases": getDatabasesSchema(true),
},
},
},
@@ -166,14 +171,15 @@ func dataSourceInstanceListRead(ctx context.Context, d *schema.ResourceData, m i
ins["resource_id"] = instanceID
ins["title"] = instance.Title
ins["name"] = instance.Name
+ ins["activation"] = instance.Activation
ins["engine"] = instance.Engine.String()
ins["engine_version"] = instance.EngineVersion
ins["external_link"] = instance.ExternalLink
ins["environment"] = instance.Environment
if op := instance.Options; op != nil {
- ins["sync_interval"] = op.SyncInterval.GetSeconds()
- ins["maximum_connections"] = op.MaximumConnections
+ ins["sync_interval"] = op.GetSyncInterval().GetSeconds()
+ ins["maximum_connections"] = op.GetMaximumConnections()
}
dataSources, err := flattenDataSourceList(d, instance.DataSources)
@@ -182,12 +188,6 @@ func dataSourceInstanceListRead(ctx context.Context, d *schema.ResourceData, m i
}
ins["data_sources"] = schema.NewSet(dataSourceHash, dataSources)
- databases, err := c.ListDatabase(ctx, instance.Name, "")
- if err != nil {
- return diag.FromErr(err)
- }
- ins["databases"] = flattenDatabaseList(databases)
-
instances = append(instances, ins)
}
diff --git a/provider/data_source_project.go b/provider/data_source_project.go
index 8114714..cf92471 100644
--- a/provider/data_source_project.go
+++ b/provider/data_source_project.go
@@ -257,7 +257,7 @@ func setProject(
"project": project.Name,
})
- databases, err := client.ListDatabase(ctx, project.Name, "")
+ databases, err := client.ListDatabase(ctx, project.Name, "", true)
if err != nil {
return diag.FromErr(err)
}
diff --git a/provider/data_source_project_list.go b/provider/data_source_project_list.go
index 7c666b0..64415d4 100644
--- a/provider/data_source_project_list.go
+++ b/provider/data_source_project_list.go
@@ -117,7 +117,7 @@ func dataSourceProjectListRead(ctx context.Context, d *schema.ResourceData, m in
proj["skip_backup_errors"] = project.AllowModifyStatement
proj["postgres_database_tenant_mode"] = project.PostgresDatabaseTenantMode
- databases, err := c.ListDatabase(ctx, project.Name, "")
+ databases, err := c.ListDatabase(ctx, project.Name, "", false)
if err != nil {
return diag.FromErr(err)
}
diff --git a/provider/data_source_setting.go b/provider/data_source_setting.go
index 58245d5..8b5f90d 100644
--- a/provider/data_source_setting.go
+++ b/provider/data_source_setting.go
@@ -27,17 +27,15 @@ func dataSourceSetting() *schema.Resource {
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(api.SettingWorkspaceApproval),
- string(api.SettingWorkspaceExternalApproval),
string(api.SettingWorkspaceProfile),
string(api.SettingDataClassification),
string(api.SettingSemanticTypes),
}, false),
},
- "approval_flow": getWorkspaceApprovalSetting(true),
- "external_approval_nodes": getExternalApprovalSetting(true),
- "workspace_profile": getWorkspaceProfileSetting(true),
- "classification": getClassificationSetting(true),
- "semantic_types": getSemanticTypesSetting(true),
+ "approval_flow": getWorkspaceApprovalSetting(true),
+ "workspace_profile": getWorkspaceProfileSetting(true),
+ "classification": getClassificationSetting(true),
+ "semantic_types": getSemanticTypesSetting(true),
},
}
}
@@ -341,48 +339,6 @@ func getWorkspaceProfileSetting(computed bool) *schema.Schema {
}
}
-func getExternalApprovalSetting(computed bool) *schema.Schema {
- return &schema.Schema{
- Computed: computed,
- Optional: true,
- Default: nil,
- Type: schema.TypeList,
- Description: "Configure external nodes in the approval flow. Require ENTERPRISE subscription.",
- Elem: &schema.Resource{
- Schema: map[string]*schema.Schema{
- "nodes": {
- Type: schema.TypeSet,
- Computed: computed,
- Required: !computed,
- Elem: &schema.Resource{
- Schema: map[string]*schema.Schema{
- "id": {
- Type: schema.TypeString,
- Computed: computed,
- Required: !computed,
- Description: "The unique external node id.",
- },
- "title": {
- Type: schema.TypeString,
- Computed: computed,
- Required: !computed,
- Description: "The external node title.",
- },
- "endpoint": {
- Type: schema.TypeString,
- Computed: computed,
- Required: !computed,
- Description: "The endpoint URL to receive the approval message. Learn more: https://www.bytebase.com/docs/api/external-approval",
- },
- },
- },
- Set: itemIDHash,
- },
- },
- },
- }
-}
-
func getWorkspaceApprovalSetting(computed bool) *schema.Schema {
return &schema.Schema{
Computed: computed,
@@ -515,12 +471,6 @@ func setSettingMessage(ctx context.Context, d *schema.ResourceData, client api.C
return diag.Errorf("cannot set workspace_approval_setting: %s", err.Error())
}
}
- if value := setting.Value.GetExternalApprovalSettingValue(); value != nil {
- settingVal := flattenExternalApprovalSetting(value)
- if err := d.Set("external_approval_nodes", settingVal); err != nil {
- return diag.Errorf("cannot set external_approval_nodes: %s", err.Error())
- }
- }
if value := setting.Value.GetWorkspaceProfileSettingValue(); value != nil {
settingVal := flattenWorkspaceProfileSetting(value)
if err := d.Set("workspace_profile", settingVal); err != nil {
@@ -668,22 +618,6 @@ func flattenWorkspaceApprovalSetting(ctx context.Context, client api.Client, set
return []interface{}{approvalSetting}, nil
}
-func flattenExternalApprovalSetting(setting *v1pb.ExternalApprovalSetting) []interface{} {
- nodeList := []interface{}{}
- for _, node := range setting.Nodes {
- rawNode := map[string]interface{}{}
- rawNode["id"] = node.Id
- rawNode["title"] = node.Title
- rawNode["endpoint"] = node.Endpoint
- nodeList = append(nodeList, rawNode)
- }
-
- approvalSetting := map[string]interface{}{
- "nodes": nodeList,
- }
- return []interface{}{approvalSetting}
-}
-
func flattenWorkspaceProfileSetting(setting *v1pb.WorkspaceProfileSetting) []interface{} {
raw := map[string]interface{}{}
diff --git a/provider/internal/mock_client.go b/provider/internal/mock_client.go
index a9e9a27..c2f88a4 100644
--- a/provider/internal/mock_client.go
+++ b/provider/internal/mock_client.go
@@ -390,7 +390,7 @@ func (c *mockClient) GetDatabase(_ context.Context, databaseName string) (*v1pb.
}
// ListDatabase list the databases.
-func (c *mockClient) ListDatabase(_ context.Context, instaceID, filter string) ([]*v1pb.Database, error) {
+func (c *mockClient) ListDatabase(_ context.Context, instaceID, filter string, _ bool) ([]*v1pb.Database, error) {
projectID := "-"
if strings.HasPrefix(filter, "project == ") {
projectID = strings.Split(filter, "project == ")[1]
diff --git a/provider/resource_instance.go b/provider/resource_instance.go
index d31a4e4..5902917 100644
--- a/provider/resource_instance.go
+++ b/provider/resource_instance.go
@@ -47,6 +47,12 @@ func resourceInstance() *schema.Resource {
ValidateFunc: validation.StringIsNotEmpty,
Description: "The instance title.",
},
+ "activation": {
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true,
+ Description: "Whether assign license for this instance or not.",
+ },
"name": {
Type: schema.TypeString,
Computed: true,
@@ -123,7 +129,7 @@ func resourceInstance() *schema.Resource {
v1pb.DataSourceType_ADMIN.String(),
v1pb.DataSourceType_READ_ONLY.String(),
}, false),
- Description: "The data source type. Should be ADMIN or RO.",
+ Description: "The data source type. Should be ADMIN or READ_ONLY.",
},
"username": {
Type: schema.TypeString,
@@ -138,6 +144,118 @@ func resourceInstance() *schema.Resource {
Default: "",
Description: "The connection user password used by Bytebase to perform DDL and DML operations.",
},
+ "external_secret": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Description: "The external secret to get the database password. Learn more: https://www.bytebase.com/docs/get-started/instance/#use-external-secret-manager",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "vault": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Description: "The Valut to get the database password. Reference doc https://developer.hashicorp.com/vault/api-docs/secret/kv/kv-v2",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The Vault URL.",
+ },
+ "token": {
+ Type: schema.TypeString,
+ Optional: true,
+ Sensitive: true,
+ Description: "The root token without TTL. Learn more: https://developer.hashicorp.com/vault/docs/commands/operator/generate-root",
+ },
+ "app_role": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Description: "The Vault app role to get the password.",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "role_id": {
+ Type: schema.TypeString,
+ Required: true,
+ Sensitive: true,
+ Description: "The app role id.",
+ },
+ "secret": {
+ Type: schema.TypeString,
+ Required: true,
+ Sensitive: true,
+ Description: "The secret id for the role without ttl.",
+ },
+ "secret_type": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The secret id type, can be PLAIN (plain text for the secret) or ENVIRONMENT (envirionment name for the secret).",
+ ValidateFunc: validation.StringInSlice([]string{
+ v1pb.DataSourceExternalSecret_AppRoleAuthOption_PLAIN.String(),
+ v1pb.DataSourceExternalSecret_AppRoleAuthOption_ENVIRONMENT.String(),
+ }, false),
+ },
+ },
+ },
+ },
+ "engine_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The name for secret engine.",
+ },
+ "secret_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The secret name in the engine to store the password.",
+ },
+ "password_key_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The key name for the password.",
+ },
+ },
+ },
+ },
+ "aws_secrets_manager": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Description: "The AWS Secrets Manager to get the database password. Reference doc https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "secret_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The secret name to store the password.",
+ },
+ "password_key_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The key name for the password.",
+ },
+ },
+ },
+ },
+ "gcp_secret_manager": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Description: "The GCP Secret Manager to get the database password. Reference doc https://cloud.google.com/secret-manager/docs",
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "secret_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The secret name should be like \"projects/{project-id}/secrets/{secret-id}\".",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
"ssl_ca": {
Type: schema.TypeString,
Optional: true,
@@ -181,6 +299,12 @@ func resourceInstance() *schema.Resource {
},
Set: dataSourceHash,
},
+ "list_all_databases": {
+ Type: schema.TypeBool,
+ Optional: true,
+ Default: false,
+ Description: "List all databases in this instance. If false, will only list 500 databases.",
+ },
"databases": getDatabasesSchema(true),
},
}
@@ -198,6 +322,8 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
instanceName := fmt.Sprintf("%s%s", internal.InstanceNamePrefix, instanceID)
title := d.Get("title").(string)
externalLink := d.Get("external_link").(string)
+ environment := d.Get("environment").(string)
+ activation := d.Get("activation").(bool)
instanceOptions := &v1pb.InstanceOptions{
SyncInterval: &durationpb.Duration{
Seconds: int64(d.Get("sync_interval").(int)),
@@ -257,6 +383,12 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
if externalLink != "" && externalLink != existedInstance.ExternalLink {
updateMasks = append(updateMasks, "external_link")
}
+ if environment != existedInstance.Environment {
+ updateMasks = append(updateMasks, "environment")
+ }
+ if activation != existedInstance.Activation {
+ updateMasks = append(updateMasks, "activation")
+ }
if op := existedInstance.Options; op != nil {
if instanceOptions.SyncInterval.GetSeconds() != op.SyncInterval.GetSeconds() {
updateMasks = append(updateMasks, "options.sync_interval")
@@ -275,6 +407,8 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
Title: title,
ExternalLink: externalLink,
DataSources: dataSourceList,
+ Environment: environment,
+ Activation: activation,
State: v1pb.State_ACTIVE,
Options: instanceOptions,
}, updateMasks); err != nil {
@@ -289,12 +423,13 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
} else {
if _, err := c.CreateInstance(ctx, instanceID, &v1pb.Instance{
Name: instanceName,
- Title: d.Get("title").(string),
+ Title: title,
Engine: engine,
- ExternalLink: d.Get("external_link").(string),
+ ExternalLink: externalLink,
State: v1pb.State_ACTIVE,
DataSources: dataSourceList,
- Environment: d.Get("environment").(string),
+ Environment: environment,
+ Activation: activation,
Options: instanceOptions,
}); err != nil {
return diag.FromErr(err)
@@ -350,9 +485,6 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter
if d.HasChange("resource_id") {
return diag.Errorf("cannot change the resource id")
}
- if d.HasChange("environment") {
- return diag.Errorf("cannot change the environment in instance")
- }
if d.HasChange("engine") {
return diag.Errorf("cannot change the engine in instance")
}
@@ -394,6 +526,12 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter
if d.HasChange("external_link") {
paths = append(paths, "external_link")
}
+ if d.HasChange("environment") {
+ paths = append(paths, "environment")
+ }
+ if d.HasChange("activation") {
+ paths = append(paths, "activation")
+ }
if d.HasChange("data_sources") {
paths = append(paths, "data_sources")
}
@@ -409,6 +547,8 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter
Name: instanceName,
Title: d.Get("title").(string),
ExternalLink: d.Get("external_link").(string),
+ Environment: d.Get("environment").(string),
+ Activation: d.Get("activation").(bool),
DataSources: dataSourceList,
State: v1pb.State_ACTIVE,
Options: &v1pb.InstanceOptions{
@@ -479,6 +619,9 @@ func setInstanceMessage(
if err := d.Set("environment", instance.Environment); err != nil {
return diag.Errorf("cannot set environment for instance: %s", err.Error())
}
+ if err := d.Set("activation", instance.Activation); err != nil {
+ return diag.Errorf("cannot set activation for instance: %s", err.Error())
+ }
if err := d.Set("engine", instance.Engine.String()); err != nil {
return diag.Errorf("cannot set engine for instance: %s", err.Error())
}
@@ -489,10 +632,10 @@ func setInstanceMessage(
return diag.Errorf("cannot set external_link for instance: %s", err.Error())
}
if op := instance.Options; op != nil {
- if err := d.Set("sync_interval", op.SyncInterval.GetSeconds()); err != nil {
+ if err := d.Set("sync_interval", op.GetSyncInterval().GetSeconds()); err != nil {
return diag.Errorf("cannot set sync_interval for instance: %s", err.Error())
}
- if err := d.Set("maximum_connections", op.MaximumConnections); err != nil {
+ if err := d.Set("maximum_connections", op.GetMaximumConnections()); err != nil {
return diag.Errorf("cannot set maximum_connections for instance: %s", err.Error())
}
}
@@ -509,7 +652,8 @@ func setInstanceMessage(
"instance": instance.Name,
})
- databases, err := client.ListDatabase(ctx, instance.Name, "")
+ listAllDatabases := d.Get("list_all_databases").(bool)
+ databases, err := client.ListDatabase(ctx, instance.Name, "", listAllDatabases)
if err != nil {
return diag.FromErr(err)
}
@@ -548,6 +692,57 @@ func flattenDataSourceList(d *schema.ResourceData, dataSourceList []*v1pb.DataSo
raw["ssl_cert"] = ds.SslCert
raw["ssl_key"] = ds.SslKey
}
+
+ if v := dataSource.ExternalSecret; v != nil {
+ switch v.SecretType {
+ case v1pb.DataSourceExternalSecret_GCP_SECRET_MANAGER:
+ gcp := map[string]interface{}{
+ "secret_name": v.SecretName,
+ }
+ raw["external_secret"] = []any{
+ map[string]interface{}{
+ "gcp_secret_manager": []any{gcp},
+ },
+ }
+ case v1pb.DataSourceExternalSecret_AWS_SECRETS_MANAGER:
+ aws := map[string]interface{}{
+ "secret_name": v.SecretName,
+ "password_key_name": v.PasswordKeyName,
+ }
+ raw["external_secret"] = []any{
+ map[string]interface{}{
+ "aws_secrets_manager": []any{aws},
+ },
+ }
+ case v1pb.DataSourceExternalSecret_VAULT_KV_V2:
+ vault := map[string]interface{}{
+ "url": v.Url,
+ "engine_name": v.EngineName,
+ "secret_name": v.SecretName,
+ "password_key_name": v.PasswordKeyName,
+ }
+ switch v.AuthType {
+ case v1pb.DataSourceExternalSecret_TOKEN:
+ if ds, ok := oldDataSourceMap[dataSource.Id]; ok && ds.GetExternalSecret() != nil {
+ vault["token"] = ds.GetExternalSecret().GetToken()
+ }
+ case v1pb.DataSourceExternalSecret_VAULT_APP_ROLE:
+ appRole := map[string]interface{}{
+ "secret_type": v.GetAppRole().Type.String(),
+ }
+ if ds, ok := oldDataSourceMap[dataSource.Id]; ok && ds.GetExternalSecret() != nil {
+ appRole["role_id"] = ds.GetExternalSecret().GetAppRole().GetRoleId()
+ appRole["secret"] = ds.GetExternalSecret().GetAppRole().GetSecretId()
+ }
+ vault["app_role"] = []any{appRole}
+ }
+ raw["external_secret"] = []any{
+ map[string]interface{}{
+ "vault": []any{vault},
+ },
+ }
+ }
+ }
res = append(res, raw)
}
return res, nil
@@ -583,6 +778,53 @@ func convertDataSourceCreateList(d *schema.ResourceData, validate bool) ([]*v1pb
if v, ok := obj["password"].(string); ok && v != "" {
dataSource.Password = v
}
+ if v, ok := obj["external_secret"].([]interface{}); ok && len(v) == 1 {
+ externalSecret := &v1pb.DataSourceExternalSecret{}
+ rawExternalSecret := v[0].(map[string]interface{})
+ if v, ok := rawExternalSecret["vault"].([]interface{}); ok && len(v) == 1 {
+ rawVault := v[0].(map[string]interface{})
+ externalSecret.SecretType = v1pb.DataSourceExternalSecret_VAULT_KV_V2
+ externalSecret.Url = rawVault["url"].(string)
+ externalSecret.EngineName = rawVault["engine_name"].(string)
+ externalSecret.SecretName = rawVault["secret_name"].(string)
+ externalSecret.PasswordKeyName = rawVault["password_key_name"].(string)
+
+ if token, ok := rawVault["token"].(string); ok && token != "" {
+ externalSecret.AuthType = v1pb.DataSourceExternalSecret_TOKEN
+ externalSecret.AuthOption = &v1pb.DataSourceExternalSecret_Token{
+ Token: token,
+ }
+ } else if v, ok := rawVault["app_role"].([]interface{}); ok && len(v) == 1 {
+ rawAppRole := v[0].(map[string]interface{})
+ externalSecret.AuthType = v1pb.DataSourceExternalSecret_VAULT_APP_ROLE
+ externalSecret.AuthOption = &v1pb.DataSourceExternalSecret_AppRole{
+ AppRole: &v1pb.DataSourceExternalSecret_AppRoleAuthOption{
+ RoleId: rawAppRole["role_id"].(string),
+ SecretId: rawAppRole["secret"].(string),
+ Type: v1pb.DataSourceExternalSecret_AppRoleAuthOption_SecretType(v1pb.DataSourceExternalSecret_AppRoleAuthOption_SecretType_value[rawAppRole["secret_type"].(string)]),
+ },
+ }
+ } else {
+ return nil, errors.Errorf("require token or app_role for Vault")
+ }
+ } else if v, ok := rawExternalSecret["aws_secrets_manager"].([]interface{}); ok && len(v) == 1 {
+ rawAWS := v[0].(map[string]interface{})
+ externalSecret.SecretType = v1pb.DataSourceExternalSecret_AWS_SECRETS_MANAGER
+ externalSecret.SecretName = rawAWS["secret_name"].(string)
+ externalSecret.PasswordKeyName = rawAWS["password_key_name"].(string)
+ } else if v, ok := rawExternalSecret["gcp_secret_manager"].([]interface{}); ok && len(v) == 1 {
+ rawGCP := v[0].(map[string]interface{})
+ externalSecret.SecretType = v1pb.DataSourceExternalSecret_GCP_SECRET_MANAGER
+ externalSecret.SecretName = rawGCP["secret_name"].(string)
+ } else {
+ return nil, errors.Errorf("must set one of vault, aws_secrets_manager or gcp_secret_manager")
+ }
+ dataSource.ExternalSecret = externalSecret
+ }
+ if dataSource.Password != "" && dataSource.ExternalSecret != nil {
+ return nil, errors.Errorf("cannot set both password and external_secret")
+ }
+
if v, ok := obj["ssl_ca"].(string); ok {
dataSource.SslCa = v
}
diff --git a/provider/resource_project.go b/provider/resource_project.go
index 398ce1c..3241d4b 100644
--- a/provider/resource_project.go
+++ b/provider/resource_project.go
@@ -448,7 +448,7 @@ func updateMembersInProject(ctx context.Context, d *schema.ResourceData, client
const batchSize = 100
func updateDatabasesInProject(ctx context.Context, d *schema.ResourceData, client api.Client, projectName string) diag.Diagnostics {
- databases, err := client.ListDatabase(ctx, projectName, "")
+ databases, err := client.ListDatabase(ctx, projectName, "", true)
if err != nil {
return diag.Errorf("failed to list database with error: %v", err.Error())
}
diff --git a/provider/resource_setting.go b/provider/resource_setting.go
index b26ba20..d008baf 100644
--- a/provider/resource_setting.go
+++ b/provider/resource_setting.go
@@ -33,17 +33,15 @@ func resourceSetting() *schema.Resource {
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(api.SettingWorkspaceApproval),
- string(api.SettingWorkspaceExternalApproval),
string(api.SettingWorkspaceProfile),
string(api.SettingDataClassification),
string(api.SettingSemanticTypes),
}, false),
},
- "approval_flow": getWorkspaceApprovalSetting(false),
- "external_approval_nodes": getExternalApprovalSetting(false),
- "workspace_profile": getWorkspaceProfileSetting(false),
- "classification": getClassificationSetting(false),
- "semantic_types": getSemanticTypesSetting(false),
+ "approval_flow": getWorkspaceApprovalSetting(false),
+ "workspace_profile": getWorkspaceProfileSetting(false),
+ "classification": getClassificationSetting(false),
+ "semantic_types": getSemanticTypesSetting(false),
},
}
}
@@ -71,16 +69,6 @@ func resourceSettingUpsert(ctx context.Context, d *schema.ResourceData, m interf
WorkspaceApprovalSettingValue: workspaceApproval,
},
}
- case api.SettingWorkspaceExternalApproval:
- externalApproval, err := convertToV1ExternalNodesSetting(d)
- if err != nil {
- return diag.FromErr(err)
- }
- setting.Value = &v1pb.Value{
- Value: &v1pb.Value_ExternalApprovalSettingValue{
- ExternalApprovalSettingValue: externalApproval,
- },
- }
case api.SettingWorkspaceProfile:
workspaceProfile, updatePathes, err := convertToV1WorkspaceProfileSetting(d)
if err != nil {
@@ -240,31 +228,6 @@ func convertToV1ClassificationSetting(d *schema.ResourceData) (*v1pb.DataClassif
}, nil
}
-func convertToV1ExternalNodesSetting(d *schema.ResourceData) (*v1pb.ExternalApprovalSetting, error) {
- rawList, ok := d.Get("external_approval_nodes").([]interface{})
- if !ok || len(rawList) != 1 {
- return nil, errors.Errorf("invalid external_approval_nodes")
- }
-
- raw := rawList[0].(map[string]interface{})
- nodes, ok := raw["nodes"].(*schema.Set)
- if !ok {
- return nil, errors.Errorf("missing nodes")
- }
-
- externalApprovalSetting := &v1pb.ExternalApprovalSetting{}
-
- for _, node := range nodes.List() {
- rawNode := node.(map[string]interface{})
- externalApprovalSetting.Nodes = append(externalApprovalSetting.Nodes, &v1pb.ExternalApprovalSetting_Node{
- Id: rawNode["id"].(string),
- Title: rawNode["title"].(string),
- Endpoint: rawNode["endpoint"].(string),
- })
- }
- return externalApprovalSetting, nil
-}
-
func convertToV1ApprovalSetting(d *schema.ResourceData) (*v1pb.WorkspaceApprovalSetting, error) {
rawList, ok := d.Get("approval_flow").([]interface{})
if !ok || len(rawList) != 1 {