Consider I have an Azure Function App with some app settings and some functions created via the following YAML task:
- task: AzureResourceManagerTemplateDeployment#3
displayName: 'deploy resources'
inputs:
azureResourceManagerConnection: azureResourceManagerConnection
subscriptionId:subscriptionId
resourceGroupName: rg
location:location
csmFile: template.bicep
csmParametersFile:parameters.json
deploymentMode: 'Incremental'
Let’s say I modified app settings.
If I run the above YAML task in Incremental deployment mode, does that recreate the Azure Function App with the modified app settings and functions or does it just update the app settings - Function app and existing functions stay the same?
Here is how my template.bicep looks like:
var appSettings = [
{
name: 'WEBSITE_ADD_SITENAME_BINDINGS_IN_APPHOST_CONFIG'
value: 1
}
{
name: 'WEBSITE_ENABLE_SYNC_UPDATE_SITE'
value: 1
}
{
name: 'SCM_TOUCH_WEBCONFIG_AFTER_DEPLOYMENT'
value: 0
}
{
name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
value: reference(resourceId(appInsightsResourceGroup, 'microsoft.insights/components/', appInsightsName), '2015-05-01').InstrumentationKey
}
{
name: 'AzureWebJobsStorage'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${listKeys(resourceId(storageAccountResourceGroup, 'Microsoft.Storage/storageAccounts', storageAccountName), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value}'
}
{
name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${listKeys(resourceId(storageAccountResourceGroup, 'Microsoft.Storage/storageAccounts', storageAccountName), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value}'
}
{
name: 'FUNCTIONS_WORKER_RUNTIME'
value: 'dotnet'
}
{
name: 'FUNCTIONS_EXTENSION_VERSION'
value: '~4'
}
{
name: 'WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT'
value: maximumElasticWorkerCount
}
{
name: 'appConfigurationEndpoint'
value: appConfigurationEndpoint
}
{
name: 'membershipStorageAccountName'
value: '#Microsoft.KeyVault(SecretUri=${reference(membershipStorageAccountName, '2019-09-01').secretUriWithVersion})'
}
{
name: 'membershipContainerName'
value: '#Microsoft.KeyVault(SecretUri=${reference(membershipContainerName, '2019-09-01').secretUriWithVersion})'
}
]
var stagingSettings = [
{
name: 'WEBSITE_CONTENTSHARE'
value: toLower('functionApp-staging')
}
{
name: 'AzureFunctionsJobHost__extensions__durableTask__hubName'
value: '${solutionAbbreviation}compute${environmentAbbreviationStaging}'
}
{
name: 'AzureWebJobs.StarterFunction.Disabled'
value: 1
}
]
var productionSettings = [
{
name: 'WEBSITE_CONTENTSHARE'
value: toLower('functionApp')
}
{
name: 'AzureFunctionsJobHost__extensions__durableTask__hubName'
value: '${solutionAbbreviation}compute${environmentAbbreviation}'
}
{
name: 'AzureWebJobs.StarterFunction.Disabled'
value: 0
}
]
module functionAppTemplate 'functionApp.bicep' = {
name: 'functionAppTemplater'
params: {
name: '${functionAppName}'
kind: functionAppKind
location: location
servicePlanName: servicePlanName
dataKeyVaultName: dataKeyVaultName
dataKeyVaultResourceGroup: dataKeyVaultResourceGroup
secretSettings: union(appSettings, productionSettings)
}
dependsOn: [
servicePlanTemplate
]
}
module functionAppSlotTemplate 'functionAppSlot.bicep' = {
name: 'functionAppSlotTemplate'
params: {
name: '${functionAppName}/staging'
kind: functionAppKind
location: location
servicePlanName: servicePlanName
dataKeyVaultName: dataKeyVaultName
dataKeyVaultResourceGroup: dataKeyVaultResourceGroup
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'
}
}
Your Function App will not be recreated. Only the state or values which does not match the desired state are changed.
This means, if you change a setting e.g. FUNCTIONS_EXTENSION_VERSION in the bicep file, it will be changed in the Function App settings.
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/overview
Repeatable results: Repeatedly deploy your infrastructure throughout the development lifecycle and have confidence your resources are deployed in a consistent manner. Templates are idempotent, which means you can deploy the same template many times and get the same resource types in the same state. You can develop one template that represents the desired state, rather than developing lots of separate templates to represent updates.
Related
agent { label 'jenkins-slave' }
environment {
CRED_REPO_URL = 'gitcredentials.git'
SERVICES_REPO_URL = 'gitrepo'
ENV_NAME = 'dev_dev'
REGION = 'ap-south-1'
}
parameters {
choice name: 'ENV', choices: ['dev', 'qa'], description: 'Choose an env'
choice name: 'DIRS', choices: choiceArray, description: 'Choose a dir from branch'
gitParameter branchFilter: 'origin/(.*)',
tagFilter: '*',
defaultValue: 'main',
name: 'BRANCH',
type: 'BRANCHTAG',
quickFilterEnabled: 'true',
description: 'branch to execute',
useRepository: 'gitrepo'
}
}
facing some issue.so need to assist for this while select the branch in jenkins it has to shown that repo directories as a drop down.
The following snippet (Node/Typescript) utilizes Google's CloudBuild API (v1) to build a container and push to Google's Container Registry (GCR). If it is possible, what's the right way to have CloudBuild push the image to AWS ECR instead of GCR?
import { cloudbuild_v1 } from "googleapis";
[...]
const manifestLocation = `gs://${manifestFile.bucket}/${manifestFile.fullpath}`;
const buildDestination = `gcr.io/${GOOGLE_PROJECT_ID}/xxx:yyy`;
const result = await builds.create({
projectId: GOOGLE_PROJECT_ID,
requestBody: {
steps: [
{
name: 'gcr.io/cloud-builders/gcs-fetcher',
args: [
'--type=Manifest',
`--location=${manifestLocation}`
]
},
{
name: 'docker',
args: ['build', '-t', buildDestination, '.'],
}
],
images: [buildDestination]
}
})```
Yes you can by setting a custom step where you do that.
for this you can have a step with the docker image that makes the build and pushes it to AWS ECR.
steps:
- name: 'gcr.io/cloud-builders/docker'
args: [ 'build', '-t', '<AWS_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/<IMAGE_NAME>', '.' ]
Here is a guide on how to use cludbuild which can be useful to you.
BAsically on your usecase you can just change the value of destination to the AWS ECR URL like this:
import { cloudbuild_v1 } from "googleapis";
[...]
const manifestLocation = `gs://${manifestFile.bucket}/${manifestFile.fullpath}`;
const buildDestination = `<AWS_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/<IMAGE_NAME>`;
const result = await builds.create({
projectId: GOOGLE_PROJECT_ID,
requestBody: {
steps: [
{
name: 'gcr.io/cloud-builders/gcs-fetcher',
args: [
'--type=Manifest',
`--location=${manifestLocation}`
]
},
{
name: 'docker',
args: ['build', '-t', buildDestination, '.'],
}
],
images: [buildDestination]
}
})```
So I'm getting a routing problem whenever I use nuxt ssr with serverless. When I use either deploy to AWS lambda or use serverless-offline it generates the url prefixed with /{stage}, but nuxt can't seem to handle this and either throws 403, 404 or 500 errors because the routes to static files aren't prefixed with /{stage}.
I have tried adding {stage} to the public path on build, the results in a 404 because now the static file path needs to prefixed with another /{stage}. If I go directly to {stage}/{stage}/_nuxt/{file} it works.
build: {
publicPath: '/{stage}/_nuxt'
}
So looking around I found that I can update the router base to the below
router: {
base: '/{stage}'
}
but now the file only loads if its {stage}/{stage}/{stage}/_nuxt/{file} and removing the publicPath code above doesn't make it work either.
And this is for the static files, when it comes to the actual routes the homepage set at '/' either works but any other pages don't because the nuxt-links to them aren't prefixed with /{stage} or if I add the prefix to the base I get a Cannot GET / error when I visit /{stage}.
I have tried many different ways of doing this such as using express however I have had no luck and any tutorials that I found online are at least 2 years old and the github repos have the same problem. The closest thing I have found on stackoverflow that is somewhat similar to what I have is here but this is for a static site.
Anybody have any ideas? Below is the code for the serverless.yaml, handler.js, nuxt.js, nuxt.config.js.
Github Repo
serverless.yaml
service: nuxt-ssr-lambda
provider:
name: aws
runtime: nodejs12.x
stage: ${env:STAGE}
region: eu-west-1
lambdaHashingVersion: 20201221
environment:
NODE_ENV: ${env:STAGE}
apiGateway:
shouldStartNameWithService: true
functions:
nuxt:
handler: handler.nuxt
events:
- http: ANY /
- http: ANY /{proxy+}
plugins:
- serverless-apigw-binary
- serverless-dotenv-plugin
- serverless-offline
custom:
apigwBinary:
types:
- '*/*'
handler.js
const sls = require('serverless-http')
const binaryMimeTypes = require('./binaryMimeTypes')
const nuxt = require('./nuxt')
module.exports.nuxt = sls(nuxt, {
binary: binaryMimeTypes
})
nuxt.js
const { Nuxt } = require('nuxt')
const config = require('./nuxt.config.js')
const nuxt = new Nuxt({ ...config, dev: false })
module.exports = (req, res) =>
nuxt.ready().then(() => nuxt.server.app(req, res))
nuxt.config.js
module.exports = {
telemetry: false,
head: {
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
css: [
],
plugins: [
],
components: true,
buildModules: [
'#nuxtjs/tailwindcss',
],
modules: [
],
router: {
base: '/prod'
},
build: {
}
}
Are you passing it as
<p>Path: {{ $route.path }}</p>
<NuxtLink to="/">Back to Mountains</NuxtLink>
if Yes then it should work else try going with redirect('/{stage}/_nuxt')
for an if statement put this inside else , I think it should work.
I have Cypress 5.0 and Edge v84 installed on my machine. When I run
> npx cypress open
Then I set the debugger mode
> set DEBUG=cypress:launcher
Cypress is trying edge in the following location
cypress:launcher looking at possible paths... { browser: { name: 'edge', family: 'chromium', channel: 'stable', displayName: 'Edge', versionRegex: /Microsoft Edge (\S+)/m, binary: 'edge' }, exePaths: [ 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe' ] } +0ms
cypress:launcher found C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe ? false +1ms
cypress:launcher looking at possible paths... { browser: { name: 'edge', family: 'chromium', channel: 'canary', displayName: 'Edge Canary', versionRegex: /Microsoft Edge Canary (\S+)/m, binary: 'edge-canary' }, exePaths: [ 'C:\\Users\\muthu\\AppData\\Local\\Microsoft\\Edge SxS\\Application\\msedge.exe' ] } +0ms
cypress:launcher found C:\Users\muthu\AppData\Local\Microsoft\Edge SxS\Application\msedge.exe ? false +1ms
cypress:launcher looking at possible paths... { browser: { name: 'edge', family: 'chromium', channel: 'beta', displayName: 'Edge Beta', versionRegex: /Microsoft Edge Beta (\S+)/m, binary: 'edge-beta' }, exePaths: [ 'C:\\Program Files (x86)\\Microsoft\\Edge Beta\\Application\\msedge.exe' ] } +0ms
cypress:launcher found C:\Program Files (x86)\Microsoft\Edge Beta\Application\msedge.exe ? false +1ms
cypress:launcher looking at possible paths... { browser: { name: 'edge', family: 'chromium', channel: 'dev', displayName: 'Edge Dev', versionRegex: /Microsoft Edge Dev (\S+)/m, binary: 'edge-dev' }, exePaths: [ 'C:\\Program Files (x86)\\Microsoft\\Edge Dev\\Application\\msedge.exe' ] } +0ms
cypress:launcher found C:\Program Files (x86)\Microsoft\Edge Dev\Application\msedge.exe ? false +1ms
But Edge is installed in different location - C:\Windows\SystemApps\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\MicrosoftEdge.exe
How can I get Cypress identify Edge?
If you install in another location you can add it manually in the following path
cypress/plugins/index.js
You need to put the following code
const execa = require('execa')
const findBrowser = () => {
const browserPath = {Browser Path Location}
return execa(browserPath, ['--version']).then((result) => {
const [, version] = /Edge Browser (\d+\.\d+\.\d+\.\d+)/.exec(result.stdout)
const majorVersion = parseInt(version.split('.')[0])
return {
name: 'Edge',
channel: 'stable',
family: 'chromium',
displayName: 'Edge',
version,
path: browserPath,
majorVersion,
}
})
}
module.exports = (on, config) => {
return findBrowser().then((browser) => {
return {
browsers: config.browsers.concat(browser),
}
})
}
Reference: https://docs.cypress.io/guides/guides/launching-browsers#Customize-available-browsers
When I add html content to CKEditor (source-code mode) and then save the html content, some tags are removed - for example <strong> or <h4>.
I am using the default YAML Konfiguration and add my own one:
# EXT:my_ext/Configuration/RTE/Default.yaml
imports:
# Import default RTE config (for example)
- { resource: "EXT:rte_ckeditor/Configuration/RTE/Processing.yaml" }
- { resource: "EXT:rte_ckeditor/Configuration/RTE/Editor/Base.yaml" }
- { resource: "EXT:rte_ckeditor/Configuration/RTE/Full.yaml" }
# Import the image plugin configuration
- { resource: "EXT:rte_ckeditor_image/Configuration/RTE/Plugin.yaml" }
editor:
config:
# RTE default config removes image plugin - restore it:
removePlugins: null
removeButtons:
- Anchor
extraAllowedContent: 'a[onclick]'
toolbarGroups:
- { name: basicstyles, groups: [ basicstyles, align, cleanup ] }
- { name: styles }
stylesSet:
- { name: "Rote Schrift", element: "span", attributes: { class: "highlighted red"} }
- { name: "Button", element: "a", attributes: { class: "btn"} }
- { name: "Checkliste", element: "ul", attributes: { class: "check-list"} }
toolbarGroups:
- { name: links, groups: ['MenuLink', 'Unlink', 'Anchor'] }
externalPlugins:
typo3image: { allowedExtensions: "jpg,jpeg,png,gif,svg" }
typo3link: { resource: "EXT:rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js", route: "rteckeditor_wizard_browse_links" }
processing:
HTMLparser_db:
denyTags: null
Furthermore I have the following TS page config (not sure if this is used by TYPO3 - it's a setup of the old RTE editor):
RTE.default.enableWordClean.HTMLparser {
allowTags = a,b,blockquote,br,div,em,h2,h3,h4,h5,h6,hr,i,img,li,ol,p,span,strike,strong, ...
I finally found the solution, by comparing my Custom.yaml with typo3\sysext\rte_ckeditor\Configuration\RTE\Full.yaml
To allow more tags I had to add the new tags in the following sections of my Yaml file:
editor:
config:
allowTags:
- link
- strong
- h4
processing:
allowTags:
- link
- strong
- h4