diff --git a/internal/provider/provider.go b/internal/provider/provider.go index a12faf6e..1fc2f1a8 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1,6 +1,8 @@ package provider import ( + "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -24,3 +26,8 @@ func New() *schema.Provider { }, } } + +func RemoveResourceFromState(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + d.SetId("") + return nil +} diff --git a/internal/provider/resource_id.go b/internal/provider/resource_id.go index 1c0262ea..c8fec007 100644 --- a/internal/provider/resource_id.go +++ b/internal/provider/resource_id.go @@ -1,14 +1,15 @@ package provider import ( + "context" "crypto/rand" "encoding/base64" "encoding/hex" - "errors" + "fmt" "math/big" "strings" - "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -28,11 +29,11 @@ the ` + "`create_before_destroy`" + ` lifecycle flag set to avoid conflicts with unique names during the brief period where both the old and new resources exist concurrently. `, - Create: CreateID, - Read: RepopulateEncodings, - Delete: schema.RemoveFromState, + CreateContext: CreateID, + ReadContext: RepopulateEncodings, + DeleteContext: RemoveResourceFromState, Importer: &schema.ResourceImporter{ - State: ImportID, + StateContext: ImportID, }, Schema: map[string]*schema.Schema{ @@ -95,31 +96,38 @@ exist concurrently. } } -func CreateID(d *schema.ResourceData, meta interface{}) error { +func CreateID(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics byteLength := d.Get("byte_length").(int) bytes := make([]byte, byteLength) n, err := rand.Reader.Read(bytes) if n != byteLength { - return errors.New("generated insufficient random bytes") + return append(diags, diag.Errorf("generated insufficient random bytes: %s", err)...) } if err != nil { - return errwrap.Wrapf("error generating random bytes: {{err}}", err) + return append(diags, diag.Errorf("error generating random bytes: %s", err)...) } b64Str := base64.RawURLEncoding.EncodeToString(bytes) d.SetId(b64Str) - return RepopulateEncodings(d, meta) + repopEncsDiags := RepopulateEncodings(ctx, d, meta) + if repopEncsDiags != nil { + return append(diags, repopEncsDiags...) + } + + return diags } -func RepopulateEncodings(d *schema.ResourceData, _ interface{}) error { +func RepopulateEncodings(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + var diags diag.Diagnostics prefix := d.Get("prefix").(string) base64Str := d.Id() bytes, err := base64.RawURLEncoding.DecodeString(base64Str) if err != nil { - return errwrap.Wrapf("Error decoding ID: {{err}}", err) + return append(diags, diag.Errorf("error decoding ID: %s", err)...) } b64StdStr := base64.StdEncoding.EncodeToString(bytes) @@ -138,7 +146,7 @@ func RepopulateEncodings(d *schema.ResourceData, _ interface{}) error { return nil } -func ImportID(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { +func ImportID(_ context.Context, d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { id := d.Id() sep := strings.LastIndex(id, ",") @@ -149,7 +157,7 @@ func ImportID(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, bytes, err := base64.RawURLEncoding.DecodeString(id) if err != nil { - return nil, errwrap.Wrapf("Error decoding ID: {{err}}", err) + return nil, fmt.Errorf("error decoding ID: %w", err) } d.Set("byte_length", len(bytes)) diff --git a/internal/provider/resource_integer.go b/internal/provider/resource_integer.go index bf9422ce..3ad1a4ea 100644 --- a/internal/provider/resource_integer.go +++ b/internal/provider/resource_integer.go @@ -1,11 +1,13 @@ package provider import ( + "context" "fmt" "strconv" "strings" "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -17,11 +19,11 @@ func resourceInteger() *schema.Resource { "This resource can be used in conjunction with resources that have the `create_before_destroy` " + "lifecycle flag set, to avoid conflicts with unique names during the brief period where both the " + "old and new resources exist concurrently.", - Create: CreateInteger, - Read: schema.Noop, - Delete: schema.RemoveFromState, + CreateContext: CreateInteger, + ReadContext: schema.NoopContext, + DeleteContext: RemoveResourceFromState, Importer: &schema.ResourceImporter{ - State: ImportInteger, + StateContext: ImportInteger, }, Schema: map[string]*schema.Schema{ @@ -70,13 +72,17 @@ func resourceInteger() *schema.Resource { } } -func CreateInteger(d *schema.ResourceData, meta interface{}) error { +func CreateInteger(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics min := d.Get("min").(int) max := d.Get("max").(int) seed := d.Get("seed").(string) if max <= min { - return fmt.Errorf("Minimum value needs to be smaller than maximum value") + return append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "minimum value needs to be smaller than maximum value", + }) } rand := NewRand(seed) number := rand.Intn((max+1)-min) + min @@ -87,7 +93,7 @@ func CreateInteger(d *schema.ResourceData, meta interface{}) error { return nil } -func ImportInteger(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { +func ImportInteger(_ context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { parts := strings.Split(d.Id(), ",") if len(parts) != 3 && len(parts) != 4 { return nil, fmt.Errorf("Invalid import usage: expecting {result},{min},{max} or {result},{min},{max},{seed}") diff --git a/internal/provider/resource_password.go b/internal/provider/resource_password.go index 8a81c538..6120beb7 100644 --- a/internal/provider/resource_password.go +++ b/internal/provider/resource_password.go @@ -11,10 +11,10 @@ func resourcePassword() *schema.Resource { "data handling in the [Terraform documentation](https://www.terraform.io/docs/language/state/sensitive-data.html).\n" + "\n" + "This resource *does* use a cryptographic random number generator.", - Create: createStringFunc(true), - Read: readNil, - Delete: schema.RemoveFromState, - Schema: stringSchemaV1(true), + CreateContext: createStringFunc(true), + ReadContext: readNil, + DeleteContext: RemoveResourceFromState, + Schema: stringSchemaV1(true), Importer: &schema.ResourceImporter{ StateContext: importStringFunc(true), }, diff --git a/internal/provider/resource_pet.go b/internal/provider/resource_pet.go index bb1e3dfd..de7d16d6 100644 --- a/internal/provider/resource_pet.go +++ b/internal/provider/resource_pet.go @@ -1,11 +1,12 @@ package provider import ( + "context" "fmt" "strings" petname "github.com/dustinkirkland/golang-petname" - + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -22,9 +23,9 @@ func resourcePet() *schema.Resource { "This resource can be used in conjunction with resources that have the `create_before_destroy` " + "lifecycle flag set, to avoid conflicts with unique names during the brief period where both the old " + "and new resources exist concurrently.", - Create: CreatePet, - Read: schema.Noop, - Delete: schema.RemoveFromState, + CreateContext: CreatePet, + ReadContext: schema.NoopContext, + DeleteContext: RemoveResourceFromState, Schema: map[string]*schema.Schema{ "keepers": { @@ -67,7 +68,7 @@ func resourcePet() *schema.Resource { } } -func CreatePet(d *schema.ResourceData, meta interface{}) error { +func CreatePet(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { length := d.Get("length").(int) separator := d.Get("separator").(string) prefix := d.Get("prefix").(string) diff --git a/internal/provider/resource_shuffle.go b/internal/provider/resource_shuffle.go index 05da8298..6e49059e 100644 --- a/internal/provider/resource_shuffle.go +++ b/internal/provider/resource_shuffle.go @@ -1,6 +1,9 @@ package provider import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -8,9 +11,9 @@ func resourceShuffle() *schema.Resource { return &schema.Resource{ Description: "The resource `random_shuffle` generates a random permutation of a list of strings " + "given as an argument.", - Create: CreateShuffle, - Read: schema.Noop, - Delete: schema.RemoveFromState, + CreateContext: CreateShuffle, + ReadContext: schema.NoopContext, + DeleteContext: RemoveResourceFromState, Schema: map[string]*schema.Schema{ "keepers": { @@ -71,7 +74,7 @@ func resourceShuffle() *schema.Resource { } } -func CreateShuffle(d *schema.ResourceData, _ interface{}) error { +func CreateShuffle(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { input := d.Get("input").([]interface{}) seed := d.Get("seed").(string) diff --git a/internal/provider/resource_string.go b/internal/provider/resource_string.go index 749ed846..ce77d92d 100644 --- a/internal/provider/resource_string.go +++ b/internal/provider/resource_string.go @@ -14,9 +14,11 @@ func resourceString() *schema.Resource { "Historically this resource's intended usage has been ambiguous as the original example used " + "it in a password. For backwards compatibility it will continue to exist. For unique ids please " + "use [random_id](id.html), for sensitive random values please use [random_password](password.html).", - Create: createStringFunc(false), - Read: readNil, - Delete: schema.RemoveFromState, + CreateContext: createStringFunc(false), + ReadContext: readNil, + DeleteContext: RemoveResourceFromState, + // MigrateState is deprecated but the implementation is being left in place as per the + // [SDK documentation](https://github.com/hashicorp/terraform-plugin-sdk/blob/main/helper/schema/resource.go#L91). MigrateState: resourceRandomStringMigrateState, SchemaVersion: 1, Schema: stringSchemaV1(false), diff --git a/internal/provider/resource_uuid.go b/internal/provider/resource_uuid.go index d92c9228..ea39fcec 100644 --- a/internal/provider/resource_uuid.go +++ b/internal/provider/resource_uuid.go @@ -1,8 +1,11 @@ package provider import ( + "context" + "github.com/hashicorp/errwrap" "github.com/hashicorp/go-uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -13,11 +16,11 @@ func resourceUuid() *schema.Resource { "\n" + "This resource uses [hashicorp/go-uuid](https://github.com/hashicorp/go-uuid) to generate a " + "UUID-formatted string for use with services needed a unique string identifier.", - Create: CreateUuid, - Read: schema.Noop, - Delete: schema.RemoveFromState, + CreateContext: CreateUuid, + ReadContext: schema.NoopContext, + DeleteContext: RemoveResourceFromState, Importer: &schema.ResourceImporter{ - State: ImportUuid, + StateContext: ImportUuid, }, Schema: map[string]*schema.Schema{ @@ -44,17 +47,18 @@ func resourceUuid() *schema.Resource { } } -func CreateUuid(d *schema.ResourceData, meta interface{}) error { +func CreateUuid(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics result, err := uuid.GenerateUUID() if err != nil { - return errwrap.Wrapf("error generating uuid: {{err}}", err) + return append(diags, diag.Errorf("error generating uuid: %s", err)...) } d.Set("result", result) d.SetId(result) return nil } -func ImportUuid(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { +func ImportUuid(_ context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { id := d.Id() bytes, err := uuid.ParseUUID(id) if err != nil { diff --git a/internal/provider/string.go b/internal/provider/string.go index 8ab2e686..b460bff4 100644 --- a/internal/provider/string.go +++ b/internal/provider/string.go @@ -9,7 +9,7 @@ import ( "math/big" "sort" - "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -123,12 +123,15 @@ func stringSchemaV1(sensitive bool) map[string]*schema.Schema { } } -func createStringFunc(sensitive bool) func(d *schema.ResourceData, meta interface{}) error { - return func(d *schema.ResourceData, meta interface{}) error { +func createStringFunc(sensitive bool) func(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return func(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { const numChars = "0123456789" const lowerChars = "abcdefghijklmnopqrstuvwxyz" const upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - var specialChars = "!@#$%&*()-_=+[]{}<>:?" + var ( + specialChars = "!@#$%&*()-_=+[]{}<>:?" + diags diag.Diagnostics + ) length := d.Get("length").(int) upper := d.Get("upper").(bool) @@ -169,18 +172,18 @@ func createStringFunc(sensitive bool) func(d *schema.ResourceData, meta interfac for k, v := range minMapping { s, err := generateRandomBytes(&k, v) if err != nil { - return errwrap.Wrapf("error generating random bytes: {{err}}", err) + return append(diags, diag.Errorf("error generating random bytes: %s", err)...) } result = append(result, s...) } s, err := generateRandomBytes(&chars, length-len(result)) if err != nil { - return errwrap.Wrapf("error generating random bytes: {{err}}", err) + return append(diags, diag.Errorf("error generating random bytes: %s", err)...) } result = append(result, s...) order := make([]byte, len(result)) if _, err := rand.Read(order); err != nil { - return errwrap.Wrapf("error generating random bytes: {{err}}", err) + return append(diags, diag.Errorf("error generating random bytes: %s", err)...) } sort.Slice(result, func(i, j int) bool { return order[i] < order[j] @@ -209,7 +212,7 @@ func generateRandomBytes(charSet *string, length int) ([]byte, error) { return bytes, nil } -func readNil(d *schema.ResourceData, meta interface{}) error { +func readNil(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { return nil } diff --git a/tools/tools.go b/tools/tools.go index f03ce3dd..8abc7c8d 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -1,3 +1,4 @@ +//go:build tools // +build tools package tools