How do I skip builders and go straight to provisioners or post-processors stages when using packer? - packer

I want to skip the builders stage. How do I skip builders and go straight to provisioners or post-processors stages when using packer?

Use "communicator": "none"
{
"builders": [
{
"type": "null",
"communicator": "none"
}
],
"provisioners": [
{
"type": "shell-local",
"inline": ["exit 2"]
}
],
"error-cleanup-provisioner": {
"type": "shell-local",
"inline": ["echo 'rubber ducky'> ducky.txt"]
}
}

Related

Need to apply IAMPass Role to specific environment

I have cloudformation template. Here we have multiple environments(dev,qa,uat) and need to use same template for all environments.
In template Under "Action": ["iam:PassRole"] there are 4 resources, 3 resources are belongs to qa. When am deploying code on dev and uat Env, qa resources are applying to dev and uat environment as well but I need to create these 3 qa resources only for qa environment. I tried some conditions but isn't working. Is there any approach for this.
Please find below template code.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"CloudFormationRole": {
"Type": "AWS::IAM::Role",
"Description": "Service role in IAM for AWS CloudFormation",
"Properties": {
"RoleName": {
"Fn::Sub": "${Environment}-workflow-CloudFormationRole"
},
"Path": "/",
"Policies": [
{
"PolicyName": "WorkerCloudFormationRolePolicy",
"PolicyDocument": {
"Statement": [
{
"Action": [
"lambda:AddPermission",
"lambda:PutFunctionEventInvokeConfig",
"lambda:UpdateFunctionEventInvokeConfig"
],
"Resource": {
"Fn::Sub": "arn:aws:lambda:function:orderser-${Environment}-workflow-*"
},
"Effect": "Allow"
},
{
"Action": [
"iam:PassRole"
],
"Resource": [
{"Fn::Sub": "arn:aws:iam::role/orderser-workflow-*"},
{"Fn::Sub": "arn:aws:iam::role/orderserv-qa-workflowLambdaRole1"},
{"Fn::Sub": "arn:aws:iam::role/orderserv-qa-workflowLambdaRole2"},
{"Fn::Sub": "arn:aws:iam::role/orderserv-qa-workflowLmbdRole3"}
],
"Effect": "Allow"
}
]
}
}
]
}
}
}
}
Parameterize the pass role ARNs and have different set of parameter files for each environment
And, since you have multiple values, use CommaDelimitedList type parameter which can take multiple string values
Ref here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html

Develop a VSCode theme using variables

I'm creating a VScode theme.
My project structure is very simple:
mytheme
|_ .vscode
|_ launch.json
|_ assets
|_ ...some png files
|_ themes
|_ mytheme.json
.vscodeignore
package.json
README.md
The mytheme.json is something like this:
{
"name": "mytheme",
"type": "dark",
"colors": {
//////////////////////////////
// CONTRAST COLOR
// The contrast colors are typically only set for high contrast themes.
// If set, they add an additional border around items across the UI to increase the contrast.
//////////////////////////////
// An extra border around active elements to separate them from others for greater contrast.
"contrastActiveBorder": "#fa0000",
// "contrastActiveBorder": "#FFFFFF00",
// An extra border around elements to separate them from others for greater contrast.
//"contrastBorder": "#fa0000",
//////////////////////////////
// BASE COLORS
//////////////////////////////
// Overall border color for focused elements. This color is only used if not overridden by a component.
"focusBorder": "#9B6DFF66",
// Overall foreground color. This color is only used if not overridden by a component.
"foreground": "#D9E0E8",
// Shadow color of widgets such as Find/Replace inside the editor.
"widget.shadow": "#1F2330",
// Background color of text selections in the workbench (for input fields or text areas, does not apply to selections within the editor and the terminal).
"selection.background": "#9B6DFF99",
// Foreground color for description text providing additional information, for example for a label.
"descriptionForeground": "#808182",
// Overall foreground color for error messages (this color is only used if not overridden by a component).
"errorForeground": "#9B6DFF",
// The default color for icons in the workbench.
"icon.foreground": "#D9E0E8",
...
}
}
and my package.json:
{
"name": "mytheme",
"version": "1.0.0",
"publisher": "...",
"icon": "assets/logo_square.png",
"galleryBanner": {
"color": "#1F2330",
"theme": "dark"
},
"engines": {
"vscode": "^1.42.0"
},
"displayName": "Mytheme",
"description": "...",
"categories": [
"Themes"
],
"contributes": {
"themes": [
{
"label": "Mytheme",
"uiTheme": "vs-dark",
"path": "./themes/mytheme.json"
}
]
},
"repository": {
"type": "git",
"URL": "....git"
},
"bugs": {
"URL": "..."
},
"author": {
"name": "...",
"email": "...",
},
"license": "MIT",
"keywords": [
"vscode",
"theme",
"color-theme",
"dark"
],
"private": false
}
Very simple. It works like a charm. But there is a big problem: it's very difficult to maintain because mytheme.json is a very very long file and it's a simple .json and If I want to modify for example the accent color, I need to do a find and replace.
I would like to develop my theme in a smarter way, I would like to use variables, save my N colors in variables and use them.
json format doesn't support variables so I ask you how can I do that?
I don't know if there is a standard way to do that, I imagine developing in js and then running a script that transforms my work into a valid json but how?
For example:
const PURPLE = "#9B6DFF"
const baseColors = {
...
errorForeground: PURPLE,
...
}
return ...
I didn't find a guide to follow.
Following the suggestion of #rioV8, I created these files:
.vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "extensionHost",
"request": "launch",
"name": "Launch Extension",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"preLaunchTask": "parseToJson",
},
],
}
.vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "parseToJson",
"command": "tsc",
"type": "shell",
"presentation": {
"reveal": "silent",
"panel": "new"
},
"args": [
"--target",
"ES5",
"--outDir",
"js",
"--sourceMap",
"--watch",
"parse.ts"
],
"problemMatcher": "$tsc"
}
]
}
.vscode/parse.ts:
const PURPLE = "#9B6DFF"
const baseColors = {
errorForeground: PURPLE,
}
// create json
const mytheme = {
"name": "mytheme",
"type": "dark",
"colors": {...baseColors}
}
function createJsonTheme() {
// save to json
const file = new File(mytheme, "../themes/mytheme.json", {
type: "text/plain",
});
}
createJsonTheme()
When I run it, I get:
error TS6053: File 'parse.ts' not found. The file is in the program
because:
Root file specified for compilation
The path seems ok to me, where is The problem?
The createJsonTheme function goal is to create an object to save then in a json file inside themes folder.
Variables won't help. The theme file is a mapping of token values to color values. A theme editor tool could help you to be more productive, but I don't know any.
I solved doing like this:
launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"preLaunchTask": "npm: build"
},
{
"name": "Run Extension Without Build",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
]
}
]
}
tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "start",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"label": "npm: start",
"detail": "nodemon --watch src src/index.js"
},
{
"type": "npm",
"script": "build",
"group": "build",
"problemMatcher": [],
"label": "npm: build",
"detail": "node src/index.js"
}
]
}
package.json:
...
"scripts": {
"start": "nodemon --watch src src/index.js",
"build": "node src/index.js && mkdir -p build",
"prepublishOnly": "npm run build && vsce publish"
}
...
src/index.js:
const fs = require('fs').promises
const getTheme = require('./theme')
const ohlalaTheme = getTheme({
theme: 'dark',
name: 'Mytheme',
})
// write theme
fs.mkdir('./themes', { recursive: true })
.then(() =>
Promise.all([
fs.writeFile('./themes/mytheme.json', JSON.stringify(ohlalaTheme, null, 2)),
])
)
.catch(() => process.exit(1))
src/theme.js
const { colors } = require('./colors')
function getTheme({ theme, name }) {
const themes = (options) => options[theme]
return {
name: name,
colors: {
focusBorder: colors.green,
},
semanticHighlighting: true,
...
}
}
module.exports = getTheme
src/colors.js:
const colors = {
green: '#......',
}
module.exports = { colors }

How to run AWS ECS Task with CloudFormation overriding container environment variables

I was searching a way to run ecs task. I already have a cluster and task definition settings. I just wanted to trigger a task using CloudFormation template. I know that I can run a task by clicking on the console and it works fine. For cfn, approach needs to be define properly.
Check the attached screenshots. I wanted to run that task using CloudFormation and pass container override environment variables. As per my current templates, it is not allowing me to do same like I can do using console. Using console I just need to select the following options
1. Launch type
2. Task Definition
Family
Revision
3. VPC and security groups
4. Environment variable overrides rest of the things automatically selected
It starts working with console but with cloudformaton template how can we do that. Is it possible to do or there is no such feature?
"taskdefinition": {
"Type" : "AWS::ECS::TaskDefinition",
"DependsOn": "DatabaseMaster",
"Properties" : {
"ContainerDefinitions" : [{
"Environment" : [
{
"Name" : "TARGET_DATABASE",
"Value" : {"Ref":"DBName"}
},
{
"Name" : "TARGET_HOST",
"Value" : {"Fn::GetAtt": ["DatabaseMaster", "Endpoint.Address"]}
}
]
}],
"ExecutionRoleArn" : "arn:aws:iam::xxxxxxxxxx:role/ecsTaskExecutionRole",
"Family" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"TaskRoleArn" : "arn:aws:iam::xxxxxxxxxxxxxxx:role/xxxxxxxxxxxxxxx-XXXXXXXXX"
}
},
"EcsService": {
"Type" : "AWS::ECS::Service",
"Properties" : {
"Cluster" : "xxxxxxxxxxxxxxxxx",
"LaunchType" : "FARGATE",
"NetworkConfiguration" : {
"AwsvpcConfiguration" : {
"SecurityGroups" : ["sg-xxxxxxxxxxx"],
"Subnets" : ["subnet-xxxxxxxxxxxxxx"]
}
},
"TaskDefinition" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
There is no validity error in the code however, I am talking about the approach. I added image name container name but now it is asking for memory and cpu, it should not ask as it is already defined we just need to run a task.
Edited
I wanted to run a task after creation of my database and wanted to pass those database values to the task to run and complete a job.
Here is the working example of what you can do if you wanted to pass variable and run a task. In my case, I wanted to run a task after creation of my database but with environment variables, directly AWS does not provide any feature to do so, this is the solution which can help to trigger you ecs task.
"IAMRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"events.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Description": "Allow CloudWatch Events to trigger ECS task",
"Policies": [
{
"PolicyName": "Allow-ECS-Access",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:*",
"iam:PassRole",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
}
],
"RoleName": { "Fn::Join": [ "", ["CloudWatchTriggerECSRole-", { "Ref": "DBInstanceIdentifier" }]]}
}
},
"DummyParameter": {
"Type" : "AWS::SSM::Parameter",
"Properties" : {
"Name" : {"Fn::Sub": "${AWS::StackName}-${DatabaseMaster}-EndpointAddress"},
"Type" : "String",
"Value" : {"Fn::GetAtt": "DatabaseMaster.Endpoint.Address"}
},
"DependsOn": "TaskSchedule"
},
"TaskSchedule": {
"Type": "AWS::Events::Rule",
"Properties": {
"Description": "Trigger ECS task upon creation of DB instance",
"Name": { "Fn::Join": [ "", ["ECSTaskTrigger-", { "Ref": "DBName" }]]},
"RoleArn": {"Fn::GetAtt": "IAMRole.Arn"},
"EventPattern": {
"source": [ "aws.ssm" ],
"detail-type": ["Parameter Store Change"] ,
"resources": [{"Fn::Sub":"arn:aws:ssm:eu-west-1:XXXXXXX:parameter/${AWS::StackName}-${DatabaseMaster}-EndpointAddress"}],
"detail": {
"operation": ["Create"],
"name": [{"Fn::Sub": "${AWS::StackName}-${DatabaseMaster}-EndpointAddress"}],
"type": ["String"]
}
},
"State": "ENABLED",
"Targets": [
{
"Arn": "arn:aws:ecs:eu-west-1:xxxxxxxx:cluster/NameOf-demo",
"Id": "NameOf-demo",
"RoleArn": {"Fn::GetAtt": "IAMRole.Arn"},
"EcsParameters": {
"LaunchType": "FARGATE",
"NetworkConfiguration": {
"AwsVpcConfiguration": {
"SecurityGroups": {"Ref":"VPCSecurityGroups"},
"Subnets": {"Ref":"DBSubnetName"}
}
},
"PlatformVersion": "LATEST",
"TaskDefinitionArn": "arn:aws:ecs:eu-west-1:XXXXXXXX:task-definition/NameXXXXXXXXX:1"
},
"Input": {"Fn::Sub": [
"{\"containerOverrides\":[{\"name\":\"MyContainerName\",\"environment\":[{\"name\":\"VAR1\",\"value\":\"${TargetDatabase}\"},{\"name\":\"VAR2\",\"value\":\"${TargetHost}\"},{\"name\":\"VAR3\",\"value\":\"${TargetHostPassword}\"},{\"name\":\"VAR4\",\"value\":\"${TargetPort}\"},{\"name\":\"VAR5\",\"value\":\"${TargetUser}\"},{\"name\":\"VAR6\",\"value\":\"${TargetLocation}\"},{\"name\":\"VAR7\",\"value\":\"${TargetRegion}\"}]}]}",
{
"VAR1": {"Ref":"DBName"},
"VAR2": {"Fn::GetAtt": ["DatabaseMaster", "Endpoint.Address"]},
"VAR3": {"Ref":"DBPassword"},
"VAR4": "5432",
"VAR5": {"Ref":"DBUser"},
"VAR6": "value6",
"VAR7": "eu-west-2"
}
]}
}
]
}
}
For Fargate task, we need to specify in CPU in Task Definition. and memory or memory reservation in either task or container definition.
and environment variables should be passed to each container as ContainerDefinitions and overrided when task is run from ecs task-run from console or cli.
{
"ContainerTaskdefinition": {
"Type": "AWS::ECS::TaskDefinition",
"Properties": {
"Family": "SomeFamily",
"ExecutionRoleArn": !Ref RoleArn,
"TaskRoleArn": !Ref TaskRoleArn,
"Cpu": "256",
"Memory": "1GB",
"NetworkMode": "awsvpc",
"RequiresCompatibilities": [
"EC2",
"FARGATE"
],
"ContainerDefinitions": [
{
"Name": "container name",
"Cpu": 256,
"Essential": "true",
"Image": !Ref EcsImage,
"Memory": "1024",
"LogConfiguration": {
"LogDriver": "awslogs",
"Options": {
"awslogs-group": null,
"awslogs-region": null,
"awslogs-stream-prefix": "ecs"
}
},
"Environment": [
{
"Name": "ENV_ONE_KEY",
"Value": "Valu1"
},
{
"Name": "ENV_TWO_KEY",
"Value": "Valu2"
}
]
}
]
}
}
}
EDIT(from discussion in comments):
ECS Task Run is not a cloud-formation resource, it can only be run from console or CLI.
But if we choose to run from a cloudformation resource, it can be done using cloudformation custom resource. But once task ends, we now have a resource in cloudformation without an actual resource behind. So, custom resource needs to do:
on create: run the task.
on delete: do nothing.
on update: re-run the task
Force an update by changing an attribute or logical id, every time we need to run the task.

Specify shared/'common' values for configurations in CppProperties.json or CMakeSettings.json

When using the "Open Folder" functionality of Visual Studio, the IDE searches for project settings and configurations in a special json file. For CPP projects, this could be CppProperties.json. For CMake projects, this could be CMakeSettings.json.
This json file contains a collection of one or more "configurations," such as "Debug" or "Release". I will use a recent CMake project as an example:
"configurations": [
{
"name": "ARM-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [
"gcc-arm"
],
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"intelliSenseMode": "linux-gcc-arm",
"variables": [
{
"name": "CMAKE_TOOLCHAIN_FILE",
"value": "${workspaceRoot}/cmake/arm-none-eabi-toolchain.cmake"
}
]
},
{
"name": "ARM-Release",
"generator": "Ninja",
"configurationType": "Release",
"inheritEnvironments": [
"gcc-arm"
],
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"intelliSenseMode": "linux-gcc-arm",
"variables": [
{
"name": "CMAKE_TOOLCHAIN_FILE",
"value": "${workspaceRoot}/cmake/arm-none-eabi-toolchain.cmake"
}
]
}
As you can see, I have two configurations with nearly identical properties.
My question: is it possible to define these common/shared properties once, in such a way as to allow the configurations to inherit them and avoid repeating myself?
The easier way is to define an environment at global level (outside of any configuration), such as:
{
"environments": [
{
"namespace" : "env",
"varName": "varValue"
}
],
Then you can reuse that wherever you need to, e.g.:
"cmakeCommandArgs": "${env.varName}",
You can also have multiple environments, and reuse them, like this:
{
"environments": [
{
"environment": "env1",
"namespace": "env",
"varName": "varValueEnv1"
},
{
"environment": "env2",
"namespace": "env",
"varName": "varValueEnv2"
}
],
"configurations": [
{
"name": "x64-Release",
"inheritEnvironments": [
"msvc_x64_x64", "env2"
],
"cmakeCommandArgs": "${env.varName}",
.....
}
]
the 'x64-Release' will inherit the variables's value in the environment called "env2" (namespace 'env')

Addition of subnets to existing Vnet through ARM templates

The following is my input parameter file(parameter.json)
{
"VNetSettings":{
"value":{
"name":"VNet2",
"addressPrefixes":"10.0.0.0/16",
"subnets":[
{
"name": "sub1",
"addressPrefix": "10.0.1.0/24"
},
{
"name":"sub2",
"addressPrefix":"10.0.2.0/24"
}
]
}
}
}
The following is my arm template that should deploy the subnets.(deploy.json)
{
"contentversion":"1.0.0.0",
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"parameters":{
"VNetSettings":{"type":"object"},
"noofsubnets":
{
"type":"int"
},
"newOrExisting":
{
"type":"string",
"allowedvalues":
[
"new",
"existing"
]
}
},
"resources":
[{
"condition":"[equals(parameters('newOrExisting'),'new')]",
"type": "Microsoft.Network/virtualNetworks",
"mode":"Incremental",
"apiVersion": "2015-06-15",
"name":"[parameters('VNetSettings').name]",
"location":"[resourceGroup().location]",
"properties":
{
"addressSpace":{
"addressPrefixes":["[parameters('VNetSettings').addressPrefixes]"]
},
"copy":
[{
"name":"subnets",
"count":"[parameters('noofsubnets')]",
"input":
{
"name": "[parameters('VNetSettings').subnets[copyIndex('subnets')].name]",
"properties":
{
"addressPrefix": "[parameters('VNetSettings').subnets[copyIndex('subnets')].addressPrefix]"
}
}
}]
}
}]
}
What the template should be doing is add these two subnets(sub1 & sub2) to the Vnet in addition to the existing subnets if there is already one.But what it is doing is replacing the existing subnets with these two subnets present in the input file. Mode: Incremental should be doing this but I'm not sure whether I'm placing it in the right place. I'm deploying this template using the following powershell commmand:
New-AzureRmResourceGroupDeployment -Name testing -ResourceGroupName rgname -TemplateFile C:\Test\deploy.json -TemplateParameterFile C:\Test\parameterfile.json
This is expected behavior. you should read on 'Idempotence'. what you need to do is create a subnet resource, that way you will work around it.
{
"apiVersion": "2016-03-30",
"name": "vnetName\subnetName",
"location": "[resourceGroup().location]]",
"type": "Microsoft.Network/virtualNetworks/subnets",
"properties": {
"addressPrefix": "xx.x.x.xx"
}
}
vnetName has to be the vnet you want to create resource in.