Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ locals {









Expand Down Expand Up @@ -662,3 +665,63 @@ moved {
from = cloudflare_access_group.auth_context
to = cloudflare_zero_trust_access_group.auth_context
}

# Pattern 25: Azure block with list id (APIX-1110)
resource "cloudflare_zero_trust_access_group" "azure_list_id" {
account_id = var.cloudflare_account_id
name = "${local.name_prefix} Azure List ID Group"

include = [
{
azure_ad = {
identity_provider_id = "idp-123"
id = "group-id-1"
}
},
]
}

moved {
from = cloudflare_access_group.azure_list_id
to = cloudflare_zero_trust_access_group.azure_list_id
}

# Pattern 26: GSuite block with list email
resource "cloudflare_zero_trust_access_group" "gsuite_list_email" {
account_id = var.cloudflare_account_id
name = "${local.name_prefix} GSuite List Email Group"

include = [
{
gsuite = {
email = "group@example.com"
identity_provider_id = "idp-123"
}
},
]
}

moved {
from = cloudflare_access_group.gsuite_list_email
to = cloudflare_zero_trust_access_group.gsuite_list_email
}

# Pattern 27: Okta block with list name
resource "cloudflare_zero_trust_access_group" "okta_list_name" {
account_id = var.cloudflare_account_id
name = "${local.name_prefix} Okta List Name Group"

include = [
{
okta = {
name = "okta-group-1"
identity_provider_id = "idp-123"
}
},
]
}

moved {
from = cloudflare_access_group.okta_list_name
to = cloudflare_zero_trust_access_group.okta_list_name
}
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,45 @@ resource "cloudflare_access_group" "auth_context" {
}
}

# Pattern 25: Azure block with list id (APIX-1110)
resource "cloudflare_access_group" "azure_list_id" {
account_id = var.cloudflare_account_id
name = "${local.name_prefix} Azure List ID Group"

include {
azure {
identity_provider_id = "idp-123"
id = ["group-id-1"]
}
}
}

# Pattern 26: GSuite block with list email
resource "cloudflare_access_group" "gsuite_list_email" {
account_id = var.cloudflare_account_id
name = "${local.name_prefix} GSuite List Email Group"

include {
gsuite {
email = ["group@example.com"]
identity_provider_id = "idp-123"
}
}
}

# Pattern 27: Okta block with list name
resource "cloudflare_access_group" "okta_list_name" {
account_id = var.cloudflare_account_id
name = "${local.name_prefix} Okta List Name Group"

include {
okta {
name = ["okta-group-1"]
identity_provider_id = "idp-123"
}
}
}

# Pattern 23: Already-renamed v4 resource (exercises UpgradeState path, not MoveState)
# When the v4 config already uses cloudflare_zero_trust_access_group (the newer v4 name),
# tf-migrate does NOT generate a moved {} block. During v5 apply, Terraform triggers
Expand Down
47 changes: 44 additions & 3 deletions internal/resources/zero_trust_access_group/v4_to_v5.go
Original file line number Diff line number Diff line change
Expand Up @@ -1612,8 +1612,9 @@ func (m *V4ToV5Migrator) buildGithubOrgItems(nameExpr, teamExpr, identityProvide
}

// expandGsuite handles gsuite blocks
// gsuite = [{email = "group@example.com", identity_provider_id = "id"}]
// gsuite = [{email = ["group@example.com"], identity_provider_id = "id"}]
// -> {gsuite = {email = "group@example.com", identity_provider_id = "id"}}
// Note: in v4, gsuite.email is a list; in v5, gsuite.email is a string.
func (m *V4ToV5Migrator) expandGsuite(item hclsyntax.ObjectConsItem) []hclsyntax.Expression {
tup, ok := item.ValueExpr.(*hclsyntax.TupleConsExpr)
if !ok {
Expand All @@ -1628,6 +1629,10 @@ func (m *V4ToV5Migrator) expandGsuite(item hclsyntax.ObjectConsItem) []hclsyntax
continue
}

// Unwrap email from list to scalar: email = [value] -> email = value
// In v4, gsuite.email is a list of strings; in v5, gsuite.email is a string
gsuiteObj = m.unwrapSingleElementList(gsuiteObj, "email")

newObj := &hclsyntax.ObjectConsExpr{
Items: []hclsyntax.ObjectConsItem{
{
Expand All @@ -1643,8 +1648,9 @@ func (m *V4ToV5Migrator) expandGsuite(item hclsyntax.ObjectConsItem) []hclsyntax
}

// expandOkta handles okta blocks
// okta = [{name = "group", identity_provider_id = "id"}]
// okta = [{name = ["group"], identity_provider_id = "id"}]
// -> {okta = {name = "group", identity_provider_id = "id"}}
// Note: in v4, okta.name is a list; in v5, okta.name is a string.
func (m *V4ToV5Migrator) expandOkta(item hclsyntax.ObjectConsItem) []hclsyntax.Expression {
tup, ok := item.ValueExpr.(*hclsyntax.TupleConsExpr)
if !ok {
Expand All @@ -1659,6 +1665,10 @@ func (m *V4ToV5Migrator) expandOkta(item hclsyntax.ObjectConsItem) []hclsyntax.E
continue
}

// Unwrap name from list to scalar: name = [value] -> name = value
// In v4, okta.name is a list of strings; in v5, okta.name is a string
oktaObj = m.unwrapSingleElementList(oktaObj, "name")

newObj := &hclsyntax.ObjectConsExpr{
Items: []hclsyntax.ObjectConsItem{
{
Expand Down Expand Up @@ -1767,8 +1777,9 @@ func (m *V4ToV5Migrator) expandAuthContext(item hclsyntax.ObjectConsItem) []hcls
}

// expandAzure handles azure blocks
// azure = [{id = "group-id", identity_provider_id = "id"}]
// azure = [{id = ["group-id"], identity_provider_id = "id"}]
// -> {azure_ad = {id = "group-id", identity_provider_id = "id"}}
// Note: in v4, azure.id is a list; in v5, azure_ad.id is a string.
func (m *V4ToV5Migrator) expandAzure(item hclsyntax.ObjectConsItem) []hclsyntax.Expression {
tup, ok := item.ValueExpr.(*hclsyntax.TupleConsExpr)
if !ok {
Expand All @@ -1783,6 +1794,10 @@ func (m *V4ToV5Migrator) expandAzure(item hclsyntax.ObjectConsItem) []hclsyntax.
continue
}

// Unwrap id from list to scalar: id = [value] -> id = value
// In v4, azure.id is a list of strings; in v5, azure_ad.id is a string
azureObj = m.unwrapSingleElementList(azureObj, "id")

// Rename azure to azure_ad for v5
newObj := &hclsyntax.ObjectConsExpr{
Items: []hclsyntax.ObjectConsItem{
Expand All @@ -1800,6 +1815,32 @@ func (m *V4ToV5Migrator) expandAzure(item hclsyntax.ObjectConsItem) []hclsyntax.

// Helper functions

// unwrapSingleElementList unwraps a single-element list attribute to a scalar value.
// For example: id = [value] -> id = value
// This is needed for azure.id, gsuite.email, okta.name which are lists in v4 but
// strings in v5.
func (m *V4ToV5Migrator) unwrapSingleElementList(obj *hclsyntax.ObjectConsExpr, attrName string) *hclsyntax.ObjectConsExpr {
var newItems []hclsyntax.ObjectConsItem
for _, item := range obj.Items {
key := m.getKeyString(item.KeyExpr)
if key == attrName {
if tup, ok := item.ValueExpr.(*hclsyntax.TupleConsExpr); ok && len(tup.Exprs) == 1 {
// Unwrap single-element list to scalar
newItems = append(newItems, hclsyntax.ObjectConsItem{
KeyExpr: item.KeyExpr,
ValueExpr: tup.Exprs[0],
})
continue
}
}
newItems = append(newItems, item)
}
return &hclsyntax.ObjectConsExpr{
Items: newItems,
SrcRange: obj.SrcRange,
}
}

// getKeyString extracts the string value from a key expression
func (m *V4ToV5Migrator) getKeyString(keyExpr hclsyntax.Expression) string {
switch k := keyExpr.(type) {
Expand Down
Loading
Loading