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
}
}
Related
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?
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
As mentioned in the documentation route aliases can be put in the API service, but I want to put the aliases in the individual service settings, how can I do that?
Let's say I have a users service and API gateway,
and the users service have a role action and it will just send back the id as an example
If I send a get request to /users/role/1 I will get 1 as result
It works like this
api.service.js
"use strict";
const ApiGateway = require("moleculer-web");
module.exports = {
name: "api",
mixins: [ApiGateway],
settings: {
port: process.env.PORT || 3000,
routes: [{
path: "/api",
whitelist: [
// Access to any actions in all services under "/api" URL
"**"
],
aliases: {
"GET users/role/:uid": "users.role"
}
}],
// Serve assets from "public" folder
assets: {
folder: "public"
},
},
};
users.service.js
"use strict";
module.exports = {
name: "users",
/**
* Service settings
*/
settings: {},
/**
* Actions
*/
actions: {
role: {
cache: {
keys: ["uid"]
},
rest: "GET role/:uid",
handler(ctx) {
return ctx.params.uid
}
}
},
};
wanted somthing like this
api.service.js
"use strict";
const ApiGateway = require("moleculer-web");
module.exports = {
name: "api",
mixins: [ApiGateway],
settings: {
port: process.env.PORT || 3000,
routes: [{
path: "/api",
whitelist: [
// Access to any actions in all services under "/api" URL
"**"
]
}],
// Serve assets from "public" folder
assets: {
folder: "public"
},
},
};
users.service.js
"use strict";
module.exports = {
name: "users",
/**
* Service settings
*/
settings: {
routes: [{
path: "/",
aliases: {
"GET role/:uid": "role"
}
}],
},
/**
* Actions
*/
actions: {
role: {
cache: {
keys: ["uid"]
},
rest: "GET role/:uid",
handler(ctx) {
return ctx.params.uid
}
}
},
};
the goal is that every service is separated in its own project and the aliases for any service can be put in it and not in the API service
// api.service.js
module.exports = {
mixins: [ApiGateway],
settings: {
port: process.env.PORT || 3000,
routes: [
{
path: "/",
whitelist: [
"users.**"
],
autoAliases: true
}
]
}
};
// users.service.js
module.exports = {
name: "users",
settings: {
// Base path
rest: "users/"
},
actions: {
role: {
cache: {
keys: ["uid"]
},
rest: "GET role/:uid",
handler(ctx) {
return ctx.params.uid
}
}
}
};
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));