How to prevent reversion of changes known to be applied elsewhere? #9921
-
I have a template that describes a set of Container App instances and surrounding infrastructure. It works great to initially provision it all, and it's a great way to incrementally evolve that infra. However, there are some places where I wish I could annotate a particular property as being only relevant when initially creating a resource. For example, the name of a container app's container image: it's strictly necessary to create the resource, but it's known and expected that that property will be changed outside of bicep deployments (whether via the portal, or far more commonly via CI/CD processes that only ever bump the deployed container image, and don't touch anything else). As it stands, I need to be sure the container image parameter going into the deployment process matches what is currently deployed, or obviously, bad things will happen. This is to say nothing of possible race conditions between a bicep deployment and a CI/CD-originated container image bump, or some future where we'll have multiple versions of container images in different app replicas, etc. Is there a way to make bicep deployments ignore certain resource properties that are known to be regularly modified otherwise? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
Hi @cemerick On some resource types some properties are optional and it is possible setup conditions on these OR on the whole resources. If you do use a condition you can maintain state such as a flag to say to skip the deployment all together. However in the case of containerApps the image is a required property. So you can only skip deploying the resource all together. Would it be possible to integrate your same template into your Deployment pipeline? That way you pass in the image name as a parameter which comes from a Build variable? It's hard if you have 2 separate pipelines, So perhaps just build the Container App Environment in your main templates, then deploy the Apps in the App Pipeline? In theory it is possible to use and existing Resource to read the current setting, then use that to apply over the top of your new deployment. The first time you deploy you need to set a flag to provide a starter value, then onwards from them, it uses the results of the GET to be used on the PUT ... I will setup a sample for you, then post back.... in the meantime here is a sample of the same from App Service. appConfigCurrent: contains(ws, 'initialDeploy') && bool(ws.initialDeploy) ? {} : appsettingsCurrent[index].list().properties You have to use a nested Module to make it work... you have a default value and use that if initialDeploy: 1 then you pass in the output from the existing and use that if intialDeploy: 0. So you do need to toggle that or deploy twice in the beginning to get it up and running.
containers: [
{
image: 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
name: 'simple-hello-world-container' I think it's just a though experiment and perhaps not the way to run in production. Anyway I will test it out. |
Beta Was this translation helpful? Give feedback.
-
@cemerick how did you end up solving this? It seems using the bicep as part of the app CD using an image param is the only option. Typically we'd configure infrastructure in a dedicated pipeline but as it stands any infrastructure update would revert the image to the incorrect version. If say for example it had been updated as part of a dedicated app pipeline. |
Beta Was this translation helpful? Give feedback.
-
Did you arrive on any good workflows here @thisispaulsmith @cemerick ? Struggle really hard to create a good deployment pipeline that doesn't go through an entire Bicep-deployment where rest of infrastructure and dependent resources are created. I would imagine splitting the provisioning part and the updates of the app "manifest/template" would be ideal in my case at least. So as a potential workaround now I might be able to set a variable "initialProvisioning" to only create the container app in the case where we are initially provisioning resources using the if expression on the resource: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/conditional-resource-deployment#new-or-existing-resource param initialProvisioning bool
var containerAppName = 'some-container-app-name'
resource containerApp 'Microsoft.App/containerApps@2023-05-01' = if (initialProvisioning) {
name: containerAppName
location: location
....
And rather use a app.yml properties:
configuration:
....
template:
containers:
- image: 'someimage'
name: container-app
probes:
- type: Liveness
httpGet:
path: "/healthz"
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
scale:
minReplicas: 2
maxReplicas: 5 This way I can:
This feels like a hacky'ish solution though... Would appreciate some input on achieving a similar workflow! @brwilkinson |
Beta Was this translation helpful? Give feedback.
Hi @cemerick
On some resource types some properties are optional and it is possible setup conditions on these OR on the whole resources.
If you do use a condition you can maintain state such as a flag to say to skip the deployment all together.
However in the case of containerApps the image is a required property. So you can only skip deploying the resource all together.
Would it be possible to integrate your same template into your Deployment pipeline? That way you pass in the image name as a parameter which comes from a Build variable?
It's hard if you have 2 separate pipelines, So perhaps just build the Container App Environment in your main templates, then deploy the Apps in the App P…