{"id":31733487,"url":"https://github.com/frankthelen/cloudmonkey","last_synced_at":"2026-04-18T19:32:22.678Z","repository":{"id":57200818,"uuid":"123164557","full_name":"frankthelen/cloudmonkey","owner":"frankthelen","description":"Small infrastructure testing framework -- EXPERIMENTAL","archived":false,"fork":false,"pushed_at":"2020-06-02T18:26:41.000Z","size":1946,"stargazers_count":1,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-08T18:08:18.812Z","etag":null,"topics":["aws","cloud","infrastructure","testing"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frankthelen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-27T17:34:10.000Z","updated_at":"2020-06-02T12:30:17.000Z","dependencies_parsed_at":"2022-09-16T15:12:05.516Z","dependency_job_id":null,"html_url":"https://github.com/frankthelen/cloudmonkey","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/frankthelen/cloudmonkey","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankthelen%2Fcloudmonkey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankthelen%2Fcloudmonkey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankthelen%2Fcloudmonkey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankthelen%2Fcloudmonkey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frankthelen","download_url":"https://codeload.github.com/frankthelen/cloudmonkey/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankthelen%2Fcloudmonkey/sbom","scorecard":{"id":409690,"data":{"date":"2025-08-11","repo":{"name":"github.com/frankthelen/cloudmonkey","commit":"3fc746bd09b217194ddadd74564ef120c6e74ccf"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.5,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"47 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-6chw-6frg-f759","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-rrc9-gqf8-8rwg","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-3gx7-xhv7-5mx3","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-4q6p-r6v2-jvc5","Warn: Project is vulnerable to: GHSA-q42p-pg8m-cqh6","Warn: Project is vulnerable to: GHSA-w457-6q6x-cgp9","Warn: Project is vulnerable to: GHSA-62gr-4qp9-h98f","Warn: Project is vulnerable to: GHSA-f52g-6jhx-586p","Warn: Project is vulnerable to: GHSA-2cf5-4w76-r9qv","Warn: Project is vulnerable to: GHSA-3cqr-58rm-57f8","Warn: Project is vulnerable to: GHSA-g9r4-xpmj-mj65","Warn: Project is vulnerable to: GHSA-q2c6-c6pm-g3gh","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-2pr6-76vf-7546","Warn: Project is vulnerable to: GHSA-8j8c-7jfh-h6hx","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-675m-85rw-j3w4","Warn: Project is vulnerable to: GHSA-4xc9-xhrj-v574","Warn: Project is vulnerable to: GHSA-x5rq-j2xg-h7qm","Warn: Project is vulnerable to: GHSA-jf85-cpcp-j695","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-4xcv-9jjx-gfj3","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-g6ww-v8xp-vmwg","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-776f-qx25-q3cc","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T22:22:28.901Z","repository_id":57200818,"created_at":"2025-08-18T22:22:28.901Z","updated_at":"2025-08-18T22:22:28.901Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001076,"owners_count":26082991,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","cloud","infrastructure","testing"],"created_at":"2025-10-09T08:26:54.510Z","updated_at":"2025-10-09T08:26:55.634Z","avatar_url":"https://github.com/frankthelen.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CloudMonkey\n\nSmall infrastructure testing framework -- **EXPERIMENTAL**\n\nThe idea is to fill the gap between\nunit testing of infrastructure scripts (Terraform, CloudFormation, etc.) on the one hand,\nand live integration testing of the real infrastructure on the other hand.\nCloudMonkey pulls meta information of cloud infrastructure elements\nand provides them through a unified abstract interface for testing.\nWrite assertions against your cloud infrastructure\nusing your preferred test runner and assertion library.\nServices and resource types are extendable and pluggable.\n\n[![Build Status](https://travis-ci.org/frankthelen/cloudmonkey.svg?branch=master)](https://travis-ci.org/frankthelen/cloudmonkey)\n[![Coverage Status](https://coveralls.io/repos/github/frankthelen/cloudmonkey/badge.svg?branch=master)](https://coveralls.io/github/frankthelen/cloudmonkey?branch=master)\n[![dependencies Status](https://david-dm.org/frankthelen/cloudmonkey/status.svg)](https://david-dm.org/frankthelen/cloudmonkey)\n[![Greenkeeper badge](https://badges.greenkeeper.io/frankthelen/cloudmonkey.svg)](https://greenkeeper.io/)\n[![Maintainability](https://api.codeclimate.com/v1/badges/520457acb01e31acc0a3/maintainability)](https://codeclimate.com/github/frankthelen/cloudmonkey/maintainability)\n[![node](https://img.shields.io/node/v/cloudmonkey.svg)]()\n[![code style](https://img.shields.io/badge/code_style-airbnb-brightgreen.svg)](https://github.com/airbnb/javascript)\n[![License Status](http://img.shields.io/npm/l/cloudmonkey.svg)]()\n\n## Install\n\n```batch\nnpm install cloudmonkey\n```\n\n## Usage\n\nA quick example (assuming mocha and chai):\n```javascript\nconst { CloudMonkey, EC2 } = require('cloudmonkey');\n\nconst monkey = new CloudMonkey();\nmonkey.register(new EC2({ region: 'eu-central-1' }));\n\ndescribe('my subnets', () =\u003e {\n  it('should be tagged \"zone c\" if public', async () =\u003e {\n    const igw = await monkey.select.one.ec2.internetGateway({ vpc: 'vpc-12345678' });\n    const rtb = await igw.travel.to.all.routeTables();\n    const sn = await rtb.travel.to.all.subnets();\n    expect(sn).to.containAll(subnet =\u003e\n      subnet.Tags.filter(tag =\u003e\n        tag.Key === 'security-zone' \u0026\u0026\n        tag.Value === 'c').length);\n  });\n});\n```\n\n## Prerequisites\n\nConfigure the [AWS access keys](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/getting-started-nodejs.html#getting-started-nodejs-configure-keys).\n\n## Features\n### Register services and resource types\n\nThe interface model knows services and resource types.\nServices must be registered with CloudMonkey.\nEach service defines its resource types.\nServices are registered like this:\n\n```javascript\nconst { CloudMonkey, EC2 } = require('cloudmonkey');\n\nconst monkey = new CloudMonkey();\nmonkey.register(new EC2({ region: 'eu-central-1' }));\nmonkey.help();\n```\n\nUse `help()` to printout information such as the registered services,\ntheir resource types, filter and travel options:\n```bash\nCloudMonkey 1.0.0\n\nservice \"ec2\"\n* resource type \"instance\"\n  filter by \"id\", \"vpc\"\n  travel to \"subnet\", \"securityGroup\"\n* resource type \"internetGateway\"\n  filter by \"id\", \"vpc\"\n  travel to \"routeTable\"\n* resource type \"routeTable\"\n  filter by \"id\", \"vpc\"\n  travel to \"subnet\"\n* resource type \"securityGroup\"\n  filter by \"id\", \"name\", \"vpc\"\n* resource type \"subnet\"\n  filter by \"id\", \"vpc\"\n  travel to \"instance\"\n```\n\n### Selecting resources\n\nThe selection interface provides a means to select resources in your infrastructure.\nFor example:\n```javascript\nconst monkey = new CloudMonkey();\nmonkey.register(new EC2({ region: 'eu-central-1' }));\nconst igw = await monkey.select.one.ec2.internetGateway({ vpc: 'vpc-12345678' });\n```\n\nThe select interface of `CloudMonkey` has the following format:\n```\nselect.\u003cquantifier\u003e.\u003cservice\u003e.\u003cresourceType\u003e(\u003cfilter\u003e)\n```\n\n`\u003cqualifier\u003e` is `one`, `some` or `all`.\n`one` returns one single object while `all` and `some` return an array.\n`one` will throw an error if there is none or if there are more than one objects available.\n`\u003cservice\u003e` must be one of the services registered.\n`\u003cresourceType\u003e` must be one of the resource types provided by the service\n(plural, i.e., adding an `s` for nicer reading, is supported).\n\nThe returned data (whether it is an array or a single object) provides the meta data of the selected infrastructure element(s).\nThis can be used to further assertions, e.g., using mocha or jasmine or chai or any other assertion library of your choice.\n\nIn addition, it is decorated with `dump()` to simply print out the meta data.\n\n```javascript\nconst igw = await monkey.select.one.ec2.internetGateway({ vpc: 'vpc-12345678' });\nigw.dump();\nconst rtb = await monkey.select.all.ec2.routeTables();\nrtb.dump();\n```\n\nAnd it also provides the `travel` interface for traveling to related resources within the same service.\n\n### Travel to other resources\n\nThe travel interface allows to travel from resources (of one resource type) to related resources (of another resource type within the same service).\nIt also accepts filters, just like the select interface.\nUse `help()` (see above) to learn which travel and filter options are available for a particular resource type.\n\n```javascript\nconst igw = await monkey.select.one.ec2.internetGateway();\nconst rtb = await igw.travel.to.all.routeTables();\nconst sn = await rtb.travel.to.all.subnets();\nsn.dump();\n// do some assertions here\n```\n\nThe travel interface has the following format:\n```\ntravel.to.\u003cquantifier\u003e.\u003cresourceType\u003e(\u003cfilter\u003e)\n```\n\n### Extending CloudMonkey with new services\n\nCloudMonkey per se is cloud-agnostic.\nIt only knows services (which strictly speaking don't even have to be cloud services) and their resource types.\nTo add new services to CloudMonkey, simply derive from `Service`.\nA quick example:\n\n```javascript\nconst { CloudMonkey, Service } = require('cloudmonkey');\n\nclass FooService extends Service {\n  constructor({ alias } = {}) {\n    super({ name: 'foo', alias });\n    // register resource type 'bar'\n    this.register({\n      name: 'bar',\n      list: async () =\u003e Promise.resolve([]), // array of `bar` resources\n      filters: {\n        id: (bar, value) =\u003e bar.id === value,\n      },\n      identity: bar =\u003e bar.id,\n      travel: {\n        baz: async (bars) =\u003e Promise.resolve([]), // array of `baz` resources\n      }\n    });\n    // register resource type 'baz'\n    // ...\n  }\n}\n\nconst monkey = new CloudMonkey();\nmonkey.register(new FooService());\n\nconst bar = await monkey.select.one.foo.bar({ id: '1234' });\nconst bazs = await bar.travel.to.all.bazs();\n```\n\nCloudMonkey doesn't do any caching, i.e., if caching makes sense, the service has to take care itself.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrankthelen%2Fcloudmonkey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrankthelen%2Fcloudmonkey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrankthelen%2Fcloudmonkey/lists"}