Azure / Azure/bicep

Proposal - 'Strict mode' for WhatIf / Preflight validation

Open
#7,497 3 comments 1 reaction 0 assignees View on GitHub
discussion enhancement proposal
Dominant language
Bicep
Stars
3.6k
Forks
830
Avg merge
1d 21m
Merged PRs (30d)
79

Description

# Proposal - 'Strict mode' for WhatIf / Preflight validation

## Problem statement
Without any diagnostics, it is difficult to understand which scenarios might cause a template to be partially validated by preflight or what-if. Some example problematic authoring patterns:
* Passing 'runtime' values to nested module parameters, and then using them to format resource names.
* Using `newGuid` / `utcNow` to format resource names.

Other patterns which may decrease WhatIf accuracy or reduce Preflight validation capabilities include:
* Combining 'runtime' & 'deploy time' values to format large body properties.

I'd like to see a 'Strict mode' which can be enabled in the Bicep config, so that full validation is the default behavior, with a way of opting out in situations where runtime behavior is unavoidable.

The opt-out of Strict mode could behave a bit like Rust's [`unsafe` keyword](https://doc.rust-lang.org/std/keyword.unsafe.html) - where all the 'non-strict' code is clearly marked and easier to scrutinize - using for example a `#disable-next-line strict-mode-validation`.

## Syntax
Just some very rough mockups to give an idea of what I'm thinking. With the below, Bicep should give the user the guarantee that **everything** will be evaluated during preflight/what-if, apart from the things that the user has explicitly opted out of with `#disable-next-line strict-mode-validation`.

### bicepconfig.json
```json
{
"strict-mode": {
"enabled": true
}
}
```

### Bicep samples
#### module.bicep
```bicep
// params must be constants by default - requiring a @runtime decorator to opt-out
@runtime()
param myRuntimeValue string

// by default, parameters are considered to be deploy-time constants
param myConstant string

// Blocked with an error message. Runtime value is being used as a default value for a constant param
param myConstantGuid string = newGuid()

// Blocked with an error message. Runtime value is being used as a default value for a constant param
param myConstantDefaultValue string = toLower(myRuntimeValue)

resource blah '...' = {
// Permitted
name: toLower(myConstant)
...
}

resource blah2 '...' = {
// Blocked with an error message. Runtime param value is being used to format a resource name
name: toLower(myRuntimeValue )
...
}

resource blah3 '...' = {
name: 'blah3'
// Warning - preflight/whatif validation will not be precise as we're using a runtime value to format a resource body
properties: myRuntimeValue
}

resource blah4 '...' = {
name: 'blah4'
// Permitted - user has opted out of warning
#disable-next-line strict-mode-validation
properties: myRuntimeValue
}

// Permitted - outputting a Runtime value, but marking as such
@runtime()
output myRuntimeOutput string = blah.properties.runtimeValue

// Permitted - id is a constant
output constantResId string = blah.id

// Permitted - name is a constant
output constantResName string = blah.name

// Blocked - the output has not been marked with @runtime, but is outputting a runtime value
output myConstantOutput string = blah.properties.runtimeValue
```

#### main.bicep
```bicep
resource foo '...' existing = {
name: 'foo'
}

module myMod './module.bicep' = {
name: 'myMod'
params: {
// Permitted - using a runtime value for a param marked with @runtime
myRuntimeValue: foo.properties.somethingUnsafe
// Blocked
myConstant: foo.properties.somethingUnsafe
// Permitted - id, name, type & apiVersion are constants
myConstantGuid : foo.id
}
}

module otherMod './otherMod.bicep' = {
// Permitted - we know that constantResName is a constant
name: myMod.outputs.constantResName
params: {
// Permitted - passing a runtime output to a runtime param
runtimeParam: myMod.outputs.myRuntimeOutput
// Permitted - passing a constant output to a constant param
constantParam: myMod.outputs.constantResId
}
}
```

## Implementation
TBD. I wanted to create this issue to gauge interest first.

Contributor guide

Open the contributing guide

Research direction

Review the proposal's bicepconfig.json, module.bicep, and main.bicep examples to identify the requested strict-mode rules, runtime opt-outs, and diagnostics. Implementation is marked TBD; work would be complete when the behavior, configuration, syntax, and validation scope are defined and agreed for the shown scenarios.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure
Domain
cloud, compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.