Problem
I’m using the BICEP template to pass a list of services.
param objectarray array =[]
In addition, I have an array variable that holds a subset of the service names I passed in.
var objectarray =
[
'Abc'
'DEF'
'GHI'
]
My goal is to see if the service names I’m passing in are in the subset, and if they are, I’ll need to change another variable. What is the most effective method for accomplishing this? In BICEP, I’ve used conditional loops and if statements separately, but never combined.
var isInSubset =
Additional Info
I made an attempt.
var apis_with_listener = contains(objectarray, objectarray)
However, the resource I’m creating is a backend policy, and I’m using a for loop to set the value dependent on what apis with listener is set to in the resource creation. Sorry if this sounds perplexing.
value: '<\r\n<policies>\r\n <inbound>\r\n <base />\r\n <set-backend-service backend-id="${APIM_Name}" sf-resolve-condition="@(context.LastError?.Reason == "BackendConnectionFailure")" sf-service-instance-name="@("fabric:/${Application_Name}${Customer_AreaName}/${api}")" **sf-listener-name="${api}Service**" />\r\n </inbound>\r\n <backend>\r\n <base />\r\n </backend>\r\n <outbound>\r\n <base />\r\n </outbound>\r\n <on-error>\r\n <base />\r\n </on-error>\r\n</policies>'
As a result, the sf-listener-name must be set ONLY if the service is one of the subset’s. I’m not sure how to correctly use a for loop and an if statement.
resource BackendPolicy 'Microsoft.ApiManagement/service/apis/policies@2021-04-01-preview'= [for (api,i) in API_Names : {
name: 'policy'
parent:API_Service[i]
properties: {
value: '<\r\n<policies>\r\n <inbound>\r\n <base />\r\n <set-backend-service backend-id="${APIM_Name}" sf-resolve-condition="@(context.LastError?.Reason == "BackendConnectionFailure")" sf-service-instance-name="@("fabric:/${Application_Name}${Customer_AreaName}/${api}")" sf-listener-name="${api}Service" />\r\n </inbound>\r\n <backend>\r\n <base />\r\n </backend>\r\n <outbound>\r\n <base />\r\n </outbound>\r\n <on-error>\r\n <base />\r\n </on-error>\r\n</policies>'
format: 'xml'
}
}]
Asked by Amy
Solution #1
First of all, Bicep doesn’t allow loops within loops, but you don’t need that here as you’re just looking for whether an array contains the string value you’re matching against. Let’s start my saying that all the APIM policy setting is going to happen in its own module, ‘sf-apimPolicy.bicep’, for clarity.
We’ll start with an array of your Service Fabric service names to see if any of them are in a subset, presumably one maintained in your targeted module, as you’ve mentioned.
// sf-apimPolicy.bicep
@description('Your APIM resource name')
param APIM_Name string
@description('The prefix of your SF application name')
param Application_Name string
@description('Used to route to the appropriate SF application per customer')
param Customer_AreaName string
@description('Contains each of your Service names being passed in')
param API_Names array //Presumably this is the 'objectarray' you mention in the question
@description('The array of service names that set a constraint on what can be set in this policy')
param ApiNameConstraints array
resource ApimService 'Microsoft.ApiManagement/service/apis@2021-04-01-preview' existing = {
name: '${APIM_Name}/${ApiServiceName}'
}
//And finally you're looking to set the policy itself if ApiNameConstraints contains your api value
resource BackendPolicy 'Microsoft.ApiManagement/service/apis/policies@2021-04-01-preview' = [for (api, i) in API_Names: if (contains(ApiNameConstraints, api)): {
name: 'policy'
parent: ApimService
properties: {
value: '''
<policies>
<inbound>
<base> // As an aside, changed this from your original value as it used a content-less close tag
<set-backend-service backend-id="${APIM_Name}" sf-resolve-condition="@(context.LastError?.Reason == "BackendConnectionFailure")" sf-service-instance-name="@("fabric:/${Application_Name}${Customer_AreaName}/${api}")" **sf-listener-name="${api}Service**" />
</base> //Also changed this as it didn't use a close tag
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
'''
format: 'xml'
}
}]
The loop will be handled internally if you simply call this module and populate the relevant parameters to call it.
Answered by Whit Waldo
Post is based on https://stackoverflow.com/questions/70351002/use-arrays-and-for-loops-in-bicep