diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..4274da1 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,10 @@ +# vim:ts=4:sts=4:sw=4:et +# +# This is the CODEOWNERS file. The syntax is as follows: +# [ ...] + +# For the 'docs/' directory, @jnbdz is the code owner. +/docs/ @jnbdz + +# For the rest of the repository, @jnbdz and @ianbenlolo are the code owners. +* @jnbdz # @ianbenlolo diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..384d38c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,85 @@ +--- +name: "🐛 Bug Report" +description: Report a bug +title: "(short issue description)" +labels: [bug, needs-triage] +assignees: [] +body: + - type: textarea + id: description + attributes: + label: Describe the bug + description: What is the problem? A clear and concise description of the bug. + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: | + What did you expect to happen? + validations: + required: true + - type: textarea + id: current + attributes: + label: Current Behavior + description: | + What actually happened? + + Please include full errors, uncaught exceptions, stack traces, and relevant logs. + If service responses are relevant, please include wire logs. + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: Reproduction Steps + description: | + Provide a self-contained, concise snippet of code that can be used to reproduce the issue. + For more complex issues provide a repo with the smallest sample that reproduces the bug. + + Avoid including business logic or unrelated code, it makes diagnosis more difficult. + The code sample should be an SSCCE. See http://sscce.org/ for details. In short, please provide a code sample that we can copy/paste, run and reproduce. + validations: + required: true + - type: textarea + id: solution + attributes: + label: Possible Solution + description: | + Suggest a fix/reason for the bug + validations: + required: false + - type: textarea + id: context + attributes: + label: Additional Information/Context + description: | + Anything else that might be relevant for troubleshooting this bug. Providing context helps us come up with a solution that is most useful in the real world. + validations: + required: false + - type: input + id: version + attributes: + label: Version used + validations: + required: true + - type: input + id: environment + attributes: + label: OS name and version + validations: + required: true + - type: input + id: package-manager + attributes: + label: Package manager used + validations: + required: false + - type: input + id: python-version + attributes: + label: Python version used (if applicable) + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..952202d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,6 @@ +--- +blank_issues_enabled: false +contact_links: + - name: 💬 General Question + url: https://github.com/AmadlaOrg/amadla-cli/discussions/categories/q-a + about: Please ask and answer questions as a discussion thread diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml new file mode 100644 index 0000000..5755427 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -0,0 +1,22 @@ +name: "📕 Documentation Issue" +description: Report an issue in the API Reference documentation or Developer Guide +title: "(short issue description)" +labels: [documentation, needs-triage] +assignees: [] +body: + - type: textarea + id: description + attributes: + label: Describe the issue + description: A clear and concise description of the issue. + validations: + required: true + + - type: textarea + id: links + attributes: + label: Links + description: | + Include links to affected documentation page(s). + validations: + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000..b7418c8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,71 @@ +--- +name: 🚀 Feature Request +description: Suggest an idea for this project +title: "(short issue description)" +labels: [feature-request, needs-triage] +assignees: [] +body: + - type: textarea + id: description + attributes: + label: Describe the feature + description: A clear and concise description of the feature you are proposing. + validations: + required: true + - type: textarea + id: use-case + attributes: + label: Use Case + description: | + Why do you need this feature? For example: "I'm always frustrated when..." + validations: + required: true + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: | + Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation. + validations: + required: false + - type: textarea + id: other + attributes: + label: Other Information + description: | + Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc. + validations: + required: false + - type: checkboxes + id: ack + attributes: + label: Acknowledgements + options: + - label: I may be able to implement this feature request + required: false + - label: This feature might incur a breaking change + required: false + - type: input + id: version + attributes: + label: Version used + validations: + required: true + - type: input + id: environment + attributes: + label: OS name and version + validations: + required: false + - type: input + id: package-manager + attributes: + label: Package manager used + validations: + required: false + - type: input + id: python-version + attributes: + label: Python version used (if applicable) + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/source-distribution.yml b/.github/ISSUE_TEMPLATE/source-distribution.yml new file mode 100644 index 0000000..1b4db0d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/source-distribution.yml @@ -0,0 +1,46 @@ +--- +name: "Source distribution issue" +description: Report an issue with source distribution +title: "(short issue description)" +labels: [source-distribution, needs-triage] +assignees: [] +body: + - type: textarea + id: description + attributes: + label: Describe the issue + description: What is the problem? A clear and concise description of the issue. + validations: + required: true + - type: textarea + id: context + attributes: + label: Additional Information/Context + description: | + All of the commands, arguments and their outputs used when trying to build the Amadla CLI. Anything else that might be relevant for troubleshooting this issue. + validations: + required: false + - type: input + id: version + attributes: + label: Version used + validations: + required: true + - type: input + id: environment + attributes: + label: OS name and version + validations: + required: true + - type: input + id: package-manager + attributes: + label: Package manager used + validations: + required: true + - type: input + id: python-version + attributes: + label: Python version used (if applicable) + validations: + required: false diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..206c939 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,40 @@ +name: Deploy with Amadla CLI + +on: + workflow_call: + secrets: + GH_PAT: + description: GitHub Token with permissions 'repo' and 'read:org' to list GitHub repos + required: true + inputs: + logLevel: + description: 'Log level' + required: true + default: 'warning' + type: choice + options: + - info + - warning + - debug + environment: + description: 'Environment to run tests against' + type: environment + required: true + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install Amadla CLI + uses: SiteNetSoft/GitHub-Actions/.github/workflows/install-amadla-cli.yml@develop + + - name: Deploy + uses: SiteNetSoft/GitHub-Actions/.github/workflows/deploy.yml@develop + with: + logLevel: ${{ github.event.inputs.logLevel }} + environment: ${{ github.event.inputs.environment }} + ghPat: ${{ secrets.GH_PAT }} + ``` diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 0000000..e438e61 --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,5 @@ +name: Generate and Deploy Documentation + +on: + release: + types: [created] diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml new file mode 100644 index 0000000..0ca4bbd --- /dev/null +++ b/.github/workflows/install.yml @@ -0,0 +1,13 @@ +name: Install Amadla CLI + +on: + workflow_call: + +jobs: + install-amadla-cli: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install Amadla CLI diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml new file mode 100644 index 0000000..2ac75a3 --- /dev/null +++ b/.github/workflows/readme.yml @@ -0,0 +1,6 @@ +name: Update README +on: + push: + branches: + - master + - main diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..259c749 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,11 @@ +name: CI/CD + +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main diff --git a/PYTHON_VERSION b/PYTHON_VERSION new file mode 100644 index 0000000..1dbf52a --- /dev/null +++ b/PYTHON_VERSION @@ -0,0 +1 @@ +^3.12 \ No newline at end of file diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000..18587f2 --- /dev/null +++ b/README.fr.md @@ -0,0 +1,46 @@ +Amadla logo + +# Amadla CLI + +[![Language: English](https://img.shields.io/badge/Language-English-blue.svg)](./README.md) +[![Language: Français](https://img.shields.io/badge/Langue-Fran%C3%A7ais-blue.svg)](./README.fr.md) + +[![Build Status][build_status_badge]][build_status_link] [![Say Thanks!](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/amadla.org) + +[![GitHub stars](https://img.shields.io/github/stars/AmadlaOrg/amadla-cli?logo=github)](https://github.com/AmadlaOrg/amadla-cli/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/AmadlaOrg/amadla-cli?logo=github)](https://github.com/AmadlaOrg/amadla-cli/network) +[![Lines of Code](https://img.shields.io/badge/lines%20of%20code-k-lightgrey)](https://github.com/AmadlaOrg/amadla-cli#hari-sekhon---devops-bash-tools) +[![License](https://img.shields.io/badge/license-MIT-green)](https://github.com/AmadlaOrg/amadla-cli/blob/master/LICENSE) +[![GitHub Last Commit](https://img.shields.io/github/last-commit/AmadlaOrg/amadla-cli?logo=github)](https://github.com/AmadlaOrg/amadla-cli/commits/master) + +[![Python 3.11](https://img.shields.io/badge/Python-3.11+-3776AB?logo=python&logoColor=white)](https://github.com/AmadlaOrg/amadla-cli/) + +Cet outil, utilisant Vault, Packer, Ansible et Terraform, crée des images de serveur et construit une infrastructure. + +Site web: [Amadla](https://amadla.org/) + +## :rice_scene: Contexte + +La décennie précédente a connu une explosion d'outils conçus pour simplifier la configuration de serveurs cloud. Bien que cette évolution soit positive, l'assemblage et la configuration de ces outils demeurent un défi. Cette tâche est chronophage et nécessite une expertise approfondie des systèmes cloud, des outils d'Infrastructure as Code (IaC), de Linux, de la cybersécurité, etc. + +Pour de nombreuses personnes qui ont simplement besoin d'un environnement cloud pour exécuter des applications côté serveur simples, telles qu'un VPN, un blog, un serveur de messagerie ou un gestionnaire de fichiers, respecter les meilleures pratiques et garantir la sécurité peut sembler intimidant ; c'est trop compliqué et prend trop de temps. + +Amadla simplifie ce processus en automatisant la création d'un environnement cloud de base adapté à un usage personnel ou aux entreprises de toutes tailles. Il facilite également la mise en place d'un serveur et d'un environnement cloud en abstrayant de nombreux aspects. + +## :books: Documentation +:card_index_dividers: /docs + +## :label: Terminologie + +- [IaC](https://en.wikipedia.org/wiki/Infrastructure_as_code) - Infrastructure as Code. +- CE - Community Edition. +- [Amadla](https://amadla.org/) - Juste un nom inventé. + +## :scroll: Droits d'auteur et Licence +Le contenu de cette documentation est dans le domaine public. + +La licence pour le code se trouve dans le fichier [LICENSE](./LICENSE). + +--- + +Fabriqué au Québec :fleur_de_lis:, Canada 🇨🇦! diff --git a/amadlacli/app.py b/amadlacli/app.py index 0e8516c..029d90f 100644 --- a/amadlacli/app.py +++ b/amadlacli/app.py @@ -5,10 +5,14 @@ Released under MIT License """ +import os import tomllib +project_root = os.path.dirname(os.path.dirname(__file__)) +pyproject_path = os.path.join(project_root, "pyproject.toml") + try: - with open("pyproject.toml", "rb") as f: + with open(pyproject_path, "rb") as f: try: project_data = tomllib.load(f) except tomllib.TOMLDecodeError as e: @@ -48,4 +52,4 @@ def description(self): """ Application description. """ - return self.metadata["description"] \ No newline at end of file + return self.metadata["description"] diff --git a/amadlacli/cli/__init__.py b/amadlacli/cli/__init__.py index e69de29..025c4a7 100644 --- a/amadlacli/cli/__init__.py +++ b/amadlacli/cli/__init__.py @@ -0,0 +1,34 @@ +""" +Amadla cli. + +(C) 2024 Jean-Nicolas Boulay Desjardins (JNBD) +Released under MIT License + +CLI classes. +""" + +import click + +from amadlacli.app import APP +from amadlacli.cli.entity import entity_cli +from amadlacli.cli.template import template_cli +from amadlacli.cli.schema import schema_cli + + +@click.group() +@click.version_option(APP().version()) +@click.pass_context +def cli(ctx): + """ + Amadla CLI + """ + pass + + +# Register the subgroups +cli.add_command(entity_cli.entity) +cli.add_command(template_cli.template) +cli.add_command(schema_cli.schema) + +if __name__ == '__main__': + cli() diff --git a/amadlacli/cli/entity.py b/amadlacli/cli/entity.py new file mode 100644 index 0000000..01050d2 --- /dev/null +++ b/amadlacli/cli/entity.py @@ -0,0 +1,43 @@ +""" +Amadla cli. + +(C) 2024 Jean-Nicolas Boulay Desjardins (JNBD) +Released under MIT License + +CLI classes. +""" + +import click + + +class EntityCli: + """ + Schema utilities + """ + + @click.group() + @click.pass_context + def entity(self, ctx): + """ + Schema utilities + """ + pass + + @entity.command() + @click.pass_context + def validate(self, ctx): + """ + Validate schemas + """ + click.echo("Schema validated.") + + @entity.command() + @click.pass_context + def generate(self, ctx): + """ + Generate schema + """ + click.echo("Schema generated.") + + +entity_cli = EntityCli() diff --git a/amadlacli/cli/schema.py b/amadlacli/cli/schema.py new file mode 100644 index 0000000..2dd44b9 --- /dev/null +++ b/amadlacli/cli/schema.py @@ -0,0 +1,43 @@ +""" +Amadla cli. + +(C) 2024 Jean-Nicolas Boulay Desjardins (JNBD) +Released under MIT License + +CLI classes. +""" + +import click + + +class SchemaCli: + """ + Schema utilities + """ + + @click.group() + @click.pass_context + def schema(self, ctx): + """ + Schema utilities + """ + pass + + @schema.command() + @click.pass_context + def validate(self, ctx): + """ + Validate schemas + """ + click.echo("Schema validated.") + + @schema.command() + @click.pass_context + def generate(self, ctx): + """ + Generate schema + """ + click.echo("Schema generated.") + + +schema_cli = SchemaCli() diff --git a/amadlacli/cli/template.py b/amadlacli/cli/template.py new file mode 100644 index 0000000..a8678fd --- /dev/null +++ b/amadlacli/cli/template.py @@ -0,0 +1,43 @@ +""" +Amadla cli. + +(C) 2024 Jean-Nicolas Boulay Desjardins (JNBD) +Released under MIT License + +CLI classes. +""" + +import click + + +class TemplateCli: + """ + Schema utilities + """ + + @click.group() + @click.pass_context + def template(self, ctx): + """ + Schema utilities + """ + pass + + @template.command() + @click.pass_context + def validate(self, ctx): + """ + Validate schemas + """ + click.echo("Schema validated.") + + @template.command() + @click.pass_context + def generate(self, ctx): + """ + Generate schema + """ + click.echo("Schema generated.") + + +template_cli = TemplateCli() diff --git a/amadlacli/extensions/jinja2/extends.py b/amadlacli/extensions/jinja2/extends.py new file mode 100644 index 0000000..16675b8 --- /dev/null +++ b/amadlacli/extensions/jinja2/extends.py @@ -0,0 +1,35 @@ +""" +Amadla cli. + +(C) 2024 Jean-Nicolas Boulay Desjardins (JNBD) +Released under MIT License + +CLI classes. +""" + +from jinja2 import nodes +from jinja2.ext import Extension + + +class AmadlaExtendsExtension(Extension): + """ + amadla_extends Jinja2 tag + """ + tags = {'amadla_extends'} + + def parse(self, parser): + lineno = next(parser.stream).lineno + template_name = parser.parse_expression() + return nodes.Extends(template_name, lineno=lineno) + + +class UrlExtendsExtension(Extension): + """ + url_extends Jinja2 tag + """ + tags = {'url_extends'} + + def parse(self, parser): + lineno = next(parser.stream).lineno + template_url = parser.parse_expression() + return nodes.Extends(template_url, lineno=lineno) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/assets/diagrams/cascading_configs.d2 b/docs/assets/diagrams/cascading_configs.d2 new file mode 100644 index 0000000..b65f8b1 --- /dev/null +++ b/docs/assets/diagrams/cascading_configs.d2 @@ -0,0 +1,6 @@ +"apps.yml" -> "clouds.yml" -> "servers.yml" -> "instances.yml" -> "amadla.lock" + +"apps.yml".shape: page +"servers.yml".shape: page +"clouds.yml".shape: page +"instances.yml".shape: page diff --git a/docs/assets/diagrams/cascading_configs.svg b/docs/assets/diagrams/cascading_configs.svg new file mode 100644 index 0000000..1390312 --- /dev/null +++ b/docs/assets/diagrams/cascading_configs.svg @@ -0,0 +1,99 @@ +apps.ymlclouds.ymlservers.ymlinstances.ymlamadla.lock + + + + + + + diff --git a/docs/assets/diagrams/combined-tools.d2 b/docs/assets/diagrams/combined-tools.d2 new file mode 100644 index 0000000..d8d652d --- /dev/null +++ b/docs/assets/diagrams/combined-tools.d2 @@ -0,0 +1,188 @@ +amadla-cli: { + grid-rows: 13 + + validateschema: { + grid-rows: 3 + explanation: |md + + # validateschema + - Validates a json or yaml file against a schema (https://json-schema.org/) + - The schemas can be found in a directory + + | + doc: |md + + # Parameters + - `--version` ou `-v`: The version of the schema + - `--schema` ou `-s`: The path to the schema + - `--schema-dir` ou `-d`: The path to the directory containing the schema + - `--file` ou `-f`: The path to the file to validate + - `--help` ou `-h`: Display the help message + + ## Default + - `--version`: 1 (the version of the schema can be also extracted from the file name of the schema) + - `--schema-dir`: schemas + + | + example: |bash + validateschema --schema configuration.v1.schema.json --file data.json + # or + validateschema -s configuration.v1.schema.json -f data.json + # or + validateschema -v 1 -s configuration.v1.schema.json -f data.yaml + # or + validateschema -v 1 -d schemas -f data.yaml + # or + validateschema data.yaml + | + } + + pyproject_to_sphinx: { + grid-rows: 3 + explanation: |md + + # pyproject_to_sphinx + - Pulls data from pyproject.toml to populate the sphinx `conf.py` + - Following the `conf.py` being populated Sphinx can be used to generate documentation + - Used in the terminal it will print an json string containing the data that it would have written to the `conf.py` + - If no path to `pyproject.toml` is provided it will look for it in the current directory + + | + example: |bash + pyproject_to_sphinx ./pyproject.toml + # or + pyproject_to_sphinx + | + } + + pydictmerge: { + grid-rows: 3 + explanation: |md + + # pydictmerge + - Merges two dictionaries + - They are two ways to merge the dictionaries + + | + example: |bash + pydictmerge --file1 ./file1.json --file2 ./file2.json --merge-type 1 + # or + pydictmerge -f1 ./file1.json -f2 ./file2.json -m 1 + # or + pydictmerge -f1 ./file1.json -f2 ./file2.json -m 2 + | + } + + secretmerge: { + grid-rows: 3 + explanation: |md + + # secretmerge + - Exports secrets from a json file to environment variables + - The secrets from different sources and KMS keys can be merged + + | + } + + envmerge: { + grid-rows: 3 + explanation: |md + + # envmerge + - Exports environment variables from a json file to environment variables + + | + } + + dryrun: { + grid-rows: 3 + explanation: |md + + # dryrun + - Runs a command without executing it + + | + } + + pygitmodule: { + grid-rows: 3 + explanation: |md + + # pygitmodule + - Creates a git module + + | + example: |bash + pygitmodule --module-name module_name --remove + # or + pygitmodule -n module_name -r + # or + pygitmodule -n module_name -a + # or + + | + } + + amadladiagrams: { + grid-rows: 3 + explanation: |md + + # amadladiagrams + - Converts a d file to an amadla fileamadladiagrams + - Will convert the configuration files and some module content into d2lang files + - To easily generate diagrams of your setup + - An image is worth a thousand words! + + | + example: |bash + pyd2amadla --file ./file.d --output ./output.d2 + # or + pyd2amadla -f ./file.d -o ./output.d2 + | + } + + amadlaconfig: { + grid-rows: 3 + explanation: |md + + # amadlaconfig + - Creates an amadla config file + + | + } + + pylockfilehelper: { + grid-rows: 3 + explanation: |md + + # pylockfilehelper + - Creates a lock file + + | + example: |bash + pylockfilehelper --file ./file.json --lock-file ./lock.json + # or + pylockfilehelper -f ./file.json -l ./lock.json + | + } + + pyclickmerge: { + grid-rows: 3 + explanation: |md + + # pyclickmerge + - Merges two click commands + + | + } + + pyproject_to_app: { + grid-rows: 3 + explanation: |md + + # pyproject_to_app + - Pulls data from pyproject.toml to populate the app class + + | + } +} diff --git a/docs/assets/diagrams/combined-tools.svg b/docs/assets/diagrams/combined-tools.svg new file mode 100644 index 0000000..74d1c38 --- /dev/null +++ b/docs/assets/diagrams/combined-tools.svg @@ -0,0 +1,998 @@ +amadla-clivalidateschemapyproject_to_sphinxpydictmergesecretmergeenvmergedryrunpygitmodulepyd2amadlaamadlaconfigpylockfilehelperpyclickmergepyproject_to_app

validateschema

+
    +
  • Validates a json or yaml file against a schema (https://json-schema.org/)
  • +
  • The schemas can be found in a directory
  • +
+

Parameters

+
    +
  • --version ou -v: The version of the schema
  • +
  • --schema ou -s: The path to the schema
  • +
  • --schema-dir ou -d: The path to the directory containing the schema
  • +
  • --file ou -f: The path to the file to validate
  • +
  • --help ou -h: Display the help message
  • +
+

Default

+
    +
  • --version: 1 (the version of the schema can be also extracted from the file name of the schema)
  • +
  • --schema-dir: schemas
  • +
+
validateschema --schema configuration.v1.schema.json --file data.json +# or +validateschema -s configuration.v1.schema.json -f data.json +# or +validateschema -v 1 -s configuration.v1.schema.json -f data.yaml +# or +validateschema -v 1 -d schemas -f data.yaml +# or +validateschema data.yamlvalidateschema --schema configuration.v1.schema.json --file data.json +# or +validateschema -s configuration.v1.schema.json -f data.json +# or +validateschema -v 1 -s configuration.v1.schema.json -f data.yaml +# or +validateschema -v 1 -d schemas -f data.yaml +# or +validateschema data.yaml

pyproject_to_sphinx

+
    +
  • Pulls data from pyproject.toml to populate the sphinx conf.py
  • +
  • Following the conf.py being populated Sphinx can be used to generate documentation
  • +
  • Used in the terminal it will print an json string containing the data that it would have written to the conf.py
  • +
  • If no path to pyproject.toml is provided it will look for it in the current directory
  • +
+
pyproject_to_sphinx ./pyproject.toml +# or +pyproject_to_sphinxpyproject_to_sphinx ./pyproject.toml +# or +pyproject_to_sphinx

pydictmerge

+
    +
  • Merges two dictionaries
  • +
  • They are two ways to merge the dictionaries
  • +
+
pydictmerge --file1 ./file1.json --file2 ./file2.json --merge-type 1 +# or +pydictmerge -f1 ./file1.json -f2 ./file2.json -m 1 +# or +pydictmerge -f1 ./file1.json -f2 ./file2.json -m 2pydictmerge --file1 ./file1.json --file2 ./file2.json --merge-type 1 +# or +pydictmerge -f1 ./file1.json -f2 ./file2.json -m 1 +# or +pydictmerge -f1 ./file1.json -f2 ./file2.json -m 2

secretmerge

+
    +
  • Exports secrets from a json file to environment variables
  • +
  • The secrets from different sources and KMS keys can be merged
  • +
+

envmerge

+
    +
  • Exports environment variables from a json file to environment variables
  • +
+

dryrun

+
    +
  • Runs a command without executing it
  • +
+

pygitmodule

+
    +
  • Creates a git module
  • +
+
pygitmodule --module-name module_name --remove +# or +pygitmodule -n module_name -r +# or +pygitmodule -n module_name -a +# or +pygitmodule --module-name module_name --remove +# or +pygitmodule -n module_name -r +# or +pygitmodule -n module_name -a +# or +

pyd2amadla

+
    +
  • Converts a d file to an amadla file
  • +
  • Will convert the configuration files and some module content into d2lang files
  • +
  • To easily generate diagrams of your setup
  • +
  • An image is worth a thousand words!
  • +
+
pyd2amadla --file ./file.d --output ./output.d2 +# or +pyd2amadla -f ./file.d -o ./output.d2pyd2amadla --file ./file.d --output ./output.d2 +# or +pyd2amadla -f ./file.d -o ./output.d2

amadlaconfig

+
    +
  • Creates an amadla config file
  • +
+

pylockfilehelper

+
    +
  • Creates a lock file
  • +
+
pylockfilehelper --file ./file.json --lock-file ./lock.json +# or +pylockfilehelper -f ./file.json -l ./lock.jsonpylockfilehelper --file ./file.json --lock-file ./lock.json +# or +pylockfilehelper -f ./file.json -l ./lock.json

pyclickmerge

+
    +
  • Merges two click commands
  • +
+

pyproject_to_app

+
    +
  • Pulls data from pyproject.toml to populate the app class
  • +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/docs/assets/diagrams/deploy.d2 b/docs/assets/diagrams/deploy.d2 new file mode 100644 index 0000000..279baf3 --- /dev/null +++ b/docs/assets/diagrams/deploy.d2 @@ -0,0 +1,108 @@ +Amadla: Amadla CLI +Amadla: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/sitenetsoft/amadla/amadla.png +} + +GenerateVariablesFiles: Generate Variables Files +GenerateVariablesFiles.shape: rectangle + +LoopThroughClouds: Loop Through Clouds +LoopThroughClouds.shape: oval + +LoopThroughInstances: Loop Through Instances +LoopThroughInstances.shape: oval + +GetInstanceBuilderName: Get Instance Builder Name +GetInstanceBuilderName.shape: parallelogram + +BuilderNameSource: This information\n is taken from the\n Amadla configuration files +BuilderNameSource.shape: callout + +BuilderTemplateSource: It is an extension component that\n can be added to Amadla\n to support new builders +BuilderTemplateSource.shape: callout + +RunBuilderExplanation: The builder template\n that was just populated\n is a Bash script\n that will be executed +RunBuilderExplanation.shape: callout + +GetBuilderTemplate: Get Builder Template +GetBuilderTemplate.shape: parallelogram + +PopulateBuilderTemplate: Populate Builder Template +PopulateBuilderTemplate.shape: rectangle + +RunBuilder: Run Builder +RunBuilder.shape: rectangle + +BuilderSelector: Select builder +BuilderSelector.shape: diamond + +Terraform: "" +Terraform: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/terraform.png +} + +Packer: "" +Packer: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/packer.png +} + +Ansible: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/ansible.png +} + +PackerThenAnsible: Ansible +PackerThenAnsible: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/ansible.png +} + +Puppet: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/puppet.png +} + +Chef: "" +Chef: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/chef.png +} + +BuilderOthers: Others... +BuilderOthers.shape: stored_data + +RunBuilder: Run Builder +RunBuilder.shape: rectangle + +Amadla -> GenerateVariablesFiles +GenerateVariablesFiles -> LoopThroughClouds + +LoopThroughClouds -> LoopThroughInstances +LoopThroughInstances -> GetInstanceBuilderName + +GetInstanceBuilderName -> BuilderSelector +BuilderNameSource -- GetInstanceBuilderName + +BuilderSelector -> Terraform +BuilderSelector -> Ansible +BuilderSelector -> Puppet +BuilderSelector -> Chef +BuilderSelector -> BuilderOthers +Terraform -> Packer: If present\n in the Terraform\n configuration +Packer -> PackerThenAnsible: If present\n in the Packer\n configuration + +Terraform -> GetBuilderTemplate +Packer -> GetBuilderTemplate +PackerThenAnsible -> GetBuilderTemplate +Ansible -> GetBuilderTemplate +Puppet -> GetBuilderTemplate +Chef -> GetBuilderTemplate +BuilderOthers -> GetBuilderTemplate + +GetBuilderTemplate -> PopulateBuilderTemplate +BuilderTemplateSource -- GetBuilderTemplate +RunBuilderExplanation -- RunBuilder +PopulateBuilderTemplate -> RunBuilder diff --git a/docs/assets/diagrams/deploy.png b/docs/assets/diagrams/deploy.png new file mode 100644 index 0000000..d2dfd61 Binary files /dev/null and b/docs/assets/diagrams/deploy.png differ diff --git a/docs/assets/diagrams/deploy.svg b/docs/assets/diagrams/deploy.svg new file mode 100644 index 0000000..9aba486 --- /dev/null +++ b/docs/assets/diagrams/deploy.svg @@ -0,0 +1,119 @@ +Amadla CLIGenerate Variables FilesLoop Through CloudsLoop Through InstancesGet Instance Builder NameThis information is taken from the Amadla configuration filesIt is an extension component that can be added to Amadla to support new buildersThe builder template that was just populated is a Bash script that will be executedGet Builder TemplatePopulate Builder TemplateRun BuilderSelect builderAnsibleAnsiblePuppetOthers... If present in the Terraform configurationIf present in the Packer configuration + + + + + + + + + + + + + + + + + + + + diff --git a/docs/assets/diagrams/gather_secrets.d2 b/docs/assets/diagrams/gather_secrets.d2 new file mode 100644 index 0000000..4eb826d --- /dev/null +++ b/docs/assets/diagrams/gather_secrets.d2 @@ -0,0 +1,42 @@ +Amadla: Amadla CLI +Amadla: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/sitenetsoft/amadla/amadla.png +} + +Vault: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/security/vault.png +} + +EnvFile: .env +EnvFile.shape: page + +EnvVar: Environment Variable +EnvVar: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/programming/language/bash.png +} + +AddSecretsToVars: Add Secrets To Vars +AddSecretsToVars.shape: rectangle +AddSecretsToVars: { + style: { + fill: "#DF2D2D" + stroke: "#890B0B" + } +} + +Amadla -> EnvVar + +EnvVar -> EnvFile: Not set +EnvVar -> AddSecretsToVars: Set + +EnvFile -> Vault: Not set +EnvFile -> AddSecretsToVars: Set + +Vault -> AddSecretsToVars: Set + +RaiseNotFoundError: Raise Not Found Error +RaiseNotFoundError.shape: rectangle +Vault -> RaiseNotFoundError: Not set diff --git a/docs/assets/diagrams/gather_secrets.png b/docs/assets/diagrams/gather_secrets.png new file mode 100644 index 0000000..1fb777d Binary files /dev/null and b/docs/assets/diagrams/gather_secrets.png differ diff --git a/docs/assets/diagrams/gather_secrets.svg b/docs/assets/diagrams/gather_secrets.svg new file mode 100644 index 0000000..25cab42 --- /dev/null +++ b/docs/assets/diagrams/gather_secrets.svg @@ -0,0 +1,113 @@ +Amadla CLIVault.envEnvironment VariableAdd Secrets To VarsRaise Not Found Error Not setSetNot setSetSetNot set + + + + + + + + + + + + + + diff --git a/docs/assets/diagrams/generate_vars_files.d2 b/docs/assets/diagrams/generate_vars_files.d2 new file mode 100644 index 0000000..6a61d66 --- /dev/null +++ b/docs/assets/diagrams/generate_vars_files.d2 @@ -0,0 +1,95 @@ +Amadla: Amadla CLI +Amadla: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/sitenetsoft/amadla/amadla.png +} + +GatherSecrets: Gather Secrets +GatherSecrets.shape: rectangle + +AddSecretsToVars: Add Secrets To Vars +AddSecretsToVars.shape: rectangle +AddSecretsToVars + +PullAmadlaLockFile: Pull\n Amadla\n Lock File +PullAmadlaLockFile.shape: page + +GetAllTheModulesGitRepos: Get All\n The Modules\n Git Repos +GetAllTheModulesGitRepos.shape: rectangle + +CheckIfModulesExists: Modules Exists? +CheckIfModulesExists.shape: diamond + +CheckIfModulesAreUpToDate: Modules Are Up To Date? +CheckIfModulesAreUpToDate.shape: diamond + +DownloadModules: Download\n Modules +DownloadModules.shape: square + +LookupModulesVariablesTemplateFile: Lookup\n Modules\n variables\n template file +LookupModulesVariablesTemplateFile.shape: page + +RaiseErrorIfModulesVariablesTemplateFileNotFound: Raise Error:\n If Modules\n variables\n template file\n not found +RaiseErrorIfModulesVariablesTemplateFileNotFound.shape: rectangle +RaiseErrorIfModulesVariablesTemplateFileNotFound { + style: { + fill: "#DF2D2D" + stroke: "#890B0B" + } +} + +PopulateModulesVariablesTemplateFile: Populate\n Modules\n variables\n template file +PopulateModulesVariablesTemplateFile.shape: rectangle + +RaiseErrorIfModulesVariablesTemplateFileIsNotValid: Raise Error:\n If Modules\n variables\n template file is\n not valid +RaiseErrorIfModulesVariablesTemplateFileIsNotValid.shape: rectangle +RaiseErrorIfModulesVariablesTemplateFileIsNotValid { + style: { + fill: "#DF2D2D" + stroke: "#890B0B" + } +} + +LoopThroughModules: Loop Through\n Modules +LoopThroughModules.shape: oval + +LookupModulesVariablesFile: Lookup\n Modules\n variables file +LookupModulesVariablesFile.shape: page + +Terraform: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/terraform.png +} + +Packer: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/packer.png +} + +Ansible: { + shape: image + icon: https://raw.githubusercontent.com/SiteNetSoft/resources/master/images/onprem/iac/ansible.png +} + +Others: Others... +Others.shape: page + +Amadla -> GatherSecrets +GatherSecrets -> PullAmadlaLockFile +PullAmadlaLockFile -> AddSecretsToVars +AddSecretsToVars -> GetAllTheModulesGitRepos +GetAllTheModulesGitRepos -> CheckIfModulesExists +CheckIfModulesExists -> CheckIfModulesAreUpToDate: Yes +CheckIfModulesAreUpToDate -> DownloadModules: No +CheckIfModulesExists -> DownloadModules: No +CheckIfModulesAreUpToDate -> LookupModulesVariablesTemplateFile: Yes +DownloadModules -> LookupModulesVariablesTemplateFile +LookupModulesVariablesTemplateFile -> RaiseErrorIfModulesVariablesTemplateFileNotFound: Not Found +LookupModulesVariablesTemplateFile -> PopulateModulesVariablesTemplateFile: Found +PopulateModulesVariablesTemplateFile -> LoopThroughModules +LoopThroughModules -> LookupModulesVariablesFile +LookupModulesVariablesFile -> Terraform +LookupModulesVariablesFile -> Packer +LookupModulesVariablesFile -> Ansible +LookupModulesVariablesFile -> Others +LookupModulesVariablesFile -> RaiseErrorIfModulesVariablesTemplateFileIsNotValid: Not Valid diff --git a/docs/assets/diagrams/generate_vars_files.png b/docs/assets/diagrams/generate_vars_files.png new file mode 100644 index 0000000..b7da27b Binary files /dev/null and b/docs/assets/diagrams/generate_vars_files.png differ diff --git a/docs/assets/diagrams/generate_vars_files.svg b/docs/assets/diagrams/generate_vars_files.svg new file mode 100644 index 0000000..9573e1f --- /dev/null +++ b/docs/assets/diagrams/generate_vars_files.svg @@ -0,0 +1,126 @@ +Amadla CLIGather SecretsAdd Secrets To VarsPull Amadla Lock FileGet All The Modules Git ReposModules Exists?Modules Are Up To Date?Download ModulesLookup Modules variables template fileRaise Error: If Modules variables template file not foundPopulate Modules variables template fileRaise Error: If Modules variables template file is not validLoop Through ModulesLookup Modules variables fileTerraformPackerAnsibleOthers... YesNoNoYesNot FoundFoundNot Valid + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/assets/diagrams/merge_config_to_amadla_lock.d2 b/docs/assets/diagrams/merge_config_to_amadla_lock.d2 new file mode 100644 index 0000000..0909375 --- /dev/null +++ b/docs/assets/diagrams/merge_config_to_amadla_lock.d2 @@ -0,0 +1,10 @@ +"apps.yml" -> "amadla.lock" +"clouds.yml" -> "amadla.lock" +"servers.yml" -> "amadla.lock" +"instances.yml" -> "amadla.lock" + +"apps.yml".shape: page +"servers.yml".shape: page +"clouds.yml".shape: page +"instances.yml".shape: page +"amadla.lock".shape: page diff --git a/docs/assets/diagrams/merge_config_to_amadla_lock.svg b/docs/assets/diagrams/merge_config_to_amadla_lock.svg new file mode 100644 index 0000000..1d94dc2 --- /dev/null +++ b/docs/assets/diagrams/merge_config_to_amadla_lock.svg @@ -0,0 +1,99 @@ +apps.ymlamadla.lockservers.ymlclouds.ymlinstances.yml + + + + + + + diff --git a/docs/assets/diagrams/resources/amadla-logo-512x512.png b/docs/assets/diagrams/resources/amadla-logo-512x512.png new file mode 100644 index 0000000..d20b3dd Binary files /dev/null and b/docs/assets/diagrams/resources/amadla-logo-512x512.png differ diff --git a/docs/assets/diagrams/validateschema.d2 b/docs/assets/diagrams/validateschema.d2 new file mode 100644 index 0000000..e69de29 diff --git a/docs/assets/logo-big-circle.svg b/docs/assets/logo-big-circle.svg new file mode 100644 index 0000000..028be14 --- /dev/null +++ b/docs/assets/logo-big-circle.svg @@ -0,0 +1,121 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..6d3d1c3 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,82 @@ +# Configuration file for the Sphinx documentation builder. + +# -- Project information + +import toml +import subprocess + + +def get_contributors(directory): + git_command = ['git', 'log', '--pretty=format:%an', f'-- {directory}'] + result = subprocess.run(git_command, capture_output=True, text=True) + contributors = set(result.stdout.splitlines()) + return contributors + + +def extract_copyright(filename): + with open(filename) as f: + for line in f: + if "Copyright" in line: + return line.strip() + return None + + +def get_short_version(long_version: str): + parts = long_version.split('.') + if len(parts) >= 2: + return '.'.join(parts[:2]) + else: + return long_version + + +project_data = toml.load("../pyproject.toml") +metadata = project_data["tool"]["poetry"] + +project = metadata["title"] +copyright = extract_copyright('../LICENSE') +author = ', '.join(get_contributors('docs/')) + +# - version: This is a shorter, "quick reference" version of your project, +# which usually omits smaller point-level details. For example, if your project's full version is '1.3.4', +# the version might just be '1.3'. +# - release: This is the full version string of your project, including alpha/beta/rc tags. +# Continuing the previous example, the release would be '1.3.4'. +# +# In the pyproject.toml file, the [tool.poetry] section only has a version field, +# which corresponds to the full version of your project, similar to the release field in Sphinx's conf.py. +# The version in pyproject.toml typically follows the format of MAJOR.MINOR.PATCH, for example '1.3.4', +# and can also include identifiers for pre-release and build metadata. +# +# For more information about Sphinx versioning see: +# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-version +release = metadata["version"] +version = get_short_version(metadata["version"]) + +language = 'en' +languages = ['en', 'fr'] + +# -- General configuration + +extensions = [ + 'sphinx.ext.duration', + 'sphinx.ext.doctest', + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.intersphinx', + 'sphinx.ext.githubpages', +] + +intersphinx_mapping = { + 'python': ('https://docs.python.org/3/', None), + 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), +} +intersphinx_disabled_domains = ['std'] + +templates_path = ['_templates'] + +# -- Options for HTML output + +html_theme = 'sphinx_rtd_theme' + +# -- Options for EPUB output +epub_show_urls = 'footnote' diff --git a/docs/source/en/README.rst b/docs/source/en/README.rst new file mode 100644 index 0000000..4d2c6a8 --- /dev/null +++ b/docs/source/en/README.rst @@ -0,0 +1,5 @@ +Docs \| Amadla CE +============================= + +Menu +-------------------- diff --git a/docs/source/en/ci-cd.rst b/docs/source/en/ci-cd.rst new file mode 100644 index 0000000..a1fe45f --- /dev/null +++ b/docs/source/en/ci-cd.rst @@ -0,0 +1,2 @@ +CI/CD +========= diff --git a/docs/source/en/dev.rst b/docs/source/en/dev.rst new file mode 100644 index 0000000..f46f495 --- /dev/null +++ b/docs/source/en/dev.rst @@ -0,0 +1,489 @@ +Dev +========================= + +There are many layers of automation in Amadla. This makes it very easy +to make a small mistakes that can have a cascading affect on all the +other layers of automation for this reason it is important for anyone +who wants to contribute to familiarize themselves with this +documentation. + +Rules +------------------------ + +1. `Fail-fast! `__ - No, it is + a not a new Fast & Furious movie. It is all about clear errors and + avoiding cascading issues that make it very hard to clean up and + debug a problem. + + - Don’t hesitate to put conditions to verify if a value is valid. + - Catch as many possible failures. + - Testing the fails is a way to make sure we follow the fail-fast + principle as much as possible. + +2. Every time you make a change to one of the different ways to run + Amadla you need to make sure it is mirrored to all the other ways + (`Jenkins <../Jenkinsfile>`__, `GitHub + Workflow <../.github/workflows/generate.yml>`__ –NOTE– Maybe Worflow + can just call Jenkin script instead of having a whole seperated CI/CD + –NOTE–, `containers <../containers/Makefile>`__ ???, or all the + `tools installed on the system itself <../Makefile>`__). +3. Documentation is crucial! Also it is helpful to add links to the + terms, accronyms, or concepts that might not be well known to the + average person. Let make it easy. +4. Testing. + + - With the four different ways to run Amadla. + - As many cloud environment as possible + - Basics: + + - `AWS `__ + - `Azure `__ + - `Google Cloud `__ + - `DigitalOcean `__ + - `Linode `__ + - `Vultr `__ + - `RackSpace `__ (or any other cloud + services that uses `OpenStack `__)) + - `CloudStack `__\ (??? - unsure) + + - Testing the other layers of automation. + +5. Following the rules of: + + - ```.editorconfig`` <../.editorconfig>`__ + - ```.gitattributes`` <../.gitattributes>`__. + +:information_source: Resources +------------------------------ + +- `Demystifying Ansible Automation Controller \| + GitHub `__ +- `Full Stack AWS Application Development \| + GitHub `__ +- `Cloud Native Observability \| + GitHub `__ +- `Go for DevOps \| GitHub `__ +- `Ansible for Real life Automation \| + GitHub `__ +- `HashiCorp Packer in Production \| + GitHub `__ + +Makefile +-------- + +Rules: - Uppercase is for global variables and lowercase is for a +specific target + + Might remove! + +:package: Containers +-------------------- + +:cook: Compose +~~~~~~~~~~~~~~ + +:military_helmet: Manage Secrets +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Many applications and services need secrets like username, password, TLS +keys, SSH keys, etc. + +Since Amadla uses compose, here is an example of a compose configuration +that uses secrets: + +.. code:: yaml + + secrets: + nextcloud_admin_password: + nextcloud_admin_user: + postgres_db: + postgres_password: + postgres_user: + +This example is taken from NextCloud. + +Podman and Docker have tools to manage secrets. + +.. code:: bash + + podman secret --help + +Results: + +:: + + Manage secrets + + Description: + Manage secrets + + Usage: + podman secret [command] + + Available Commands: + create Create a new secret + inspect Inspect a secret + ls List secrets + rm Remove one or more secrets + +:luggage: Module +---------------- + +Modules are found in ``apps.d``, ``servers.d`` and ``clouds.d``. + +:left_luggage: Adding a Module +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Most of Amadla is tightly integrated with Git with the usage of branches +and tags. It is not tightly attached to GitHub so you can easily use +another Git server. But using another code versioning system would be +very difficult. + +The structure needs to follow the standard so that Amadla is able to use +and integrate the module. + +:shinto_shrine: Jinja +~~~~~~~~~~~~~~~~~~~~~ + +Documentation: https://jinja.palletsprojects.com/en/3.1.x/templates/ + +:ocean: Git flow +~~~~~~~~~~~~~~~~ + +Amadla is tightly + +Ini: + +.. code:: bash + + git flow init + +.. + + For ``Version tag prefix? [] v`` + +Start a new feature: + +.. code:: bash + + git flow feature start pilot + +It will return: + +.. code:: bash + + git flow feature start pilot + Switched to a new branch 'feature/pilot' + + Summary of actions: + - A new branch 'feature/pilot' was created, based on 'develop' + - You are now on branch 'feature/pilot' + + Now, start committing on your feature. When done, use: + + git flow feature finish pilot + +Git push the new branch: + +.. code:: bash + + git push --set-upstream origin feature/pilot + +:gem: Applications +^^^^^^^^^^^^^^^^^^ + +Here is the list of the essentials for **applications**: - ``config/`` - +The ``config`` directory contains the configurations, most of it is +Jinja format. - ``compose.yml.j2`` - This is the Jinja template for the +container compose file that is used by the container engine (Podman or +Docker). If the application is installed - ``docs/`` (optional) - The +``docs`` directory contains the Markdown documentation. Only needed if +there are special actions, details, development instructions. - +``LICENSE`` - ``module.yml`` - - ``README.md`` - + +:paperclips: ``config/`` +'''''''''''''''''''''''' + +:paperclip: ``compose.yml.j2`` +'''''''''''''''''''''''''''''' + +:baggage_claim: ``module.yml`` +'''''''''''''''''''''''''''''' + +Lets start with an example: + +.. code:: yaml + + --- + version: 1 + module: + description: Vault - Secret tool. + authors: + - Jean-Nicolas Boulay (JN) + category: Application + tags: + - keys + - security + - password + - secrets + - storage + configuration: + network: + internal: + ports: + - protocol: tcp + internal: 8080 + external: 8080 + private: + locations: + - location: /vault + ports: + - protocol: tcp + internal: 8200 + external: + +- ``version`` - Is the first key to indicate the version of the + ``module.yml`` configuration file. +- ``module`` - Is to groupe all the module settings. +- ``description`` - The description of the module and what it is about. +- ``authors`` (optional) - You can list the authors of the module. +- ``type`` - … +- ``category`` - There are three categories you can use: + + - Application + - Server + - Cloud + +- ``tags`` - Is a list of words that help grouping modules. +- ``configuration`` - + + - ``network`` - + + - :red_circle: ``protected`` - This means that only services and + applications can be access internaly in the same server. + - :yellow_circle: ``internal`` - This indicates to Amadla that + this can only be access by internal services and applications. + + - ``locations`` - List of locations (in case you need multiple + paths). + - ``ports`` - List of ports and protocols that are used with + the entrypoint, firewall and container. + + - ``protocol`` (optional) - ``tcp`` or ``udp`` (default + ``tcp``). + - ``internal`` - This is the port **in** the container + (example: **8080**:80). + - ``external`` - This is the port **outside** of the + container (example: 8080:**80**). + + - :large_blue_circle: ``private`` - This indicates to Amadla that + the application can only be access via a VPN. + - :green_circle: ``public`` - This indicates to Amadla that the + application can be access via the web without the need of using + a VPN nor is it just internal. + ++-------+--------------+----------------+--------------+-------------+ +| Name | Local server | Internal | Need VPN for | Anyone | +| | access | server access | access | | ++=======+==============+================+==============+=============+ +| :r | :heavy | | | | +| ed_ci | _check_mark: | | | | +| rcle: | | | | | +| prot | | | | | +| ected | | | | | ++-------+--------------+----------------+--------------+-------------+ +| :yell | :heavy | :hea | | | +| ow_ci | _check_mark: | vy_check_mark: | | | +| rcle: | | | | | +| int | | | | | +| ernal | | | | | ++-------+--------------+----------------+--------------+-------------+ +| :lar | :heavy | :hea | :heavy | | +| ge_bl | _check_mark: | vy_check_mark: | _check_mark: | | +| ue_ci | | | | | +| rcle: | | | | | +| pr | | | | | +| ivate | | | | | ++-------+--------------+----------------+--------------+-------------+ +| :gre | :heavy | :hea | :heavy | :heavy_ | +| en_ci | _check_mark: | vy_check_mark: | _check_mark: | check_mark: | +| rcle: | | | | | +| p | | | | | +| ublic | | | | | ++-------+--------------+----------------+--------------+-------------+ + +:open_book: ``README.md`` +''''''''''''''''''''''''' + +:: + + # Plugin Name + Application Plugin Name (link to the website of the application/service). + + ![Screenshot](http://url_to_project_screenshot) This is optional. + + The screenshot is practicle if you have a web interface that communicates what the application is about. + + ## How to use + ... + + ## Screenshots + This section is optional, but encouraged if one screenshot doesn't tell the whole story. Just a list of images, one per line. We do the resizing, so use actual size screenshots. + + ![Screenshot 1](http://url_to_project_screenshot) + ![Screenshot 2](http://url_to_project_screenshot) + ![Screenshot 3](http://url_to_project_screenshot) + ![Screenshot 4](http://url_to_project_screenshot) + + ## Arbitrary section + This is an arbitrary section. You can have as many of these as you want. + Some arbitrary section examples: + + * FAQ + * Notes + * Misc + * Known issues + + The name is up to you, but remember to keep it meaningful, short and simple. If it is very verbose and detailed please use the `docs/` directory. Arbitrary sections are always optional. + +Server +^^^^^^ + +The server configurations use `Ansible `__ to +install all the packages and other components that are needed. It also +takes care of all the settings of SELinux and other Linux +configurations. + +**Environment variables:** - ``USER_USERNAME`` - +``USER_SERVER_PASSWORD`` + +Cloud +^^^^^ + +The cloud configurations use `Packer `__\ … + +Image Builder +~~~~~~~~~~~~~ + +Here is the bash script of the container that runs the builder: + +.. code:: bash + + #!/usr/bin/env bash + + podman run --rm -it \ + -v /etc/localtime:/etc/localtime:ro \ + -v ./entry.sh:/home/entry.sh \ + -v ./plugins/packer-builder-vultr:/root/.packer.d/plugins/packer-builder-vultr \ + -v ./plugins/packer-builder-vultr:/bin/packer-builder-vultr \ + -v ./clouds.d/:/home/clouds.d/ \ + -v ./ansible/base/:/home/ansible/ \ + -v ./.vault:/home/.vault \ + -v ~/.ssh/id_ed25519.pub:/home/.ssh/id_ed25519.pub \ + -v ~/.ssh/id_ed25519:/home/.ssh/id_ed25519 \ + -e "GET_INFO=${GET_INFO}" \ + -e "CLOUD_SERVICE=${CLOUD_SERVICE}" \ + -e "VAULT_ADDRESS=${VAULT_ADDRESS}" \ + -e "USER_ID=${USER_ID}" \ + -e "USER_USERNAME=jn" \ + -e "USER_SERVER_PASSWORD=amadlatest" \ + -e "SERVICE_PROFILE=default" \ + -e "PACKER_LOG=${PACKER_LOG}" \ + --net host \ + --name image-builder \ + image-builder + +Volumes +^^^^^^^ + +- ``/etc/localtime:/etc/localtime:ro`` - +- ``./entry.sh:/home/entry.sh`` - +- ``./plugins/packer-builder-vultr:/root/.packer.d/plugins/packer-builder-vultr`` +- ``./plugins/packer-builder-vultr:/bin/packer-builder-vultr`` +- ``./clouds.d/:/home/clouds.d/`` - +- ``./ansible/base/:/home/ansible/`` - +- ``./.vault:/home/.vault`` - +- ``~/.ssh/id_ed25519.pub:/home/.ssh/id_ed25519.pub`` - +- ``~/.ssh/id_ed25519:/home/.ssh/id_ed25519`` - + +Environment variables +^^^^^^^^^^^^^^^^^^^^^ + +- ``GET_INFO=${GET_INFO}`` - It’s a call for info about +- ``CLOUD_SERVICE=${CLOUD_SERVICE}`` - Pass the name of the cloud you + want to execute (maybe change to a *volume*\ …) +- ``VAULT_ADDRESS=${VAULT_ADDRESS}`` - The Vault address (in local + environment: http://127.0.0.1:1234/). The value comes from Vault + after it starts, you will only need to copy paste the command given + by it. +- ``USER_ID=${USER_ID}`` - [STRIKEOUT:This is for storing and + retrieving the secrets of a particular user (this is useful if you + have multiple users using Amadla)] **DEPRECATED** Instead you will + use: `Userpass \| + Vault `__ + + `Identity: Entities and Groups \| + Vault `__ + + `Manage Authentication Methods \| + Vault `__ +- ``USER_USERNAME=jn`` - It is the username for the SSH of the server + (needs a better name… Seriously!) NOTE -> Used in Ansible +- ``USER_SERVER_PASSWORD=amadlatest`` - Password for the SSH of the + server (needs also a better name… Very serious!) -> Used in Ansible +- ``SERVICE_PROFILE=default`` - No idea +- ``PACKER_LOG=${PACKER_LOG}`` - Log level?? Maybe… No idea + +``config/containers/image-builder/entry.sh`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Is the container main entry point bash script +- It also calls with ``curl`` the Vault server to get the secrets + needed to connect to the cloud service + +**Vault path:** + +``"${VAULT_ADDRESS}/${VAULT_API_VERSION}/secret/data/${CLOUD_SERVICE}/credentials/${SERVICE_PROFILE}"`` + +- ``VAULT_ADDRESS`` - Is the same value that is pass by the ``run.sh`` + script +- ``VAULT_API_VERSION`` - (Maybe added to ``run.sh``??) - For now it is + hardcoded in the ``entry.sh`` script it is required in the HTTP API + enpoint path +- ``CLOUD_SERVICE`` - Since you can have multiple cloud services the + storage in Vault is devided by cloud providers +- ``SERVICE_PROFILE`` - Not sure why it’s called that and it’s also + because they might be different credentials based on what you are + using it from e.g. Prod, Staging, etc + +Step by step +~~~~~~~~~~~~ + +- ``entry.sh`` - The entrypoint for the container +- Call to Vault to get the secrets to connect to the cloud service API +- ``build.sh`` - Simple bash function that calls another script named + ``creds.sh`` and then calls (with the credential from ``creds.sh``) + the secrets needed to execute ``packer build`` that will execute the + packer script +- ``creds.sh`` - Calls Vault to get secret uses the bash function in + the ``entry.sh`` and populates a environment variable that will later + be used as source of the secret or secrets to communicated with the + API of the cloud service +- ``.base.pkr.hcl`` - The Packer script +- Ansible is called inside the Packer script (depending on the server + type you configure it will load the one you set in the configuration + file) + +.. + + @TODO: Add Terraform… For now this is only for generating an server + image. + +Unit Testing +------------ + +The command to run the Python unit test: + +.. code:: bash + + python3 -m unittest tests/test_*.py + +The unit tests are found ``./tests/`` directory. diff --git a/docs/source/en/how-it-works.rst b/docs/source/en/how-it-works.rst new file mode 100644 index 0000000..58d8c00 --- /dev/null +++ b/docs/source/en/how-it-works.rst @@ -0,0 +1,2 @@ +How It Works +========================== diff --git a/docs/source/en/index.rst b/docs/source/en/index.rst new file mode 100644 index 0000000..6b77336 --- /dev/null +++ b/docs/source/en/index.rst @@ -0,0 +1,29 @@ +Welcome to Amadla's CLI documentation! +=================================== + +**Amadla** (/ah-mah-dlah/) is a set of :abbr:`IaC (Infrastructure as Code)` tools to help deploy and manage various cloud environments, dedicated servers, and on-premise systems. + +*Amadla is a Zulu word meaning "power" or "strength".* + +.. attention:: + + This project is under active development. + +.. image:: https://raw.githubusercontent.com/AmadlaOrg/AmadlaOrg.github.io/master/assets/android-chrome-192x192.png + :target: https://amadla.org + :align: center + :alt: Amadla Logo + +Contents +-------- + +.. toctree:: + + quickstart + setup + how-it-works + secrets-management + ci-cd + application-compatibility + apps-d + dev diff --git a/docs/source/en/quickstart.rst b/docs/source/en/quickstart.rst new file mode 100644 index 0000000..f9d4981 --- /dev/null +++ b/docs/source/en/quickstart.rst @@ -0,0 +1,22 @@ +Quickstart +========== + +These are two ways to start quickly with Amadla CLI. + +For more details, see :ref:`setup`. + +Development environment +----------------------- + +.. code-block:: bash + + poetry install + poetry run amadla + +Production environment +---------------------- + +.. code-clock:: bash + + poetry install --no-dev + amadla diff --git a/docs/source/en/setup.rst b/docs/source/en/setup.rst new file mode 100644 index 0000000..1a45d12 --- /dev/null +++ b/docs/source/en/setup.rst @@ -0,0 +1,2 @@ +Setup +============== diff --git a/docs/source/fr/README.rst b/docs/source/fr/README.rst new file mode 100644 index 0000000..f67e3eb --- /dev/null +++ b/docs/source/fr/README.rst @@ -0,0 +1,2 @@ +Docs \| Amadla CE +============================= diff --git a/docs/source/fr/ci-cd.rst b/docs/source/fr/ci-cd.rst new file mode 100644 index 0000000..a1fe45f --- /dev/null +++ b/docs/source/fr/ci-cd.rst @@ -0,0 +1,2 @@ +CI/CD +========= diff --git a/docs/source/fr/dev.rst b/docs/source/fr/dev.rst new file mode 100644 index 0000000..2c0a448 --- /dev/null +++ b/docs/source/fr/dev.rst @@ -0,0 +1,2 @@ +Dev +========================= diff --git a/docs/source/fr/how-it-works.rst b/docs/source/fr/how-it-works.rst new file mode 100644 index 0000000..58d8c00 --- /dev/null +++ b/docs/source/fr/how-it-works.rst @@ -0,0 +1,2 @@ +How It Works +========================== diff --git a/docs/source/fr/index.rst b/docs/source/fr/index.rst new file mode 100644 index 0000000..1ab1622 --- /dev/null +++ b/docs/source/fr/index.rst @@ -0,0 +1,26 @@ +Welcome to Amadla's CLI documentation! +=================================== + +**Amadla** (/ah-mah-dlah/) is a set of :abbr:`IaC (Infrastructure as Code)` tools to help deploy and manage various cloud environments, dedicated servers, and on-premise systems. + +*Amadla is a Zulu word meaning "power" or "strength".* + +.. attention:: + + This project is under active development. + +.. image:: https://raw.githubusercontent.com/AmadlaOrg/AmadlaOrg.github.io/master/assets/android-chrome-192x192.png + :target: https://amadla.org + :align: center + :alt: Amadla Logo + +Contents +-------- + +.. toctree:: + + quickstart + setup + how-it-works + ci-cd + dev diff --git a/docs/source/fr/quickstart.rst b/docs/source/fr/quickstart.rst new file mode 100644 index 0000000..f9d4981 --- /dev/null +++ b/docs/source/fr/quickstart.rst @@ -0,0 +1,22 @@ +Quickstart +========== + +These are two ways to start quickly with Amadla CLI. + +For more details, see :ref:`setup`. + +Development environment +----------------------- + +.. code-block:: bash + + poetry install + poetry run amadla + +Production environment +---------------------- + +.. code-clock:: bash + + poetry install --no-dev + amadla diff --git a/docs/source/fr/setup.rst b/docs/source/fr/setup.rst new file mode 100644 index 0000000..1a45d12 --- /dev/null +++ b/docs/source/fr/setup.rst @@ -0,0 +1,2 @@ +Setup +============== diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..861d450 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,9 @@ +Amadla Docs +=========== + +.. toctree:: + :maxdepth: 2 + :caption: Language Versions: + + en/index + fr/index diff --git a/pyproject.toml b/pyproject.toml index 55b7b99..0e55d82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ classifiers=[ packages = [{include='amadlacli', from='.'}] [tool.poetry.scripts] -amadlacli = 'amadlacli.cli:main' +amadla = 'amadlacli.cli:cli' [tool.poetry.dependencies] python = "^3.12.0" diff --git a/tests/test_app.py b/tests/test_app.py new file mode 100755 index 0000000..bd85db7 --- /dev/null +++ b/tests/test_app.py @@ -0,0 +1,43 @@ +""" +Amadla python management cli application unit test. + +(C) 2024 Amadla. All rights reserved. +Released under MIT License +""" + +import unittest +from amadlacli.app import APP + +# https://calmcode.io/typer/test.html +#from typer.testing import CliRunner + +#runner = CliRunner() + + +class TestAPP(unittest.TestCase): + """ + Test application information. + """ + + def setUp(self): + """ + Set up the variables for the following tests. + """ + self.app_name = 'Amadla CLI' + self.version = '1.0.0' + + def test_name(self): + """ + Make sure it has the name of the application. + """ + self.assertEqual(APP().name(), self.app_name, "incorrect value") + + def test_version(self): + """ + Make sure it has the version of the application. + """ + self.assertEqual(APP().version(), self.version, "incorrect value") + + +if __name__ == '__main__': + unittest.main()