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

Support parameter projections in order to simplify "root" dictionary configurations #6788

Open
WhitWaldo opened this issue May 9, 2022 · 6 comments
Labels
enhancement New feature or request Needs: Upvote This issue requires more votes to be considered

Comments

@WhitWaldo
Copy link

I have an elaborate dictionary variable that describes a number of different properties of some Service Fabric applications and containing services. This dictionary describes several values known ahead of time - what's the name and port of each web service (to pass into Application Gateway for rule building), but there are also several values of this dictionary I'd like to populate as the script deploys (pulled from various output values).

Ideally I'd like to put all this into the single array of dictionaries so it's all in a single place and so I'm not dealing with ensuring that indexes match across sets of arrays, but if I were to do this in Bicep today (constant values in the dictionary + values set as the output of future modules), then pass this object into the modules that will produce said outputs, I get a circular dependency error, as you'd expect.

Today, this looks similar to the apps variable in my example below, but everything that comes from an output is maintained in a separate variable that is created to match the indexes of the first, but created only after the dependencies have run to use their outputs. Then both arrays are passed into still downstream dependencies and the value pulled with key: constantArr[index].value ?? outputArr[index].value. This is a real pain to maintain and tweak.

But this is because Bicep isn't smart enough to look down the usage tree of this parameter and determine that it's not actually circular after-all, because I don't use the values of any of these keys that are set with outputs as part of that module. They just happen to be there and will be set later on.

Describe the solution you'd like
What I'd like to see is Bicep get smarter about understanding how parameters are passed through the module graph and at build, apply projections to narrow the values actually passed to only those that are in use. Ideally this would also indicate true circular dependencies at development time.

Then at development time, I can maintain my large array of dictionaries variable at a root location and keep everything in one place, but know that when it is built, circular dependencies have simply been removed (so they're only included in the projection when their values are both used and set downstream).

This is a contrived example of what I'd like to see (grossly simplified from what I'd actually implement, but gets the point across):

// root.bicep
var apps = [
  {
    name: 'AppA'
    type: 'AppAType'
    targetDomain: 'example.com' //Because no downstream modules ever reference this, it should be grayed out as unused and never actually sent to any modules
    storageContainerName: AzDeployments.outputs.containerName
  }
  //In practice this spans a whole pile of additional properties, both initially known and derived from outputs
]

module AzDeployments './deployment.bicep' = {
  name: 'deployments'
  params: {
     Apps: apps
  }
}

module SfDeployments './sfDeployment.bicep' = {
  name: 'sf-deployments'
  params: {
    Apps: apps
  }
  dependsOn: [
    AzDeployments //Not really necessary since the projector would already know about the dependency from the module reference in the value, but it gives me a great opportunity to place this comment
  ]
}
// deployments.bicep
param Apps array //Because the only values used from this are $.name and $.type, these would be the only two values provided - because $.storageContainerName isn't included, there's no circular dependency

module DeployStorage './storage.bicep' = [for app in Apps: {
  name: 'storage-${app.name}'
  params: {
    name: app.name
    type: app.type
  }
}]

outputs containerName string = DeployStorage.outputs.containerName
// sfDeployment.bicep
param Apps array // And because we use the storageContainerName value here, it's included in this projection along with name and type

module Sf './sf.bicep' = [for app in Apps: {
  name: 'sf-${app.name}
  params: {
    name: app.name
    type: app.type
    containerName: app.storageContainerName
  }
}]
@WhitWaldo WhitWaldo added the enhancement New feature or request label May 9, 2022
@ghost ghost added the Needs: Triage 🔍 label May 9, 2022
@alex-frankel
Copy link
Collaborator

I wonder if this situation would be improved by the introduction of "globals", which was originally raised in #1121 and further discussed in the most recent community call:
https://www.youtube.com/watch?v=OUqg0Xn3K0Y

Thoughts?

@alex-frankel
Copy link
Collaborator

Also may be related to #444 and "Type System v2"

@WhitWaldo
Copy link
Author

@alex-frankel For the most part, I don't know that globals would help because the underlying ask here is for the ability to change the overall shape of a variable between where it's defined and where it's being used.

As I understand them, Globals is more like taking a giant variable on the outside of an operation and making those properties available to everything on the inside in a read-only capacity of sorts, but I already do that. I've got a -root.bicep file that contains sets of these variables and passes them into -subscription.bicep and passes those and outputs from those operations into -rg.bicep where most of the fun happens. Where I'm sitting, Globals would simply reduce some boilerplate between -root and -rg, but not in a particularly meaningful way. Far more useful to me would be being able to add/remove/modify elements from arrays (e.g. pass array with 5 elements into module, get one with 3 differently shaped objects back) and have the intellisense keep up with how I'm modifying objects throughout the ins and outs.

@ghost
Copy link

ghost commented May 24, 2023

Hi WhitWaldo, this issue has been marked as stale because it was labeled as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. Thanks for contributing to bicep! 😄 🦾

@WhitWaldo
Copy link
Author

Dear @msftbot - please stop closing random issues due to lack of activity given that a lot of these issues are undergoing long-term, but active consideration. Thank you!

@alex-frankel
Copy link
Collaborator

We are still working out the kinks for the auto-closer, but the idea is to auto-close items that haven't received a response after we've asked a question. In this case, we forgot to remove the "awaiting response" label for this issue back when you responded on 5/18/22, but we will now do this automatically.

@alex-frankel alex-frankel removed this from the Committed Backlog milestone May 26, 2023
@alex-frankel alex-frankel added the Needs: Upvote This issue requires more votes to be considered label May 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Needs: Upvote This issue requires more votes to be considered
Projects
Status: Todo
Development

No branches or pull requests

4 participants