Azure / bicep

Bicep is a declarative language for describing and deploying Azure resources
MIT License
3.27k stars 756 forks source link

Support float values #1386

Open miqm opened 3 years ago

miqm commented 3 years ago

Follow up from #486

We need to add support for floating point values that can be entered by user. Floating point values - numbers with dot i.e. 3.14 have following constraints:

Valid usage in ARM:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "inPi": {
      "type": "string",
      "defaultValue": "3.14"
    }
  },
  "functions": [],
  "variables": {
    "pi": 3.14,
    "objectPi": {
      "pi": 3.14
    },
    "pi2": "[float('3.14')]",
    "pi3": "[float(variables('pi'))]",
    "pi4": "[float(parameters('inPi'))]"
  },
  "resources": [],
  "outputs": {
    "out0": {
      "type": "object",
      "value": "[createObject('pi', variables('pi'))]"
    },
    "out1": {
      "type": "object",
      "value": "[variables('objectPi')]"
    },
    "out2": {
      "type": "object",
      "value": "[createObject('pi2',variables('pi2'))]"
    },
    "out3": {
      "type": "object",
      "value": "[createObject('pi3',variables('pi3'))]"
    },
    "out4": {
      "type": "object",
      "value": "[createObject('pi4',variables('pi4'))]"
    }
  }
}
kopendrex commented 3 years ago

Problem with the floating point is in the 'Microsoft.ContainerInstance/containerGroups' too, there is validation error during try set 0.5 memory resources:{ requests:{ cpu: 1 memoryInGB: 0.5 } }

miqm commented 3 years ago

@alex-frankel perhaps we can shift this to v0.3?

alex-frankel commented 3 years ago

No objections to doing this sooner, but @miqm I think there are more pressing needs for 0.3. Do you think you could pick up either of these?

image

Obviously, no worries if you'd rather not pick those up and focus on items that are more appealing to you. LMK.

majastrz commented 3 years ago

Yeah, I'm not sure there's an agreed upon design for this issue yet. Also, @TarunSunkaraneni picked up the output file location one.

miqm commented 3 years ago

Ok, then I'll take the key vault issue.

anthony-c-martin commented 3 years ago

If anyone runs into this, the workaround for now is to use the json() function with a string representation of your float value, so where you would want to write 3.14, instead write json('3.14').

e.g.:

var pi = json('3.14')

output out0 object = {
  pi: pi
}
benc-uk commented 3 years ago

I'm trying to deploy the new 'Azure Container Apps' https://docs.microsoft.com/en-gb/azure/container-apps/?ocid=AID3042118

This also requires a fractional (floating point) when specifying the resources for containers

If I try to pass cpu: 1 I get the following error

Container with name 'foo' has an invalid CPU resource request: '0'. The 'cpu' field for each container, if provided, must contain a decimal value to no more than two decimal places. Example: '0.25'

The json() workaround above didn't work for me

anthony-c-martin commented 3 years ago

The json() workaround above didn't work for me

Would you mind sharing the error message you got with this workaround, and a code sample (if possible)?

benc-uk commented 3 years ago

This is error I'm getting, when I tried using cpu: json('0.50')

Container with name 'nodeapp' has an invalid CPU resource request: '0'. The 'cpu' field for each container, if provided, must contain a decimal value to no more than two decimal places. Example: '0.25'

This is when deploying 'Microsoft.Web/containerApps@2021-03-01 resource

If you deploy one of these via the portal it looks like this

{
    "id": "/subscriptions/blah/resourceGroups/apps/providers/Microsoft.Web/containerApps/test",
    "name": "test",
    "type": "Microsoft.Web/containerApps",
    "location": "North Central US (Stage)",
    "properties": {
        "provisioningState": "Succeeded",
        "kubeEnvironmentId": "/subscriptions/blah/resourceGroups/nodeapp/providers/Microsoft.Web/kubeEnvironments/nodeapp",
        "latestRevisionName": "test--2x1mta5",
        "latestRevisionFqdn": "test--2x1mta5.mangopond-04fd2bbf.northcentralusstage.azurecontainerapps.io",
        "configuration": {
            "activeRevisionsMode": "Multiple",
            "ingress": "REMOVED FOR BREVITY"
        },
        "template": {
            "revisionSuffix": "",
            "containers": [
                {
                    "image": "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest",
                    "name": "simple-hello-world-container",
                    "resources": {
                        "cpu": 0.25,
                        "memory": ".5Gi"
                    }
                }
            ],
            "scale": {
                "maxReplicas": 10
            }
        }
    }
}

It could be a bug with that RP, as it's super new, and basically hardly documented at this point, so I'm a little bleeding edge here!

alex-frankel commented 3 years ago

@benc-uk if you authored this directly in ARM Template JSON, would the template deploy? Can you try:

  1. Run bicep build on a version of the bicep file that validates w/o errors
  2. Tweak the emitted JSON to use the float value directly
  3. Deploy

If that works, that may add some urgency to supporting floats as the API would be able to handle it.

miqm commented 3 years ago

I've took the portal template and basically the container definition there is taken from parameter file. If you look at the parameters object, the cpu property is a string, not a float. image I also tested the json('0.25') workaround and it works for me, here's my bicep successfully deployed:

param name string
param location string
param environmentName string
param workspaceName string

resource containerApp 'Microsoft.Web/containerapps@2021-03-01' = {
  name: name
  kind: 'containerapps'
  location: location
  properties: {
    kubeEnvironmentId: kubeEnv.id
    configuration: {
      secrets: []
      registries: []
      ingress: {
        external: true
        targetPort: 80
      }
    }
    template: {
      containers: [
        {
          name: 'simple-hello-world-container'
          image: 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
          command: []
          resources: {
            cpu: json('0.25')
            memory: '.5Gi'
          }
        }
      ]
    }
  }
}

resource kubeEnv 'Microsoft.Web/kubeEnvironments@2021-03-01' = {
  name: environmentName
  location: location
  properties: {
    type: 'managed'
    internalLoadBalancerEnabled: false
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalytics.properties.customerId
        sharedKey: logAnalytics.listKeys().primarySharedKey
      }
    }
  }
}

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2020-08-01' = {
  name: workspaceName
  location: location
  properties: {
    sku: {
      name: 'PerGB2018'
    }
    retentionInDays: 30
    workspaceCapping: {}
  }
}

Also, when I tried to do some changes to test different cpu values (I used 0.25 as in the portal default, you used 0.5) - I've got a following message: Total CPU and memory for all containers defined in a Container App must add up to one of the following CPU - Memory combinations: [cpu: 0.25, memory: 0.5Gi]; [cpu: 0.5, memory: 1.0Gi]; [cpu: 0.75, memory: 1.5Gi]; [cpu: 1.0, memory: 2.0Gi]; [cpu: 1.25, memory: 2.5Gi]; [cpu: 1.5, memory: 3.0Gi]; [cpu: 1.75, memory: 3.5Gi]; [cpu: 2.0, memory: 4.0Gi]

I assume the error you're getting was RP related, not bicep or ARM one. Perhaps try again and let us know if it works or not.

benc-uk commented 3 years ago

I'm a total idiot, it was an error in my template 🤦‍♂️🤡

I had my resources nested inside an requests object for some strange reason, my brain probably lapsed into Kubernetes pod YAML or something. Muscle memory I guess. And this is such a new resource & API version I didn't have any type hints

// Don't do this, it's wrong
resources: {
  requests: {
    cpu: json('0.25')
    memory: '.5Gi'
  }
}

To be fair the error I got from the RP was extremely misleading, but that's not a Bicep problem!

Sorry for wasting people's time 😖 And thanks @miqm for the working template

nansravn commented 3 years ago

The creation of AKS managed pools with spot instances is also being affected by this issue #1386. I'll try the json() workaround, that I've just found on this thread.

I'm creating a ManagedCluster on AKS and one of my node pools will use Spot VMs. My bicep structure:

resource aks 'Microsoft.ContainerService/managedClusters@2021-07-01' = {
    ...
    agentPoolProfiles: [
        ...
        {
            ...
            scaleSetPriority: 'Spot'
            spotMaxPrice: json('0.5')
        }
    ]
}

By now the property spotMaxPrice expects an int, but the it should be able to be filled with decimal values, if Bicep supported it.

This is the description of spotMaxPrice from the official documentation:

Name Description Value
spotMaxPrice Possible values are any decimal value greater than zero or -1 which indicates the willingness to pay any on-demand price. For more details on spot pricing, see spot VMs pricing int
hansmbakker commented 2 years ago

there is also an issue with creating Azure Container Instances because of this. The memoryInGB property can take a float which bicep only supports using the json workaround: https://docs.microsoft.com/en-us/azure/templates/microsoft.containerinstance/containergroups?tabs=bicep

SeidChr commented 2 years ago

float is still not supported, even though it is clearly part of arm. issue is active for almost 1.5 years now. ms already lost interest in bicep? another dead project? havnt looked at bicep in quite some time and expected it to be more stable now, and the first arm template i try to convert to bicep uses a float .. *bummer

brwilkinson commented 2 years ago

@SeidChr just use the workaround?

json('0.25')

SeidChr commented 2 years ago

@SeidChr just use the workaround?

json('0.25')

Yes, probably going to do that.

But my post had a slightly different subtone 😅 I was using bicep like anyone new to it would probably use it, by converting an arm into bicep. Yet the first issue i find is a 1.5 year old bug. It's just doesn't shine a good light on the project which is the supposed successor of arm that is in the news for quite some time.

Probably not the right place to express this. Sorry.

ds-evo commented 2 years ago

float is still not supported, even though it is clearly part of arm. issue is active for almost 1.5 years now. ms already lost interest in bicep? another dead project? havnt looked at bicep in quite some time and expected it to be more stable now, and the first arm template i try to convert to bicep uses a float .. *bummer

maybe, this is the future? https://azure.github.io/azure-service-operator/

don't know

onionhammer commented 2 years ago

Nobody knows the future, but bicep is definitely seeing a lot of investment in terms of being added to all the official azure docs and examples. Releases are still being made regularly, this feature just didnt get prioritized.. probably because there is a simple workaround.

brwilkinson commented 2 years ago

@SeidChr

If you have been away then the best place to catch up is checking out the community calls.

March: https://www.youtube.com/watch?v=mW74PTpAXXs Jan: https://www.youtube.com/watch?v=nDlH6TiOedI

miqm commented 2 years ago

@alex-frankel this issue keeps popping out, can we re-prioritise it?

alex-frankel commented 2 years ago

Had a two minute discussion about what might be required for this. Capturing a few notes below:

ezYakaEagle442 commented 2 years ago

@brwilkinson I have a similar requirement:

I try to configure an Azure Container App setting a pram to set the Resources CPU&RAM. I hit The value must be a compile-time constant.bicep(BCP032):

How to implement this please ?

@allowed([ json('0.25') json('0.5') json('0.75') json('1.0')
json('1.25') json('1.5') json('1.75') json('2.0')
]) @description('The container Resources CPU') param containerResourcesCpu object = json('0.25')

@allowed([ json('0.5') json('1.0')
json('1.5') json('2.0')
json('2.5') json('3.0')
json('3.5') json('4.0')
]) @description('The container Resources Memory') param containerResourcesMemory object = json('0.5')

resource ContainerApp 'Microsoft.App/containerApps@2022-03-01' = { properties: { template: { containers: [ { resources: { cpu: containerResourcesCpu // json('0.5') //500m memory: containerResourcesMemory // Gi }

What is the plan for Bicep to support float ?

ezYakaEagle442 commented 2 years ago

work around with :

@allowed([
  '0.25'
  '0.5'
  '0.75'
  '1.0' 
  '1.25'
  '1.5'
  '1.75'
  '2.0'    
])
@description('The container Resources CPU')
param containerResourcesCpu string = '0.5'

@allowed([
  '0.5'
  '1.0'  
  '1.5'
  '2.0'    
  '2.5'
  '3.0'  
  '3.5'
  '4.0'    
])
@description('The container Resources Memory')
param containerResourcesMemory string = '1.0'

resource ContainerApp 'Microsoft.App/containerApps@2022-03-01' = {
  properties: {
    template: {
      containers: [
        {
          resources: {
            cpu: json(containerResourcesCpu) // 250m
            memory: json(containerResourcesMemory) // Gi
          }
brwilkinson commented 2 years ago

@ezYakaEagle442

was about to suggest

@allowed([
  '0.25'
  '0.5'
  '0.75'
  '1.0'
  '1.25'
  '1.5'
  '1.75'
  '2.0'
])
@description('The container Resources CPU')
param containerResourcesCpu string = '0.25'

@allowed([
  '0.5'
  '1.0'
  '1.5'
  '2.0'
  '2.5'
  '3.0'
  '3.5'
  '4.0'
])
@description('The container Resources Memory')
param containerResourcesMemory string = '0.5'

output cpu string = json(containerResourcesCpu)
output mem string = json(containerResourcesMemory)
michalchecinski commented 1 year ago

Is this issue on the roadmap? It's open for over 2 years, and since the json() workaround works, it's not working for all scenarios (e.g.: What-If deployment, the issue described here: https://github.com/TheCloudTheory/arm-estimator/issues/180).

brwilkinson commented 1 year ago

I was going to write a ceil (ceiling) function, then realized we don't support Float.

I guess I would upvote.

onionhammer commented 1 year ago

Two years later.. how we doing on this one?

image

flytzen commented 1 year ago

Another issue with this is that some values are returned as floats, even though (parts of) Bicep thinks it's an int. For example, for a Log Analytics Workspace, properties.workspaceCapping.dailyQuotaGb is a float - though Bicep intellisense thinks it's an int.

If you then try to reference that value, say to set an alert when you are at 80% you get into trouble. var eightyPercentOfLawCap =logAnalyticsWorkspace.properties.workspaceCapping.dailyQuotaGb * 80 / 100 will fail with the error 'The template language function 'mul' expects its first parameter to be of type 'Integer'.

Workaround is to set a variable for the daily quota first and then use that in both places. (Although, that doesn't really work because the decimals are stripped from the calculation because of the general lack of support for float, but that is the more general issue).

sdball commented 1 year ago

This is also an issue when defining expressions for logic apps in Bicep.

A valid declaration in logic app json

{
  "less": [
    "@variables('some_var')",
    0.95
  ]
}

That decompiles into the bicep

{
  less: [
    '@variables('some_var')'
    '0.95'
  ]
}

When deployed from Bicep that results in a logic app that has the 0.95 value declared as a string which then throws an error because less cannot evaluate with a Float / String mismatch.

Bicep doesn't allow declaring the 0.95 value directly, but the json() workaround does work fine once manually applied.

chrisbuttacavoliadec commented 11 months ago

How is this still not supported? Bicep should support float values like every other programming language

sebader commented 6 months ago

Usually I'm not a fan of +1 posts...but: any update on this one @alex-frankel ?

ARM templates support it, RP API specifications do support it, so Bicep needs to support it, too.

alex-frankel commented 6 months ago

No major updates sorry..

I think this is one of those paper cuts that is really silly to experience, but the workaround/mitigation is relatively straightforward. Is that a fair interpretation?

If we have a misunderstanding on that, I'm happy to share it with the team and maybe we can reprioritize.

onionhammer commented 6 months ago

Seems silly that this is still an issue, especially now that there's support for complex custom types

sebader commented 6 months ago

I think this is one of those paper cuts that is really silly to experience, but the workaround/mitigation is relatively straightforward. Is that a fair interpretation?

The workaround might be easy - if you know it. But it's neither intuitive nor in the docs (unless I'm mistaken) so how would any user know of it?

SeidChr commented 6 months ago

Sorry for the unpopular opinion, but Bicep really feels like dead. And to be honest, it feels like this from the beginning. There is hardly any visible progress in the development. Yet it's pushed hard in all the promotional dev demos. It's just an additional layer of complexity defining defaults for certain properties which saves space, but stops any tool from natively generating it, because it's not json. It does not provide any additional functionality over arm templates (that i am aware of. Please challenge my opinion), and just 'simplifies' the Creation of arm template json files. Literally any other tool which can output json can do that, more and better. I guess it's not the right place to post this, but i don't know a better one. It's frustrating to see.

Sebastian @.***> schrieb am Di., 21. Mai 2024, 22:38:

I think this is one of those paper cuts that is really silly to experience, but the workaround/mitigation is relatively straightforward. Is that a fair interpretation?

The workaround might be easy - if you know it. But it's not intuitive not in the docs (unless I'm mistaken) so how would any user know of it?

— Reply to this email directly, view it on GitHub https://github.com/Azure/bicep/issues/1386#issuecomment-2123402633, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOWPJH5GH72PRB46IXH6Q3ZDOWEHAVCNFSM4WT7NBN2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TEMJSGM2DAMRWGMZQ . You are receiving this because you were mentioned.Message ID: @.***>

SvenAelterman commented 6 months ago

Sorry for the unpopular opinion, but Bicep really feels like dead. And to be honest, it feels like this from the beginning. There is hardly any visible progress in the development. Yet it's pushed hard in all the promotional dev demos. It's just an additional layer of complexity defining defaults for certain properties which saves space, but stops any tool from natively generating it, because it's not json. It does not provide any additional functionality over arm templates (that i am aware of. Please challenge my opinion), and just 'simplifies' the Creation of arm template json files. Literally any other tool which can output json can do that, more and better. I guess it's not the right place to post this, but i don't know a better one. It's frustrating to see.

I think you've described exactly what the purpose of Bicep is: to simplify creating ARM templates. As such, in my experience, the abstraction doesn't create additional complexity but rather hides that of ARM JSON.

As such, we should only expect to have language features (or which there are plenty, such as modules, UDTs, etc.)

I am curious to learn of any other tool that can make the creation of ARM templates easier?

SeidChr commented 6 months ago

Well, a Powershell module will do the job. Content is hardcoded defaults, put into Powershell objects, manipulated by parameters, extensible with own functions (modules) or callback scripts. Serializable to arm templates directly with native in-built support for generating json, and also compatible with all sorts of dotnet objects. And you can even apply logic, number conversions and similar.

Sven Aelterman @.***> schrieb am Do., 23. Mai 2024, 14:20:

Sorry for the unpopular opinion, but Bicep really feels like dead. And to be honest, it feels like this from the beginning. There is hardly any visible progress in the development. Yet it's pushed hard in all the promotional dev demos. It's just an additional layer of complexity defining defaults for certain properties which saves space, but stops any tool from natively generating it, because it's not json. It does not provide any additional functionality over arm templates (that i am aware of. Please challenge my opinion), and just 'simplifies' the Creation of arm template json files. Literally any other tool which can output json can do that, more and better. I guess it's not the right place to post this, but i don't know a better one. It's frustrating to see.

I think you've described exactly what the purpose in Bicep is: to simplify creating ARM templates. As such, in my experience, the abstraction doesn't create additional complexity but rather hides that of ARM JSON.

As such, we should only expect to have language features (or which there are plenty, such as modules, UDTs, etc.)

I am curious to learn of any other tool that can make the creation of ARM templates easier?

— Reply to this email directly, view it on GitHub https://github.com/Azure/bicep/issues/1386#issuecomment-2126969146, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOWPJGVA3UJE7XHJTBLZGDZDXNHJAVCNFSM4WT7NBN2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TEMJSGY4TMOJRGQ3A . You are receiving this because you were mentioned.Message ID: @.***>

slavizh commented 6 months ago

Bicep is not dead. There were significant improvements made since the start of the project. Those improvements are not only Bicep specific but also available in ARM. Nobody stops you from using PowerShell if you do not find Bicep suitable for your task and liking. The advantages and disadvantages of using Bicep vs PowerShell or other automation tools are well known and we are getting out of topic discussing them in this thread.

alex-frankel commented 6 months ago

+1 to @slavizh

@SeidChr - I'd recommend creating a Discussion post for this topic.

Though I will defend one point - we do essentially zero "official" marketing. There are no sales/field targets set around moving to bicep or anything of the sort. Bicep's popularity (or lack thereof depending on your perspective) has been organic precisely because we want to avoid any perception that we are pushing customers one way or another. If you feel there is aggressive marketing happening out there, it is not coming from this group. @SeidChr if you have any examples of this I'd love to take a look.

alex-frankel commented 6 months ago

But it's neither intuitive nor in the docs (unless I'm mistaken) so how would any user know of it?

Yes, this is the indeed the problem. We had a discussion about this yesterday and fixing this is surprisingly expensive to implement, thus the relatively low ROI. That being said, given the passion here, we will do our best to reprioritize.

vRune4 commented 3 months ago

It worries me when Alex says this is expensive to implement as perhaps there are more important issues in the pipeline that will have a bigger positive impact on my projects.

Would it be easier if properties changed from int to string in the templates? E.g.: cpu: '0.25'

yggdrasiljsp commented 1 week ago

this was a big surprise to find out about, thanks for the json workaround. Native support for floats/decimals would be very beneficial