diff --git a/atlas/resource_atlas_schema.go b/atlas/resource_atlas_schema.go index 7577f44..f4f4a64 100644 --- a/atlas/resource_atlas_schema.go +++ b/atlas/resource_atlas_schema.go @@ -18,7 +18,7 @@ func newSchemaResource() *schema.Resource { CreateContext: applySchema, UpdateContext: applySchema, ReadContext: readSchema, - DeleteContext: readSchema, + DeleteContext: deleteSchema, Schema: map[string]*schema.Schema{ "hcl": { Type: schema.TypeString, @@ -41,6 +41,33 @@ func newSchemaResource() *schema.Resource { } } +func deleteSchema(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + var diags diag.Diagnostics + url := d.Get("url").(string) + + cli, err := sqlclient.Open(ctx, url) + if err != nil { + return diag.FromErr(err) + } + var schemas []string + if cli.URL.Schema != "" { + schemas = append(schemas, cli.URL.Schema) + } + realm, err := cli.InspectRealm(ctx, &atlaschema.InspectRealmOption{Schemas: schemas}) + if err != nil { + return diag.FromErr(err) + } + desired := &atlaschema.Realm{} + changes, err := cli.RealmDiff(realm, desired) + if err != nil { + return diag.FromErr(err) + } + if err = cli.ApplyChanges(ctx, changes); err != nil { + return diag.FromErr(err) + } + return diags +} + func readSchema(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var diags diag.Diagnostics url := d.Get("url").(string) @@ -72,17 +99,18 @@ func applySchema(ctx context.Context, d *schema.ResourceData, m interface{}) dia if err != nil { return diag.FromErr(err) } - - realm, err := cli.InspectRealm(ctx, nil) + var schemas []string + if cli.URL.Schema != "" { + schemas = append(schemas, cli.URL.Schema) + } + realm, err := cli.InspectRealm(ctx, &atlaschema.InspectRealmOption{Schemas: schemas}) if err != nil { return diag.FromErr(err) } - desired := &atlaschema.Realm{} if err = cli.Evaluator.Eval([]byte(hcl), desired, nil); err != nil { return diag.FromErr(err) } - if devURL, ok := d.GetOk("dev_db_url"); ok { dev, err := sqlclient.Open(ctx, devURL.(string)) if err != nil { diff --git a/atlas/resource_atlas_schema_test.go b/atlas/resource_atlas_schema_test.go index 0e6dc3b..323e3ee 100644 --- a/atlas/resource_atlas_schema_test.go +++ b/atlas/resource_atlas_schema_test.go @@ -13,7 +13,7 @@ import ( const testAccActionConfigCreate = ` data "atlas_schema" "market" { - dev_db_url = "mysql://root:pass@localhost:3307/test" + dev_db_url = "mysql://root:pass@localhost:3307" src = <<-EOT schema "test" { charset = "utf8mb4" @@ -34,13 +34,13 @@ data "atlas_schema" "market" { } resource "atlas_schema" "testdb" { hcl = data.atlas_schema.market.hcl - url = "mysql://root:pass@localhost:3306/test" + url = "mysql://root:pass@localhost:3306" } ` const testAccActionConfigUpdate = ` data "atlas_schema" "market" { - dev_db_url = "mysql://root:pass@localhost:3307/test" + dev_db_url = "mysql://root:pass@localhost:3307" src = <<-EOT schema "test" { charset = "utf8mb4" @@ -65,7 +65,7 @@ data "atlas_schema" "market" { } resource "atlas_schema" "testdb" { hcl = data.atlas_schema.market.hcl - url = "mysql://root:pass@localhost:3306/test" + url = "mysql://root:pass@localhost:3306" } ` @@ -78,13 +78,13 @@ func TestAccAtlasDatabase(t *testing.T) { { Config: testAccActionConfigCreate, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("atlas_schema.testdb", "id", "mysql://root:pass@localhost:3306/test"), + resource.TestCheckResourceAttr("atlas_schema.testdb", "id", "mysql://root:pass@localhost:3306"), ), }, { Config: testAccActionConfigUpdate, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("atlas_schema.testdb", "id", "mysql://root:pass@localhost:3306/test"), + resource.TestCheckResourceAttr("atlas_schema.testdb", "id", "mysql://root:pass@localhost:3306"), func(s *terraform.State) error { res := s.RootModule().Resources["atlas_schema.testdb"] cli, err := sqlclient.Open(context.TODO(), res.Primary.ID) @@ -106,3 +106,65 @@ func TestAccAtlasDatabase(t *testing.T) { }, }) } + +func TestAccDestroySchemas(t *testing.T) { + // Create schemas "main" and "do-not-delete". + preExistingSchema := `resource "atlas_schema" "testdb" { + hcl = <<-EOT + schema "do-not-delete" {} + schema "main" {} + EOT + url = "mysql://root:pass@localhost:3306" + }` + // When the following destroys, it only deletes schema "main". + tfSchema := `resource "atlas_schema" "testdb" { + hcl = <<-EOT + table "orders" { + schema = schema.main + column "id" { + null = true + type = int + } + } + schema "main" { + } + EOT + url = "mysql://root:pass@localhost:3306/main" + }` + resource.Test(t, resource.TestCase{ + Providers: map[string]*schema.Provider{ + "atlas": Provider(), + }, + Steps: []resource.TestStep{ + { + Config: preExistingSchema, + Destroy: false, + // ignore non-normalized schema + ExpectNonEmptyPlan: true, + }, + { + Config: tfSchema, + // ignore non-normalized schema + ExpectNonEmptyPlan: true, + }, + }, + CheckDestroy: func(s *terraform.State) error { + url := "mysql://root:pass@localhost:3306" + cli, err := sqlclient.Open(context.Background(), url) + if err != nil { + return err + } + realm, err := cli.InspectRealm(context.Background(), nil) + if err != nil { + return err + } + if _, ok := realm.Schema("do-not-delete"); !ok { + return fmt.Errorf("schema 'do-not-delete' does not exist, but expected to not be destroyed.") + } + if _, ok := realm.Schema("main"); ok { + return fmt.Errorf("schema 'main' wasn't deleted.") + } + return nil + }, + }) +} diff --git a/docs/index.md b/docs/index.md index 5df4a24..aabce76 100644 --- a/docs/index.md +++ b/docs/index.md @@ -20,13 +20,13 @@ Use the navigation to the left to read about the available resources. provider "atlas" {} data "atlas_schema" "market" { - dev_db_url = "mysql://root:pass@localhost:3307/test" + dev_db_url = "mysql://root:pass@localhost:3307/market" src = file("${path.module}/schema.hcl") } resource "atlas_schema" "market" { hcl = data.atlas_schema.market.hcl - url = "mysql://root:pass@localhost:3306/test" + url = "mysql://root:pass@localhost:3306/market" } ``` diff --git a/examples/main.tf b/examples/main.tf index c1b96bb..f1495cc 100644 --- a/examples/main.tf +++ b/examples/main.tf @@ -24,7 +24,7 @@ resource "docker_container" "dev" { name = "devdb" env = [ "MYSQL_ROOT_PASSWORD=pass", - "MYSQL_DATABASE=test", + "MYSQL_DATABASE=market", ] ports { external = 3307 @@ -37,7 +37,7 @@ resource "docker_container" "prod" { name = "proddb" env = [ "MYSQL_ROOT_PASSWORD=pass", - "MYSQL_DATABASE=test", + "MYSQL_DATABASE=market", ] ports { external = 3306 @@ -47,12 +47,12 @@ resource "docker_container" "prod" { data "atlas_schema" "market" { depends_on = [ docker_container.dev ] - dev_db_url = "mysql://root:pass@localhost:3307/test" + dev_db_url = "mysql://root:pass@localhost:3307/market" src = file("${path.module}/schema.hcl") } resource "atlas_schema" "market" { depends_on = [ docker_container.prod ] hcl = data.atlas_schema.market.hcl - url = "mysql://root:pass@localhost:3306/test" + url = "mysql://root:pass@localhost:3306/market" } diff --git a/examples/provider/basic/main.tf b/examples/provider/basic/main.tf index e206e98..e9e4cf4 100644 --- a/examples/provider/basic/main.tf +++ b/examples/provider/basic/main.tf @@ -1,11 +1,11 @@ provider "atlas" {} data "atlas_schema" "market" { - dev_db_url = "mysql://root:pass@localhost:3307/test" + dev_db_url = "mysql://root:pass@localhost:3307/market" src = file("${path.module}/schema.hcl") } resource "atlas_schema" "market" { hcl = data.atlas_schema.market.hcl - url = "mysql://root:pass@localhost:3306/test" + url = "mysql://root:pass@localhost:3306/market" } diff --git a/examples/provider/main.tf b/examples/provider/main.tf index a260a4a..3f2c981 100644 --- a/examples/provider/main.tf +++ b/examples/provider/main.tf @@ -23,7 +23,7 @@ resource "docker_container" "dev" { name = "devdb" env = [ "MYSQL_ROOT_PASSWORD=pass", - "MYSQL_DATABASE=test", + "MYSQL_DATABASE=market", ] ports { external = 3307 @@ -36,7 +36,7 @@ resource "docker_container" "prod" { name = "proddb" env = [ "MYSQL_ROOT_PASSWORD=pass", - "MYSQL_DATABASE=test", + "MYSQL_DATABASE=market", ] ports { external = 3306 @@ -46,13 +46,13 @@ resource "docker_container" "prod" { data "atlas_schema" "market" { depends_on = [ docker_container.dev ] - dev_db_url = "mysql://root:pass@localhost:3307/test" + dev_db_url = "mysql://root:pass@localhost:3307/market" src = file("${path.module}/schema.hcl") } resource "atlas_schema" "market" { depends_on = [ docker_container.prod ] hcl = data.atlas_schema.market.hcl - url = "mysql://root:pass@localhost:3306/test" - dev_db_url = "mysql://root:pass@localhost:3307/test" + url = "mysql://root:pass@localhost:3306/market" + dev_db_url = "mysql://root:pass@localhost:3307/market" }