├── .devcontainer ├── .dockerfile ├── devcontainer.json └── docker-compose.yaml ├── .githooks └── pre-push ├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE │ ├── 1-enhancement.yml │ ├── 2-bug.yml │ ├── 3-problem-statement.yml │ ├── 4-business-feature-twg.yml │ ├── 5-technical-feature-twg.yml │ └── config.yml ├── pull_request_template.md └── workflows │ ├── pages.yml │ └── pr-checks.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── assets └── margo-logo.svg ├── doc-generation ├── check-examples.bash ├── configurations │ ├── application-package-api.json │ └── desired-state-api.json └── generate-documentation.bash ├── mkdocs.yml ├── poetry.lock ├── pyproject.toml ├── src └── margo-api-reference │ └── workload-api │ ├── application-package-api │ ├── application-description.linkml.yaml │ └── resources │ │ ├── class.md.jinja2 │ │ ├── examples │ │ └── valid │ │ │ ├── ApplicationDescription-001.yaml │ │ │ └── ApplicationDescription-002.yaml │ │ └── index.md.jinja2 │ └── desired-state-api │ ├── desired-state.linkml.yaml │ └── resources │ ├── examples │ ├── invalid │ │ ├── DesiredState-001.yaml │ │ ├── DesiredState-002.yaml │ │ ├── DesiredState-003.yaml │ │ └── DesiredState-004.yaml │ └── valid │ │ ├── DesiredState-001.yaml │ │ └── DesiredState-002.yaml │ └── index.md.jinja2 └── system-design ├── CNAME ├── app-interoperability ├── .gitignore ├── application-package-definition.md ├── local-registries.md ├── publishing-workload-observability-data.md └── workload-orch-to-app-reg-interaction.md ├── assets ├── favicon.ico └── margo_white.svg ├── css └── margo.css ├── device-interoperability ├── collecting-workload-observability-data.md └── device-requirements.md ├── figures ├── System-design-observability-deployment1.drawio.svg ├── System-design-observability-deployment2.drawio.svg ├── System-design-observability.drawio.svg ├── System-design-workload-orchestration-agent-apply-desired.drawio.svg ├── System-design-workload-orchestration-agent-repository-traffic.drawio.svg ├── System-design-workload-orchestration-agent.drawio.svg ├── System-design.drawio.svg ├── Workload-orchestration-app-package-definition.drawio.svg ├── Workload-orchestration-node-capability-discovery.drawio.svg ├── Workload-orchestration-software.drawio.svg ├── Workload-orchestrator-app-config-deploy.drawio.svg ├── Workload-orchestrator-app-repo-comms.drawio.svg ├── device-layers.drawio.svg ├── margo-interface-generic.drawio.svg ├── margo-logo.svg ├── multiple-personas-device-platform.drawio.svg ├── multiple-personas-ot-user-workload.drawio.svg ├── persona-relationship.drawio.svg └── workload-install-sequence.drawio.svg ├── fleet-management └── workload │ ├── consuming-workload-observability-data.md │ ├── device-capability-reporting.md │ ├── management-interface-requirements.md │ ├── workload-deployment.md │ └── workload-fleet-management-edge-onboarding.md ├── how-to-contribute ├── contribution-navigation.md └── contribution-tutorial.md ├── index.md ├── margo-api-reference ├── margo-api-specification.md └── workload-api │ ├── application-package-api │ └── application-description.md │ ├── desired-state-api │ ├── .gitignore │ └── .gittree │ ├── device-api │ ├── deployment-status.md │ └── device-capabilities.md │ └── onboarding-api │ ├── device-onboarding.md │ └── rootca-download.md └── margo-overview ├── application-package-overview.md ├── devices-overview.md ├── introduction-system-design.md ├── personas-extended.md ├── personas.md ├── software-composition.md ├── technical-lexicon.md ├── workload-management-interface-overview.md └── workload-observability-overview.md /.devcontainer/.dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/vscode/devcontainers/python:3.12-bookworm 2 | 3 | WORKDIR /work 4 | 5 | RUN pip install pyproject.toml 6 | 7 | EXPOSE 8000 8 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu 3 | { 4 | "name": "mkdocs", 5 | "service": "mkdocs", 6 | "workspaceFolder": "/home/vscode/docs/", 7 | "dockerComposeFile": [ 8 | "../.devcontainer/docker-compose.yaml" 9 | ], 10 | "remoteUser": "vscode" 11 | } -------------------------------------------------------------------------------- /.devcontainer/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | mkdocs: 3 | build: 4 | context: ../ 5 | dockerfile: ./.devcontainer/.dockerfile 6 | container_name: mkdocs 7 | ports: 8 | - 8000:8000 9 | volumes: 10 | - ..:/home/vscode/docs/ 11 | tty: true # <- keeps container running 12 | networks: 13 | - mkdocs-network 14 | 15 | networks: 16 | mkdocs-network: 17 | driver: bridge -------------------------------------------------------------------------------- /.githooks/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # An example hook script to verify what is about to be pushed. Called by "git 4 | # push" after it has checked the remote status, but before anything has been 5 | # pushed. If this script exits with a non-zero status nothing will be pushed. 6 | # 7 | # This hook is called with the following parameters: 8 | # 9 | # $1 -- Name of the remote to which the push is being done 10 | # $2 -- URL to which the push is being done 11 | # 12 | # If pushing without using a named remote those arguments will be equal. 13 | # 14 | # Information about the commits which are being pushed is supplied as lines to 15 | # the standard input in the form: 16 | # 17 | # 18 | # 19 | # This sample shows how to prevent push of commits where the log message starts 20 | # with "WIP" (work in progress). 21 | 22 | remote="$1" 23 | url="$2" 24 | 25 | zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" 48 | exit 1 49 | fi 50 | 51 | # Check test examples 52 | set -e 53 | doc-generation/check-examples.bash 54 | set +e 55 | 56 | fi 57 | done 58 | 59 | exit 0 60 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @margo/maintainers-spec 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting enhancement requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 6 | 7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 8 | 9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 10 | 11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 12 | 13 | This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at https://www.contributor-covenant.org/version/1/0/0/code-of-conduct.html 14 | 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-enhancement.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Enhancement request 3 | description: Request an enhancement to the Margo Specification 4 | labels: [enhancement] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Before requesting: search [existing issues](https://github.com/margo/specification/labels/enhancement). 10 | 11 | - type: textarea 12 | attributes: 13 | label: "Description" 14 | description: "Describe the enhancement you're requesting." 15 | placeholder: "This enhancement adds ..." 16 | validations: 17 | required: true 18 | 19 | - type: textarea 20 | attributes: 21 | label: "Motivation" 22 | description: "Describe additional context helping in understanding the enhancement request." 23 | placeholder: "This enhancement provides ..." 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | attributes: 29 | label: "Proposed Solution (optional)" 30 | description: "..." 31 | validations: 32 | required: false 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-bug.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | description: File a new bug for the Margo Specification 4 | labels: [bug, triage] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Before requesting: search [existing issues](https://github.com/margo/spefification/labels/bug). 10 | 11 | - type: textarea 12 | attributes: 13 | label: "Bug description" 14 | description: "Description of the bug." 15 | validations: 16 | required: true 17 | 18 | - type: textarea 19 | attributes: 20 | label: "Proposed fix" 21 | description: "Description of the proposed fix." 22 | validations: 23 | required: false 24 | 25 | - type: textarea 26 | attributes: 27 | label: "Anything else (optional)" 28 | description: "Any additional information, hints, links, or references?" 29 | validations: 30 | required: false 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3-problem-statement.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Problem Statement 3 | description: Describe a problem statement associated with the Margo Specification that requires a resolution. 4 | labels: "[Problem Statement]" 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Search [existing issues](https://github.com/margo/specification/labels/Problem%20Statement) before creating a new problem statement 10 | 11 | - type: markdown 12 | attributes: 13 | value: "## Problem Statement" 14 | - type: markdown 15 | attributes: 16 | value: | 17 | A problem statement is a special work item for complex issues that can be solved in many ways. The purpose of a problem statement is to solicit feedback from the community on how to solve the problem by documenting proposals instead of only discussing them during weekly calls. 18 | - type: textarea 19 | attributes: 20 | label: "Description" 21 | validations: 22 | required: true 23 | 24 | - type: textarea 25 | attributes: 26 | label: "Associated requirements" 27 | description: "Link to any requirements this problem statement addresses" 28 | validations: 29 | required: false 30 | 31 | - type: dropdown 32 | attributes: 33 | label: "Impacted Margo components" 34 | multiple: true 35 | options: 36 | - Application Definition Package 37 | - Workload Fleet Manager 38 | - Device Agent 39 | - Observability 40 | - Device Fleet Manager 41 | validations: 42 | required: true 43 | 44 | - type: markdown 45 | attributes: 46 | value: "---" 47 | - type: markdown 48 | attributes: 49 | value: "## Proposed Solutions" 50 | - type: markdown 51 | attributes: 52 | value: | 53 | If anyone has a proposed solution, it must be documented and placed in the location indicated below. Only documented proposals will be considered when evaluating solutions to this problem. 54 | - type: input 55 | attributes: 56 | label: "Location" 57 | description: "Location for documented proposals" 58 | placeholder: "[link](link)." 59 | - type: textarea 60 | attributes: 61 | label: "Use cases/scenarios" 62 | description: "Describe the use cases/scenarios each proposal must address" 63 | value: | 64 | 1. 65 | 2. 66 | 3. 67 | ... 68 | validations: 69 | required: false 70 | 71 | - type: markdown 72 | attributes: 73 | value: "---" 74 | - type: markdown 75 | attributes: 76 | value: "## References" 77 | - type: textarea 78 | attributes: 79 | label: "Reference links" 80 | validations: 81 | required: false 82 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/4-business-feature-twg.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Business Feature 3 | description: A business feature is a roadmap work item that drives additional functionality/value within the Margo deliverables. Business features are associated with one to many product management child epic(s). 4 | labels: "[Business Feature]" 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: "## Business Feature" 9 | - type: markdown 10 | attributes: 11 | value: | 12 | A business feature is a roadmap work item that drives additional functionality/value within the Margo deliverables. Business features are associated with one to many product management child epic(s). 13 | - type: textarea 14 | attributes: 15 | label: "Provide feature description below:" 16 | validations: 17 | required: true 18 | 19 | - type: markdown 20 | attributes: 21 | value: "## Acceptance Criteria" 22 | - type: textarea 23 | attributes: 24 | label: "Provide adequate technical acceptance criteria(s) associated with this feature below:" 25 | validations: 26 | required: true 27 | 28 | - type: markdown 29 | attributes: 30 | value: "## Feature Use-Cases" 31 | - type: textarea 32 | attributes: 33 | label: "Although not required, it is highly encouraged to provide feature use-cases below:" 34 | validations: 35 | required: false 36 | 37 | - type: markdown 38 | attributes: 39 | value: "## Additional Feature Information" 40 | - type: textarea 41 | attributes: 42 | label: "Additional information" 43 | description: "Describe any associated Functional/Non-Functional requirements, technical workflows, or other details to ensure clarity on the goals of the feature." 44 | validations: 45 | required: false 46 | 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/5-technical-feature-twg.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Technical Feature 3 | description: A technical feature is a roadmap work item that drives additional functionality/value within the Margo deliverables. Technical features may be associated with business features. 4 | labels: "[Technical Feature]" 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: "## Technical Feature" 9 | - type: markdown 10 | attributes: 11 | value: | 12 | A technical feature is a roadmap work item that drives additional functionality/value within the Margo deliverables. Technical features may be associated with business features. 13 | - type: textarea 14 | attributes: 15 | label: "Feature description" 16 | validations: 17 | required: true 18 | 19 | - type: markdown 20 | attributes: 21 | value: "## Acceptance Criteria" 22 | - type: textarea 23 | attributes: 24 | label: "Provide adequate technical acceptance criteria(s) associated with this feature below:" 25 | validations: 26 | required: true 27 | 28 | - type: markdown 29 | attributes: 30 | value: "## Feature Use-Cases" 31 | - type: textarea 32 | attributes: 33 | label: "Although not required, it is highly encouraged to provide feature use-cases below:" 34 | validations: 35 | required: false 36 | 37 | - type: markdown 38 | attributes: 39 | value: "## Additional Feature Information" 40 | - type: textarea 41 | attributes: 42 | label: "Additional information" 43 | description: "Describe any associated Functional/Non-Functional requirements, technical workflows, or other details to ensure clarity on the goals of the feature." 44 | validations: 45 | required: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Margo Contact Form 4 | url: https://margo.org/about/contact/ 5 | about: Please ask any other questions here. 6 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | Please provide a concise summary of the changes and their motivation. 4 | 5 | #### Issues Addressed 6 | 7 | List and link all the issues addressed by this PR. 8 | 9 | #### Change Type 10 | 11 | Please select the relevant options: 12 | 13 | - [ ] Fix (change that resolves an issue) 14 | - [ ] New enhancement (change that adds specification content) 15 | - [ ] Content edits (change that edits existing content) 16 | 17 | #### Checklist 18 | 19 | - [ ] I have read the [CONTRIBUTING](../CONTRIBUTING.md) document. 20 | - [ ] My changes adhere to the established patterns, and best practices. 21 | -------------------------------------------------------------------------------- /.github/workflows/pages.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2024 Margo 2 | # 3 | # SPDX-License-Identifier: MIT 4 | # 5 | # Author: Christian Storm 6 | # Author: Silvano Cirujano Cuesta 7 | --- 8 | name: GitHub Pages 9 | 10 | on: [push, pull_request, workflow_dispatch] 11 | 12 | permissions: 13 | contents: write 14 | 15 | jobs: 16 | quality-checks: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | 22 | - name: Setup Python 23 | uses: actions/setup-python@v5 24 | with: 25 | python-version: 3.12 26 | 27 | - name: Install poetry 28 | run: pipx install poetry 29 | 30 | - name: Check pyproject.toml and poetry.lock 31 | run: poetry check 32 | 33 | validate: 34 | needs: 35 | - quality-checks 36 | runs-on: ubuntu-latest 37 | steps: 38 | - name: Check out repository 39 | uses: actions/checkout@v4 40 | with: 41 | fetch-depth: 0 42 | 43 | - name: Ensure tags if not run from main repo 44 | if: github.repository != 'margo/specification' 45 | run: | 46 | git remote add upstream https://github.com/margo/specification 47 | git fetch upstream --tags 48 | 49 | - name: Install poetry 50 | run: pipx install poetry 51 | 52 | - uses: actions/setup-python@v5 53 | id: setup-python 54 | with: 55 | python-version: '3.12' 56 | cache: 'poetry' 57 | 58 | - name: Install dependencies 59 | run: poetry install --no-interaction --all-extras 60 | 61 | - name: Run tests 62 | run: | 63 | doc-generation/check-examples.bash 64 | 65 | documents: 66 | needs: 67 | - quality-checks 68 | runs-on: ubuntu-latest 69 | steps: 70 | - name: Check out repository 71 | uses: actions/checkout@v4 72 | with: 73 | fetch-depth: 0 74 | 75 | - name: Ensure tags if not run from main repo 76 | if: github.repository != 'margo/specification' 77 | run: | 78 | git remote add upstream https://github.com/margo/specification 79 | git fetch upstream --tags 80 | 81 | - name: Install poetry 82 | run: pipx install poetry 83 | 84 | - uses: actions/setup-python@v5 85 | id: setup-python 86 | with: 87 | python-version: '3.12' 88 | cache: 'poetry' 89 | 90 | - name: Install dependencies 91 | run: poetry install --no-interaction --all-extras 92 | 93 | - name: Generate MarkDown documentation 94 | run: | 95 | doc-generation/generate-documentation.bash 96 | 97 | - name: Share generated documentation with later jobs 98 | uses: actions/upload-artifact@v4 99 | with: 100 | name: generated-documentation 101 | path: | 102 | system-design/app-interoperability/application-package-definition.md 103 | system-design/margo-api-reference/workload-api/desired-state-api/desired-state.md 104 | 105 | pages: 106 | needs: 107 | - validate 108 | - documents 109 | runs-on: ubuntu-latest 110 | steps: 111 | - name: Checkout 112 | uses: actions/checkout@v4 113 | 114 | - name: Setup Python 115 | uses: actions/setup-python@v4 116 | with: 117 | python-version: 3.x 118 | 119 | - name: Install poetry 120 | uses: abatilo/actions-poetry@v2 121 | 122 | # create local virtualenv to enable caching in CI 123 | - name: Configure poetry 124 | run: | 125 | poetry config virtualenvs.create true --local 126 | poetry config virtualenvs.in-project true --local 127 | 128 | - name: Setup Cache 129 | uses: actions/cache@v4 130 | with: 131 | path: ./.venv 132 | # cache is invalidated if dependencies change 133 | key: venv-${{ hashFiles('poetry.lock') }} 134 | 135 | - name: Install the project dependencies 136 | run: poetry install 137 | 138 | - name: Get generated documentation from previous jobs 139 | uses: actions/download-artifact@v4 140 | with: 141 | name: generated-documentation 142 | path: system-design/ 143 | 144 | - name: Build Pages 145 | run: poetry run -- mkdocs build 146 | 147 | - name: GitHub Pages Deploy 148 | # only deploy if we are on the default branch 149 | if: ${{ github.ref == 'refs/heads/pre-draft' }} 150 | run: poetry run -- mkdocs gh-deploy --force --clean --verbose 151 | 152 | - name: Upload pages 153 | uses: actions/upload-artifact@v4 154 | if: ${{ github.ref != 'refs/heads/pre-draft' }} 155 | with: 156 | name: margo-specification 157 | path: site 158 | retention-days: 5 159 | -------------------------------------------------------------------------------- /.github/workflows/pr-checks.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2024 Margo 2 | # 3 | # SPDX-License-Identifier: MIT 4 | # 5 | # Author: Christian Storm 6 | --- 7 | name: PR checks 8 | 9 | on: 10 | pull_request: 11 | types: 12 | - opened 13 | - synchronize 14 | 15 | permissions: 16 | contents: read 17 | pull-requests: write 18 | 19 | jobs: 20 | check-sign-off: 21 | name: Comment if commits are not signed-off 22 | env: 23 | FORCE_COLOR: 1 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: live627/check-pr-signoff-action@v1 27 | 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | site 2 | .DS_Store 3 | .cache 4 | myenv 5 | .python-version 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This document explains the general requirements on contributions and the recommended preparation steps. 4 | It also sketches the typical integration process. 5 | 6 | ## New Features 7 | 8 | Contributions to Margo are _typically_ very welcome! 9 | However, please keep the following in mind when adding new enhancements: 10 | It is ultimately the responsibility of the maintainers to maintain your addition (although any help is more than appreciated!). 11 | Thus, when accepting new enhancements, we have to make a trade-off between the added value and the added cost of maintenance. 12 | If the maintenance cost exceeds the added value by far, we reserve the right to reject the feature. 13 | Hence it is **recommended to first create a new issue on Github before starting the actual implementation** and wait for feedback from the maintainers. 14 | 15 | ## Bug Fixes 16 | 17 | Bug and security fixes are _always_ welcome and take the highest priority, see our [Security Policy](SECURITY.md). 18 | 19 | ## Contribution Checklist 20 | 21 | - Contributions to the Specification must be covered by a Corporate CLA or Individual CLA 22 | - Any code changes must be accompanied with automated tests 23 | - Add the required copyright header to each new file introduced if appropriate, see [licensing information](LICENSE) 24 | - Add `signed-off` to all commits to certify the "Developer's Certificate of Origin", see below 25 | - Structure your commits logically, in small steps 26 | - one separable functionality/fix/refactoring = one commit 27 | - do not mix those there in a single commit 28 | - after each commit, the tree still has to build and work, i.e. do not add 29 | even temporary breakages inside a commit series (helps when tracking down 30 | bugs). This also applies to documentation commits processed by, e.g., `mkdocs` 31 | - Base commits on top of latest `pre-draft` branch 32 | 33 | ### Signing the CLA for Contributions to the Specification 34 | If you have not yet signed the Individual CLA, or your organization has not yet signed the Corporate CLA, or if your account has not yet been authorized by your organization to contribute to Margo, the [LFX EasyCLA bot](https://easycla.lfx.linuxfoundation.org/#/) will prompt you to follow the appriopriate steps to authorize your contribution. 35 | 36 | To ensure your contribution is covered before you make a pull request or to sign the CLA, open a PR at https://github.com/margo/EasyCLA. 37 | 38 | ### Sign your work 39 | 40 | The sign-off is a simple line at the end of the explanation for the patch, e.g. 41 | 42 | Signed-off-by: Random J Developer 43 | 44 | This lines certifies that you wrote it or otherwise have the right to pass it on as an open-source patch. 45 | Check with your employer when not working on your own! 46 | 47 | **Tip**: The sign-off will be created for you automatically if you use `git commit -s` (or `git revert -s`). 48 | 49 | ### Developer's Certificate of Origin 1.1 50 | 51 | By making a contribution to this project, I certify that: 52 | 53 | (a) The contribution was created in whole or in part by me and I 54 | have the right to submit it under the open source license 55 | indicated in the file; or 56 | 57 | (b) The contribution is based upon previous work that, to the best 58 | of my knowledge, is covered under an appropriate open source 59 | license and I have the right under that license to submit that 60 | work with modifications, whether created in whole or in part 61 | by me, under the same open source license (unless I am 62 | permitted to submit under a different license), as indicated 63 | in the file; or 64 | 65 | (c) The contribution was provided directly to me by some other 66 | person who certified (a), (b) or (c) and I have not modified 67 | it. 68 | 69 | (d) I understand and agree that this project and the contribution 70 | are public and that a record of the contribution (including all 71 | personal information I submit with it, including my sign-off) is 72 | maintained indefinitely and may be redistributed consistent with 73 | this project or the open source license(s) involved. 74 | 75 | ## Contribution Integration Process 76 | 77 | 1. Create a pull request on Github. 78 | 2. The EasyCLA check, CI pipeline, and other applicable checks as may be introduced must pass. 79 | 3. Accepted pull requests are merged into the `pre-draft` branch. 80 | 81 | ## Documentation Generation Process 82 | 83 | Some of the resources being used in the Margo APIs are being manually specified using MarkDown files. 84 | In this case `mkdocs` is used to generate the documentation in HTML format. 85 | 86 | But for some others the modeling language [LinkML](https://linkml.io/) is being used to generate the documentation. 87 | In this case `linkml` is used to generate the MarkDown documents that are integrated with the above mentioned documents before `mkdocs` can generate the HTML documents. 88 | 89 | ### Preparation 90 | 91 | There are multiple different possibilities to cover as many user set-ups as possible: 92 | 93 | - [Development Containers](https://containers.dev/) 94 | - [Python Poetry](https://python-poetry.org/) 95 | - [Python PIP](https://pypi.org/project/pip/) 96 | - Others might or might not work out of the box 97 | 98 | #### Development Containers 99 | 100 | This repository provides a Development Container (AKA dev-container) that is automatically recognized by VsCode. 101 | 102 | It is out of the scope of this project to document how to use Development Containers, please visit to help yourself. 103 | 104 | The provided dev-container includes all dependencies. 105 | Therefore, once the Development Container has been activated, the preparation is done. 106 | 107 | #### Python Poetry 108 | 109 | Python Poetry is a widely used tool for dependency management in the Python ecosystem. 110 | 111 | It is out of the scope of this project to document how to use Python Poetry, please visit to help yourself. 112 | 113 | One feature of Poetry (also available in some of the other tools) very important for the reliability of the generation process is the possibility of easily "freezing" the dependencies and installing them in Python virtual environments (AKA _venv_s). 114 | Poetry is being used in the pipeline that generates the documentation for a more reliable process (thanks to its reproducibility). 115 | 116 | Poetry v2 is required to ensure that the same dependencies specification file can be also used with other tools (like PIP), thanks to its conformance with [PEP-518](https://peps.python.org/pep-0518/). 117 | 118 | In order to install the dependencies, simply run `poetry install` from the top directory of this repository. 119 | With this the preparation is done. 120 | 121 | #### Python PIP 122 | 123 | Python PIP is the most basic dependency manager in the Python ecosystem and is therefore available almost in all Python installations. 124 | 125 | It is out of the scope of this project to document how to use Python PIP, please visit to help yourself. 126 | 127 | In order to install the dependencies, simply run `pip install `, being __ the path to the file under that name provided in the top directory of this repository. 128 | With this the preparation is done. 129 | 130 | ### Generation of the Documentation 131 | 132 | Once the required tools have been installed as documented in the [Preparation](#preparation) section, these tools can be used to: 133 | 134 | 1. [Optional] [Only for LinkML specified resources] Validate the input for the MarkDown document generation. 135 | 2. [Only for LinkML specified resources] Generate all the needed MarkDown documents. 136 | 3. Generate the HTML documents. 137 | 138 | As mentioned in a previous section, as of now only some of the resources are being specified in LinkML and are being used to generate the MarkDown documents. 139 | Steps 1. and 2. only apply to those documents. 140 | 141 | Currently two Bash scripts are being provided the directory `doc-generation` to simplify steps 1. and 2. 142 | 143 | The input for the generation of the MarkDown documents is provided in the directory `[src](./src/)`. 144 | 145 | #### Validate input for MarkDown Generation 146 | 147 | The script [check-examples.bash](./doc-generation/check-examples.bash) checks: 148 | 149 | - the validity of the LinkML resource definitions (AKA schemas), and 150 | - the validity of provided examples and counter-examples according the resource definitions 151 | 152 | "Counter-examples" are examples that should be recognized as invalid, when checked against the resource definitions. 153 | 154 | #### Generate MarkDown Documents 155 | 156 | The script [generate-documentation.bash](./doc-generation/generate-documentation.bash) generates MarkDown documents for the resources specified in LinkML format. 157 | 158 | The LinkML specification documents can be found in the directory [src](./src/) and the resulting MarkDown documents are integrated with the other MarkDown documents in the directory [system-design](./system-design/). 159 | 160 | #### Generate HTML Documents 161 | 162 | The documentation gets converted into HTML for public availability using `mkdocs`. 163 | 164 | MkDocs cannot only convert MarkDown documents into HTML documentation (using `mkdocs build`), but is can also start a webserver (using `mkdocs serve`) for local rendering of the documentation on a web browser. 165 | 166 | ### Other information 167 | 168 | Each resource description has a responsible person which can decide to use LinkML to generate the MarkDown documentation or to write the MarkDown documentation manually. 169 | 170 | Transforming a manually written MarkDown document into one generated out of LinkML is not a one-direction road. 171 | Going back to manually written (or generated differently) MarkDown documents is as easy as committing the MarkDown documents generated out of LinkML and disabling the generation. 172 | 173 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Margo contributors contributing to this draft specification have made those contributions subject to the Open Web Foundation Contributor License Agreement Contribution Copyright Grant, available at [Open Web Foundation - CLA Copyright Grant 0.9](https://www.openwebfoundation.org/the-agreements/the-owf-0-9-agreements-necessary-claims/cla-copyright-grant-0-9). 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

margo logo

2 | 3 | ![Static Badge](https://img.shields.io/badge/Deliverable_Development_Status-Pre_Draft-blue) 4 | [![GitHub Pages](https://github.com/margo/specification/actions/workflows/pages.yml/badge.svg)](https://github.com/margo/specification/actions/workflows/pages.yml) 5 | 6 | The margo initiative defines mechanisms for interoperation between edge applications, devices, and orchestration software through ― amongst others ― an open standard at home in this repository. 7 | 8 | Find out more about the Margo initiative here [https://www.margo.org/](https://www.margo.org/). 9 | 10 | ## Contributing 11 | 12 | Contributions are encouraged and welcome! Contributors to the specification are required to sign the appropriate CLA. See [CONTRIBUTING.md](CONTRIBUTING.md) for details. 13 | 14 | ## Licenses 15 | 16 | Margo contributors contributing to this draft specification have made those contributions subject to the Open Web Foundation Contributor License Agreement Contribution Copyright Grant, available at [Open Web Foundation - CLA Copyright Grant 0.9](https://www.openwebfoundation.org/the-agreements/the-owf-0-9-agreements-necessary-claims/cla-copyright-grant-0-9). 17 | 18 | Copyright ©️ 2025 Margo. 19 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Margo takes the security of its specification and code seriously. 4 | If you think you have found a security vulnerability, please read the next section and follow the instructions to 5 | report your finding. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | Please *DO NOT* report any potential security vulnerability via a public channel (GitHub issue etc.). 10 | Instead, please report it directly to Margo by emailing [security@margo.org](mailto:security@margo.org). 11 | Please provide a detailed description of the issue, the steps to reproduce it, the affected versions and, if already available, a proposal for a fix. 12 | 13 | You should receive a response within 5 working days. If the issue is confirmed as a vulnerability by us, we will open a Security Advisory on GitHub and give credits for your report if desired. 14 | This project follows a 90 day disclosure timeline. 15 | -------------------------------------------------------------------------------- /assets/margo-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 27 | 28 | 29 | 38 | 46 | 50 | 64 | 70 | 71 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /doc-generation/check-examples.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | THIS_SCRIPT="$(readlink -f "${0}")" 6 | THIS_DIR="$(dirname "${THIS_SCRIPT}")" 7 | ROOT_DIR="$(dirname "${THIS_DIR}")" 8 | DOCS_GEN="${THIS_DIR}" 9 | CONFIGS="${DOCS_GEN}/configurations" 10 | 11 | if command -v poetry 2>&1 >/dev/null ; then 12 | RUN="poetry run" 13 | else 14 | if ! command -v linkml 2>&1 >/dev/null ; then 15 | echo "The command 'linkml' is missing" 16 | exit 1 17 | fi 18 | if ! command -v mkdocs 2>&1 >/dev/null ; then 19 | echo "The command 'mkdocs' is missing" 20 | exit 1 21 | fi 22 | RUN="" 23 | fi 24 | 25 | check_spec () { 26 | SPEC_ROOT="${ROOT_DIR}/$(jq -r '.root' "${CONFIGS}/$1")" 27 | echo "Spec root folder: ${SPEC_ROOT}" 28 | 29 | TARGET_CLASS="$(jq -r '.targetclass' "${CONFIGS}/$1")" 30 | echo "Target class: ${TARGET_CLASS}" 31 | 32 | SCHEMA_FILE="$(jq -r '.schemafile' "${CONFIGS}/$1")" 33 | echo "Schema file: ${SCHEMA_FILE}" 34 | 35 | EXAMPLES_DIR="${SPEC_ROOT}/resources/examples/valid" 36 | echo "Examples folder: ${EXAMPLES_DIR}" 37 | for EXAMPLE in $(ls "${EXAMPLES_DIR}"/*-0*.yaml) ; do 38 | echo "Validate example: ${EXAMPLE}" 39 | ${RUN} linkml validate \ 40 | --schema "${SPEC_ROOT}/${SCHEMA_FILE}" \ 41 | --target-class "${TARGET_CLASS}" \ 42 | "${EXAMPLE}" 43 | done 44 | 45 | COUNTEREXAMPLES_DIR="${SPEC_ROOT}/resources/examples/invalid" 46 | for COUNTEREXAMPLE in $(ls "${COUNTEREXAMPLES_DIR}"/*-0*.yaml) ; do 47 | if ! ${RUN} linkml validate \ 48 | --schema "${SPEC_ROOT}/${SCHEMA_FILE}" \ 49 | --target-class "${TARGET_CLASS}" \ 50 | "${COUNTEREXAMPLE}" ; then 51 | echo "ok: validation failed, as expected" 52 | else 53 | echo "ERROR: Validation of 'examples/invalid/${COUNTEREXAMPLE}' was expected to fail, but has succeeded." 54 | exit 1 55 | fi 56 | done 57 | 58 | # does not work due to following LinkML bugs: 59 | # https://github.com/linkml/linkml/issues/2423 60 | # https://github.com/linkml/linkml/issues/2425 61 | if false ; then 62 | ${RUN} linkml examples \ 63 | --schema "${SPEC_ROOT}/*.linkml.yaml" \ 64 | --input-directory "${SPEC_ROOT}/resources/examples/valid" \ 65 | --counter-example-input-directory "${SPEC_ROOT}/resources/examples/invalid" \ 66 | --output-directory "${SPEC_ROOT}/output" 67 | fi 68 | } 69 | 70 | for spec in $(ls "${CONFIGS}") ; do 71 | check_spec "${spec}" 72 | done 73 | 74 | -------------------------------------------------------------------------------- /doc-generation/configurations/application-package-api.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": "src/margo-api-reference/workload-api/application-package-api", 3 | "targetclass": "ApplicationDescription", 4 | "schemafile": "application-description.linkml.yaml", 5 | "markdowndoc": "application-description.md" 6 | } 7 | -------------------------------------------------------------------------------- /doc-generation/configurations/desired-state-api.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": "src/margo-api-reference/workload-api/desired-state-api", 3 | "targetclass": "DesiredState", 4 | "schemafile": "desired-state.linkml.yaml", 5 | "markdowndoc": "desired-state.md" 6 | } 7 | -------------------------------------------------------------------------------- /doc-generation/generate-documentation.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | THIS_SCRIPT="$(readlink -f "${0}")" 6 | THIS_DIR="$(dirname "${THIS_SCRIPT}")" 7 | ROOT_DIR="$(dirname "${THIS_DIR}")" 8 | DOCS_GEN="${THIS_DIR}" 9 | CONFIGS="${DOCS_GEN}/configurations" 10 | 11 | if command -v poetry 2>&1 >/dev/null ; then 12 | RUN="poetry run" 13 | else 14 | if ! command -v linkml 2>&1 >/dev/null ; then 15 | echo "The command 'linkml' is missing" 16 | exit 1 17 | fi 18 | if ! command -v mkdocs 2>&1 >/dev/null ; then 19 | echo "The command 'mkdocs' is missing" 20 | exit 1 21 | fi 22 | RUN="" 23 | fi 24 | 25 | gen_spec () { 26 | ITEM_REL_PATH=$(jq -r '.root' "${CONFIGS}/$1") 27 | SCHEMA_FILE=$(jq -r '.schemafile' "${CONFIGS}/$1") 28 | MKDOWN_FILE=$(jq -r '.markdowndoc' "${CONFIGS}/$1") 29 | SRC_ROOT="${ROOT_DIR}/${ITEM_REL_PATH}" 30 | SPEC_ROOT="${ROOT_DIR}/system-design${ITEM_REL_PATH#src}" 31 | echo "${SRC_ROOT}" 32 | 33 | ${RUN} linkml generate doc \ 34 | --directory="${SRC_ROOT}/docs" \ 35 | --template-directory="${SRC_ROOT}/resources" \ 36 | "${SRC_ROOT}/${SCHEMA_FILE}" 37 | 38 | mv "${SRC_ROOT}/docs/index.md" "${SPEC_ROOT}/${MKDOWN_FILE}" 39 | rm -r "${SRC_ROOT}/docs" 40 | } 41 | 42 | for spec in $(ls "${CONFIGS}") ; do 43 | gen_spec "${spec}" 44 | done 45 | 46 | ( 47 | cd "${ROOT_DIR}" 48 | ${RUN} mkdocs build 49 | ) 50 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Specification (pre-draft) 2 | docs_dir: system-design 3 | 4 | nav: 5 | - What is Margo?: index.md 6 | - Personas & Definitions: 7 | - margo-overview/personas.md 8 | - margo-overview/personas-extended.md 9 | - margo-overview/technical-lexicon.md 10 | - margo-overview/software-composition.md 11 | - Overview: 12 | - margo-overview/introduction-system-design.md 13 | - margo-overview/application-package-overview.md 14 | - margo-overview/workload-management-interface-overview.md 15 | - margo-overview/devices-overview.md 16 | - margo-overview/workload-observability-overview.md 17 | - Concepts: 18 | - Workloads: 19 | - app-interoperability/application-package-definition.md 20 | - app-interoperability/workload-orch-to-app-reg-interaction.md # = Application Registry 21 | - app-interoperability/publishing-workload-observability-data.md 22 | - app-interoperability/local-registries.md 23 | - Workload Fleet Managers: 24 | - fleet-management/workload/management-interface-requirements.md 25 | - fleet-management/workload/workload-fleet-management-edge-onboarding.md 26 | - fleet-management/workload/device-capability-reporting.md 27 | - fleet-management/workload/workload-deployment.md 28 | - fleet-management/workload/consuming-workload-observability-data.md 29 | - Edge Compute Devices: 30 | - device-interoperability/device-requirements.md 31 | - device-interoperability/collecting-workload-observability-data.md 32 | - Technical References: 33 | - Margo Management Interface: 34 | - margo-api-reference/margo-api-specification.md 35 | - margo-api-reference/workload-api/desired-state-api/desired-state.md 36 | - margo-api-reference/workload-api/device-api/device-capabilities.md 37 | - margo-api-reference/workload-api/device-api/deployment-status.md 38 | - margo-api-reference/workload-api/onboarding-api/device-onboarding.md 39 | - margo-api-reference/workload-api/onboarding-api/rootca-download.md 40 | - Application Package Definition: 41 | - margo-api-reference/workload-api/application-package-api/application-description.md 42 | #- Observability: 43 | - Make a Contribution: 44 | - how-to-contribute/contribution-tutorial.md 45 | - how-to-contribute/contribution-navigation.md 46 | 47 | theme: 48 | name: material 49 | features: 50 | #- navigation.tabs 51 | #- navigation.settings 52 | #- navigation.top 53 | #- navigation.sections 54 | - navigation.tracking 55 | - navigation.footer 56 | - toc.integrate 57 | - search.suggest 58 | - search.highlight 59 | - content.tabs.link 60 | - content.code.annotations 61 | - content.code.copy 62 | language: en 63 | font: 64 | text: IBM Plex Sans 65 | code: IBM Plex Mono 66 | logo: assets/margo_white.svg 67 | favicon: assets/favicon.ico 68 | palette: 69 | scheme: margo 70 | 71 | markdown_extensions: 72 | - toc: 73 | toc_depth: 2 74 | - pymdownx.superfences: 75 | custom_fences: 76 | - name: mermaid 77 | class: mermaid 78 | format: !!python/name:pymdownx.superfences.fence_code_format 79 | 80 | extra_css: 81 | - css/margo.css 82 | 83 | extra: 84 | # https://squidfunk.github.io/mkdocs-material/setup/setting-up-the-footer/#generator-notice 85 | generator: true 86 | homepage: https://margo.org 87 | copyright: Copyright © 2024 Margo 88 | reponame: !ENV [GITHUB_REPOSITORY, "margo/specification"] 89 | commit: !ENV [GITHUB_SHA, ""] 90 | social: 91 | - icon: fontawesome/brands/github 92 | link: https://github.com/margo 93 | - icon: fontawesome/brands/x-twitter 94 | link: https://twitter.com/margo_project 95 | - icon: fontawesome/brands/linkedin 96 | link: https://www.linkedin.com/company/margoproject/about/ 97 | - icon: fontawesome/brands/youtube 98 | link: https://www.youtube.com/@Margoinitiative 99 | - icon: fontawesome/brands/discord 100 | link: http://chat.margo.org/ 101 | 102 | plugins: 103 | - search 104 | - markdownextradata: 105 | jinja_options: 106 | variable_start_string: =@= 107 | variable_end_string: =@= 108 | - privacy 109 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2024 Margo 2 | # 3 | # SPDX-License-Identifier: MIT 4 | # 5 | # SPDX-FileContributor: Michael Adler 6 | [project] 7 | name = "specification" 8 | version = "0.1.0" 9 | description = "Margo Specification" 10 | authors = [] 11 | license = "Open Web Foundation - CLA Copyright Grant 0.9" 12 | readme = "README.md" 13 | requires-python = ">=3.12,<4.0" 14 | dependencies = [ 15 | 'mkdocs>=1.6.1', 16 | 'mkdocs-markdownextradata-plugin>=0.2.6', 17 | 'mkdocs-material>=9.5.44', 18 | 'linkml>=1.8.5', 19 | ] 20 | 21 | [tool.poetry] 22 | requires-poetry = ">=2.0" 23 | package-mode = false 24 | 25 | [tool.poetry.group.dev.dependencies] 26 | tox = "^4.23.2" 27 | 28 | [build-system] 29 | requires = ["poetry-core>=2.0"] 30 | build-backend = "poetry.core.masonry.api" 31 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/application-package-api/resources/class.md.jinja2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margo/specification/1d11d11334613a71843db9e68b73272ac036dd66/src/margo-api-reference/workload-api/application-package-api/resources/class.md.jinja2 -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/application-package-api/resources/examples/valid/ApplicationDescription-001.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: margo.org/v1-alpha1 2 | kind: ApplicationDescription 3 | metadata: 4 | id: com-northstartida-hello-world 5 | name: Hello World 6 | description: A basic hello world application 7 | version: "1.0" 8 | catalog: 9 | application: 10 | icon: ./resources/hw-logo.png 11 | tagline: Northstar Industrial Application's hello world application. 12 | descriptionFile: ./resources/description.md 13 | releaseNotes: ./resources/release-notes.md 14 | licenseFile: ./resources/license.pdf 15 | site: http://www.northstar-ida.com 16 | tags: ["monitoring"] 17 | author: 18 | - name: Roger Wilkershank 19 | email: rpwilkershank@northstar-ida.com 20 | organization: 21 | - name: Northstar Industrial Applications 22 | site: http://northstar-ida.com 23 | deploymentProfiles: 24 | - type: helm.v3 25 | components: 26 | - name: hello-world 27 | properties: 28 | repository: oci://northstarida.azurecr.io/charts/hello-world 29 | revision: 1.0.1 30 | wait: true 31 | parameters: 32 | greeting: 33 | value: Hello 34 | targets: 35 | - pointer: global.config.appGreeting 36 | components: ["hello-world"] 37 | greetingAddressee: 38 | value: World 39 | targets: 40 | - pointer: global.config.appGreetingAddressee 41 | components: ["hello-world"] 42 | configuration: 43 | sections: 44 | - name: General Settings 45 | settings: 46 | - parameter: greeting 47 | name: Greeting 48 | description: The greeting to use. 49 | schema: requireText 50 | - parameter: greetingAddressee 51 | name: Greeting Addressee 52 | description: The person, or group, the greeting addresses. 53 | schema: requireText 54 | schema: 55 | - name: requireText 56 | dataType: string 57 | maxLength: 45 58 | allowEmpty: false 59 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/application-package-api/resources/examples/valid/ApplicationDescription-002.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: margo.org/v1-alpha1 2 | kind: ApplicationDescription 3 | metadata: 4 | id: com-northstartida-digitron-orchestrator 5 | name: Digitron orchestrator 6 | description: The Digitron orchestrator application 7 | version: 1.2.1 8 | catalog: 9 | application: 10 | icon: ./resources/ndo-logo.png 11 | tagline: Northstar Industrial Application's next-gen, AI driven, Digitron instrument orchestrator. 12 | descriptionFile: ./resources/description.md 13 | releaseNotes: ./resources/release-notes.md 14 | licenseFile: ./resources/license.pdf 15 | site: http://www.northstar-ida.com 16 | tags: ["optimization", "instrumentation"] 17 | author: 18 | - name: Roger Wilkershank 19 | email: rpwilkershank@northstar-ida.com 20 | organization: 21 | - name: Northstar Industrial Applications 22 | site: http://northstar-ida.com 23 | deploymentProfiles: 24 | - type: helm.v3 25 | components: 26 | - name: database-services 27 | properties: 28 | repository: oci://quay.io/charts/realtime-database-services 29 | revision: 2.3.7 30 | wait: true 31 | timeout: 8m30s 32 | - name: digitron-orchestrator 33 | properties: 34 | repository: oci://northstarida.azurecr.io/charts/northstarida-digitron-orchestrator 35 | revision: 1.0.9 36 | wait: true 37 | - type: compose 38 | components: 39 | - name: digitron-orchestrator-docker 40 | properties: 41 | packageLocation: https://northsitarida.com/digitron/docker/digitron-orchestrator.tar.gz 42 | keyLocation: https://northsitarida.com/digitron/docker/public-key.asc 43 | parameters: 44 | idpName: 45 | targets: 46 | - pointer: idp.name 47 | components: ["digitron-orchestrator"] 48 | - pointer: ENV.IDP_NAME 49 | components: ["digitron-orchestrator-docker"] 50 | idpProvider: 51 | targets: 52 | - pointer: idp.provider 53 | components: ["digitron-orchestrator"] 54 | - pointer: ENV.IDP_PROVIDER 55 | components: ["digitron-orchestrator-docker"] 56 | idpClientId: 57 | targets: 58 | - pointer: idp.clientId 59 | components: ["digitron-orchestrator"] 60 | - pointer: ENV.IDP_CLIENT_ID 61 | components: ["digitron-orchestrator-docker"] 62 | idpUrl: 63 | targets: 64 | - pointer: idp.providerUrl 65 | components: ["digitron-orchestrator"] 66 | - pointer: idp.providerMetadata 67 | components: ["digitron-orchestrator"] 68 | - pointer: ENV.IDP_URL 69 | components: ["digitron-orchestrator-docker"] 70 | adminName: 71 | targets: 72 | - pointer: administrator.name 73 | components: ["digitron-orchestrator"] 74 | - pointer: ENV.ADMIN_NAME 75 | components: ["digitron-orchestrator-docker"] 76 | adminPrincipalName: 77 | targets: 78 | - pointer: administrator.userPrincipalName 79 | components: ["digitron-orchestrator"] 80 | - pointer: ENV.ADMIN_PRINCIPALNAME 81 | components: ["digitron-orchestrator-docker"] 82 | pollFrequency: 83 | value: 30 84 | targets: 85 | - pointer: settings.pollFrequency 86 | components: ["digitron-orchestrator", "database-services"] 87 | - pointer: ENV.POLL_FREQUENCY 88 | components: ["digitron-orchestrator-docker"] 89 | siteId: 90 | targets: 91 | - pointer: settings.siteId 92 | components: ["digitron-orchestrator", "database-services"] 93 | - pointer: ENV.SITE_ID 94 | components: ["digitron-orchestrator-docker"] 95 | cpuLimit: 96 | value: 1 97 | targets: 98 | - pointer: settings.limits.cpu 99 | components: ["digitron-orchestrator"] 100 | memoryLimit: 101 | value: 16384 102 | targets: 103 | - pointer: settings.limits.memory 104 | components: ["digitron-orchestrator"] 105 | configuration: 106 | sections: 107 | - name: General 108 | settings: 109 | - parameter: pollFrequency 110 | name: Poll Frequency 111 | description: How often the service polls for updated data in seconds 112 | schema: pollRange 113 | - parameter: siteId 114 | name: Site Id 115 | description: Special identifier for the site (optional) 116 | schema: optionalText 117 | - name: Identity Provider 118 | settings: 119 | - parameter: idpName 120 | name: Name 121 | description: The name of the Identity Provider to use 122 | immutable: true 123 | schema: requiredText 124 | - parameter: idpProvider 125 | name: Provider 126 | description: Provider something something 127 | immutable: true 128 | schema: requiredText 129 | - parameter: idpClientId 130 | name: Client ID 131 | description: The client id 132 | immutable: true 133 | schema: requiredText 134 | - parameter: idpUrl 135 | name: Provider URL 136 | description: The url of the Identity Provider 137 | immutable: true 138 | schema: url 139 | - name: Administrator 140 | settings: 141 | - parameter: adminName 142 | name: Presentation Name 143 | description: The presentation name of the administrator 144 | schema: requiredText 145 | - parameter: adminPrincipalName 146 | name: Principal Name 147 | description: The principal name of the administrator 148 | schema: email 149 | - name: Resource Limits 150 | settings: 151 | - parameter: cpuLimit 152 | name: CPU Limit 153 | description: Maximum number of CPU cores to allow the application to consume 154 | schema: cpuRange 155 | - parameter: memoryLimit 156 | name: Memory Limit 157 | description: Maximum number of memory to allow the application to consume 158 | schema: memoryRange 159 | schema: 160 | - name: requiredText 161 | dataType: string 162 | maxLength: 45 163 | allowEmpty: false 164 | - name: email 165 | dataType: string 166 | allowEmpty: false 167 | regexMatch: .*@[a-z0-9.-]* 168 | - name: url 169 | dataType: string 170 | allowEmpty: false 171 | regexMatch: ^(http(s):\/\/.)[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$ 172 | - name: pollRange 173 | dataType: integer 174 | minValue: 30 175 | maxValue: 360 176 | allowEmpty: false 177 | - name: optionalText 178 | dataType: string 179 | minLength: 5 180 | allowEmpty: true 181 | - name: cpuRange 182 | dataType: double 183 | minValue: 0.5 184 | maxPrecision: 1 185 | allowEmpty: false 186 | - name: memoryRange 187 | dataType: integer 188 | minValue: 16384 189 | allowEmpty: false -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/application-package-api/resources/index.md.jinja2: -------------------------------------------------------------------------------- 1 | The application description has the purpose of presenting the application, e.g., on an application catalog or marketplace from where an end user selects an application to be installed. The end user defines an `ApplicationDeployment` by specifying [configuration parameters](#defining-configurable-application-parameters) for an `ApplicationDescription`. An `ApplicationDeployment` defines the [desired state](../desired-state-api/desired-state.md) for an application. 2 | 3 | ### Top-level Attributes 4 | 5 | {% macro abort(error) %} 6 | {{ None['[ERROR] ' ~ error][0] }} 7 | {% endmacro %} 8 | 9 | {%- macro format_range(slot) -%} 10 | {%- if slot.multivalued -%} 11 | {%- if slot.inlined -%} 12 | {%- if slot.inlined_as_list -%} 13 | []{{ slot.range }} 14 | {%- else -%} 15 | {%- if slot.name == "properties" -%} 16 | map[string][string] 17 | {%- else -%} 18 | map[string][{{ slot.range }}] 19 | {%- endif -%} 20 | {%- endif -%} 21 | {%- else -%} 22 | []string 23 | {%- endif -%} 24 | {%- else -%} 25 | {{ slot.range }} 26 | {%- endif -%} 27 | {%- endmacro -%} 28 | 29 | | Attribute | Type | Required? | Description | 30 | | --- | --- | --- | --- | 31 | {% for slot in schemaview.class_slots("ApplicationDescription")|sort(attribute='rank') -%} 32 | | {{ slot }} | {{ format_range(schemaview.get_slot(slot)) }} | {% if schemaview.get_slot(slot).required == True %} Y {% else %} N {% endif %} | {{ schemaview.get_slot(slot).description }}| 33 | {% endfor -%} 34 | 35 | {% for c in gen.all_class_objects()|sort(attribute='rank') %} 36 | {%- if c.name != "ApplicationDescription" and not c.name.startswith("ComponentProperties") and not c.name.startswith("Helm") and not c.name.startswith("Compose") %} 37 | 38 | {# if c is a subclass of any: #} 39 | 40 | {%- if c.is_a -%} 41 | * #### {{ c.name }} Attributes
42 | (Subclass of {{ c.is_a }})
43 | {%- else -%} 44 | ### {{ c.name }} Attributes
45 | {%- endif %} 46 | 47 | {%- if c.description -%} 48 |
49 | {{ c.description }}
50 | {%- endif %} 51 | 52 | | Attribute | Type | Required? | Description | 53 | | --- | --- | --- | --- | 54 | {% for slot in gen.get_direct_slots(c)|sort(attribute='rank') -%} 55 | {%- if slot.name != "value" -%} 56 | | {{ slot.name }} | {{ format_range(slot) }} | {% if slot.required == True %} Y {% else %} N {% endif %} | {{ slot.description }}| 57 | {%- else -%} 58 | | {{ slot.name }} | <*see description*> | {% if slot.required == True %} Y {% else %} N {% endif %} | {{ slot.description }}| 59 | {%- endif %} 60 | {% endfor %} 61 | {%- endif %} 62 | 63 | {%- if c.name.startswith("ComponentProperties") %} 64 | 65 | ### ComponentProperties Attributes 66 | The expected properties for the suppported deployment types are indicated below. 67 | 68 | - Properties for `helm.v3` components 69 | 70 | | Attribute | Type | Required? | Description | 71 | | --- | --- | --- | --- | 72 | | repository | string | Y | The URL indicating the helm chart's location.| 73 | | revision | string | Y | The helm chart's full version.| 74 | | wait | bool | N | If `True`, indicates the device MUST wait until the helm chart has finished installing before installing the next helm chart. The default is `True`. The Workload Fleet Management Client MUST support `True` and MAY support `False`. Only applies if multiple `helm.v3` components are provided.| 75 | | timeout | string | N | The time to wait for the component's installation to complete. If the installation does not completed before the timeout occurs the installation process fails. The format is "##m##s" indicating the total number of minutes and seconds to wait. | 76 | 77 | - Properties for `compose` components 78 | 79 | > **Investigation Needed**: We need to have more discussion about how Compose should be handled and what is required here. 80 | 81 | | Attribute | Type | Required? | Description | 82 | | --- | --- | --- | --- | 83 | | packageLocation | string | Y | The URL indicating the Compose package's location. | 84 | | keyLocation | string | N | The public key used to validated the digitally signed package. It is highly recommend to digitally sign the package. When signing the package PGP MUST be used.| 85 | | wait | bool | N | If `True`, indicates the device MUST wait until the Compose file has finished starting up before starting the next Compose file. The default is `True`. The Workload Fleet Management Client MUST support `True` and MAY support `False`. Only applies if multiple `compose` components are provided.| 86 | | timeout | string | N | The time to wait for the component's installation to complete. If the installation does not completed before the timeout occurs the installation process fails. The format is "##m##s" indicating the total number of minutes and seconds to wait.| 87 | 88 | ## Defining configurable application parameters 89 | 90 | To allow customizable configuration values when installing an application, the *application description* defines the parameters and configuration sections giving the application vendor control over what can be configured when installing, or updating, an application. The [configuration](#configuration-attributes) section describes how the workload orchestration software vendor must display parameters to the user to allow them to specify the values. The [schema](#schema-attributes) section describes how the workload orchestration software vendor must validate the values provided by the user before the application is installed or updated. 91 | 92 | > **Note:** At this point the specification only deals with parameter values provided by the user as part of installing, or updating, the application. We anticipate parameter values to come from other sources, such as the device, in the future and not only from the user. 93 | 94 | {%- endif %} 95 | {%- endfor %} 96 | 97 | ## Application Description Examples 98 | 99 | ### Example 1: Simple Application Description 100 | A simple hello-world example of an `ApplicationDescription` is shown below: 101 | 102 | ```yaml 103 | {% include 'examples/valid/ApplicationDescription-001.yaml' %} 104 | ``` 105 | 106 | ### Example 2: Application Description with Deployment Profiles for Helm and Compose 107 | An example of an `ApplicationDescription` defining [deployment profiles](#deploymentprofile-attributes) for both cases, Helm chart as well as Compose, is shown below. 108 | 109 | ```yaml 110 | {% include 'examples/valid/ApplicationDescription-002.yaml' %} 111 | ``` -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/desired-state-api/desired-state.linkml.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://linkml.io/linkml-model/linkml_model/jsonschema/meta.schema.json 2 | id: http://specification.margo.org/desired_state_schema 3 | name: DesiredState 4 | description: >- 5 | The desired state is expressed as a 6 | [Kubernetes custom resource definition](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) 7 | and made available to the device's management client as a YAML document using the OpenGitOps pattern. 8 | version: 1.0 #Arne: update later 9 | prefixes: 10 | linkml: https://w3id.org/linkml/ 11 | margo: http://specification.margo.org/ 12 | imports: 13 | - linkml:types 14 | 15 | default_prefix: margo 16 | default_range: string 17 | 18 | classes: 19 | DesiredState: 20 | description: A class representing the desired state of an entity. 21 | attributes: 22 | apiVersion: 23 | description: Identifier of the version of the API the object definition follows. 24 | required: true 25 | range: string 26 | rank: 10 27 | kind: 28 | description: Must be `ApplicationDeployment`. 29 | equals_string: "ApplicationDeployment" 30 | required: true 31 | range: string 32 | rank: 20 33 | metadata: 34 | description: >- 35 | Metadata element specifying characteristics about the application deployment. 36 | See the [Metadata Attributes](#metadata-attributes) section below. 37 | range: Metadata 38 | required: true 39 | rank: 30 40 | spec: 41 | description: >- 42 | Spec element that defines deployment profile and parameters associated with the application deployment. 43 | See the [Spec Attributes](#spec-attributes) section below. 44 | range: Spec 45 | required: true 46 | rank: 40 47 | 48 | Metadata: 49 | description: Metadata associated with the desired state. 50 | rank: 10 51 | attributes: 52 | annotations: 53 | description: >- 54 | Defines the application ID and unique identifier associated to the deployment specification. 55 | Needs to be assigned by the Workload Orchestration Software. 56 | See the [Annotation Attributes](#annotations-attributes) section below. 57 | range: Annotations 58 | required: true 59 | rank: 10 60 | name: 61 | description: >- 62 | When deploying to Kubernetes, the manifests name. 63 | The name is chosen by the workload orchestration vendor and is not displayed anywhere. 64 | required: true 65 | rank: 20 66 | namespace: 67 | description: When deploying to Kubernetes, the namespace the manifest is added under. The namespace is chosen by the workload orchestration solution vendor. 68 | required: true 69 | rank: 30 70 | 71 | Annotations: 72 | description: A class representing annotations. 73 | rank: 20 74 | attributes: 75 | applicationId: 76 | description: >- 77 | An identifier for the application. 78 | The id is used to help create unique identifiers where required, such as namespaces. 79 | The id must be lower case letters and numbers and MAY contain dashes. 80 | Uppercase letters, underscores and periods MUST NOT be used. 81 | The id MUST NOT be more than 200 characters. 82 | The applicationId MUST match the associated application package Metadata "id" attribute. 83 | required: true 84 | pattern: "^[-a-z0-9]{1,200}$" 85 | rank: 10 86 | id: 87 | description: >- 88 | The unique identifier UUID of the deployment specification. 89 | Needs to be assigned by the Workload Orchestration Software. 90 | required: true 91 | pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" 92 | rank: 20 93 | 94 | Spec: 95 | description: Specification details of the desired state. 96 | rank: 30 97 | attributes: 98 | deploymentProfile: 99 | description: Section that defines deployment details including type and components. 100 | range: DeploymentProfile 101 | required: true 102 | rank: 10 103 | parameters: 104 | description: Describes the configured parameters applied via the end-user. 105 | range: Parameter 106 | required: true 107 | multivalued: true 108 | inlined: true 109 | inlined_as_list: false 110 | rank: 20 111 | 112 | DeploymentProfile: 113 | description: A class representing a deployment profile. 114 | rank: 40 115 | # abstract: true 116 | slots: 117 | - type 118 | - components 119 | 120 | HelmDeploymentProfile: 121 | is_a: DeploymentProfile 122 | rank: 40 123 | slot_usage: 124 | type: 125 | equals_string: "helm.v3" 126 | rank: 10 127 | components: 128 | range: HelmComponent 129 | rank: 20 130 | 131 | ComposeDeploymentProfile: 132 | is_a: DeploymentProfile 133 | rank: 40 134 | slot_usage: 135 | type: 136 | equals_string: "compose" 137 | rank: 10 138 | components: 139 | range: ComposeComponent 140 | rank: 20 141 | 142 | Component: 143 | description: A class representing a component of a deployment profile. 144 | rank: 50 145 | # abstract: true 146 | attributes: 147 | name: 148 | description: The name of the component. 149 | # identifier: true 150 | required: true 151 | rank: 10 152 | properties: 153 | description: Properties associated with the component. 154 | range: Property 155 | required: true 156 | multivalued: true 157 | inlined: true 158 | inlined_as_list: false 159 | rank: 20 160 | 161 | HelmComponent: 162 | is_a: Component 163 | rank: 50 164 | 165 | ComposeComponent: 166 | is_a: Component 167 | rank: 50 168 | 169 | Property: 170 | rank: 80 171 | attributes: 172 | name: 173 | identifier: true 174 | range: string 175 | rank: 10 176 | value: 177 | range: string 178 | rank: 20 179 | required: true 180 | 181 | Parameter: 182 | description: A class representing a single parameter. 183 | rank: 60 184 | attributes: 185 | name: 186 | identifier: true 187 | required: true 188 | rank: 10 189 | value: 190 | description: The value of the parameter. 191 | required: true 192 | rank: 20 193 | targets: 194 | description: The targets associated with the parameter. 195 | range: Target 196 | multivalued: true 197 | required: true 198 | rank: 30 199 | 200 | Target: 201 | description: A class representing a target for a parameter. 202 | rank: 70 203 | attributes: 204 | pointer: 205 | description: The pointer indicating the location of the target. 206 | required: true 207 | rank: 10 208 | components: 209 | description: The components associated with the target. 210 | multivalued: true 211 | required: true 212 | rank: 20 213 | 214 | slots: 215 | type: 216 | description: The type of deployment profile (e.g., helm.v3, compose). 217 | range: string 218 | required: true 219 | rank: 10 220 | 221 | components: 222 | description: Components of the application 223 | range: Component 224 | multivalued: true 225 | required: true 226 | rank: 20 227 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/desired-state-api/resources/examples/invalid/DesiredState-001.yaml: -------------------------------------------------------------------------------- 1 | # Demonstrates validation of metadata.annotations.id 2 | # Invalid kind of Kubernetes custom resource. 3 | apiVersion: application.margo.org/v1alpha1 4 | # `kind` != `ApplicationDeployment` 5 | kind: SomethingErroneous 6 | metadata: 7 | annotations: 8 | applicationId: com-northstartida-digitron-orchestrator 9 | id: a3e2f5dc-912e-494f-8395-52cf3769bc06 10 | name: com-northstartida-digitron-orchestrator-deployment 11 | namespace: margo-poc 12 | spec: 13 | deploymentProfile: 14 | type: helm.v3 15 | components: 16 | - name: database-services 17 | properties: 18 | repository: oci://quay.io/charts/realtime-database-services 19 | revision: 2.3.7 20 | timeout: 8m30s 21 | wait: "true" 22 | - name: digitron-orchestrator 23 | properties: 24 | repository: oci://northstarida.azurecr.io/charts/northstarida-digitron-orchestrator 25 | revision: 1.0.9 26 | wait: "true" 27 | parameters: 28 | adminName: 29 | value: Some One 30 | targets: 31 | - pointer: administrator.name 32 | components: 33 | - digitron-orchestrator 34 | adminPrincipalName: 35 | value: someone@somewhere.com 36 | targets: 37 | - pointer: administrator.userPrincipalName 38 | components: 39 | - digitron-orchestrator 40 | cpuLimit: 41 | value: "4" 42 | targets: 43 | - pointer: settings.limits.cpu 44 | components: 45 | - digitron-orchestrator 46 | idpClientId: 47 | value: 123-ABC 48 | targets: 49 | - pointer: idp.clientId 50 | components: 51 | - digitron-orchestrator 52 | idpName: 53 | value: Azure AD 54 | targets: 55 | - pointer: idp.name 56 | components: 57 | - digitron-orchestrator 58 | idpProvider: 59 | value: aad 60 | targets: 61 | - pointer: idp.provider 62 | components: 63 | - digitron-orchestrator 64 | idpUrl: 65 | value: https://123-abc.com 66 | targets: 67 | - pointer: idp.providerUrl 68 | components: 69 | - digitron-orchestrator 70 | - pointer: idp.providerMetadata 71 | components: 72 | - digitron-orchestrator 73 | memoryLimit: 74 | value: "16384" 75 | targets: 76 | - pointer: settings.limits.memory 77 | components: 78 | - digitron-orchestrator 79 | pollFrequency: 80 | value: "120" 81 | targets: 82 | - pointer: settings.pollFrequency 83 | components: 84 | - digitron-orchestrator 85 | - database-services 86 | siteId: 87 | value: SID-123-ABC 88 | targets: 89 | - pointer: settings.siteId 90 | components: 91 | - digitron-orchestrator 92 | - database-services 93 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/desired-state-api/resources/examples/invalid/DesiredState-002.yaml: -------------------------------------------------------------------------------- 1 | # Demonstrates validation of metadata.annotations.applicationId 2 | # Invalid characters being used. 3 | apiVersion: application.margo.org/v1alpha1 4 | kind: ApplicationDeployment 5 | metadata: 6 | annotations: 7 | # id contains invalid characters: upper-case letters ('A' and 'Z'), special characters ('.' and '_') 8 | applicationId: com_northstartida.Digitron-Orchestrator 9 | id: a3e2f5dc-912e-494f-8395-52cf3769bc06 10 | name: com-northstartida-digitron-orchestrator-deployment 11 | namespace: margo-poc 12 | spec: 13 | deploymentProfile: 14 | type: helm.v3 15 | components: 16 | - name: database-services 17 | properties: 18 | repository: oci://quay.io/charts/realtime-database-services 19 | revision: 2.3.7 20 | timeout: 8m30s 21 | wait: "true" 22 | - name: digitron-orchestrator 23 | properties: 24 | repository: oci://northstarida.azurecr.io/charts/northstarida-digitron-orchestrator 25 | revision: 1.0.9 26 | wait: "true" 27 | parameters: 28 | adminName: 29 | value: Some One 30 | targets: 31 | - pointer: administrator.name 32 | components: 33 | - digitron-orchestrator 34 | adminPrincipalName: 35 | value: someone@somewhere.com 36 | targets: 37 | - pointer: administrator.userPrincipalName 38 | components: 39 | - digitron-orchestrator 40 | cpuLimit: 41 | value: "4" 42 | targets: 43 | - pointer: settings.limits.cpu 44 | components: 45 | - digitron-orchestrator 46 | idpClientId: 47 | value: 123-ABC 48 | targets: 49 | - pointer: idp.clientId 50 | components: 51 | - digitron-orchestrator 52 | idpName: 53 | value: Azure AD 54 | targets: 55 | - pointer: idp.name 56 | components: 57 | - digitron-orchestrator 58 | idpProvider: 59 | value: aad 60 | targets: 61 | - pointer: idp.provider 62 | components: 63 | - digitron-orchestrator 64 | idpUrl: 65 | value: https://123-abc.com 66 | targets: 67 | - pointer: idp.providerUrl 68 | components: 69 | - digitron-orchestrator 70 | - pointer: idp.providerMetadata 71 | components: 72 | - digitron-orchestrator 73 | memoryLimit: 74 | value: "16384" 75 | targets: 76 | - pointer: settings.limits.memory 77 | components: 78 | - digitron-orchestrator 79 | pollFrequency: 80 | value: "120" 81 | targets: 82 | - pointer: settings.pollFrequency 83 | components: 84 | - digitron-orchestrator 85 | - database-services 86 | siteId: 87 | value: SID-123-ABC 88 | targets: 89 | - pointer: settings.siteId 90 | components: 91 | - digitron-orchestrator 92 | - database-services 93 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/desired-state-api/resources/examples/invalid/DesiredState-003.yaml: -------------------------------------------------------------------------------- 1 | # Demonstrates validation of metadata.annotations.applicationId 2 | # Too long. 3 | apiVersion: application.margo.org/v1alpha1 4 | kind: ApplicationDeployment 5 | metadata: 6 | annotations: 7 | # id is over 200 characters long (it is 201 characters long) 8 | applicationId: "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901" 9 | id: a3e2f5dc-912e-494f-8395-52cf3769bc06 10 | name: com-northstartida-digitron-orchestrator-deployment 11 | namespace: margo-poc 12 | spec: 13 | deploymentProfile: 14 | type: helm.v3 15 | components: 16 | - name: database-services 17 | properties: 18 | repository: oci://quay.io/charts/realtime-database-services 19 | revision: 2.3.7 20 | timeout: 8m30s 21 | wait: "true" 22 | - name: digitron-orchestrator 23 | properties: 24 | repository: oci://northstarida.azurecr.io/charts/northstarida-digitron-orchestrator 25 | revision: 1.0.9 26 | wait: "true" 27 | parameters: 28 | adminName: 29 | value: Some One 30 | targets: 31 | - pointer: administrator.name 32 | components: 33 | - digitron-orchestrator 34 | adminPrincipalName: 35 | value: someone@somewhere.com 36 | targets: 37 | - pointer: administrator.userPrincipalName 38 | components: 39 | - digitron-orchestrator 40 | cpuLimit: 41 | value: "4" 42 | targets: 43 | - pointer: settings.limits.cpu 44 | components: 45 | - digitron-orchestrator 46 | idpClientId: 47 | value: 123-ABC 48 | targets: 49 | - pointer: idp.clientId 50 | components: 51 | - digitron-orchestrator 52 | idpName: 53 | value: Azure AD 54 | targets: 55 | - pointer: idp.name 56 | components: 57 | - digitron-orchestrator 58 | idpProvider: 59 | value: aad 60 | targets: 61 | - pointer: idp.provider 62 | components: 63 | - digitron-orchestrator 64 | idpUrl: 65 | value: https://123-abc.com 66 | targets: 67 | - pointer: idp.providerUrl 68 | components: 69 | - digitron-orchestrator 70 | - pointer: idp.providerMetadata 71 | components: 72 | - digitron-orchestrator 73 | memoryLimit: 74 | value: "16384" 75 | targets: 76 | - pointer: settings.limits.memory 77 | components: 78 | - digitron-orchestrator 79 | pollFrequency: 80 | value: "120" 81 | targets: 82 | - pointer: settings.pollFrequency 83 | components: 84 | - digitron-orchestrator 85 | - database-services 86 | siteId: 87 | value: SID-123-ABC 88 | targets: 89 | - pointer: settings.siteId 90 | components: 91 | - digitron-orchestrator 92 | - database-services 93 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/desired-state-api/resources/examples/invalid/DesiredState-004.yaml: -------------------------------------------------------------------------------- 1 | # Demonstrates validation of metadata.annotations.id 2 | # Not a valid UUID. 3 | apiVersion: application.margo.org/v1alpha1 4 | kind: ApplicationDeployment 5 | metadata: 6 | annotations: 7 | applicationId: com-northstartida-digitron-orchestrator 8 | # id is not a valid UUID 9 | id: this-is-definitively-not-a-uuid 10 | name: com-northstartida-digitron-orchestrator-deployment 11 | namespace: margo-poc 12 | spec: 13 | deploymentProfile: 14 | type: helm.v3 15 | components: 16 | - name: database-services 17 | properties: 18 | repository: oci://quay.io/charts/realtime-database-services 19 | revision: 2.3.7 20 | timeout: 8m30s 21 | wait: "true" 22 | - name: digitron-orchestrator 23 | properties: 24 | repository: oci://northstarida.azurecr.io/charts/northstarida-digitron-orchestrator 25 | revision: 1.0.9 26 | wait: "true" 27 | parameters: 28 | adminName: 29 | value: Some One 30 | targets: 31 | - pointer: administrator.name 32 | components: 33 | - digitron-orchestrator 34 | adminPrincipalName: 35 | value: someone@somewhere.com 36 | targets: 37 | - pointer: administrator.userPrincipalName 38 | components: 39 | - digitron-orchestrator 40 | cpuLimit: 41 | value: "4" 42 | targets: 43 | - pointer: settings.limits.cpu 44 | components: 45 | - digitron-orchestrator 46 | idpClientId: 47 | value: 123-ABC 48 | targets: 49 | - pointer: idp.clientId 50 | components: 51 | - digitron-orchestrator 52 | idpName: 53 | value: Azure AD 54 | targets: 55 | - pointer: idp.name 56 | components: 57 | - digitron-orchestrator 58 | idpProvider: 59 | value: aad 60 | targets: 61 | - pointer: idp.provider 62 | components: 63 | - digitron-orchestrator 64 | idpUrl: 65 | value: https://123-abc.com 66 | targets: 67 | - pointer: idp.providerUrl 68 | components: 69 | - digitron-orchestrator 70 | - pointer: idp.providerMetadata 71 | components: 72 | - digitron-orchestrator 73 | memoryLimit: 74 | value: "16384" 75 | targets: 76 | - pointer: settings.limits.memory 77 | components: 78 | - digitron-orchestrator 79 | pollFrequency: 80 | value: "120" 81 | targets: 82 | - pointer: settings.pollFrequency 83 | components: 84 | - digitron-orchestrator 85 | - database-services 86 | siteId: 87 | value: SID-123-ABC 88 | targets: 89 | - pointer: settings.siteId 90 | components: 91 | - digitron-orchestrator 92 | - database-services 93 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/desired-state-api/resources/examples/valid/DesiredState-001.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: application.margo.org/v1alpha1 2 | kind: ApplicationDeployment 3 | metadata: 4 | annotations: 5 | applicationId: com-northstartida-digitron-orchestrator 6 | id: a3e2f5dc-912e-494f-8395-52cf3769bc06 7 | name: com-northstartida-digitron-orchestrator-deployment 8 | namespace: margo-poc 9 | spec: 10 | deploymentProfile: 11 | type: helm.v3 12 | components: 13 | - name: database-services 14 | properties: 15 | repository: oci://quay.io/charts/realtime-database-services 16 | revision: 2.3.7 17 | timeout: 8m30s 18 | wait: "true" 19 | - name: digitron-orchestrator 20 | properties: 21 | repository: oci://northstarida.azurecr.io/charts/northstarida-digitron-orchestrator 22 | revision: 1.0.9 23 | wait: "true" 24 | parameters: 25 | adminName: 26 | value: Some One 27 | targets: 28 | - pointer: administrator.name 29 | components: 30 | - digitron-orchestrator 31 | adminPrincipalName: 32 | value: someone@somewhere.com 33 | targets: 34 | - pointer: administrator.userPrincipalName 35 | components: 36 | - digitron-orchestrator 37 | cpuLimit: 38 | value: "4" 39 | targets: 40 | - pointer: settings.limits.cpu 41 | components: 42 | - digitron-orchestrator 43 | idpClientId: 44 | value: 123-ABC 45 | targets: 46 | - pointer: idp.clientId 47 | components: 48 | - digitron-orchestrator 49 | idpName: 50 | value: Azure AD 51 | targets: 52 | - pointer: idp.name 53 | components: 54 | - digitron-orchestrator 55 | idpProvider: 56 | value: aad 57 | targets: 58 | - pointer: idp.provider 59 | components: 60 | - digitron-orchestrator 61 | idpUrl: 62 | value: https://123-abc.com 63 | targets: 64 | - pointer: idp.providerUrl 65 | components: 66 | - digitron-orchestrator 67 | - pointer: idp.providerMetadata 68 | components: 69 | - digitron-orchestrator 70 | memoryLimit: 71 | value: "16384" 72 | targets: 73 | - pointer: settings.limits.memory 74 | components: 75 | - digitron-orchestrator 76 | pollFrequency: 77 | value: "120" 78 | targets: 79 | - pointer: settings.pollFrequency 80 | components: 81 | - digitron-orchestrator 82 | - database-services 83 | siteId: 84 | value: SID-123-ABC 85 | targets: 86 | - pointer: settings.siteId 87 | components: 88 | - digitron-orchestrator 89 | - database-services 90 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/desired-state-api/resources/examples/valid/DesiredState-002.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: application.margo.org/v1alpha1 2 | kind: ApplicationDeployment 3 | metadata: 4 | annotations: 5 | applicationId: com-northstartida-digitron-orchestrator 6 | id: ad9b614e-8912-45f4-a523-372358765def 7 | name: com-northstartida-digitron-orchestrator-deployment 8 | namespace: margo-poc 9 | spec: 10 | deploymentProfile: 11 | type: compose 12 | components: 13 | - name: digitron-orchestrator-docker 14 | properties: 15 | keyLocation: https://northsitarida.com/digitron/docker/public-key.asc 16 | packageLocation: https://northsitarida.com/digitron/docker/digitron-orchestrator.tar.gz 17 | parameters: 18 | adminName: 19 | value: Some One 20 | targets: 21 | - pointer: ENV.ADMIN_NAME 22 | components: 23 | - digitron-orchestrator-docker 24 | adminPrincipalName: 25 | value: someone@somewhere.com 26 | targets: 27 | - pointer: ENV.ADMIN_PRINCIPALNAME 28 | components: 29 | - digitron-orchestrator-docker 30 | idpClientId: 31 | value: 123-ABC 32 | targets: 33 | - pointer: ENV.IDP_CLIENT_ID 34 | components: 35 | - digitron-orchestrator-docker 36 | idpName: 37 | value: Azure AD 38 | targets: 39 | - pointer: ENV.IDP_NAME 40 | components: 41 | - digitron-orchestrator-docker 42 | idpProvider: 43 | value: aad 44 | targets: 45 | - pointer: ENV.IDP_PROVIDER 46 | components: 47 | - digitron-orchestrator-docker 48 | idpUrl: 49 | value: https://123-abc.com 50 | targets: 51 | - pointer: ENV.IDP_URL 52 | components: 53 | - digitron-orchestrator-docker 54 | pollFrequency: 55 | value: "120" 56 | targets: 57 | - pointer: ENV.POLL_FREQUENCY 58 | components: 59 | - digitron-orchestrator-docker 60 | siteId: 61 | value: SID-123-ABC 62 | targets: 63 | - pointer: ENV.SITE_ID 64 | components: 65 | - digitron-orchestrator-docker 66 | -------------------------------------------------------------------------------- /src/margo-api-reference/workload-api/desired-state-api/resources/index.md.jinja2: -------------------------------------------------------------------------------- 1 | # Desired State 2 | 3 | > Action: This is incomplete and doesn't contain the details for the deploymentProfile or parameters 4 | 5 | > Action: We are currently investigating the best way to interface with source control infrastructure. 6 | 7 | {% if schema.description %}{{ schema.description }}{% endif %} 8 | 9 | ### ApplicationDeployment Definition 10 | 11 | ```yaml 12 | apiVersion: application.margo.org/v1alpha1 13 | kind: ApplicationDeployment 14 | metadata: 15 | annotations: 16 | id: 17 | applicationId: 18 | name: 19 | namespace: 20 | spec: 21 | deploymentProfile: 22 | type: 23 | components: 24 | - name: 25 | properties: 26 | parameters: 27 | param: 28 | value: 29 | targets: 30 | - pointer: 31 | components:[] 32 | ``` 33 | 34 | {% macro abort(error) %} 35 | {{ None['[ERROR] ' ~ error][0] }} 36 | {% endmacro %} 37 | 38 | {%- macro format_range(slot) -%} 39 | {%- if slot.multivalued and slot.inlined -%} 40 | {%- if slot.inlined_as_list -%} 41 | {{ abort("List not supported yet") }} 42 | {%- else -%} 43 | {%- if slot.name == "properties" -%} 44 | map[string][string] 45 | {%- else -%} 46 | map[string][{{ slot.range }}] 47 | {%- endif -%} 48 | {%- endif -%} 49 | {%- else -%} 50 | {{ slot.range }} 51 | {%- endif -%} 52 | {%- endmacro -%} 53 | 54 | | Attribute | Type | Required? | Description | 55 | | --- | --- | --- | --- | 56 | {% for slot in schemaview.class_slots("DesiredState")|sort(attribute='rank') -%} 57 | | {{ slot }} | {{ schemaview.get_slot(slot).range }} | {% if schemaview.get_slot(slot).required == True %} Y {% else %} N {% endif %} | {{ schemaview.get_slot(slot).description }}| 58 | {% endfor -%} 59 | 60 | {% for c in gen.all_class_objects()|sort(attribute='rank') %} 61 | {%- if c.name != "DesiredState" and not c.name.startswith("Helm") and not c.name.startswith("DockerCompose") and not c.name == "Property" %} 62 | #### {{ c.name }} Attributes 63 | 64 | | Attribute | Type | Required? | Description | 65 | | --- | --- | --- | --- | 66 | {% for slot in gen.get_direct_slots(c)|sort(attribute='rank') -%} 67 | | {{ slot.name }} | {{ format_range(slot) }} | {% if slot.required == True %} Y {% else %} N {% endif %} | {{ slot.description }}| 68 | {% endfor %} 69 | {%- endif %} 70 | {%- endfor %} 71 | 72 | ### Example: Cluster Enabled Application Deployment Specification 73 | 74 | ```yaml 75 | {% include 'examples/valid/DesiredState-001.yaml' %} 76 | ``` 77 | 78 | ### Example: Standalone Device Application Deployment Specification: 79 | 80 | ```yaml 81 | {% include 'examples/valid/DesiredState-002.yaml' %} 82 | ``` 83 | 84 | -------------------------------------------------------------------------------- /system-design/CNAME: -------------------------------------------------------------------------------- 1 | specification.margo.org -------------------------------------------------------------------------------- /system-design/app-interoperability/.gitignore: -------------------------------------------------------------------------------- 1 | docs 2 | 3 | -------------------------------------------------------------------------------- /system-design/app-interoperability/application-package-definition.md: -------------------------------------------------------------------------------- 1 | # Application Package Definition 2 | 3 | The application package, which is used to [distribute an application](../margo-overview/application-package-overview.md), comprises the following elements: 4 | 5 | - The **application description**: a YAML document with the element `kind` defined as `ApplicationDescription`, which is stored in a file (for example named `margo.yaml`) and contains information about the application's [metadata](../margo-api-reference/workload-api/application-package-api/application-description.md#metadata-attributes) (e.g., description, icon, release notes, license file, etc.), application supported [deployment configurations](../margo-api-reference/workload-api/application-package-api/application-description.md#deploymentprofile-attributes) (e.g, Helm charts, Compose package), and [configurable application parameters](../margo-api-reference/workload-api/application-package-api/application-description.md#defining-configurable-application-parameters). There SHALL be only one YAML file in the package root of kind `ApplicationDescription`. 6 | - The **resources**, which are additional information about the application (e.g., manual, icon, release notes, license file, etc.) that can be provided in an [application catalog](../margo-overview/technical-lexicon.md) or [marketplace](../margo-overview/technical-lexicon.md). 7 | 8 | The application package has the following file/folder structure: 9 | 10 | ```yaml 11 | / # REQUIRED top-level directory 12 | └── application description # REQUIRED a YAML document with element 'kind' as 'ApplicationDescription' stored in a file (e.g., 'margo.yaml') 13 | └── resources # OPTIONAL folder with application resources (e.g., icon, license file, release notes) that can be displayed in an application catalog 14 | ``` 15 | 16 | An application aggregates one or more [OCI Containers](https://github.com/opencontainers). While the application package is made available in an [application registry](./workload-orch-to-app-reg-interaction.md), the referenced OCI artifacts are stored in a remote or [local registry](../app-interoperability/local-registries.md). 17 | 18 | > **Note** 19 | > Application catalogs or marketplaces are out of scope for Margo. The exact requirements of the marketing material shall be defined by the application marketplace beyond outlined mandatory content. 20 | 21 | The [deployment profiles](../margo-api-reference/workload-api/application-package-api/application-description.md#deploymentprofile-attributes) specified in the application description SHALL be defined as Helm Charts AND/OR Compose components. 22 | 23 | - To target devices, which run Kubernetes, applications must be packaged as Helm charts using [Helm (version 3)](https://helm.sh/docs/topics/charts/). 24 | - To target devices, which deploy applications using [Compose](https://www.compose-spec.io/), applications must be packaged as a tarball file containing the *compose.yml* file and any additional artifacts referenced by the Compose file (e.g., configuration files, environment variable files, etc.). It is highly recommend to digitally sign this package. When digitally signing the package PGP encryption MUST be used. 25 | 26 | > **Investigation Needed**: We plan to do a security review of this package definition later. 27 | > During this review we will revisit the way the Compose tarball file should be signed. 28 | > We will also discuss how we should handle secure container registries that require a username and password. 29 | > 30 | > **Investigation Needed**: We need to determine what impact, if any, using 3rd party helm charts has on being Margo compliant. 31 | > 32 | > **Investigation Needed**: Missing in the current specification are ways to define the compatibility information (resources required to run, application dependencies) as well as required infrastructure services such as storage, message queues/bus, reverse proxy, or authentication/authorization/accounting. 33 | 34 | If either one cannot be implemented it MAY be omitted but Margo RECOMMENDS defining [deployment profiles](../margo-api-reference/workload-api/application-package-api/application-description.md#deploymentprofile-attributes) as both Helm chart **AND** Compose components to strengthen interoperability and applicability. 35 | 36 | > **Note** 37 | > A device running the application will only install the application using either Compose files or Helm Charts but not both. 38 | 39 | ## Relevant Links 40 | Please follow the subsuquent link to view the technical reference: 41 | 42 | - [Application Description](../margo-api-reference/workload-api/application-package-api/application-description.md) 43 | -------------------------------------------------------------------------------- /system-design/app-interoperability/local-registries.md: -------------------------------------------------------------------------------- 1 | # Local Registries 2 | 3 | This section investigates options for configuring the usage of local OCI-based container (or Helm Chart) registries. The goal of configuring such local registries is to avoid the reliance on public, Internet-accessible registries. The reasons for not using such public registries are mainly twofold: (1) publicly hosted container images or Helm charts could become unavailable at some point, as the owner decides to take the container images or Helm charts off the public registry, (2) Internet connectivity may not be available to the device and hence public registries are not reachable, or (3) end-users want to host their own registries so they can do security scans and validate the packages. 4 | 5 | In terms of connectivity, we can thereby distinguish mainly between the following device categories: 6 | 7 | 1. **Fully connected device**, which means a device is deployed in the field (e.g., a factory shop floor) and has access to the Internet. 8 | 2. **Locally connected device**, i.e., the device has connectivity to a local network (e.g., factory- or enterprise-wide) and a local repository can be made reachable. 9 | 3. **Air-gapped device**, i.e., the device generally is not connected and must be configured by accessing it directly (via USB, Bluetooth, or a direct network link, e.g., via Ethernet cable, or similar) for example via a technician’s laptop. 10 | 11 | Local registries for container images and Helm Charts can be used for all 3 categories of devices. In case of **fully connected devices**, although the device could reach the Internet, a local registry can still be useful, e.g., as a cache for remote registries to save on bandwidth or to have container images and Helm Carts reliably available. In case of **locally connected devices**, a local registry is required to enable the WOA to install margo applications on the device, as the device/WOA does not have Internet access. Thereby, the local registry can be setup as a _pull-through cache_ where data (e.g., container images) are cached locally when they are first retrieved from a remote source and subsequent requests for the same data are served from the local cache rather than fetching it again from the remote source. In case of **air-gapped devices**, a local registry has to be accessible on the technician's laptop (or other directly connected device), which performs the application installation process. 12 | 13 | To setup local registries, different configuration options exist: 14 | 15 | ## Option - Container Registry Mirror on Kubernetes Level 16 | 17 | Kubernetes supports the configuration of registry mirrors. How this is configured depends on the distribution and the underlying container runtime. Distributions that utilize **containerd** as runtime (e.g., k3s or microk8s) allow the definition of mirrors in a configuration file. For example, in k3s the file `/etc/rancher/k3s/registries.yaml` can be used to set up a mirror for each device's Kubernetes environment: 18 | 19 | ``` 20 | mirrors: 21 | "docker.io": 22 | endpoint: 23 | - "http://:5000" 24 | configs: 25 | "docker.io": 26 | auth: 27 | username: "" 28 | password: "" 29 | ``` 30 | 31 | ## Option - Container Registry as Pull-through Cache on Docker Level 32 | 33 | To configure a pull-through cache in Docker for the container registry, a Docker Registry can be setup that acts as caching proxy for a remote Docker registry. Such a Docker Registry container can be defined using the following `config.yml`: 34 | 35 | ``` 36 | version: 0.1 37 | log: 38 | fields: 39 | service: registry 40 | storage: 41 | filesystem: 42 | rootdirectory: /var/lib/registry 43 | http: 44 | addr: :5000 45 | headers: 46 | X-Content-Type-Options: [nosniff] 47 | health: 48 | storagedriver: 49 | enabled: true 50 | interval: 10s 51 | threshold: 3 52 | proxy: 53 | remoteurl: https://registry-1.docker.io 54 | ``` 55 | 56 | This registry can be started uing the following command: 57 | `docker run -d -p 5000:5000 --restart unless-stopped --name registry -v $(pwd)/config.yml:/etc/docker/registry/config.yml registry:2` 58 | 59 | Then, the Docker daemon needs to be configured to use the private registry as a mirror in the `/etc/docker/daemon.json` file: 60 | ``` 61 | { 62 | "registry-mirrors": ["http://10.100.2.102:5000"], 63 | "insecure-registries": ["10.100.2.102:5000"] 64 | } 65 | ``` 66 | 67 | ## Option - Helm Chart Registry as Pull-through Cache 68 | 69 | Setting up a pull-through cache for Helm charts in combination with Kubernetes involves configuring a local Helm chart repository, e.g., ChartMuseum that can be installed with the `PROXY_CACHE` variable set to `true`: 70 | 71 | ``` 72 | helm repo add chartmuseum https://chartmuseum.github.io/charts 73 | helm repo update 74 | helm install my-chartmuseum chartmuseum/chartmuseum --set env.open.DISABLE_API=false --set env.open.PROXY_CACHE=true 75 | ``` 76 | 77 | Then, this Helm Chart repository can be added to Helm and chart releases can be installed there: 78 | 79 | ``` 80 | helm repo add my-cached-repo http://:8080 81 | helm repo update 82 | helm install my-release my-cached-repo/ 83 | 84 | ``` 85 | Now, when deploying applications in Kubernetes using Helm, the cached repository is used to serve charts rather than the remote repository. 86 | -------------------------------------------------------------------------------- /system-design/app-interoperability/publishing-workload-observability-data.md: -------------------------------------------------------------------------------- 1 | # Publishing Workload Observability Data 2 | 3 | Compliant workloads MAY choose to expose workload specific observability data by sending their observability data to the Open Telemetry collector on the standalone device or cluster. While this is optional, it is highly recommended in order to support distributed diagnostics. 4 | 5 | Workload suppliers choosing to expose metrics, traces or logs for consumption with OpenTelemetry MUST send the data to the OpenTelemetry collector using OTLP. 6 | 7 | The information required to communicate with the device's OTEL Collector is injected into each container using [environment variables](../device-interoperability/collecting-workload-observability-data.md#connecting-to-the-opentelemetry-collector). 8 | 9 | Workload suppliers SHOULD NOT expect their workloads to be auto-instrumented by anything outside of their control (by the [OpenTelemetry operator](https://github.com/open-telemetry/opentelemetry-operator#opentelemetry-auto-instrumentation-injection) for example). 10 | 11 | A workload supplier MAY choose an observability framework other than OpenTelemetry but it MUST be self-contained within the deployment of their workload. If an alternative approach is taken, it is NOT recommended workload suppliers publish their observability data outside the device/cluster by using any other means other than the Open Telemetry collector. If the workload supplier chooses to export data without using the OpenTelemetry collector they MUST NOT do this without the end user's approval. 12 | 13 | > **Note:** See the [workload observability overview](../margo-overview/workload-observability-overview.md) page for more information about workload observablity. 14 | > 15 | > **Action:** We may need to address in some form legacy workloads that are not currently using open telemetry and don't want to migrate their workload to use it. 16 | -------------------------------------------------------------------------------- /system-design/app-interoperability/workload-orch-to-app-reg-interaction.md: -------------------------------------------------------------------------------- 1 | # Application Registry 2 | 3 | This section describes the Application Registry and the exchange of an [application package](./application-package-definition.md) from an Application Developer to the Workload Orchestration Vendor. 4 | 5 | The Application Developer SHALL use a [Git repository](https://git-scm.com/) to share an [application package](./application-package-definition.md). This Git repository is considered the Application Registry. 6 | 7 | The connectivity between the Workload Orchestration Software and the Application Registry SHALL be read-only. 8 | 9 | Upon installation request from the End User, the Workload Orchestration Vendor SHALL retrieve the [application package](./application-package-definition.md) using a ``git pull`` request from the Application Registry. 10 | 11 | The Workload Orchestration Vendor reads in the application description file, ``margo.yaml``, and presents a user interface that allows the specification of parameters available according to ``margo.yaml``. 12 | 13 | The End User then specifies the configuration parameters for the [application package](./application-package-definition.md). 14 | 15 | Then, the [application package](./application-package-definition.md) is ready to be passed on to the installation process. 16 | 17 | > **Note** 18 | > The specifics of the installation process are still under discussion: this could be for example a GitOps based approach. 19 | 20 | During this process the containers referenced in the application manifest ([Helm Chart](https://helm.sh/docs/) or [Compose](https://github.com/compose-spec/compose-spec/blob/master/03-compose-file.md)) are retrieved from container/Helm registries. 21 | 22 | At a minimum, a Margo-compliant WOS SHALL provide a way for an end user to manually setup a connection between the WOS and an application registry. This is required so as not to prohibit an end user for being able to install any Margo-compliant application they wish; including applications developed by the end user. 23 | 24 | The Workload Orchestration Vendor MAY provide enhanced user experience options such as the pre-configuring of application registries to monitor. These can include application registries from third-party application vendors or their own applications. 25 | 26 | ## Secure Access to the Application Package 27 | 28 | It is expected the connection between the Workload Orchestration software and the Application developer’s application registry is secured using standard secure connectivity best practices. Some standard practices include the following: 29 | 30 | - Basic authentication via HTTPS 31 | - Bearer token authentication 32 | - TLS certifications -------------------------------------------------------------------------------- /system-design/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margo/specification/1d11d11334613a71843db9e68b73272ac036dd66/system-design/assets/favicon.ico -------------------------------------------------------------------------------- /system-design/assets/margo_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | 46 | 70 | 73 | 77 | 81 | 85 | 89 | 93 | 97 | 101 | -------------------------------------------------------------------------------- /system-design/css/margo.css: -------------------------------------------------------------------------------- 1 | [data-md-color-scheme="margo"] { 2 | --md-primary-fg-color: hsla(218, 99%, 28%, 1); 3 | --md-footer-bg-color: hsla(218, 99%, 28%, 1); 4 | } 5 | -------------------------------------------------------------------------------- /system-design/device-interoperability/device-requirements.md: -------------------------------------------------------------------------------- 1 | # Device Requirements 2 | 3 | Within Margo, devices are represented by compute hardware that runs within the customers environment to host Margo Compliant Applications. Margo Devices are defined by the roles they can facilitate within the Margo Architecture. An Edge Compute within Margo is initially referenced as a "Device" which represents the initial lifecycle stage. Once the device is onboarded within the Workload Orchestration Software, it assumes a role based on capabilities. 4 | 5 | Supported Device roles are shown below: 6 | 7 | - Standalone Cluster 8 | - Cluster Leader 9 | - Cluster Worker 10 | - Standalone Device 11 | 12 | > Note: Additional device roles will be introduced as the specification matures. 13 | 14 | ## Base device requirements 15 | 16 | - TPM support 17 | - Secure Boot 18 | - Attestation 19 | - Zero Trust Network Access (ZTNA) 20 | 21 | ## Cluster Leader Role Details 22 | 23 | The Cluster Leader Role within Margo describes devices that have the ability to manage the cluster of one or more worker nodes that are connected. Additionally, Cluster Leader can also host Margo compliant workloads. 24 | 25 | **Cluster Leader Functional Requirements:** 26 | 27 | - Host the Workload Fleet Management Client 28 | - This enables the device with the functionality outlined within the [Workload Management](../margo-overview/workload-management-interface-overview.md) section of the specification 29 | - Enable management functionality via Kubernetes API 30 | - Host the following additional components: 31 | - Helm Client (Provider) 32 | - OCI Container Runtime 33 | - OTEL Collector 34 | - Policy Agent 35 | - Host Device Fleet Management Client 36 | - > Note: this functionality is coming soon to the specification 37 | 38 | ## Cluster Worker Role Details 39 | 40 | The Cluster Worker Role within Margo describes devices that have a limited amount of compute capacity that can still run Margo compliant workloads. This role is managed via the Cluster Leader. 41 | 42 | **Cluster Worker Functional Requirements:** 43 | 44 | - Enable Worker Node functionality within a Kubernetes Cluster via the kublet service. 45 | - Host the following additional components: 46 | - OCI Container Runtime 47 | - OTEL Collector 48 | - Policy Agent 49 | - Host Device Fleet Management Client 50 | - > Note: this functionality is coming soon to the specification 51 | 52 | ## Standalone Cluster Role Details 53 | 54 | The Standalone Cluster Role within Margo describes devices that have additional compute capacity to enable a wide range of functions within the ecosystem. 55 | 56 | **Standalone Cluster functional requirements:** 57 | 58 | - Enables both Cluster Leader and Worker roles concurrently in a single device 59 | 1. See Cluster Leader Role and Cluster Worker Role for specific requirements 60 | - The Standalone Cluster role has the ability to transition into either the Cluster Leader or Cluster Worker at a later stage in its lifecycle deployment. 61 | 62 | ## Standalone Device Role Details 63 | 64 | The Standalone Device role represents a device that can host Margo Compliant Workloads. This device role is not intended to be utilized within a clustered configuration and typically consists of devices within limited amount of resources to run workloads. 65 | 66 | **Standalone Device functional requirements:** 67 | 68 | - Host the Workload Fleet Management Client 69 | - This enables the device with the functionality outlined within the [Workload Management](../margo-overview/workload-management-interface-overview.md) section of the specification 70 | - Host the following additional components: 71 | - OCI Container Runtime 72 | - OTEL Collector 73 | - Policy Agent 74 | - Host Device Fleet Management Client 75 | - > Note: this functionality is coming soon to the specification 76 | -------------------------------------------------------------------------------- /system-design/figures/Workload-orchestration-app-package-definition.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | Application Registry & Repository 12 |
13 |
14 |
15 |
16 | 17 | Application Registry & Repository 18 | 19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | Application Package 31 |
32 |
33 |
34 |
35 | 36 | Application Package 37 | 38 |
39 |
40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 |
49 | Application Manifest 50 |
51 |
52 |
53 |
54 | 55 | Application Man... 56 | 57 |
58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 |
68 | Application Artifacts 69 |
70 |
71 |
72 |
73 | 74 | Application Art... 75 | 76 |
77 |
78 | 79 | 80 | 81 | 82 | 83 | 84 |
85 |
86 |
87 | Application Description 88 |
89 |
90 |
91 |
92 | 93 | Application Des... 94 | 95 |
96 |
97 |
98 | 99 | 100 | 101 | 102 | Text is not SVG - cannot display 103 | 104 | 105 | 106 |
-------------------------------------------------------------------------------- /system-design/figures/Workload-orchestration-node-capability-discovery.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | WORKLOAD ORCHESTRATION SERVICE 12 |
13 |
14 |
15 |
16 | 17 | WORKLOAD ORCHESTRATION SERVICE 18 | 19 |
20 |
21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | WORKLOAD 29 |
30 | ORCHESTRATION AGENT 31 |
32 |
33 |
34 |
35 | 36 | WORKLOAD... 37 | 38 |
39 |
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 |
52 |
53 | Device Capability FIle 54 |
55 |
56 |
57 |
58 | 59 | Device Ca... 60 | 61 |
62 |
63 |
64 | 65 | 66 | 67 | 68 | Text is not SVG - cannot display 69 | 70 | 71 | 72 |
-------------------------------------------------------------------------------- /system-design/figures/Workload-orchestration-software.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
WORKLOAD ORCHESTRATION SOFTWARE
WORKLOAD ORCHESTRATION SOFTWARE
Device/Node Configured App Repo
Device/Node Configured Ap...
Text is not SVG - cannot display
-------------------------------------------------------------------------------- /system-design/figures/margo-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /system-design/fleet-management/workload/consuming-workload-observability-data.md: -------------------------------------------------------------------------------- 1 | # Consuming Workload Observability Data 2 | 3 | Workload Fleet Management or observability platform suppliers MAY choose to consume workload observability data exported from the end user's devices to provide valuable services to the end user. 4 | 5 | The end user MAY choose to export observability data from Margo compliant devices to other OpenTelemetry collectors or backends within their environment that is not on the device. 6 | 7 | > **Note**: See the [workload observability overview](../../margo-overview/workload-observability-overview.md) page for more information about workload observability. 8 | -------------------------------------------------------------------------------- /system-design/fleet-management/workload/device-capability-reporting.md: -------------------------------------------------------------------------------- 1 | # Device Capabilities 2 | 3 | The purpose of device capabilities reporting is to ensure the Workload Fleet Management solution has the information needed to pair workloads with compatible edge devices. The [device's capabilities](../../margo-api-reference/workload-api/device-api/device-capabilities.md) are reported to the workload orchestration web service using [Margo management API](../../margo-api-reference/margo-api-specification.md). 4 | 5 | ### Device Capability Reporting 6 | 7 | The device owner MUST report their device's capabilities and characteristics via the [Device API](../../margo-api-reference/workload-api/device-api/device-capabilities.md) when onboarding the device with the workload orchestration solution. Additionally, during the lifecycle of the Edge device, if there is a change that impacts the reported characteristics, the device's interface shall send an update to the Workload Fleet Manager. 8 | 9 | > Action: The device capabilities details are still being discussed 10 | 11 | The following information MUST be provided: 12 | 13 | - Device Id 14 | - Device Vendor 15 | - Model Number 16 | - Serial Number 17 | - Margo Device Role Designation(Cluster Leader/Worker / Standalone Device) 18 | - Resources available for workloads to utilize on the Device: 19 | - Memory Capacity 20 | - Storage Capacity 21 | - CPU information 22 | - Device peripherals(i.e. Graphics card) 23 | - Network interfaces(wifi/eth/cellular) 24 | 25 | For more information see the [device capabilties API](../../margo-api-reference/workload-api/device-api/device-capabilities.md). 26 | -------------------------------------------------------------------------------- /system-design/fleet-management/workload/management-interface-requirements.md: -------------------------------------------------------------------------------- 1 | # Management Interface Requirements 2 | 3 | Provided below are a set of requirements that the Management Interface participants must follow to become Margo compliant. 4 | 5 | - Additional technical details can be found in the following location: [Margo Management API specification](../../margo-api-reference/margo-api-specification.md) 6 | 7 | ## Requirements 8 | 9 | - The Management Interface MUST provide the following functionality: 10 | - device onboarding with the workload orchestration solution 11 | - device capabilities reporting 12 | - identifying desired state changes 13 | - deployment status reporting 14 | - The Workload Fleet Management vendors MUST implement the server side of the API specification. 15 | - The device vendor MUST implement a client following the API specification. 16 | - The Workload Fleet Management vendors solution MUST maintain a storage repository to store the managed edge device's associated set of desired state files. 17 | - Margo does not dictate how the desired state files are stored, other than ensuring they are available upon request. 18 | - The device's management client MUST retrieve the device's set of desired state files from the Workload Fleet Manager. 19 | - Interface patterns MUST support extended device communication downtime. 20 | - The Management Interface MUST MUST reference industry security protocols and port assignments for both client and server interactions. 21 | - Running the device's management client as containerized services is preferred to enable easier lifecycle management but not required. 22 | - The Management Interface MUST allow an end user to configure the following: 23 | - Downtime configuration - ensures the device's management client is not retrying communication when operating under a known downtime. Additionally, communication errors MUST be ignored during this configurable period. 24 | - Polling Interval Period - describes a configurable time period indicating the hours in which the device's management client checks for updates to the device's desired state. 25 | - Polling Interval Rate - describes the rate for how frequently the device's management client checks for updates to the device's desire state. -------------------------------------------------------------------------------- /system-design/fleet-management/workload/workload-deployment.md: -------------------------------------------------------------------------------- 1 | # Workload Deployment 2 | 3 | Margo uses an [OpenGitOps](https://opengitops.dev/) approach for managing the edge device's desired state. The workload orchestration solution vendor maintains Git repositories, under their control, to push updates to the desired state for each device being managed. The device's management client is responsible for monitoring the device's assigned Git repository for any changes to the desired state that MUST be applied. 4 | > Action: The use of GitOps patterns for pulling desired state is still being discussed/investigated. 5 | 6 | 7 | ### Desired State Requirements: 8 | 9 | > Note: Need to investigate best way to construct the Git Repository. Folder structure / Multiple applications per Edge Device/Cluster 10 | > Note: this is the recommendation from FluxCD 11 | 12 | - The workload orchestration solution MUST store the device's [desired state documents](../../margo-api-reference/workload-api/desired-state-api/desired-state.md) within a Git repository the device's management client can access. 13 | > Note: Git repository storage was selected to ensure secure storage and traceability pertaining to the workload's desire state(s). 14 | - The device's management client MUST monitor the device's Git repository for updates to the desired state using the URL and access token provided by the workload orchestration solution during onboarding. 15 | 16 | ### Workload Management Sequence of Operations 17 | 18 | #### Desired State lifecycle: 19 | 20 | 1. The workload orchestration solution creates the [desired state documents](../../margo-api-reference/workload-api/desired-state-api/desired-state.md) based on the end user's inputs when installing, updating or deleting an application. 21 | 2. The workload orchestration solution pushes updates to the device's Git repository reflecting the changes to the desired state. 22 | 3. The device's management client monitors its assigned Git repository for changes. 23 | 4. When the device's management client notices a difference between the current (running) state and the desired state, it MUST pull down and attempt to apply the new desired state. 24 | 25 | #### Applying the Desired State: 26 | 27 | 1. The device attempts to apply the desired state to become new current state 28 | 2. While the new desired state is being applied, the device's management client MUST report progress on state changes (see the [deployment state](#deployment-status) section below) using the [Device API](../../margo-api-reference/workload-api/device-api/deployment-status.md) 29 | 30 | #### Deployment Status 31 | 32 | The deployment status is sent to the workload orchestration web service using the [Device API](../../margo-api-reference/workload-api/device-api/deployment-status.md) when there is a change in the deployment state. This informs the workload orchestration web service of the current state as the new desired state is applied. 33 | 34 | The deployment status uses the following rules: 35 | 36 | - The state is `Pending` once the device management client has received the updated desired state but has not started applying it. When reporting this state indicate the reason. 37 | - Such as waiting on Policy agent 38 | - Waiting on other applications in the 'Order of operations' to be completed. 39 | - The state is `Installing` once the device management client has started the process of applying the desired state. 40 | - The state is `Failure` if at any point the desired state fails to be applied. When reporting a `Failure` state the error message and error code MUST be reported 41 | - The state is `Success` once the desired state has been applied completely 42 | 43 | ![Workload Install Sequence Diagram (svg)](../../figures/workload-install-sequence.drawio.svg) 44 | -------------------------------------------------------------------------------- /system-design/fleet-management/workload/workload-fleet-management-edge-onboarding.md: -------------------------------------------------------------------------------- 1 | # Onboarding 2 | In order for the Workload Fleet Management software to manage the edge device's workloads, the device's management client must first complete onboarding. 3 | 4 | > Action: The details in this page are still under discussion and have not been finalized. 5 | 6 | **The onboarding process includes:** 7 | 8 | - The end user provides the the Workload Fleet Management web service's root URL to the device's management client 9 | - The device's management client downloads the workload orchestration solution vendor's public root CA certificate using the [Onboarding API](../../margo-api-reference/workload-api/onboarding-api/rootca-download.md) 10 | - Context and trust is established between the device's management client and the Workload Fleet Management web service 11 | - The device's management client uses the [Onboarding API](../../margo-api-reference/workload-api/onboarding-api/device-onboarding.md) to onboard with the workload orchestration service. 12 | - The device's management client receives the client Id, client secret and token endpoint URL used to generate a bearer token. 13 | - The device's management client receives the URL for the Git repository containing its desired state and an associated access token for authentication 14 | - The [device capabilities](./device-capability-reporting.md) information is sent from the device to the workload orchestration web service using the [Device API](../../margo-api-reference/workload-api/device-api/device-capabilities.md) 15 | 16 | ![Margo Management Interface Operational Flow Diagram (svg)](../../figures/margo-interface-generic.drawio.svg) 17 | > Action: FIDO Device onboarding has not been finalized as the standard onboarding solution. Further discussion/investigations are needed. 18 | 19 | ### Configuring the Workload Fleet Management Web Service URL 20 | 21 | > Action: Ideally this URL is discoverable instead of having to manually enter it but we still need to determine if there is a good way to make this discoverable by using something like the FDO Rendezvous service or multicast DNS. Also, once we determine how the Margo compliant device onboarding and fleet management is going to work it will probably impact this. 22 | 23 | To ensure the management client is configured to communicate with the correct Workload Fleet Management web service, the device's management client needs to be configured with the expected URL. The device vendor MUST provide a way for the end user to manually set the URL the device's management client uses to communicate with the workload orchestration solution chosen by the end user. 24 | 25 | ### Margo Web API Authentication Method 26 | 27 | The Margo Web API communication pattern between the device's management client and the workload orchestration web service must use a secure communication channel. In order to facilitate this secure communication Margo requires the use of oAuth 2.0 for authentication. 28 | 29 | #### API Authorization Strategy 30 | 31 | - During the [onboarding process](../../margo-api-reference/workload-api/onboarding-api/device-onboarding.md) the Workload Fleet Management's web service provides the management client with a client Id, client secret and token endpoint URL 32 | - The management client uses this information to [create a bearer token ](../../margo-api-reference/margo-api-specification.md#authorization-header)for each request 33 | - The bearer token is set in the `Authorization` header for each web request sent to the Workload Fleet Management's web service requiring authorization. 34 | 35 | #### Payload Security Method 36 | 37 | > Action: Certificate Rotation / Unique Identifier for device are still research areas needed. 38 | 39 | Because of limitations using mTLS with common OT infrastructure such as TLS terminating HTTPS load-balancer or a HTTPS proxy doing lawful inspection Margo has adopted a certificate-based payload signing approach to protect payloads from being tampered with. By utilizing the certificates to create payload envelopes, the device's management client can ensure secure transport between the device's management client and the Workload Fleet Management's web service. 40 | 41 | - During the onboarding process the end user uploads the device's x.509 certificate to the workload orchestration solution 42 | - The device's management client downloads the root CA certificate using the [Onboarding API](../../margo-api-reference/workload-api/onboarding-api/rootca-download.md) 43 | - Once this is complete, both parties are able to [secure their payloads](../../margo-api-reference/margo-api-specification.md#signing-payloads). 44 | 45 | ##### Details pertaining to the message Envelope: 46 | 47 | Once the edge device has a message prepared for the Workload Fleet Management's web service, it completes the following to secure the message. 48 | 49 | - The device's management client calculates a digest and signature of the payload 50 | - The device's management client adds an envelope around it that has: 51 | - actual payload 52 | - SHA of the payload, signed by the device certificate 53 | - Identifier for the certificate that corresponds to the private key used to sign it. 54 | - This identifier MUST be the GUID provided by the device manufacturer. Typically the hardware serial number. 55 | - The envelope is sent as the payload to the Workload Fleet Management's web service. 56 | - The Workload Fleet Management's web service treats the request's payload as envelope structure, and receives the certificate identifier. 57 | > Note: This certificate is the device certificate that was manually uploaded to the workload orchestration solution during onboarding. 58 | - The Workload Fleet Management's web service computes digest from the payload, and verifies the signature using the device certification. 59 | - The payload is then processed by the Workload Fleet Management's web service. 60 | 61 | 62 | ### GitOps Service Enrollment 63 | 64 | > Action: The Margo TWG is currently reviewing alternatives to GitOps. This page will be updated upon a finalization of a new strategy. 65 | 66 | #### Authorization methods for the Desired State Git Repository 67 | 68 | - Git access tokens shall be provided to the device's management client. These access tokens MUST be tied to a dedicated non-user account for access where credentials are frequently rotated and short lived. 69 | - Need to support accessing rotations of tokens 70 | -------------------------------------------------------------------------------- /system-design/how-to-contribute/contribution-navigation.md: -------------------------------------------------------------------------------- 1 | # Technical Working Group(TWG) Details 2 | 3 | ## Charter Agreement 4 | - **Working Group Scope** 5 | - Fulfill the project technical oversight to achieve edge-based interoperability across automation vendors, system integrators and platform providers. The intended result will allow edge devices, apps, and orchestration software, sourced from multiple suppliers to be interoperable in heterogenous industrial ecosystems. The working group is responsible to develop and maintain an open-source reference implementation, define and maintain associated open interoperability standards, develop and maintain a compliance framework, process and tooling. Activities also would include education and training for adopters. 6 | - **Copyright Licensing** - Open Web Foundation 0.9. 7 | - **Patent Licensing** - Open Web Foundation Agreement 0.9 Mode. 8 | - **Source Code** - MIT License, available at https://opensource.org/licenses/MIT. 9 | 10 | ## Technical Working Group Repository(TWG) 11 | Repository for Technical Working Group collaboration. 12 | 13 | - Location to view the meeting agenda and minutes for technical working sessions. 14 | - These are auto generated as an issue within this repository every week per focus group. Focus group leads should edit the agenda post auto creation to inform attendees of topics to be discussed. 15 | - Meeting minutes are attached to the Meeting agenda MDs then the issue is closed for record keeping. 16 | - General Information regarding the current Focus groups and planned focus groups for the Margo Release 1 System Design. 17 | 18 | [**Link to Repository**](https://github.com/margo/technical-wg) 19 | 20 | 21 | 22 | ## Current Technical Focus Group(FG) Details 23 | Below are details regarding the current focus groups, leads, meeting information, associated Github Project, and associated markdowns within the specification repository. 24 | 25 | ### FG: Workload Fleet Management API 26 | - Focus Group Lead 27 | - Armand Craig(ajcraig@rockwellautomation.com) 28 | * Focus Group Meeting Details 29 | - Tuesdays, 2pm CET 30 | - Associated Github Project to track activites 31 | - [Link to Project](https://github.com/orgs/margo/projects/3) 32 | ### FG: Application Package definitions 33 | - Focus Group Lead 34 | - Arne Broering(arne.broering@siemens.com) 35 | - Focus Group Meeting Details 36 | - Wednesdays, 2PM CET 37 | - Associated Github Project to track activites 38 | - [Link to Project](https://github.com/orgs/margo/projects/5) 39 | ### FG: Device Requirements (Meetings Currently Paused) 40 | - Focus Group Lead 41 | - Merrill Harriman(merrill.harriman@se.com) 42 | - Focus Group Meeting Details 43 | - Paused 44 | - Associated Github Project to track activites 45 | - [Link to Project](https://github.com/orgs/margo/projects/6) 46 | ### FG: Observability requirements (Meetings Currently Paused) 47 | - Focus Group Lead 48 | - Philip Presson(philip.presson@us.abb.com) 49 | - Focus Group Meeting Details 50 | - Paused 51 | - Associated Github Project to track activites 52 | - [Link to Project](https://github.com/orgs/margo/projects/4) 53 | 54 | 55 | ## Future Planned Focus Group Details 56 | Note: We are looking for volunteers/contributers within these focus groups. 57 | 58 | ### FG: System Security 59 | - Short Description: This focus group will be responsible for maintaining security standards throughout the focus group. Both security requirements 60 | - Notes: 61 | - This working group is in the process of being constructed. 62 | - Current discussions can be found in the following [Issue](https://github.com/margo/specification/issues/65) 63 | ### FG: Device Fleet Management Interface 64 | - Short Description: This is intended to descibe the functionality of the management interface between Device Fleet Management Suppliers and Device Suppliers. 65 | - Notes: 66 | - This focus group's scope is under discussion in the following location. 67 | - [Issue](https://github.com/margo/specification/issues/50) 68 | ### FG: Device Update Definition 69 | - Short Description: This is intended to describe the device update definition within Margo. 70 | - Notes: 71 | - This focus group's scope is under discussion in the following location. 72 | - [Issue](https://github.com/margo/specification/issues/49) 73 | ### FG: Device Observability 74 | - Short Description: This is intended to describe the device observability functionality within Margo. 75 | - Notes: 76 | - This focus group's scope is under discussion in the following location. 77 | - [Issue](https://github.com/margo/specification/issues/51) 78 | ### FG: Device Onboarding 79 | - Short Description: This is intended to describe the device onboarding functionality within Margo. 80 | - Notes: 81 | - This focus group's scope is under discussion in the following location. 82 | - [Issue](https://github.com/margo/specification/issues/52) 83 | ### FG: Policy Agent 84 | - Short Description: This focus group is related to the Policy Agent that exists within the Margo Compliant Devices. 85 | ### FG: Test and Compliance Suite 86 | - Short Description: This focus group is intended to tackle and plan the test and compliance suite that will be utilized by product vendors to ensure compliance with the Margo Specification 87 | ### FG: Official Reference Implementation 88 | - Short Description: This focus group is intended to work on the official reference implementation. 89 | -------------------------------------------------------------------------------- /system-design/index.md: -------------------------------------------------------------------------------- 1 | # What is Margo? 2 | 3 | ![(Margo )](./figures/margo-logo.svg) 4 | 5 | The Margo initiative is an open collaboration between like-minded organizations and individuals, sharing a common vision: deliver edge interoperability for industrial automation ecosystems. Margo is hosted by the Linux Foundation. 6 | 7 | Find out more about the Margo initiative and how to become engaged at [margo.org](https://www.margo.org/). 8 | 9 | > **Disclaimer** 10 | 11 | This is a commit *snapshot* rendering of the of work-in-progress Margo Specification draft from the repository [=@=reponame=@=](https://github.com/=@=reponame=@=), commit `=@=commit=@=`. 12 | 13 | Do not attempt to implement this version of the Specification or reference this version as authoritative in any way! 14 | 15 | ## Mission Statement 16 | 17 | Margo’s mission emphasizes unlocking innovation barriers in industrial automation through edge interoperability. This is achieved through creation of a reference implementation, open standard, and compliance testing toolkit to facilitate the interoperable orchestration of edge applications and devices. The Margo initiative aims to accelerate digital transformation by simplifying the deployment, scalability, and operation of industrial solutions, thereby enabling organizations to innovate and grow more efficiently. 18 | 19 | Read more about Margo's [Mission Statement](https://margo.org/about/who-are-we/#mission) on our website. 20 | 21 | ## Addressing Industrial Edge Pain Points 22 | 23 | Because of recent trends in industrial manufacturing, lifecycle management is becoming a challenge because of the massive increase of compute devices and apps from a multitude of suppliers deployed in plants. Margo intends to reduce the complexity of maintaining and operating such an infrastructure at scale in a multi-vendor environment. 24 | 25 | Read more about how Margo is [addressing industrial edge pain points](https://margo.org/about/who-are-we/#industrial-edge) on our website. 26 | 27 | ## Applying an Open Approach 28 | 29 | While Margo intends to address innovation barriers, this cannot be done without widespread collaboration and interaction with peer communities. 30 | 31 | Read about Margo's [open approach](https://margo.org/about/who-are-we/#open-approach) on our web site. 32 | 33 | ## An Edge Interoperability User Story 34 | 35 | Interoperability is a challenge with multiple facets and personas. In order to stay focused on solving the market’s pain points, Margo’s contributors use a persona based user story as the tangible guideline for the collaboration. 36 | 37 | Read about Margo's [edge interoperability user story](https://margo.org/about/who-are-we/#interoperability) on our web site. 38 | 39 | ## Delivering the Interoperability Promise 40 | 41 | Margo relies on a few principles in tackling the interoperability challenge and simplifying the process of building, deploying, scaling, and operating complex, multi-vendor edge environments for organizations of all sizes. 42 | 43 | Read about Margo's plans to [deliver on the interoperability promise](https://margo.org/about/who-are-we/#promise) on our web site. 44 | 45 | ## Margo Deliverables 46 | 47 | The core deliverables for Margo address the mission to enable interoperability at scale: 48 | 49 | - Reference Implementation 50 | - Open Standard 51 | - Open Compliance Test Suite 52 | 53 | Read more about [Margo's deliverables](https://margo.org/about/who-are-we/#deliverables) on our web site. 54 | 55 | ## License 56 | 57 | =@=copyright=@= 58 | 59 | See [License](https://github.com/margo/specification?#licenses). 60 | -------------------------------------------------------------------------------- /system-design/margo-api-reference/margo-api-specification.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The Margo Management API is used to enable communication between Margo compliant devices and orchestration solutions. 4 | 5 | Links below provide further detail regarding the API definition: 6 | 7 | - [Desired State](./workload-api/desired-state-api/desired-state.md) 8 | - [Device Capabilities](./workload-api/device-api/device-capabilities.md) 9 | - [Deployment Status](./workload-api/device-api/deployment-status.md) 10 | - [RootCA Download](./workload-api/onboarding-api/rootca-download.md) 11 | 12 | ## Authorization and Security Details 13 | 14 | ### Authorization Header 15 | For requests requiring authentication a bearer token MUST be present in the message's `Authorization` header. 16 | 17 | You can get the access token by sending a request to the workload orchestration web service's token URL, providing the device's client Id and secret. 18 | 19 | ```bash 20 | curl -X POST \ 21 | -H "Content-Type: application/x-www-form-urlencoded" \ 22 | -d "grant_type=client_credentials&client_id=&client_secret=" \ 23 | 24 | ``` 25 | The request's response indicates the access token to use for subsequent requests. 26 | 27 | ```json 28 | { 29 | "access_token": "ACCESS_TOKEN", 30 | "token_type": "Bearer", 31 | "expires_in": 3600 32 | } 33 | ``` 34 | 35 | Set the `Authorization` headers value to `Bearer ` When making request requiring authorization. For example: 36 | 37 | ```bash 38 | curl -H "Authorization: Bearer ACCESS_TOKEN" https://wos.example.com/device/2fc3d8e9-8c56-4270-b7d3-8ed30262e5e1 39 | ``` 40 | 41 | 42 | ### Signing Payloads 43 | 44 | The following steps are used to sign a payload 45 | 46 | 1. Generate a SHA-256 hash value for the request's body 47 | 2. Create a digital signature by using the message source certificates's private key to encrypt the the hash value 48 | 3. Base-64 encode the certificate's public key and the digital signature in the format of `;` 49 | 3. Include the base-64 encoded string in the request's `X-Payload-Signature` header 50 | 51 | ### Verifying Signed Payloads 52 | 53 | The following steps are used to verify signed payloads 54 | 55 | 1. Retrieve the public key from the `X-Payload-Signature` header 56 | 2. Decrypt the digital signature using the public key to get the original hash value 57 | 3. Generate a SHA-256 hash value for the requests's body 58 | 4. Ensure the generated hash value matches the hash value from the message 59 | 60 | -------------------------------------------------------------------------------- /system-design/margo-api-reference/workload-api/desired-state-api/.gitignore: -------------------------------------------------------------------------------- 1 | docs 2 | desired-state.md 3 | -------------------------------------------------------------------------------- /system-design/margo-api-reference/workload-api/desired-state-api/.gittree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margo/specification/1d11d11334613a71843db9e68b73272ac036dd66/system-design/margo-api-reference/workload-api/desired-state-api/.gittree -------------------------------------------------------------------------------- /system-design/margo-api-reference/workload-api/device-api/deployment-status.md: -------------------------------------------------------------------------------- 1 | # Deployment Status 2 | 3 | While applying a new desired state the device's management client MUST provide the workload orchestration web service with an indication of the current status. This is done calling the Device API's `device status` endpoint. 4 | 5 | ### Route and HTTP Methods 6 | 7 | ```http 8 | POST /device/{deviceId}/deployment/{deploymentId}/status 9 | ``` 10 | 11 | ### Route Parameters 12 | 13 | |Parameter | Type | Required? | Description| 14 | |----------|------|-----------|------------| 15 | | {deviceId} | string | Y | The device's Id registered with the workload orchestration solution during onboarding.| 16 | | {deploymentId} | string | Y | The deployment Id the status is being reported for | 17 | 18 | ### Request Body Fields 19 | 20 | > Action: Need to figure out the options for error code and message. Are these to be free form? 21 | 22 | | Fields | Type | Required? | Description | 23 | |-----------------|-----------------|-----------------|-----------------| 24 | | apiVersion | string | Y | Identifier of the version of the API the object definition follows.| 25 | | kind | string | Y | Must be `DeploymentStatus`.| 26 | | deploymentId | string | Y | The unique identifier UUID of the deployment specification. Needs to be assigned by the Workload Orchestration Software. | 27 | | status | []status | Y | Element that defines overall deployment status. See the [Status Fields](#status-fields) section below.| 28 | | components | []components | Y | Element that defines the individual component's deployment status. See the [Component Fields](#component-fields) section below.| 29 | 30 | #### Status Fields 31 | 32 | | Fields | Type | Required? | Description | 33 | |-----------------|-----------------|-----------------|-----------------| 34 | | state | string | Y | Current state of the overall deployment. The state value MUST be one the following options: Pending, Installing, Installed, Failed. The overall deployment status MUST inherit the current component's status until it has gone through installing each component.| 35 | | error | Error | N | Element that defines the overall installation error if one occured. See the [Error Fields](#error-fields) section below.| 36 | 37 | #### Component Fields 38 | 39 | | Attribute | Type | Required? | Description | 40 | |-----------------|-----------------|-----------------|-----------------| 41 | | name | string | Y | Name of the deployment component, inherited via the deployment specification | 42 | | state | string | Y | The component's current deployment state of the component. MUST be one of the following options: Pending, Installing, Installed, Failed | 43 | | error | Error | N | Element that defines the components installation error if one occured. See the [Error Fields](#error-fields) section below. | 44 | 45 | #### Error Fields 46 | 47 | | Fields | Type | Required? | Description | 48 | |-----------------|-----------------|-----------------|-----------------| 49 | | code | string | Y | Associated error code following a component failure during installation. | 50 | | message | string | Y | Associated error message that provides further details to the WOS about the error that was encountered. | 51 | 52 | ### Example Request 53 | 54 | ```json 55 | { 56 | "apiVersion": "deployment.margo/v1", 57 | "kind": "DeploymentStatus", 58 | "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", 59 | "status": { 60 | "state": "pending", 61 | "error": { 62 | "code": "", 63 | "message": "" 64 | } 65 | }, 66 | "components": [ 67 | { 68 | "name": "digitron-orchestrator", 69 | "state": "pending", 70 | "error": { 71 | "code":"", 72 | "message":"" 73 | } 74 | }, 75 | { 76 | "name": "database-services", 77 | "state": "pending", 78 | "error": { 79 | "code": "", 80 | "message ": "" 81 | } 82 | } 83 | ] 84 | } 85 | ``` 86 | 87 | ### Response Code 88 | 89 | | Code | Description | 90 | |------|-------------| 91 | | 201 | The deployment status was added, or updated, successfully | 92 | | 4XX-5XX | The requests was not completed sucessfully | 93 | -------------------------------------------------------------------------------- /system-design/margo-api-reference/workload-api/device-api/device-capabilities.md: -------------------------------------------------------------------------------- 1 | # Device Capabilities 2 | 3 | Devices MUST provide the workload orchestration service with its capabilities and characteristics. This is done by calling the Device API's `device capabilities` endpoint. 4 | 5 | ### Route and HTTP Methods 6 | 7 | ```http 8 | POST /device/{deviceId}/capabilities 9 | PUT /device/{deviceId}/capabilities 10 | ``` 11 | 12 | ### Route Parameters 13 | 14 | |Parameter | Type | Required? | Description| 15 | |----------|------|-----------|------------| 16 | | {deviceId} | string | Y | The device's Id registered with the workload orchestration web service during onboarding.| 17 | 18 | ### Request Body Fields 19 | 20 | > Action: Discusssion still needed on "types" and "properties" per type that would be required. This is relevant for both the peripherals and interfaces section. 21 | 22 | | Field | Type | Required? | Description | 23 | |-----------------|-----------------|-----------------|-----------------| 24 | | apiVersion | string | Y | Identifier of the version of the API the object definition follows.| 25 | | kind | string | Y | Must be `DeviceCapabilities`.| 26 | | properties | Properties | Y | Element that defines characteristics about the device. See the [Properties Fields](#properties-fields) section below. | 27 | 28 | #### Properties Fields 29 | 30 | | Field | Type | Required? | Description | 31 | |-----------------|-----------------|-----------------|-----------------| 32 | | id | string | Y | Unique deviceID assigned to the device via the Device Owner.| 33 | | vendor | string | Y | Defines the device vendor.| 34 | | modelNumber | string | Y | Defines the model number of the device.| 35 | | serialNumber | string | Y | Defines the serial number of the device.| 36 | | roles | []string | Y | Element that defines the device role it can provide to the Margo environment. MUST be one of the following: Standalone Cluster, Cluster Leader, or Standalone Device | 37 | | resources | []Resource | Y | Element that defines the device's resources available to the application deployed on the device. See the [Resource Fields](#resources-fields) section below. | 38 | | peripherals | []Peripheral | Y | Element that defines the device's peripherals available to the application deployed on the device. See the [Peripheral Fields](#peripheral-fields) section below. | 39 | | interfaces | []Interface | Y | Element that defines the device's interfaces that are available to the application deployed on the device. See the [Interface Fields](#interface-fields) section below. | 40 | 41 | #### Resources Fields 42 | 43 | | Fields | Type | Required? | Description | 44 | |-----------------|-----------------|-----------------|-----------------| 45 | | cpus | []CPU | Y | Element that defines the device's CPUs that are available to the application deployed on the device. See the [CPU Fields](#cpu-fields) section below.| 46 | | memory | integer | Y | Defines the memory capacity available for applciations on the device. This MUST be defined in GBs| 47 | | storage | integer | Y | Defines the storage capacity available for applications to utilize. This MUST be defined in GBs.| 48 | 49 | #### CPU Fields 50 | 51 | | Fields | Type | Required? | Description | 52 | |-----------------|-----------------|-----------------|-----------------| 53 | | cpuArchitecture | string | Y | Defines the CPUs architecture. i.e. ARM/Intel x86.| 54 | | cores | integer | Y | Defines the cores available within the hosts CPU.| 55 | | frequency | integer | Y | Defines the frequency of the CPU. Must be defined in Ghz.| 56 | 57 | #### Peripheral Fields 58 | 59 | | Fields | Type | Required? | Description | 60 | |-----------------|-----------------|-----------------|-----------------| 61 | | name | string | Y | Name of the peripheral.| 62 | | type | string | Y | Type of the peripheral. i.e. GPU| 63 | | modelNumber | string | Y | Model number of the peripheral.| 64 | | properties | map[string]string | Y | Properties of the peripheral.| 65 | 66 | #### Interface Fields 67 | 68 | | Fields | Type | Required? | Description | 69 | |-----------------|-----------------|-----------------|-----------------| 70 | | name | string | Y | Name of the interface.| 71 | | type | string | Y | Type of the interface. i.e. Ethernet NIC, | 72 | | modelNumber | string | Y | Model number of the interface.| 73 | | properties | map[string]string | Y | Properties of the interface to inform the WOS with additional information.| 74 | 75 | ### Example Request 76 | 77 | ```json 78 | { 79 | "apiVersion": "device.margo/v1", 80 | "kind": "DeviceCapability", 81 | "properties": { 82 | "id": "northstarida.xtapro.k8s.edge", 83 | "vendor": "Northstar Industrial Applications", 84 | "modelNumber": "332ANZE1-N1", 85 | "serialNumber": "PF45343-AA", 86 | "roles": ["standalone cluster", "cluster lead"], 87 | "resources": { 88 | "memory": "64.0 GB", 89 | "storage": "2000 GB", 90 | "cpus": [{ 91 | "architecture": "Intel x64", 92 | "cores": 24, 93 | "frequency": "6.2 GHz" 94 | }] 95 | }, 96 | "peripherals": [{ 97 | "name": "NVIDIA GeForce RTX 4070 Ti SUPER OC Edition Graphics Card", 98 | "type": "GPU", 99 | "modelNumber": "TUF-RTX4070TIS-O16G", 100 | "properties": { 101 | "manufacturer": "NVIDIA", 102 | "series": "NVIDIA GeForce RTX 40 Series", 103 | "gpu": "GeForce RTX 4070 Ti SUPER", 104 | "ram": "16 GB", 105 | "clockSpeed": "2640 MHz" 106 | } 107 | }], 108 | "interfaces": [ 109 | { 110 | "name": "RTL8125 NIC 2.5G Gigabit LAN Network Card", 111 | "type": "Ethernet", 112 | "modelNumber": "RTL8125", 113 | "properties": { 114 | "maxSpeed": "2.5 Gbps" 115 | } 116 | }, 117 | { 118 | "name": "WiFi 6E Intel AX411NGW M.2 Cnvio2", 119 | "type": "Wi-Fi", 120 | "modelNumber": "AX411NGW", 121 | "properties": { 122 | "bands": ["2.4 GHz", "5 GHz", "6GHz"], 123 | "maxSpeed": "2.4 Gbps" 124 | } 125 | }] 126 | } 127 | } 128 | ``` 129 | 130 | ### Response Code 131 | 132 | | Code | Description | 133 | |------|-------------| 134 | | 201 | The device capabilities document was added, or updated, successfully | 135 | | 4XX-5XX | The requests was not completed sucessfully | 136 | -------------------------------------------------------------------------------- /system-design/margo-api-reference/workload-api/onboarding-api/device-onboarding.md: -------------------------------------------------------------------------------- 1 | # Device Onboarding 2 | 3 | > Action: This API needs to be defined 4 | 5 | ### Route and HTTP Methods 6 | 7 | ```http 8 | POST /onboarding/ 9 | ``` 10 | ### Request Body 11 | 12 | TBD 13 | 14 | ### Response Body 15 | 16 | TBD 17 | -------------------------------------------------------------------------------- /system-design/margo-api-reference/workload-api/onboarding-api/rootca-download.md: -------------------------------------------------------------------------------- 1 | # Certificate API 2 | 3 | In order to facilitate secure communication between the device's management client and workload orchestration web service the workload orchestration web service's root CA certificate must be downloaded using the Onboarding API's `certificate` endpoint. 4 | 5 | ### Route and HTTP Methods 6 | 7 | ```http 8 | GET /onboarding/certificate 9 | ``` 10 | 11 | ### Response Body 12 | 13 | ```json 14 | { 15 | "certificate":"" 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /system-design/margo-overview/application-package-overview.md: -------------------------------------------------------------------------------- 1 | # Workloads 2 | 3 | A [workload](./technical-lexicon.md#workload) is software deployed to, and run on, Margo compliant [edge compute devices](./technical-lexicon.md#edge-compute-device). 4 | 5 | In order to help achieve Margo's interoperability [mission statement](../index.md#mission-statement) we are initially targeting [containerized](https://github.com/opencontainers) workloads capable of running on platforms like Kubernetes, Docker and Podman. The flexibility these platforms provide enables [workload suppliers](personas.md#workload-supplier) to define and package their workloads in a common way using [Helm](https://helm.sh/docs/) or the [Compose specification](https://github.com/compose-spec/compose-spec/blob/main/spec.md) so they can more easily be deployed to multiple compatible edge compute devices. 6 | 7 | While Margo is initially targeting deployments using Helm or Compose, we plan to support other deployment types in the future. One of our design goals is to make it easier for [workload fleet managers](./technical-lexicon.md#workload-fleet-manager) to support the current and future deployment types without having to implement special logic for each type. In order to achieve this, Margo defines an [application description model](../app-interoperability/application-package-definition.md) to abstract away some of the details to make it easier for workload fleet managers to support the different deployment types. 8 | 9 | The three main goals of Margo's application description model is to allow workload fleet managers to do the following: 10 | 11 | - Display information about the workloads the [OT user](personas.md#ot-user) can deploy (e.g., a [workload catalog](./technical-lexicon.md#workload-catalog)). 12 | - Determine which edge compute devices are compatible with the workloads (e.g., processor types match, GPU present, etc.) 13 | - Capture, and validate, configuration information from the OT user when deploying and updating workloads. 14 | 15 | Another advantage of Margo's [application description model](../app-interoperability/application-package-definition.md) is to enable workload suppliers to define different deployment profiles in a single application description file to target deploying to different types of edge compute devices (e.g., Arm vs. x86, Kubernetes vs. Docker) instead of needing to maintain multiple application description files. 16 | 17 | ## Packaging 18 | 19 | To distribute one, or more, workloads they are wrapped in an [application package](../app-interoperability/application-package-definition.md) that is provided by the workload supplier who aims to provide it to Margo-compliant edge compute devices. Therefore, the workload supplier creates an application description YAML document containing information about the application and a reference on how to deploy the [OCI-containerized](https://github.com/opencontainers) workloads that make up the application. The application package is made available in an [application registry](../app-interoperability/workload-orch-to-app-reg-interaction.md) and the OCI artifacts are stored in a remote or [local registry](../app-interoperability/local-registries.md). 20 | 21 | ## Example workflow 22 | 23 | The following diagram provides an example workflow showing one way a workload fleet manager might use the application description information: 24 | 25 | ```mermaid 26 | --- 27 | config: 28 | layout: elk 29 | 30 | 31 | --- 32 | sequenceDiagram 33 | actor EndUser as End User 34 | participant frontend as Workload Fleet Manager Frontend 35 | participant fleetmgr as Workload Fleet Manager 36 | participant registry as Application Registry 37 | 38 | autonumber 39 | 40 | EndUser->>frontend: Visits Application Catalog 41 | frontend->>fleetmgr: Get list of available workloads (=Apps) 42 | 43 | alt 44 | fleetmgr ->> registry: Get 'application description' from each known application registry. 45 | else 46 | fleetmgr ->> fleetmgr: Get 'application description' for all cached applications. 47 | end 48 | fleetmgr->>frontend: Return list of 'application description's 49 | 50 | frontend ->> frontend: Read all 'application description's -> 'metadata' element 51 | frontend ->> EndUser: Show UI with list of applications 52 | EndUser->>frontend: Select workload (=App) to install 53 | frontend ->> frontend: Read 'application description' -> 'configuration' element 54 | frontend -->> EndUser: Show UI to fill App configuration 55 | EndUser ->> frontend: Answer configurable questions to be applied to workload(s) 56 | frontend ->> fleetmgr: Create 'ApplicationDeployment' definition 57 | 58 | ``` 59 | 60 | 1. An end user visits an [workload catalog](./technical-lexicon.md#workload-catalog) of the Workload Fleet Manager Frontend. 61 | 2. This frontend requests all workloads from the Workload Fleet Manager. 62 | 3. _Either_: the Workload Fleet Manager requests all application descriptions from each known Application Registry. 63 | 4. _Or_: the Workload Fleet Manager maintains a cache of application descriptions and services the request from there. 64 | 5. The Workload Fleet Manager returns the retrieved documents of application descriptions to the frontend. 65 | 6. The frontend parses the [metadata](../margo-api-reference/workload-api/application-package-api/application-description.md#metadata-attributes) element of all received application description documents. 66 | 7. The frontend presents the parsed metadata in a UI to the end user. 67 | 8. The end user selects the workload to be installed. 68 | 9. The frontend parses the [configuration](../margo-api-reference/workload-api/application-package-api/application-description.md#configuration-attributes) element of the selected application description. 69 | 10. The frontend presents the parsed configuration to the user. 70 | 11. The end user fills out the [configurable application parameters](../margo-api-reference/workload-api/application-package-api/application-description.md#defining-configurable-application-parameters) to be applied to the workload. 71 | 12. The frontend creates an `ApplicationDeployment` definition (from the `ApplicationDescription` and the filled out parameters) and sends it to the Workload Fleet Manager, which executes it as the [desired state](../margo-api-reference/workload-api/desired-state-api/desired-state.md). 72 | 73 | ## Relevant Links 74 | 75 | Please follow the subsequent links to view more technical information regarding Margo application packaging: 76 | 77 | - [Application Package Definition](../app-interoperability/application-package-definition.md) 78 | - [Application Registry](../app-interoperability/workload-orch-to-app-reg-interaction.md) 79 | -------------------------------------------------------------------------------- /system-design/margo-overview/devices-overview.md: -------------------------------------------------------------------------------- 1 | # Edge Compute Devices 2 | 3 | Within Margo, devices are represented by compute hardware that host Margo compliant workloads within the customers environment. Devices are defined by the roles they can provide the Margo ecosystem. Each role has it's own requirements which enable unique functionality such as cluster management. These Margo device ensure the Workload Developers with guaranteed functionality they can depend on being present in every compliant device. These devices are onboarded and managed by a single Workload Fleet Manager. 4 | 5 | The promise the Margo specification provides Device vendors the following benefits: 6 | 7 | - By producing a Margo compliant device it is compatible with ALL Margo compliant Fleet Managers 8 | - Device vendors have freedom of implementation regarding the specific components, i.e. oci container runtime, as long as the component provides the agreed upon functionality the Application Vendors expect. 9 | 10 | Supported Device roles are shown below: 11 | 12 | - Standalone Cluster 13 | - Cluster Leader 14 | - Cluster Worker 15 | - Standalone Device 16 | 17 | > Note: Additional device roles will be introduced as the specification matures. 18 | 19 | ## Margo Device layers 20 | 21 | Margo device roles consist of three major layers: Margo interface layer, platform layer, traditional device layer. Although Margo requires compliance towards it's requirements, such as hosting the Margo management interface client, the device vendor has freedom to implement as they see fit. 22 | 23 | Below is a diagram that depicts the device layers along with some examples: 24 | 25 | ![Device Layer Drawing)](../figures/device-layers.drawio.svg) 26 | 27 | ## Relevant Links 28 | 29 | Please follow the subsequent links to view more technical information regarding Margo compliant devices: 30 | 31 | - [Device Requirements](../device-interoperability/device-requirements.md) 32 | - [Collecting Application Observability Data](../device-interoperability/collecting-workload-observability-data.md) -------------------------------------------------------------------------------- /system-design/margo-overview/introduction-system-design.md: -------------------------------------------------------------------------------- 1 | # Envisioned System Design 2 | 3 | Margo intends to create an open [interoperability](./technical-lexicon.md#interoperability) standard and ecosystem for the industrial edge, allowing [edge compute devices](./technical-lexicon.md#edge-compute-device), [workloads](./technical-lexicon.md#workload), and [fleet management](./technical-lexicon.md#fleet-management-concepts) software to be compatible and interoperable across manufacturers and software developers willing to adopt such standard. 4 | 5 | ## Overview 6 | 7 | ![System Design Drawing)](../figures/System-design.drawio.svg) 8 | 9 | The envisioned system can be broken down into the following main components: 10 | 11 | ### Workloads 12 | 13 | Workloads are the software deployed to Margo-compliant edge compute devices. See the [workloads overview](./application-package-overview.md) page to learn more Margo's supported workloads and how the are packaged. 14 | 15 | ### Workload Observability 16 | 17 | For distributed systems its vitally important to collect diagnostics information about the workloads and systems running within the environment. See the [workload observability overview](./workload-observability-overview.md) page to see how Margo is making use of the Open Telemetry specification to capture this information. 18 | 19 | ### Workload Fleet Management 20 | 21 | Workload fleet management software is the centralized software solution for managing the lifecycle of workloads on Margo compliant edge compute devices. See the [workload fleet management](./workload-management-interface-overview.md) page to learn more more. 22 | 23 | ### Edge compute devices 24 | 25 | Edge compute devices are the compute surfaces workloads are deployed to and run on. As part of the Margo initiative we are very prescriptive about how a edge compute devices must be configured to make it Margo compliant. See the [edge compute device overview](./devices-overview.md) page to learn more. 26 | 27 | 28 | -------------------------------------------------------------------------------- /system-design/margo-overview/personas-extended.md: -------------------------------------------------------------------------------- 1 | # Persona Examples 2 | 3 | ## Multiple Personas per Entity 4 | 5 | In some cases, a single entity, such as a company or organization, may provide multiple roles within the Margo enabled ecosystem. Below are a few examples of this with some visualizations. 6 | 7 | ### Combination of Device Supplier and Platform Supplier 8 | 9 | A supplier may be both the device supplier (the underlying hardware) and the platform provider, selling a "ready to deploy" offering for consumption by end users: 10 | 11 | ![(Multiple Personas - Device Supplier and Platform Supplier)](../figures/multiple-personas-device-platform.drawio.svg) 12 | 13 | > Note: 14 | > 15 | > This diagram is a subset of the diagram above, with modifications for the combined personas of device supplier and platform supplier 16 | 17 | ### Combination of Workload Supplier and OT User 18 | 19 | A persona in the end user category, such as an OT user, could also internally develop an application, and leverage the Margo specification to ease deployment to devices in their environment: 20 | 21 | ![Multiple Personas - OT User and Workload Supplier](../figures/multiple-personas-ot-user-workload.drawio.svg) 22 | 23 | > Note: 24 | > 25 | > This diagram is a subset of the diagram above, with modifications for the combined personas of OT user and workload supplier 26 | 27 | ## Notes 28 | 29 | - Other personas to be added as requested or required -------------------------------------------------------------------------------- /system-design/margo-overview/personas.md: -------------------------------------------------------------------------------- 1 | # Personas 2 | 3 | Throughout this documentation, the following personas are used to represent interaction with the standard and/or with entities defined by the standard. 4 | 5 | ## Persona Relationships 6 | ![Persona Relationships](../figures/persona-relationship.drawio.svg) 7 | 8 | ## Categories 9 | 10 | These categories group common personas together under a shared goal or role. These categories will be used in other documentation to provide grouping and clarity where appropriate. 11 | 12 | ### End Users 13 | - Evaluates the best-in-class products offered by the suppliers 14 | - Consumes products provided by the suppliers 15 | - Assembles multiple vendor's products into a productive automation system 16 | 17 | ### Suppliers 18 | - Contribute knowledge and expertise to the specification sections relevant to their business. 19 | - Builds products compliant with the Margo specification. 20 | - Markets and sells their products to end users 21 | 22 | ## Persona Definitions 23 | 24 | These persona definitions represent individual entities with specified use cases and requirements, aligned with the other personas in their category. 25 | 26 | ### End Users 27 | 28 | End users consume products and technologies that adopt the specification to deliver desired business outcomes. 29 | 30 | #### OT User 31 | 32 | Consumer of functionality provided by the application vendors to run critical and non-critical business functions, or to improve business efficiency 33 | 34 | #### OT Architect 35 | 36 | Creates and enforces standards across OT deployment locations or sites for greater supportability and consistency 37 | 38 | #### Integrator 39 | 40 | Optional persona, external to the organization of the other end user personas, but tasked with assembling and installing hardware and software provided by the suppliers 41 | 42 | #### IT Service Provider 43 | 44 | Provides "IT-like" services, such as connectivity, backup and restore, automation, security and auditing, within the End User's OT environment. 45 | 46 | ### Suppliers 47 | 48 | Suppliers provides hardware or software that's evaluated and deployed by the end users 49 | 50 | #### Workload Supplier 51 | 52 | Provides an application that performs some desired function, such as computer vision, software-defined control, etc, which is deployed to device via a Workload Fleet Manager 53 | 54 | #### Fleet Management Supplier 55 | 56 | Provides a software package that enables End Users to manage their workloads and/or devices the workloads run on via Fleet management patterns. 57 | 58 | #### Device Supplier 59 | 60 | Provides hardware resources, such as CPU and memory, along with lifecycle support, such as firmware and BIOS updates 61 | 62 | #### Platform Supplier 63 | 64 | Provides operating system level software to abstract hardware resources, and optionally, container orchestration software on top of the the operating system layer -------------------------------------------------------------------------------- /system-design/margo-overview/technical-lexicon.md: -------------------------------------------------------------------------------- 1 | # Technical Lexicon 2 | 3 | Below are concepts and terms utilized throughout the Margo Specification along with their associated description/definition. 4 | 5 | ## Concepts 6 | 7 | #### Interoperability 8 | 9 | Interoperability is an overloaded term that has different meanings depending on the context. For Margo, interoperability is about achieving the following: 10 | 11 | - Defining a common approach for packaging [Components](#component) so they can be deployed as [Workloads](#workload) to any compatible Margo-compliant [Edge Compute Devices](#edge-compute-device) via any Margo-compliant [Workload Fleet Manager](#workload-fleet-manager). 12 | - Defining a common approach for packaging device software and firmware updates so they can be deployed to any Margo-compliant [Edge Compute Devices](#edge-compute-device) via any Margo-compliant [Device Fleet Manager](#device-fleet-manager). 13 | - Defining a common API to enable communication between any Margo-compliant [Edge Compute Devices](#edge-compute-device) and any Margo-compliant [fleet management](#fleet-management) software. 14 | - Defining a common approach for collecting and transmitting diagnostics and observability data from a Margo-compliant [Edge Compute Device](#edge-compute-device) 15 | 16 | #### Orchestration 17 | 18 | Orchestration is an overloaded term that has different meanings depending on the context. For Margo, orchestration is about the deployment of [Workloads](#workload) and device software updates to Margo-compliant [Edge Compute Devices](#edge-compute-device) via Margo-compliant [fleet management](#fleet-management) software. Margo depends on container orchestration platforms such as Kubernetes, Docker and Podman existing on the [Edge Compute Devices](#edge-compute-device) and is not an attempt to duplicate what these platforms provide. 19 | 20 | #### Fleet Management 21 | 22 | Fleet Management represents a concept or pattern that enables users to manage one to many set of [workloads](#workload) and devices the customer owns. Many strategies exist within fleet management such as canary deployments, rolling deployments, and many others. Below are two fleet management concepts that have been adopted by Margo. 23 | 24 | ##### State Seeking 25 | 26 | The state seeking methodology, adopted via Margo, is enabled first by the [Workload Fleet Manager](#workload-fleet-manager) when it establishes the "Desired state". The [Edge Device](#edge-compute-device) then reconciles it's "Current state" with the "Desired state" provided by the Fleet Manager and reports the status. 27 | 28 | ##### Provider Model 29 | 30 | The provider model within Margo describes a service that is able to orchestrate or implement the desired state within the [Edge Device](#edge-compute-device). 31 | Current providers supported: 32 | 33 | - Helm Client 34 | - Compose Client 35 | 36 | ## Technical Terms 37 | 38 | #### Application 39 | 40 | An application is a collection of one, or more, [Components](#component), as defined by an Application Description, and bundled within an [application package](#application-package). 41 | 42 | #### Application Package 43 | 44 | An Application Package is used to distribute an [application](#application). 45 | According the [specification](../app-interoperability/application-package-definition.md), it is a folder in a Git repository referenced by URL, which contains the Application Description (that refers to contained and deployable Components) as well as associated resources (e.g., icons). 46 | 47 | #### Component 48 | 49 | A Component is a piece of software tailored to be deployed within a customer's environment on an [Edge Compute Device](#edge-compute-device). 50 | Currently Margo-supported components are: 51 | 52 | - Helm Chart 53 | - Compose Archive 54 | 55 | #### Workload 56 | 57 | A Workload is an instance of a [Component](#component) running within a customer's environment on a [Edge Compute Device](#edge-compute-device). 58 | 59 | #### Edge Compute Device 60 | 61 | Edge Compute Devices are represented by compute hardware that runs within the customer's environment to enable the system with Margo Compliant [Workloads](#workload). Edge Compute Devices host the Margo compliant management agents, container orchestration platform, and device operating systems. Margo Edge Compute Devices are defined by the roles they can facilitate within the Margo Architecture. 62 | Supported Device roles are shown below: 63 | 64 | - Standalone Cluster(Leader and/or Worker) 65 | - Cluster Worker 66 | - Standalone Device 67 | 68 | #### Workload Fleet Manager 69 | 70 | Workload Fleet Manager (WFM) represents a software offering that enables End Users to configure, deploy, and manage edge [Workloads](#workload) as a fleet on their registered [Edge Devices](#edge-compute-device). 71 | 72 | ##### Application Registry 73 | 74 | An Application Registry holds [Application](#application) Packages. 75 | It is used by developers to make their applications available. 76 | An Application Registries MUST be a Git repository. 77 | 78 | [Workload Fleet Managers](#workload-fleet-manager) cannot access Application Registries directly, they can only access [Application Catalogs](#application-catalog). 79 | 80 | ##### Application Catalog 81 | 82 | An Application Catalog holds Application Packages that were preselected to be install-ready for the edge environment of a [Workload Fleet Manager](#workload-fleet-manager) to deploy them to managed [Edge Compute Devices](#edge-compute-device). 83 | 84 | An Application Catalog obtains the offered [Applications](#application) from one or more [Application Registries](#application-registry). 85 | 86 | 87 | ##### Component Registry 88 | 89 | A Component Registry holds [Components](#component) (e.g., Helm Charts and Compose Archives) for Application Packages. 90 | When an application gets deployed through a [Workload Fleet Manager](#workload-fleet-manager), the components (linked within an Application Description) are requested from the Component Registry. 91 | 92 | This can be implemented, for example, as an OCI Registry. 93 | 94 | #### Workload Fleet Management Client 95 | 96 | The Workload Fleet Management Agent is a service that runs on the [Edge Compute Device](#edge-compute-device) which communicates with the [Workload Fleet Manager](#workload-fleet-manager) to receive [Components](#component) that will be instantiated as [Workloads](#workload) and configurations to be applied on the [Edge Compute Device](#edge-compute-device). 97 | 98 | #### Device Fleet Manager 99 | 100 | Device Fleet Manager (DFM) represents a software offering that enables End Users to onboard, delete, and maintain [Edge Compute Devices](#edge-compute-device) within the ecosystem. This software is utilized in conjunction with the [Workload Fleet Manager](#workload-fleet-manager) software to provide users with the features required to manage their [Edge Device](#edge-compute-device) along with [Workloads](#workload) running on them. 101 | 102 | #### Device Fleet Management Client 103 | 104 | The Device Fleet Management Agent is a service that runs on the [Edge Compute Device](#edge-compute-device) which communicates with the [Device Fleet Manager](#device-fleet-manager) to receive device configuration to be applied on the [Edge Compute Device](#edge-compute-device). 105 | 106 | #### Workload Marketplace 107 | 108 | Workload Marketplace is the location where end users purchase the rights to access [Workloads](#workload) from a vendor. 109 | 110 | Functional Requirements of the Workload Marketplace: 111 | 112 | - Provide users with a list of Workloads available for purchase 113 | - Enable users to purchase access rights to a Workload 114 | - Enable users with the meta data to access associated Workload Registries/Repositories 115 | 116 | > Note: The Workload Marketplace component is out of scope for Project Margo. However, it is necessary to define to clarify the full user workflow. 117 | -------------------------------------------------------------------------------- /system-design/margo-overview/workload-management-interface-overview.md: -------------------------------------------------------------------------------- 1 | # Workload Fleet Management 2 | 3 | Workload Management is a critical functionality that enables deployment and maintenance of workloads that are deployed to the customers edge to enable business goals. In order to achieve Margo's interoperability mission statement, the [Margo Management Interface](../margo-api-reference/margo-api-specification.md) is a critical component that enables interoperability between Workload Fleet Management Software vendors and Device Vendors. Interface hosting solutions are able to utilize the open implementation provided by the Margo community as is, or follow the specification to build their own compatible client/server components. 4 | 5 | The main goals of the management interface are as follows: 6 | 7 | - By hosting the server side of the interface, Workload Fleet Managers are enabled with the ability to onboard and manage workloads on all Margo compliant devices. 8 | - Device Vendors are able to build devices that include the client side of the interface which enables workload management via all Margo compliant fleet managers. 9 | 10 | ## Workload Deployment Sequence Diagram 11 | 12 | ```mermaid 13 | --- 14 | config: 15 | layout: elk 16 | 17 | 18 | --- 19 | sequenceDiagram 20 | actor EndUser 21 | participant WorkloadFleetManagerFrontEnd 22 | participant WorkloadManifestRepo 23 | participant WorkloadContainerRepo 24 | participant WorkloadFleetManager 25 | participant DeviceDeploymentspecificationRepo 26 | participant ContainerOrchestrator 27 | participant ContainerRuntime 28 | participant WorkloadFleetManagementClient 29 | 30 | autonumber 31 | EndUser->>WorkloadFleetManagerFrontEnd: Visits App Catalog Page 32 | WorkloadFleetManagerFrontEnd->>WorkloadFleetManager: Get list of available workloads 33 | activate WorkloadFleetManager 34 | WorkloadFleetManager->>WorkloadFleetManagerFrontEnd: Return 35 | deactivate WorkloadFleetManager 36 | EndUser->>WorkloadFleetManagerFrontEnd: Select workload to install 37 | WorkloadFleetManagerFrontEnd->>WorkloadFleetManager: Get list of devices 38 | activate WorkloadFleetManager 39 | WorkloadFleetManager-->>WorkloadFleetManager: Filter devices on capability match 40 | WorkloadFleetManager->>WorkloadFleetManagerFrontEnd: Return Compatible devices 41 | deactivate WorkloadFleetManager 42 | EndUser->>WorkloadFleetManagerFrontEnd: Select Device(s) to install application on 43 | EndUser->>WorkloadFleetManagerFrontEnd: Answer configurable questions to be applied to workload(s) 44 | WorkloadFleetManager-->>WorkloadFleetManager: Create & Store new deployment specification(s) 45 | activate WorkloadFleetManagementClient 46 | loop Continuous check for new deployment specifications 47 | WorkloadFleetManagementClient->>WorkloadFleetManager: Queries for new deployment spec(s) 48 | end 49 | WorkloadFleetManager->>WorkloadFleetManagementClient: Pulls deployment specification(s) 50 | WorkloadFleetManagementClient->>WorkloadManifestRepo: Pulls Workload Manifest(Helm) 51 | %% Need to include authentication to the app devs repository 52 | WorkloadFleetManagementClient->>ContainerOrchestrator: Provides Workload Manifest 53 | deactivate WorkloadFleetManagementClient 54 | loop 55 | ContainerOrchestrator->>ContainerRuntime: Initiates workload installation component 1 56 | ContainerOrchestrator->>ContainerRuntime: Initiates workload installation component 2 57 | ContainerOrchestrator->>ContainerRuntime: Initiates workload installation component n 58 | end 59 | ContainerRuntime->>WorkloadContainerRepo: Pulls OCI Containers 60 | activate WorkloadFleetManagementClient 61 | WorkloadFleetManagementClient->>WorkloadFleetManager: Provides Component Status Updates 62 | loop 63 | WorkloadFleetManagementClient->>WorkloadFleetManager: Component 1 Status update 64 | WorkloadFleetManagementClient->>WorkloadFleetManager: Component 2 Status update 65 | WorkloadFleetManagementClient->>WorkloadFleetManager: Component n Status update 66 | end 67 | WorkloadFleetManagementClient->>WorkloadFleetManager: Provides Full Deployment Status 68 | deactivate WorkloadFleetManagementClient 69 | WorkloadFleetManager->>WorkloadFleetManagerFrontEnd: Updates Web UI Full Deployment Status 70 | WorkloadFleetManagerFrontEnd->>EndUser: EndUser Receives Final Update 71 | ``` 72 | 73 | ## Relevant Links 74 | 75 | Please follow the subsequent links to view more technical information regarding Margo compliant devices: 76 | 77 | - [Workload Fleet Manager Component overview](../fleet-management/workload/management-interface-requirements.md) 78 | - [Margo API Reference](../margo-api-reference/margo-api-specification.md) 79 | -------------------------------------------------------------------------------- /system-design/margo-overview/workload-observability-overview.md: -------------------------------------------------------------------------------- 1 | # Workload Observability 2 | 3 | Observability involves the collection and analysis of information produced by a system to monitor its internal behavior. 4 | 5 | Observability data is captured using the following signals: 6 | 7 | - [Metrics](https://opentelemetry.io/docs/specs/otel/metrics/) - a numerical measurement in time used to observe change over a period of time or configured limits. For example, memory consumption, CPU Usage, available disk space. 8 | - [Logs](https://opentelemetry.io/docs/specs/otel/logs/) - text outputs produced by a running system/workloads to provide information about what is happening. For example, outputs to capture security events such as failed login attempts, or unexpected conditions such as errors. 9 | - [Traces](https://opentelemetry.io/docs/specs/otel/trace/) - contextual data used to follow a request's entire path through a distributed system. For example, trace data can be used to identify bottlenecks, or failure points, within a distributed system. 10 | 11 | Margo's workload observability scope is limited to the following areas: 12 | 13 | - The device's container platform 14 | - The device's Workload Fleet Management Client 15 | - The compliant workloads deployed to the device. 16 | 17 | The workload observability data is intended to be used for purposes such as: 18 | 19 | - Monitoring the container platform's health and current state. This includes aspects such as memory, CPU, and disk usage as well as cluster, node, pod, and container availability, run state, and configured resource limits. This enables end users to make decisions such as whether or not a device can support more workloads, or has too many deployed. 20 | - Monitoring the Workload Fleet Management Client and containerized workload's state to ensure it is running correctly, performing as expected and not consuming more resource than expected. 21 | - To assist with debugging/diagnostics for workloads encountering unexpected conditions impacting their ability to run as expected. 22 | 23 | Margo's workload observability is NOT intended to be used to monitor anything outside the device such as production processes, machinery, controllers, or sensors and should NOT be used for this purpose. 24 | 25 | ## Workload Observability Framework 26 | 27 | Workload observability data is made available using [OpenTelemetry](https://opentelemetry.io/docs/). OpenTelemetry, a popular open source specification, defines a common way for observability data to be generated and consumed. 28 | 29 | There are several reasons why OpenTelemetry was chosen: 30 | 31 | - OpenTelemetry is based on a open source specification and not only an implementation 32 | - OpenTelemetry is widely adopted 33 | - OpenTelemetry has a large, and active, open source community 34 | - OpenTelemetry provides [SDKs](https://opentelemetry.io/docs/languages/) for many popular languages if people wish to use them 35 | - The OpenTelemetry community project has reusable components such as telemetry [receivers](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver) for Kubernetes, Docker and the host system making integration easier. 36 | - OpenTelemetry is vendor agnostic. 37 | 38 | > **Decision Needed:** Need to determine which version(s) of the specification are supported 39 | 40 | ## Relevant Links 41 | 42 | Please follow the subsequent links to view more technical information regarding Margo's workload observability: 43 | 44 | - How workload suppliers can [publish observability data](../app-interoperability/publishing-workload-observability-data.md) 45 | - How devices must [collection workload observability data](../device-interoperability/collecting-workload-observability-data.md) 46 | - How workload fleet management solutions can [consume workload observability data](../fleet-management/workload/consuming-workload-observability-data.md) 47 | --------------------------------------------------------------------------------