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

Using variables for zones in template results in type mismatch #449

Closed
Adunaphel opened this issue Sep 4, 2020 · 7 comments · Fixed by #2664
Closed

Using variables for zones in template results in type mismatch #449

Adunaphel opened this issue Sep 4, 2020 · 7 comments · Fixed by #2664
Assignees
Labels
bug Something isn't working discussion This is a discussion issue and not a change proposal. type system
Milestone

Comments

@Adunaphel
Copy link

I am trying to do the following ARM in Bicep:

"variables": {
    "zones": "[if( greater( parameters( 'virtualMachine' ).zone, 0 ), array( parameters( 'virtualMachine' ).zone ), json( '[]' ) )]",
}
"resources": [
    {
            "name": "[variables( 'publicIpAddressName' )]",
            "type": "Microsoft.Network/publicIPAddresses",
            "zones": "[if( parameters( 'virtualMachine' ).network.enablePublicIpZone, variables( 'zones' ), json( 'null' ) )]",
    }
]

When I condense it down to the following:

var zones = virtualMachine.zone > 0 ? createArray(virtualMachine.zone) : []

resource pubipv4 'Microsoft.Network/publicIpAddresses@2020-05-01' = {
    name: '${virtualMachine.name}-pip'
    zones: virtualMachine.network.enabledPublicIpZone ? zones : null
}

I am greeted by the error message "The property 'zones' expected a value of type 'string[]' but the provided value is of type 'array | null'."

@ghost ghost added the Needs: Triage 🔍 label Sep 4, 2020
@alex-frankel
Copy link
Collaborator

Good catch.

Just posting this here for future reference to have an example VM with zones:
https://github.com/Azure/azure-quickstart-templates/blob/master/101-vm-simple-zones/azuredeploy.json

@alex-frankel alex-frankel added bug Something isn't working and removed Needs: Triage 🔍 labels Sep 4, 2020
@alex-frankel alex-frankel added this to the v0.2 milestone Sep 4, 2020
@alex-frankel alex-frankel modified the milestones: v0.2, v0.3 Sep 30, 2020
@alex-frankel
Copy link
Collaborator

alex-frankel commented Oct 1, 2020

We're going to take care of this as part of our 0.3 release, as the fix is going to take us a bit more time to do right. In the meantime, we have an undocumented escape hatch that you can use called any(). If you wrap the value in the any function, it should disable the type check:

var zones = virtualMachine.zone > 0 ? createArray(virtualMachine.zone) : []

resource pubipv4 'Microsoft.Network/publicIpAddresses@2020-05-01' = {
    name: '${virtualMachine.name}-pip'
    zones: any(virtualMachine.network.enabledPublicIpZone ? zones : null)
}

Let us know if you have any questions.

We will document any() as part of #585

@anthony-c-martin
Copy link
Member

Adding my comment from #1735 here:

The way I'd like to see this work is for all non-required properties to be treated as nullable, and then treat the assigned type of the ternary expression as <type> | null - e.g.:

var myObj = {
  // returns an error
  required: null
  // returns an error
  alsoRequired: condition ? null : someValue
  // is allowed
  optional: null
  // is allowed
  alsoOptional: condition ? null : someValue
}

@miqm
Copy link
Collaborator

miqm commented Mar 15, 2021

Adding one case that I think it's related with this - using a conditional in a module scope:

Following code:

module mod 'mod.bicep' = if (!empty(otherResourceGroup)) {
  name: '${_deployment}-mod'
  scope: !empty(otherResourceGroup) ? resourceGroup(otherResourceGroup) : resourceGroup()

results in error:

The property "scope" expected a value of type "resourceGroup" but the provided value is of type "resourceGroup | resourceGroup".

@anthony-c-martin
Copy link
Member

Adding one case that I think it's related with this - using a conditional in a module scope:

Great find! Would you mind creating a separate issue for this?

@majastrz
Copy link
Member

I agree with @anthony-c-martin's idea here. That is the cleanest way to fix it. However, we have to decide how we present this to the users in the language server. The vast majority of properties in swaggers are not marked as required even though they are actually required to create the resource.

Once we implement the idea in the type system, the types of non-required properties will appear as string | null, int | null, 'foo' | 'bar' | null, or similar. This will show up in hovers, error messages, etc. My worry is that we will create an expectation of being able to assign null to properties that do not actually accept null.

One option would be to simplify the rendering/presentation of any type of the form <x> | null to just <x>. That solves the problem I mentioned but could be misleading in a different way.

I'm inclined to just expose the problem so everything stays consistent and then deal with the swagger inaccuracies over time, but I'm curious what others think.

@majastrz majastrz added the discussion This is a discussion issue and not a change proposal. label May 12, 2021
@majastrz
Copy link
Member

Changing the type of all non-required properties to <x> | null will have a side effect of breaking property access expressions that are using it. For example, if you use a string property of a resource in a concat function, it doesn't allow null values, so an error would be logged.

One option would be to have two types on every property: a "read" type and a "write" type and only modify the "write" type to include the | null part.

For now we decided to make a simpler fix to simply relax some of the assignability checks when we have TypePropertyFlags available. This is less risky and should unblock these scenarios. We can revisit making a more comprehensive change in the future.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working discussion This is a discussion issue and not a change proposal. type system
Projects
None yet
5 participants