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

what-if for App Gateway does not preserve order of all child resources #387

Open
jrobins-tfa opened this issue Jan 13, 2025 · 5 comments
Open

Comments

@jrobins-tfa
Copy link

jrobins-tfa commented Jan 13, 2025

Bicep version
Bicep CLI version 0.32.4 (b326faa456)

This problem has also has happened on all earlier versions, I just haven't gotten around to a bug report until now.

Describe the bug
We have an Azure App Gateway we maintain via Bicep. Within it are the various child resources - backend pools, backend settings, request routing rules, probes, etc.

When running a what-if command, it does not maintain the order of child resources. I see this most often with the request routing rules, but have seen it with other child resources as well. The what-if will swap around some of the rules, so it looks like a ton of changes are being made when there are actually no changes. For example, if I have six routing rules, agwrr1 through agwrr6 (in that order), when I run a what-if, I might see:

    ~ properties.requestRoutingRules: [
      ~ 1:
        ~ name:                       "agwrr1" => "agwrr3"
        ~ propertyX:                  "propX1" => "propX3"
        ~ propertyY:                  "propY1" => "propY3"

      ~ 2:
        ~ name:                       "agwrr2" => "agwrr5"
        ~ propertyX:                  "propX2" => "propX5"
        ~ propertyY:                  "propY2" => "propY5"

      ~ 3:
        ~ name:                       "agwrr3" => "agwrr2"
        ~ propertyX:                  "propX3" => "propX2"
        ~ propertyY:                  "propY3" => "propY2"

      ~ 5:
        ~ name:                       "agwrr5" => "agwrr1"
        ~ propertyX:                  "propX5" => "propX1"
        ~ propertyY:                  "propY5" => "propY1"

...but with quite a few properties on each of these, with longer names and values, and no rhyme or reason I can find for why it puts them in that particular order. If I run the bicep file and then immediately do the what-if, I still get the same result, so I don't think that what-if here is predicting the changes accurately. When I execute the bicep file, it doesn't actually rearrange the rules.

This creates a lot of noise in the what-if, which makes it hard to see what actual changes are going to be applied, especially if there are changes in the request routing rules themselves (or whatever other child resource is getting incorrectly ordered).

To Reproduce
Create a bicep file for deploying an application gateway, set it up with several backend pools, backend settings, request routing rules, etc. Deploy it, then run a what-if.

I have searched for a report for this and didn't find one, though I know there are known issues with what-if.

@jeskew
Copy link
Member

jeskew commented Jan 15, 2025

@jrobins-tfa Are the routing rules sorted in a stable way (e.g., alphabetically by name, in the order they would be evaluated by the service, etc.)? It's not ideal, but you may be able to work around the noise by changing the order of the array in the template to match whatever sort the service uses.

@jrobins-tfa
Copy link
Author

@jeskew That's a good idea, but unfortunately not feasible the way we have things organized. We have several apps deployed to this gateway and we store the properties for each one in a separate file and then join them together with the spread operator in the main param file. So we have something like:

app1.bicep
@export
var routingRules = [
  {
    name: rule1
    ...
  }
  {
    name: rule2
  }
]

(other vars here)
app2.bicep
@export
var routingRules = [
  {
    name: rule3
    ...
  }
  {
    name: rule4
  }
]

(other vars here)
agw.bicep
import * as app1 from 'app1.bicep'
import * as app2 from 'app2.bicep'

var routingRules = [
  ...app1.routingRules
  ...app2.routingRules
]

Since the arbitrary swapping does things like swap rule1 and rule 3, which are in different files, we wouldn't be able to change the order of our array without abandoning our organizational scheme.

@jrobins-tfa
Copy link
Author

It occurred to me just now (and I think it's not the first time, but I forgot when I was creating this ticket) that even better than preserving order would be if the command correctly matched up child resources by name. In my example just above, app1 has rule1 and rule2, and app2 has rule3 and rule4. If I then add rule5 to app 1, then processing these in order would lead to a bunch of mismatches - app1 and app2 would be in the same spots, but rule 5 would be third, rule3 would be fourth, and rule4 would be fifth. Instead of trying to maintain the order of resources, it could correctly say "rule1 matches existing rule1, rule2 matches existing rule2, rule3 matches existing rule3, rule4 matches existing rule4, rule5 is new", then it would only show the changes of rule5 and ignore the ones that hadn't changed, regardless of their order.

@majastrz
Copy link
Member

We are currently looking at improving this experience by diffing array elements better by recognizing which property is the "key" or "identifier" of an array element. However, longer term this can be solved by introducing new OpenAPI Spec annotations for RPs to adopt.

@jeskew jeskew transferred this issue from Azure/bicep Jan 15, 2025
@jrobins-tfa
Copy link
Author

We are currently looking at improving this experience by diffing array elements better by recognizing which property is the "key" or "identifier" of an array element. However, longer term this can be solved by introducing new OpenAPI Spec annotations for RPs to adopt.

Thanks! That sounds like it will solve the problem, so this ticket can probably be folded into that one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Todo
Development

No branches or pull requests

3 participants