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

There is always an in-place update in terraform plan on each run #146

Open
mohamaa opened this issue May 1, 2023 · 1 comment
Open

There is always an in-place update in terraform plan on each run #146

mohamaa opened this issue May 1, 2023 · 1 comment

Comments

@mohamaa
Copy link

mohamaa commented May 1, 2023

Hi Team,

I am creating Feature Flags through Terraform provider version ~> 2.0.
First, apply creates the flag and adds variations but the next consecutive runs always show changes and try to do an update in place when the variation is empty.

Please note: For non-empty variations, it doesn't reapply the changes but skips them.

# launchdarkly_feature_flag_environment.feature_env["1"] will be updated in-place
 ~ resource "launchdarkly_feature_flag_environment" "feature_env" {
       id            = "rcm_revitcloudmodels/production/worksharing-activity-indicator"
       # (5 unchanged attributes hidden)

     + targets {
         + values    = []
         + variation = 0
       }
     + targets {
         + values    = []
         + variation = 1
       }

       # (1 unchanged block hidden)
   }

My code:

main.tf:


data "launchdarkly_team_member" "tesla" {
  email = "[email protected]"
}

data "launchdarkly_environment" "env" {
  key         = var.env_name
  project_key = "project_key"
}

data "launchdarkly_feature_flag" "flag" {
  for_each    = var.create_flags ? tomap({}) : tomap({ for i, v in var.ff_list : i => v })
  key         = each.value.ff_name
  project_key = "project_key"
}

# Create a new feature flag
resource "launchdarkly_feature_flag" "feature" {
  for_each       = var.create_flags ? tomap({ for i, v in var.ff_list : i => v }) : tomap({})
  project_key    = "project_key"
  name           = each.value.ff_name
  key            = each.value.ff_name
  description    = "Adds the ${each.value.ff_name} to the displayed interface"
  tags           = ["managed-by-terraform"]
  maintainer_id  = data.launchdarkly_team_member.tesla.id
  temporary      = each.value.temporary
  variation_type = "boolean"
  variations {
    value = false
  }
  variations {
    value = true
  }
}

resource "launchdarkly_feature_flag_environment" "feature_env" {
  for_each = { for i, v in var.ff_list : i => v }
  flag_id  = var.create_flags ? launchdarkly_feature_flag.feature[each.key].id : data.launchdarkly_feature_flag.flag[each.key].id
  env_key  = data.launchdarkly_environment.env.key
  on       = each.value.enabled
  targets {
    values    = each.value.targets_false
    variation = 0
  }
  targets {
    values    = each.value.targets_true
    variation = 1
  }
  fallthrough {
    variation       = each.value.default_rule
    rollout_weights = each.value.rollout_weights
  }
  off_variation = 0
}

Variables.tf:

variable "env_name" {
  description = "LaunchDarkly env name."
  type        = string
  default     = "development"
}

variable "create_flags" {
  description = "Boolean to enable/disable feature flag creation."
  type        = bool
  default     = true
}

variable "ff_list" {
  description = "An object that contains all the ff list and its persona/targets. Only default_rule or rollout weights can be specified, it can not be both. 0 = false, 1 = true. Rollout weights must sum to 100000. Example, [50000, 50000]."
  type = list(object({
    ff_name         = string
    enabled         = bool
    temporary       = bool
    rollout_weights = list(number)
    default_rule    = number
    targets_false   = list(string)
    targets_true    = list(string)
  }))
  default = []
}
@mohamaa mohamaa changed the title There are always an in-place update in terraform plan on each run There is always an in-place update in terraform plan on each run May 1, 2023
@sloloris
Copy link
Contributor

Hi @mohamaa,

I'm sorry you're dealing with this issue.

The reason this is happening is that our API does not return a targets attribute in the read response when the targets are empty. This means that, if you are defining empty targets, there is no way for Terraform to detect that they were already there.

Because of the way you are defining the launchdarkly_feature_flag_environment resources - by looping through variables - any flag resources that do not explicitly have populated target values will nonetheless try to populate empty target attributes into the Terraform state, meaning that when the plan read comes through, the state contains empty targets where the API returns nothing, causing a diff in plan.

As this is a relatively niche issue and we do not generally expect users to define empty targets, we will not be addressing this at this time; however, I have filed an internal ticket to investigate more elegant behaviors in the future when engineering resources are more readily available and will leave this issue open for future reference. Thank you for bringing this to our attention and please do file any issues you hit moving forward - it helps us continue to improve the provider.

My sincerest apologies that we cannot offer a better fix at this time and I hope this explanation makes up for some of the confusion surrounding this issue! Have a lovely weekend :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants