├── awsmp ├── __init__.py ├── yaml_utils.py ├── types.py ├── constants.py ├── errors.py ├── cli.py ├── changesets.py └── _driver.py ├── tests ├── __init__.py ├── prices.csv ├── local_config │ ├── test_config_7.yaml │ ├── test_config_5.yaml │ ├── test_config_1.yaml │ ├── test_config_6.yaml │ ├── test_config_2.yaml │ ├── test_config_3.yaml │ └── test_config_4.yaml ├── test_config.yaml ├── description.yaml ├── test_config.json └── test_changesets.py ├── .wokeignore ├── docs ├── .sphinx │ ├── _static │ │ ├── tag.png │ │ ├── favicon.png │ │ ├── header-nav.js │ │ ├── github_issue_links.css │ │ ├── github_issue_links.js │ │ ├── 404.svg │ │ ├── header.css │ │ ├── furo_colors.css │ │ └── custom.css │ ├── pa11y.json │ ├── _templates │ │ ├── base.html │ │ ├── sidebar │ │ │ └── search.html │ │ ├── 404.html │ │ ├── header.html │ │ ├── page.html │ │ └── footer.html │ ├── spellingcheck.yaml │ └── build_requirements.py ├── .custom_wordlist.txt ├── .wokeignore ├── .gitignore ├── .wordlist.txt ├── .readthedocs.yaml ├── make.bat ├── index.rst ├── inspect │ └── index.rst ├── installation.rst ├── init.sh ├── private-offer │ └── index.rst ├── Makefile ├── doc-cheat-sheet-myst.md ├── conf.py ├── doc-cheat-sheet.rst ├── custom_conf.py └── public-offer │ └── index.rst ├── .gitignore ├── .github ├── workflows │ ├── automatic-doc-checks.yml │ └── pr.yaml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── SECURITY.md ├── README.rst ├── renovate.json ├── tox.ini ├── snap └── snapcraft.yaml ├── pyproject.toml └── listing_configuration.yaml /awsmp/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.wokeignore: -------------------------------------------------------------------------------- 1 | docs/.wokeignore -------------------------------------------------------------------------------- /docs/.sphinx/_static/tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canonical/awsmp/main/docs/.sphinx/_static/tag.png -------------------------------------------------------------------------------- /docs/.sphinx/_static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canonical/awsmp/main/docs/.sphinx/_static/favicon.png -------------------------------------------------------------------------------- /tests/prices.csv: -------------------------------------------------------------------------------- 1 | c3.2xlarge,0.014,98.112 2 | c3.4xlarge,0.028,196.224 3 | c3.8xlarge,0.056,392.448 4 | c4.large,0.00,0.00 5 | -------------------------------------------------------------------------------- /docs/.sphinx/pa11y.json: -------------------------------------------------------------------------------- 1 | { 2 | "chromeLaunchConfig": { 3 | "args": [ 4 | "--no-sandbox" 5 | ] 6 | }, 7 | "reporter": "cli", 8 | "standard": "WCAG2AA" 9 | } -------------------------------------------------------------------------------- /docs/.custom_wordlist.txt: -------------------------------------------------------------------------------- 1 | awsmp 2 | yaml 3 | AMI 4 | config 5 | csv 6 | Snapcraft 7 | Snapstore 8 | AWS 9 | USD 10 | str 11 | awsmpcli 12 | GovCloud 13 | Instructions 14 | instance -------------------------------------------------------------------------------- /docs/.wokeignore: -------------------------------------------------------------------------------- 1 | # the cheat sheets contain a link to a repository with a block word which we 2 | # cannot avoid for now, ie 3 | # https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html 4 | doc-cheat-sheet* 5 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | /*env*/ 2 | .sphinx/venv/ 3 | .sphinx/requirements.txt 4 | .sphinx/warnings.txt 5 | .sphinx/.wordlist.dic 6 | .sphinx/.doctrees/ 7 | .sphinx/node_modules/ 8 | package*.json 9 | _build 10 | .DS_Store 11 | __pycache__ 12 | .idea/ 13 | .vscode/ 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # editors 2 | /.idea/ 3 | /.vscode/ 4 | 5 | # python 6 | /awsmp.egg-info/ 7 | *.pyc 8 | .tox/ 9 | .cache 10 | .mypy_cache/ 11 | .pytest_cache/ 12 | __pycache__/ 13 | build 14 | dist 15 | venv/ 16 | .coverage 17 | /.eggs/ 18 | 19 | # temp files 20 | *~ 21 | *.csv 22 | *.snap 23 | -------------------------------------------------------------------------------- /docs/.sphinx/_static/header-nav.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $(document).on("click", function () { 3 | $(".more-links-dropdown").hide(); 4 | }); 5 | 6 | $('.nav-more-links').click(function(event) { 7 | $('.more-links-dropdown').toggle(); 8 | event.stopPropagation(); 9 | }); 10 | }) 11 | -------------------------------------------------------------------------------- /docs/.sphinx/_templates/base.html: -------------------------------------------------------------------------------- 1 | {% extends "furo/base.html" %} 2 | 3 | {% block theme_scripts %} 4 | 7 | {% endblock theme_scripts %} 8 | 9 | {# ru-fu: don't include the color variables from the conf.py file, but use a 10 |  separate CSS file to save space #} 11 | {% block theme_styles %} 12 | {% endblock theme_styles %} 13 | -------------------------------------------------------------------------------- /.github/workflows/automatic-doc-checks.yml: -------------------------------------------------------------------------------- 1 | name: Main Documentation Checks 2 | 3 | on: 4 | - push 5 | - pull_request 6 | - workflow_dispatch 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | documentation-checks: 14 | uses: canonical/documentation-workflows/.github/workflows/documentation-checks.yaml@main 15 | with: 16 | working-directory: 'docs' -------------------------------------------------------------------------------- /docs/.sphinx/_templates/sidebar/search.html: -------------------------------------------------------------------------------- 1 |
7 | 8 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting a vulnerability 2 | To report a security issue, file a [Private Security Report](https://github.com/Canonical/awsmp/security/advisories/new) 3 | with a description of the issue, the steps you took to create the issue, 4 | affected versions, and, if known, mitigations for the issue. 5 | The [Ubuntu Security disclosure and embargo policy](https://ubuntu.com/security/disclosure-policy) 6 | contains more information about what you can expect when you contact us and what we expect from you. 7 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ***** 2 | awsmp 3 | ***** 4 | 5 | **awsmp** is a module and CLI tool that can be used to interact with the AWS Marketplace API. 6 | 7 | Documentation 8 | ############# 9 | 10 | The documentation can be found at https://canonical-awsmp.readthedocs-hosted.com/. 11 | 12 | It'll cover installation instructions and specific use cases such as creating a private offer. 13 | 14 | Report issues 15 | ############# 16 | 17 | Please use https://github.com/canonical/awsmp/issues to report problems or ask questions. -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ], 6 | "packageRules": [ 7 | { 8 | "groupName": "all non-major dependencies", 9 | "groupSlug": "all-minor-patch", 10 | "matchPackageNames": [ 11 | "*" 12 | ], 13 | "matchUpdateTypes": [ 14 | "minor", 15 | "patch" 16 | ] 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. 16 | 2. 17 | 3. 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Additional context** 23 | Add any other context about the problem here. 24 | -------------------------------------------------------------------------------- /docs/.wordlist.txt: -------------------------------------------------------------------------------- 1 | addons 2 | API 3 | APIs 4 | balancer 5 | Charmhub 6 | CLI 7 | Diátaxis 8 | dropdown 9 | EBS 10 | EKS 11 | enablement 12 | favicon 13 | Furo 14 | Git 15 | GitHub 16 | Grafana 17 | IAM 18 | installable 19 | JSON 20 | Juju 21 | Kubeflow 22 | Kubernetes 23 | Launchpad 24 | LTS 25 | Makefile 26 | Matrix 27 | Mattermost 28 | MyST 29 | namespace 30 | namespaces 31 | NodePort 32 | observability 33 | OEM 34 | OLM 35 | Permalink 36 | pre 37 | Quickstart 38 | ReadMe 39 | reST 40 | reStructuredText 41 | RTD 42 | subdirectories 43 | subfolders 44 | subtree 45 | Ubuntu 46 | UI 47 | UUID 48 | VM 49 | YAML -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | isolated_build = true 3 | env_list = lint, py{310,311,313}, test 4 | minversion = 4.10.0 5 | 6 | [testenv] 7 | skip_install = true 8 | deps = 9 | poetry 10 | allowlist_externals = poetry 11 | commands_pre = poetry install 12 | package = wheel 13 | wheel_build_env = .pkg 14 | 15 | [testenv:test] 16 | description = run the tests with pytest 17 | commands = 18 | poetry run poe test 19 | 20 | [testenv:lint] 21 | description = run linter 22 | commands = 23 | poetry run poe lint 24 | 25 | [testenv:fix] 26 | description = run formatters 27 | commands = 28 | poetry run poe format 29 | -------------------------------------------------------------------------------- /docs/.sphinx/_static/github_issue_links.css: -------------------------------------------------------------------------------- 1 | .github-issue-link-container { 2 | padding-right: 0.5rem; 3 | } 4 | .github-issue-link { 5 | font-size: var(--font-size--small); 6 | font-weight: bold; 7 | background-color: #D6410D; 8 | padding: 13px 23px; 9 | text-decoration: none; 10 | } 11 | .github-issue-link:link { 12 | color: #FFFFFF; 13 | } 14 | .github-issue-link:visited { 15 | color: #FFFFFF 16 | } 17 | .muted-link.github-issue-link:hover { 18 | color: #FFFFFF; 19 | text-decoration: underline; 20 | } 21 | .github-issue-link:active { 22 | color: #FFFFFF; 23 | text-decoration: underline; 24 | } 25 | -------------------------------------------------------------------------------- /docs/.sphinx/spellingcheck.yaml: -------------------------------------------------------------------------------- 1 | matrix: 2 | - name: rST files 3 | aspell: 4 | lang: en 5 | d: en_GB 6 | dictionary: 7 | wordlists: 8 | - .wordlist.txt 9 | - .custom_wordlist.txt 10 | output: .sphinx/.wordlist.dic 11 | sources: 12 | - _build/**/*.html 13 | pipeline: 14 | - pyspelling.filters.html: 15 | comments: false 16 | attributes: 17 | - title 18 | - alt 19 | ignores: 20 | - code 21 | - pre 22 | - spellexception 23 | - link 24 | - title 25 | - div.relatedlinks 26 | - strong.command 27 | - div.visually-hidden 28 | - img 29 | - a.p-navigation__link 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | 22 | -------------------------------------------------------------------------------- /awsmp/yaml_utils.py: -------------------------------------------------------------------------------- 1 | import yaml 2 | from yaml.dumper import SafeDumper 3 | 4 | 5 | class LiteralString(str): 6 | pass 7 | 8 | 9 | def literal_str_representer(dumper, data): 10 | text = data if data.endswith("\n") else data + "\n" 11 | return dumper.represent_scalar("tag:yaml.org,2002:str", text, style="|") 12 | 13 | 14 | class IndentListDumper(SafeDumper): 15 | def increase_indent(self, flow=False, indentless=False): 16 | return super().increase_indent(flow, False) 17 | 18 | 19 | yaml.add_representer(LiteralString, literal_str_representer, Dumper=IndentListDumper) 20 | 21 | 22 | def dump(data, config): 23 | yaml.dump(data, config, Dumper=IndentListDumper, default_flow_style=False, indent=2, sort_keys=False) 24 | -------------------------------------------------------------------------------- /docs/.sphinx/_templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "page.html" %} 2 | 3 | {% block content -%} 4 |Sorry, but the documentation page that you are looking for was not found.
\n\nDocumentation changes over time, and pages are moved around. We try to redirect you to the updated content where possible, but unfortunately, that didn\'t work this time (maybe because the content you were looking for does not exist in this version of the documentation).
\nYou can try to use the navigation to locate the content you\'re looking for, or search for a similar page.
\n', 82 | } 83 | 84 | # Default image for OGP (to prevent font errors, see 85 | # https://github.com/canonical/sphinx-docs-starter-pack/pull/54 ) 86 | if not 'ogp_image' in locals(): 87 | ogp_image = 'https://assets.ubuntu.com/v1/253da317-image-document-ubuntudocs.svg' 88 | 89 | ############################################################ 90 | ### General configuration 91 | ############################################################ 92 | 93 | exclude_patterns = [ 94 | '_build', 95 | 'Thumbs.db', 96 | '.DS_Store', 97 | '.sphinx', 98 | 'SECURITY.md', 99 | ] 100 | exclude_patterns.extend(custom_excludes) 101 | 102 | rst_epilog = ''' 103 | .. include:: /reuse/links.txt 104 | ''' 105 | if 'custom_rst_epilog' in locals(): 106 | rst_epilog = custom_rst_epilog 107 | 108 | source_suffix = { 109 | '.rst': 'restructuredtext', 110 | '.md': 'markdown', 111 | } 112 | 113 | if not 'conf_py_path' in html_context and 'github_folder' in html_context: 114 | html_context['conf_py_path'] = html_context['github_folder'] 115 | 116 | # For ignoring specific links 117 | linkcheck_anchors_ignore_for_url = [ 118 | r'https://github\.com/.*' 119 | ] 120 | linkcheck_anchors_ignore_for_url.extend(custom_linkcheck_anchors_ignore_for_url) 121 | 122 | # Tags cannot be added directly in custom_conf.py, so add them here 123 | for tag in custom_tags: 124 | tags.add(tag) 125 | 126 | ############################################################ 127 | ### Styling 128 | ############################################################ 129 | 130 | # Find the current builder 131 | builder = 'dirhtml' 132 | if '-b' in sys.argv: 133 | builder = sys.argv[sys.argv.index('-b')+1] 134 | 135 | # Setting templates_path for epub makes the build fail 136 | if builder == 'dirhtml' or builder == 'html': 137 | templates_path = ['.sphinx/_templates'] 138 | notfound_template = '404.html' 139 | 140 | # Theme configuration 141 | html_theme = 'furo' 142 | html_last_updated_fmt = '' 143 | html_permalinks_icon = '¶' 144 | 145 | if html_title == '': 146 | html_theme_options = { 147 | 'sidebar_hide_name': True 148 | } 149 | 150 | ############################################################ 151 | ### Additional files 152 | ############################################################ 153 | 154 | html_static_path = ['.sphinx/_static'] 155 | 156 | html_css_files = [ 157 | 'custom.css', 158 | 'header.css', 159 | 'github_issue_links.css', 160 | 'furo_colors.css' 161 | ] 162 | html_css_files.extend(custom_html_css_files) 163 | 164 | html_js_files = ['header-nav.js'] 165 | if 'github_issues' in html_context and html_context['github_issues'] and not disable_feedback_button: 166 | html_js_files.append('github_issue_links.js') 167 | html_js_files.extend(custom_html_js_files) 168 | -------------------------------------------------------------------------------- /docs/doc-cheat-sheet.rst: -------------------------------------------------------------------------------- 1 | :orphan: 2 | 3 | .. _cheat-sheet: 4 | 5 | reStructuredText cheat sheet 6 | ============================ 7 | 8 | This file contains the syntax for commonly used reST markup. 9 | Open it in your text editor to quickly copy and paste the markup you need. 10 | 11 | See the `reStructuredText style guide