diff --git a/.github/workflows/automatic-doc-checks.yml b/.github/workflows/automatic-doc-checks.yml new file mode 100644 index 00000000..cba712e5 --- /dev/null +++ b/.github/workflows/automatic-doc-checks.yml @@ -0,0 +1,16 @@ +name: Main Documentation Checks + +on: + - push + - pull_request + - workflow_dispatch + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + documentation-checks: + uses: canonical/documentation-workflows/.github/workflows/documentation-checks.yaml@main + with: + working-directory: 'docs' diff --git a/.wokeignore b/.wokeignore new file mode 120000 index 00000000..19f3fe4b --- /dev/null +++ b/.wokeignore @@ -0,0 +1 @@ +docs/.wokeignore \ No newline at end of file diff --git a/README.md b/README.md index 02129cd2..3e04e048 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,41 @@ -# DISCLAIMER +# Charmed OpenStack Upgrader -This is a work in progress prototype. The code contained in this repository -may not be representative of what the final approach should be. -It is likely that the end result will live under a different name, in a -different repository, and only use some of the code and ideas found here. +Charmed OpenStack Upgrader (COU) is an application (packaged as a snap) to upgrade +a Canonical distribution of [Charmed OpenStack](https://ubuntu.com/openstack/docs/overview) +in an automated and frictionless manner. The application detects the version of the +running cloud and proposes an upgrade plan to the next available OpenStack release. + +For more information, please refer to [COU Documentation](https://canonical-charmed-openstack-upgrader.readthedocs-hosted.com/). # Setup +The Charmed OpenStack Upgrader snap can be installed directly from the snap store: + ```bash -# Instructions for local builds until we have automatic connections and alias -make clean -sudo snap remove charmed-openstack-upgrader --purge -make build -sudo snap install ./charmed-openstack-upgrader.snap --dangerous -sudo snap connect charmed-openstack-upgrader:juju-client-observe snapd -sudo snap connect charmed-openstack-upgrader:dot-local-share-cou snapd -sudo snap connect charmed-openstack-upgrader:ssh-public-keys snapd -sudo snap alias charmed-openstack-upgrader.cou cou +sudo snap install charmed-openstack-upgrader ``` -Then you can use ```cou``` +An alias `cou` will be automatically enabled upon successful installation. + +Run `cou -h` to learn about the available commands: + +```bash +Usage: cou [options] + +Charmed OpenStack Upgrader (cou) is an application to upgrade +a Canonical distribution of Charmed OpenStack. +The application auto-detects the version of the running cloud +and will propose an upgrade to the next available version. + +Options: + -h, --help Show this help message and exit. + --version, -V Show version details. + +Commands: + {help,plan,upgrade} For more information about a command, run 'cou help '. + plan Show the steps COU will take to upgrade the cloud to the next release. + upgrade Run the cloud upgrade. +``` ## Environment Variables @@ -38,3 +54,7 @@ Application supports: - Focal/Wallaby -> Focal/Yoga upgrades. + +# License +Charmed OpenStack Upgrader is a free software, distributed under the Apache-2.0 license. Refer to the +[LICENSE](https://github.com/canonical/snap-tempest/blob/main/LICENSE) file for details. \ No newline at end of file diff --git a/docs/.custom_wordlist.txt b/docs/.custom_wordlist.txt new file mode 100644 index 00000000..d321a9b9 --- /dev/null +++ b/docs/.custom_wordlist.txt @@ -0,0 +1,23 @@ +OpenStack +Upgrader +ussuri +Github +frictionless +COU +cou +COUModel +SIGINT +SIGINTs +SIGTERM +SIGTERMs +STDOUT +juju +libjuju +VPN +ctrl +snapcraft +OpenStackApplication +yaml +backoff +BACKOFF +websockets \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..743e132a --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,11 @@ +/*env*/ +.sphinx/venv/ +.sphinx/warnings.txt +.sphinx/.wordlist.dic +.sphinx/.doctrees/ +.sphinx/node_modules/ +package*.json +_build +.DS_Store +__pycache__ +.idea/ diff --git a/docs/.readthedocs.yaml b/docs/.readthedocs.yaml new file mode 100644 index 00000000..45fe3a88 --- /dev/null +++ b/docs/.readthedocs.yaml @@ -0,0 +1,27 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + builder: dirhtml + configuration: docs/conf.py + fail_on_warning: true + +# If using Sphinx, optionally build your docs in additional formats such as PDF +formats: + - pdf + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: docs/.sphinx/requirements.txt diff --git a/docs/.sphinx/_static/custom.css b/docs/.sphinx/_static/custom.css new file mode 100644 index 00000000..4ef05c0a --- /dev/null +++ b/docs/.sphinx/_static/custom.css @@ -0,0 +1,210 @@ +/** Fix the font weight (300 for normal, 400 for slightly bold) **/ + +div.page, h1, h2, h3, h4, h5, h6, .sidebar-tree .current-page>.reference, button, input, optgroup, select, textarea, th.head { + font-weight: 300 +} + +.toc-tree li.scroll-current>.reference, dl.glossary dt, dl.simple dt, dl:not([class]) dt { + font-weight: 400; +} + +/** Table styling **/ + +th.head { + text-transform: uppercase; + font-size: var(--font-size--small); +} + +table.docutils { + border: 0; + box-shadow: none; + width:100%; +} + +table.docutils td, table.docutils th, table.docutils td:last-child, table.docutils th:last-child, table.docutils td:first-child, table.docutils th:first-child { + border-right: none; + border-left: none; +} + +/* Allow to centre text horizontally in table data cells */ +table.align-center { + text-align: center !important; +} + +/** No rounded corners **/ + +.admonition, code.literal, .sphinx-tabs-tab, .sphinx-tabs-panel, .highlight { + border-radius: 0; +} + +/** Admonition styling **/ + +.admonition { + border-top: 1px solid #d9d9d9; + border-right: 1px solid #d9d9d9; + border-bottom: 1px solid #d9d9d9; +} + +/** Color for the "copy link" symbol next to headings **/ + +a.headerlink { + color: var(--color-brand-primary); +} + +/** Line to the left of the current navigation entry **/ + +.sidebar-tree li.current-page { + border-left: 2px solid var(--color-brand-primary); +} + +/** Some tweaks for issue #16 **/ + +[role="tablist"] { + border-bottom: 1px solid var(--color-sidebar-item-background--hover); +} + +.sphinx-tabs-tab[aria-selected="true"] { + border: 0; + border-bottom: 2px solid var(--color-brand-primary); + background-color: var(--color-sidebar-item-background--current); + font-weight:300; +} + +.sphinx-tabs-tab{ + color: var(--color-brand-primary); + font-weight:300; +} + +.sphinx-tabs-panel { + border: 0; + border-bottom: 1px solid var(--color-sidebar-item-background--hover); + background: var(--color-background-primary); +} + +button.sphinx-tabs-tab:hover { + background-color: var(--color-sidebar-item-background--hover); +} + +/** Custom classes to fix scrolling in tables by decreasing the + font size or breaking certain columns. + Specify the classes in the Markdown file with, for example: + ```{rst-class} break-col-4 min-width-4-8 + ``` +**/ + +table.dec-font-size { + font-size: smaller; +} +table.break-col-1 td.text-left:first-child { + word-break: break-word; +} +table.break-col-4 td.text-left:nth-child(4) { + word-break: break-word; +} +table.min-width-1-15 td.text-left:first-child { + min-width: 15em; +} +table.min-width-4-8 td.text-left:nth-child(4) { + min-width: 8em; +} + +/** Underline for abbreviations **/ + +abbr[title] { + text-decoration: underline solid #cdcdcd; +} + +/** Use the same style for right-details as for left-details **/ +.bottom-of-page .right-details { + font-size: var(--font-size--small); + display: block; +} + +/** Version switcher */ +button.version_select { + color: var(--color-foreground-primary); + background-color: var(--color-toc-background); + padding: 5px 10px; + border: none; +} + +.version_select:hover, .version_select:focus { + background-color: var(--color-sidebar-item-background--hover); +} + +.version_dropdown { + position: relative; + display: inline-block; + text-align: right; + font-size: var(--sidebar-item-font-size); +} + +.available_versions { + display: none; + position: absolute; + right: 0px; + background-color: var(--color-toc-background); + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 11; +} + +.available_versions a { + color: var(--color-foreground-primary); + padding: 12px 16px; + text-decoration: none; + display: block; +} + +.available_versions a:hover {background-color: var(--color-sidebar-item-background--current)} + +.show {display:block;} + +/** Fix for nested numbered list - the nested list is lettered **/ +ol.arabic ol.arabic { + list-style: lower-alpha; +} + +/** Make expandable sections look like links **/ +details summary { + color: var(--color-link); +} + +/** Fix the styling of the version box for readthedocs **/ + +#furo-readthedocs-versions .rst-versions, #furo-readthedocs-versions .rst-current-version, #furo-readthedocs-versions:focus-within .rst-current-version, #furo-readthedocs-versions:hover .rst-current-version { + background: var(--color-sidebar-item-background--hover); +} + +.rst-versions .rst-other-versions dd a { + color: var(--color-link); +} + +#furo-readthedocs-versions:focus-within .rst-current-version .fa-book, #furo-readthedocs-versions:hover .rst-current-version .fa-book, .rst-versions .rst-other-versions { + color: var(--color-sidebar-link-text); +} + +.rst-versions .rst-current-version { + color: var(--color-version-popup); + font-weight: bolder; +} + +/* Code-block copybutton invisible by default + (overriding Furo config to achieve default copybutton setting). */ +.highlight button.copybtn { + opacity: 0; +} + +/* Mimicking the 'Give feedback' button for UX consistency */ +.sidebar-search-container input[type=submit] { + color: #FFFFFF; + border: 2px solid #D6410D; + padding: var(--sidebar-search-input-spacing-vertical) var(--sidebar-search-input-spacing-horizontal); + background: #D6410D; + font-weight: bold; + font-size: var(--font-size--small); + cursor: pointer; +} + +.sidebar-search-container input[type=submit]:hover { + text-decoration: underline; +} diff --git a/docs/.sphinx/_static/favicon.png b/docs/.sphinx/_static/favicon.png new file mode 100644 index 00000000..7f175e46 Binary files /dev/null and b/docs/.sphinx/_static/favicon.png differ diff --git a/docs/.sphinx/_static/furo_colors.css b/docs/.sphinx/_static/furo_colors.css new file mode 100644 index 00000000..ffc36cbc --- /dev/null +++ b/docs/.sphinx/_static/furo_colors.css @@ -0,0 +1,88 @@ +body { + --color-code-background: #f8f8f8; + --color-code-foreground: black; + --font-stack: Ubuntu, -apple-system, Segoe UI, Roboto, Oxygen, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + --font-stack--monospace: Ubuntu Mono, Consolas, Monaco, Courier, monospace; + --color-foreground-primary: #111; + --color-foreground-secondary: var(--color-foreground-primary); + --color-foreground-muted: #333; + --color-background-secondary: #FFF; + --color-background-hover: #f2f2f2; + --color-brand-primary: #111; + --color-brand-content: #06C; + --color-api-background: #cdcdcd; + --color-inline-code-background: rgba(0,0,0,.03); + --color-sidebar-link-text: #111; + --color-sidebar-item-background--current: #ebebeb; + --color-sidebar-item-background--hover: #f2f2f2; + --toc-font-size: var(--font-size--small); + --color-admonition-title-background--note: var(--color-background-primary); + --color-admonition-title-background--tip: var(--color-background-primary); + --color-admonition-title-background--important: var(--color-background-primary); + --color-admonition-title-background--caution: var(--color-background-primary); + --color-admonition-title--note: #24598F; + --color-admonition-title--tip: #24598F; + --color-admonition-title--important: #C7162B; + --color-admonition-title--caution: #F99B11; + --color-highlighted-background: #EbEbEb; + --color-link-underline: var(--color-background-primary); + --color-link-underline--hover: var(--color-background-primary); + --color-version-popup: #772953; +} + +@media not print { + body[data-theme="dark"] { + --color-code-background: #202020; + --color-code-foreground: #d0d0d0; + --color-foreground-secondary: var(--color-foreground-primary); + --color-foreground-muted: #CDCDCD; + --color-background-secondary: var(--color-background-primary); + --color-background-hover: #666; + --color-brand-primary: #fff; + --color-brand-content: #06C; + --color-sidebar-link-text: #f7f7f7; + --color-sidebar-item-background--current: #666; + --color-sidebar-item-background--hover: #333; + --color-admonition-background: transparent; + --color-admonition-title-background--note: var(--color-background-primary); + --color-admonition-title-background--tip: var(--color-background-primary); + --color-admonition-title-background--important: var(--color-background-primary); + --color-admonition-title-background--caution: var(--color-background-primary); + --color-admonition-title--note: #24598F; + --color-admonition-title--tip: #24598F; + --color-admonition-title--important: #C7162B; + --color-admonition-title--caution: #F99B11; + --color-highlighted-background: #666; + --color-link-underline: var(--color-background-primary); + --color-link-underline--hover: var(--color-background-primary); + --color-version-popup: #F29879; + } + @media (prefers-color-scheme: dark) { + body:not([data-theme="light"]) { + --color-code-background: #202020; + --color-code-foreground: #d0d0d0; + --color-foreground-secondary: var(--color-foreground-primary); + --color-foreground-muted: #CDCDCD; + --color-background-secondary: var(--color-background-primary); + --color-background-hover: #666; + --color-brand-primary: #fff; + --color-brand-content: #06C; + --color-sidebar-link-text: #f7f7f7; + --color-sidebar-item-background--current: #666; + --color-sidebar-item-background--hover: #333; + --color-admonition-background: transparent; + --color-admonition-title-background--note: var(--color-background-primary); + --color-admonition-title-background--tip: var(--color-background-primary); + --color-admonition-title-background--important: var(--color-background-primary); + --color-admonition-title-background--caution: var(--color-background-primary); + --color-admonition-title--note: #24598F; + --color-admonition-title--tip: #24598F; + --color-admonition-title--important: #C7162B; + --color-admonition-title--caution: #F99B11; + --color-highlighted-background: #666; + --color-link-underline: var(--color-background-primary); + --color-link-underline--hover: var(--color-background-primary); + --color-version-popup: #F29879; + } + } +} diff --git a/docs/.sphinx/_static/github_issue_links.css b/docs/.sphinx/_static/github_issue_links.css new file mode 100644 index 00000000..db166ed9 --- /dev/null +++ b/docs/.sphinx/_static/github_issue_links.css @@ -0,0 +1,24 @@ +.github-issue-link-container { + padding-right: 0.5rem; +} +.github-issue-link { + font-size: var(--font-size--small); + font-weight: bold; + background-color: #D6410D; + padding: 13px 23px; + text-decoration: none; +} +.github-issue-link:link { + color: #FFFFFF; +} +.github-issue-link:visited { + color: #FFFFFF +} +.muted-link.github-issue-link:hover { + color: #FFFFFF; + text-decoration: underline; +} +.github-issue-link:active { + color: #FFFFFF; + text-decoration: underline; +} diff --git a/docs/.sphinx/_static/github_issue_links.js b/docs/.sphinx/_static/github_issue_links.js new file mode 100644 index 00000000..f0706038 --- /dev/null +++ b/docs/.sphinx/_static/github_issue_links.js @@ -0,0 +1,34 @@ +// if we already have an onload function, save that one +var prev_handler = window.onload; + +window.onload = function() { + // call the previous onload function + if (prev_handler) { + prev_handler(); + } + + const link = document.createElement("a"); + link.classList.add("muted-link"); + link.classList.add("github-issue-link"); + link.text = "Give feedback"; + link.href = ( + github_url + + "/issues/new?" + + "title=docs%3A+TYPE+YOUR+QUESTION+HERE" + + "&body=*Please describe the question or issue you're facing with " + + `"${document.title}"` + + ".*" + + "%0A%0A%0A%0A%0A" + + "---" + + "%0A" + + `*Reported+from%3A+${location.href}*` + ); + link.target = "_blank"; + + const div = document.createElement("div"); + div.classList.add("github-issue-link-container"); + div.append(link) + + const container = document.querySelector(".article-container > .content-icon-container"); + container.prepend(div); +}; diff --git a/docs/.sphinx/_static/header-nav.js b/docs/.sphinx/_static/header-nav.js new file mode 100644 index 00000000..3608576e --- /dev/null +++ b/docs/.sphinx/_static/header-nav.js @@ -0,0 +1,10 @@ +$(document).ready(function() { + $(document).on("click", function () { + $(".more-links-dropdown").hide(); + }); + + $('.nav-more-links').click(function(event) { + $('.more-links-dropdown').toggle(); + event.stopPropagation(); + }); +}) diff --git a/docs/.sphinx/_static/header.css b/docs/.sphinx/_static/header.css new file mode 100644 index 00000000..0b944090 --- /dev/null +++ b/docs/.sphinx/_static/header.css @@ -0,0 +1,167 @@ +.p-navigation { + border-bottom: 1px solid var(--color-sidebar-background-border); +} + +.p-navigation__nav { + background: #333333; + display: flex; +} + +.p-logo { + display: flex !important; + padding-top: 0 !important; + text-decoration: none; +} + +.p-logo-image { + height: 44px; + padding-right: 10px; +} + +.p-logo-text { + margin-top: 18px; + color: white; + text-decoration: none; +} + +ul.p-navigation__links { + display: flex; + list-style: none; + margin-left: 0; + margin-top: auto; + margin-bottom: auto; + max-width: 800px; + width: 100%; +} + +ul.p-navigation__links li { + margin: 0 auto; + text-align: center; + width: 100%; +} + +ul.p-navigation__links li a { + background-color: rgba(0, 0, 0, 0); + border: none; + border-radius: 0; + color: var(--color-sidebar-link-text); + display: block; + font-weight: 400; + line-height: 1.5rem; + margin: 0; + overflow: hidden; + padding: 1rem 0; + position: relative; + text-align: left; + text-overflow: ellipsis; + transition-duration: .1s; + transition-property: background-color, color, opacity; + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + white-space: nowrap; + width: 100%; +} + +ul.p-navigation__links .p-navigation__link { + color: #ffffff; + font-weight: 300; + text-align: center; + text-decoration: none; +} + +ul.p-navigation__links .p-navigation__link:hover { + background-color: #2b2b2b; +} + +ul.p-navigation__links .p-dropdown__link:hover { + background-color: var(--color-sidebar-item-background--hover); +} + +ul.p-navigation__links .p-navigation__sub-link { + background: var(--color-background-primary); + padding: .5rem 0 .5rem .5rem; + font-weight: 300; +} + +ul.p-navigation__links .more-links-dropdown li a { + border-left: 1px solid var(--color-sidebar-background-border); + border-right: 1px solid var(--color-sidebar-background-border); +} + +ul.p-navigation__links .more-links-dropdown li:first-child a { + border-top: 1px solid var(--color-sidebar-background-border); +} + +ul.p-navigation__links .more-links-dropdown li:last-child a { + border-bottom: 1px solid var(--color-sidebar-background-border); +} + +ul.p-navigation__links .p-navigation__logo { + padding: 0.5rem; +} + +ul.p-navigation__links .p-navigation__logo img { + width: 40px; +} + +ul.more-links-dropdown { + display: none; + overflow-x: visible; + height: 0; + z-index: 55; + padding: 0; + position: relative; + list-style: none; + margin-bottom: 0; + margin-top: 0; +} + +.nav-more-links::after { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath fill='%23111' d='M8.187 11.748l6.187-6.187-1.06-1.061-5.127 5.127L3.061 4.5 2 5.561z'/%3E%3C/svg%3E"); + background-position: center; + background-repeat: no-repeat; + background-size: contain; + content: ""; + display: block; + filter: invert(100%); + height: 1rem; + pointer-events: none; + position: absolute; + right: 1rem; + text-indent: calc(100% + 10rem); + top: calc(1rem + 0.25rem); + width: 1rem; +} + +.nav-ubuntu-com { + display: none; +} + +@media only screen and (min-width: 480px) { + ul.p-navigation__links li { + width: 100%; + } + + .nav-ubuntu-com { + display: inherit; + } +} + +@media only screen and (max-width: 800px) { + .nav-more-links { + margin-left: auto !important; + padding-right: 2rem !important; + width: 8rem !important; + } +} + +@media only screen and (min-width: 800px) { + ul.p-navigation__links li { + width: 100% !important; + } +} + +@media only screen and (min-width: 1310px) { + ul.p-navigation__links { + margin-left: calc(50% - 41em); + } +} diff --git a/docs/.sphinx/_static/tag.png b/docs/.sphinx/_static/tag.png new file mode 100644 index 00000000..f6f6e5aa Binary files /dev/null and b/docs/.sphinx/_static/tag.png differ diff --git a/docs/.sphinx/_templates/base.html b/docs/.sphinx/_templates/base.html new file mode 100644 index 00000000..33081547 --- /dev/null +++ b/docs/.sphinx/_templates/base.html @@ -0,0 +1,12 @@ +{% extends "furo/base.html" %} + +{% block theme_scripts %} + +{% endblock theme_scripts %} + +{# ru-fu: don't include the color variables from the conf.py file, but use a + separate CSS file to save space #} +{% block theme_styles %} +{% endblock theme_styles %} diff --git a/docs/.sphinx/_templates/footer.html b/docs/.sphinx/_templates/footer.html new file mode 100644 index 00000000..dbaaf733 --- /dev/null +++ b/docs/.sphinx/_templates/footer.html @@ -0,0 +1,105 @@ +{# ru-fu: copied from Furo, with modifications as stated below. Modifications are marked 'mod:'. #} + + +
+
+ {%- if show_copyright %} + + {%- endif %} + + {# mod: removed "Made with" #} + + {%- if last_updated -%} +
+ {% trans last_updated=last_updated|e -%} + Last updated on {{ last_updated }} + {%- endtrans -%} +
+ {%- endif %} + + {%- if show_source and has_source and sourcename %} + + {%- endif %} +
+
+ + {# mod: replaced RTD icons with our links #} + + {% if discourse %} + + {% endif %} + + {% if mattermost %} + + {% endif %} + + {% if github_url and github_version and github_folder %} + + {% if github_issues %} + + {% endif %} + + + {% endif %} + + +
+
+ diff --git a/docs/.sphinx/_templates/header.html b/docs/.sphinx/_templates/header.html new file mode 100644 index 00000000..1a128b6f --- /dev/null +++ b/docs/.sphinx/_templates/header.html @@ -0,0 +1,36 @@ + diff --git a/docs/.sphinx/_templates/page.html b/docs/.sphinx/_templates/page.html new file mode 100644 index 00000000..bda30610 --- /dev/null +++ b/docs/.sphinx/_templates/page.html @@ -0,0 +1,49 @@ +{% extends "furo/page.html" %} + +{% block footer %} + {% include "footer.html" %} +{% endblock footer %} + +{% block body -%} + {% include "header.html" %} + {{ super() }} +{%- endblock body %} + +{% if meta and ((meta.discourse and discourse_prefix) or meta.relatedlinks) %} + {% set furo_hide_toc_orig = furo_hide_toc %} + {% set furo_hide_toc=false %} +{% endif %} + +{% block right_sidebar %} +
+ {% if not furo_hide_toc_orig %} +
+ + {{ _("Contents") }} + +
+
+
+ {{ toc }} +
+
+ {% endif %} + {% if meta and ((meta.discourse and discourse_prefix) or meta.relatedlinks) %} + + + {% endif %} +
+{% endblock right_sidebar %} diff --git a/docs/.sphinx/_templates/sidebar/search.html b/docs/.sphinx/_templates/sidebar/search.html new file mode 100644 index 00000000..644a5ef6 --- /dev/null +++ b/docs/.sphinx/_templates/sidebar/search.html @@ -0,0 +1,7 @@ + + diff --git a/docs/.sphinx/requirements.txt b/docs/.sphinx/requirements.txt new file mode 100644 index 00000000..0f7ffa5f --- /dev/null +++ b/docs/.sphinx/requirements.txt @@ -0,0 +1,14 @@ +canonical-sphinx-extensions +furo +linkify-it-py +myst-parser +pyspelling +sphinx +sphinx-autobuild +sphinx-copybutton +sphinx-design +sphinx-notfound-page +sphinx-reredirects +sphinx-tabs +sphinxcontrib-jquery +sphinxext-opengraph diff --git a/docs/.sphinx/spellingcheck.yaml b/docs/.sphinx/spellingcheck.yaml new file mode 100644 index 00000000..fc9d3c50 --- /dev/null +++ b/docs/.sphinx/spellingcheck.yaml @@ -0,0 +1,29 @@ +matrix: +- name: rST files + aspell: + lang: en + d: en_GB + dictionary: + wordlists: + - .wordlist.txt + - .custom_wordlist.txt + output: .sphinx/.wordlist.dic + sources: + - _build/**/*.html + pipeline: + - pyspelling.filters.html: + comments: false + attributes: + - title + - alt + ignores: + - code + - pre + - spellexception + - link + - title + - div.relatedlinks + - strong.command + - div.visually-hidden + - img + - a.p-navigation__link diff --git a/docs/.wokeignore b/docs/.wokeignore new file mode 100644 index 00000000..c64a6037 --- /dev/null +++ b/docs/.wokeignore @@ -0,0 +1,4 @@ +# the cheat sheets contain a link to a repository with a block word which we +# cannot avoid for now, ie +# https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html +doc-cheat-sheet* diff --git a/docs/.wordlist.txt b/docs/.wordlist.txt new file mode 100644 index 00000000..16778ad9 --- /dev/null +++ b/docs/.wordlist.txt @@ -0,0 +1,46 @@ +addons +API +APIs +balancer +Charmhub +CLI +dropdown +Diátaxis +EBS +EKS +favicon +Furo +Git +GitHub +Grafana +IAM +installable +JSON +Juju +Kubernetes +Kubeflow +Launchpad +LTS +Makefile +Mattermost +MyST +namespace +namespaces +NodePort +observability +OEM +OLM +Permalink +pre +ReadMe +reST +reStructuredText +RTD +subdirectories +subtree +subfolders +Ubuntu +UI +UUID +VM +YAML diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..5a6f134b --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,101 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= -c . -d .sphinx/.doctrees +SPHINXBUILD ?= sphinx-build +SPHINXDIR = .sphinx +SOURCEDIR = . +BUILDDIR = _build +VENVDIR = $(SPHINXDIR)/venv +PA11Y = $(SPHINXDIR)/node_modules/pa11y/bin/pa11y.js +VENV = $(VENVDIR)/bin/activate + +.PHONY: help woke-install pa11y-install install run html epub serve clean \ + clean-doc spelling linkcheck woke pa11y Makefile + +# Put it first so that "make" without argument is like "make help". +help: $(VENVDIR) + @. $(VENV); $(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +# Explicit target avoids fall-through to the "Makefile" target. +$(SPHINXDIR)/requirements.txt: + test -f $(SPHINXDIR)/requirements.txt + +# If requirements are updated, venv should be rebuilt and timestamped. +$(VENVDIR): $(SPHINXDIR)/requirements.txt + @echo "... setting up virtualenv" + python3 -m venv $(VENVDIR) + . $(VENV); pip install --require-virtualenv \ + --upgrade -r $(SPHINXDIR)/requirements.txt \ + --log $(VENVDIR)/pip_install.log + @test ! -f $(VENVDIR)/pip_list.txt || \ + mv $(VENVDIR)/pip_list.txt $(VENVDIR)/pip_list.txt.bak + @. $(VENV); pip list --local --format=freeze > $(VENVDIR)/pip_list.txt + @echo "\n" \ + "--------------------------------------------------------------- \n" \ + "* watch, build and serve the documentation: make run \n" \ + "* only build: make html \n" \ + "* only serve: make serve \n" \ + "* clean built doc files: make clean-doc \n" \ + "* clean full environment: make clean \n" \ + "* check links: make linkcheck \n" \ + "* check spelling: make spelling \n" \ + "* check inclusive language: make woke \n" \ + "* check accessibility: make pa11y \n" \ + "* other possible targets: make \n" \ + "--------------------------------------------------------------- \n" + @touch $(VENVDIR) + +woke-install: + @type woke >/dev/null 2>&1 || \ + { echo "Installing \"woke\" snap... \n"; sudo snap install woke; } + +pa11y-install: + @type $(PA11Y) >/dev/null 2>&1 || { \ + echo "Installing \"pa11y\" from npm... \n"; \ + mkdir -p $(SPHINXDIR)/node_modules/ ; \ + npm install --prefix $(SPHINXDIR) pa11y; \ + } + +install: $(VENVDIR) woke-install + +run: install + . $(VENV); sphinx-autobuild -b dirhtml "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) + +# Doesn't depend on $(BUILDDIR) to rebuild properly at every run. +html: install + . $(VENV); $(SPHINXBUILD) -b dirhtml "$(SOURCEDIR)" "$(BUILDDIR)" -w .sphinx/warnings.txt $(SPHINXOPTS) + +epub: install + . $(VENV); $(SPHINXBUILD) -b epub "$(SOURCEDIR)" "$(BUILDDIR)" -w .sphinx/warnings.txt $(SPHINXOPTS) + +serve: html + cd "$(BUILDDIR)"; python3 -m http.server 8000 + +clean: clean-doc + @test ! -e "$(VENVDIR)" -o -d "$(VENVDIR)" -a "$(abspath $(VENVDIR))" != "$(VENVDIR)" + rm -rf $(VENVDIR) + rm -rf .sphinx/.doctrees + +clean-doc: + git clean -fx "$(BUILDDIR)" + +spelling: html + . $(VENV) ; python3 -m pyspelling -c .sphinx/spellingcheck.yaml + +linkcheck: install + . $(VENV) ; $(SPHINXBUILD) -b linkcheck "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) + +woke: woke-install + woke *.rst **/*.rst --exit-1-on-failure \ + -c https://github.com/canonical/Inclusive-naming/raw/main/config.yml + +pa11y: pa11y-install html + find $(BUILDDIR) -name *.html -exec $(PA11Y) {} \; + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + . $(VENV); $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..b02b9fe2 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,139 @@ +import sys + +sys.path.append('./') +from custom_conf import * + +# Configuration file for the Sphinx documentation builder. +# You should not do any modifications to this file. Put your custom +# configuration into the custom_conf.py file. +# If you need to change this file, contribute the changes upstream. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +############################################################ +### Extensions +############################################################ + +extensions = [ + 'sphinx_design', + 'sphinx_tabs.tabs', + 'sphinx_reredirects', + 'canonical.youtube-links', + 'canonical.related-links', + 'canonical.custom-rst-roles', + 'canonical.terminal-output', + 'sphinx_copybutton', + 'sphinxext.opengraph', + 'myst_parser', + 'sphinxcontrib.jquery', + 'notfound.extension' +] +extensions.extend(custom_extensions) + +### Configuration for extensions + +# Additional MyST syntax +myst_enable_extensions = [ + 'substitution', + 'deflist', + 'linkify' +] +myst_enable_extensions.extend(custom_myst_extensions) + +# Used for related links +if not 'discourse_prefix' in html_context and 'discourse' in html_context: + html_context['discourse_prefix'] = html_context['discourse'] + '/t/' + +# The default for notfound_urls_prefix usually works, but not for +# documentation on documentation.ubuntu.com +if slug: + notfound_urls_prefix = '/' + slug + '/en/latest/' + +notfound_context = { + 'title': 'Page not found', + 'body': '

Page not found

\n\n

Sorry, but the documentation page that you are looking for was not found.

\n

Documentation 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).

\n

You can try to use the navigation to locate the content you\'re looking for, or search for a similar page.

\n', +} + +# Default image for OGP (to prevent font errors, see +# https://github.com/canonical/sphinx-docs-starter-pack/pull/54 ) +if not 'ogp_image' in locals(): + ogp_image = 'https://assets.ubuntu.com/v1/253da317-image-document-ubuntudocs.svg' + +############################################################ +### General configuration +############################################################ + +exclude_patterns = [ + '_build', + 'Thumbs.db', + '.DS_Store', + '.sphinx', +] +exclude_patterns.extend(custom_excludes) + +rst_epilog = ''' +.. include:: /reuse/links.txt +''' +if 'custom_rst_epilog' in locals(): + rst_epilog = custom_rst_epilog + +source_suffix = { + '.rst': 'restructuredtext', + '.md': 'markdown', +} + +if not 'conf_py_path' in html_context and 'github_folder' in html_context: + html_context['conf_py_path'] = html_context['github_folder'] + +# For ignoring specific links +linkcheck_anchors_ignore_for_url = [ + r'https://github\.com/.*' +] +linkcheck_anchors_ignore_for_url.extend(custom_linkcheck_anchors_ignore_for_url) + +# Tags cannot be added directly in custom_conf.py, so add them here +for tag in custom_tags: + tags.add(tag) + +############################################################ +### Styling +############################################################ + +# Find the current builder +builder = 'dirhtml' +if '-b' in sys.argv: + builder = sys.argv[sys.argv.index('-b')+1] + +# Setting templates_path for epub makes the build fail +if builder == 'dirhtml' or builder == 'html': + templates_path = ['.sphinx/_templates'] + +# Theme configuration +html_theme = 'furo' +html_last_updated_fmt = '' +html_permalinks_icon = '¶' + +if html_title == '': + html_theme_options = { + 'sidebar_hide_name': True + } + +############################################################ +### Additional files +############################################################ + +html_static_path = ['.sphinx/_static'] + +html_css_files = [ + 'custom.css', + 'header.css', + 'github_issue_links.css', + 'furo_colors.css' +] +html_css_files.extend(custom_html_css_files) + +html_js_files = ['header-nav.js'] +if 'github_issues' in html_context and html_context['github_issues'] and not disable_feedback_button: + html_js_files.append('github_issue_links.js') +html_js_files.extend(custom_html_js_files) diff --git a/docs/custom_conf.py b/docs/custom_conf.py new file mode 100644 index 00000000..dd4030e0 --- /dev/null +++ b/docs/custom_conf.py @@ -0,0 +1,175 @@ +import datetime + +# Custom configuration for the Sphinx documentation builder. +# All configuration specific to your project should be done in this file. +# +# The file is included in the common conf.py configuration file. +# You can modify any of the settings below or add any configuration that +# is not covered by the common conf.py file. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html +# +# If you're not familiar with Sphinx and don't want to use advanced +# features, it is sufficient to update the settings in the "Project +# information" section. + +############################################################ +### Project information +############################################################ + +# Product name +project = 'Charmed OpenStack Upgrader' +author = 'Canonical Group Ltd' + +# The title you want to display for the documentation in the sidebar. +# You might want to include a version number here. +# To not display any title, set this option to an empty string. +html_title = project + ' documentation' + +# The default value uses the current year as the copyright year. +# +# For static works, it is common to provide the year of first publication. +# Another option is to give the first year and the current year +# for documentation that is often changed, e.g. 2022–2023 (note the en-dash). +# +# A way to check a GitHub repo's creation date is to obtain a classic GitHub +# token with 'repo' permissions here: https://github.com/settings/tokens +# Next, use 'curl' and 'jq' to extract the date from the GitHub API's output: +# +# curl -H 'Authorization: token ' \ +# -H 'Accept: application/vnd.github.v3.raw' \ +# https://api.github.com/repos/canonical/ | jq '.created_at' + +copyright = '%s, %s' % (datetime.date.today().year, author) + +## Open Graph configuration - defines what is displayed as a link preview +## when linking to the documentation from another website (see https://ogp.me/) +# The URL where the documentation will be hosted (leave empty if you +# don't know yet) +ogp_site_url = 'https://canonical-charmed-openstack-upgrader.readthedocs-hosted.com/' +# The documentation website name (usually the same as the product name) +ogp_site_name = project +# The URL of an image or logo that is used in the preview +ogp_image = 'https://assets.ubuntu.com/v1/253da317-image-document-ubuntudocs.svg' + +# Update with the local path to the favicon for your product +# (default is the circle of friends) +html_favicon = '.sphinx/_static/favicon.png' + +# (Some settings must be part of the html_context dictionary, while others +# are on root level. Don't move the settings.) +html_context = { + + # Change to the link to the website of your product (without "https://") + # For example: "ubuntu.com/lxd" or "microcloud.is" + # If there is no product website, edit the header template to remove the + # link (see the readme for instructions). + 'product_page': 'snapcraft.io/charmed-openstack-upgrader', + + # Add your product tag (the orange part of your logo, will be used in the + # header) to ".sphinx/_static" and change the path here (start with "_static") + # (default is the circle of friends) + 'product_tag': '_static/tag.png', + + # Change to the discourse instance you want to be able to link to + # using the :discourse: metadata at the top of a file + # (use an empty value if you don't want to link) + 'discourse': '', + + # Change to the Mattermost channel you want to link to + # (use an empty value if you don't want to link) + 'mattermost': '', + + # Change to the GitHub URL for your project + 'github_url': 'https://github.com/canonical/charmed-openstack-upgrader', + + # Change to the branch for this version of the documentation + 'github_version': 'main', + + # Change to the folder that contains the documentation + # (usually "/" or "/docs/") + 'github_folder': '/docs/', + + # Change to an empty value if your GitHub repo doesn't have issues enabled. + # This will disable the feedback button and the issue link in the footer. + 'github_issues': 'enabled', + + # Controls the existence of Previous / Next buttons at the bottom of pages + # Valid options: none, prev, next, both + 'sequential_nav': "none" +} + +# If your project is on documentation.ubuntu.com, specify the project +# slug (for example, "lxd") here. +slug = "" + +############################################################ +### Redirects +############################################################ + +# Set up redirects (https://documatt.gitlab.io/sphinx-reredirects/usage.html) +# For example: 'explanation/old-name.html': '../how-to/prettify.html', + +redirects = {} + +############################################################ +### Link checker exceptions +############################################################ + +# Links to ignore when checking links + +linkcheck_ignore = [ + 'http://127.0.0.1:8000' + ] + +# Pages on which to ignore anchors +# (This list will be appended to linkcheck_anchors_ignore_for_url) + +custom_linkcheck_anchors_ignore_for_url = [ + ] + +############################################################ +### Additions to default configuration +############################################################ + +## The following settings are appended to the default configuration. +## Use them to extend the default functionality. + +# Add extensions +custom_extensions = [] + +# Add MyST extensions +custom_myst_extensions = [] + +# Add files or directories that should be excluded from processing. +custom_excludes = [ + 'doc-cheat-sheet*', +] + +# Add CSS files (located in .sphinx/_static/) +custom_html_css_files = [] + +# Add JavaScript files (located in .sphinx/_static/) +custom_html_js_files = [] + +## The following settings override the default configuration. + +# Specify a reST string that is included at the end of each file. +# If commented out, use the default (which pulls the reuse/links.txt +# file into each reST file). +# custom_rst_epilog = '' + +# By default, the documentation includes a feedback button at the top. +# You can disable it by setting the following configuration to True. +disable_feedback_button = False + +# Add tags that you want to use for conditional inclusion of text +# (https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#tags) +custom_tags = [] + +############################################################ +### Additional configuration +############################################################ + +## Add any configuration that is not covered by the common conf.py file. diff --git a/docs/doc-cheat-sheet-myst.md b/docs/doc-cheat-sheet-myst.md new file mode 100644 index 00000000..19b07f53 --- /dev/null +++ b/docs/doc-cheat-sheet-myst.md @@ -0,0 +1,243 @@ +--- +orphan: true +myst: + substitutions: + reuse_key: "This is **included** text." + advanced_reuse_key: "This is a substitution that includes a code block: + ``` + code block + ```" +--- + +(cheat-sheet-myst)= +# Markdown/MyST cheat sheet + +This file contains the syntax for commonly used Markdown and MyST markup. +Open it in your text editor to quickly copy and paste the markup you need. + +Also see the [MyST documentation](https://myst-parser.readthedocs.io/en/latest/index.html) for detailed information, and the [Canonical Documentation Style Guide](https://docs.ubuntu.com/styleguide/en) for general style conventions. + +## H2 heading + +### H3 heading + +#### H4 heading + +##### H5 heading + +## Inline formatting + +- {guilabel}`UI element` +- `code` +- {command}`command` +- {kbd}`Key` +- *Italic* +- **Bold** + +## Code blocks + +Start a code block: + + code: + - example: true + +``` +# Demonstrate a code block +code: + - example: true +``` + +```yaml +# Demonstrate a code block +code: + - example: true +``` + +(_a_section_target)= +## Links + +- [Canonical website](https://canonical.com/) +- https://canonical.com/ +- {ref}`a_section_target` +- {ref}`Link text ` +- {doc}`index` +- {doc}`Link text ` + + +## Navigation + +Use the following syntax:: + + ```{toctree} + :hidden: + + sub-page1 + sub-page2 + ``` + +## Lists + +1. Step 1 + - Item 1 + * Sub-item + - Item 2 + 1. Sub-step 1 + 1. Sub-step 2 +1. Step 2 + 1. Sub-step 1 + - Item + 1. Sub-step 2 + +Term 1 +: Definition + +Term 2 +: Definition + +## Tables + +## Markdown tables + +| Header 1 | Header 2 | +|------------------------------------|----------| +| Cell 1
Second paragraph | Cell 2 | +| Cell 3 | Cell 4 | + +Centred: + +| Header 1 | Header 2 | +|:----------------------------------:|:--------:| +| Cell 1
Second paragraph | Cell 2 | +| Cell 3 | Cell 4 | + +## List tables + +```{list-table} + :header-rows: 1 + +* - Header 1 + - Header 2 +* - Cell 1 + + Second paragraph + - Cell 2 +* - Cell 3 + - Cell 4 +``` + +Centred: + +```{list-table} + :header-rows: 1 + :align: center + +* - Header 1 + - Header 2 +* - Cell 1 + + Second paragraph + - Cell 2 +* - Cell 3 + - Cell 4 +``` + +## Notes + +```{note} +A note. +``` + +```{tip} +A tip. +``` + +```{important} +Important information +``` + +```{caution} +This might damage your hardware! +``` + +## Images + +![Alt text](https://assets.ubuntu.com/v1/b3b72cb2-canonical-logo-166.png) + +```{figure} https://assets.ubuntu.com/v1/b3b72cb2-canonical-logo-166.png + :width: 100px + :alt: Alt text + + Figure caption +``` + +## Reuse + +### Keys + +Keys can be defined at the top of a file, or in a `myst_substitutions` option in `conf.py`. + +{{reuse_key}} + +{{advanced_reuse_key}} + +### File inclusion + +```{include} index.rst + :start-after: include_start + :end-before: include_end +``` + +## Tabs + +````{tabs} +```{group-tab} Tab 1 + +Content Tab 1 +``` + +```{group-tab} Tab 2 +Content Tab 2 +``` +```` + +## Glossary + +```{glossary} + +some term + Definition of the example term. +``` + +{term}`some term` + +## More useful markup + +- ```{versionadded} X.Y +- {abbr}`API (Application Programming Interface)` + +---- + +## Custom extensions + +Related links at the top of the page (surrounded by `---`): + + relatedlinks: https://github.com/canonical/lxd-sphinx-extensions, [RTFM](https://www.google.com) + discourse: 12345 + +Terms that should not be checked by the spelling checker: {spellexception}`PurposelyWrong` + +A terminal view with input and output: + +```{terminal} + :input: command + :user: root + :host: vampyr + +the output +``` + +A link to a YouTube video: + +```{youtube} https://www.youtube.com/watch?v=iMLiK1fX4I0 + :title: Demo +``` diff --git a/docs/doc-cheat-sheet.rst b/docs/doc-cheat-sheet.rst new file mode 100644 index 00000000..b12ebcdf --- /dev/null +++ b/docs/doc-cheat-sheet.rst @@ -0,0 +1,258 @@ +:orphan: + +.. _cheat-sheet: + +reStructuredText cheat sheet +============================ + +This file contains the syntax for commonly used reST markup. +Open it in your text editor to quickly copy and paste the markup you need. + +See the `reStructuredText style guide `_ for detailed information and conventions. + +Also see the `Sphinx reStructuredText Primer `_ for more details on reST, and the `Canonical Documentation Style Guide `_ for general style conventions. + +H2 heading +---------- + +H3 heading +~~~~~~~~~~ + +H4 heading +^^^^^^^^^^ + +H5 heading +.......... + +Inline formatting +----------------- + +- :guilabel:`UI element` +- ``code`` +- :file:`file path` +- :command:`command` +- :kbd:`Key` +- *Italic* +- **Bold** + +Code blocks +----------- + +Start a code block:: + + code: + - example: true + +.. code:: + + # Demonstrate a code block + code: + - example: true + +.. code:: yaml + + # Demonstrate a code block + code: + - example: true + +.. _a_section_target: + +Links +----- + +- `Canonical website `_ +- `Canonical website`_ (defined in ``reuse/links.txt`` or at the bottom of the page) +- https:\ //canonical.com/ +- :ref:`a_section_target` +- :ref:`Link text ` +- :doc:`index` +- :doc:`Link text ` + + +Navigation +---------- + +Use the following syntax:: + + .. toctree:: + :hidden: + + sub-page1 + sub-page2 + + +Lists +----- + +1. Step 1 + + - Item 1 + + * Sub-item + - Item 2 + + i. Sub-step 1 + #. Sub-step 2 +#. Step 2 + + a. Sub-step 1 + + - Item + #. Sub-step 2 + +Term 1: + Definition +Term 2: + Definition + +Tables +------ + ++----------------------+------------+ +| Header 1 | Header 2 | ++======================+============+ +| Cell 1 | Cell 2 | +| | | +| Second paragraph | | ++----------------------+------------+ +| Cell 3 | Cell 4 | ++----------------------+------------+ + +.. list-table:: + :header-rows: 1 + + * - Header 1 + - Header 2 + * - Cell 1 + + Second paragraph + - Cell 2 + * - Cell 3 + - Cell 4 + +.. rst-class:: align-center + + +----------------------+------------+ + | Header 1 | Header 2 | + +======================+============+ + | Cell 1 | Cell 2 | + | | | + | Second paragraph | | + +----------------------+------------+ + | Cell 3 | Cell 4 | + +----------------------+------------+ + +.. list-table:: + :header-rows: 1 + :align: center + + * - Header 1 + - Header 2 + * - Cell 1 + + Second paragraph + - Cell 2 + * - Cell 3 + - Cell 4 + +Notes +----- + +.. note:: + A note. + +.. tip:: + A tip. + +.. important:: + Important information + +.. caution:: + This might damage your hardware! + +Images +------ + +.. image:: https://assets.ubuntu.com/v1/b3b72cb2-canonical-logo-166.png + +.. figure:: https://assets.ubuntu.com/v1/b3b72cb2-canonical-logo-166.png + :width: 100px + :alt: Alt text + + Figure caption + +Reuse +----- + +.. |reuse_key| replace:: This is **included** text. + +|reuse_key| + +.. include:: index.rst + :start-after: include_start + :end-before: include_end + +Tabs +---- + +.. tabs:: + + .. group-tab:: Tab 1 + + Content Tab 1 + + .. group-tab:: Tab 2 + + Content Tab 2 + + +Glossary +-------- + +.. glossary:: + + example term + Definition of the example term. + +:term:`example term` + +More useful markup +------------------ + +- .. versionadded:: X.Y +- | Line 1 + | Line 2 + | Line 3 +- .. This is a comment +- :abbr:`API (Application Programming Interface)` + +---- + +Custom extensions +----------------- + +Related links at the top of the page:: + + :relatedlinks: https://github.com/canonical/lxd-sphinx-extensions, [RTFM](https://www.google.com) + :discourse: 12345 + +Terms that should not be checked by the spelling checker: :spellexception:`PurposelyWrong` + +A terminal view with input and output: + +.. terminal:: + :input: command + :user: root + :host: vampyr + + the output + +A link to a YouTube video: + +.. youtube:: https://www.youtube.com/watch?v=iMLiK1fX4I0 + :title: Demo + + + +.. LINKS +.. _Canonical website: https://canonical.com/ diff --git a/docs/explanation/analysis.rst b/docs/explanation/analysis.rst new file mode 100644 index 00000000..04300b90 --- /dev/null +++ b/docs/explanation/analysis.rst @@ -0,0 +1,9 @@ +======== +Analysis +======== + +This phase is responsible for obtaining all the required OpenStack cloud information +from Juju: the model status and the configuration for each application is obtained +and stored in an Analysis object, divided into control and data plane. Each +application is represented by a generic **OpenStackApplication** class or by a custom +subclass, e.g. **Keystone(OpenStackApplication)**. diff --git a/docs/explanation/index.rst b/docs/explanation/index.rst new file mode 100644 index 00000000..44718c7f --- /dev/null +++ b/docs/explanation/index.rst @@ -0,0 +1,13 @@ +=========== +Explanation +=========== + +This section provides additional information about the upgrade stages, implementation, +and known issues. + +.. toctree:: + :maxdepth: 1 + + analysis + planning + upgrade diff --git a/docs/explanation/planning.rst b/docs/explanation/planning.rst new file mode 100644 index 00000000..688eebf5 --- /dev/null +++ b/docs/explanation/planning.rst @@ -0,0 +1,37 @@ +======== +Planning +======== + +The plan has a tree structure with three main sections: pre-upgrade steps, +control-plane upgrade and data-plane upgrade. + +.. code:: + + Top-level plan + ├── pre-upgrade steps + │ ├── verify cloud is in idle state + │ └── MySQL backup + ├── control-plane upgrade + │ ├── principal applications + │ | ├── application 1.. + │ | | ├── pre-upgrade steps + | | | ├── upgrade steps + │ | | └── post-upgrade steps + │ | └── application N + │ | ├── pre-upgrade steps + | | ├── upgrade steps + │ | └── post-upgrade steps + | └── subordinate applications... + ├── data-plane upgrade + ... + +The **pre-upgrades** steps are used to obtain any further information about the +applications or to verify their state. + +The **upgrade** steps are the main steps needed to run upgrades for each application. + +The **post-upgrade** steps are responsible for making sure that upgrade finishes +successfully. + +The plan can also be obtained without the need to perform cloud upgrade using +the **plan** command. See :doc:`Plan an upgrade <../how-to/plan-upgrade>`. diff --git a/docs/explanation/upgrade.rst b/docs/explanation/upgrade.rst new file mode 100644 index 00000000..42b53978 --- /dev/null +++ b/docs/explanation/upgrade.rst @@ -0,0 +1,8 @@ +======= +Upgrade +======= + +This phase is responsible for applying the upgrade plan step by step (see +:doc:`Upgrade a cloud <../how-to/upgrade-cloud>`). Most steps will be applied +sequentially, but for some that are defined to be run in parallel, they will be +executed in such a way. diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst new file mode 100644 index 00000000..42fbed62 --- /dev/null +++ b/docs/get-started/index.rst @@ -0,0 +1,32 @@ +=========== +Get started +=========== + +Verify Access +------------- +To use **COU** you need to have access to a `Charmed OpenStack`_ cloud, which is deployed +using `Juju`_. **COU** uses Juju credentials to access the OpenStack cloud, so accessing +the cloud with Juju is mandatory. + +**COU** requires at minimum *write* permission to the target model (see +`User access levels`_ for more information). To verify your current +user's model-scoped access level, run the following Juju command and look for +your OpenStack model. + +.. code:: bash + + juju models + +Installation +------------ +Install the **COU** snap from the `snap store`_: + +.. code:: bash + + sudo snap install charmed-openstack-upgrader + +.. LINKS +.. _Charmed OpenStack: https://ubuntu.com/openstack/docs +.. _Juju: https://juju.is/docs/juju +.. _User access levels: https://juju.is/docs/juju/user-permissions +.. _snap store: https://snapcraft.io/ \ No newline at end of file diff --git a/docs/help-woke.rst b/docs/help-woke.rst new file mode 100644 index 00000000..8bc2a488 --- /dev/null +++ b/docs/help-woke.rst @@ -0,0 +1,57 @@ +=================================== +Inclusive language check exemptions +=================================== + +This page provides an overview of two inclusive language check exemption +methods for files written in reST format. See the `woke documentation`_ for +full coverage. + +Exempt a word +------------- + +To exempt an individual word, place a custom ``none`` role (defined in the +``canonical-sphinx-extensions`` Sphinx extension) anywhere on the line +containing the word in question. The role syntax is: + +.. code-block:: none + + :none:`wokeignore:rule=,` + +For instance: + +.. code-block:: none + + This is your text. The word in question is here: whitelist. More text. :none:`wokeignore:rule=whitelist,` + +To exempt an element of a URL, it is recommended to use the standard reST +method of placing links at the bottom of the page (or in a separate file). In +this case, a comment line is placed immediately above the URL line. The comment +syntax is: + +.. code-block:: none + + .. wokeignore:rule= + +Here is an example where a URL element contains the string "master": :none:`wokeignore:rule=master,` + +.. code-block:: none + + .. LINKS + .. wokeignore:rule=master + .. _link definition: https://some-external-site.io/master/some-page.html + +You can now refer to the label ``link definition_`` in the body of the text. + +Exempt an entire file +--------------------- + +A more drastic solution is to make an exemption for the contents of an entire +file. For example, to exempt file ``docs/foo/bar.rst`` add the following line +to file ``.wokeignore``: + +.. code-block:: none + + foo/bar.rst + +.. LINKS +.. _woke documentation: https://docs.getwoke.tech/ignore diff --git a/docs/how-to/configure-connection.rst b/docs/how-to/configure-connection.rst new file mode 100644 index 00000000..db8e7aad --- /dev/null +++ b/docs/how-to/configure-connection.rst @@ -0,0 +1,20 @@ +================================= +Change model connection behaviour +================================= + +There are three variables through which the connection behaviour to the Juju model +can be tuned. This may be necessary if **COU** is run from behind a VPN or if the network +is heavily used. + +* **COU_TIMEOUT** - set the timeout of retries for any calls by COUModel to libjuju. It's unit-less and the number represents the number of seconds. Defaults to 10 seconds. + +* **COU_MODEL_RETRIES** - set how many times to retry connecting to the Juju model before giving up. Defaults to 5. + +* **COU_MODEL_RETRY_BACKOFF** - sets the number of seconds in between connection retry attempts (for example, a backoff of 10 with 3 retries would wait 10s, 20s, and 30s). It’s unit-less and the number represents the number of seconds. Defaults to 2 seconds. + +Usage example +~~~~~~~~~~~~~ + +.. code:: + + $ COU_TIMEOUT=120 cou upgrade \ No newline at end of file diff --git a/docs/how-to/different-model.rst b/docs/how-to/different-model.rst new file mode 100644 index 00000000..6321a729 --- /dev/null +++ b/docs/how-to/different-model.rst @@ -0,0 +1,33 @@ +====================================== +Target a different model or controller +====================================== + +The current active model will be used by default, but it's possible to select a +different one, even on a different controller. There are two ways to choose the +model you want to operate on. + +Using CLI argument +~~~~~~~~~~~~~~~~~~ + +.. code:: + + $ cou plan --model + $ cou plan --model : + +Using environment variables +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since **COU** is using `python-libjuju`_, it's possible for some of the environment variables +mentioned in the documented `Juju environment variables`_ to affect the behaviour of the +program. For example, `JUJU_DATA`_ can be used to specify a different path for Juju +configuration files. + +.. code:: + + $ JUJU_DATA=./my-remote-cloud-juju-data cou plan + + +.. LINKS +.. _python-libjuju: https://github.com/juju/python-libjuju +.. _Juju environment variables: https://juju.is/docs/juju/environment-variables#heading--jujudata +.. _JUJU_DATA: https://juju.is/docs/juju/environment-variables#heading--jujudata diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst new file mode 100644 index 00000000..16cbe19d --- /dev/null +++ b/docs/how-to/index.rst @@ -0,0 +1,18 @@ +============= +How-to guides +============= + +These How-to guides will cover a variety of operations that +are possible with **COU**. + + +.. toctree:: + :maxdepth: 1 + + plan-upgrade + upgrade-cloud + different-model + interruption + configure-connection + no-backup + verbosity diff --git a/docs/how-to/interruption.rst b/docs/how-to/interruption.rst new file mode 100644 index 00000000..d453f70b --- /dev/null +++ b/docs/how-to/interruption.rst @@ -0,0 +1,94 @@ +=============================== +Interrupt and resume an upgrade +=============================== + +Since a partially executed upgrade step can leave the cloud in an inconsistent state, +**COU** ensures upgrades can be interrupted only in between steps. By doing so, upgrades +can be safely stopped and resumed later on. + +Abort +----- + +In interactive mode, the user must approve each step, and has a chance to interrupt +the process at any prompt. + +Usage example: + +.. code:: + + $ cou upgrade + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connected to 'test-model' ✔ + Analyzing cloud... ✔ + Generating upgrade plan... ✔ + Upgrade cloud from 'ussuri' to 'victoria' + ... + Running cloud upgrade... + Verify that all OpenStack applications are in idle state ✔ + Backup mysql databases ✔ + Upgrade plan for 'keystone' to victoria + Upgrade software packages of 'keystone' from the current APT repositories + Upgrade 'keystone' to the new channel: 'victoria/stable' + Change charm config of 'keystone' 'openstack-origin' to 'cloud:focal-victoria' + Wait 1800s for model test-model to reach the idle state. + Check if the workload of 'keystone' has been upgraded + + Would you like to start the upgrade? Continue (y/N): n + $ + +SIGINT or SIGTERM signals +------------------------- + +**COU** will exit upon receiving SIGINT or SIGTERM signals, but if the upgrade is already +in progress one of two behaviours will occur. If SIGINT or SIGTERM is sent only once +(e.g. by pressing *ctrl+c* once), currently running steps will be allowed to finish, +but any further upgrade step will be cancelled. If **COU** receives two or more SIGINTs +(e.g. by pressing *ctrl+c* multiple times) or SIGTERMs, the upgrade will be cancelled +abruptly in a potentially unsafe way: currently running steps will be immediately +stopped, and no further step will be executed. This is generally not recommended as +the cloud may be left in an inconsistent state. + +Exiting before running upgrade plan: + +.. code:: + + $ cou upgrade - # ctrl+c is pressed while connecting to the controller + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connecting to 'default' model... ✖ + charmed-openstack-upgrader has been terminated + $ cou upgrade # ctrl+c is pressed while the cloud is being analyzed + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connecting to 'default' model... ✔ + Analyzing cloud... ✖ + charmed-openstack-upgrader has been terminated + $ + +Safe cancel: + +.. code:: + + $ cou upgrade # ctrl+c is pressed once during the upgrade + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connected to 'test-model' ✔ + Analyzing cloud... ✔ + Generating upgrade plan... ✔ + ... + Running cloud upgrade... + Canceling upgrade... (Press ctrl+c again to stop immediately) ✔ + charmed-openstack-upgrader has been stopped safely + $ + +Unsafe cancel: + +.. code:: + + $ cou upgrade # ctrl+c is pressed twice during the upgrade + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connected to 'test-model' ✔ + Analyzing cloud... ✔ + Generating upgrade plan... ✔ + ... + Running cloud upgrade... + Canceling upgrade... (Press ctrl+c again to stop immediately) ✖ + charmed-openstack-upgrader has been terminated without waiting + $ \ No newline at end of file diff --git a/docs/how-to/no-backup.rst b/docs/how-to/no-backup.rst new file mode 100644 index 00000000..64a806fe --- /dev/null +++ b/docs/how-to/no-backup.rst @@ -0,0 +1,53 @@ +========================================== +Plan/Upgrade without cloud database backup +========================================== + +By default, **COU** plans for and runs a backup step of the cloud database before +proceeding to actual upgrade steps. This can be turned off with `--no-backup` flag. + +Usage examples +~~~~~~~~~~~~~~ + +Plan: + +.. code:: + + $ cou plan --no-backup + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connected to 'test-model' ✔ + Analyzing cloud... ✔ + Generating upgrade plan... ✔ + Upgrade cloud from 'ussuri' to 'victoria' + Verify that all OpenStack applications are in idle state + # note that there's no backup step planned + Control Plane principal(s) upgrade plan + Upgrade plan for 'rabbitmq-server' to victoria + Upgrade software packages of 'rabbitmq-server' from the current APT repositories + ... + +Upgrade: + +.. code:: + + $ cou upgrade --no-backup + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connected to 'test-model' ✔ + Analyzing cloud... ✔ + Generating upgrade plan... ✔ + ... + Running cloud upgrade... + Verify that all OpenStack applications are in idle state ✔ + # note that there's no backup step being executed + + Upgrade plan for 'rabbitmq-server' to victoria + Upgrade software packages of 'rabbitmq-server' from the current APT repositories + Upgrade 'rabbitmq-server' to the new channel: '3.9/stable' + Change charm config of 'rabbitmq-server' 'source' to 'cloud:focal-victoria' + Wait 1800s for model test-model to reach the idle state. + Check if the workload of 'rabbitmq-server' has been upgraded + + Continue (y/n): y + Upgrade plan for 'rabbitmq-server' to victoria ✔ + + ... # apply steps + Upgrade completed. diff --git a/docs/how-to/plan-upgrade.rst b/docs/how-to/plan-upgrade.rst new file mode 100644 index 00000000..4e541f23 --- /dev/null +++ b/docs/how-to/plan-upgrade.rst @@ -0,0 +1,81 @@ +================ +Plan an upgrade +================ + +The **plan** command is used to generate the upgrade plan; the result will be +printed on STDOUT. + +.. code:: + + $ cou plan + +Usage example +~~~~~~~~~~~~~ + +.. code:: + + $ cou plan + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connected to 'test-model' ✔ + Analyzing cloud... ✔ + Generating upgrade plan... ✔ + Upgrade cloud from 'ussuri' to 'victoria' + Verify that all OpenStack applications are in idle state + Backup mysql databases + Control Plane principal(s) upgrade plan + Upgrade plan for 'rabbitmq-server' to victoria + Upgrade software packages of 'rabbitmq-server' from the current APT repositories + Upgrade 'rabbitmq-server' to the new channel: '3.9/stable' + Change charm config of 'rabbitmq-server' 'source' to 'cloud:focal-victoria' + Wait 1800s for model test-model to reach the idle state. + Check if the workload of 'rabbitmq-server' has been upgraded + Upgrade plan for 'keystone' to victoria + Upgrade software packages of 'keystone' from the current APT repositories + Upgrade 'keystone' to the new channel: 'victoria/stable' + Change charm config of 'keystone' 'openstack-origin' to 'cloud:focal-victoria' + Wait 1800s for model test-model to reach the idle state. + Check if the workload of 'keystone' has been upgraded + Upgrade plan for 'cinder' to victoria + Upgrade software packages of 'cinder' from the current APT repositories + Upgrade 'cinder' to the new channel: 'victoria/stable' + Change charm config of 'cinder' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app cinder to reach the idle state. + Check if the workload of 'cinder' has been upgraded + Upgrade plan for 'glance' to victoria + Upgrade software packages of 'glance' from the current APT repositories + Upgrade 'glance' to the new channel: 'victoria/stable' + Change charm config of 'glance' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app glance to reach the idle state. + Check if the workload of 'glance' has been upgraded + Upgrade plan for 'neutron-api' to victoria + Upgrade software packages of 'neutron-api' from the current APT repositories + Upgrade 'neutron-api' to the new channel: 'victoria/stable' + Change charm config of 'neutron-api' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app neutron-api to reach the idle state. + Check if the workload of 'neutron-api' has been upgraded + Upgrade plan for 'neutron-gateway' to victoria + Upgrade software packages of 'neutron-gateway' from the current APT repositories + Upgrade 'neutron-gateway' to the new channel: 'victoria/stable' + Change charm config of 'neutron-gateway' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app neutron-gateway to reach the idle state. + Check if the workload of 'neutron-gateway' has been upgraded + Upgrade plan for 'placement' to victoria + Upgrade software packages of 'placement' from the current APT repositories + Upgrade 'placement' to the new channel: 'victoria/stable' + Change charm config of 'placement' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app placement to reach the idle state. + Check if the workload of 'placement' has been upgraded + Upgrade plan for 'nova-cloud-controller' to victoria + Upgrade software packages of 'nova-cloud-controller' from the current APT repositories + Upgrade 'nova-cloud-controller' to the new channel: 'victoria/stable' + Change charm config of 'nova-cloud-controller' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app nova-cloud-controller to reach the idle state. + Check if the workload of 'nova-cloud-controller' has been upgraded + Upgrade plan for 'mysql' to victoria + Upgrade software packages of 'mysql' from the current APT repositories + Change charm config of 'mysql' 'source' to 'cloud:focal-victoria' + Wait 1800s for app mysql to reach the idle state. + Check if the workload of 'mysql' has been upgraded + Control Plane subordinate(s) upgrade plan + Upgrade plan for 'neutron-openvswitch' to victoria + Upgrade 'neutron-openvswitch' to the new channel: 'victoria/stable' diff --git a/docs/how-to/upgrade-cloud.rst b/docs/how-to/upgrade-cloud.rst new file mode 100644 index 00000000..733fcfe9 --- /dev/null +++ b/docs/how-to/upgrade-cloud.rst @@ -0,0 +1,151 @@ +=============== +Upgrade a cloud +=============== + +Run interactive upgrades +------------------------ + +Use the **upgrade** command to automatically plan and execute the upgrade of your +cloud. This command runs upgrade in interactive mode by default, requiring the user +to confirm each step. + +.. code:: + + $ cou upgrade + +Usage example +^^^^^^^^^^^^^ + +.. code:: + + $ cou upgrade + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211917.log' + Connected to 'test-model' ✔ + Analyzing cloud... ✔ + Generating upgrade plan... ✔ + Upgrade cloud from 'ussuri' to 'victoria' + Verify that all OpenStack applications are in idle state + Backup mysql databases + Control Plane principal(s) upgrade plan + Upgrade plan for 'rabbitmq-server' to victoria + Upgrade software packages of 'rabbitmq-server' from the current APT repositories + Upgrade 'rabbitmq-server' to the new channel: '3.9/stable' + Change charm config of 'rabbitmq-server' 'source' to 'cloud:focal-victoria' + Wait 1800s for model test-model to reach the idle state. + Check if the workload of 'rabbitmq-server' has been upgraded + Upgrade plan for 'keystone' to victoria + Upgrade software packages of 'keystone' from the current APT repositories + Upgrade 'keystone' to the new channel: 'victoria/stable' + Change charm config of 'keystone' 'openstack-origin' to 'cloud:focal-victoria' + Wait 1800s for model test-model to reach the idle state. + Check if the workload of 'keystone' has been upgraded + Upgrade plan for 'cinder' to victoria + Upgrade software packages of 'cinder' from the current APT repositories + Refresh 'cinder' to the latest revision of 'ussuri/stable' + Upgrade 'cinder' to the new channel: 'victoria/stable' + Change charm config of 'cinder' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app cinder to reach the idle state. + Check if the workload of 'cinder' has been upgraded + Upgrade plan for 'glance' to victoria + Upgrade software packages of 'glance' from the current APT repositories + Upgrade 'glance' to the new channel: 'victoria/stable' + Change charm config of 'glance' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app glance to reach the idle state. + Check if the workload of 'glance' has been upgraded + Upgrade plan for 'neutron-api' to victoria + Upgrade software packages of 'neutron-api' from the current APT repositories + Upgrade 'neutron-api' to the new channel: 'victoria/stable' + Change charm config of 'neutron-api' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app neutron-api to reach the idle state. + Check if the workload of 'neutron-api' has been upgraded + Upgrade plan for 'neutron-gateway' to victoria + Upgrade software packages of 'neutron-gateway' from the current APT repositories + Upgrade 'neutron-gateway' to the new channel: 'victoria/stable' + Change charm config of 'neutron-gateway' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app neutron-gateway to reach the idle state. + Check if the workload of 'neutron-gateway' has been upgraded + Upgrade plan for 'placement' to victoria + Upgrade software packages of 'placement' from the current APT repositories + Upgrade 'placement' to the new channel: 'victoria/stable' + Change charm config of 'placement' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app placement to reach the idle state. + Check if the workload of 'placement' has been upgraded + Upgrade plan for 'nova-cloud-controller' to victoria + Upgrade software packages of 'nova-cloud-controller' from the current APT repositories + Refresh 'nova-cloud-controller' to the latest revision of 'ussuri/stable' + Upgrade 'nova-cloud-controller' to the new channel: 'victoria/stable' + Change charm config of 'nova-cloud-controller' 'openstack-origin' to 'cloud:focal-victoria' + Wait 300s for app nova-cloud-controller to reach the idle state. + Check if the workload of 'nova-cloud-controller' has been upgraded + Upgrade plan for 'mysql' to victoria + Upgrade software packages of 'mysql' from the current APT repositories + Change charm config of 'mysql' 'source' to 'cloud:focal-victoria' + Wait 1800s for app mysql to reach the idle state. + Check if the workload of 'mysql' has been upgraded + Control Plane subordinate(s) upgrade plan + Upgrade plan for 'neutron-openvswitch' to victoria + Upgrade 'neutron-openvswitch' to the new channel: 'victoria/stable' + Would you like to start the upgrade? Continue (y/N): y + Running cloud upgrade... + Verify that all OpenStack applications are in idle state ✔ + Backup mysql databases ✔ + + Upgrade plan for 'rabbitmq-server' to victoria + Upgrade software packages of 'rabbitmq-server' from the current APT repositories + Upgrade 'rabbitmq-server' to the new channel: '3.9/stable' + Change charm config of 'rabbitmq-server' 'source' to 'cloud:focal-victoria' + Wait 1800s for model test-model to reach the idle state. + Check if the workload of 'rabbitmq-server' has been upgraded + + Continue (y/n): y + Upgrade plan for 'rabbitmq-server' to victoria ✔ + + Upgrade plan for 'keystone' to victoria + Upgrade software packages of 'keystone' from the current APT repositories + Upgrade 'keystone' to the new channel: 'victoria/stable' + Change charm config of 'keystone' 'openstack-origin' to 'cloud:focal-victoria' + Wait 1800s for model test-model to reach the idle state. + Check if the workload of 'keystone' has been upgraded + + Continue (y/n): y + Upgrade software packages of 'keystone' from the current APT repositories \ + + ... # apply each step + Upgrade completed. + + +Run non-interactive upgrades +---------------------------- + +**COU** provides a non-interactive mode which suppresses user prompts. This option +allows **COU** to be used by scripts or during upgrade testing. A quiet mode switch +is also offered, which will only output error logs and a completion message to STDOUT. + +Usage examples +^^^^^^^^^^^^^^ + +Non-interactive mode: + +.. code:: + + $ cou upgrade --no-interactive + Full execution log: '/home/ubuntu/.local/share/cou/log/cou-20231215211717.log' + Connected to 'test-model' ✔ + Analyzing cloud... ✔ + Generating upgrade plan... ✔ + ... + Running cloud upgrade... + Verify that all OpenStack applications are in idle state ✔ + Backup mysql databases ✔ + Upgrade software packages of 'keystone' from the current APT repositories ✔ + Upgrade 'keystone' to the new channel: 'victoria/stable' ✔ + ... + Upgrade completed. + + +Non-interactive and quiet mode: + +.. code:: + + $ cou upgrade --no-interactive --quiet + Upgrade completed. \ No newline at end of file diff --git a/docs/how-to/verbosity.rst b/docs/how-to/verbosity.rst new file mode 100644 index 00000000..de0fda37 --- /dev/null +++ b/docs/how-to/verbosity.rst @@ -0,0 +1,36 @@ +====================== +Change verbosity level +====================== + +The verbose parameter can be used to increase the verbosity level. The parameter +can be used multiple times (up to four), increasing verbosity from error to debug +log level. + +The default verbosity level is **error**. + +Usage examples +~~~~~~~~~~~~~~ + +The warning level. + +.. code:: + + $ cou upgrade -v + +The info level. + +.. code:: + + $ cou upgrade -vv + +The debug level for all messages except **python-libjuju** and **websockets**. + +.. code:: + + $ cou upgrade -vvv + +The debug level for all messages including the **python-libjuju** and **websockets**. + +.. code:: + + $ cou upgrade -vvvv \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..6c6c722a --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,57 @@ +Charmed OpenStack Upgrader +========================== + +`Charmed OpenStack Upgrader`_ (**COU**) is an application (packaged as a snap) to upgrade +a Canonical distribution of `Charmed OpenStack`_ +in an automated and frictionless manner. The application detects the version of the +running cloud and proposes an upgrade plan to the next available OpenStack release. + +**COU** follows the steps defined in the `charm-guide`_ upgrades overview. + +Notes: + +- Currently only control plane upgrades are supported. + +- The tool supports upgrades from focal-ussuri to focal-yoga. + +Source code available on `Github`_. + +In this documentation +--------------------- + +.. grid:: 1 1 2 2 + + .. grid-item:: :doc:`Get Started ` + + **Start here** to prepare the environment and install the application + + .. grid-item:: :doc:`How-to guides ` + + **Step-by-step guides** covering key operations and common tasks + +.. grid:: 1 1 2 2 + + .. grid-item:: :doc:`Reference ` + + **Technical information** - commands, environmental variables, and known issues + + .. grid-item:: :doc:`Explanation ` + + **Additional information** - details of upgrade phases defined in **COU** + + +.. toctree:: + :hidden: + :maxdepth: 2 + + get-started/index + how-to/index + reference/index + explanation/index + +.. LINKS +.. _Charmed OpenStack Upgrader: https://snapcraft.io/charmed-openstack-upgrader +.. _Charmed OpenStack: https://ubuntu.com/openstack/docs +.. _charm-guide: https://docs.openstack.org/charm-guide/latest/admin/upgrades/overview.html +.. _Code of conduct: https://ubuntu.com/community/ethos/code-of-conduct +.. _GitHub: https://github.com/canonical/charmed-openstack-upgrader diff --git a/docs/init.sh b/docs/init.sh new file mode 100755 index 00000000..f6f02269 --- /dev/null +++ b/docs/init.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Generate a unique directory name based on timestamp +timestamp=$(date +%Y%m%d%H%M%S) +temp_directory="temp-starter-pack-$timestamp" + +# Ask the user for the installation directory +read -p "Enter the installation directory (e.g., '.' or 'docs'): " install_directory + +# Clone the starter pack repository to the temporary directory +echo "Cloning the starter pack repository..." +git clone --depth 1 https://github.com/canonical/sphinx-docs-starter-pack "$temp_directory" +rm -rf "$temp_directory/.git" + +# Update file contents for the install directory +echo "Updating working directory in workflow files..." +sed -i "s|working-directory:\s*'\.'|working-directory: '$install_directory'|g" "$temp_directory/.github/workflows"/* +echo "Updating .readthedocs.yaml configuration..." +sed -i "s|configuration:\s*conf\.py|configuration: $install_directory/conf.py|g" "$temp_directory/.readthedocs.yaml" +sed -i "s|requirements:\s*\.sphinx/requirements\.txt|requirements: $install_directory/.sphinx/requirements.txt|g" "$temp_directory/.readthedocs.yaml" + +# Create the specified installation directory if it doesn't exist +if [ ! -d "$install_directory" ]; then + echo "Creating the installation directory: $install_directory" + mkdir -p "$install_directory" +fi + +# Copy the contents of the starter pack repository to the installation directory +echo "Copying contents to the installation directory..." +cp -R "$temp_directory"/* "$temp_directory"/.??* "$install_directory" + +# Move workflow files and configuration +if [ "$install_directory" != "." ]; then + echo "Moving workflow files and configuration..." + if [ ! -d .github/workflows ]; then + mkdir -p .github/workflows + fi + mv "$install_directory/.github/workflows"/* .github/workflows + if [ ! -f .wokeignore ]; then + ln -s "$install_directory/.wokeignore" + else + echo "ACTION REQUIRED: Found a .wokeignore file in the root directory. Include the contents from $install_directory/.wokeignore in this file!" + fi +fi + +# Clean up +echo "Cleaning up..." +rm -rf "$temp_directory" + +echo "Setup completed!" diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..32bb2452 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/pa11y.json b/docs/pa11y.json new file mode 100644 index 00000000..8df0cb9c --- /dev/null +++ b/docs/pa11y.json @@ -0,0 +1,9 @@ +{ + "chromeLaunchConfig": { + "args": [ + "--no-sandbox" + ] + }, + "reporter": "cli", + "standard": "WCAG2AA" +} \ No newline at end of file diff --git a/docs/readme.rst b/docs/readme.rst new file mode 100644 index 00000000..5957c891 --- /dev/null +++ b/docs/readme.rst @@ -0,0 +1,296 @@ +Documentation starter pack +========================== + +See the `Read the Docs at Canonical `_ and +`How to publish documentation on Read the Docs `_ guides for +instructions on how to get started with Sphinx documentation. + +Then go through the following sections to use this starter pack to set up your docs repository. + +**Note:** After setting up your repository with the starter pack, you need to track the changes made to it and manually update your repository with the required files. +The `change log `_ lists the most relevant (and of course all breaking) changes. +We're planning to provide the contents of this repository as an installable package in the future to make updates easier. + +Set up your documentation repository +------------------------------------ + +You can either create a standalone documentation project based on this repository or include the files from this repository in a dedicated documentation folder in an existing code repository. + +The next two sections provide manual steps for enabling the starter pack for your repository. See `Setup script `_ for an automated method (currently in beta). + +Standalone documentation repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To create a standalone documentation repository, clone this starter pack +repository, `update the configuration <#configure-the-documentation>`_, and +then commit all files to the documentation repository. + +You don't need to move any files, and you don't need to do any special +configuration on Read the Docs. + +Here is one way to do this for newly-created fictional docs repository +``canonical/alpha-docs``: + +.. code-block:: none + + git clone git@github.com:canonical/sphinx-docs-starter-pack alpha-docs + cd alpha-docs + rm -rf .git + git init + git branch -m main + UPDATE THE CONFIGURATION AND BUILD THE DOCS + git add -A + git commit -m "Import sphinx-docs-starter-pack" + git remote add upstream git@github.com:canonical/alpha-docs + git push -f upstream main + +Documentation in a code repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To add documentation to an existing code repository: + +#. create a directory called ``docs`` at the root of the code repository +#. populate the above directory with the contents of the starter pack + repository (with the exception of the ``.git`` directory) +#. copy the file(s) located in the ``docs/.github/workflows`` directory into + the code repository's ``.github/workflows`` directory +#. in the above workflow file(s), change the value of the ``working-directory`` field from ``.`` to ``docs`` +#. create a symbolic link to the ``docs/.wokeignore`` file from the root directory of the code repository +#. in file ``docs/.readthedocs.yaml`` set the following: + + * ``configuration: docs/conf.py`` + * ``requirements: docs/.sphinx/requirements.txt`` + +**Note:** When configuring RTD itself for your project, the setting "Path for +``.readthedocs.yaml``" (under **Advanced Settings**) will need to be given the +value of ``docs/.readthedocs.yaml``. + +Getting started +--------------- + +There are make targets defined in the ``Makefile`` that do various things. To +get started, we will: + +* install prerequisite software +* view the documentation + +Install prerequisite software +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To install the prerequisites: + +.. code-block:: none + + make install + +This will create a virtual environment (``.sphinx/venv``) and install +dependency software (``.sphinx/requirements.txt``) within it. + +**Note**: +By default, the starter pack uses the latest compatible version of all tools and does not pin its requirements. +This might change temporarily if there is an incompatibility with a new tool version. +There is therefore no need in using a tool like Renovate to automatically update the requirements. + +View the documentation +~~~~~~~~~~~~~~~~~~~~~~ + +To view the documentation: + +.. code-block:: none + + make run + +This will do several things: + +* activate the virtual environment +* build the documentation +* serve the documentation on **127.0.0.1:8000** +* rebuild the documentation each time a file is saved +* send a reload page signal to the browser when the documentation is rebuilt + +The ``run`` target is therefore very convenient when preparing to submit a +change to the documentation. + +.. note:: + + If you encounter the error ``locale.Error: unsupported locale setting`` when activating the Python virtual environment, include the environment variable in the command and try again: ``LC_ALL=en_US.UTF-8 make run`` + +Local checks +~~~~~~~~~~~~ + +Before committing and pushing changes, it's a good practice to run various checks locally to catch issues early in the development process. + +Local build +^^^^^^^^^^^ + +Run a clean build of the docs to surface any build errors that would occur in RTD: + +.. code-block:: none + + make clean-doc + make html + +Spelling check +^^^^^^^^^^^^^^ + +Ensure there are no spelling errors in the documentation: + +.. code-block:: shell + + make spelling + +Inclusive language check +^^^^^^^^^^^^^^^^^^^^^^^^ + +Ensure the documentation uses inclusive language: + +.. code-block:: shell + + make woke + +Link check +^^^^^^^^^^ + +Validate links within the documentation: + +.. code-block:: shell + + make linkcheck + +Configure the documentation +--------------------------- + +You must modify some of the default configuration to suit your project. +To simplify keeping your documentation in sync with the starter pack, all custom configuration is located in the ``custom_conf.py`` file. +You should never modify the common ``conf.py`` file. + +Go through all settings in the ``Project information`` section of the ``custom_conf.py`` file and update them for your project. + +See the following sections for further customisation. + +Configure the header +~~~~~~~~~~~~~~~~~~~~ + +By default, the header contains your product tag, product name (taken from the ``project`` setting in the ``custom_conf.py`` file), a link to your product page, and a drop-down menu for "More resources" that contains links to Discourse and GitHub. + +You can change any of those links or add further links to the "More resources" drop-down by editing the ``.sphinx/_templates/header.html`` file. +For example, you might want to add links to announcements, tutorials, getting started guides, or videos that are not part of the documentation. + +Configure the spelling check +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The spelling check uses ``aspell``. +Its configuration is located in the ``.sphinx/spellingcheck.yaml`` file. + +To add exceptions for words flagged by the spelling check, edit the ``.custom_wordlist.txt`` file. +You shouldn't edit ``.wordlist.txt``, because this file is maintained and updated centrally and contains words that apply across all projects. + +Customisation of inclusive language checks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, the inclusive language check is applied only to reST files located +under the documentation directory (usually ``docs``). To check Markdown files, +for example, or to use a location other than the ``docs`` sub-tree, you must +change how the ``woke`` tool is invoked from within ``docs/Makefile`` (see +the `woke User Guide `_ for help). + +Some circumstances may require you to use some non-inclusive words. In such +cases you will need to create check-exemptions for them. See file +:doc:`help-woke` for how to do that. + +Configure the link check +~~~~~~~~~~~~~~~~~~~~~~~~ + +If you have links in the documentation that you don't want to be checked (for +example, because they are local links or give random errors even though they +work), you can add them to the ``linkcheck_ignore`` variable in the ``custom_conf.py`` file. + +Activate/deactivate feedback button +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A feedback button is included by default, which appears at the top of each page +in the documentation. It redirects users to your GitHub issues page, and +populates an issue for them with details of the page they were on when they +clicked the button. + +If your project does not use GitHub issues, set the ``github_issues`` variable +in the ``custom_conf.py`` file to an empty value to disable both the feedback button +and the issue link in the footer. +If you want to deactivate only the feedback button, but keep the link in the +footer, set ``disable_feedback_button`` in the ``custom_conf.py`` file to ``True``. + +Add redirects +~~~~~~~~~~~~~ + +You can add redirects to make sure existing links and bookmarks continue working when you move files around. +To do so, specify the old and new paths in the ``redirects`` setting of the ``custom_conf.py`` file. + +Configure included extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The starter pack includes a set of extensions that are useful for all documentation sets. +They are pre-configured as needed, but you can customise their configuration in the ``custom_conf.py`` file. + +The following extensions are always included: + +- |sphinx-design|_ +- |sphinx_tabs.tabs|_ +- |sphinx_reredirects|_ +- |lxd-sphinx-extensions|_ (``youtube-links``, ``related-links``, ``custom-rst-roles``, and ``terminal-output``) +- |sphinx_copybutton|_ +- |sphinxext.opengraph|_ +- |myst_parser|_ +- |sphinxcontrib.jquery|_ +- |notfound.extension|_ + +You can add further extensions in the ``custom_extensions`` variable in ``custom_conf.py``. + +Add custom configuration +~~~~~~~~~~~~~~~~~~~~~~~~ + +To add custom configurations for your project, see the ``Additions to default configuration`` and ``Additional configuration`` sections in the ``custom_conf.py`` file. +These can be used to extend or override the common configuration, or to define additional configuration that is not covered by the common ``conf.py`` file. + +The following links can help you with additional configuration: + +- `Sphinx configuration`_ +- `Sphinx extensions`_ +- `Furo documentation`_ (Furo is the Sphinx theme we use as our base.) + +Other resources +--------------- + +- `Example product documentation `_ +- `Example product documentation repository `_ + +Change log +---------- + +See the `change log `_ for a list of relevant changes to the starter pack. + +.. LINKS + +.. wokeignore:rule=master +.. _`Sphinx configuration`: https://www.sphinx-doc.org/en/master/usage/configuration.html +.. wokeignore:rule=master +.. _`Sphinx extensions`: https://www.sphinx-doc.org/en/master/usage/extensions/index.html +.. _`Furo documentation`: https://pradyunsg.me/furo/quickstart/ + +.. |sphinx-design| replace:: ``sphinx-design`` +.. _sphinx-design: https://sphinx-design.readthedocs.io/en/latest/ +.. |sphinx_tabs.tabs| replace:: ``sphinx_tabs.tabs`` +.. _sphinx_tabs.tabs: https://sphinx-tabs.readthedocs.io/en/latest/ +.. |sphinx_reredirects| replace:: ``sphinx_reredirects`` +.. _sphinx_reredirects: https://documatt.gitlab.io/sphinx-reredirects/ +.. |lxd-sphinx-extensions| replace:: ``lxd-sphinx-extensions`` +.. _lxd-sphinx-extensions: https://github.com/canonical/lxd-sphinx-extensions#lxd-sphinx-extensions +.. |sphinx_copybutton| replace:: ``sphinx_copybutton`` +.. _sphinx_copybutton: https://sphinx-copybutton.readthedocs.io/en/latest/ +.. |sphinxext.opengraph| replace:: ``sphinxext.opengraph`` +.. _sphinxext.opengraph: https://sphinxext-opengraph.readthedocs.io/en/latest/ +.. |myst_parser| replace:: ``myst_parser`` +.. _myst_parser: https://myst-parser.readthedocs.io/en/latest/ +.. |sphinxcontrib.jquery| replace:: ``sphinxcontrib.jquery`` +.. _sphinxcontrib.jquery: https://github.com/sphinx-contrib/jquery/ +.. |notfound.extension| replace:: ``notfound.extension`` +.. _notfound.extension: https://sphinx-notfound-page.readthedocs.io/en/latest/ diff --git a/docs/reference/commands.rst b/docs/reference/commands.rst new file mode 100644 index 00000000..9f7c22cd --- /dev/null +++ b/docs/reference/commands.rst @@ -0,0 +1,55 @@ +======== +Commands +======== + +**COU** offers only two commands; bash completion further simplifies its usage. + +Plan +---- + +The **plan** command will analyse the cloud and output a human-readable representation +of the proposed upgrade plan. It does not require any interaction. Refer to the +output below for a description of all allowed options. + +.. code:: + + $ cou plan --help + Usage: cou plan [options] + + Show the steps COU will take to upgrade the cloud to the next release. + + Options: + -h, --help Show this help message and exit. + --model MODEL_NAME Set the model to operate on. + If not set, the currently active Juju model will be used. + --backup, --no-backup + Include database backup step before cloud upgrade. + Default to enabling database backup. + --verbose, -v Increase logging verbosity in STDOUT. Multiple 'v's yield progressively more detail (up to 4). + Note that by default the logfile will include standard logs from juju and websockets, as well as debug logs from all other modules. To also include the debug level logs from juju and websockets modules, use the maximum verbosity. + --quiet, -q Disable output in STDOUT. + +Upgrade +------- + +The **upgrade** command will implicitly generate a plan before moving onto the actual +upgrade phase. Refer to the output below for a description of all available options. + +.. code:: + $ cou upgrade --help + Usage: cou upgrade [options] + + Run the cloud upgrade. + + Options: + -h, --help Show this help message and exit. + --model MODEL_NAME Set the model to operate on. + If not set, the currently active Juju model will be used. + --backup, --no-backup + Include database backup step before cloud upgrade. + Default to enabling database backup. + --verbose, -v Increase logging verbosity in STDOUT. Multiple 'v's yield progressively more detail (up to 4). + Note that by default the logfile will include standard logs from juju and websockets, as well as debug logs from all other modules. To also include the debug level logs from juju and websockets modules, use the maximum verbosity. + --quiet, -q Disable output in STDOUT. + --auto-approve Automatically approve and continue with each upgrade step without prompt. + diff --git a/docs/reference/environment-variables.rst b/docs/reference/environment-variables.rst new file mode 100644 index 00000000..9dba5d55 --- /dev/null +++ b/docs/reference/environment-variables.rst @@ -0,0 +1,8 @@ +===================== +Environment Variables +===================== + +* **JUJU_DATA** - sets the path containing Juju configuration files (e.g. credentials.yaml). Defaults to ~/.local/share/juju +* **COU_TIMEOUT** - define timeout for **COU** retry policy. Default value is 10 seconds. +* **COU_MODEL_RETRIES** - define how many times to retry the connection to Juju model before giving up. Default value is 5 times. +* **COU_MODEL_RETRY_BACKOFF** - define number of seconds to increase the wait between connection to the Juju model retry attempts. Default value is 2 seconds. diff --git a/docs/reference/index.rst b/docs/reference/index.rst new file mode 100644 index 00000000..785b9782 --- /dev/null +++ b/docs/reference/index.rst @@ -0,0 +1,12 @@ +========= +Reference +========= + +This section explains the list of available commands and environmental variables. + +.. toctree:: + :maxdepth: 1 + + commands + environment-variables + known-issues diff --git a/docs/reference/known-issues.rst b/docs/reference/known-issues.rst new file mode 100644 index 00000000..8645f20d --- /dev/null +++ b/docs/reference/known-issues.rst @@ -0,0 +1,10 @@ +============ +Known issues +============ + +Potential known upgrade bugs and non-standard procedures are listed in the OpenStack Charm Guide: + +- `Issues, charm procedures, and OpenStack upgrade notes`_ + +.. LINKS: +.. _Issues, charm procedures, and OpenStack upgrade notes: https://docs.openstack.org/charm-guide/latest/project/issues-and-procedures.html \ No newline at end of file diff --git a/docs/reuse/links.txt b/docs/reuse/links.txt new file mode 100644 index 00000000..04cfff56 --- /dev/null +++ b/docs/reuse/links.txt @@ -0,0 +1,4 @@ +.. _reStructuredText style guide: https://canonical-documentation-with-sphinx-and-readthedocscom.readthedocs-hosted.com/style-guide/ +.. _Read the Docs at Canonical: https://library.canonical.com/documentation/read-the-docs +.. _How to publish documentation on Read the Docs: https://library.canonical.com/documentation/publish-on-read-the-docs +.. _Example product documentation: https://canonical-example-product-documentation.readthedocs-hosted.com/ diff --git a/docs/setup-script.rst b/docs/setup-script.rst new file mode 100644 index 00000000..f0e471fe --- /dev/null +++ b/docs/setup-script.rst @@ -0,0 +1,34 @@ +Setup script +============ + +An alternative to the manual setup steps is to use a setup script to automatically initialise your repository using the starter pack. This script is provided as a beta feature: use it with care and check all changes manually before committing them to your repository. + +Prerequisites +~~~~~~~~~~~~~ + +Before you begin, ensure you have the following: + +* A GitHub repository where you want to host your documentation, cloned to your local machine. The recommended approach is to host the documentation alongside your code in a `docs` folder. But a standalone documentation repository is also an option; in this case, start with an empty repository. +* Git and Bash installed on your system. + +Initialise your documentation repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``init.sh`` Bash script is used to initialise your repository with the starter pack content. It adds all the files to your repository that are needed to get started with Sphinx documentation. + +To use the script, follow these steps: + +* Copy ``init.sh`` to your repository's root directory. +* Run the script: ``./init.sh`` +* Enter the installation directory when prompted. For standalone repositories, enter ".". For documentation alongside code, enter the folder where your documentation are e.g. "docs". + +This Bash script does the following: + +* Clones the starter pack GitHub repository +* Creates the specified installation directory if necessary +* Updates working directory paths in workflow files, and updates configuration paths in the ``.readthedocs.yaml`` file +* Copies and moves contents and ``.github`` files from the starter pack to the installation directory +* Deletes the cloned repository when it's done + +When the script completes, review all changes before committing, then commit your changes. + diff --git a/pyproject.toml b/pyproject.toml index a07d6275..82399639 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ [tool.flake8] ignore = ["C901", "D100", "D101", "D102", "D103", "W503", "W504"] -exclude = ['.eggs', '.git', '.tox', '.venv', '.build', 'build', 'report'] +exclude = ['.eggs', '.git', '.tox', '.venv', '.build', 'build', 'report', 'docs'] max-line-length = 99 max-complexity = 10 @@ -19,6 +19,7 @@ exclude = ''' | .build | build | report + | docs )/ ''' @@ -31,7 +32,8 @@ skip_glob = [ ".venv", ".build", "build", - "report" + "report", + "docs" ] [tool.pylint] @@ -45,7 +47,8 @@ ignore-paths = [ ".build", "build", "report", - "tests" + "tests", + "docs" ] no-docstring-rgx = "__.*__" default-docstring-type = "sphinx" @@ -69,7 +72,8 @@ exclude = [ "build", "lib", "report", - "tests" + "tests", + "docs" ] [tool.coverage.run] @@ -89,7 +93,7 @@ directory = "tests/unit/report/html" output = "tests/unit/report/coverage.xml" [tool.codespell] -skip = ".eggs,.tox,.git,.venv,venv,build,.build,lib,report" +skip = ".eggs,.tox,.git,.venv,venv,build,.build,lib,report,docs" quiet-level = 3 check-filenames = true