aws cloudformation -resource property error - aws-cloudformation

I have defined my parameters like this:
{
"PrivateSubnets":{
"Description":"db subnetlist",
"Type": "List<AWS::EC2::Subnet::Id>"
},
"VPCLIST": {
"Description": "VPC list",
"Type": "List<AWS::EC2::VPC::Id>"
}
}
and referring the above parameters in "resources" section like below:
"InstanceSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : {"Ref": "VPCLIST"} ,
"GroupDescription" : "Enable 3306/80/SSH access via port 22"
}
and while executing this I am getting the below error.
AWS::EC2::SecurityGroup InstanceSecurityGroup "Value of property VpcId must be of type String"
Note: I have only default VPC available which is not taken as string? any solutions to this issue...

The correct way is make this change:
{
"PrivateSubnets": {
"Description":"db subnetlist",
"Type": "AWS::EC2::Subnet::Id"
},
"VPCLIST": {
"Description": "VPC list",
"Type": "AWS::EC2::VPC::Id"
}
}

The Security Groups requires the VpcId to be a string, the property is an array list, So you need to change the property to Type: String, or use the
Fn::Select function.
{ "Fn::Select" : [ 0, VPCLIST ] }
List – An array of VPC IDs
{
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupName" : String,
"GroupDescription" : String,
"SecurityGroupEgress" : [ Security Group Rule, ... ],
"SecurityGroupIngress" : [ Security Group Rule, ... ],
"Tags" : [ Resource Tag, ... ],
"VpcId" : String
}
}
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html

Related

Terraform ARM-Template fails because of not unique ID

I use the following Terraform ARM template to deploy to Azure Stack:
...
resource "azurestack_template_deployment" "nsg-rule1" {
count = "${var.nsgr_map["nsg_sourceportranges"] == "" && var.nsgr_map["nsg_destinationportranges"] == "" && var.nsgr_map["nsg_sourceaddressprefixes"] == "" && var.nsgr_map["nsg_destinationaddressprefixes"] == "" ? 1 : 0}"
name = "${var.nsgr_map["nsg_rulename"]}"
resource_group_name = "${var.nsgr_map["rsg_name"]}"
template_body = <<DEPLOY
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"networkSecurityGroupName": {
"type": "String"
},
"networkSecurityGroupRuleName": {
"type" : "String"
},
"protocol" : {
"type" : "String"
},
"sourcePortRange": {
"type" : "String"
},
"destinationPortRange": {
"type" : "String"
},
"sourceAddressPrefix" : {
"type" : "String"
},
"destinationAddressPrefix" : {
"type" : "String"
},
"access" : {
"type" : "String"
},
"priority" : {
"type" : "String"
},
"direction" : {
"type" : "String"
},
"sourcePortRanges" : {
"type" : "String"
},
"destinationPortRanges" : {
"type" : "String"
},
"sourceAddressPrefixes" : {
"type" : "String"
},
"destinationAddressPrefixes" : {
"type" : "String"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Network/networkSecurityGroups/securityRules",
"apiVersion": "2017-10-01",
"name": "[concat(parameters('networkSecurityGroupName'),'/',parameters('networkSecurityGroupRuleName'))]",
"properties": {
"protocol": "[parameters('protocol')]",
"sourcePortRange": "[parameters('sourcePortRange')]",
"destinationPortRange": "[parameters('destinationPortRange')]",
"sourceAddressPrefix": "[parameters('sourceAddressPrefix')]",
"destinationAddressPrefix": "[parameters('destinationAddressPrefix')]",
"access": "[parameters('access')]",
"priority": "[parameters('priority')]",
"direction": "[parameters('direction')]",
"sourcePortRanges": "[parameters('sourcePortRanges')]",
"destinationPortRanges": "[parameters('destinationPortRanges')]",
"sourceAddressPrefixes": "[parameters('sourceAddressPrefixes')]",
"destinationAddressPrefixes": "[parameters('destinationAddressPrefixes')]"
}
}
]
}
DEPLOY
# these key-value pairs are passed into the ARM Template's `parameters` block
parameters = {
networkSecurityGroupName = "${var.nsgr_map["nsg_name"]}"
networkSecurityGroupRuleName = "${var.nsgr_map["nsg_rulename"]}"
protocol = "${var.nsgr_map["nsg_protocol"]}"
sourcePortRange = "${var.nsgr_map["nsg_source_portrange"]}"
destinationPortRange = "${var.nsgr_map["nsg_destination_portrange"]}"
sourceAddressPrefix ="${var.nsgr_map["nsg_sourceaddressprefix"]}"
destinationAddressPrefix = "${var.nsgr_map["nsg_destinationaddressprefix"]}"
access = "${var.nsgr_map["nsg_access"]}"
priority = "${var.nsgr_map["nsg_priority"]}"
direction = "${var.nsgr_map["nsg_direction"]}"
sourcePortRanges = ""
destinationPortRanges = ""
sourceAddressPrefixes = ""
destinationAddressPrefixes = ""
}
deployment_mode = "Incremental"
}
...
In fact I want to add to an existing Network Security Group (NSG) on Azure Stack, some NSG-rules.
The problem is that if I deploy different rules with the same name under the same resource group the deployment fails because the NSG is not part of the ID, which identifies the resource to create.
In other words I have two rules with the same name - say 'NSG_Rule_Open_VPN' under the resource group 'Virtual_Network_1' but for two different network security groups 'nsg_1' and 'nsg_2'.
Then the deployment fails with an error, because Terraform deploys the same resource twice (but the targeted NSG's are not the same)
If I look to the activity protocol on Azure Stack it becomes clear that Terraform doesn't use the name of the targeted NSG in the ID to create the resource:
"resourceId": "/subscriptions/yyyxxx/resourcegroups/RSG_99_VirtualNetwork_01/providers/Microsoft.Resources/deployments/NSR_out_TCP_allow_VMtoINTERNET-HTTPS",
It uses only the resource group name 'RSG_99_VirtualNetwork_01' and the rule name 'NSR_out_TCP_allow_VMtoINTERNET-HTTPS' but not the NSG name.
Is there a way to avoid this. so that Terraform creates a resourceID which also has a dependency to the NSG name?
this happens because this is the deployment name, not the NSG rule name. so you need to update this bit to include nsg-name or some counter or something random:
resource "azurestack_template_deployment" "nsg-rule1" {
count = not_important_removed
name = "${var.nsgr_map["nsg_rulename"]}" # this bit needs to be updated
resource_group_name = "${var.nsgr_map["rsg_name"]}"

Launch an ec2 instance with cloudformation

I am trying to launch an ec2 instance using cloudformation.I created this json template but I get error Template format error: At least one Resources member must be defined.
{
"Type" : "AWS::EC2::Instance",
"Properties" : {
"ImageId" : "ami-08ddb3f251a88cf33",
"InstanceType" : "t2.micro ",
"KeyName" : "Stagingkey",
"LaunchTemplate" : {
"LaunchTemplateId" : "jen1",
"LaunchTemplateName" : "Launchinstance",
"Version":"V1"
},
"SecurityGroupIds" : [ "sg-055f49a32efd4238b" ],
"SecurityGroups" : [ "jenkins_group" ],
}
}
What am I doing wrong?
Is there any other template for ap-south-1 region which I could use? Any help would be appreciated.
The error says it all: At least one Resources member must be defined.
The major sections of a template are:
Parameters
Mappings
Resources
Outputs
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "My Stack",
"Resources": {
"MyInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-08ddb3f251a88cf33",
"InstanceType": "t2.micro ",
"KeyName": "Stagingkey",
"LaunchTemplate": {
"LaunchTemplateId": "jen1",
"LaunchTemplateName": "Launchinstance",
"Version": "V1"
},
"SecurityGroupIds": [
"sg-055f49a32efd4238b"
],
"SecurityGroups": [
"jenkins_group"
]
}
}
}
}
You'll need to test it. For example, it is unlikely that you will define both SecurityGroupIds and SecurityGroups.
All the properties you have entered are properties of an EC2 resource, which you need to declare. You have no resources block/a logical name for you resource, like so:
"Resources": {
"MyTomcatName": {
"Type": "AWS::EC2::Instance",
"Properties": {
[...]

Autodesk Design Automation API DWG to PDF using Dropbox

Hello I am struggling with finding a working example on how to convert a DWG file to a PDF file. I am using Autodesk Design Automation API and Dropbox. I try to use following command to place a WorkItem
{
"Arguments":{
"InputArguments":[
{
"Resource": "https://content.dropboxapi.com/2/files/download",
"Name": "HostDwg",
"Headers":[
{
"Name":"Authorization",
"Value":"Bearer xxxxxxxxxxxxxxxxxxxxxxxx"
},{
"Name":"Dropbox-API-Arg",
"Value" : {"path":"/original.dwg"}
}
]
}
],
"OutputArguments":[
{
"Name": "Result",
"HttpVerb": "PUT",
"Resource": "https://content.dropboxapi.com/2/files/upload",
"StorageProvider": "Generic",
"Headers":[
{
"Name":"Authorization",
"Value":"Bearer xxxxxxxxxxxxxx"
},{
"Name":"Dropbox-API-Arg",
"Value": {"path":"/test.pdf"}
}
]
}
]
}, "ActivityId": "PlotToPDF","Id": ""}
Unfortunately I get following Error message
An unexpected 'StartObject' node was found for property named 'Value' when reading from the JSON reader. A 'PrimitiveValue' node was expected.
I think it has to do with the second Header I have defined, to specify the file to be downloaded or uploaded. It is unclear to me how to set this value correct.
If Iam using dropbox api without Design Automation API this is working. I can define a Header named Dropbox-API-Arg and define to download/upload path.
Any help would be appreciated. Thankyou
We have improved Design Automation so that now using Dropbox-API-Arg header works both for upload and download. The following will convert a DWG to PDF in your dropbox account:
{
"Arguments": {
"InputArguments": [
{
"Resource": "https://content.dropboxapi.com/2/files/download",
"Name": "HostDwg",
"Headers" : [
{
"Name" : "Authorization",
"Value" : "Bearer ..."
},
{
"Name" : "Dropbox-API-Arg",
"Value" : "{\"path\":\"/test/test.dwg\"}"
}
]
}
],
"OutputArguments": [
{
"Name": "Result",
"HttpVerb": "POST",
"Resource": "https://content.dropboxapi.com/2/files/upload",
"Headers" : [
{
"Name" : "Authorization",
"Value" : "Bearer ..."
},
{
"Name" : "Content-Type",
"Value" : "application/octet-stream"
},
{
"Name" : "Dropbox-API-Arg",
"Value" : "{\"path\":\"/test/test.pdf\", \"mode\":\"add\"}"
}
]
}
]
},
"ActivityId": "PlotToPDF"
}
The problem is that we expect "Value" to be string and you are passing an object. Here's a working example:
{
"Arguments": {
"InputArguments": [
{
"Resource": "http://download.autodesk.com/us/samplefiles/acad/blocks_and_tables_-_imperial.dwg",
"Name": "HostDwg"
}
],
"OutputArguments": [
{
"Name": "Result",
"HttpVerb": "POST",
"Resource": "https://content.dropboxapi.com/2/files/upload",
"Headers" : [
{
"Name" : "Authorization",
"Value" : "Bearer ..."
},
{
"Name":"Content-Type",
"Value":"application/octet-stream"
},
{
"Name" : "Dropbox-API-Arg",
"Value" : "{\"path\":\"/test/test.pdf\", \"mode\":\"add\"}"
}
]
}
]
},
"ActivityId": "PlotToPDF"
}
EDITED
Either you can pass Dropbox-API-Arg header as below
"Name" : "Dropbox-API-Arg",
"Value" : "{\"path\":\"/test/test.pdf\", \"mode\":\"add\"}"
in the payload.
Or, passing arg url encoded string will also works.
Use following payload to work with Dropbox using Forge Design Automation.
You need to pass Arg parameter instead of ‘Dropbox-API-Arg’ header.
arg={"path":"/result.pdf"} encoded in URL as "arg=%7B%22path%22%3A%22%2Fresult.pdf%22%7D"
For example:
To post result.pdf in Dropbox.
{
"Arguments": {
"InputArguments": [
{
"Resource": "http://download.autodesk.com/us/samplefiles/acad/blocks_and_tables_-_metric.dwg",
"Name": "HostDwg"
}
],
"OutputArguments": [
{
"Name": "Result",
"HttpVerb": "POST",
"Resource": "https://content.dropboxapi.com/2/files/upload?arg=%7B%22path%22%3A%22%2Fresult.pdf%22%7D",
"StorageProvider": "Generic",
"Headers": [
{
"Name":"Authorization",
"Value":"Bearer blahblahblah"
},
{"Name":"Content-Type",
"Value":"application/octet-stream"
}
]
}
]
},
"ActivityId": "PlotToPDF"
}

How to do either operation in IRItemplate in a Hydra:Operation?

My hydra vocab is similar to Markus-lanthaler Vocab.Here is one of my operation on User Class to retrieve collection of Users.
{
"#id": "payu:retrieve_users",
"#type": "hydra:Operation",
"method": "GET",
"label": "Retrieve users",
"description": "Retrieves Users",
"expects": null,
"returns": "hydra:Collection",
"IriTemplate" : {
"#type" : "IriTemplate",
"template" : "{?userIds,firstName,lastName}",
"variableRepresentation": "BasicRepresentation",
"mapping" : [
{
"#type" : "IriTemplateMapping",
"variable" : "userIds",
"property" : "hydra:property",
"required" : false
},
{
"#type" : "IriTemplateMapping",
"variable" : "firstName",
"property" : "hydra:property",
"required" : false
},
{
"#type" : "IriTemplateMapping",
"variable" : "lastName",
"property" : "hydra:property",
"required" : false
}
]
}
}
As you can see in IRItemplate
"template" : "{?userIds,firstName,lastName}"
so I want to get control over retrieve either a third person will be able to retrieve through (userIds) or (firstName,lastName).
Should I make two separate hydra Operations having IRItemplate :
In First Operation:
"template" : "{?userIds}"
In Second Operation:
"template" : "{?firstName,lastName}"
Or Is there any existing way to do this in Hydra Specification using single operation ?
Currently there's no way to specify that for a single operation. You'll need to have two operations. Also, you need to associate the operation to the IriTemplate and not the other way round:
{
"#type" : "IriTemplate",
"template" : "{?userIds,firstName,lastName}",
...
"operation": {
"#id": "payu:retrieve_users",
"#type": "hydra:Operation",
"method": "GET",
...
}
}

Retrieving the ResourceId of a scaleable target

In the AWS Resource AWS::ApplicationAutoScaling::ScalableTarget, how do I retrieve the value of ResourceId which is the unique resource identifier that associated with the scaleable target?
The format used in the ResourceId property is service/cluster_name/service_name.
You are correct that the ResourceId property should be in the form service/<cluster_name>/<service_name>.
Incidentally, (and to help future Googlers) the error message that you get when you use an incorrect ResourceId or ScalableDimension is:
Unsupported service namespace, resource type or scalable dimension
To achieve this in CloudFormation you can use a Fn::Join for the ResourceId. Here is a snippet of the Scalable target that I am using:
"ECSServiceScalableTarget": {
"Type": "AWS::ApplicationAutoScaling::ScalableTarget",
"Properties": {
"MaxCapacity": 5,
"MinCapacity": 1,
"ResourceId": { "Fn::Join" : ["/", [
"service",
{ "Ref": "ECSCluster" },
{ "Fn::GetAtt" : ["ECSService", "Name"] }
]]},
"RoleARN": { "Fn::Join" : ["", ["arn:aws:iam::", { "Ref" : "AWS::AccountId" }, ":role/ApplicationAutoscalingECSRole"]]},
"ScalableDimension": "ecs:service:DesiredCount",
"ServiceNamespace": "ecs"
}
}
I use the {"Fn::Join" : [ ":", [ "a", "b", "c" ] ]"} to get the value of the "ResourceId".