{ "info": { "author": "@bincyber", "author_email": "bincyber@users.noreply.github.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: MacOS", "Operating System :: POSIX", "Operating System :: Unix", "Programming Language :: Python", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development :: Quality Assurance", "Topic :: Software Development :: Testing", "Topic :: System :: Systems Administration" ], "description": "# Pulumi Integration Test Framework\n\n[![License](https://img.shields.io/badge/License-Apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![Python](https://img.shields.io/badge/Python-3.7+-blue.svg)](#)\n[![Version](https://img.shields.io/badge/Pypi-v0.0.4-orange.svg)](#)\n[![Status](https://img.shields.io/badge/Status-alpha-yellow.svg)](#)\n[![Coverage Status](https://coveralls.io/repos/github/bincyber/pitfall/badge.svg?branch=master)](https://coveralls.io/github/bincyber/pitfall?branch=master)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=bincyber_pitfall&metric=alert_status)](https://sonarcloud.io/dashboard?id=bincyber_pitfall)\n[![CircleCI](https://circleci.com/gh/bincyber/pitfall.svg?style=svg)](https://circleci.com/gh/bincyber/pitfall)\n\n_pitfall_ is a Python integration testing framework for [Pulumi](https://github.com/pulumi/pulumi) Infrastructure as Code. It enables and encourages end to end testing to avoid errors, assumptions, and other pitfalls.\n\n## Installation\n\n_pitfall_ can be installed via pip:\n\n\t$ pip install pitfall\n\n## Compatibility\n\n_pitfall_ has been tested against versions 1.2.0 - 1.4.0 of Pulumi and will strive to work with the latest Pulumi release.\n\n**Warning**: this is alpha software. There are no guarantees of backwards compatibility.\n\n## Usage\n\n_pitfall_ is intended to be used in integration tests to verify the desired state of infrastructure provisioned by Pulumi.\n\nIt will do the following:\n\n* create a temp directory to store Pulumi code and state\n* copy the contents of the current directory (and all subdirectories) to the temp directory\n* move into the temp directory\n* create a new Pulumi project file: `Pulumi.yaml`\n* create a new Pulumi stack file: `Pulumi..yaml`\n* initialize a new Pulumi state file in `.pulumi/`\n* install Pulumi plugins\n* execute `pulumi preview`\n* execute `pulumi up`\n* execute `pulumi destroy`\n* delete the temp directory\n\n_pitfall_ supports a [context manager](https://docs.python.org/3/reference/datamodel.html#context-managers) to automatically do the above.\n\n_pitfall_ does not use the Pulumi Service backend.\n\n### Examples\n\n1. [Basic S3 Example](https://github.com/bincyber/pitfall/blob/master/examples/basic-s3/README.md) - provision a AWS S3 bucket and verify that required tags have been set on it\n2. [Advanced S3 Example](https://github.com/bincyber/pitfall/blob/master/examples/advanced-s3/README.md) - provision a AWS S3 bucket to host a static website and verify that it's functional\n3. [AWS VPC ComponentResource Example](https://github.com/bincyber/pitfall/blob/master/examples/aws-vpc/README.md) - provision a AWS VPC using a ComponentResource\n\n### Features\n\n#### Context Manager\n\n_pitfall_ includes a context manager to automatically setup a test and execute the Pulumi workflow:\n\n```python\nfrom pitfall import PulumiConfigurationKey, PulumiIntegrationTest\n\ndirectory = '/path/to/pulumi/code'\nopts = PulumiIntegrationTestOptions(cleanup=True, preview=True, up=True, destroy=True)\n\nwith PulumiIntegrationTest(directory=directory, opts=opts) as t:\n pass\n```\n\nThe context manager will create a temporary directory for the test, copy the entire contents of `directory` to the temporary directory, generate the Pulumi Project and Stack files, initialize a new Pulumi local state file, install Pulumi plugins, and execute `pulumi preview`, `pulumi up`, and `pulumi destroy`. Upon exit, the context manager will delete the temporary directory.\n\nTo control automatic execution of Pulumi commands, temporary directory deletion, and verbosity, set desired options with [PulumiIntegrationTestOptions](https://github.com/bincyber/pitfall/blob/master/pitfall/core.py#L36).\n\n#### Configuration and Secrets\n\n_pitfall_ supports Pulumi [Configuration and Secrets](https://www.pulumi.com/docs/intro/concepts/config/):\n\n```python\nfrom pitfall import PulumiConfigurationKey, PulumiIntegrationTest\nimport os\n\ndbpassword = os.urandom(32)\n\nconfig = [\n PulumiConfigurationKey(name='aws:region', value=\"us-east-1\"),\n PulumiConfigurationKey(name='dbpassword', value=dbpassword, encrypted=True)\n]\n\nt = PulumiIntegrationTest(config=config)\n\nt.setup()\n```\n\nWhen `t.setup()` is called, the Pulumi stack file (`Pulumi..yaml`) will automatically be created with the supplied configuration. Configuration keys are automatically namespaced with the name of the Pulumi Project and Secrets are encryped using the password set by the environment variable `PULUMI_CONFIG_PASSPHRASE`:\n\n```\n$ cat Pulumi.pitf-stack-91c13928d11648be.yaml\n\nconfig:\n aws:region: us-east-1\n pitf-project-99c24db7cc324cf9:dbpassword:\n secure: v1:6UEXewJReYiPCgrg:fOFTB4ODFyZB0bvHA2lhoZJ3khCOQCkX8n5OhLXjgSECbu+WrcIQ+wl0HaZhZ/4v\nencryptionsalt: v1:GEHe83S30O0=:v1:s8vb7cVFSz64pUmv:Ff5AbbcbTSim8cBwDCQCwraGHEQQ/A==\n```\n\n#### Pulumi State\n\n_pitfall_ exposes the Pulumi state as a Python object [PulumiState](https://github.com/bincyber/pitfall/blob/master/pitfall/state.py#L39). Both the current and previous state are accessible as Class properties. The resources in the current state file can be viewed and searched:\n\n```python\nt = PulumiIntegrationTest()\n\nresources = t.state.resources\n\nfor i in resources:\n print(i.urn, i.id, i.type)\n\nresources.providers # {\"pulumi:providers:aws\": 1}\n\nresources.types # {\"aws:s3/bucket:Bucket\": 1, \"pulumi:pulumi:Stack\": 1}\n\nresults = resources.lookup(key=\"type\", value=\"aws:s3/bucket:Bucket\")\n\ns3_bucket = results[0]\n\nprint(s3_bucket.id) # pitfall-basic-example-649ce5f\n\nprint(s3_bucket.outputs[\"arn\"]) # arn:aws:s3:::pitfall-basic-example-649ce5f\n```\n\n#### Stack Outputs\n\n_pitfall_ collects Pulumi [Stack outputs](https://www.pulumi.com/docs/intro/concepts/programming-model/#stack-outputs), so that they can be accessed in tests:\n\n```python\nwith PulumiIntegrationTest(directory=directory, opts=opts) as t:\n outputs = t.get_stack_outputs()\n\n s3_bucket_arn = outputs[\"s3_bucket\"][\"arn\"]\n```\n\n#### Resources Graph\n\n_pitfall_ can export the resources in the Pulumi state file as a DOT file:\n\n```python\nwith PulumiIntegrationTest(directory=directory, opts=opts) as t:\n resources = t.state.resources\n resources.export_dotfile(filename='~/graph.dot')\n```\n\nView the DOT file:\n```\n$ cat ~/graph.dot\n\ndigraph tree {\n \"pulumi:pulumi:Stack\";\n \"aws:s3/bucket:Bucket (pitfall-basic-example-649ce5f)\";\n \"pulumi:pulumi:Stack\" -> \"aws:s3/bucket:Bucket (pitfall-basic-example-649ce5f)\";\n}\n```\n\nThis DOT file can then be viewed using the `dot` command or online at [webgraphviz.com](http://www.webgraphviz.com/).\n\n#### Test Helpers\n\n_pitfall_ includes useful helper classes and functions that can be used in integration tests. These can be found under [pitfall/helpers](https://github.com/bincyber/pitfall/tree/master/pitfall/helpers).\n\n\n### Environment Variables\n\nThe following environment variables are supported:\n\n| Environment Variable | Default Value | Description\n| -------- | -------- | --------\n| PULUMI_HOME | `~/.pulumi` | the location of Pulumi's home directory\n| PULUMI_CONFIG_PASSPHRASE | `pulumi` | the password for encrypting secrets\n\nIf they are set, they will be inherited by _pitfall_.\n\n\n## Documentation\n\nTODO\n\n## Testing\n\n[nose2](http://nose2.readthedocs.io/en/latest/) is used for unit and integration testing.\n\n`pulumi` must be installed for tests to pass.\n\n### Unit Tests\n\nUnit tests are located in `/tests`.\n\nTo run the unit tests:\n\n $ make test\n\n### End to End Tests\n\nEnd to end tests are located in `e2e/`.\n\n1. testing using [localstack](https://github.com/localstack/localstack)\n\ne2e tests that use localstack are located in `e2e/localstack`. These tests require localstack running locally in a container.\n\nTo run localstack:\n\n $ make run-localstack\n\nRun the e2e tests:\n\n $ make e2e-test-localstack\n\n\n2. testing using [AWS](https://aws.amazon.com/)\n\ne2e tests that use AWS are located in `e2e/aws`. These tests require an AWS account and valid AWS API keys.\n\nRun the e2e tests:\n\n $ make e2e-test-aws\n\n\n## Contributing\n\nWe encourage the following contributions at this time: user feedback, documentation, bug reports, and feature requests.\n\n## Acknowledgement\n\n_pitfall_ was built upon the Python libraries listed in its [Pipfile](https://github.com/bincyber/pitfall/blob/master/Pipfile).\n\n## License\n\nCopyright 2019 Ali (@bincyber)\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/bincyber/pitfall", "keywords": "infrastructure-as-code testing devops pulumi", "license": "Apache", "maintainer": "", "maintainer_email": "", "name": "pitfall", "package_url": "https://pypi.org/project/pitfall/", "platform": "any", "project_url": "https://pypi.org/project/pitfall/", "project_urls": { "Homepage": "http://github.com/bincyber/pitfall" }, "release_url": "https://pypi.org/project/pitfall/0.0.4/", "requires_dist": [ "anytree (==2.7.2)", "boto3 (==1.10.9)", "pycryptodomex (==3.9.0)", "PyYAML (==5.1.2)" ], "requires_python": ">=3.7", "summary": "An integration testing framework for Pulumi Infrastructure as Code", "version": "0.0.4", "yanked": false, "yanked_reason": null }, "last_serial": 6166653, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "3c8bb69b24ae9e4a5a862a51fa0ae0aa", "sha256": "a9688b2daeffa82baf1b35c022736023ff4cd68b170e57b858d43111a60bfe10" }, "downloads": -1, "filename": "pitfall-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "3c8bb69b24ae9e4a5a862a51fa0ae0aa", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 22304, "upload_time": "2019-10-28T10:45:56", "upload_time_iso_8601": "2019-10-28T10:45:56.888466Z", "url": "https://files.pythonhosted.org/packages/27/df/7866d0d33b55a52b2a6113103ca74e3ade5ee8f87eb7b00c55076c81660e/pitfall-0.0.1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "78cdcd136aa84210e38fd44d136c586b", "sha256": "99a9344ea92563cfca5c30e1b7c509645a8be230e3c304b0fd2e892ac9e82051" }, "downloads": -1, "filename": "pitfall-0.0.1.tar.gz", "has_sig": false, "md5_digest": "78cdcd136aa84210e38fd44d136c586b", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 16382, "upload_time": "2019-10-28T10:45:59", "upload_time_iso_8601": "2019-10-28T10:45:59.065388Z", "url": "https://files.pythonhosted.org/packages/73/1b/40cc95bd97080526cb4219dceae8acc6103c415bec24306f1a07dbe6e06b/pitfall-0.0.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "8a823d527f7474d7915ba1ce27d6826f", "sha256": "7a1529b23427d8af4b6cbc7c71bb2fecbb26e3d7fee69b00873826c4a427dafd" }, "downloads": -1, "filename": "pitfall-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "8a823d527f7474d7915ba1ce27d6826f", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 24321, "upload_time": "2019-11-05T15:52:05", "upload_time_iso_8601": "2019-11-05T15:52:05.155028Z", "url": "https://files.pythonhosted.org/packages/1e/6b/5e0e99927bde549fdfc8ae30a13eda38ea503029d4c54ee47f6626879961/pitfall-0.0.2-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "abd339cfc084244398bc0f5905a37b46", "sha256": "0d3b2a85c9e6cd9e69cfc5e3ad9c2088a232c40d59171ab19fa5c36f2c2bec30" }, "downloads": -1, "filename": "pitfall-0.0.2.tar.gz", "has_sig": false, "md5_digest": "abd339cfc084244398bc0f5905a37b46", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 19794, "upload_time": "2019-11-05T15:52:07", "upload_time_iso_8601": "2019-11-05T15:52:07.377542Z", "url": "https://files.pythonhosted.org/packages/58/a5/08927e6467642225378c5f681526cb48a236d29bd087c7ffb862f857c476/pitfall-0.0.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "39a3727df62e08325e924d89d866da30", "sha256": "91398d5f4c08a2b15f74f640533108b4aa1a644110c61dedb6ff2326ca39dcb6" }, "downloads": -1, "filename": "pitfall-0.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "39a3727df62e08325e924d89d866da30", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 23004, "upload_time": "2019-11-19T22:50:57", "upload_time_iso_8601": "2019-11-19T22:50:57.796482Z", "url": "https://files.pythonhosted.org/packages/f8/4a/2d65a5e771b2efac8207d1fb9f17e8dcfd5d4ef03ee8f8c7064e7c89b085/pitfall-0.0.3-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "0c9fd41f6a5a9ed034cb303701c386d0", "sha256": "2cfe3918361c12594499d32c954d84a621bd80e7f87a760deef8837c95e29e76" }, "downloads": -1, "filename": "pitfall-0.0.3.tar.gz", "has_sig": false, "md5_digest": "0c9fd41f6a5a9ed034cb303701c386d0", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 16511, "upload_time": "2019-11-19T22:50:59", "upload_time_iso_8601": "2019-11-19T22:50:59.679442Z", "url": "https://files.pythonhosted.org/packages/04/4b/b2c7d41a27ca899785d217399672c1218c4355092390198f3fe127a54965/pitfall-0.0.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "1750ca65e0ba46befc8842b9d387215b", "sha256": "80c439d122a12060ddddb08d8d012a1802bccb69d3d36f43b1db4f31c3f231cd" }, "downloads": -1, "filename": "pitfall-0.0.4-py3-none-any.whl", "has_sig": false, "md5_digest": "1750ca65e0ba46befc8842b9d387215b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 26683, "upload_time": "2019-11-20T04:35:06", "upload_time_iso_8601": "2019-11-20T04:35:06.745748Z", "url": "https://files.pythonhosted.org/packages/ac/26/7ab9d36f678377fd4912f511d6fdfc13c8e0caac450f255e9df50fdf2385/pitfall-0.0.4-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "dee4b3d10403071c43d0b2bafd4550b1", "sha256": "378254db04d528b7ea1464e41a8987bdf94aac4952c21d45ba7464d9fd78785b" }, "downloads": -1, "filename": "pitfall-0.0.4.tar.gz", "has_sig": false, "md5_digest": "dee4b3d10403071c43d0b2bafd4550b1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 18160, "upload_time": "2019-11-20T04:35:08", "upload_time_iso_8601": "2019-11-20T04:35:08.369527Z", "url": "https://files.pythonhosted.org/packages/fb/5f/007984ed04c0acdd8f1128ce1a3d15ab8d55ac03ff755ef56f7518cf7e3f/pitfall-0.0.4.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "1750ca65e0ba46befc8842b9d387215b", "sha256": "80c439d122a12060ddddb08d8d012a1802bccb69d3d36f43b1db4f31c3f231cd" }, "downloads": -1, "filename": "pitfall-0.0.4-py3-none-any.whl", "has_sig": false, "md5_digest": "1750ca65e0ba46befc8842b9d387215b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 26683, "upload_time": "2019-11-20T04:35:06", "upload_time_iso_8601": "2019-11-20T04:35:06.745748Z", "url": "https://files.pythonhosted.org/packages/ac/26/7ab9d36f678377fd4912f511d6fdfc13c8e0caac450f255e9df50fdf2385/pitfall-0.0.4-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "dee4b3d10403071c43d0b2bafd4550b1", "sha256": "378254db04d528b7ea1464e41a8987bdf94aac4952c21d45ba7464d9fd78785b" }, "downloads": -1, "filename": "pitfall-0.0.4.tar.gz", "has_sig": false, "md5_digest": "dee4b3d10403071c43d0b2bafd4550b1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 18160, "upload_time": "2019-11-20T04:35:08", "upload_time_iso_8601": "2019-11-20T04:35:08.369527Z", "url": "https://files.pythonhosted.org/packages/fb/5f/007984ed04c0acdd8f1128ce1a3d15ab8d55ac03ff755ef56f7518cf7e3f/pitfall-0.0.4.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }