so I send an adaptive card with submitting action on my bot framework, that submit action have invoked action. When the TaskModuleContinueResponse is set to card the task module is working fine, but when I Used my NRGROK URL for the TaskModuleContinueResponse it will only show blank. I already add my NGROK URL in the valid domains, when I see the NGROK inspect I don't see my page being called.
Here is my manifest
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.9/MicrosoftTeams.schema.json",
"manifestVersion": "1.9",
"version": "1.0.0",
"id": "1c07cd26-a088-4db8-8928-ace382fa219f",
"packageName": "Some.microsoft.teams.companycommunicator.authors",
"developer": {
"name": "Some",
"websiteUrl": "https://somewebsite.com",
"privacyUrl": "https://somewebsite.com",
"termsOfUseUrl": "https://somewebsite.com"
},
"icons": {
"color": "color.png",
"outline": "outline.png"
},
"name": {
"short": "Announce (Authors)",
"full": "Company Announce (Authors)"
},
"description": {
"short": "Broadcast messages to multiple teams and people in one go",
"full": "Broadcasts messages to multiple teams and individuals through channel posts and chat messages"
},
"accentColor": "#64A2CC",
"configurableTabs": [
{
"configurationUrl": "https://b0837b7151f7.ngrok.io/configtab",
"canUpdateConfiguration": true,
"scopes": [
"team"
],
"context": [
"channelTab"
]
}
],
"bots": [
{
"botId": "eae687a6-936c-4fd7-ade7-1f01b388ac16",
"scopes": [
"team"
],
"commandLists": [
{
"scopes": [
"team"
],
"commands": [
{
"title": "Test",
"description": "Test bot trigger"
}
]
}
],
"supportsFiles": true,
"isNotificationOnly": false
}
],
"permissions": [
"identity",
"messageTeamMembers"
],
"validDomains": [
"b0837b7151f7.ngrok.io",
],
"webApplicationInfo": {
"id": "eae687a6-936c-4fd7-ade7-1f01b388ac16",
"resource": "api://b0837b7151f7.ngrok.io"
}
}
and here is my code for the task module I using ASP Net core
protected override async Task<TaskModuleResponse> OnTeamsTaskModuleFetchAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
{
var reply = MessageFactory.Text("OnTeamsTaskModuleFetchAsync TaskModuleRequest: " + JsonConvert.SerializeObject(taskModuleRequest));
await turnContext.SendActivityAsync(reply);
return new TaskModuleResponse
{
Task = new TaskModuleContinueResponse
{
Value = new Microsoft.Bot.Schema.Teams.TaskModuleTaskInfo()
{
//Card = CreateAdaptiveCardAttachment(),
Url = "https://b0837b7151f7.ngrok.io/details",
FallbackUrl = "https://b0837b7151f7.ngrok.io/details",
Height = 800,
Width = 1000,
Title = "Details",
},
},
};
}
And for my page is just simple hello world.
import React, { Component } from 'react'
import * as microsoftTeams from "#microsoft/teams-js";
export default class SeeDetail extends Component {
componentDidMount() {
microsoftTeams.initialize();
}
render() {
return (
<div>
<center>
<h1>Hello World</h1>
</center>
</div>
)
}
}
I don't know why like its been blocked or something because I don't see any request to my page on the NGROK Inspect. Is there something missing here
I have tried with your code it's working.
Please check in browser is your react page rendering correctly in browser when you call using https://b0837b7151f7.ngrok.io/details and try to render a page by generating a new ngrok Url.
Also check by adding your react page url in task module working sample.
If the issue still persists then try by deleting the existing app and upload your manifest again in teams App studio.
I believe for adaptive cards that you have to register any submit urls with the actionable messages dashboard here https://outlook.office.com/connectors/oam/publish
as in title, I am trying to use Google API Explorer to run vm instance. I am using instances.insert for this, but I can't get it to work. After successfuly executing the call I can not see any newly creted vm instance in https://console.cloud.google.com/compute/instances
The request I am trying to execute is copied from Equivalent REST request in Google Cloud Console Create an instance web page :
{
"name": "some-name",
"machineType": "projects/my-project-id/zones/europe-west3-c/machineTypes/f1-micro",
"displayDevice": {
"enableDisplay": false
},
"metadata": {
"items": [
{
"key": "startup-script",
"value": "#! /bin/bash\necho hello\nEOF"
}
]
},
"tags": {
"items": []
},
"disks": [
{
"type": "PERSISTENT",
"boot": true,
"mode": "READ_WRITE",
"autoDelete": true,
"deviceName": "some-name",
"initializeParams": {
"sourceImage": "projects/debian-cloud/global/images/debian-10-buster-v20200910",
"diskType": "projects/my-project-id/zones/europe-west3-c/diskTypes/pd-standard",
"diskSizeGb": "10",
"labels": {}
},
"diskEncryptionKey": {}
}
],
"canIpForward": false,
"networkInterfaces": [
{
"subnetwork": "projects/my-project-id/regions/europe-west3/subnetworks/default",
"accessConfigs": [
{
"name": "External NAT",
"type": "ONE_TO_ONE_NAT",
"networkTier": "PREMIUM"
}
],
"aliasIpRanges": []
}
],
"description": "",
"labels": {},
"scheduling": {
"preemptible": false,
"onHostMaintenance": "MIGRATE",
"automaticRestart": true,
"nodeAffinities": []
},
"deletionProtection": false,
"reservationAffinity": {
"consumeReservationType": "ANY_RESERVATION"
},
"serviceAccounts": [
{
"email": "some-number-compute#developer.gserviceaccount.com",
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
}
],
"shieldedInstanceConfig": {
"enableSecureBoot": false,
"enableVtpm": true,
"enableIntegrityMonitoring": true
},
"confidentialInstanceConfig": {
"enableConfidentialCompute": false
}
}
Here is the response with status 200
{
"id": "2981010757915612255",
"name": "operation-1602235056020-5b1396b5c5cee-e0e30499-4d06ce75",
"zone": "https://www.googleapis.com/compute/v1/projects/my-project-id/zones/europe-west3-c",
"operationType": "insert",
"targetLink": "https://www.googleapis.com/compute/v1/projects/my-project-id/zones/europe-west3-c/instances/ams2-linux-race-1",
"targetId": "1541614827291382879",
"status": "RUNNING",
"user": "email#gmail.com",
"progress": 0,
"insertTime": "2020-10-09T02:17:36.818-07:00",
"startTime": "2020-10-09T02:17:36.821-07:00",
"selfLink": "https://www.googleapis.com/compute/v1/projects/my-project-id/zones/europe-west3-c/operations/operation-1602235056020-5b1396b5c5cee-e0e30499-4d06ce75",
"kind": "compute#operation"
}
I have the same issue with C# code example from https://cloud.google.com/compute/docs/reference/rest/v1/instances/insert#examples
I can execute the same request without errors and in response I am getting this
{
"clientOperationId":null,
"creationTimestamp":null,
"description":null,
"endTime":null,
"error":null,
"httpErrorMessage":null,
"httpErrorStatusCode":null,
"id":3283200477858999168,
"insertTime":"2020-10-09T00:46:55.187-07:00",
"kind":"compute#operation",
"name":"operation-1602229614262-5b1382701b989-381126a6-cc145485",
"operationType":"insert",
"progress":0,
"region":null,
"selfLink":"https://www.googleapis.com/compute/v1/projects/my-project-id/zones/europe-west3-c/operations/operation-1602229614262-5b1382701b989-381126a6-cc145485",
"startTime":"2020-10-09T00:46:55.189-07:00",
"status":"RUNNING",
"statusMessage":null,
"targetId":2365846324436118401,
"targetLink":"https://www.googleapis.com/compute/v1/projects/my-project-id/zones/europe-west3-c/instances/some-name",
"user":"email#gmail.com",
"warnings":null,
"zone":"https://www.googleapis.com/compute/v1/projects/my-project-id/zones/europe-west3-c",
"ETag":null
}
but I can't see any new instance beeing created...
Does any one know what is the issue here?
The Compute Engine API is enabled. Result of gcloud services list:
NAME TITLE
...
compute.googleapis.com Compute Engine API
...
Can you please double check if Compute Engine Api is enabled and post the result in your question.
gcloud services list
I believe your Compute Engine Api is not enabled.
When I retrieve a checklist instance, I got the following section related to attachment.
{
"type": "instance_item_attachments",
"id": "5a0a2acf-b02a-4b88-86cc-962c3831bdee",
"attributes": {
"name": "6856ad10-6ab0-11e9-9150-9fda3da0626e.png",
"attachmentType": "OSS",
"mimeType": "image/png",
"uploadStatus": "COMPLETED",
"urns": [
{
"urn": "urn:adsk.wipprod:fs.file:vf.gy4mB910SneymU86Gc4O0A?version=1",
"type": "WIP"
},
{
"urn": "urn:adsk.objects:os.object:wip.dm.prod/ede3de59-1b68-485c-82fe-f1f2af3442fe.png",
"type": "OSS"
},
{
"urn": "urn:adsk.checklists.cs.attachment:58b8afcf-d7cd-49ad-aa10-78c50610761b/5a0a2acf-b02a-4b88-86cc-962c3831bdee",
"type": "CHECKLIST"
}
],
"createdAt": "2019-04-29T18:55:51.334Z",
"updatedAt": "2019-04-29T18:55:54.137Z",
"createdBy": "TAKCJQU6HGXW",
"modifiedBy": "TAKCJQU6HGXW",
"permittedActions": [
"canArchive",
"canEdit"
],
"permittedAttributes": [
"mimeType",
"uploadStatus"
]
},
"links": {
"self": "/containers/58b8afcf-d7cd-49ad-aa10-78c50610761b/instance_item_attachments/5a0a2acf-b02a-4b88-86cc-962c3831bdee"
},
"relationships": {
"container": {
"meta": {
"relation": "primary",
"readOnly": false
},
"links": {
"self": "/containers/58b8afcf-d7cd-49ad-aa10-78c50610761b/instance_item_attachments/5a0a2acf-b02a-4b88-86cc-962c3831bdee/relationships/container",
"related": "/containers/58b8afcf-d7cd-49ad-aa10-78c50610761b/instance_item_attachments/5a0a2acf-b02a-4b88-86cc-962c3831bdee/container"
},
"data": {
"type": "containers",
"id": "58b8afcf-d7cd-49ad-aa10-78c50610761b"
}
},
"item": {
"meta": {
"relation": "primary",
"readOnly": false
},
"links": {
"self": "/containers/58b8afcf-d7cd-49ad-aa10-78c50610761b/instance_item_attachments/5a0a2acf-b02a-4b88-86cc-962c3831bdee/relationships/item",
"related": "/containers/58b8afcf-d7cd-49ad-aa10-78c50610761b/instance_item_attachments/5a0a2acf-b02a-4b88-86cc-962c3831bdee/item"
},
"data": null
}
}
}
Now, I want to download this attachment, the provided URN is: wip.dm.prod/ede3de59-1b68-485c-82fe-f1f2af3442fe.png
If I try to access it using the following link, it says not found
developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/b30e3ffe-333b-446c-b834-e2f2141096b4.png
However, if I changed the URL a bit (by adding objects), it works fine.
developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/b30e3ffe-333b-446c-b834-e2f2141096b4.png
Am I doing something wrong here? or this is a bug in the provided urn?
Adding to Adam Nagy reply, you would need to break the URN. From your original question:
urn:adsk.objects:os.object:wip.dm.prod/ede3de59-1b68-485c-82fe-f1f2af3442fe.png
In .NET you can try (using System.Linq):
string bucketKey = urn.Split("/").First().Split(":").Last();
string objectName = urn.Split("/").Last();
Then rebuild as:
string attachemtnUrl = string.Format("{0}/oss/v2/buckets/{1}/objects/{2}", BASE_URL, bucketKey, objectName);
And you'll also need the Authorization header with a valid access token.
The id / urn of an object in OSS (Object Storage Service) contains the bucket name and object name after the "urn:adsk.objects:os.object:" section.
There is a tutorial on downloading a file https://forge.autodesk.com/en/docs/data/v2/tutorials/download-file/
It shows that the reply concerning an item contains both the id and the actual URL of the download link under the storage section:
"storage": {
"data": {
"type": "objects",
"id": "urn:adsk.objects:os.object:wip.dm.prod/977d69b1-43e7-40fa-8ece-6ec4602892f3.rvt"
},
"meta": {
"link": {
"href": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/977d69b1-43e7-40fa-8ece-6ec4602892f3.rvt"
}
}
}
There you can see the connection between the id and the URL you can use to download the file
I want to create an Elastic Beanstalk configuration that allows me to deploy a .NET Windows Service but without deploying a web application.
I have just read this blog post which explains how to use .ebextensions to deploy a Windows Service alongside your web application, but is there a scenario for which the .ebextensions can be run without deploying a Web Deploy package for a web application?
Is my only option to create an empty web application that contains the .ebextensions directory and then deploy the Web Deploy package?
The Elastic Beanstalk FAQ mentions the ability to deploy non-web applications (here) and I have found a similar (unanswered) question on the AWS developer forums (here).
Update
Due to the lack of activity on this question and my inability to find any other information on the internet, I just assumed that the answer to this question is "No" (at least for now).
I ended up creating an empty web application and used that to deploy my Windows Service via the .ebextensions YAML config.
As a side note, I'd like to highlight this page from Amazon's documentation which I found to be a very helpful guide to creating those special config files.
Another Update
After implementing the approach mentioned above, I discovered that Elastic Beanstalk was not executing my .ebextensions scripts for new Beanstalk instances. As a result, the Windows Service failed to be installed when new instances were created. I had to jump through several more hoops to finally arrive at a scalable solution. Please let me know if you want the details of the final solution.
Ultimately, it just seems like Elastic Beanstalk wasn't meant for deploying scalable Windows Services.
Basic Solution
I'm not comfortable releasing the source code since it was not for a personal project, but here is the basic structure of my current deployment solution:
A custom EC2 AMI contains a 'bootstrap' program that runs on startup. The program does the following:
1.1. Download a 'zip' archive from a (configurable) 'deployment' S3 bucket
1.2. Extract the downloaded zip file to a temporary directory
1.3. An "install.bat" script is located/executed (the name of the script is also configurable). This script installs and starts the windows service.
The Elastic Beanstalk "Instance AMI" is set to the custom AMI with the bootsrap program (see: this article)
To deploy new code: upload the installation .zip archive (that contains the windows service and install.bat file) to the S3 bucket and terminate all EC2 instances for the Elastic Beanstalk application. As the instances are re-created the bootstrapping program will download/install the newly updated code.
Of course, if I were starting over, I would just skip using Elastic Beanstalk and use the standard AWS auto-scaling along with a similar deployment scheme. The bottom line is that if you don't have a web application, don't use Elastic Beanstalk; you're better off with the standard AWS auto-scaling.
New AWS Deployment Tools
Amazon recently announced several new code deployment/management services that seem to address deployment issues: http://aws.amazon.com/blogs/aws/code-management-and-deployment/
I have yet to use these new services (I'm not even sure if they've been released yet), but they look promising.
Since this question has been around for a while and still have no answer, but continues to draw interest, let me share my solution to a very similar problem - installing a Windows service on a EC2 instance. I'm not using Beanstalk though, since that service is designed more for quick deploy of web applications. Instead, I'm using directly CloudFormation which Beanstalk uses underneath to deploy resources related to the web application.
The stack expects existing VPC (our spans through several availability zones), a S3 bucket that stores all service build artifacts and a EC2 key pair. Template creates EC2 instance using Windows AMI and few other resources like IAM User with access keys and a working S3 bucket just for illustration of how to create additional resources that your service might need. Template also takes as a parameter the name of a zipped package with all service binaries and configuration files that's been uploaded on the build artifacts S3 bucket (we use TeamCity build server that makes that for us, but you can create and upload the package manually of course). When you build new version of the service, you simply create new package (for example service.v2.zip), update the stack with the new name and the service will be updated automatically. Template contains ids of AMIs in 4 different regions, but you can always add other regions if you wish. Here's the stack template:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Service stack template.",
"Parameters": {
"KeyPair": {
"Type": "String",
"Default": "MyDefaultKeys",
"Description": "Name of EC2 Key Pair."
},
"ServicePackageName": {
"Type": "String",
"Default": "service.zip",
"Description": "Name of the zip package of the service files."
},
"DeploymentBucketName": {
"Type": "String",
"Default": "",
"Description": "Name of the deployment bucket where all the artifacts are."
},
"VPCId": {
"Type": "String",
"Default": "",
"Description": "Identifier of existing VPC."
},
"VPCSubnets": {
"Default": "",
"Description": "Commaseparated list of existing subnets within the existing VPC. Could be just one.",
"Type": "CommaDelimitedList"
},
"VPCSecurityGroup": {
"Default": "",
"Description": "Existing VPC security group. That should be the ID of the VPC's default security group.",
"Type": "String"
}
},
"Mappings": {
"Region2WinAMI": {
"us-east-1": { "64": "ami-40f0d32a" },
"us-west-1": { "64": "ami-20601740" },
"us-west-2": { "64": "ami-ff4baf9f" },
"eu-west-1": { "64": "ami-3367d340" }
}
},
"Resources": {
"ServiceInstance": {
"Type": "AWS::EC2::Instance",
"Metadata": {
"Comment": "Install Service",
"AWS::CloudFormation::Init": {
"configSets": {
"default": [ "ServiceConfig" ]
},
"ServiceConfig": {
"files": {
"c:\\service\\settings.config": {
"source": { "Fn::Join": [ "/", [ "https://s3.amazonaws.com", { "Ref": "DeploymentBucketName" }, "deployments/stacks", { "Ref": "AWS::StackName" }, "templates/settings.config.mustache" ] ] },
"context": {
"region": { "Ref": "AWS::Region" },
"accesskey": { "Ref": "IAMUserAccessKey" },
"secretkey": { "Fn::GetAtt": [ "IAMUserAccessKey", "SecretAccessKey" ] },
"bucket": { "Ref": "BucketName" }
}
},
"c:\\cfn\\cfn-hup.conf": {
"content": {
"Fn::Join": [
"",
[
"[main]\n",
"stack=",
{ "Ref": "AWS::StackId" },
"\n",
"region=",
{ "Ref": "AWS::Region" },
"\n",
"interval=1"
]
]
}
},
"c:\\cfn\\hooks.d\\cfn-auto-reloader.conf": {
"content": {
"Fn::Join": [
"",
[
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.ServiceInstance.Metadata.AWS::CloudFormation::Init\n",
"action=cfn-init.exe -v -s ",
{ "Ref": "AWS::StackName" },
" -r ServiceInstance --region ",
{ "Ref": "AWS::Region" },
"\n"
]
]
}
}
},
"sources": {
"c:\\tmp\\service": { "Fn::Join": [ "/", [ "https://s3.amazonaws.com", { "Ref": "DeploymentBucketName" }, "deployments/stacks", { "Ref": "AWS::StackName" }, "artifacts/Service", { "Ref": "ServicePackageName" } ] ] }
},
"commands": {
"Install Service": {
"command": "call c:\\tmp\\service\\install.bat",
"ignoreErrors": "false"
}
},
"services": {
"windows": {
"cfn-hup": {
"enabled": "true",
"ensureRunning": "true",
"files": [ "c:\\cfn\\cfn-hup.conf", "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf" ]
}
}
}
}
}
},
"Properties": {
"ImageId": { "Fn::FindInMap": [ "Region2WinAMI", { "Ref": "AWS::Region" }, "64" ] },
"InstanceType": "t2.micro",
"KeyName": { "Ref": "KeyPair" },
"SecurityGroupIds" : [{ "Ref": "VPCSecurityGroup" }],
"SubnetId" : { "Fn::Select": [ "0", { "Ref": "VPCSubnets" } ] },
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"<script>\n",
"if not exist \"C:\\logs\" mkdir C:\\logs \n",
"cfn-init.exe -v -s ",
{ "Ref": "AWS::StackName" },
" -r ServiceInstance --region ",
{ "Ref": "AWS::Region" },
" -c default \n",
"</script>\n"
]
]
}
},
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sda1",
"Ebs": {
"DeleteOnTermination": "true",
"VolumeSize": "40",
"VolumeType": "gp2"
}
}
],
"Tags": [
{ "Key": "Name", "Value": { "Fn::Join": [ ".", [ { "Ref": "AWS::StackName" }, "service" ] ] } }
]
}
},
"BucketName": {
"Type": "AWS::S3::Bucket",
"Properties": {
"AccessControl": "PublicRead"
},
"DeletionPolicy": "Retain"
},
"IAMUser": {
"Type": "AWS::IAM::User",
"Properties": {
"Path": "/",
"Groups": [ "stack-users" ],
"Policies": [
{
"PolicyName": "giveaccesstobuckets",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [ "s3:*" ],
"Resource": [ { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "BucketName" }, "/*" ] ] } ]
}
]
}
}
]
}
},
"IAMUserAccessKey": {
"Type": "AWS::IAM::AccessKey",
"Properties": {
"UserName": { "Ref": "IAMUser" }
}
}
}
}
As you can see, after copying the artifacts, we execute install.bat batch file (included in the zip file) that will move the files to the correct location and register the service. Here is the contents of the file:
#echo off
sc query MyService > NUL
IF ERRORLEVEL 1060 GOTO COPYANDCREATE
sc stop MyService
waitfor /T 20 ServiceStop
echo D | xcopy "c:\tmp\service" "c:\service\" /E /Y /i
GOTO END
:COPYANDCREATE
echo D | xcopy "c:\tmp\service" "c:\service\" /E /Y /i
sc create MyService binpath= "c:\service\MyService.exe" start= "auto"
:END
sc start MyService
Template also creates config file (from the settings.config.mustache which also resides on the artifacts bucket) containing information about the other resources that has been created for the service to use. Here it is:
<appSettings>
<add key="AWSAccessKey" value="{{accesskey}}" />
<add key="AWSSecretKey" value="{{secretkey}}" />
<add key="AWSRegion" value="{{region}}" />
<add key="AWSBucket" value="{{bucket}}" />
</appSettings>
You create and later update the stack either from the AWS web console or CLI.
And that's pretty much it. You can visit the AWS CloudFormation website to get more info about the service and how to work with templates.
P.S.: I realised that it would be better if I also share the template that creates the VPC. I keep it separate as I have one VPC per region. You can integrate it with the Service template if you wish, but that would mean that every time you create new stack a new VPC will be also created. Here is the VPC template:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "VPC stack template.",
"Mappings": {
"Region2AZ": {
"us-east-1": { "AZ": [ "us-east-1a", "us-east-1b", "us-east-1d" ] },
"us-west-1": { "AZ": [ "us-west-1b", "us-west-1c" ] },
"us-west-2": { "AZ": [ "us-west-2a", "us-west-2b", "us-west-2c" ] },
"eu-west-1": { "AZ": [ "eu-west-1a", "eu-west-1b", "eu-west-1c" ] }
}
},
"Conditions": {
"RegionHas3Zones": { "Fn::Not" : [ { "Fn::Equals" : [ { "Ref": "AWS::Region" }, "us-west-1" ] } ] }
},
"Resources": {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsSupport" : "true",
"EnableDnsHostnames" : "true"
}
},
"VPCSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group for VPC.",
"VpcId": { "Ref": "VPC" }
}
},
"Subnet0": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": "10.0.0.0/24",
"AvailabilityZone": { "Fn::Select": [ "0", { "Fn::FindInMap": [ "Region2AZ", { "Ref": "AWS::Region" }, "AZ" ] } ] }
}
},
"Subnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": "10.0.1.0/24",
"AvailabilityZone": { "Fn::Select": [ "1", { "Fn::FindInMap": [ "Region2AZ", { "Ref": "AWS::Region" }, "AZ" ] } ] }
}
},
"Subnet2": {
"Type": "AWS::EC2::Subnet",
"Condition": "RegionHas3Zones",
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": "10.0.2.0/24",
"AvailabilityZone": { "Fn::Select": [ "2", { "Fn::FindInMap": [ "Region2AZ", { "Ref": "AWS::Region" }, "AZ" ] } ] }
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
}
},
"AttachGateway": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": { "Ref": "VPC" },
"InternetGatewayId": { "Ref": "InternetGateway" }
}
},
"RouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "VPC" }
}
},
"Route": {
"Type": "AWS::EC2::Route",
"DependsOn": "AttachGateway",
"Properties": {
"RouteTableId": { "Ref": "RouteTable" },
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": { "Ref": "InternetGateway" }
}
},
"SubnetRouteTableAssociation0": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "Subnet0" },
"RouteTableId": { "Ref": "RouteTable" }
}
},
"SubnetRouteTableAssociation1": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "Subnet1" },
"RouteTableId": { "Ref": "RouteTable" }
}
},
"SubnetRouteTableAssociation2": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Condition": "RegionHas3Zones",
"Properties": {
"SubnetId": { "Ref": "Subnet2" },
"RouteTableId": { "Ref": "RouteTable" }
}
},
"NetworkAcl": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": { "Ref": "VPC" }
}
},
"AllowAllInboundTCPAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAcl" },
"RuleNumber": "100",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": { "From": "0", "To": "65535" }
}
},
"AllowAllInboundUDPAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAcl" },
"RuleNumber": "101",
"Protocol": "17",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": { "From": "0", "To": "65535" }
}
},
"AllowAllOutboundTCPAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAcl" },
"RuleNumber": "100",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": { "From": "0", "To": "65535" }
}
},
"AllowAllOutboundUDPAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAcl" },
"RuleNumber": "101",
"Protocol": "17",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": { "From": "0", "To": "65535" }
}
},
"SubnetNetworkAclAssociation0": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": { "Ref": "Subnet0" },
"NetworkAclId": { "Ref": "NetworkAcl" }
}
},
"SubnetNetworkAclAssociation1": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": { "Ref": "Subnet1" },
"NetworkAclId": { "Ref": "NetworkAcl" }
}
},
"SubnetNetworkAclAssociation2": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Condition": "RegionHas3Zones",
"Properties": {
"SubnetId": { "Ref": "Subnet2" },
"NetworkAclId": { "Ref": "NetworkAcl" }
}
}
},
"Outputs": {
"VPC": {
"Description": "VPC",
"Value": { "Ref": "VPC" }
},
"VPCSecurityGroup": {
"Description": "VPC Security Group Id",
"Value": { "Fn::GetAtt": [ "VPCSecurityGroup", "GroupId" ] }
},
"Subnet0": {
"Description": "Subnet0 Id",
"Value": { "Ref": "Subnet0" }
},
"Subnet1": {
"Description": "Subnet1 Id",
"Value": { "Ref": "Subnet1" }
},
"Subnet2": {
"Description": "Subnet2 Id",
"Condition": "RegionHas3Zones",
"Value": { "Ref": "Subnet2" }
}
}
}
From my own experience, implementing anything using ebextensions significantly adds to the elapsed time for deployment. So much so that it can take up to 15 minutes for an instance to spin up when auto-scaling. Almost defeats the purpose.
In any event, be sure to configure the Auto Scaling Group's "Health Check Grace Period" property to something significant. For example, we use 900 (i.e. 15 minutes). Anything less and the instance never passes the health check and the scale up event fails; which makes for an unending series of attempts to scale up.