onelogin / terraform-provider-onelogin

GNU General Public License v3.0
27 stars 19 forks source link

error when attempting terraform import of onelogin_app_rules #63

Closed dlethin closed 3 years ago

dlethin commented 3 years ago

Hello. @dcaponi suggested here I could run the following to import an app rule into my project:

terraform import onelogin_app_rules.<your app_rule name> <app_rule_id>

However I received the following error when I tried to run it:

terraform import onelogin_app_rules.example NNNNNN
onelogin_app_rules.example: Importing from ID "NNNNNN"...
onelogin_app_rules.example: Import prepared!
  Prepared onelogin_app_rules for import
onelogin_app_rules.example: Refreshing state... [id=NNNNNN]
╷
│ Error: error: context: [ol http service], error_message: [{"name":"NotFoundError","message":"Resource not found","statusCode":404}]
│
│
╵

Here's what I did:

I have a project that looks like this:

resource "onelogin_app_rules" "example" {
  app_id   = XXXXXXX
  enabled  = true
  match    = "all"
  name     = "terraform-test"
  conditions {
    operator = "="
    source   = "email"
    value    = "me@mycompany.com
  }
  actions {
    action = "set_role_from_existing"
    value = [
      "arn:aws:iam::YYYYYYYYYYYYYY:role/my-role"
    ]
  }
}

I then run terraform apply:

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

onelogin_app_rules.example: Creating...
onelogin_app_rules.example: Creation complete after 1s [id=NNNNNN]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

I then show the terraform state to get the rule id, remove the resource from state, and then attempt to re-import it, but get the error message:

$ terraform state show onelogin_app_rules.example
# onelogin_app_rules.example:
resource "onelogin_app_rules" "example" {
    app_id   = "AAAAAAAA"
    enabled  = true
    id       = "NNNNNN"
    match    = "all"
    name     = "terraform-test"
    position = 10

    actions {
        action = "set_role_from_existing"
        value  = [
            "arn:aws:iam::YYYYYYYYYYYYYY:role/my-role",
        ]
    }

    conditions {
        operator = "="
        source   = "email"
        value    = "me@mycompany.com"
    }
}
$ terraform state rm onelogin_app_rules.example
Removed onelogin_app_rules.example
Successfully removed 1 resource instance(s).
$ terraform import onelogin_app_rules.example NNNNNN
onelogin_app_rules.example: Importing from ID "NNNNNN"...
onelogin_app_rules.example: Import prepared!
  Prepared onelogin_app_rules for import
onelogin_app_rules.example: Refreshing state... [id=NNNNNN]
╷
│ Error: error: context: [ol http service], error_message: [{"name":"NotFoundError","message":"Resource not found","statusCode":404}]
│
│
╵

Any idea what might be happening here? Am I doing something wrong?

Thanks.

Doug

dlethin commented 3 years ago

I understand the problem. The issue is that you can't get an app_rule from the rule_id itself. you also need to supply the app_id as well, so the import schema for the resource needs to be changed follow the model seen here: https://www.terraform.io/docs/extend/resources/import.html#importer-state-function

This way the import command gets run like this:

terraform import onelogin_app_rules.example APP_ID:RULE_ID

And the resource_onelogin_app_rules.go needs the following changes:

// AppRules returns a resource with the CRUD methods and Terraform Schema defined
func AppRules() *schema.Resource {
    return &schema.Resource{
        Create:   appRuleCreate,
        Read:     appRuleRead,
        Update:   appRuleUpdate,
        Delete:   appRuleDelete,
        Importer: &schema.ResourceImporter {
            // State is added here, which splits app_id and rules_id
            // and sets them appropriately before reading
            State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
                // d.Id() here is the last argument passed to the `terraform import RESOURCE_TYPE.RESOURCE_NAME RESOURCE_ID` command
                app_id, rule_id, err := parseImportId(d.Id())
                if err != nil {
                  return nil, err
                }
                d.SetId(rule_id)
                d.Set("app_id", app_id)

                return []*schema.ResourceData{d}, nil
            },
        },
        Schema:   apprulesschema.Schema(),
    }
}

func parseImportId(id string) (string, string, error) {
  parts := strings.SplitN(id, ":", 2)

  if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
    return "", "", fmt.Errorf("unexpected format of ID (%s), expected attribute1:attribute2", id)
  }

  return parts[0], parts[1], nil
}

I tested this out with a sidecar loaded version of the plugin and the import then worked:

$ terraform import onelogin_app_rules.example [REDACTED]:[REDACTED]
onelogin_app_rules.example: Importing from ID "[REDACTED]:[REDACTED]"...
onelogin_app_rules.example: Import prepared!
  Prepared onelogin_app_rules for import
onelogin_app_rules.example: Refreshing state... [id=[REDACTED]]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

$ terraform plan
onelogin_app_rules.example: Refreshing state... [id=[REDACTED]]

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your configuration and the remote system(s). As a result, there are no
actions to take.

I could try to put a PR together for this but you guys might be faster since you live in this code. I'm not sure what other requirements you might have for automated testing or how to go about updating the terraform documentation to indicate the schema to provide ( app_id:rule_id) when performing the import.

Cheers.

Doug

dcaponi commented 3 years ago

@dlethin that is basically the entire pull request right there 🙂

I just threw the id parser code into a utils file with some other cross-cutting stuff since there might be another resource with similar behavior. Other than that, I'd think you were a seasoned go developer.

I'll have a release out shortly. Look for v0.1.20 ~within the hour~ out now 🎉

dlethin commented 3 years ago

Other than that, I'd think you were a seasoned go developer.

Aw, shucks... well, this was just mostly grabbed from terraform's developer guide doc. I just figure its easier for someone more active in this code-base to arrange it how they like.

Thanks for pushing it through. I'll look for the version to be available in the registry and give it a try.

dlethin commented 3 years ago

Just gave v0.1.20 a try and its working for me. Thanks again.