Giter Club home page Giter Club logo

cloudformation-cli's Introduction

CloudFormation CLI

AWS CloudFormation CLI

The CloudFormation CLI (cfn) allows you to author your own resource providers, hooks, and modules that can be used by CloudFormation.

Usage

Documentation

Primary documentation for the CloudFormation CLI can be found at the AWS Documentation site.

Installation

This tool can be installed using pip from the Python Package Index (PyPI). It requires Python 3. For resource and hook types, the tool requires at least one language plugin. Language plugins are not needed to create a module type. The language plugins are also available on PyPI and as such can be installed all at once:

pip install cloudformation-cli cloudformation-cli-java-plugin cloudformation-cli-go-plugin cloudformation-cli-python-plugin cloudformation-cli-typescript-plugin

Command: init

To create a project in the current directory, use the init command. A wizard will guide you through the creation.

cfn init

Command: generate

To refresh auto-generated code, use the generate command. Usually, plugins try to integrate this command in the native build flow, so please consult a plugin's README to see if this is necessary. In a module project, this will regenerate the module schema.

cfn generate

Command: submit

To register a resource provider, module, or hook in your account, use the submit command.

cfn submit
cfn submit --dry-run #prepares schema handler package without submitting for registration
cfn submit --set-default # if successfully registered, set submitted version to be the new default version

Command: package

This is to create a schema handler package without submitting equivalent to cfn submit --dry-run

cfn package

Command: test

To run the contract tests for a resource type, use the test command.

cfn test
cfn test -- -k contract_delete_update # to run a single test
cfn test -- --tb=long # exhaustive, informative traceback formatting
cfn test --enforce-timeout 60  # Read/List handler timeout (Create/Update/Delete handler timeout is twice the Read/List handler timeout)
cfn test --enforce-timeout 60 -- -k contract_delete_update # combine arguments
cfn test --log-group-name cw_log_group --log-role-arn log_delivery_role_arn # Handler logs generated by contract tests will be delivered to the specified cw_log_group using the credentials from log_delivery_role_arn

Note:

  • To use your type configuration in contract tests, you will need to save your type configuration json file in ~/.cfn-cli/typeConfiguration.json or specify the file you would like to use

    • --typeconfig ./myResourceTypeConfig.json
    • --typeconfig /test/myresource/config1.json
    • --typeconfig C:\MyResource\typeconf.json
  • To use propertyTransform in schema, you will need to install PYJQ. This feature will not be available to use with contract tests on Windows OS

Install PYJQ for Linux system

yum install autoconf automake libtool
pip install pyjq

Install PYJQ for macOS system

brew install autoconf automake libtool
brew install jq
pip install pyjq

Install PYJQ for Ubuntu system

pip install pyjq

Command: validate

To validate the schema, use the validate command.

This command is automatically run whenever one attempts to submit a resource, module, or hook. Errors will prevent you from submitting your resource/module. Module fragments will additionally be validated via cfn-lint (but resulting warnings will not cause this step to fail).

cfn validate

Command: build-image

To build an image for a resource type. This image provides a minimalistic execution environment for the resource handler that does not depend on AWS Lambda in anyway. This image can be used during cfn invoke and cfn test instead of using sam cli.

cfn build-image
cfn build-image --image-name my-handler --executable target/myjar.jar

The resulting image can be run in a container by executing the following command:

docker run IMAGE_NAME HANDLER_ENTRYPOINT PAYLOAD
docker run my-test-resource com.my.test.resource.ExecutableHandlerWrapper PAYLOAD_JSON # Example for a java based-project

Development

For developing, it's strongly suggested to install the development dependencies inside a virtual environment. (This isn't required if you just want to use this tool.)

python3 -m venv env
source env/bin/activate
pip install -e . -r requirements.txt
pre-commit install

If you're creating a resource or hook type, you will also need to install a language plugin, such as the Java language plugin, also via pip install. For example, assuming the plugin is checked out in the same parent directory as this repository:

pip install -e ../cloudformation-cli-java-plugin
# run all hooks on all files, mirrors what the CI runs
pre-commit run --all-files
# run unit tests only. can also be used for other hooks, e.g. black, flake8, pylint-local
pre-commit run pytest-local

If you want to generate an HTML coverage report afterwards, run coverage html. The report is output to htmlcov/index.html.

Plugin system

New language plugins can be independently developed. As long as they declare the appropriate entry point and are installed in the same environment, they can even be completely separate codebases. For example, a plugin for Groovy might have the following entry point:

entry_points={
    "rpdk.v1.languages": ["groovy = rpdk.groovy:GroovyLanguagePlugin"],
},

Plugins must provide the same interface as LanguagePlugin (in plugin_base.py). And they may inherit from LanguagePlugin for the helper methods - but this is not necessary. As long as the class has the same methods, it will work as a plugin.

Supported plugins

Resource Types Supported Plugins

Language Status Github PyPI
Java Available cloudformation-cli-java-plugin cloudformation-cli-java-plugin
Go Available cloudformation-cli-go-plugin cloudformation-cli-go-plugin
Python Available cloudformation-cli-python-plugin cloudformation-cli-python-plugin
TypeScript Available cloudformation-cli-typescript-plugin cloudformation-cli-typescript-plugin

Hook Types Supported Plugins

Language Status Github PyPI
Java Available cloudformation-cli-java-plugin cloudformation-cli-java-plugin
Python Available cloudformation-cli-python-plugin cloudformation-cli-python-plugin

License

This library is licensed under the Apache 2.0 License.

Community

Join us on Discord! Connect & interact with CloudFormation developers & experts, find channels to discuss and get help for our CLI, cfn-lint, CloudFormation registry, StackSets, Guard and more:

Join our Discord

cloudformation-cli's People

Contributors

adam-daily avatar akifrafique avatar ammokhov avatar anshikg avatar aygold92 avatar brianwithay21 avatar dependabot[bot] avatar github-actions[bot] avatar himanshs23 avatar hyyrkm avatar johnttompkins avatar kddejong avatar malikatalla-aws avatar marc-1010 avatar mmaeng avatar mrinaudo-aws avatar nina-ctrlv avatar omkhegde avatar patmyron avatar prerna-p avatar rajdnp avatar rjlohan avatar saieshwarm avatar stilvoid avatar sungkkim avatar tobywf avatar waela avatar yueful27 avatar yunhao-jiao avatar zjinmei 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  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  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

cloudformation-cli's Issues

make type or $ref required for each property

every property needs to know for sure what type it is, even if you use oneOf to add additional validation. For example, the following currently would be evaluted to an object type, when it should be a string (a few examples did this, like Kinesis Stream).

{
    "type": "object",
    "properties": {
        "Test": {
            "anyOf": [
                { "$ref": "#/definitions/SomeStringWithRegex"},
                { "$ref": "#/definitions/SomeOtherStringWithRegex"}
            ]
        }
    }
}

The following should work, though we've apparently not been able to get it working:

"anyOf": [
   { "required": ["type"]},
   { "required": ["$ref"] }
]

add sample schema to init command

The init command should generate a simple sample schema, so that the whole CLI can work end to end without doing anything. This will also jump start development.

The command could potentially take the resourceType so that it could auto populate that in the schema

`Init` command should cleanup previous codegen runs

When playing with the init wizard, I noticed that if I re-run init in the same repo and change my resource type name, the generated sources from a prior execution are left in place (not overwritten or removed) which can lead to broken build.

To repro;

uluru-cli init
a::b::c
mvn package

Builds OK.

uluru-cli init
My::Actual::Resource
mvn package

Fails, as the src from a/b/c is left in the repo. Not a biggie, just a usability enhancement.

Use identifiers correctly in example schemas

identifiers was introduced in #47 , but I think our example schemas are using it incorrectly, since specifying multiple values is equivalent to a compound identifier.

  • AWS::SQS::Queue example says: "identifiers": ["#/properties/Arn", "#/properties/QueueName", "#/properties/URL"], however a combination of these doesn't make sense, since either Arn or URL (maybe even QueueName) is enough to uniquely identify the resource (L106-L110)
  • AWS::EC2::Instance doesn't have it at all
  • AWS::S3::Bucket is similar to Queue, BucketName is already globally unique (L954-L958)

Contract Event Listener Logging and Error handling

Add logging to the event listener that listens for progress events from handlers. Also add better handling of unexpected progress event type i.e. if a posted event is not a json object. Currently we are sending an error response back, whereas it may be better to record the error on the server side

On build, run `generate`

Automatically run generate when the user builds the Java project to avoid desync between schema and code. Ideally, call generate as part of the maven build step. If that isn't possible, add a pre-build step to the IntelliJ project.

Resource generation outstanding issues

The current resource generator in #104 handles simpler cases of resource generation. The below items are necessary to bring the generator to a more operable state that can handle most if not all valid resource definition schemas.

  • Refs are not handled. This is fine, but needs some kind of step prior to make sure it works
  • Type keywords. Keywords that can be specified in jsonschema draft 07 for primitive types should be accounted for in resource generation. #104 handles some of this but not all (e.g. minLength and maxLength is not supported for arrays).
  • Assuming type is a string. We assume the schema type is a string and cannot be an array. Arrays are valid values for type keys and we need to generate values based off all of the types listed.
  • String formats. jsonschema has a "format" keyword that allows for specific string formats like json pointers, domain names, email addresses, etc. that should be able to be generated by the resource generator. The logic to do this is in place, but we need to construct regular expression strategies that we can map to format names.
  • Options to generate more than the required properties. Currently the generator only generates those that are required. Having an option to generate a maximal set of properties would be beneficial for testing the robustness of handlers.
  • Combiners. Currently allOf and anyOf are not supported by the generator. anyOf should be a simple addition because it is handled in the same way as oneOf. allOf will require to merge the child schemas.
  • Const and enum. Constant values and enum schemas are not supported currently.
  • Needs to only generate a resource blob (i.e. the stuff under properties)
  • Refactor generation functions for readability.
  • #287

Also, some research needs to be done to see if the flattener and resource generator can be combined in some way. They are both walking the schema in a similar way, so it would be nice to remove duplicate implementations of this to lessen the amount of code to be maintained.

disallow circular references

I'm not necessarily sure we should do this as this may be a valid use case; in fact, AWS::EMR::Cluster does this. However, the topic was up for debate, so I will raise an issue about it.

Package SAM Handler Template

A SAM template is needed for the package command in the rpdk. This should be generated during either the init or generate stages, and it should contain a local file path to the jar location specified in the pom by the artifact id and output directory. This should also include sufficient roles for cloudformation to execute the lambda function

remove additionalItems and make items only 1 schema

additionalItems is very weird property, makes little sense, and doesn't need to be used for a resource schema.
details are here https://json-schema.org/understanding-json-schema/reference/array.html

This goes hand in hand with removing multiple schemas for the items array. An ordered array of different schema objects (and then the rest of the objects being specified using the additionalItems schema) is very confusing for both developers and customers. The best way to model this would be with key:value pairs

Include `createOnly` semantic in meta-schema

An additional semantic (like readOnly and writeOnly) should be expressed in the schema to describe those properties which can be mutated post-create for a resource.

Alternately, the semantic can be described as createOnly to define those properties of a resource which are write-once (or "immutable" in CloudFormation's current resource specification parlance).

NOTE: This semantic describes those properties of a resource which are documented as "Update requires: Replacement".

Change resource input format for contract tests

Currently the handler request interface calls for resourceProperties when Creating/Updating a file. For the test command, the user passes a json object of properties with no reference to the resource type into the command. E.g a for a Queue, the test command expects {"QueueName": "Something"} Changing this input to reflect the resource schema that CloudFormation accepts would be less confusing to users, so the SQS Queue input would become { "Type" : "AWS::SQS::Queue", "Properties" : { "QueueName": Something } }

Restrict use of sub-properties.

To simplify resource definition authoring, we could restrict the use of sub-properties and require that sub-property objects are defined in the definitions block of the document. This would encourage re-use, avoid typos/errors on repeat sub-properties, and generally reduce nesting - making for simpler authoring experience and a consistent schema to read.

Schema versioning

How will schemas be versioned, and how will this fit in with the package and generate steps?

Test Command Verbosity argument

When specifying "-v" on the test subcommand, the cli says that the verbosity argument is not recognized. The verbosity argument parser is being added at the wrong level and is being ignored. Need to add the argument at the right level so that this argument works for all test subcommands

project-settings command not working

The project-settings option is currently broken.

Traceback (most recent call last):
  File "/usr/local/bin/uluru-cli", line 11, in <module>
    load_entry_point('aws-cloudformation-rpdk', 'console_scripts', 'uluru-cli')()
  File "aws-cloudformation-rpdk/src/rpdk/cli.py", line 59, in main
    args.command(args)
  File "aws-cloudformation-rpdk/src/rpdk/project_settings.py", line 13, in project_settings
    settings = f.read().decode("utf-8")
AttributeError: 'str' object has no attribute 'decode'

Idempotency Contract Tests

We need to test if handlers are idempotent. For Create, Read, and Delete operations after requests are verified as successful, send an identical request with the same token and ensures it returns the same result.

Contract tests must not leak resources

  • Tests should delete resources even if an exception occurred (context manager or try...finally)
  • These deletes shouldn't ever fail, but can log if we couldn't delete the resource
  • Generally err on the side of deleting

Move to stable release of jsonschema

#16 needs a pre-release version of jsonschema. For now, we're using pip to install that. Once a stable version is released, we need to undo changes to the README and buildspec.yml, as well as pin the jsonschema version in setup.py so people will always have a version that supports draft-6.

Generate Resource Examples for contract tests

Currently, a developer needs to provide a resource example when running contract tests. A more convenient user experience would be to generate valid examples based off the schema that they create/provide.

Add extra validation outside JSON Schema

As discussed in #45, it would be nice to provide validation above and beyond what's expressible in JSON Schema, e.g. the mutually exclusiveness of readOnly and writeOnly properties.

Refine `init` / `generate` behaviours

I realised after posting #60, that the init command is what sets up the workspace (#protip: think first, PR second).

However that got me thinking; now that I'm going through this workflow, I'm realising there's some deficiencies we should address. Currently, init takes language and output-directory args. As goes generate. Perhaps it would be neater if we had a single init command which setup a workspace with language of your choice, and moved generate to an implicit build action for the initialised projects.

I think 2 steps is one too many, and there's too many ways to misalign your CLI args. And since I was one of the designers of the current workflow and I can't get it right in usage, that's not a good sign. 😆

Require examples for complex properties

For the contract tests, it would be ideal if we could generate properties from the schema. For most properties, this isn't hard (e.g. generating a random integer with min and max constraints). The benefit is we could use hypothesis for this, and maybe test e.g. negative integers to see if they are valid.

However, e.g. a string with regex validation would make this difficult. One thing we could do is try and generate e.g. 100 random strings. If less than 80 pass validation, then we could require e.g. 3 examples. Then we could auto-generate create requests + update requests and have one spare.

Fast sanely when credentials are invalid

On commands that require interaction with AWS (package and submit), we should fast fail and report some error to the user if their credentials are invalid. Currently the user would have to look in the logs to see this result. A function that checks credentials could be added before these command execute their main portions, and this function could inform the user of no credentials or bad credentials.

Introduce `identifiers` semantic in meta-schema

The identifiers semantic is a top-level metadata item supplied as a list of json-pointers to the properties used to uniquely identify the resource.

Note that multiple properties may serve as identifiers. For example, AWS::ECS::Service is uniquely identified by “ServiceName” and “Cluster”, because a ServiceName is only unique within a given Cluster.

don't allow patternProperties when properties is used

It doesn't make sense for a SubObject to have some properties defined, and others undefined. If some of the properties are undefined, it's an additional arbitrary map of properties, which itself should be a property.

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.