microsoft / terraform-provider-power-platform

Power Platform Terraform Provider
https://registry.terraform.io/providers/microsoft/power-platform/latest/docs
MIT License
35 stars 13 forks source link

Error trying to import an existing DLP policy to a state file #332

Closed rpothin closed 5 months ago

rpothin commented 5 months ago

Describe the bug

I am exploring the scenario of switching from manually managing DLP policies to managing them using Terraform. I tried to use the terraform import command and the import block approach to achieve this, but without success.

To Reproduce

terraform import command approach

Steps to reproduce the behavior:

  1. Get the ID of an existing DLP policy in the Power Platform Admin Center (from the URL after opening a DLP policy or from network traces getting the list of the DLP policies)
  2. Set up a "simple" Terraform configuration with a DLP policy resource - like presented here
  3. Run the terraform import command - in the case of the configuration above, it would be something like terraform powerplatform_data_loss_prevention_policy.my_policy <ID of the DLP policy you got from PPAC>
  4. You should get the following error - like I got here:
│ Error: State Write Error
│ 
│ An unexpected error was encountered trying to retrieve type information at
│ a given path. This is always an error in the provider. Please report the
│ following to the provider developer:
│ 
│ Error: AttributeName("Id") still remains in the path: could not find
│ attribute or block "Id" in schema

import block approach

Steps to reproduce the behavior:

  1. Get the ID of an existing DLP policy in the Power Platform Admin Center (from the URL after opening a DLP policy or from network traces getting the list of the DLP policies)
  2. Set up a "simple" Terraform configuration with a DLP policy resource and a related import block (the ID of the DLP Policy to import could be static in your configuration or coming from a var file) - like presented here
  3. Try to go through the "classic" plan and apply process
  4. You should get the following error during the plan step - like I got here:
data.powerplatform_connectors.all_connectors: Reading...
data.powerplatform_connectors.all_connectors: Read complete after 4s [id=1226]
powerplatform_data_loss_prevention_policy.policy: Preparing import... [id=2d51ba59-b747-4776-bd93-07e2009caf97]

Planning failed. Terraform encountered an error while generating this plan.

Error: State Write Error

An unexpected error was encountered trying to retrieve type information at a
given path. This is always an error in the provider. Please report the
following to the provider developer:

Error: AttributeName("Id") still remains in the path: could not find
attribute or block "Id" in schema

Terraform Plan Failed!

Sample Terraform Code - used in the import block approach

terraform {
  required_providers {
    powerplatform = {
      source  = "microsoft/power-platform"
      version = "2.3.1-preview"
    }
  }

  backend "azurerm" {
    use_oidc = true
  }
}

provider "powerplatform" {
  use_oidc = true
}

data "powerplatform_connectors" "all_connectors" {}

import {
  to = powerplatform_data_loss_prevention_policy.policy
  id = var.id
}

resource "powerplatform_data_loss_prevention_policy" "policy" {
  display_name                      = var.display_name
  default_connectors_classification = "Blocked"
  environment_type                  = var.environment_type
  environments                      = var.environments

  business_connectors     = var.business_connectors

  # Dynamically generate non-business connectors based on the business connectors specified
  non_business_connectors = [for conn in data.powerplatform_connectors.all_connectors.connectors : {
    id                           = conn.id
    name                         = conn.name
    default_action_rule_behavior = ""
    action_rules                 = [],
    endpoint_rules               = []
  } if conn.unblockable == true && !contains([for bus_conn in var.business_connectors : bus_conn.id], conn.id)]

  # Dynamically generate blocked connectors based on the business connectors specified
  blocked_connectors      = [for conn in data.powerplatform_connectors.all_connectors.connectors : {
    id                           = conn.id
    default_action_rule_behavior = ""
    action_rules                 = [],
    endpoint_rules               = []
  } if conn.unblockable == false && !contains([for bus_conn in var.business_connectors : bus_conn.id], conn.id)]

  custom_connectors_patterns = var.custom_connectors
}

Expected behavior

I would like to be able to successfully execute the terraform import command or to use the import block approach to import an existing DLP policy into a state file to be able to switch the management of its configuration to Terraform.

System Information

Additional context

After some research and analysis, I think the issue is coming from the implementation of the ImportState method for the DLP policy resource.

Like mentioned in the Terraform documentation, the resource state should be set in resource.ImportStateResponse and it does not seem to be the case currently.

I am not sure if path.Root("Id") in the call to the ImportStatePassthroughID works as expected.

Based on a long discussion with GitHub Copilot to try to understand this issue, I think a fix like the one below could potentially work:

func (r *resourceDlpPolicy) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) error {
    id := req.ID

    // Use the id to retrieve the DLP policy from your service
    policy, err := r.apiClient.GetDlpPolicy(ctx, id)
    if err != nil {
        return err
    }

    // Create a new instance of your resource's state and populate it with the policy's data
    state := &resourceDlpPolicyState{
        ID:     policy.ID,
        Name:   policy.Name,
        // Populate other fields as necessary
    }

    // Use the state to set the resource's state in the response
    resp.State = state

    return nil
}

What do you think?

Contribution

Do you plan to raise a PR to address this issue? YES, but only after we come to an agreement regarding the potential solution to fix this issue - if the issue is confirmed on your side obviously 😊

Thank you for taking the time to take a look at this issue and have a great day.

mawasile commented 5 months ago

Thanks for raising a bug @rpothin. There was a type in the unique identifier field; I have it fixed, should get into release soon.

rpothin commented 5 months ago

Hey @mawasile 👋

Thank you very much for your quick action.

Your fix proposition seems definitely better than mine 😅

I hope the details I shared at least helped you find what to fix and where ☺️

I am looking forward to test this fix.

👍 Bonus point for you for also providing a fix for other resources in a similar situation.

Have a great day. Regards, Raphael

rpothin commented 5 months ago

Hi @mawasile,

I hope you are doing well.

Just to let you know I just done a test of import with the latest release and it works as expected (run).

image

Thank you again for your quick fix and have a great day. Raphael