Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-implement ability to import resource state #196

Merged
merged 14 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/195.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:note
Added `terraform import` documentation to all applicable resources.
```
15 changes: 15 additions & 0 deletions .changelog/196.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```release-note:bug
`resource/davinci_variable`: Fixed error when attempting to import resource state.
```

```release-note:bug
`resource/davinci_application`: Fixed error when attempting to import resource state.
```

```release-note:bug
`resource/davinci_flow`: Fixed error when attempting to import resource state.
```

```release-note:bug
`resource/davinci_connection`: Fixed error when attempting to import resource state.
```
7 changes: 7 additions & 0 deletions docs/resources/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,10 @@ Optional:
- `update_body_message` (String) This is deprecated in the UI and will be removed in a future release.
- `update_message` (String) This is deprecated in the UI and will be removed in a future release.

## Import

Import is supported using the following syntax, where attributes in `<>` brackets are replaced with the relevant ID. For example, `<environment_id>` should be replaced with the ID of the environment to import from.

```shell
$ terraform import davinci_application.example <environment_id>/<davinci_application_id>
```
9 changes: 8 additions & 1 deletion docs/resources/connection.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ Optional:

- `type` (String) Type of the property. This is used to cast the value to the correct type. Must be: string or boolean. Use 'string' for array

## Import

Import is supported using the following syntax, where attributes in `<>` brackets are replaced with the relevant ID. For example, `<environment_id>` should be replaced with the ID of the environment to import from.

```shell
$ terraform import davinci_connection.example <environment_id>/<davinci_connection_id>
```

<!-- start: connections docs generated by dvgenerate do not manually edit -->
## DaVinci Connection Definitions
Expand Down Expand Up @@ -3484,4 +3491,4 @@ If the `value` type of a property is not defined it must be inferred.



<!-- end: connections docs generated by dvgenerate -->
<!-- end: connections docs generated by dvgenerate -->
7 changes: 7 additions & 0 deletions docs/resources/flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,10 @@ Read-Only:
- `name` (String)
- `type` (String)

## Import

Import is supported using the following syntax, where attributes in `<>` brackets are replaced with the relevant ID. For example, `<environment_id>` should be replaced with the ID of the environment to import from.

```shell
$ terraform import davinci_flow.example <environment_id>/<davinci_flow_id>
```
7 changes: 7 additions & 0 deletions docs/resources/variable.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,10 @@ resource "davinci_variable" "my_global_var" {

- `id` (String) The ID of this resource.

## Import

Import is supported using the following syntax, where attributes in `<>` brackets are replaced with the relevant ID. For example, `<environment_id>` should be replaced with the ID of the environment to import from.

```shell
$ terraform import davinci_variable.example <environment_id>/<davinci_variable_id>
```
1 change: 1 addition & 0 deletions examples/resources/davinci_application/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ terraform import davinci_application.example <environment_id>/<davinci_application_id>
1 change: 1 addition & 0 deletions examples/resources/davinci_connection/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ terraform import davinci_connection.example <environment_id>/<davinci_connection_id>
1 change: 1 addition & 0 deletions examples/resources/davinci_flow/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ terraform import davinci_flow.example <environment_id>/<davinci_flow_id>
1 change: 1 addition & 0 deletions examples/resources/davinci_variable/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ terraform import davinci_variable.example <environment_id>/<davinci_variable_id>
34 changes: 33 additions & 1 deletion internal/service/davinci/resource_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package davinci
import (
"context"
"fmt"
"regexp"
"strings"

"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/validation"
"github.com/pingidentity/terraform-provider-davinci/internal/sdk"
"github.com/pingidentity/terraform-provider-davinci/internal/utils"
dv "github.com/samir-gandhi/davinci-client-go/davinci"
)

Expand Down Expand Up @@ -382,7 +384,7 @@ func ResourceApplication() *schema.Resource {
},
},
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
StateContext: resourceApplicationImport,
},
}
}
Expand Down Expand Up @@ -580,6 +582,36 @@ func resourceApplicationDelete(ctx context.Context, d *schema.ResourceData, meta
return diags
}

func resourceApplicationImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {

idComponents := []utils.ImportComponent{
{
Label: "environment_id",
Regexp: regexp.MustCompile(`[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`),
},
{
Label: "davinci_application_id",
Regexp: regexp.MustCompile(`[a-f0-9]{32}`),
PrimaryID: true,
},
}

attributes, err := utils.ParseImportID(d.Id(), idComponents...)
if err != nil {
return nil, err
}

if err = d.Set("environment_id", attributes["environment_id"]); err != nil {
return nil, err
}

d.SetId(attributes["davinci_application_id"])

resourceApplicationRead(ctx, d, meta)

return []*schema.ResourceData{d}, nil
}

func expandApp(d *schema.ResourceData) (*dv.AppUpdate, error) {
// Set Top layer.
a := dv.AppUpdate{
Expand Down
79 changes: 79 additions & 0 deletions internal/service/davinci/resource_application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package davinci_test

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/pingidentity/terraform-provider-davinci/internal/acctest"
)

Expand Down Expand Up @@ -101,6 +103,23 @@ func TestAccResourceApplication_WithFlowPolicy(t *testing.T) {
resource.TestCheckResourceAttrSet(resourceFullName, "policy.0.policy_id"),
),
},
// Test importing the resource
{
ResourceName: resourceFullName,
ImportStateIdFunc: func() resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[resourceFullName]
if !ok {
return "", fmt.Errorf("Resource Not found: %s", resourceFullName)
}

return fmt.Sprintf("%s/%s", rs.Primary.Attributes["environment_id"], rs.Primary.ID), nil
}
}(),
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{},
},
},
})
}
Expand Down Expand Up @@ -224,6 +243,25 @@ func TestAccResourceApplication_P1SessionFlowPolicy(t *testing.T) {
resource.TestCheckNoResourceAttr(resourceFullName, "policy.1.policy_id"),
),
},
// Test importing the resource
{
ResourceName: resourceFullName,
ImportStateIdFunc: func() resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[resourceFullName]
if !ok {
return "", fmt.Errorf("Resource Not found: %s", resourceFullName)
}

return fmt.Sprintf("%s/%s", rs.Primary.Attributes["environment_id"], rs.Primary.ID), nil
}
}(),
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"context", // This shouldn't be ignored, can be solved on migration to the plugin framework
},
},
},
})
}
Expand Down Expand Up @@ -349,3 +387,44 @@ resource "davinci_application" "%[2]s" {
`, baseHcl, resourceName, flows.PingOneSessionMainFlow.Name)
return hcl
}

func TestAccResourceApplication_BadParameters(t *testing.T) {

resourceBase := "davinci_application"
resourceName := acctest.ResourceNameGen()
resourceFullName := fmt.Sprintf("%s.%s", resourceBase, resourceName)

hcl := testAccResourceApplication_Slim_Hcl(resourceName)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheckPingOneAndTfVars(t) },
ProviderFactories: acctest.ProviderFactories,
ExternalProviders: acctest.ExternalProviders,
ErrorCheck: acctest.ErrorCheck(t),
CheckDestroy: acctest.CheckResourceDestroy([]string{"davinci_application"}),
Steps: []resource.TestStep{
// Configure
{
Config: hcl,
},
// Errors
{
ResourceName: resourceFullName,
ImportState: true,
ExpectError: regexp.MustCompile(`Invalid import ID specified \(".*"\). The ID should be in the format "environment_id/davinci_application_id" and must match regex: .*`),
},
{
ResourceName: resourceFullName,
ImportStateId: "/",
ImportState: true,
ExpectError: regexp.MustCompile(`Invalid import ID specified \(".*"\). The ID should be in the format "environment_id/davinci_application_id" and must match regex: .*`),
},
{
ResourceName: resourceFullName,
ImportStateId: "badformat/badformat",
ImportState: true,
ExpectError: regexp.MustCompile(`Invalid import ID specified \(".*"\). The ID should be in the format "environment_id/davinci_application_id" and must match regex: .*`),
},
},
})
}
34 changes: 33 additions & 1 deletion internal/service/davinci/resource_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package davinci
import (
"context"
"fmt"
"regexp"
"strconv"

"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/validation"
"github.com/pingidentity/terraform-provider-davinci/internal/sdk"
"github.com/pingidentity/terraform-provider-davinci/internal/utils"
dv "github.com/samir-gandhi/davinci-client-go/davinci"
)

Expand Down Expand Up @@ -74,7 +76,7 @@ func ResourceConnection() *schema.Resource {
},
},
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
StateContext: resourceConnectionImport,
},
}
}
Expand Down Expand Up @@ -266,6 +268,36 @@ func resourceConnectionDelete(ctx context.Context, d *schema.ResourceData, meta
return diags
}

func resourceConnectionImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {

idComponents := []utils.ImportComponent{
{
Label: "environment_id",
Regexp: regexp.MustCompile(`[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`),
},
{
Label: "davinci_connection_id",
Regexp: regexp.MustCompile(`[a-f0-9]{32}`),
PrimaryID: true,
},
}

attributes, err := utils.ParseImportID(d.Id(), idComponents...)
if err != nil {
return nil, err
}

if err = d.Set("environment_id", attributes["environment_id"]); err != nil {
return nil, err
}

d.SetId(attributes["davinci_connection_id"])

resourceConnectionRead(ctx, d, meta)

return []*schema.ResourceData{d}, nil
}

func flattenConnectionProperties(connectionProperties *dv.Properties) ([]map[string]interface{}, error) {
if connectionProperties == nil {
return nil, fmt.Errorf("no properties")
Expand Down
61 changes: 61 additions & 0 deletions internal/service/davinci/resource_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package davinci_test

import (
"fmt"
"regexp"
"strconv"
"strings"
"testing"
Expand Down Expand Up @@ -35,6 +36,25 @@ func TestAccResourceConnection_Slim(t *testing.T) {
resource.TestCheckResourceAttr(resourceFullName, "name", resourceName),
),
},
// Test importing the resource
{
ResourceName: resourceFullName,
ImportStateIdFunc: func() resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[resourceFullName]
if !ok {
return "", fmt.Errorf("Resource Not found: %s", resourceFullName)
}

return fmt.Sprintf("%s/%s", rs.Primary.Attributes["environment_id"], rs.Primary.ID), nil
}
}(),
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"property.1.value",
samir-gandhi marked this conversation as resolved.
Show resolved Hide resolved
},
},
},
})
}
Expand Down Expand Up @@ -257,3 +277,44 @@ data "davinci_application" "http_%[2]s_%[1]s" {

return hcl
}

func TestAccResourceConnection_BadParameters(t *testing.T) {

resourceBase := "davinci_connection"
resourceName := acctest.ResourceNameGen()
resourceFullName := fmt.Sprintf("%s.%s", resourceBase, resourceName)

hcl := testAccResourceConnection_Slim_Hcl(resourceName, "slim")

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheckPingOneAndTfVars(t) },
ProviderFactories: acctest.ProviderFactories,
ExternalProviders: acctest.ExternalProviders,
ErrorCheck: acctest.ErrorCheck(t),
CheckDestroy: acctest.CheckResourceDestroy([]string{"davinci_connection"}),
Steps: []resource.TestStep{
// Configure
{
Config: hcl,
},
// Errors
{
ResourceName: resourceFullName,
ImportState: true,
ExpectError: regexp.MustCompile(`Invalid import ID specified \(".*"\). The ID should be in the format "environment_id/davinci_connection_id" and must match regex: .*`),
},
{
ResourceName: resourceFullName,
ImportStateId: "/",
ImportState: true,
ExpectError: regexp.MustCompile(`Invalid import ID specified \(".*"\). The ID should be in the format "environment_id/davinci_connection_id" and must match regex: .*`),
},
{
ResourceName: resourceFullName,
ImportStateId: "badformat/badformat",
ImportState: true,
ExpectError: regexp.MustCompile(`Invalid import ID specified \(".*"\). The ID should be in the format "environment_id/davinci_connection_id" and must match regex: .*`),
},
},
})
}
Loading