GithubHelp home page GithubHelp logo

aws-cloudformation-resource-providers-awsutilities-commandrunner's Introduction

AWSUtility::CloudFormation::CommandRunner

CommandRunner v2.0.1 is here! ๐Ÿš€ ๐Ÿš€ ๐Ÿš€

I took all the feedback, issues and feature requests from all our users to create this new major version. All known bugs for CommandRunner have now been fixed!

This version comes with 3 new properties InstanceType, Timeout and DisableTerminateInstancesCheck, improved error handling, logging, reliability, documentation and functionality.

To update to the new version or do a fresh install, simply run the following commands in a new directory.

git clone https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner.git

cd aws-cloudformation-resource-providers-awsutilities-commandrunner

curl -LO https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner/releases/latest/download/awsutility-cloudformation-commandrunner.zip

./scripts/register.sh --set-default

For more details, check the Change Log section below.


Table Of Contents


Introduction

AWSUtility::CloudFormation::CommandRunner is a CloudFormation resource type created using the recently released CloudFormation Resource Providers framework.

The AWSUtility::CloudFormation::CommandRunner resource allows users to run Bash commands in any CloudFormation stack.

This allows for unlimited customization such as executing AWS CLI/API calls, running scripts in any language, querying databases, doing external REST API calls, cleanup routines, validations, dynamically referencing parameters and just about anything that can be done using the shell on an EC2 instance.

The AWSUtility::CloudFormation::CommandRunner resource runs any command provided to it before or after any resource in the Stack.

AWSUtility::CloudFormation::CommandRunner can be used to perform inside your CloudFormation stack, any API call, script, custom logic, external check, conditions, cleanup, dynamic parameter retrieval and just about anything that can be done using a command.

Any output written using the command to the reserved file /command-output.txt can be referenced anywhere in your template by using !Fn::GetAtt Command.Output like below, where Command is the logical name of the AWSUtility::CloudFormation::CommandRunnerresource.

Resources:
  MyCommand:
    Type: 'AWSUtility::CloudFormation::CommandRunner'
    Properties:
      Command: aws s3 ls | sed -n 1p | cut -d " " -f3 > /command-output.txt
      Role: String #Optional
      LogGroup: String #Optional
      SubnetId: String #Optional
      SecurityGroupId: String #Optional
      KeyId: String #Optional
      Timeout: String #Optional **NEW**
      DisableTerminateInstancesCheck: String #Optional **NEW**
      InstanceType: #Optional **NEW**

Outputs:
    Output:
        Description: The output of the CommandRunner.
        Value: !GetAtt MyCommand.Output

Note: In the above example, sed -n 1p prints only the first line from the response returned by aws s3 ls. To get the bucket name, sed -n 1p pipes the response to cut -d " " -f3, which chooses the third element in the array created after splitting the line delimited by a space.

Only the property Command is required, while Role, LogGroup, SubnetId and SecurityGroupId are not required and have defaults.

Command is the Bash command. Role is the IAM Role to run the command. LogGroup is the CloudWatch Log Group to send logs from the command's execution. SubnetId is the ID of the Subnet that the command will be executed in. SecurityGroupId is the ID of the Security Group applied during the execution of the command.

For more information about the above properties, navigate to Properties in the Documentation.

Note that the command once executed cannot be undone. It is highly recommended to test the AWSUtility::CloudFormation::CommandRunner resource out in a test stack before adding it to your production stack.


Prerequisites

  • AWS CLI
  • To register the AWSUtility::CloudFormation::CommandRunner resource to your AWS account/region, you need IAM permissions to perform the following actions.
s3:CreateBucket
s3:DeleteBucket
s3:PutBucketPolicy
s3:PutObject
cloudformation:RegisterType
cloudformation:DescribeTypeRegistration
iam:createRole
logs:CreateLogGroup

User Installation Steps

Note: To build the source yourself, see the Developer Build Steps section below.

Step 0: Clone this repository and download the latest release using the following commands.

git clone https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner.git
cd aws-cloudformation-resource-providers-awsutilities-commandrunner
curl -LO https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner/releases/latest/download/awsutility-cloudformation-commandrunner.zip

Step 1: Use the register.sh bash script to register resource from scratch and upload package to S3 bucket. Pass the optional --set-default option to set this version to be the default version for the AWSUtility::CloudFormation::CommandRunner resource.

$ ./scripts/register.sh --set-default

...And that's it!

Below is an example of a successful registration using the register.sh script.

$ ./scripts/register.sh
Creating Execution Role...
Waiting for execution role stack to complete...
Waiting for execution role stack to complete...
Waiting for execution role stack to complete...
Waiting for execution role stack to complete...
Creating/Updating Execution Role complete.
Creating temporary S3 Bucket 7c96b969af1c41bfb2bd10f552255ca2...
Creating temporary S3 Bucket 7c96b969af1c41bfb2bd10f552255ca2 complete.
Configuring S3 Bucket Policy for temporary S3 Bucket 7c96b969af1c41bfb2bd10f552255ca2...
Configuring S3 Bucket Policy for temporary S3 Bucket 7c96b969af1c41bfb2bd10f552255ca2 complete.
Copying Schema Handler Package to temporary S3 Bucket 7c96b969af1c41bfb2bd10f552255ca2...
Copying Schema Handler Package to temporary S3 Bucket 7c96b969af1c41bfb2bd10f552255ca2 complete.
Creating CommandRunner Log Group called awsutility-cloudformation-commandrunner-logs2...
Creating CommandRunner Log Group complete.
Registering AWSUtility::CloudFormation::CommandRunner to AWS CloudFormation...
RegistrationToken: 0ae0622e-af3d-463b-9b2d-1d1e5fa41d14
Waiting for registration to complete...
Waiting for registration to complete...
Waiting for registration to complete...
Waiting for registration to complete...
Registering AWSUtility::CloudFormation::CommandRunner to AWS CloudFormation complete.
Cleaning up temporary S3 Bucket...
Deleting SchemaHandlerPackage from temporary S3 Bucket 7c96b969af1c41bfb2bd10f552255ca2...
Deleting SchemaHandlerPackage from temporary S3 Bucket 7c96b969af1c41bfb2bd10f552255ca2 complete.
Cleaning up temporary S3 Bucket complete.

AWSUtility::CloudFormation::CommandRunner is ready to use.

The register.sh script performs the following operations to register the AWSUtility::CloudFormation::CommandRunner resource.

  • Creates an Execution Role for the AWSUtility::CloudFormation::CommandRunner resource to give it permissions to perform the following actions.
cloudformation:DeleteStack
cloudformation:CreateStack
cloudformation:DescribeStacks

logs:CreateLogStream
logs:DescribeLogGroups
logs:PutLogEvents

cloudwatch:PutMetricData

ssm:GetParameter
ssm:PutParameter
ssm:DeleteParameter

ec2:DescribeSubnets
ec2:DescribeVpcs
ec2:DescribeSecurityGroups
ec2:CreateSecurityGroup
ec2:RevokeSecurityGroupEgress
ec2:RevokeSecurityGroupIngress
ec2:CreateTags
ec2:AuthorizeSecurityGroupIngress
ec2:AuthorizeSecurityGroupEgress
ec2:RunInstances
ec2:DescribeInstances
ec2:TerminateInstances
ec2:DeleteSecurityGroup

iam:PassRole
iam:GetInstanceProfile
iam:SimulatePrincipalPolicy

#Only required if using the KeyId property, i.e custom KMS Key for the SSM SecureString
kms:Encrypt
kms:Decrypt

sts:GetCallerIdentity
  • Runs the aws s3 mb AWS CLI command to create an S3 bucket with the name specified.
  • Runs the aws s3api put-bucket-policy AWS CLI command to put the following bucket policy on the new bucket, where <BUCKET_NAME> is the specified bucket name.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::<BUCKET_NAME>/*",
                "arn:aws:s3:::<BUCKET_NAME"
            ],
            "Principal": {
                "Service": "cloudformation.amazonaws.com"
            }
        }
    ]
}
  • Runs the aws s3 cp AWS CLI command to copy the SchemaHandlerPackage awsutility-cloudformation-commandrunner.zip into the S3 bucket.
  • Runs the aws logs create-log-group AWS CLI command to create the Log Group or skip it if it already exists.
  • Runs the aws cloudformation register-type AWS CLI command to register the AWSUtility::CloudFormation::CommandRunner resource to CloudFormation.
  • Cleans up the temporary S3 bucket created during registration.

Note that to run the register.sh script the IAM Role/User configured in the AWS CLI should have the following IAM permissions.

s3:CreateBucket
s3:DeleteBucket
s3:PutBucketPolicy
s3:PutObject
cloudformation:RegisterType
cloudformation:DescribeTypeRegistration
iam:CreateRole

The following sample policy can be attached to the IAM User/Role if they do not have the necessary permissions.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:RegisterType",
                "cloudformation:DescribeTypeRegistration"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:CreateBucket",
                "s3:DeleteBucket",
                "s3:PutBucketPolicy",
                "s3:PutObject"
            ],
            "Resource": "*"
        }
    ]
}

Documentation

Syntax

JSON

{
    "Resources": {
        "CommandRunner": {
            "Type": "AWSUtility::CloudFormation::CommandRunner",
            "Properties": {
                "Command": "String",
                "Role": "String",
                "LogGroup": "String",
                "SubnetId": "String",
                "SecurityGroupId": "String",
                "KeyId": "String",
                "Timeout": "String",
                "DisableTerminateInstancesCheck": "String",
                "InstanceType": "String"
            }
        }
    }
}

YAML

Resources:
  CommandRunner:
    Type: 'AWSUtility::CloudFormation::CommandRunner'
    Properties:
      Command: String
      Role: String #Optional
      LogGroup: String #Optional
      SubnetId: String #Optional
      SecurityGroupId: String #Optional
      KeyId: String #Optional
      Timeout: String #Optional **NEW**
      DisableTerminateInstancesCheck: String #Optional **NEW**
      InstanceType: #Optional **NEW**

Outputs:
    Output:
        Description: The output of the CommandRunner.
        Value: !GetAtt Command.Output

Properties

Command

The bash command that you would like to run.

For AWS CLI commands, please specify the region using the --region option.

Note:

Every command needs to output the desired value into the reserved file "/command-output.txt" like the following example. The value written to the file must be a non-empty single word value without quotation marks like vpc-0a12ab123abc9876 as they are intended to be used inside the CloudFormation template using Fn::GetAtt.

aws ec2 describe-vpcs --query Vpcs[0].VpcId --output text > /command-output.txt

Note:

The command is run on the latest Amazon Linux 2 AMI in your region.

Required: Yes

Type: String

Update requires: Replacement

Role

The IAM Instance Profile to be used to run the Command. The Role in the Instance Profile will need all the permissions required to run the above Command.

Note:

The Role should have permissions to perform the actions below to write logs to CloudWatch from the command's execution.

"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:PutLogEvents"

If the Role does not have the above logging permissions, the command will still work but no logs will be written.

Note:

The Role in the Instance Profile should specify ec2.amazonaws.com as a Trusted Entity. An Instance Profile is created automatically when a Role is created using the Console for an EC2 instance.

Required: No

Type: String

Update requires: Replacement

LogGroup

The CloudWatch Log Group to stream the logs from the specified command.

If one is not provided the default cloudformation-commandrunner-log-group one will be used.

If the specified log group does not exist, a new one will be created.

Tip:

To log a trace of your commands and their arguments after they are expanded and before they are executed, run set -xe in the Command property before your actual command.

Required: No

Type: String

Update requires: Replacement

SubnetId

The Id of the Subnet to execute the command in. Note that the SubnetId specified should have access to the internet to be able to communicate back to CloudFormation. Ensure that the Route Table associated with the Subnet has a route to the internet via either an Internet Gateway (IGW) or a NAT Gateway (NGW).

Note:

If the SubnetID is not specified, it will create the resource in a subnet in the default VPC of the region.

Required: No

Type: String

Update requires: Replacement

SecurityGroupId

The Id of the Security Group to attach to the instance the command is run in. If using SecurityGroup, the SubnetId property is required.

Note:

If the SecurityGroupId is not specified, the command will be run with a security group with open Egress rules and no Ingress rules.

Required: No

Type: String

Update requires: Replacement

KeyId

Id of the KMS key to use when encrypting the output stored in SSM Parameter Store. If not specified, the account's default KMS key is used.

Required: No

Type: String

Update requires: Replacement

Timeout

By default, the timeout is 600 seconds. To increase the timeout specify a higher Timeout value in seconds. The maximum timeout value is 43200 seconds i.e 12 hours.

Required: No

Type: String

Update requires: Replacement

DisableTerminateInstancesCheck

By default, CommandRunner checks to see if the execution role can perform a TerminateInstances API call. Set this property to true if you want to skip the check. Note that this means that the CommandRunner instance may not be terminated and will have to be terminated manually.

Required: No

Type: String

Update requires: Replacement

InstanceType

By default, the instance type used is t2.medium. However you can use this property to specify any supported instance type.

Required: No

Type: String

Update requires: Replacement


Return Values

Fn::GetAtt

Users can reference the output of the command written to /command-output.txt using Fn::GetAtt like in the following syntax.

Outputs:
    Output:
        Description: The output of the command.
        Value: !GetAtt Command.Output

User Guides

Run A Command Before Or After A Resource

To run the command after a resource with logical name Resource, specify DependsOn: Resource in the AWSUtility::CloudFormation::CommandRunner resource's definition.

Resources:
   Command:
      DependsOn: Resource
      Type: AWSUtility::CloudFormation::CommandRunner
      Properties:
         Command: echo success > /command-output.txt
         LogGroup: my-cloudwatch-log-group
         Role: MyEC2InstanceProfile
   Resource:
      Type: AWS::EC2::Instance
      Properties:
         Image: ami-abcd1234

To run the command before a resource, put a DependsOn with the logical name of the AWSUtility::CloudFormation::CommandRunner resource in that resource's definition.

Resources:
   Command:
      Type: AWSUtility::CloudFormation::CommandRunner
      Properties:
         Command: echo success > /command-output.txt
         LogGroup: my-cloudwatch-log-group
         Role: MyEC2InstanceProfile
   Resource:
      DependsOn: Command
      Type: AWS::EC2::Instance
      Properties:
         Image: ami-abcd1234

Run a script in any programming language using any SDK

You can write a script in any programming language and upload it to S3. Use the aws s3 cp command to copy the script from S3 followed by && and the command to run the script like the following example.

Resources:
    Command:
        Type: AWSUtility::CloudFormation::CommandRunner
        Properties:
            Command: 'aws s3 cp s3://cfn-cli-project/S3BucketCheck.py . && python S3BucketCheck.py my-bucket third-name-option-a'
            Role: MyEC2InstanceProfile
            LogGroup: my-cloudwatch-log-group
Outputs:
    Output:
        Description: The output of the command.
        Value: !GetAtt Command.Output

Install Packages before Running Command

Resources:
    Command:
        Type: AWSUtility::CloudFormation::CommandRunner
        Properties:
            Command:
                Fn::Sub: |
                    yum install jq -y
                    aws ssm get-parameter --name RepositoryName --region us-east-1 > response.json
                    jq -r .Parameter.Value response.json > /command-output.txt'
            Role: MyEC2InstanceProfile
            LogGroup: my-cloudwatch-log-group
Outputs:
    Output:
        Description: The output of the command.
        Value: !GetAtt Command.Output

Using AWSCLI --query option

Resources:
    Command:
        Type: AWSUtility::CloudFormation::CommandRunner
        Properties:
            Command:
                Fn::Sub: |
                    aws ssm get-parameter --name RepositoryName --region us-east-1 --query Parameter.Value --output text > /command-output.txt
            Role: MyEC2InstanceProfile
            LogGroup: my-cloudwatch-log-group
Outputs:
    Output:
        Description: The output of the command.
        Value: !GetAtt Command.Output

Run A Multi-Line Script

Resources:
   CommandRunner:
      Type: AWSUtility::CloudFormation::CommandRunner
      Properties:
         Command:
            Fn::Sub: |
                echo "my log"
                echo '{"key":"value"}' > mydata.json
                ...
                <ANY OTHER COMMANDS>
                ...
                echo success > /command-output.txt
         LogGroup: my-cloudwatch-log-group
         Role: MyEC2InstanceProfile

Use Cases

  • The AWSUtility::CloudFormation::CommandRunner resource lets you perform any API call, script, custom logic, external check, conditions, cleanup, dynamic parameter retrieval and anything else that can be done using a command.

  • Get parameters dynamically during the Stack's execution instead of passing in Parameters during stack creation.

    • Currently, Dynamic Referencing i.e SSM {{resolve}} on CloudFormation cannot automatically get the latest version of the SSM Parameter. Due to this, users have to know the latest version number and manually put it in every time or the CFN stack will continue to resolve to the old version. This can be worked around using AWSUtility::CloudFormation::CommandRunner to always get the latest parameter value.
  • Currently, there is no AWS::ECS resource that allows you to configure the Account Settings. However, you can do this using the AWSUtility::CloudFormation::CommandRunner resource by running the aws ecs put-account-setting CLI commmand.

  • Currently, there is no way to create an image (AMI) using a running EC2 instance, but it can be done using the AWSUtility::CloudFormation::CommandRunner resource by using the aws ec2 create-image CLI command.

  • Add a lag between resources using CommandRunner. Specify a sleep command in the Command property.


FAQ

Q. Why use EC2 instead of Lambda?

  • Lambda does not natively support using Bash.

  • Even if Bash is added using custom Lambda Layers it will still not allow installing new packages or running other programming / scripting languages.

  • Lambda is also more expensive than running a small EC2 instance for approximately 2 minutes.

Q. Why make this when Custom Resources and Macros are available?

  • Developing a Custom Resource or Macro requires writing several lines of code and troubleshooting which is considered to be development effort.

  • The AWSUtility::CloudFormation::CommandRunner provides a quick fix to solve problems with a single line of code and does not require any development effort.

  • Using the AWSUtility::CloudFormation::CommandRunner, users can quickly unblock themselves without relying on CloudFormation to resolve the issue to unblock them.


Developer Build Steps

Please execute the included build script by running ./scripts/build.sh to build and register the resource to AWS CloudFormation for your account. The script waits while CloudFormation registers the resource so it typically takes about 5-10 minutes.

Note that the script assumes that you have AWS CLI configured and the necessary permissions to register a resource provider to CloudFormation, jq, mvn and the prerequisites mentioned here. https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/what-is-cloudformation-cli.html

The build script will do the following:

  1. Runs cfn generate to generate the rpdk files for the Resource Provider.

  2. mvn package packages the Java code up and cfn submit registers the built Resource to AWS CloudFormation in your AWS account.

  3. From the output of the cfn submit command, it gets the version of the build and updates the default version to be used in CloudFormation.

Once the script finishes, the AWSUtility::CloudFormation::CommandRunner resource will be ready to use.

You can find an example of how to use the resource in the file usage-template.yaml.

As of March 2024, the recommended versions and dependencies for the build are as follows.

$ cfn --version
cfn 0.2.35

$ mvn -version
Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae)
Maven home: /opt/homebrew/Cellar/maven/3.9.6/libexec
Java version: 19.0.2, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-19.jdk/Contents/Home
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "14.1.1", arch: "aarch64", family: "mac"

$ java -version
java 19.0.2 2023-01-17
Java(TM) SE Runtime Environment (build 19.0.2+7-44)
Java HotSpot(TM) 64-Bit Server VM (build 19.0.2+7-44, mixed mode, sharing)

$ ./scripts/build.sh

Change Log

v2.0.1

  • Updated from java8 to java8.al2.
  • Updated README and added more examples.
  • Fixed IAM policy.
  • Fixed register.sh.
  • Better region determination in register.sh.

v2.0

  • Updated package versions in pom.xml to latest, fixing build issues related to outdated dependencies.
  • Improved Error Handling
    • For when command fails or when invalid value is written to /command-output.txt
      • Error message about checking cloud-init-output.log also includes network related issues.
    • When no default VPC exists.
      • Added try catch block for catching exception if no default VPC.
      • Error message - "No default VPC found in this region, please specify a subnet using the SubnetId property."
  • Improved logging
    • Added contents of /command-output.txt to CloudWatch logs under cloud-init-output.log.
    • Updated BaseTemplate to add contents of /command-output.txt to cloudwatch logs.
  • Added catch for failures on CommandRunner stack.
    • Failure on CommandRunner stack was not being caught when response sent to CommandRunner stack in WaitCondition is malformed.
    • Failures are now caught right away, if CommandRunner stack goes into ROLLBACK_COMPLETE, or ROLLBACK_FAILED, then it will now gracefully clean up the CommandRunner stack.
  • Updated user installation script register.sh
    • Added creation of log group in register.sh, along with handling the case where it already exists.
    • LogGroup not created for new region, line 103 of register.sh check if log-group exists if not, create one.
    • register.sh will try to create a fresh execution role stack, if it exists it will try to update it, if it is up to date it will skip it.
  • Fixed bugs with networking configuration properties i.e SubnetId, SecurityGroupId
    • Removed empty string checks, now all different scenarios with/without SubnetId, SecurityGroupId work.
  • Added new Timeout property.
    • Timeout property to change timeout in WaitCondition in BaseTemplate, this will give the option to easy fail, by default timeout is 600 right now, this will allow for a max timeout of 12 hours i.e 43200
  • Added new DisableTerminateInstancesCheck property.
    • Some users were running into issues where their SCP policies did not allow the ec2:TerminateInstances action, but they still want to create CommandRunner instances. Setting this property to true allows them to create CommandRunner instances even without the ec2:TerminateInstances action.
  • Added new InstanceType property.
  • Now works in Private Subnets. We had seen some issues where CommandRunner wouldn't work in private subnets, this issue is now resolved.
  • Added check for Instance Profile validity. An error is thrown within 5 seconds of resource creation if the Role property specified is not a valid Instance Profile.
  • Added .gitignore to repository, removed unnecessary temporary files.
  • Added the CommandRunner banner to both installation and build scripts.
  • Documentation
    • Fixed typos and grammatical errors.
    • Added new properties to all examples and schemas.
    • Added new properties to documentation.
    • Added new permissions to documentation.
  • Fixed a bug where a fresh installation using register.sh wouldnโ€™t work unless build.sh had been used before it.

v1.21

  • Updated README to add more clarification into what values are accepted by /command-output.txt.
  • Changed cloudwatch: to logs:, fixing the permissions issue when writing logs.
  • Updated README to improve instructions for user installation steps.

v1.2

  • Output stored in SSM Parameter Store is now SecureString by default i.e Encrypted at rest using the Default KMS key of the account.
  • Added new parameter KMSKeyId allowing users to specify their own customer-managed KMS Key to encrypt the SSM SecureString Parameter.
  • Updated README with log permissions and specified that no error is thrown when it canโ€™t write to log group. It requires the following permissions to write logs. If not provided, it wonโ€™t do any logging.
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:PutLogEvents"
  • The idea is that the command should still run even if the logs canโ€™t be written. Users should have the option to not log if not required.

v1.1

  • Added register.shand user build steps
  • Added notes to the Properties
  • Contract tests using cfn test all work with the following results.
collected 12 items / 5 deselected / 7 selected

handler_create.py::contract_create_delete PASSED                                                                                                [ 14%]
handler_create.py::contract_create_duplicate PASSED                                                                                             [ 28%]
handler_create.py::contract_create_read_success PASSED                                                                                          [ 42%]
handler_delete.py::contract_delete_read PASSED                                                                                                  [ 57%]
handler_delete.py::contract_delete_delete PASSED                                                                                                [ 71%]
handler_delete.py::contract_delete_create SKIPPED                                                                                               [ 85%]
handler_misc.py::contract_check_asserts_work PASSED                                                                                             [100%]

v1.0

  • Improved build script build.sh, it now does not use S3. The BaseTemplate.json is stored as a resource in the .jar file.
  • Cleaned up code, removed comments, verbose code, etc.

v0.9

  • Removed all the extra build steps, now it takes only running the build.sh script after youโ€™ve cloned the repo.

    • Previously, to build the project, the static variables in CreateHandler.java needed to be replaced. They are now dynamically inferred and replaced in CreateHandler.java using the build.sh script.
    • Added 2 new parameters and the Java logic to support them. Users can now optionally specify the SubnetId and the SecurityGroupId or both. If neither is provided itโ€™ll use a subnet in the default VPC and create a SecurityGroup automatically.
  • Instead of using {{resolve}}, Fn::GetAtt now works, you can do !GetAtt Command.Output

  • Updated the presentation to reflect the above changes.

  • Updated the documentation

    • New build steps and what build.sh does
    • Dependencies and versions used
    • Disclaimer about Command in docs
    • Properties SubnetId and SecurityGroupId
    • Referencing using Fn::GetAtt
    • Added Change History section
  • If a security group is not provided, the one that is automatically created has no inbound rules and only allows outbound communication.

  • Previously I had provided wildcard permissions to the resource. Now, only the below permissions are used and there are no wildcards.

cloudformation:DeleteStack
cloudformation:CreateStack
cloudformation:DescribeStacks

logs:CreateLogStream
logs:DescribeLogGroups

ssm:GetParameter
ssm:PutParameter

ec2:DescribeSubnets
ec2:DescribeVpcs
ec2:DescribeSecurityGroups
ec2:CreateSecurityGroup
ec2:RevokeSecurityGroupEgress
ec2:RevokeSecurityGroupIngress
ec2:CreateTags
ec2:AuthorizeSecurityGroupIngress
ec2:AuthorizeSecurityGroupEgress
ec2:RunInstances
ec2:DescribeInstances
ec2:TerminateInstances
ec2:DeleteSecurityGroup
iam:PassRole

#Only required if using the KeyId property, i.e custom KMS Key for the SSM SecureString
kms:Encrypt
kms:Decrypt

See Also

AWS Blogs - AWS Cloud Operations & Migrations Blog - Running bash commands in AWS CloudFormation templates

AWS Premium Support - Knowledge Center - CloudFormation - How do I use AWSUtility::CloudFormation::CommandRunner to run a command before or after a resource in my CloudFormation stack?

aws-cloudformation-resource-providers-awsutilities-commandrunner's People

Contributors

amazon-auto avatar cfn-rpdk-ci avatar craigataws avatar shantgup avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

aws-cloudformation-resource-providers-awsutilities-commandrunner's Issues

facing issue while running ./scripts/build.sh

[INFO] Compiling 11 source files to /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[45,64] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[50,54] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[54,66] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[131,29] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[150,43] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[45,50] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[50,54] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[54,66] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[140,29] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[159,43] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/ResourceModel.java:[58,17] cannot find symbol
symbol: method getId()
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/ResourceModel.java:[59,51] cannot find symbol
symbol: method getId()
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[51,41] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[55,53] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[68,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[83,9] cannot find symbol
symbol: variable loggerProxy
location: class software.awsutility.cloudformation.commandrunner.HandlerWrapperExecutable
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[85,30] cannot find symbol
symbol: variable loggerProxy
location: class software.awsutility.cloudformation.commandrunner.HandlerWrapperExecutable
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[86,9] cannot find symbol
symbol: variable loggerProxy
location: class software.awsutility.cloudformation.commandrunner.HandlerWrapperExecutable
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[97,47] cannot find symbol
symbol: method handleRequest(java.io.InputStream,java.io.FileOutputStream)
location: class software.awsutility.cloudformation.commandrunner.HandlerWrapperExecutable
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[116,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[124,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[129,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[133,26] wrong number of type arguments; required 1
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[149,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[154,5] method does not override or implement a method from a supertype
[INFO] 25 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.096 s
[INFO] Finished at: 2021-09-08T12:11:11Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project awsutility-cloudformation-commandrunner-handler: Compilation failure: Compilation failure:
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[45,64] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[50,54] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[54,66] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[131,29] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[150,43] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[45,50] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[50,54] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[54,66] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[140,29] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[159,43] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/ResourceModel.java:[58,17] cannot find symbol
[ERROR] symbol: method getId()
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/ResourceModel.java:[59,51] cannot find symbol
[ERROR] symbol: method getId()
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[51,41] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[55,53] wrong number of type arguments; required 2
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[68,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[83,9] cannot find symbol
[ERROR] symbol: variable loggerProxy
[ERROR] location: class software.awsutility.cloudformation.commandrunner.HandlerWrapperExecutable
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[85,30] cannot find symbol
[ERROR] symbol: variable loggerProxy
[ERROR] location: class software.awsutility.cloudformation.commandrunner.HandlerWrapperExecutable
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[86,9] cannot find symbol
[ERROR] symbol: variable loggerProxy
[ERROR] location: class software.awsutility.cloudformation.commandrunner.HandlerWrapperExecutable
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[97,47] cannot find symbol
[ERROR] symbol: method handleRequest(java.io.InputStream,java.io.FileOutputStream)
[ERROR] location: class software.awsutility.cloudformation.commandrunner.HandlerWrapperExecutable
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[116,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[124,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[129,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[133,26] wrong number of type arguments; required 1
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[149,5] method does not override or implement a method from a supertype
[ERROR] /home/ubuntu/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[154,5] method does not override or implement a method from a supertype
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Build.sh not working even after changing the instance type

Hi Team,

I have updated the instance type as suggested in old issue but even after changing the instance type am facing the same issue.

ERROR

INFO] 67 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.268 s
[INFO] Finished at: 2021-12-19T18:00:53Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project awsutility-cloudformation-commandrunner-handler: Compilation failure: Compilation failure:
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[45,64] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[50,54] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[54,66] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[131,29] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapperExecutable.java:[150,43] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[45,50] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[50,54] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[54,66] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[140,29] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/HandlerWrapper.java:[159,43] wrong number of type arguments; required 2
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/ReadHandler.java:[26,39] cannot find symbol
[ERROR] symbol: method getId()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/ReadHandler.java:[31,18] cannot find symbol
[ERROR] symbol: method setOutput(java.lang.String)
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/ResourceModel.java:[58,17] cannot find symbol
[ERROR] symbol: method getId()
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/target/generated-sources/rpdk/software/awsutility/cloudformation/commandrunner/ResourceModel.java:[59,51] cannot find symbol
[ERROR] symbol: method getId()
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/Configuration.java:[12,9] constructor BaseConfiguration in class software.awsutility.cloudformation.commandrunner.BaseConfiguration cannot be applied to given types;
[ERROR] required: no arguments
[ERROR] found: java.lang.String
[ERROR] reason: actual and formal argument lists differ in length
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[143,48] cannot find symbol
[ERROR] symbol: method getCommand()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[146,26] cannot find symbol
[ERROR] symbol: method getRole()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[146,53] cannot find symbol
[ERROR] symbol: method getRole()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[149,63] cannot find symbol
[ERROR] symbol: method getRole()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[159,26] cannot find symbol
[ERROR] symbol: method getLogGroup()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[159,57] cannot find symbol
[ERROR] symbol: method getLogGroup()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[162,53] cannot find symbol
[ERROR] symbol: method getLogGroup()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[168,27] cannot find symbol
[ERROR] symbol: method getSubnetId()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[168,58] cannot find symbol
[ERROR] symbol: method getSecurityGroupId()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[169,31] cannot find symbol
[ERROR] symbol: method getSubnetId()
[ERROR] location: variable model of type software.awsutility.cloudformation.commandrunner.ResourceModel
[ERROR] /opt/aws-cloudformation-resource-providers-awsutilities-commandrunner/src/main/java/software/awsutility/cloudformation/commandrunner/CreateHandler.java:[169,60] cannot find symbol
[ERROR] symbol: method getSecurityGroupId()

Get outputs from other resource

I'm creating msk using cloud formation template, SInce msk resource in cloud formation only gives msk arn as output,
I ran an was command to get the bootstrap broker URL, But when running the command I'm not able to refer output from the msk resource (!GetAtt MskCluster.Arn)

Please help me fix this

Invalid bucket name

I tried to install it using git bash but I faced with this error:

$ ./scripts/register.sh --set-default
Creating Execution Role...
Waiting for execution role stack to complete...
Waiting for execution role stack to complete...
Waiting for execution role stack to complete...
Creating Execution Role complete.
./scripts/register.sh: line 70: uuidgen: command not found
Creating temporary S3 Bucket ...
Creating temporary S3 Bucket failed, please try again.
 Invalid bucket name "": Bucket name must match the regex "^[a-zA-Z0-9.\-_]{1,255}$" or be an ARN matching the regex "^arn:(aws).*:s3:[a-z\-0-9]+:[0-9]{12}:accesspoint[/:][a-zA-Z0-9\-]{1,63}$"

Can't get it working - validation error

Hi there,
I'm trying to use command runner with CF.

Here's my CF file, it's pretty simple:

AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Resources:
  CommandRunner:
    Type: AWSUtility::CloudFormation::CommandRunner
    Properties:
      Command: aws s3 ls
      Role: TestEC2Role

Then I get this error:
Resource handler returned message: "1 validation error detected: Value '' at 'value' failed to satisfy constraint: Member must have length greater than or equal to 1. (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: ValidationException;

My EC2 role is configured properly and I have installed commandrunner as it's described in docs.
Do you have any idea why it doesn't work?

Thank you! :)

Fixed: Cannot run register.sh in CloudShell

I thought it would be straightforward and a good fit to run register.sh in AWS CloudShell but it was not; it was complaining about default region.

I tried setting AWS_DEFAULT_REGION but this did not work...

I dug into register.sh and made the region detection more robust, working from CloudShell (no environment var needed) and also tested on my local CLI, and made a PR:

#53

Unable to run aws ecs update-service --region us-east-1 --cluster xxxxxx --service xxxxxxxx --deployment-configuration '{"deploymentCircuitBreaker":{"enable":true,"rollback":true},"maximumPercent":200,"minimumHealthyPercent":100}' > ./command-output.txt ````

Hi ,
I am unable run the below command using CommandeRunner utility, however I can run it successfully using CLI directly
aws ecs update-service --region us-east-1 --cluster xxxxxx --service xxxxxxxx --deployment-configuration '{"deploymentCircuitBreaker":{"enable":true,"rollback":true},"maximumPercent":200,"minimumHealthyPercent":100}'

./command-output.txt ````

the issue seems to be with the AWS CLI version that's running
on the command runner created instance, I would like to request you to please update the AWS CLI to aws-cli/2.x.x .

Cfn stack create keeps failing with error 'Value '' at 'value' failed to satisfy constraint'

I am trying to find the latest snapshot identifier for a RDS instances. I use this output to restore a DB instance from the snapshot identifier.
I have given RDSFullReadAccess to the commandrunner role

cfn template :

AWSTemplateFormatVersion: "2010-09-09"
Metadata:
  Generator: "cfn"
Description: "test"

Resources:
  LatestSnapshotIdentifier:
    Type: AWSUtility::CloudFormation::CommandRunner
    Properties:
      Command: 'aws rds describe-db-snapshots --region ap-south-1 --db-instance-identifier ap-s1-test-rds-pg-sg-0 --query "DBSnapshots[0].DBInstanceIdentifier" --output text > /command-output.txt'

Expected output:
commandrunner should successfully execute this command

actual output:
getting an error


1 validation error detected: Value '' at 'value' failed to satisfy constraint: Member must have length greater than or equal to 1. (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: ValidationException; Request ID: 341ac0af-5b67-46fd-9cdd-d99504a9e7eb)
--

I tried a bunch of things- in order to see if this is permissions issue,

  1. modified template to run this command -
aws s3 mb s3://test-storage-as-0 --region ap-south-1 > /command-output.txt

failed

aws s3 ls |tail -n 1 > command-output.txt

Failed

3. 
4. ```
aws ec2 describe-instances --instance-ids i-042f829ed0c341724 --region ap-south-1 --profile dev --query="Reservations[0]|Instances[0]|InstanceId

Failed

The overall experience was that cfn failed to work with any aws cli command in general.

SecurityGroupId cannot use multiple values for individual parameter

It looks like SecurityGroupId parameter only support 1 security group id. We would like to pass 2 security group ids as CommaDelimitedList type, but currently implementation doesn't support.

Is there a way to pass multiple security groups for SecurityGroupId parameter?

The command runner EC2 status remains "CREATE_IN_PROGRESS" until it times out and fails.

I believe the command runner EC2 never gets created because the VpcId value is empty. The Role, SecurityGroupId, and SubnetId parameters are correct. See attached screenshot of the command runner parameters.

Command Runner Parameters

There are no default VPC's in the account.

I think if the VpcId was a parameter like the SecurityGroupId and SubnetId it would solve the issue.

Thanks,
John

register.sh fails if uuidgen isn't installed

Because uuidgen is used to name the S3 bucket used for installation, running register.sh fails if uuidgen isn't installed. The error message the user receives is:

Invalid bucket name "": Bucket name must match the regex "^[a-zA-Z0-9.\-_]{1,255}$" or be an ARN matching the regex "^arn:(aws).*:(s3|s3-object-lambda):[a-z\-0-9]*:[0-9]{12}:accesspoint[/:][a-zA-Z0-9\-.]{1,63}$|^arn:(aws).*:s3-outposts:[a-z\-0-9]+:[0-9]{12}:outpost[/:][a-zA-Z0-9\-]{1,63}[/:]accesspoint[/:][a-zA-Z0-9\-]{1,63}$"

It looks like there used to be a --bucket-name parameter that could be passed in but that parameter is commented out in the script. Perhaps we could add the parameter back as a workaround for when uuidgen isn't available? It might also be nice if the error message could explain to the user a little more clearly why it's failing. Currently the message is fairly confusing because it talks about an invalid bucket name, but the user hasn't provided a bucket name so it's hard to know what corrective action to take without opening up the script.

CodeBuild

# - cd "$CODEBUILD_SRC_DIR/my_resource"
# - mvn clean verify --no-transfer-progress
# finally:
# - cat "$CODEBUILD_SRC_DIR/my_resource/rpdk.log"

Your CodeBuild config is not building anything. Please change this to mimic this:

  build:
    commands:
      - pre-commit run --all-files
      - |
        for directory in $CODEBUILD_SRC_DIR/*/; do
          cd "$directory"
          mvn -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B clean verify --no-transfer-progress
        done

DynamoDB - CFT Import error

Created a yaml file for dynamo db, getting below error while trying to import from AWS CFT.

There was an error creating this change set
1 validation error detected: Value '{TableName=}' at 'resourcesToImport.1.member.resourceIdentifier' failed to satisfy constraint: Map value must satisfy constraint: [Member must have length less than or equal to 2048, Member must have length greater than or equal to 1]

DynamoDBTableKnowledge:
Type: "AWS::DynamoDB::GlobalTable"
DeletionPolicy: Retain
Properties:
TableName: "Testdev-Knowledge"
AttributeDefinitions:
- AttributeName: "id"
AttributeType: "N"
KeySchema:
- AttributeName: "id"
KeyType: "HASH"
BillingMode: "PAY_PER_REQUEST"
SSESpecification:
SSEEnabled: true
SSEType: "KMS"
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES

Improve ErrorHandling

Add error handling if there is no default VPC in the region. After the DescribeVpcs API call in the CreateHandler code. Currently it throws Index: 0, Size: 0, because the Java code throws an error as it is trying to access an index that doesn't exist from a response.

Add error handling if the /command-output.txt value is not a non-empty, single word value without quotes.

Add error handling if the InstanceProfile isn't valid.

Add error handling if /command-output.txt isn't specified. Currently it throws 1 validation error detected: Value '' at 'value' failed to satisfy constraint: Member must have length greater than or equal to 1. (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: ValidationExcept ion; Request ID: 35d8c36c-dbaa-4cff-a7cf-dcce65bd53e5)

New functionality: support tagging

Some organisations leverage Service Control Policies SCPs (e.g. for cost control) that enforce putting proper tags on your resources. In such scenarios CommandRunner won't be able to create an EC2 instance.

For this in addition to AWS::EC2::Instance we must use AWS::EC2::LaunchTemplate because Cloudformation puts tags on an EC2 instance in 2 API calls, whereas if you launch your EC2 based on a LaunchTemplate there will be 1 API call.

So we can add another parameter to the configuration file, fetch the tag list and programatically add tag parameters to BaseTemplate.json in CreateHandler.java .

Using Change Sets Causes "Internal Failure"

To reproduce:

Resources:
  CommandRunner:
    Type: 'AWSUtility::CloudFormation::CommandRunner'
    Properties:
      Command: echo 1 > /command-output.txt
  1. Create stack with template above
  2. Modify to "echo 2", create change set
  3. Execute change set
  4. Observe the CommandRunner resource fails with "Internal Failure"

What is the proper way of updating `Command` section when using SAM

Hi

i'm using Cloudformation and SAM for deploying project infrastrcuture.
While using CommandRunner custom resource I faced with an issue of updating/adding/removing Command section.
So it fails to deploy infrastructure with updated Command section with Status reason: The following resource(s) failed to update: [CommandRunner]

The only workaround right now is to comment/uncomment AWSUtility::CloudFormation::CommandRunner in a template every time I need to make a change.

Can you please clarify on the flow I have to follow.

Can't find awsutility-cloudformation-commandrunner.zip file

Hi,

Unfortunately I can't find awsutility-cloudformation-commandrunner.zip file in the project.
The register script failed at the stage : "Copying Schema Handler Package to temporary S3 Bucket"

Do you know how to get ( or generate ) this file before the register execution ?

Thanks

Issue with S3 copy

I am trying to run the code snippet below:
"RunCommandTitle": {
"Type": "AWSUtility::CloudFormation::CommandRunner",
"DependsOn" : "S3Bucket",
"Properties": {
"Command": "aws s3 cp ../LambdaHandler/anomaly_detection.zip s3://krisrajztest/anomaly_detection.zip",
"Role": "EC2ServerFullAccess"
}
}

And getting the error message:
You do not have permissions to make the TerminateInstances API call. Please try again with the necessary permissions.

Can someone help please?

Thanks

Make instance type OR AZ configurable.

At the moment instance type is hardcoded in the code:

This creates an issue in AZs that do not support t3.micro.

Example of the error from AWS Console:

Your requested instance type (t3.micro) is not supported in your requested Availability Zone (us-east-1e). Please retry your request by not specifying an Availability Zone or choosing us-east-1a, us-east-1b, us-east-1c, us-east-1d, us-east-1f. (Service: AmazonEC2; Status Code: 400; Error Code: Unsupported; Request ID: removed; Proxy: null)

Solution:

  • Option 1: make instance type configurable
  • Option 2: make Availability Zone configurable

New functionality: add Teardown parameter

Right now we can do anything in the bash command (Command parameter) - we can fetch values from e.g. RDS, we can use AWS CLI to get some information, initialise databases, make external calls, etc. But we can also create new resources.

For instance Cloudformation does not support Storage Gateway (yet). So I am using CommandRunner to register Storage Gateway programmatically via AWS CLI, e.g.:

  StorageGatewayActivator:
    Type: AWSUtility::CloudFormation::CommandRunner
    Properties:
      SubnetId: !Ref SubnetId
      Role: !Ref ActivatorInstanceProfile
      LogGroup: !Ref ActivatorLogGroup
      Command: !Sub |
        curl -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
        unzip awscliv2.zip
        sudo ./aws/install
        alias aws="/usr/local/bin/aws"
        key=`curl "http://${StorageGateway.PrivateIp}/?gatewayType=FILE_S3&activationRegion=${AWS::Region}&no_redirect"`
        gw=`aws --region ${AWS::Region} storagegateway activate-gateway \
           --activation-key $key \
           --gateway-type FILE_S3 \
           --gateway-name ${AWS::StackName} \
           --gateway-timezone GMT+1:00 \
           --gateway-region ${AWS::Region} | jq -r .GatewayARN`
        sleep 30
        diskid=`aws --region ${AWS::Region} storagegateway list-local-disks --gateway-arn $gw | jq -r .Disks[0].DiskId`
        aws --region ${AWS::Region} storagegateway add-cache \
          --gateway-arn $gw \
          --disk-ids $diskid | jq -r .GatewayARN > /command-output.txt
        aws --region ${AWS::Region} storagegateway update-gateway-information \
          --gateway-arn $gw \
          --cloud-watch-log-group-arn ${StorageGWLogGroup.Arn} \
          --gateway-name ${AWS::StackName}
        aws --region ${AWS::Region} storagegateway create-nfs-file-share \
          --client-token token-$RANDOM \
          --gateway-arn $gw \
          --role ${StorageGatewayRole.Arn} \
          --location-arn ${BucketArn} \
          --client-list ${NfsClientIp} \
          --squash NoSquash \
          --vpc-endpoint-dns-name ${S3VpcEndpointDns} \
          --file-share-name ${AWS::StackName} \
          --bucket-region ${AWS::Region}
    DependsOn: StorageGatewayEC2

Now suppose I want to remove the stack. The only thing Cloudformation will remove is the Output value from Parameter Store. But it won't deactivate Storage gateway, nor will it detach the nfs file share.

So what we can do, is along with the Command parameter we can introduce another parameter e.g. TeardownCommand where we can add some teardown logic (bash script) and start a new CommandRunner stack (inside DeleteHandler.java).

Multiple Outputs from the command

Hello Everyone,
I'm running a command that gives json object as output
I'm writing that to command-output.txt file

Imagine I wrote {"key1": "value1", "key2": "value2"} to the file

But when I tried to access the output as !GetAtt Command.Output.a
I'm getting below error

Requested attribute Output.a does not exist in schema for AWSUtility::CloudFormation::CommandRunner

But when I wrote !GetAtt Command.Output as output got {\ as output

Please give me a solution where I can access multiple outputs from a command

Unable to run a command with my yaml file

Hi,

I have cloned this and selected all the setting correctly as directed in the documentation. While I try to create stack from my yaml file, it creates a dependent stack which is trying to create an ec2 instance but fails to create it even though EC2 full access is provided to the role.

The error I receive is Unable to resolve following error "waitcondition timed out. received 0 conditions when expecting 1"

The following is the yaml I have used to create a stack which isn't getting created.
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Keyid:
Description: "Key Id for the KMS key to enable key rotation"
Default: 8eef2781-9753-47fd-9ee4-892f16e3d973
Type: String
RegionForKMSkey:
Description: "Please enter the Region where your KMS key is present"
Default: us-east-1
Type: String
InstanceRole:
Description: "Please enter the Role Name that Ec2 instance will assume to execute the command"
Default: ""
Type: String
Resources:
Commandrunner:
Properties:
Command: !Sub 'aws kms enable-key-rotation --key-id ${Keyid} --region ${RegionForKMSkey} && echo "Key rotation enabled successfully" > /command-output.txt'
Role: !Ref InstanceRole
Type: "AWSUtility::CloudFormation::CommandRunner"
Outputs:
Commands:
Description: "Echo command Text"
Value:
"Fn::GetAtt": Commandrunner.Output

ec2:TerminateInstances already included in execution role policy

I tried to use in our company, but with my restricted access I ended up with an error: You do not have permissions to make the TerminateInstances API call. Please try again with the necessary permissions.

I checked your code and found out, that the error is thrown because You are trying to add ec2:TerminateInstances in CreateHandler.java again. But ec2:TerminateInstances permissions are already added in execution role policy. Can You please delete that of the code? Thanks.

Incorrect logical resource name in some README examples

The README shows the following differences among its code blocks:

First form (2 occurrences):

Resources:
  CommandRunner: # <-- NOTE
    # ...

Outputs:
  Output:
    Value: !GetAtt "Command.Output"

Second form (4 occurrences):

Resources:
  Command:
    # ...

Outputs:
  Output:
    Value: !GetAtt "Command.Output"

I'm 99% sure that for !GetAtt "Command.Output" to work, the resource must be logically named Command (second form), not CommandRunner (first form). But there's a lot of magic here, so I may be missing something.

Which is correct?

Template contains errors.: Template format error: Unrecognized resource types: [AWSUtility::CloudFormation::CommandRunner]

Hi,

In Cloudformation I keep getting this error

Template` contains errors.: Template format error: Unrecognized resource types: `[AWSUtility::CloudFormation::CommandRunner]

This is my CloudFormation template

AWSTemplateFormatVersion: 2010-09-09
Resources:
  Command:
    Type: 'AWSUtility::CloudFormation::Command'
    Properties:
      Command: aws s3 ls | sed -n 1p | cut -d " " -f3 > /command-output.txt
      Role: <ADDED_IAM_ROLE>
Outputs:
    Output:
        Description: The output of the CommandRunner.
        Value: !GetAtt Command.Output

I have added IAM permissions as per documentation

                  "cloudformation:ValidateTemplate",
                  "cloudformation:GetTemplateSummary",
                  "cloudformation:*",
                  "s3:CreateBucket",
                  "s3:DeleteBucket",
                  "s3:PutBucketPolicy",
                  "s3:PutObject",
                  "cloudformation:RegisterType",
                  "cloudformation:DescribeTypeRegistration",
                  "iam:createRole"
                ],
                "Resource": ["*"]

Tried Role ARN as well

Any help appreciated :)

Deploy Error

Error Message

1 validation error detected: Value '' at 'value' failed to satisfy constraint: Member must have length greater than or equal to 1. (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: ValidationExcept
ion; Request ID: 35d8c36c-dbaa-4cff-a7cf-dcce65bd53e5)

CloudFormation Template

Parameters:
  CommandRole:
    Type: String
    Description: 'https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner#role'

  Command:
    Type: String
    Description: 'https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner#command'

  KeyId:
    Type: String
    Description: 'https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner#keyid'

Resources:
  Command:
    Type: 'AWSUtility::CloudFormation::CommandRunner'
    Properties:
      Command: !Ref Command
      Role: !Ref CommandRole
      KeyId: !Ref KeyId

Failing when CommandRunner is run in a private subnet

I am trying to run CommandRunner in a private subnet with the following definition:

AWSTemplateFormatVersion: 2010-09-09
Description: AWS CLI version


Resources:
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/command-runner/${AWS::StackName}/"
      RetentionInDays: 14

  Role:
    Type: AWS::IAM::Role
    Properties:
      Description: "Role assumed by Command Runnner"
      MaxSessionDuration: 14400
      Path: "/"
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref Role

  CommandRunner:
    Type: AWSUtility::CloudFormation::CommandRunner
    Properties:
      LogGroup: !Ref LogGroup
      Role: !Ref InstanceProfile
      SubnetId: subnet-029045502cbb1957b
      Command: |
        aws --version 2>&1 \
          | tail -1 \
          | head -n 1 \
          > /command-output.txt


Outputs:
  AwsCliVersion:
    Description: AWS CLI version
    Value: !GetAtt CommandRunner.Output

The Cloudformation stack fails with the following error (for the CommandRunner local resource name):

Resource handler returned message: "ParameterValue for ParameterKey SecurityGroupId is 
required (Service: AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; 
Request ID: 40883ed7-9c82-4c7a-9680-a725d511af23; Proxy: null) 400 ValidationError 
Client 40883ed7-9c82-4c7a-9680-a725d511af23" (RequestToken: 
1e4386ca-6b22-bbf0-3fb8-db6c14321538, HandlerErrorCode: InternalFailure)

According to BaseTemplate.json:

  "Resources": {
    "SecurityGroup": {
      "Condition": "CreateSecurityGroup",
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupName": {
          "Fn::Sub": "aws-cloudformation-commandrunner-temp-sg-${AWS::StackName}}"
        },
        "GroupDescription": "A temporary security group for AWS::CloudFormation::Command",
        "SecurityGroupEgress": [
          {
            "CidrIp": "0.0.0.0/0",
            "FromPort": -1,
            "IpProtocol": -1,
            "ToPort": -1
          }
        ],
        "VpcId": {
          "Ref": "VpcId"
        }
      }
    },

a security group will be created if the CreateSecurityGroup condition is met:

  "Conditions": {
    "CreateSecurityGroup": {
      "Fn::Equals": [
        {
          "Ref": "SecurityGroupId"
        },
        "empty"
      ]
    },

So, that means that the error raised when deploying my CommandRunner example template (SecurityGroupId is
required) doesn't make any sense. The stack should be deployed normally without any error.

I am reporting this as a bug.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.