I have the following bicep file to create an Azure Function App with a staging slot:
module functionAppTemplate 'functionApp.bicep' = {
name: 'functionAppTemplate'
params: {
name: '${functionAppName}'
kind: functionAppKind
location: location
servicePlanName: servicePlanName
secretSettings: union(appSettings, productionSettings)
}
dependsOn: [
servicePlanTemplate
]
}
module functionAppSlotTemplate 'functionAppSlot.bicep' = {
name: 'functionAppSlotTemplate'
params: {
name: '${functionAppName}/staging'
kind: functionAppKind
location: location
servicePlanName: servicePlanName
secretSettings: union(appSettings, stagingSettings)
}
dependsOn: [
functionAppTemplate
]
}
functionApp.bicep
resource functionApp 'Microsoft.Web/sites#2018-02-01' = {
name: name
location: location
kind: kind
properties: {
serverFarmId: resourceId('Microsoft.Web/serverfarms', servicePlanName)
clientAffinityEnabled: false
httpsOnly: true
siteConfig: {
use32BitWorkerProcess : false
appSettings: secretSettings
}
}
identity: {
type: 'SystemAssigned'
}
}
functionAppSlot.bicep
resource functionAppSlot 'Microsoft.Web/sites/slots#2018-11-01' = {
name: name
kind: kind
location: location
properties: {
clientAffinityEnabled: true
enabled: true
httpsOnly: true
serverFarmId: resourceId('Microsoft.Web/serverfarms', servicePlanName)
siteConfig: {
use32BitWorkerProcess : false
appSettings: secretSettings
}
}
identity: {
type: 'SystemAssigned'
}
}
Is there a way to run functionApp.bicep and create Function App resource ONLY IF that resource doesn't exist?
Related
Here is my bicep template to deploy App service. Need help to add a slot with name: 'staging' (settings to be cloned from parent)
resource appServicePlan 'Microsoft.Web/serverfarms#2020-06-01' = {
name: appServicePlanName
location: location
properties: {
reserved: true
}
sku: {
name: sku
}
kind: 'linux'
}
resource appService 'Microsoft.Web/sites#2020-06-01' = {
name: webAppName
location: location
properties: {
serverFarmId: appServicePlan.id
siteConfig: {
linuxFxVersion: linuxFxVersion
}
}
}
You are looking for the Microsoft.Web sites/slots resource. Here a minimal example:
resource stagingSlot 'Microsoft.Web/sites/slots#2021-02-01' = {
name: 'staging'
parent: yourparent
location: location
kind: 'app'
properties: {
serverFarmId: appService.id
}
}
My script deploys a cloud run service, but after several hours of search i can't find the option to make the service public available.
const auth = new google.auth.GoogleAuth({
keyFile: 'path/to/keyfile.json',
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
});
const authClient = await auth.getClient();
const run = google.run({
version: 'v1',
auth: authClient,
rootUrl: 'https://europe-west6-run.googleapis.com/'
});
const response = await run.namespaces.services.create({
parent: 'namespaces/pace21',
requestBody: {
metadata: {
name: 'my-new-service',
namespace: 'myProject',
annotations: {
'run.googleapis.com/ingress': 'all',
},
},
kind: 'Service',
apiVersion: 'serving.knative.dev/v1',
spec: {
template: {
spec: {
containers: [
{
image: 'europe-west6-docker.pkg.dev/path/to/image',
}
]
}
},
traffic: [{ percent: 100, latestRevision: true }]
}
}
}, {})
I can see an option in the package but I don't know how to apply it.
Thanks #JohnHanley.
The second request to change the policy of the new service is the answer I was searching for. For completion the node script:
const policy_response = await run.projects.locations.services.setIamPolicy({
resource: `projects/${project_id}/locations/europe-west6/services/${service_name}`,
requestBody: {
policy: {
bindings: [
{
role: 'roles/run.invoker',
members: [
'allUsers',
],
},
],
},
},
});
I have this script to loop over an array of storage account and create them with some default configurations.
param storageAccounts array = [
'storage2312'
'storage2we1'
]
resource storage_Accounts 'Microsoft.Storage/storageAccounts#2021-04-01' = [ for storageName in storageAccounts :{
name: storageName
location: 'westeurope'
sku: {
name: 'Standard_RAGRS'
}
kind: 'StorageV2'
properties: {
allowCrossTenantReplication: true
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
allowSharedKeyAccess: true
networkAcls: {
bypass: 'AzureServices'
virtualNetworkRules: []
ipRules: []
defaultAction: 'Allow'
}
supportsHttpsTrafficOnly: true
encryption: {
services: {
file: {
keyType: 'Account'
enabled: true
}
blob: {
keyType: 'Account'
enabled: true
}
}
keySource: 'Microsoft.Storage'
}
accessTier: 'Hot'
}
}]
resource storage_Accounts_name_default 'Microsoft.Storage/storageAccounts/blobServices#2021-04-01' = [ for (storageName, i) in storageAccounts :{
parent: storage_Accounts[i]
name: storageName
properties: {
changeFeed: {
enabled: false
}
restorePolicy: {
enabled: false
}
containerDeleteRetentionPolicy: {
enabled: true
days: 7
}
cors: {
corsRules: []
}
deleteRetentionPolicy: {
enabled: true
days: 30
}
isVersioningEnabled: true
}
}]
The scripts works just fine and the storage accounts get created but the script at the end throws the following error:
{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"NotFound","message":"{\r\n \"error\": {\r\n \"code\": \"HttpResourceNotFound\",\r\n \"message\": \"The request url resourcegroups/storageAccounts/providers/Microsoft.Storage/storageAccounts/storage2we1/blobServices/storage2we1?api-version=2021-04-01 is not found.\"\r\n }\r\n}"},{"code":"NotFound","message":"{\r\n \"error\": {\r\n \"code\": \"HttpResourceNotFound\",\r\n \"message\": \"The request url /resourcegroups/storageAccounts/providers/Microsoft.Storage/storageAccounts/storage2312/blobServices/storage2312?api-version=2021-04-01 is not found.\"\r\n }\r\n}"}]}}
When create a storage account manually, I have as a default container the $logs but when I run the script, and the storage account get created, under container I don't have anything, which I presume that the error is due to that.
With bicep do I have to declare the default container?
Any help and explanation would be most welcome.
thank you so much
Based on the sample provided here, please change the following line of code (in your 2nd snippet where you're configuring blob service) from:
name: storageName
to
name: 'default'
So effectively, your bicep template would be something like:
param storageAccounts array = [
'storage2'
]
resource storage_Accounts 'Microsoft.Storage/storageAccounts#2021-04-01' = [ for storageName in storageAccounts :{
name: storageName
location: 'westeurope'
sku: {
name: 'Standard_RAGRS'
tier: 'Standard'
}
kind: 'StorageV2'
properties: {
allowCrossTenantReplication: true
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
allowSharedKeyAccess: true
networkAcls: {
bypass: 'AzureServices'
virtualNetworkRules: []
ipRules: []
defaultAction: 'Allow'
}
supportsHttpsTrafficOnly: true
encryption: {
services: {
file: {
keyType: 'Account'
enabled: true
}
blob: {
keyType: 'Account'
enabled: true
}
}
keySource: 'Microsoft.Storage'
}
accessTier: 'Hot'
}
}]
resource storage_Accounts_name_default 'Microsoft.Storage/storageAccounts/blobServices#2021-04-01' = [ for (storageName, i) in storageAccounts :{
parent: storage_Accounts[i]
name: 'default'
properties: {
changeFeed: {
enabled: false
}
restorePolicy: {
enabled: false
}
containerDeleteRetentionPolicy: {
enabled: true
days: 7
}
cors: {
corsRules: []
}
deleteRetentionPolicy: {
enabled: true
days: 30
}
isVersioningEnabled: true
}
}]
Here is alternative solution with more generics
Definition of the containers to create
var containerNames = [
'web'
'blob'
'test'
]
Next we need definiton of the storage account
resource storageAccount 'Microsoft.Storage/storageAccounts#2022-09-01' = {
name: replace(storageName, '-', '')
location: location
kind:'StorageV2'
sku:{
name: skuName
}
properties: {
minimumTlsVersion:'TLS1_2'
accessTier: 'Cool'
allowBlobPublicAccess: true
networkAcls:{
bypass:'AzureServices'
defaultAction:'Allow'
virtualNetworkRules:[]
}
supportsHttpsTrafficOnly: true
}
}
then we need to define the containers using composition
resource newContainers 'Microsoft.Storage/storageAccounts/blobServices/containers#2022-09-01' = [for containerName in containerNames:{
name:'${storageAccount.name}/default/${containerName}'
dependsOn: [storageAccount]
properties:{
publicAccess:'None'
}
}]
Couple things to note:
this solution is not sanitized for invalid input
names are case sensitive for storage account
make sure you test the code
i create a json-object and want to write this down to a json-file, but the object is always empty (?)
fs.writeFileSync(__dirname + '/myNewFile.json', JSON.stringify(myObjects));
the content of the written file is now []
fs.writeFileSync(__dirname + '/myNewFile.json', JSON.stringify({bla: myObjects}));
the content of the file is now {"bla":[]}
I doublecheck myObjects and it is not empty.. it is a array with some objects in it.
why is that? what am I doing wrong?
EDIT:
this is the content of myObjects:
[ struct: { id: 'struct',
name: 'Struktur',
icon: 'fa fa-bullseye',
properties: [] },
mp: { id: 'mp',
name: 'Messpunkt',
icon: 'fa fa-circle',
properties: [] },
'356899e5-d8b0-41aa-b7cd-de2135c5a3db': { id: '356899e5-d8b0-41aa-b7cd-de2135c5a3db',
name: 'Untermessung',
icon: 'fa fa-tachometer',
properties: [] },
'8d824cfd-584f-40e9-b9fa-78d7fedcc727': { id: '8d824cfd-584f-40e9-b9fa-78d7fedcc727',
name: 'Kommune',
icon: 'fa fa-thumb-tack',
properties: [] },
'2609b2ac-77aa-42f2-af22-d49fcfc6f0f0': { id: '2609b2ac-77aa-42f2-af22-d49fcfc6f0f0',
name: 'Bereiche',
icon: 'fa fa-circle',
properties: [] },
'a4ac2e52-da95-412f-b431-499f2eff64da': { id: 'a4ac2e52-da95-412f-b431-499f2eff64da',
name: 'Gebäude',
icon: 'fa fa-industry',
properties: [ [Object], [Object] ] } ]
this recursive Mustache template can run on node.js, but if I run it on ruby, it gives very strange output. Why that happened and how can I fix it?
const mustache = require('mustache')
const componentTemplate = `
<span class="name">{{name}}</span>
{{#components.length}}
<ul>{{#components}}<li>{{>componentTemplate}}</li>{{/components}}</ul>
{{/components.length}}
`;
const view = {
name: 'System',
components: [
{ name: 'Display',
components: [
{ name: 'Monitor 1', components: [] },
{ name: 'Monitor 2', components: [] }
]
},
{ name: 'Processor',
components: [
{ name: 'CPU', components: [] },
{ name: 'Memory', components: [] },
],
},
{ name: 'Keyboard', components: [] },
{ name: 'Mouse', components: [] }
]
};
const partials = {
componentTemplate: componentTemplate
};
console.log(mustache.render(componentTemplate, view, partials));