Cloudformation error: Value of property NetworkInterfaces must be a list of objects - aws-cloudformation

I get the error Value of property NetworkInterfaces must be a list of objects when referring to a NetworkInterface in a CloudFormation template.
Here is the relevant section:
MyAppNetworkInterface:
Type: AWS::EC2::NetworkInterface
Properties:
SubnetId: !Ref SubnetPrivate
MyApp:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.medium
NetworkInterfaces:
- !Ref MyAppNetworkInterface

You can actually refer the Network Interface directly from the EC2 Host. But the syntax is slightly different:
MyAppNetworkInterface:
Type: AWS::EC2::NetworkInterface
Properties:
SubnetId: !Ref SubnetPrivate
MyApp:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.medium
NetworkInterfaces:
- NetworkInterfaceId: !Ref MyAppNetworkInterface
DeviceIndex: 0
(see: http://docs.amazonaws.cn/en_us/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-network-interface.html#cfn-awsec2networkinterface-templateexamples)

You can't do it that way. Instead , create the two resources independently, then connect with a network interface attachment resource.
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-network-interface-attachment.html

Related

How to correctly add the EnviromentFIle property to an ECS Container Definition in CloudFormation

I am trying to define an ECs cluster deployment using CLoudFormation. So far I have been successful with defining and executing the template.
I decided to externalize the environment variables for the container by using the EnvironmentFile property in the AWS::ECS::TaskDefinition resource.
I think I'm using the correct syntax according to the documentation:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-containerdefinitions.html
However running the template in CF generates an error, telling me that the keys I'm using for the EnviromentFile definition are not permitted.
The most strange thing is that the stack update since to complete successfully and I can see the property when I look at the task definition in the console. Is this an error I should ignore or Is there a more correct way to define these property
CloudFormation snippet:
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Ref 'ServiceName'
Cpu: !Ref 'ContainerCpu'
Memory: !Ref 'ContainerMemory'
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: !Ref 'ECSTaskExecutionRole'
TaskRoleArn:
Fn::If:
- 'HasCustomRole'
- !Ref 'Role'
- !Ref "AWS::NoValue"
ContainerDefinitions:
- Name: !Ref 'ServiceName'
Cpu: !Ref 'ContainerCpu'
Memory: !Ref 'ContainerMemory'
Image: !Ref 'ImageUrl'
EnvironmentFiles:
- value: !Ref EnvFile
type: s3
PortMappings:
- ContainerPort: !Ref 'ContainerPort'
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref ApplicationLogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: !Sub ${AWS::StackName}-ecs-service
Reported error:
Resource template validation failed for resource TaskDefinition as the template has invalid properties.
Please refer to the resource documentation to fix the template.
Properties validation failed for resource TaskDefinition with message:
#/ContainerDefinitions/0/EnvironmentFiles/0: extraneous key [type] is not permitted
#/ContainerDefinitions/0/EnvironmentFiles/0: extraneous key [value] is not permitted
Ok, I'm answering this to close it. After trying several things I realize that the value and type property were in lover case and CloudFomation enforces that the properties need to start with Uppercase. making this change removed the error
EnvironmentFiles:
- Value: !Ref EnvFile
Type: s3

is it possible to reuse existing route table in cloudformation template

I am writing one cft to connect dynamodb uisng vpcEndpoint.
DynamoDBEndpoint:
Type: "AWS::EC2::VPCEndpoint"
Properties:
RouteTableIds:
- !Ref PublicRouteTable
- !Ref Private0RouteTable
- !Ref Private1RouteTable
- !Ref Private2RouteTable
ServiceName:
!Sub "com.amazonaws.${AWS::Region}.dynamodb"
VpcId: !Ref VPC
Parameters:
vpcId:
Description: Choose the existing one
Type: AWS::EC2::VPC::Id
I am getting existing vpcId by using parameter ,is there any way I can ruse my existing routetable ,Please suggest me on this how could I define this ref PublicRouteTable and ref PrivateRouteTable .
Your parameter vpcId works because it uses AWS::EC2::VPC::Id type which belongs to Supported AWS-specific parameter types in CloudFormation.
Sadly, CloudFormation does not support similar type for route tables. You have to type out route tables IDs manually in console when you specify parameters.

What is the format to specify an external EDGE Gateway ApiId in CloudFormation templates?

I'm trying to create or update a stack with the following CloudFormation Template:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
ApiGatewayId:
Type: String
ApiLayerArn:
Type: String
JarLocation:
Type: String
Resources:
Function:
Type: 'AWS::Lambda::Function'
Properties:
Handler: net.bitsandpaper.api.kiosk.PlatformChecker
Runtime: java11
Code:
S3Bucket: bnp-build-artifacts
S3Key: !Ref JarLocation
Description: ''
MemorySize: 128
Timeout: 5
Role: arn:aws:iam::479832603967:role/bnp-api-lambda-execution-role
Layers:
- !Ref ApiLayerArn
ApiIntegration:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref ApiGatewayId
IntegrationType: AWS_PROXY
IntegrationUri: !Join
- ''
- - 'arn:'
- !Ref 'AWS::Partition'
- ':apigateway:'
- !Ref 'AWS::Region'
- ':lambda:path/2015-03-31/functions/'
- !Ref Function
- /invocations
TimeoutInMillis: 6000
ApiRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref ApiGatewayId
RouteKey: 'GET /kiosk/platform-check'
Target: !Join
- /
- - integrations
- !Ref ApiIntegration
The parameters are correctly passed by an external file, they look good in the Web Console, notably parameter ApiGatewayId has value 8548rqrsm5. Yet during deployment I have a CREATE_FAILED for ApiIntegration, with the message:
Invalid API identifier specified 479832603967:8548rqrsm5 (Service:
AmazonApiGatewayV2; Status Code: 404; Error Code: NotFoundException;
Request ID: 84918a83-cf9d-48d2-acf7-18d9d2e4d330; Proxy: null)
The API is an EDGE Rest API, in the same region than the CloudFormation stack. The ID is retrieved by the CLI with aws apigateway get-rest-apis.
Am I missing something in the ApiId format? The litterature is very scarce when not referencing an API in the same stack...
AWS::ApiGatewayV2 is only for WEBSOCKTES and HTTP types. From docs:
The API protocol. Valid values are WEBSOCKET or HTTP.
But since you are writing about Edge-optimized (not supported by HTTP api) it seems to that you are using REST API, rather then HTTP API. So you should be using AWS::ApiGateway resources, not AWS::ApiGatewayV2.
It seem's like the AWS::ApiGatewayV2::Route is created before the AWS::ApiGatewayV2::Integration. So When it trying to refer ApiIntegration it is not yet created.
So you should try to use DependsOn attribute.
With the DependsOn attribute you can specify that the creation of a
specific resource follows another. When you add a DependsOn attribute
to a resource, that resource is created only after the creation of the
resource specified in the DependsOn attribute.
Try this below CloudFormation code:
ApiRoute:
Type: AWS::ApiGatewayV2::Route
DependsOn: ApiIntegration
Properties:
ApiId: !Ref ApiGatewayId
RouteKey: 'GET /kiosk/platform-check'
Target: !Join
- /
- - integrations
- !Ref ApiIntegration
I hope this will help you out to resolve your problem.
Link: DependsOn Attribute UserGuide

Introduce a condition on a custom resource in CloudFormation

Another Engineer introduced a deploy date parameter into our AMIFInder Custom Resource in the prod stack which means we can no longer update the dev stack without attempting to recreate the EC2 instance.
Is it possible to introduce a condition purely based on the DeployDate parameter so I can still use one template for both stacks?
FindAmiResource:
Type: 'Custom::FindAmiFunction'
Properties:
ServiceToken:
Fn::ImportValue:
!Sub
- cfn:find-ami:${AWSAccount}:arn
- {AWSAccount: !FindInMap [AccountIDMap, Accounts, !Ref "AWS::AccountId"]}
AmiName: 'Corp_w2016_Std-*'
AmiOwner: '9999999999999'
DeployDate: !Ref AMIDeployDate
Assuming you have some information to key off (like a known AccountId or a parameter in the stack) you can create a condition that defines the stack as dev. Then you can use the 'Fn::If' function, like this:
FindAmiResource:
Type: 'Custom::FindAmiFunction'
Properties:
ServiceToken:
Fn::ImportValue:
!Sub
- cfn:find-ami:${AWSAccount}:arn
- {AWSAccount: !FindInMap [AccountIDMap, Accounts, !Ref "AWS::AccountId"]}
AmiName: 'Corp_w2016_Std-*'
AmiOwner: '9999999999999'
DeployDate:
Fn::If:
- DevCondition
- !Ref AWS::NoValue
- !Ref AMIDeployDate

Cloudformation build stuck at "create in progress" - trying to add it to use specific SG

So the last item I added to this template was the attempt to have it use a particular SecurityGroup. I did not want it to create a new one. When I do the validate check that comes back ok but apparently my code is still not correct. Other that the template was working ok.
I have tried all I can think of. there is no error when i finally times out other than "internal error" so I am at a loss here.
Parameters:
VPC:
Description: Testing using this VPC
Type: String
Default: vpc-02765
SecGroup:
Description: Name of security group
Type: AWS::EC2::SecurityGroup
KeyName:
Description: Name of an existing EC2 key pair for SSH access to the EC2 instance.
Type: AWS::EC2::KeyPair::KeyName
InstanceType:
Description: EC2 instance type.
Type: String
Default: t2.micro
...
...
...
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref 'InstanceType'
SubnetId: subnet-08b
KeyName: !Ref 'KeyName'
SecurityGroupIds:
- !Ref SecGroup
ImageId: !FindInMap
- AWSRegionArch2AMI
- !Ref 'AWS::Region'
- HVM64
'''
all I am trying to do is use the items I listed in the template. the vpc,securitygroup. The last time this worked was when I had the code in the template that builds a new SG. I than changed my mind and want to use an existing SG. so somewhere I messed up
This works in my templates:
Parameters:
SecGroup:
Type: AWS::EC2::SecurityGroup::Id
...
Resources:
MyInstance:
Properties:
SecurityGroupIds:
- !Ref SecGroup