Skip to content
8 changes: 8 additions & 0 deletions internal/sdkv2provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func New() *schema.Provider {
ResourcesMap: map[string]*schema.Resource{
"corner_user": resourceUser(),
"corner_user_identity": resourceUserIdentity(),
"corner_user_identity_upgrade": resourceUserIdentityUpgrade(0),
"corner_writeonly": resourceWriteOnly(),
"corner_writeonly_import": resourceWriteOnlyImport(),
"corner_writeonly_upgrade": resourceWriteOnlyUpgrade(0),
Expand Down Expand Up @@ -63,3 +64,10 @@ func NewWithUpgradeVersion(version int) *schema.Provider {

return p
}

func NewWithIdentityUpgradeVersion(version int) *schema.Provider {
p := New()
p.ResourcesMap["corner_user_identity_upgrade"] = resourceUserIdentityUpgrade(version)

return p
}
1 change: 1 addition & 0 deletions internal/sdkv2provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func TestAccTests(t *testing.T) {
var TestCases = map[string]func(*testing.T) resource.TestCase{
"corner_user": testAccResourceUser,
"corner_user_identity": testAccResourceUserIdentity,
"corner_user_identity_upgrade": testAccResourceUserIdentityUpgrade,
"corner_regions": testAccDataSourceRegions,
"corner_bigint_data": testAccDataSourceBigint,
"corner_bigint": testAccResourceBigint,
Expand Down
27 changes: 23 additions & 4 deletions internal/sdkv2provider/resource_user_identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import (
"context"

"github.com/hashicorp/terraform-plugin-go/tftypes"
"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"
Expand Down Expand Up @@ -45,14 +46,29 @@
},
}
},
IdentityUpgraders: []schema.IdentityUpgrader{
{
Version: 1,
Type: tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"email": tftypes.String,
},
},
},
},
},

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughWithIdentity("email"),

Check failure on line 62 in internal/sdkv2provider/resource_user_identity.go

View workflow job for this annotation

GitHub Actions / Build

undefined: schema.ImportStatePassthroughWithIdentity (typecheck)

Check failure on line 62 in internal/sdkv2provider/resource_user_identity.go

View workflow job for this annotation

GitHub Actions / Build

undefined: schema.ImportStatePassthroughWithIdentity) (typecheck)
},
}
}

func resourceUserIdentityCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*backend.Client)
email := d.Get("email").(string)
newUser := &backend.User{
Email: d.Get("email").(string),
Email: email,
Name: d.Get("name").(string),
Age: d.Get("age").(int),
}
Expand All @@ -61,14 +77,15 @@
if err != nil {
return diag.FromErr(err)
}
d.SetId(email)

return resourceUserIdentityRead(ctx, d, meta)
}

func resourceUserIdentityRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*backend.Client)

email := d.Get("email").(string)
email := d.Id()

p, err := client.ReadUser(email)
if err != nil {
Expand All @@ -79,8 +96,10 @@
return nil
}

d.SetId(email)

err = d.Set("email", email)
if err != nil {
return diag.FromErr(err)
}
err = d.Set("name", p.Name)
if err != nil {
return diag.FromErr(err)
Expand Down
10 changes: 6 additions & 4 deletions internal/sdkv2provider/resource_user_identity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package sdkv2
import (
"testing"

"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
Expand All @@ -16,10 +15,8 @@ import (
func testAccResourceUserIdentity(t *testing.T) resource.TestCase {
return resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
// Latest alpha version that this JSON data is available in
// https://github.com/hashicorp/terraform/releases/tag/v1.12.0-alpha20250319
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(version.Must(version.NewVersion("1.12.0-alpha20250319"))),
tfversion.SkipBelow(tfversion.Version1_12_0),
},
Providers: testAccProviders,
Steps: []resource.TestStep{
Expand All @@ -31,6 +28,11 @@ func testAccResourceUserIdentity(t *testing.T) resource.TestCase {
}),
},
},
{
ResourceName: "corner_user_identity.foo",
ImportState: true,
ImportStateKind: resource.ImportBlockWithResourceIdentity,
},
},
}
}
Expand Down
201 changes: 201 additions & 0 deletions internal/sdkv2provider/resource_user_identity_upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

//nolint:forcetypeassert // Test SDK provider
package sdkv2

import (
"context"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-go/tftypes"
"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 resourceUserIdentityUpgrade(version int) *schema.Resource {
return &schema.Resource{
CreateContext: resourceUserIdentityUpgradeCreate(version),
ReadContext: resourceUserIdentityUpgradeRead(version),
UpdateContext: resourceUserIdentityUpgradeUpdate(version),
DeleteContext: resourceUserIdentityUpgradeDelete(version),

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,
},
},

Identity: &schema.ResourceIdentity{
Version: int64(version),
SchemaFunc: func() map[string]*schema.Schema {
if version == 0 {
return map[string]*schema.Schema{
"email": {
Type: schema.TypeString,
RequiredForImport: true,
},
}
}
if version == 1 {
return map[string]*schema.Schema{
"local_part": {
Type: schema.TypeString,
RequiredForImport: true,
},
"domain": {
Type: schema.TypeString,
RequiredForImport: true,
},
}
}
panic(fmt.Sprintf("unknown version %d", version))
},
IdentityUpgraders: []schema.IdentityUpgrader{
{
Version: 0,
Type: tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"email": tftypes.String,
},
},
Upgrade: func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
email := rawState["email"].(string)
parts := strings.Split(email, "@")
if len(parts) != 2 {
return nil, fmt.Errorf("invalid email format: %s", email)
}
return map[string]interface{}{
"local_part": parts[0],
"domain": parts[1],
}, nil
},
},
},
},
}
}

func resourceUserIdentityUpgradeCreate(version int) schema.CreateContextFunc {
return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*backend.Client)
newUser := &backend.User{
Email: d.Get("email").(string),
Name: d.Get("name").(string),
Age: d.Get("age").(int),
}

err := client.CreateUser(newUser)
if err != nil {
return diag.FromErr(err)
}

return resourceUserIdentityUpgradeRead(version)(ctx, d, meta)
}
}

func resourceUserIdentityUpgradeRead(version int) schema.ReadContextFunc {
return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*backend.Client)

email := d.Get("email").(string)

p, err := client.ReadUser(email)
if err != nil {
return diag.FromErr(err)
}

if p == nil {
return nil
}

d.SetId(email)

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)
}

identity, err := d.Identity()
if err != nil {
return diag.FromErr(err)
}

if version == 0 {
err = identity.Set("email", email)
if err != nil {
return diag.FromErr(err)
}
} else if version == 1 {
parts := strings.Split(email, "@")
if len(parts) != 2 {
return diag.FromErr(fmt.Errorf("invalid email format: %s", email))
}

err = identity.Set("local_part", parts[0])
if err != nil {
return diag.FromErr(err)
}
err = identity.Set("domain", parts[1])
if err != nil {
return diag.FromErr(err)
}
}

return nil
}
}

func resourceUserIdentityUpgradeUpdate(version int) schema.UpdateContextFunc {
return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*backend.Client)

user := &backend.User{
Email: d.Get("email").(string),
Name: d.Get("name").(string),
Age: d.Get("age").(int),
}

err := client.UpdateUser(user)
if err != nil {
return diag.FromErr(err)
}

return nil
}
}

func resourceUserIdentityUpgradeDelete(version int) schema.DeleteContextFunc {
return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*backend.Client)

user := &backend.User{
Email: d.Get("email").(string),
Name: d.Get("name").(string),
Age: d.Get("age").(int),
}

err := client.DeleteUser(user)
if err != nil {
return diag.FromErr(err)
}

return nil
}
}
60 changes: 60 additions & 0 deletions internal/sdkv2provider/resource_user_identity_upgrade_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package sdkv2

import (
"testing"

"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
)

func testAccResourceUserIdentityUpgrade(t *testing.T) resource.TestCase {
return resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_12_0),
},
Steps: []resource.TestStep{
{
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"corner": func() (tfprotov5.ProviderServer, error) { //nolint
return NewWithIdentityUpgradeVersion(0).GRPCProvider(), nil
},
},
Config: `resource "corner_user_identity_upgrade" "foo" {
email = "ford@prefect.co"
name = "Ford Prefect"
age = 200
}`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectIdentity("corner_user_identity_upgrade.foo", map[string]knownvalue.Check{
"email": knownvalue.StringExact("ford@prefect.co"),
}),
},
},
{
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"corner": func() (tfprotov5.ProviderServer, error) { //nolint
return NewWithIdentityUpgradeVersion(1).GRPCProvider(), nil
},
},
Config: `resource "corner_user_identity_upgrade" "foo" {
email = "ford@prefect.co"
name = "Ford Prefect"
age = 200
}`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectIdentity("corner_user_identity_upgrade.foo", map[string]knownvalue.Check{
"local_part": knownvalue.StringExact("ford"),
"domain": knownvalue.StringExact("prefect.co"),
}),
},
},
},
}
}
Loading