From e1f18626aa83e092801d5d44c27fe74e1db7c89c Mon Sep 17 00:00:00 2001 From: Paddy Carver Date: Wed, 8 Sep 2021 06:59:49 -0700 Subject: [PATCH] Add tests using cty. Supporting tests for hashicorp/terraform-plugin-sdk#802. Testing the new cty stuff hanging off the ResourceData and ResourceDiff types. --- go.mod | 4 +- go.sum | 2 - .../sdkv2provider/data_source_regions_cty.go | 57 ++++++ .../data_source_regions_cty_test.go | 27 +++ internal/sdkv2provider/provider.go | 10 +- internal/sdkv2provider/provider_test.go | 2 + internal/sdkv2provider/resource_user_cty.go | 186 ++++++++++++++++++ .../sdkv2provider/resource_user_cty_test.go | 54 +++++ 8 files changed, 335 insertions(+), 7 deletions(-) create mode 100644 internal/sdkv2provider/data_source_regions_cty.go create mode 100644 internal/sdkv2provider/data_source_regions_cty_test.go create mode 100644 internal/sdkv2provider/resource_user_cty.go create mode 100644 internal/sdkv2provider/resource_user_cty_test.go diff --git a/go.mod b/go.mod index 33f61a2..9f7b9d9 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,7 @@ require ( github.com/hashicorp/go-memdb v1.3.2 github.com/hashicorp/terraform-plugin-go v0.3.1 github.com/hashicorp/terraform-plugin-mux v0.2.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.1 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.2-0.20210908140353-352c0d22644d ) + +replace github.com/hashicorp/terraform-plugin-sdk/v2 => ../terraform-plugin-sdk diff --git a/go.sum b/go.sum index 015b30f..9b062f6 100644 --- a/go.sum +++ b/go.sum @@ -207,8 +207,6 @@ github.com/hashicorp/terraform-plugin-go v0.3.1 h1:ML+THFcqpdR049gqrbEFDFo99va2W github.com/hashicorp/terraform-plugin-go v0.3.1/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM= github.com/hashicorp/terraform-plugin-mux v0.2.0 h1:d+IQlxGpztO23nrf5X3ZL8bn1JeTxwz5lPuzezEUq7w= github.com/hashicorp/terraform-plugin-mux v0.2.0/go.mod h1:ZLiSpKrAtyqS7d3QydVIz13c/j4ic0RMrhQ5Hu+S8zM= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.1 h1:vpzKKP2dIFb9n89AG8Wxl758/5JSZWZH0OuKdlq0M38= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.1/go.mod h1:o3pdss6ynDZW9FfiZ+rETUH5LEVufrXdhwLU+5OiRo0= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= diff --git a/internal/sdkv2provider/data_source_regions_cty.go b/internal/sdkv2provider/data_source_regions_cty.go new file mode 100644 index 0000000..019812c --- /dev/null +++ b/internal/sdkv2provider/data_source_regions_cty.go @@ -0,0 +1,57 @@ +package sdkv2 + +import ( + "context" + "errors" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-corner/internal/backend" +) + +func dataSourceRegionsCty() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceRegionsCtyRead, + + Schema: map[string]*schema.Schema{ + "filter": { + Type: schema.TypeString, + Required: true, + }, + "names": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func dataSourceRegionsCtyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*backend.Client) + + config := d.GetRawConfig().AsValueMap() + filter := config["filter"].AsString() + if filter == "" { + return diag.FromErr(errors.New("filter wasn't set")) + } + + regions, err := client.ReadRegions() + if err != nil { + return diag.FromErr(err) + } + + names := []string{} + for _, r := range regions { + names = append(names, r.Name) + } + + d.SetId("regions") + + err = d.Set("names", names) + if err != nil { + return diag.FromErr(err) + } + + return nil +} diff --git a/internal/sdkv2provider/data_source_regions_cty_test.go b/internal/sdkv2provider/data_source_regions_cty_test.go new file mode 100644 index 0000000..c153038 --- /dev/null +++ b/internal/sdkv2provider/data_source_regions_cty_test.go @@ -0,0 +1,27 @@ +package sdkv2 + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func testAccDataSourceRegionsCty(t *testing.T) resource.TestCase { + return resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: configDataSourceRegionsCtyBasic, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.corner_regions_cty.foo", "names.#")), + }, + }, + } +} + +const configDataSourceRegionsCtyBasic = ` +data "corner_regions_cty" "foo" { + filter = "foo" +} +` diff --git a/internal/sdkv2provider/provider.go b/internal/sdkv2provider/provider.go index 27654cb..9392837 100644 --- a/internal/sdkv2provider/provider.go +++ b/internal/sdkv2provider/provider.go @@ -11,12 +11,14 @@ import ( func New() *schema.Provider { p := &schema.Provider{ DataSourcesMap: map[string]*schema.Resource{ - "corner_regions": dataSourceRegions(), - "corner_bigint": dataSourceBigint(), + "corner_regions": dataSourceRegions(), + "corner_bigint": dataSourceBigint(), + "corner_regions_cty": dataSourceRegionsCty(), }, ResourcesMap: map[string]*schema.Resource{ - "corner_user": resourceUser(), - "corner_bigint": resourceBigint(), + "corner_user": resourceUser(), + "corner_bigint": resourceBigint(), + "corner_user_cty": resourceUserCty(), }, } diff --git a/internal/sdkv2provider/provider_test.go b/internal/sdkv2provider/provider_test.go index 60632e1..d526427 100644 --- a/internal/sdkv2provider/provider_test.go +++ b/internal/sdkv2provider/provider_test.go @@ -45,4 +45,6 @@ var TestCases = map[string]func(*testing.T) resource.TestCase{ "corner_regions": testAccDataSourceRegions, "corner_bigint_data": testAccDataSourceBigint, "corner_bigint": testAccResourceBigint, + "corner_user_cty": testAccResourceUserCty, + "corner_regions_cty": testAccDataSourceRegionsCty, } diff --git a/internal/sdkv2provider/resource_user_cty.go b/internal/sdkv2provider/resource_user_cty.go new file mode 100644 index 0000000..0c247b2 --- /dev/null +++ b/internal/sdkv2provider/resource_user_cty.go @@ -0,0 +1,186 @@ +package sdkv2 + +import ( + "context" + "errors" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-corner/internal/backend" +) + +func resourceUserCty() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceUserCtyCreate, + ReadContext: resourceUserCtyRead, + UpdateContext: resourceUserCtyUpdate, + DeleteContext: resourceUserCtyDelete, + CustomizeDiff: resourceUserCtyCustomizeDiff, + + Schema: map[string]*schema.Schema{ + "email": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "age": { + Type: schema.TypeInt, + Required: true, + }, + }, + } +} + +func resourceUserCtyCustomizeDiff(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error { + if d.Get("email").(string) != "" && d.GetRawConfig().IsNull() { + return errors.New("raw config not set in plan") + } + if d.Id() != "" && d.GetRawState().IsNull() { + return errors.New("raw state not set in plan") + } + if d.GetRawPlan().IsNull() { + return errors.New("raw plan not set in plan") + } + return nil +} + +func resourceUserCtyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*backend.Client) + config := d.GetRawConfig().AsValueMap() + age, _ := config["age"].AsBigFloat().Int64() + newUser := &backend.User{ + Email: config["email"].AsString(), + Name: config["name"].AsString(), + Age: int(age), + } + + // plan should be set + if d.GetRawPlan().IsNull() { + return diag.FromErr(errors.New("plan wasn't set")) + } + + // state should not be set + if !d.GetRawState().IsNull() { + return diag.FromErr(fmt.Errorf("state was %s, not null", d.GetRawState().GoString())) + } + + err := client.CreateUser(newUser) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(newUser.Email) + + err = d.Set("name", newUser.Name) + if err != nil { + return diag.FromErr(err) + } + err = d.Set("age", newUser.Age) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceUserCtyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*backend.Client) + + // state should be set + state := d.GetRawState().AsValueMap() + email := state["email"].AsString() + + // plan should not be set + if !d.GetRawPlan().IsNull() { + return diag.FromErr(fmt.Errorf("plan was %s, not null", d.GetRawPlan().GoString())) + } + + // config should not be set + if !d.GetRawConfig().IsNull() { + return diag.FromErr(fmt.Errorf("config was %s, not null", d.GetRawConfig().GoString())) + } + + p, err := client.ReadUser(email) + if err != nil { + return diag.FromErr(err) + } + + if p == nil { + d.SetId("") + return nil + } + + err = d.Set("name", p.Name) + if err != nil { + return diag.FromErr(err) + } + err = d.Set("age", p.Age) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceUserCtyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*backend.Client) + + config := d.GetRawConfig().AsValueMap() + age, _ := config["age"].AsBigFloat().Int64() + user := &backend.User{ + Email: config["email"].AsString(), + Name: config["name"].AsString(), + Age: int(age), + } + + // plan should be set + if d.GetRawPlan().IsNull() { + return diag.FromErr(errors.New("plan wasn't set")) + } + + // state should be set + if d.GetRawState().IsNull() { + return diag.FromErr(errors.New("state wasn't set")) + } + + err := client.UpdateUser(user) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceUserCtyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*backend.Client) + + state := d.GetRawState().AsValueMap() + age, _ := state["age"].AsBigFloat().Int64() + user := &backend.User{ + Email: state["email"].AsString(), + Name: state["name"].AsString(), + Age: int(age), + } + + // plan should be null + if !d.GetRawPlan().IsNull() { + return diag.FromErr(fmt.Errorf("plan was set to %s", d.GetRawPlan().GoString())) + } + + // config should be null + if !d.GetRawConfig().IsNull() { + return diag.FromErr(fmt.Errorf("config was set to %s", d.GetRawConfig().GoString())) + } + + err := client.DeleteUser(user) + if err != nil { + return diag.FromErr(err) + } + + return nil +} diff --git a/internal/sdkv2provider/resource_user_cty_test.go b/internal/sdkv2provider/resource_user_cty_test.go new file mode 100644 index 0000000..95a9db9 --- /dev/null +++ b/internal/sdkv2provider/resource_user_cty_test.go @@ -0,0 +1,54 @@ +package sdkv2 + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func testAccResourceUserCty(t *testing.T) resource.TestCase { + return resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: configResourceUserCtyBasic, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "corner_user.foo", "email", "ford@prefect.co"), + resource.TestCheckResourceAttr( + "corner_user.foo", "name", "Ford Prefect"), + resource.TestCheckResourceAttr( + "corner_user.foo", "age", "200"), + ), + }, + { + Config: configResourceUserCtyUpdate, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "corner_user.foo", "email", "ford@prefect.co"), + resource.TestCheckResourceAttr( + "corner_user.foo", "name", "Ford Prefect II"), + resource.TestCheckResourceAttr( + "corner_user.foo", "age", "300"), + ), + }, + }, + } +} + +const configResourceUserCtyBasic = ` +resource "corner_user" "foo" { + email = "ford@prefect.co" + name = "Ford Prefect" + age = 200 +} +` + +const configResourceUserCtyUpdate = ` +resource "corner_user" "foo" { + email = "ford@prefect.co" + name = "Ford Prefect II" + age = 300 +} +`