Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .go-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.22.9
1.24.0
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ repos:
- id: gofmts

- repo: https://github.com/golangci/golangci-lint
rev: v1.51.2
rev: v1.63.2
hooks:
- id: golangci-lint

Expand Down
1 change: 1 addition & 0 deletions docs/data-sources/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,6 @@ Read-Only:
- `min_num_approvals` (Number)
- `required` (Boolean)
- `required_approval_tags` (List of String)
- `resource_kind` (String)
- `service_config` (Map of String)
- `service_kind` (String)
270 changes: 270 additions & 0 deletions docs/guides/approval-settings-migration.md

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should either be moved to the docs dir or removed altogether.

Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
---
page_title: "Migrating to multi-resource approval settings"
description: |-
This guide explains how to use the approval_settings block to configure approval requirements for flags, segments, and AI configs within the same environment. Learn about the new resource_kind attribute, validation rules, and how to migrate existing configurations.
---

# Approval Settings Migration Guide

## Overview

The `approval_settings` block now supports multiple resource kinds (flags, segments, and AI configs) while maintaining full backwards compatibility with existing configurations.

## What's New

### Multiple Approval Settings Blocks

You can now specify approval settings for different resource types within the same environment:

**Important**: `service_kind` and `service_config` are **only supported for flag approval settings** (`resource_kind = "flag"`). Using these fields with `resource_kind = "segment"` or `resource_kind = "aiconfig"` will result in a validation error.

```hcl
resource "launchdarkly_environment" "example" {
name = "Production"
key = "production"
color = "FF0000"
project_key = "my-project"

# Flag approval settings
approval_settings {
resource_kind = "flag"
required = true
min_num_approvals = 2
can_review_own_request = false
can_apply_declined_changes = false
}

# Segment approval settings
# Note: service_kind and service_config are not supported for segment approvals
approval_settings {
resource_kind = "segment"
required = true
min_num_approvals = 1
can_apply_declined_changes = true
}

# AI Config approval settings
# Note: service_kind and service_config are not supported for aiconfig approvals
approval_settings {
resource_kind = "aiconfig"
required = false
min_num_approvals = 1
}
}
```

### New Attribute: `resource_kind`

- **Type**: `string`
- **Optional**: Yes (defaults to `"flag"`)
- **Valid values**: `"flag"`, `"segment"`, `"aiconfig"`
- **Description**: Specifies which resource type the approval settings apply to

### Validation

- Each `resource_kind` can only be specified once per environment
- Attempting to configure duplicate `resource_kind` values will result in a validation error

## Backwards Compatibility

Existing configurations without the `resource_kind` attribute will continue to work exactly as before. The attribute defaults to `"flag"` when not specified:

```hcl
# This configuration is still valid and equivalent to resource_kind = "flag"
resource "launchdarkly_environment" "example" {
name = "Production"
key = "production"
color = "FF0000"
project_key = "my-project"

approval_settings {
required = true
min_num_approvals = 1
}
}
```

## API Mapping

### Reading from API
- `approvalSettings` (root level) → `approval_settings` with `resource_kind = "flag"`
- `resourceApprovalSettings.segment` → `approval_settings` with `resource_kind = "segment"`
- `resourceApprovalSettings.aiconfig` → `approval_settings` with `resource_kind = "aiconfig"`

### Writing to API
- `resource_kind = "flag"` → PATCH operations to `/approvalSettings/*`
- `resource_kind = "segment"` → PATCH operations to `/resourceApprovalSettings/segment/*`
- `resource_kind = "aiconfig"` → PATCH operations to `/resourceApprovalSettings/aiconfig/*`

## Migration Examples

### Before: Flag Approvals Only
```hcl
resource "launchdarkly_environment" "prod" {
name = "Production"
key = "production"
project_key = "my-project"

approval_settings {
required = true
min_num_approvals = 2
}
}
```

### After: Adding Segment Approvals
```hcl
resource "launchdarkly_environment" "prod" {
name = "Production"
key = "production"
project_key = "my-project"

# Existing flag approvals (add resource_kind for clarity, but optional)
approval_settings {
resource_kind = "flag"
required = true
min_num_approvals = 2
}

# New segment approvals
approval_settings {
resource_kind = "segment"
required = true
min_num_approvals = 1
}
}
```

## Implementation Details

### Code Changes

1. **New constant**: `RESOURCE_KIND` added to `keys.go`
2. **Schema updated**: `approval_settings` block now supports `resource_kind` attribute
3. **Validation added**: `validateUniqueResourceKinds` ensures no duplicate resource kinds
4. **Patch generation**: `approvalPatchFromSettings` generates correct API paths based on resource kind
5. **Data reading**: `environmentApprovalSettingsToResourceData` handles both API structures

### Testing

Comprehensive unit tests ensure:
- Multiple resource kinds can be configured simultaneously
- Correct API paths are generated for each resource kind
- Backwards compatibility with existing configurations
- Proper handling of adding/removing resource kinds

Run tests with:
```bash
go test -v ./launchdarkly -run TestApproval
```

## Troubleshooting

### Error: "duplicate resource_kind found"

**Cause**: Multiple `approval_settings` blocks with the same `resource_kind`

**Solution**: Ensure each `approval_settings` block has a unique `resource_kind` value

```hcl
# ❌ Invalid - duplicate "flag" resource_kind
approval_settings {
resource_kind = "flag"
required = true
}
approval_settings {
resource_kind = "flag" # ERROR: duplicate
required = false
}

# ✅ Valid - unique resource_kind values
approval_settings {
resource_kind = "flag"
required = true
}
approval_settings {
resource_kind = "segment"
required = false
}
```

### Error: "service_kind cannot be set for resource_kind 'segment'"

**Cause**: Attempting to use `service_kind` with a non-default value (anything other than `"launchdarkly"`) for segment or aiconfig approval settings

**Solution**: Remove the `service_kind` field or set it to the default value `"launchdarkly"` (or omit it entirely)

```hcl
# ❌ Invalid - service_kind not supported for segment
approval_settings {
resource_kind = "segment"
service_kind = "servicenow" # ERROR: not supported for segments
required = true
}

# ✅ Valid - service_kind only used with flag resource_kind
approval_settings {
resource_kind = "flag"
service_kind = "servicenow"
required = true
}

approval_settings {
resource_kind = "segment"
required = true
# service_kind omitted or set to default "launchdarkly"
}
```

### Error: "service_config cannot be set for resource_kind 'segment'"

**Cause**: Attempting to use `service_config` for segment or aiconfig approval settings

**Solution**: Remove the `service_config` field from non-flag approval settings

```hcl
# ❌ Invalid - service_config not supported for segment
approval_settings {
resource_kind = "segment"
service_config = {
template = "template-id"
detail_column = "justification"
} # ERROR: not supported for segments
required = true
}

# ✅ Valid - service_config only used with flag resource_kind
approval_settings {
resource_kind = "flag"
service_kind = "servicenow"
service_config = {
template = "template-id"
detail_column = "justification"
}
required = true
}

approval_settings {
resource_kind = "segment"
required = true
# service_config omitted
}
```


### Import Considerations

When you import an existing environment (using `terraform import`), Terraform will read all configured approval settings from the API and represent them as separate `approval_settings` blocks in the state, each with the appropriate `resource_kind` value.

For example, if you import an environment that has both flag and segment approvals configured:

```bash
terraform import launchdarkly_environment.example project-key/env-key
```

The resulting state will contain multiple `approval_settings` blocks. You'll need to add corresponding blocks to your Terraform configuration to match the imported state.

## Additional Resources

- [LaunchDarkly Approval Settings Documentation](https://docs.launchdarkly.com/home/feature-workflows/approvals)
- [Terraform Provider Documentation](https://registry.terraform.io/providers/launchdarkly/launchdarkly/latest/docs)
9 changes: 5 additions & 4 deletions docs/resources/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,18 @@ resource "launchdarkly_environment" "approvals_example" {

Optional:

- `auto_apply_approved_changes` (Boolean) Automatically apply changes that have been approved by all reviewers. This field is only applicable for approval service kinds other than `launchdarkly`.
- `auto_apply_approved_changes` (Boolean) Automatically apply changes that have been approved by all reviewers. **Note:** This field is only supported for `resource_kind = "flag"` and is only applicable for approval service kinds other than `launchdarkly`.
- `can_apply_declined_changes` (Boolean) Set to `true` if changes can be applied as long as the `min_num_approvals` is met, regardless of whether any reviewers have declined a request. Defaults to `true`.
- `can_review_own_request` (Boolean) Set to `true` if requesters can approve or decline their own request. They may always comment. Defaults to `false`.
- `min_num_approvals` (Number) The number of approvals required before an approval request can be applied. This number must be between 1 and 5. Defaults to 1.
- `required` (Boolean) Set to `true` for changes to flags in this environment to require approval. You may only set `required` to true if `required_approval_tags` is not set and vice versa. Defaults to `false`.
- `required` (Boolean) Set to `true` for changes to resources of this kind in this environment to require approval. You may only set `required` to true if `required_approval_tags` is not set and vice versa. Defaults to `false`.
- `required_approval_tags` (List of String) An array of tags used to specify which flags with those tags require approval. You may only set `required_approval_tags` if `required` is set to `false` and vice versa.
- `service_config` (Map of String) The configuration for the service associated with this approval. This is specific to each approval service. For a `service_kind` of `servicenow`, the following fields apply:
- `resource_kind` (String) The kind of resource for which approval settings should apply. Valid values are `flag`, `segment`, and `aiconfig`. Defaults to `flag`.
- `service_config` (Map of String) The configuration for the service associated with this approval. **Note:** This field is only supported for `resource_kind = "flag"`. Using this field with `resource_kind = "segment"` or `resource_kind = "aiconfig"` will result in an error. For a `service_kind` of `servicenow`, the following fields apply:

- `template` (String) The sys_id of the Standard Change Request Template in ServiceNow that LaunchDarkly will use when creating the change request.
- `detail_column` (String) The name of the ServiceNow Change Request column LaunchDarkly uses to populate detailed approval request information. This is most commonly "justification".
- `service_kind` (String) The kind of service associated with this approval. This determines which platform is used for requesting approval. Valid values are `servicenow`, `launchdarkly`. If you use a value other than `launchdarkly`, you must have already configured the integration in the LaunchDarkly UI or your apply will fail.
- `service_kind` (String) The kind of service associated with this approval. This determines which platform is used for requesting approval. Valid values are `servicenow`, `launchdarkly`. **Note:** This field is only supported for `resource_kind = "flag"`. Using this field with `resource_kind = "segment"` or `resource_kind = "aiconfig"` will result in an error. If you use a value other than `launchdarkly`, you must have already configured the integration in the LaunchDarkly UI or your apply will fail.

## Import

Expand Down
9 changes: 5 additions & 4 deletions docs/resources/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,17 +97,18 @@ Read-Only:

Optional:

- `auto_apply_approved_changes` (Boolean) Automatically apply changes that have been approved by all reviewers. This field is only applicable for approval service kinds other than `launchdarkly`.
- `auto_apply_approved_changes` (Boolean) Automatically apply changes that have been approved by all reviewers. **Note:** This field is only supported for `resource_kind = "flag"` and is only applicable for approval service kinds other than `launchdarkly`.
- `can_apply_declined_changes` (Boolean) Set to `true` if changes can be applied as long as the `min_num_approvals` is met, regardless of whether any reviewers have declined a request. Defaults to `true`.
- `can_review_own_request` (Boolean) Set to `true` if requesters can approve or decline their own request. They may always comment. Defaults to `false`.
- `min_num_approvals` (Number) The number of approvals required before an approval request can be applied. This number must be between 1 and 5. Defaults to 1.
- `required` (Boolean) Set to `true` for changes to flags in this environment to require approval. You may only set `required` to true if `required_approval_tags` is not set and vice versa. Defaults to `false`.
- `required` (Boolean) Set to `true` for changes to resources of this kind in this environment to require approval. You may only set `required` to true if `required_approval_tags` is not set and vice versa. Defaults to `false`.
- `required_approval_tags` (List of String) An array of tags used to specify which flags with those tags require approval. You may only set `required_approval_tags` if `required` is set to `false` and vice versa.
- `service_config` (Map of String) The configuration for the service associated with this approval. This is specific to each approval service. For a `service_kind` of `servicenow`, the following fields apply:
- `resource_kind` (String) The kind of resource for which approval settings should apply. Valid values are `flag`, `segment`, and `aiconfig`. Defaults to `flag`.
- `service_config` (Map of String) The configuration for the service associated with this approval. **Note:** This field is only supported for `resource_kind = "flag"`. Using this field with `resource_kind = "segment"` or `resource_kind = "aiconfig"` will result in an error. For a `service_kind` of `servicenow`, the following fields apply:

- `template` (String) The sys_id of the Standard Change Request Template in ServiceNow that LaunchDarkly will use when creating the change request.
- `detail_column` (String) The name of the ServiceNow Change Request column LaunchDarkly uses to populate detailed approval request information. This is most commonly "justification".
- `service_kind` (String) The kind of service associated with this approval. This determines which platform is used for requesting approval. Valid values are `servicenow`, `launchdarkly`. If you use a value other than `launchdarkly`, you must have already configured the integration in the LaunchDarkly UI or your apply will fail.
- `service_kind` (String) The kind of service associated with this approval. This determines which platform is used for requesting approval. Valid values are `servicenow`, `launchdarkly`. **Note:** This field is only supported for `resource_kind = "flag"`. Using this field with `resource_kind = "segment"` or `resource_kind = "aiconfig"` will result in an error. If you use a value other than `launchdarkly`, you must have already configured the integration in the LaunchDarkly UI or your apply will fail.



Expand Down
56 changes: 56 additions & 0 deletions examples/environment_approval_settings_example.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Example of environment with approval settings for both flags and segments

resource "launchdarkly_environment" "example" {
name = "Example Environment"
key = "example-env"
color = "FFFFFF"
project_key = "example-project"

# Flag approval settings (resource_kind defaults to "flag")
approval_settings {
resource_kind = "flag" # Optional, defaults to "flag"
required = true
can_review_own_request = false
min_num_approvals = 2
can_apply_declined_changes = false
service_kind = "launchdarkly"
}

# Segment approval settings
approval_settings {
resource_kind = "segment"
required = true
can_review_own_request = false
min_num_approvals = 1
can_apply_declined_changes = true
service_kind = "launchdarkly"
}

# AI Config approval settings (if needed)
# approval_settings {
# resource_kind = "aiconfig"
# required = false
# can_review_own_request = true
# min_num_approvals = 1
# can_apply_declined_changes = true
# service_kind = "launchdarkly"
# }
}

# Example maintaining backwards compatibility (without resource_kind)
# This will default to flag approval settings
resource "launchdarkly_environment" "backwards_compatible" {
name = "Backwards Compatible Environment"
key = "backwards-compat"
color = "000000"
project_key = "example-project"

approval_settings {
# No resource_kind specified - defaults to "flag"
required = true
can_review_own_request = false
min_num_approvals = 1
can_apply_declined_changes = true
service_kind = "launchdarkly"
}
}
Loading
Loading