Skip to content

Fix permadiff when Access Context Manager returns a different order for ingress / egress rule identities #8980

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

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
12 changes: 12 additions & 0 deletions .changelog/12572.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```release-note:bug
accesscontextmanager: fixed permadiff due to reordering on `google_access_context_manager_service_perimeter_dry_run_egress_policy` `egress_from.identities`
```
```release-note:bug
accesscontextmanager: fixed permadiff due to reordering on `google_access_context_manager_service_perimeter_dry_run_ingress_policy` `ingress_from.identities`
```
```release-note:bug
accesscontextmanager: fixed permadiff due to reordering on `google_access_context_manager_service_perimeter_egress_policy` `egress_from.identities`
```
```release-note:bug
accesscontextmanager: fixed permadiff due to reordering on `google_access_context_manager_service_perimeter_ingress_policy` `ingress_from.identities`
```
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,48 @@ func AccessContextManagerServicePerimeterIngressToResourcesDiffSuppressFunc(_, _
return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterEgressFromIdentitiesDiffSuppressFunc(_, _, _ string, d *schema.ResourceData) bool {
old, new := d.GetChange("egress_from.0.identities")

oldResources, err := tpgresource.InterfaceSliceToStringSlice(old)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities config value: %s", err)
return false
}

newResources, err := tpgresource.InterfaceSliceToStringSlice(new)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities api value: %s", err)
return false
}

sort.Strings(oldResources)
sort.Strings(newResources)

return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterIngressFromIdentitiesDiffSuppressFunc(_, _, _ string, d *schema.ResourceData) bool {
old, new := d.GetChange("ingress_from.0.identities")

oldResources, err := tpgresource.InterfaceSliceToStringSlice(old)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities config value: %s", err)
return false
}

newResources, err := tpgresource.InterfaceSliceToStringSlice(new)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities api value: %s", err)
return false
}

sort.Strings(oldResources)
sort.Strings(newResources)

return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterIdentityTypeDiffSuppressFunc(_, old, new string, _ *schema.ResourceData) bool {
if old == "" && new == "IDENTITY_TYPE_UNSPECIFIED" {
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,48 @@ func AccessContextManagerServicePerimeterDryRunEgressPolicyIngressToResourcesDif
return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterDryRunEgressPolicyEgressFromIdentitiesDiffSuppressFunc(_, _, _ string, d *schema.ResourceData) bool {
old, new := d.GetChange("egress_from.0.identities")

oldResources, err := tpgresource.InterfaceSliceToStringSlice(old)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities config value: %s", err)
return false
}

newResources, err := tpgresource.InterfaceSliceToStringSlice(new)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities api value: %s", err)
return false
}

sort.Strings(oldResources)
sort.Strings(newResources)

return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterDryRunEgressPolicyIngressFromIdentitiesDiffSuppressFunc(_, _, _ string, d *schema.ResourceData) bool {
old, new := d.GetChange("ingress_from.0.identities")

oldResources, err := tpgresource.InterfaceSliceToStringSlice(old)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities config value: %s", err)
return false
}

newResources, err := tpgresource.InterfaceSliceToStringSlice(new)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities api value: %s", err)
return false
}

sort.Strings(oldResources)
sort.Strings(newResources)

return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterDryRunEgressPolicyIdentityTypeDiffSuppressFunc(_, old, new string, _ *schema.ResourceData) bool {
if old == "" && new == "IDENTITY_TYPE_UNSPECIFIED" {
return true
Expand Down Expand Up @@ -111,9 +153,10 @@ func ResourceAccessContextManagerServicePerimeterDryRunEgressPolicy() *schema.Re
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"identities": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Type: schema.TypeList,
Optional: true,
ForceNew: true,
DiffSuppressFunc: AccessContextManagerServicePerimeterDryRunEgressPolicyEgressFromIdentitiesDiffSuppressFunc,
Description: `Identities can be an individual user, service account, Google group,
or third-party identity. For third-party identity, only single identities
are supported and other identity types are not supported.The v1 identities
Expand Down Expand Up @@ -508,7 +551,30 @@ func flattenNestedAccessContextManagerServicePerimeterDryRunEgressPolicyEgressFr
}

func flattenNestedAccessContextManagerServicePerimeterDryRunEgressPolicyEgressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
rawConfigValue := d.Get("egress_from.0.identities")
// Convert config value to []string
configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities config value: %s", err)
return v
}
sortedConfigValue := append([]string{}, configValue...)
sort.Strings(sortedConfigValue)

// Convert v to []string
apiValue, err := tpgresource.InterfaceSliceToStringSlice(v)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities API value: %s", err)
return v
}
sortedApiValue := append([]string{}, apiValue...)
sort.Strings(sortedApiValue)

if slices.Equal(sortedApiValue, sortedConfigValue) {
return configValue
}

return apiValue
}

func flattenNestedAccessContextManagerServicePerimeterDryRunEgressPolicyEgressFromSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,48 @@ func AccessContextManagerServicePerimeterDryRunIngressPolicyIngressToResourcesDi
return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterDryRunIngressPolicyEgressFromIdentitiesDiffSuppressFunc(_, _, _ string, d *schema.ResourceData) bool {
old, new := d.GetChange("egress_from.0.identities")

oldResources, err := tpgresource.InterfaceSliceToStringSlice(old)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities config value: %s", err)
return false
}

newResources, err := tpgresource.InterfaceSliceToStringSlice(new)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities api value: %s", err)
return false
}

sort.Strings(oldResources)
sort.Strings(newResources)

return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterDryRunIngressPolicyIngressFromIdentitiesDiffSuppressFunc(_, _, _ string, d *schema.ResourceData) bool {
old, new := d.GetChange("ingress_from.0.identities")

oldResources, err := tpgresource.InterfaceSliceToStringSlice(old)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities config value: %s", err)
return false
}

newResources, err := tpgresource.InterfaceSliceToStringSlice(new)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities api value: %s", err)
return false
}

sort.Strings(oldResources)
sort.Strings(newResources)

return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterDryRunIngressPolicyIdentityTypeDiffSuppressFunc(_, old, new string, _ *schema.ResourceData) bool {
if old == "" && new == "IDENTITY_TYPE_UNSPECIFIED" {
return true
Expand Down Expand Up @@ -112,9 +154,10 @@ to apply.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"identities": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Type: schema.TypeList,
Optional: true,
ForceNew: true,
DiffSuppressFunc: AccessContextManagerServicePerimeterDryRunIngressPolicyIngressFromIdentitiesDiffSuppressFunc,
Description: `Identities can be an individual user, service account, Google group,
or third-party identity. For third-party identity, only single identities
are supported and other identity types are not supported.The v1 identities
Expand Down Expand Up @@ -510,7 +553,30 @@ func flattenNestedAccessContextManagerServicePerimeterDryRunIngressPolicyIngress
}

func flattenNestedAccessContextManagerServicePerimeterDryRunIngressPolicyIngressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
rawConfigValue := d.Get("ingress_from.0.identities")
// Convert config value to []string
configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities config value: %s", err)
return v
}
sortedConfigValue := append([]string{}, configValue...)
sort.Strings(sortedConfigValue)

// Convert v to []string
apiValue, err := tpgresource.InterfaceSliceToStringSlice(v)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities API value: %s", err)
return v
}
sortedApiValue := append([]string{}, apiValue...)
sort.Strings(sortedApiValue)

if slices.Equal(sortedApiValue, sortedConfigValue) {
return configValue
}

return apiValue
}

func flattenNestedAccessContextManagerServicePerimeterDryRunIngressPolicyIngressFromSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,48 @@ func AccessContextManagerServicePerimeterEgressPolicyIngressToResourcesDiffSuppr
return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterEgressPolicyEgressFromIdentitiesDiffSuppressFunc(_, _, _ string, d *schema.ResourceData) bool {
old, new := d.GetChange("egress_from.0.identities")

oldResources, err := tpgresource.InterfaceSliceToStringSlice(old)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities config value: %s", err)
return false
}

newResources, err := tpgresource.InterfaceSliceToStringSlice(new)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities api value: %s", err)
return false
}

sort.Strings(oldResources)
sort.Strings(newResources)

return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterEgressPolicyIngressFromIdentitiesDiffSuppressFunc(_, _, _ string, d *schema.ResourceData) bool {
old, new := d.GetChange("ingress_from.0.identities")

oldResources, err := tpgresource.InterfaceSliceToStringSlice(old)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities config value: %s", err)
return false
}

newResources, err := tpgresource.InterfaceSliceToStringSlice(new)
if err != nil {
log.Printf("[ERROR] Failed to convert ingress from identities api value: %s", err)
return false
}

sort.Strings(oldResources)
sort.Strings(newResources)

return slices.Equal(oldResources, newResources)
}

func AccessContextManagerServicePerimeterEgressPolicyIdentityTypeDiffSuppressFunc(_, old, new string, _ *schema.ResourceData) bool {
if old == "" && new == "IDENTITY_TYPE_UNSPECIFIED" {
return true
Expand Down Expand Up @@ -111,9 +153,10 @@ func ResourceAccessContextManagerServicePerimeterEgressPolicy() *schema.Resource
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"identities": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Type: schema.TypeList,
Optional: true,
ForceNew: true,
DiffSuppressFunc: AccessContextManagerServicePerimeterEgressPolicyEgressFromIdentitiesDiffSuppressFunc,
Description: `Identities can be an individual user, service account, Google group,
or third-party identity. For third-party identity, only single identities
are supported and other identity types are not supported.The v1 identities
Expand Down Expand Up @@ -506,7 +549,30 @@ func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromIden
}

func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
rawConfigValue := d.Get("egress_from.0.identities")
// Convert config value to []string
configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities config value: %s", err)
return v
}
sortedConfigValue := append([]string{}, configValue...)
sort.Strings(sortedConfigValue)

// Convert v to []string
apiValue, err := tpgresource.InterfaceSliceToStringSlice(v)
if err != nil {
log.Printf("[ERROR] Failed to convert egress from identities API value: %s", err)
return v
}
sortedApiValue := append([]string{}, apiValue...)
sort.Strings(sortedApiValue)

if slices.Equal(sortedApiValue, sortedConfigValue) {
return configValue
}

return apiValue
}

func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
Expand Down
Loading
Loading