├── .gitignore ├── .wokeignore ├── revive.toml ├── .github ├── labeler.yml ├── renovate.json ├── workflows │ ├── triage.yml │ ├── commits.yml │ ├── codeql.yml │ └── security.yml ├── dependabot.yml └── .jira_sync_config.yaml ├── doc ├── .sphinx │ ├── _static │ │ ├── tag.png │ │ ├── favicon.png │ │ ├── header-nav.js │ │ ├── footer.js │ │ ├── github_issue_links.css │ │ ├── footer.css │ │ ├── github_issue_links.js │ │ ├── 404.svg │ │ ├── header.css │ │ └── furo_colors.css │ ├── _integration │ │ ├── tag.png │ │ ├── rtd-search.js │ │ ├── add_config.py │ │ ├── microovn.html │ │ ├── microceph.html │ │ ├── microcloud.html │ │ ├── lxd.html │ │ └── header.css │ ├── pa11y.json │ ├── _templates │ │ ├── base.html │ │ ├── sidebar │ │ │ └── search.html │ │ ├── 404.html │ │ ├── header.html │ │ ├── page.html │ │ └── footer.html │ ├── spellingcheck.yaml │ ├── get_vale_conf.py │ └── build_requirements.py ├── images │ ├── ui_instances.png │ ├── ui_security_warning.png │ ├── ui_certificate_selection.png │ ├── microcloud_logo_dark.svg │ └── microcloud_logo_light.svg ├── .wokeignore ├── .gitignore ├── explanation │ └── index.md ├── integration │ └── README.md ├── .custom_wordlist.txt ├── .wordlist.txt ├── how-to │ ├── index.md │ ├── support.md │ ├── add_service.md │ ├── add_machine.md │ ├── remove_machine.md │ ├── shutdown_machine.md │ ├── recover.md │ ├── install.md │ ├── snaps.md │ ├── ovn_underlay.md │ └── preseed.yaml ├── .readthedocs.yaml ├── index.md ├── reference │ └── index.md └── Makefile.sp ├── api ├── types │ ├── version.go │ ├── status.go │ ├── services.go │ └── session.go ├── session_stop.go ├── response.go ├── services_tokens.go ├── services.go ├── services_auth.go └── session_join.go ├── staticcheck.conf ├── multicast ├── version.go ├── info.go └── discovery_test.go ├── service ├── test_wordlist.go ├── interface.go ├── version.go ├── lxd_join.go ├── version_test.go └── lxd_test.go ├── test ├── lint │ ├── capitalize-errors.sh │ ├── no-oneline-assign-and-test.sh │ ├── no-short-form-imports.sh │ ├── negated-is-bool.sh │ └── newline-after-block.sh ├── includes │ └── check.sh └── suites │ └── recover.sh ├── .golangci.yml ├── cmd ├── microcloud │ ├── input.go │ ├── waitready.go │ ├── shutdown.go │ ├── remove.go │ ├── test_input.go │ ├── sql.go │ ├── tokens.go │ ├── main.go │ └── join.go └── tui │ ├── table.go │ ├── asker.go │ ├── console.go │ └── handler.go ├── SECURITY.md ├── version └── version.go ├── client ├── proxy.go └── client.go ├── Makefile ├── go.mod └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.snap 2 | -------------------------------------------------------------------------------- /.wokeignore: -------------------------------------------------------------------------------- 1 | doc/.wokeignore -------------------------------------------------------------------------------- /revive.toml: -------------------------------------------------------------------------------- 1 | [rule.exported] 2 | Arguments = ["checkPrivateReceivers"] 3 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | Documentation: 2 | - changed-files: 3 | - any-glob-to-any-file: 4 | - doc/**/* -------------------------------------------------------------------------------- /doc/.sphinx/_static/tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/microcloud/main/doc/.sphinx/_static/tag.png -------------------------------------------------------------------------------- /doc/images/ui_instances.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/microcloud/main/doc/images/ui_instances.png -------------------------------------------------------------------------------- /api/types/version.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // APIVersion is the current API version. 4 | const APIVersion = "1.0" 5 | -------------------------------------------------------------------------------- /doc/.sphinx/_integration/tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/microcloud/main/doc/.sphinx/_integration/tag.png -------------------------------------------------------------------------------- /doc/.sphinx/_static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/microcloud/main/doc/.sphinx/_static/favicon.png -------------------------------------------------------------------------------- /doc/images/ui_security_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/microcloud/main/doc/images/ui_security_warning.png -------------------------------------------------------------------------------- /doc/images/ui_certificate_selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/microcloud/main/doc/images/ui_certificate_selection.png -------------------------------------------------------------------------------- /staticcheck.conf: -------------------------------------------------------------------------------- 1 | # Checks being ignored: 2 | # ST1005: error strings should not be capitalized 3 | checks = ["inherit", "-ST1005"] 4 | -------------------------------------------------------------------------------- /multicast/version.go: -------------------------------------------------------------------------------- 1 | package multicast 2 | 3 | // Version is the current version of the multicast discovery format. 4 | const Version = "2.0" 5 | -------------------------------------------------------------------------------- /doc/.sphinx/pa11y.json: -------------------------------------------------------------------------------- 1 | { 2 | "chromeLaunchConfig": { 3 | "args": [ 4 | "--no-sandbox" 5 | ] 6 | }, 7 | "reporter": "cli", 8 | "standard": "WCAG2AA" 9 | } -------------------------------------------------------------------------------- /service/test_wordlist.go: -------------------------------------------------------------------------------- 1 | //go:build test 2 | 3 | package service 4 | 5 | // Testing wordlist that will always print `a a a a`. 6 | var wordlist = `1 a 7 | 2 a 8 | 3 a 9 | 4 a` 10 | -------------------------------------------------------------------------------- /test/lint/capitalize-errors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | echo "Checking for error messages beginning with lower-case letters..." 4 | 5 | ! git grep --untracked -P -n 'fmt\.Errorf\("[a-z]' -- '*.go' 6 | -------------------------------------------------------------------------------- /doc/.wokeignore: -------------------------------------------------------------------------------- 1 | # the cheat sheets contain a link to a repository with a block word which we 2 | # cannot avoid for now, ie 3 | # https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html 4 | doc-cheat-sheet* 5 | -------------------------------------------------------------------------------- /test/lint/no-oneline-assign-and-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | echo "Checking for oneline assign & test..." 4 | 5 | # Recursively grep go files for if statements that contain assignments. 6 | ! git grep --untracked -P -n '^\s+if.*:=.*;.*{\s*$' -- '*.go' 7 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "enabled": false, 4 | "dependencyDashboard": false, 5 | "extends": [ 6 | "config:recommended", 7 | ":disableDependencyDashboard" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | enable: 3 | - gofmt 4 | - misspell 5 | - godot 6 | - whitespace 7 | - gci 8 | linters-settings: 9 | gci: 10 | sections: 11 | - standard 12 | - default 13 | - prefix(github.com/canonical/microcloud/microcloud) 14 | -------------------------------------------------------------------------------- /test/lint/no-short-form-imports.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | echo "Checking for short form imports..." 4 | 5 | OUT=$(git grep --untracked -n -P '^\s*import\s+"' '*.go' | grep -v ':import "C"$' || true) 6 | if [ -n "${OUT}" ]; then 7 | echo "ERROR: found short form imports: ${OUT}" 8 | exit 1 9 | fi 10 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | /*env*/ 2 | .sphinx/venv/ 3 | .sphinx/requirements.txt 4 | .sphinx/warnings.txt 5 | .sphinx/.wordlist.dic 6 | .sphinx/.doctrees/ 7 | .sphinx/node_modules/ 8 | package*.json 9 | _build 10 | .DS_Store 11 | __pycache__ 12 | .idea/ 13 | .vscode/ 14 | .sphinx/styles/* 15 | .sphinx/vale.ini 16 | integration/ 17 | -------------------------------------------------------------------------------- /doc/.sphinx/_static/header-nav.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $(document).on("click", function () { 3 | $(".more-links-dropdown").hide(); 4 | }); 5 | 6 | $('.nav-more-links').click(function(event) { 7 | $('.more-links-dropdown').toggle(); 8 | event.stopPropagation(); 9 | }); 10 | }) 11 | -------------------------------------------------------------------------------- /doc/.sphinx/_integration/rtd-search.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("readthedocs-addons-data-ready", function(event) { 2 | document.querySelector("[role='search'] input").addEventListener("focusin", function() { 3 | const event = new CustomEvent("readthedocs-search-show"); 4 | document.dispatchEvent(event); 5 | }); 6 | }); 7 | -------------------------------------------------------------------------------- /test/lint/negated-is-bool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | echo "Checking usage of negated shared.Is(True|False)*() functions..." 4 | 5 | OUT=$(git grep --untracked -P '!(shared\.)?Is(True|False).*\(' '*.go' || true) 6 | if [ -n "${OUT}" ]; then 7 | echo "ERROR: negated shared.Is(True|False)*() function in script: ${OUT}" 8 | exit 1 9 | fi 10 | -------------------------------------------------------------------------------- /doc/explanation/index.md: -------------------------------------------------------------------------------- 1 | (explanation)= 2 | # Explanation 3 | 4 | The explanatory guides in this section introduce you to the concepts used in MicroCloud and help you understand how things fit together. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | 9 | /explanation/microcloud 10 | Initialisation process 11 | ``` 12 | -------------------------------------------------------------------------------- /doc/integration/README.md: -------------------------------------------------------------------------------- 1 | This folder is populated with `make doc-integrate` (from the root of the repository) or `make integrate` (from the doc folder). 2 | The subfolders are clones of the respective repositories and should not be checked in or modified. 3 | 4 | Some of the files are overridden by modified variants. 5 | These modified files are stored in doc/.sphinx/_integration/. 6 | -------------------------------------------------------------------------------- /doc/.sphinx/_static/footer.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $(document).on("click", function () { 3 | $(".all-contributors").hide(); 4 | $("#overlay").hide(); 5 | }); 6 | 7 | $('.display-contributors').click(function(event) { 8 | $('.all-contributors').toggle(); 9 | $("#overlay").toggle(); 10 | event.stopPropagation(); 11 | }); 12 | }) 13 | -------------------------------------------------------------------------------- /doc/.sphinx/_templates/base.html: -------------------------------------------------------------------------------- 1 | {% extends "furo/base.html" %} 2 | 3 | {% block theme_scripts %} 4 | 7 | {% endblock theme_scripts %} 8 | 9 | {# ru-fu: don't include the color variables from the conf.py file, but use a 10 |  separate CSS file to save space #} 11 | {% block theme_styles %} 12 | {% endblock theme_styles %} 13 | -------------------------------------------------------------------------------- /cmd/microcloud/input.go: -------------------------------------------------------------------------------- 1 | //go:build !test 2 | 3 | package main 4 | 5 | import ( 6 | "context" 7 | "os" 8 | 9 | "github.com/canonical/microcloud/microcloud/cmd/tui" 10 | ) 11 | 12 | func setupAsker(ctx context.Context) (*tui.InputHandler, error) { 13 | noColor := os.Getenv("NO_COLOR") 14 | if noColor != "" { 15 | tui.DisableColors() 16 | } 17 | 18 | return tui.NewInputHandler(os.Stdin, os.Stdout), nil 19 | } 20 | -------------------------------------------------------------------------------- /doc/.sphinx/_templates/sidebar/search.html: -------------------------------------------------------------------------------- 1 |
7 | 8 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | To report a security issue, file a [Private Security 2 | Report](https://github.com/canonical/microcloud/security/advisories/new) with 3 | a description of the issue, the steps you took to create the issue, affected 4 | versions, and, if known, mitigations for the issue. 5 | 6 | The [Ubuntu Security disclosure and embargo 7 | policy](https://ubuntu.com/security/disclosure-policy) contains more 8 | information about what you can expect when you contact us and what we expect 9 | from you. 10 | -------------------------------------------------------------------------------- /doc/.custom_wordlist.txt: -------------------------------------------------------------------------------- 1 | ACL 2 | ACLs 3 | AGPLv 4 | backend 5 | balancers 6 | Ceph 7 | Ceph's 8 | CephFS 9 | CIDR 10 | DCO 11 | DHCP 12 | disaggregate 13 | disaggregated 14 | DNS 15 | FDE 16 | GiB 17 | HA 18 | HWE 19 | intra 20 | IOV 21 | IPs 22 | IPv 23 | LTS 24 | LXD 25 | LXD's 26 | mDNS 27 | MicroCeph 28 | MicroCloud 29 | MicroCloud's 30 | MicroOVN 31 | multicast 32 | NAT 33 | NVMe 34 | OVN 35 | pre 36 | preseed 37 | rollout 38 | roadmap 39 | snapd 40 | subnet 41 | uplink 42 | VLAN 43 | VM 44 | VMs 45 | ZFS 46 | subnets 47 | GbE 48 | QSFP 49 | OSDs 50 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | // Package version provides shared version information. 2 | package version 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | // RawVersion is the current daemon version of MicroCloud. 9 | // LTS versions also include the patch number. 10 | const RawVersion = "2.1.0" 11 | 12 | // LTS should be set if the current version is an LTS (long-term support) version. 13 | const LTS = true 14 | 15 | // Version appends "LTS" to the raw version string if MicroCloud is an LTS version. 16 | func Version() string { 17 | if LTS { 18 | return fmt.Sprintf("%s LTS", RawVersion) 19 | } 20 | 21 | return RawVersion 22 | } 23 | -------------------------------------------------------------------------------- /doc/.sphinx/_static/github_issue_links.css: -------------------------------------------------------------------------------- 1 | .github-issue-link-container { 2 | padding-right: 0.5rem; 3 | } 4 | .github-issue-link { 5 | font-size: var(--font-size--small); 6 | font-weight: bold; 7 | background-color: #D6410D; 8 | padding: 13px 23px; 9 | text-decoration: none; 10 | } 11 | .github-issue-link:link { 12 | color: #FFFFFF; 13 | } 14 | .github-issue-link:visited { 15 | color: #FFFFFF 16 | } 17 | .muted-link.github-issue-link:hover { 18 | color: #FFFFFF; 19 | text-decoration: underline; 20 | } 21 | .github-issue-link:active { 22 | color: #FFFFFF; 23 | text-decoration: underline; 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/triage.yml: -------------------------------------------------------------------------------- 1 | name: Triaging 2 | on: 3 | pull_request_target: 4 | issues: 5 | types: 6 | - labeled 7 | - unlabeled 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | label: 14 | if: github.event.pull_request 15 | permissions: 16 | contents: read # for actions/labeler to determine modified files 17 | pull-requests: write # for actions/labeler to add labels to PRs 18 | name: PR labels 19 | runs-on: ubuntu-22.04 20 | steps: 21 | - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 22 | with: 23 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 24 | sync-labels: true -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | labels: [] 6 | schedule: 7 | interval: "weekly" 8 | target-branch: "main" 9 | 10 | - package-ecosystem: "gomod" 11 | directory: "/" 12 | labels: [] 13 | schedule: 14 | interval: "weekly" 15 | target-branch: "main" 16 | 17 | - package-ecosystem: "github-actions" 18 | directory: "/" 19 | labels: [] 20 | schedule: 21 | interval: "weekly" 22 | target-branch: "v2-edge" 23 | 24 | - package-ecosystem: "gomod" 25 | directory: "/" 26 | labels: [] 27 | schedule: 28 | interval: "weekly" 29 | target-branch: "v2-edge" 30 | -------------------------------------------------------------------------------- /doc/.sphinx/spellingcheck.yaml: -------------------------------------------------------------------------------- 1 | matrix: 2 | - name: rST files 3 | aspell: 4 | lang: en 5 | d: en_GB 6 | dictionary: 7 | wordlists: 8 | - .wordlist.txt 9 | - .custom_wordlist.txt 10 | output: .sphinx/.wordlist.dic 11 | sources: 12 | - _build/**/*.html 13 | pipeline: 14 | - pyspelling.filters.html: 15 | comments: false 16 | attributes: 17 | - title 18 | - alt 19 | ignores: 20 | - code 21 | - pre 22 | - spellexception 23 | - .spellexception 24 | - link 25 | - title 26 | - div.relatedlinks 27 | - strong.command 28 | - div.visually-hidden 29 | - img 30 | - a.p-navigation__link 31 | - a.contributor 32 | -------------------------------------------------------------------------------- /doc/.sphinx/_templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "page.html" %} 2 | 3 | {% block content -%} 4 |