diff --git a/internal/auth0/connection/resource_client.go b/internal/auth0/connection/resource_client.go index 8652f5c8a..cce82d589 100644 --- a/internal/auth0/connection/resource_client.go +++ b/internal/auth0/connection/resource_client.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/auth0/terraform-provider-auth0/internal/mutex" + internalSchema "github.com/auth0/terraform-provider-auth0/internal/schema" ) var ( @@ -49,7 +50,7 @@ func NewClientResource() *schema.Resource { ReadContext: readConnectionClient, DeleteContext: deleteConnectionClient, Importer: &schema.ResourceImporter{ - StateContext: importConnectionClient, + StateContext: internalSchema.ImportResourcePairID("connection_id", "client_id"), }, Description: "With this resource, you can enable a single client on a connection.", } diff --git a/internal/auth0/connection/resource_client_import.go b/internal/auth0/connection/resource_client_import.go deleted file mode 100644 index 5cddcf8e1..000000000 --- a/internal/auth0/connection/resource_client_import.go +++ /dev/null @@ -1,36 +0,0 @@ -package connection - -import ( - "context" - "strings" - - "github.com/hashicorp/go-multierror" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func importConnectionClient( - _ context.Context, - data *schema.ResourceData, - _ interface{}, -) ([]*schema.ResourceData, error) { - rawID := data.Id() - if rawID == "" { - return nil, errEmptyConnectionClientID - } - - if !strings.Contains(rawID, ":") { - return nil, errInvalidConnectionClientIDFormat - } - - idPair := strings.Split(rawID, ":") - if len(idPair) != 2 { - return nil, errInvalidConnectionClientIDFormat - } - - result := multierror.Append( - data.Set("connection_id", idPair[0]), - data.Set("client_id", idPair[1]), - ) - - return []*schema.ResourceData{data}, result.ErrorOrNil() -} diff --git a/internal/auth0/connection/resource_client_import_test.go b/internal/auth0/connection/resource_client_import_test.go deleted file mode 100644 index fab69deb4..000000000 --- a/internal/auth0/connection/resource_client_import_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package connection - -import ( - "context" - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/stretchr/testify/assert" -) - -func TestImportConnectionClient(t *testing.T) { - var testCases = []struct { - testName string - givenID string - expectedConnectionID string - expectedClientID string - expectedError error - }{ - { - testName: "it correctly parses the resource ID", - givenID: "conn_5678:client_1234", - expectedConnectionID: "conn_5678", - expectedClientID: "client_1234", - }, - { - testName: "it fails when the given ID is empty", - givenID: "", - expectedError: fmt.Errorf("ID cannot be empty"), - }, - { - testName: "it fails when the given ID does not have \":\" as a separator", - givenID: "client_1234conn_5678", - expectedError: fmt.Errorf("ID must be formated as :"), - }, - { - testName: "it fails when the given ID has too many separators", - givenID: "client_1234:conn_5678:", - expectedError: fmt.Errorf("ID must be formated as :"), - }, - } - - for _, testCase := range testCases { - t.Run(testCase.testName, func(t *testing.T) { - data := schema.TestResourceDataRaw(t, NewClientResource().Schema, nil) - data.SetId(testCase.givenID) - - actualData, err := importConnectionClient(context.Background(), data, nil) - - if testCase.expectedError != nil { - assert.EqualError(t, err, testCase.expectedError.Error()) - assert.Nil(t, actualData) - return - } - - assert.Equal(t, actualData[0].Get("connection_id").(string), testCase.expectedConnectionID) - assert.Equal(t, actualData[0].Get("client_id").(string), testCase.expectedClientID) - assert.Equal(t, actualData[0].Id(), testCase.givenID) - }) - } -} diff --git a/internal/auth0/organization/resource_connection.go b/internal/auth0/organization/resource_connection.go index e679ac082..7185ef013 100644 --- a/internal/auth0/organization/resource_connection.go +++ b/internal/auth0/organization/resource_connection.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/auth0/terraform-provider-auth0/internal/mutex" + internalSchema "github.com/auth0/terraform-provider-auth0/internal/schema" ) var ( @@ -27,7 +28,7 @@ func NewConnectionResource() *schema.Resource { UpdateContext: updateOrganizationConnection, DeleteContext: deleteOrganizationConnection, Importer: &schema.ResourceImporter{ - StateContext: importOrganizationConnection, + StateContext: internalSchema.ImportResourcePairID("organization_id", "connection_id"), }, Schema: map[string]*schema.Schema{ "organization_id": { diff --git a/internal/auth0/organization/resource_import.go b/internal/auth0/organization/resource_import.go deleted file mode 100644 index a47fff6c1..000000000 --- a/internal/auth0/organization/resource_import.go +++ /dev/null @@ -1,63 +0,0 @@ -package organization - -import ( - "context" - "strings" - - "github.com/hashicorp/go-multierror" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func importOrganizationConnection( - _ context.Context, - data *schema.ResourceData, - _ interface{}, -) ([]*schema.ResourceData, error) { - rawID := data.Id() - if rawID == "" { - return nil, errEmptyOrganizationConnectionID - } - - if !strings.Contains(rawID, ":") { - return nil, errInvalidOrganizationConnectionIDFormat - } - - idPair := strings.Split(rawID, ":") - if len(idPair) != 2 { - return nil, errInvalidOrganizationConnectionIDFormat - } - - result := multierror.Append( - data.Set("organization_id", idPair[0]), - data.Set("connection_id", idPair[1]), - ) - - return []*schema.ResourceData{data}, result.ErrorOrNil() -} - -func importOrganizationMember( - _ context.Context, - data *schema.ResourceData, - _ interface{}, -) ([]*schema.ResourceData, error) { - rawID := data.Id() - if rawID == "" { - return nil, errEmptyOrganizationMemberID - } - - if !strings.Contains(rawID, ":") { - return nil, errInvalidOrganizationMemberIDFormat - } - - idPair := strings.Split(rawID, ":") - if len(idPair) != 2 { - return nil, errInvalidOrganizationMemberIDFormat - } - - result := multierror.Append( - data.Set("organization_id", idPair[0]), - data.Set("user_id", idPair[1]), - ) - - return []*schema.ResourceData{data}, result.ErrorOrNil() -} diff --git a/internal/auth0/organization/resource_import_test.go b/internal/auth0/organization/resource_import_test.go deleted file mode 100644 index d14bc0ba1..000000000 --- a/internal/auth0/organization/resource_import_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package organization - -import ( - "context" - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/stretchr/testify/assert" -) - -func TestImportOrganizationConnection(t *testing.T) { - var testCases = []struct { - testName string - givenID string - expectedOrganizationID string - expectedConnectionID string - expectedError error - }{ - { - testName: "it correctly parses the resource ID", - givenID: "org_1234:conn_5678", - expectedOrganizationID: "org_1234", - expectedConnectionID: "conn_5678", - }, - { - testName: "it fails when the given ID is empty", - givenID: "", - expectedError: fmt.Errorf("ID cannot be empty"), - }, - { - testName: "it fails when the given ID does not have \":\" as a separator", - givenID: "org_1234conn_5678", - expectedError: fmt.Errorf("ID must be formated as :"), - }, - { - testName: "it fails when the given ID has too many separators", - givenID: "org_1234:conn_5678:", - expectedError: fmt.Errorf("ID must be formated as :"), - }, - } - - for _, testCase := range testCases { - t.Run(testCase.testName, func(t *testing.T) { - data := schema.TestResourceDataRaw(t, NewConnectionResource().Schema, nil) - data.SetId(testCase.givenID) - - actualData, err := importOrganizationConnection(context.Background(), data, nil) - - if testCase.expectedError != nil { - assert.EqualError(t, err, testCase.expectedError.Error()) - assert.Nil(t, actualData) - return - } - - assert.Equal(t, actualData[0].Get("organization_id").(string), testCase.expectedOrganizationID) - assert.Equal(t, actualData[0].Get("connection_id").(string), testCase.expectedConnectionID) - assert.Equal(t, actualData[0].Id(), testCase.givenID) - }) - } -} - -func TestImportOrganizationMember(t *testing.T) { - var testCases = []struct { - testName string - givenID string - expectedOrganizationID string - expectedUserID string - expectedError error - }{ - { - testName: "it correctly parses the resource ID", - givenID: "org_1234:auth0|62d82", - expectedOrganizationID: "org_1234", - expectedUserID: "auth0|62d82", - }, - { - testName: "it fails when the given ID is empty", - givenID: "", - expectedError: fmt.Errorf("ID cannot be empty"), - }, - { - testName: "it fails when the given ID does not have \":\" as a separator", - givenID: "org_1234auth0|62d82", - expectedError: fmt.Errorf("ID must be formated as :"), - }, - { - testName: "it fails when the given ID has too many separators", - givenID: "org_1234:auth0|62d82:", - expectedError: fmt.Errorf("ID must be formated as :"), - }, - } - - for _, testCase := range testCases { - t.Run(testCase.testName, func(t *testing.T) { - data := schema.TestResourceDataRaw(t, NewMemberResource().Schema, nil) - data.SetId(testCase.givenID) - - actualData, err := importOrganizationMember(context.Background(), data, nil) - - if testCase.expectedError != nil { - assert.EqualError(t, err, testCase.expectedError.Error()) - assert.Nil(t, actualData) - return - } - - assert.Equal(t, actualData[0].Get("organization_id").(string), testCase.expectedOrganizationID) - assert.Equal(t, actualData[0].Get("user_id").(string), testCase.expectedUserID) - assert.Equal(t, actualData[0].Id(), testCase.givenID) - }) - } -} diff --git a/internal/auth0/organization/resource_member.go b/internal/auth0/organization/resource_member.go index c0975b927..5f65ac36f 100644 --- a/internal/auth0/organization/resource_member.go +++ b/internal/auth0/organization/resource_member.go @@ -10,14 +10,10 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/auth0/terraform-provider-auth0/internal/mutex" + internalSchema "github.com/auth0/terraform-provider-auth0/internal/schema" "github.com/auth0/terraform-provider-auth0/internal/value" ) -var ( - errEmptyOrganizationMemberID = fmt.Errorf("ID cannot be empty") - errInvalidOrganizationMemberIDFormat = fmt.Errorf("ID must be formated as :") -) - // NewMemberResource will return a new auth0_organization_member resource. func NewMemberResource() *schema.Resource { return &schema.Resource{ @@ -27,7 +23,7 @@ func NewMemberResource() *schema.Resource { UpdateContext: updateOrganizationMember, DeleteContext: deleteOrganizationMember, Importer: &schema.ResourceImporter{ - StateContext: importOrganizationMember, + StateContext: internalSchema.ImportResourcePairID("organization_id", "user_id"), }, Schema: map[string]*schema.Schema{ "organization_id": { diff --git a/internal/auth0/prompt/resource_custom_text.go b/internal/auth0/prompt/resource_custom_text.go index cd0357dcc..7a96f437b 100644 --- a/internal/auth0/prompt/resource_custom_text.go +++ b/internal/auth0/prompt/resource_custom_text.go @@ -9,11 +9,12 @@ import ( "strings" "github.com/auth0/go-auth0/management" - "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + internalSchema "github.com/auth0/terraform-provider-auth0/internal/schema" ) var ( @@ -28,8 +29,6 @@ var ( "hu", "id", "is", "it", "ja", "ko", "lt", "lv", "nb", "nl", "pl", "pt", "pt-BR", "pt-PT", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-TW", } - errEmptyPromptCustomTextID = fmt.Errorf("ID cannot be empty") - errInvalidPromptCustomTextIDFormat = fmt.Errorf("ID must be formated as prompt:language") ) // NewCustomTextResource will return a new auth0_prompt_custom_text resource. @@ -40,7 +39,7 @@ func NewCustomTextResource() *schema.Resource { UpdateContext: updatePromptCustomText, DeleteContext: deletePromptCustomText, Importer: &schema.ResourceImporter{ - StateContext: importPromptCustomText, + StateContext: internalSchema.ImportResourcePairID("prompt", "language"), }, Description: "With this resource, you can manage custom text on your Auth0 prompts. You can read more about " + "custom texts [here](https://auth0.com/docs/customize/universal-login-pages/customize-login-text-prompts).", @@ -71,22 +70,6 @@ func NewCustomTextResource() *schema.Resource { } } -func importPromptCustomText(ctx context.Context, d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { - prompt, language, err := getPromptAndLanguage(d) - if err != nil { - return []*schema.ResourceData{}, err - } - - d.SetId(d.Id()) - - result := multierror.Append( - d.Set("prompt", prompt), - d.Set("language", language), - ) - - return []*schema.ResourceData{d}, result.ErrorOrNil() -} - func createPromptCustomText(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { d.SetId(d.Get("prompt").(string) + ":" + d.Get("language").(string)) return updatePromptCustomText(ctx, d, m) @@ -115,20 +98,22 @@ func readPromptCustomText(ctx context.Context, d *schema.ResourceData, m interfa func updatePromptCustomText(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { api := m.(*management.Management) - prompt, language, err := getPromptAndLanguage(d) - if err != nil { - return diag.FromErr(err) + + prompt := d.Get("prompt").(string) + language := d.Get("language").(string) + body := d.Get("body").(string) + + if body == "" { + return nil } - if d.Get("body").(string) != "" { - var body map[string]interface{} - if err := json.Unmarshal([]byte(d.Get("body").(string)), &body); err != nil { - return diag.FromErr(err) - } + var payload map[string]interface{} + if err := json.Unmarshal([]byte(body), &payload); err != nil { + return diag.FromErr(err) + } - if err := api.Prompt.SetCustomText(prompt, language, body); err != nil { - return diag.FromErr(err) - } + if err := api.Prompt.SetCustomText(prompt, language, payload); err != nil { + return diag.FromErr(err) } return readPromptCustomText(ctx, d, m) @@ -147,24 +132,6 @@ func deletePromptCustomText(ctx context.Context, d *schema.ResourceData, m inter return nil } -func getPromptAndLanguage(d *schema.ResourceData) (string, string, error) { - rawID := d.Id() - if rawID == "" { - return "", "", errEmptyPromptCustomTextID - } - - if !strings.Contains(rawID, ":") { - return "", "", errInvalidPromptCustomTextIDFormat - } - - idPair := strings.Split(rawID, ":") - if len(idPair) != 2 { - return "", "", errInvalidPromptCustomTextIDFormat - } - - return idPair[0], idPair[1], nil -} - func marshalCustomTextBody(b map[string]interface{}) (string, error) { bodyBytes, err := json.Marshal(b) if err != nil { diff --git a/internal/schema/importer.go b/internal/schema/importer.go new file mode 100644 index 000000000..c91e35484 --- /dev/null +++ b/internal/schema/importer.go @@ -0,0 +1,44 @@ +package schema + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +const separator = ":" + +var ( + errEmptyID = fmt.Errorf("ID cannot be empty") + errInvalidIDFormat = "ID must be formatted as <%s>:<%s>" +) + +// ImportResourcePairID deconstructs the given ID when terraform +// import runs, so the 2 pairs can be set within terraform state. +func ImportResourcePairID(resourceAID, resourceBID string) schema.StateContextFunc { + return func(_ context.Context, data *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { + givenRawID := data.Id() + if givenRawID == "" { + return nil, errEmptyID + } + + if !strings.Contains(givenRawID, separator) { + return nil, fmt.Errorf(errInvalidIDFormat, resourceAID, resourceBID) + } + + idPair := strings.Split(givenRawID, separator) + if len(idPair) != 2 { + return nil, fmt.Errorf(errInvalidIDFormat, resourceAID, resourceBID) + } + + result := multierror.Append( + data.Set(resourceAID, idPair[0]), + data.Set(resourceBID, idPair[1]), + ) + + return []*schema.ResourceData{data}, result.ErrorOrNil() + } +} diff --git a/internal/schema/importer_test.go b/internal/schema/importer_test.go new file mode 100644 index 000000000..54824160f --- /dev/null +++ b/internal/schema/importer_test.go @@ -0,0 +1,85 @@ +package schema + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/stretchr/testify/assert" +) + +func TestImportResourcePairID(t *testing.T) { + var testCases = []struct { + testName string + givenID string + expectedFirstID string + expectedSecondID string + expectedError error + }{ + { + testName: "it correctly parses the resource ID (org:conn)", + givenID: "org_1234:conn_5678", + expectedFirstID: "org_1234", + expectedSecondID: "conn_5678", + }, + { + testName: "it correctly parses the resource ID (org:user)", + givenID: "org_1234:auth0|62d82", + expectedFirstID: "org_1234", + expectedSecondID: "auth0|62d82", + }, + { + testName: "it correctly parses the resource ID (conn:client)", + givenID: "conn_5678:client_1234", + expectedFirstID: "conn_5678", + expectedSecondID: "client_1234", + }, + { + testName: "it fails when the given ID is empty", + givenID: "", + expectedError: fmt.Errorf("ID cannot be empty"), + }, + { + testName: "it fails when the given ID does not have \":\" as a separator", + givenID: "org_1234conn_5678", + expectedError: fmt.Errorf("ID must be formatted as :"), + }, + { + testName: "it fails when the given ID has too many separators", + givenID: "org_1234:conn_5678:", + expectedError: fmt.Errorf("ID must be formatted as :"), + }, + } + + testSchema := map[string]*schema.Schema{ + "resource_a_id": { + Type: schema.TypeString, + Required: true, + }, + "resource_b_id": { + Type: schema.TypeString, + Required: true, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.testName, func(t *testing.T) { + data := schema.TestResourceDataRaw(t, testSchema, nil) + data.SetId(testCase.givenID) + + importFunc := ImportResourcePairID("resource_a_id", "resource_b_id") + actualData, err := importFunc(context.Background(), data, nil) + + if testCase.expectedError != nil { + assert.EqualError(t, err, testCase.expectedError.Error()) + assert.Nil(t, actualData) + return + } + + assert.Equal(t, actualData[0].Get("resource_a_id").(string), testCase.expectedFirstID) + assert.Equal(t, actualData[0].Get("resource_b_id").(string), testCase.expectedSecondID) + assert.Equal(t, actualData[0].Id(), testCase.givenID) + }) + } +}