├── .gitignore ├── .gitlab-ci.yml ├── DEVELOP.md ├── LICENSE ├── README.md ├── adeploy ├── __init__.py ├── common │ ├── __init__.py │ ├── args.py │ ├── colors.py │ ├── deployment.py │ ├── errors.py │ ├── gopass.py │ ├── helpers.py │ ├── jinja │ │ ├── __init__.py │ │ ├── dict.py │ │ ├── env.py │ │ ├── filters.py │ │ └── globals.py │ ├── kubectl.py │ ├── logging.py │ ├── provider.py │ ├── secret.py │ ├── version.py │ └── yaml │ │ ├── __init__.py │ │ ├── find.py │ │ ├── labels.py │ │ ├── probes.py │ │ ├── resources.py │ │ └── update.py ├── main.py ├── providers │ ├── __init__.py │ ├── helm │ │ ├── README.md │ │ ├── __init__.py │ │ ├── common │ │ │ ├── __init__.py │ │ │ ├── helm.py │ │ │ ├── helm_output.py │ │ │ └── helm_provider.py │ │ ├── deployer.py │ │ ├── renderer.py │ │ ├── tester.py │ │ └── watcher.py │ └── jinja │ │ ├── README.md │ │ ├── __init__.py │ │ ├── deployer.py │ │ ├── renderer.py │ │ ├── tester.py │ │ └── watcher.py └── steps │ ├── __init__.py │ ├── config.py │ ├── deploy.py │ ├── render.py │ ├── test.py │ └── watch.py ├── docs ├── assets │ ├── css │ │ ├── asciinema-player.css │ │ ├── badges.css │ │ ├── docstrings.css │ │ └── footer.css │ ├── download.sh │ ├── img │ │ └── awesome-logo.png │ └── js │ │ ├── asciinema-init.js │ │ └── asciinema-player.min.js ├── common │ ├── _more.md │ ├── filters.md │ ├── functions.md │ ├── includes.md │ ├── index.md │ ├── labels.md │ ├── macros.md │ ├── probes.md │ ├── resource-limits.md │ └── secrets.md ├── helm.cast ├── helm │ ├── helm-deploy.cast │ ├── helm-render.cast │ ├── helm-test.cast │ ├── hooks.md │ └── index.md ├── hooks │ ├── asciinema.py │ └── badges.py ├── index.md ├── install.md ├── jinja.cast ├── jinja │ ├── index.md │ ├── jinja-deploy.cast │ ├── jinja-render.cast │ └── jinja-test.cast ├── overrides │ └── partials │ │ └── copyright.html └── usage.md ├── examples ├── .exclude-from-test ├── helm │ ├── 001-quickstart │ │ ├── README.md │ │ ├── build │ │ │ └── helm │ │ │ │ ├── charts │ │ │ │ └── hello-world │ │ │ │ │ ├── .helmignore │ │ │ │ │ ├── Chart.yaml │ │ │ │ │ ├── README.md │ │ │ │ │ ├── templates │ │ │ │ │ ├── NOTES.txt │ │ │ │ │ ├── _helpers.tpl │ │ │ │ │ ├── deployment.yaml │ │ │ │ │ ├── service.yaml │ │ │ │ │ └── serviceaccount.yaml │ │ │ │ │ └── values.yaml │ │ │ │ └── playground │ │ │ │ └── hello-world │ │ │ │ └── test │ │ │ │ ├── manifest.yml │ │ │ │ └── values.yml │ │ ├── defaults.yml │ │ └── namespaces │ │ │ └── playground │ │ │ └── test.yml │ └── 002-hooks │ │ ├── README.md │ │ ├── build │ │ └── helm │ │ │ ├── charts │ │ │ └── hello-world │ │ │ │ ├── .helmignore │ │ │ │ ├── Chart.yaml │ │ │ │ ├── README.md │ │ │ │ ├── templates │ │ │ │ ├── NOTES.txt │ │ │ │ ├── _helpers.tpl │ │ │ │ ├── deployment.yaml │ │ │ │ ├── service.yaml │ │ │ │ └── serviceaccount.yaml │ │ │ │ └── values.yaml │ │ │ └── playground │ │ │ └── hello-world │ │ │ └── test │ │ │ ├── manifest.yml │ │ │ └── values.yml │ │ ├── defaults.yml │ │ ├── hooks │ │ ├── patch.sh │ │ └── patches.d │ │ │ └── 001-add-env.patch │ │ └── namespaces │ │ └── playground │ │ └── test.yml └── jinja │ ├── 001-general-structure │ ├── .exclude-from-test │ ├── README.md │ ├── build │ │ └── jinja │ │ │ └── playground │ │ │ └── 001-general-structure │ │ │ ├── prod │ │ │ ├── deployment.yml │ │ │ └── job.yml │ │ │ └── test │ │ │ ├── deployment.yml │ │ │ └── job.yml │ ├── defaults.yml │ ├── namespaces │ │ └── playground │ │ │ ├── prod.yml │ │ │ └── test.yml │ └── templates │ │ ├── deployment.yml │ │ └── job.yml │ ├── 002-secrets-ingress │ ├── README.md │ ├── build │ │ └── jinja │ │ │ ├── 002-secrets-ingress │ │ │ └── secrets │ │ │ │ └── playground │ │ │ │ ├── prod │ │ │ │ ├── secret-6e1adb2c4c075e35335e851dd6ebc5f0f7397a80 │ │ │ │ ├── secret-7e33ba97416ba4d45b6ce4c6c68b6aace36eacc5 │ │ │ │ └── secret-e5e0c551a537d65bcea7c18eb47badaf9c09c349 │ │ │ │ └── test │ │ │ │ ├── secret-7929a442fae0ceee9eef9558a9a2ef02cc9d4421 │ │ │ │ ├── secret-dcf2a6e7bd78ee395f73f6434b19a9044790c00a │ │ │ │ └── secret-f310a9ad786b3fb5f7160436346e69795693b951 │ │ │ └── playground │ │ │ └── 002-secrets-ingress │ │ │ ├── prod │ │ │ ├── deployment.yml │ │ │ └── ingress.yml │ │ │ └── test │ │ │ ├── deployment.yml │ │ │ └── ingress.yml │ ├── defaults.yml │ ├── namespaces │ │ └── playground │ │ │ ├── prod.yml │ │ │ ├── secrets │ │ │ ├── domain_prod │ │ │ │ ├── mydomain.com.crt │ │ │ │ └── mydomain.com.key │ │ │ ├── domain_test │ │ │ │ ├── mydomain.com.crt │ │ │ │ └── mydomain.com.key │ │ │ ├── my_secret_prod │ │ │ └── my_secret_test │ │ │ └── test.yml │ └── templates │ │ ├── deployment.yml │ │ └── ingress.yml │ ├── 002-secrets │ ├── README.md │ ├── build │ │ └── jinja │ │ │ ├── 002-secrets │ │ │ └── secrets │ │ │ │ └── playground │ │ │ │ ├── prod │ │ │ │ ├── secret-7e33ba97416ba4d45b6ce4c6c68b6aace36eacc5 │ │ │ │ └── secret-e5e0c551a537d65bcea7c18eb47badaf9c09c349 │ │ │ │ └── test │ │ │ │ ├── secret-7929a442fae0ceee9eef9558a9a2ef02cc9d4421 │ │ │ │ └── secret-f310a9ad786b3fb5f7160436346e69795693b951 │ │ │ └── playground │ │ │ └── 002-secrets │ │ │ ├── prod │ │ │ └── deployment.yml │ │ │ └── test │ │ │ └── deployment.yml │ ├── defaults.yml │ ├── namespaces │ │ └── playground │ │ │ ├── prod.yml │ │ │ ├── secrets │ │ │ ├── my_secret_prod │ │ │ └── my_secret_test │ │ │ └── test.yml │ └── templates │ │ └── deployment.yml │ ├── 003-include │ ├── README.md │ ├── build │ │ └── jinja │ │ │ └── playground │ │ │ └── 003-include │ │ │ ├── prod │ │ │ ├── common │ │ │ │ └── configmap.yml │ │ │ ├── nginx │ │ │ │ └── deployment.yml │ │ │ └── redis │ │ │ │ └── deployment.yml │ │ │ └── test │ │ │ ├── common │ │ │ └── configmap.yml │ │ │ ├── nginx │ │ │ └── deployment.yml │ │ │ └── redis │ │ │ └── deployment.yml │ ├── defaults.yml │ ├── namespaces │ │ └── playground │ │ │ ├── prod.yml │ │ │ └── test.yml │ └── templates │ │ ├── common │ │ ├── __affinity.yml │ │ ├── __env.yml │ │ └── configmap.yml │ │ ├── files │ │ ├── conf.d │ │ │ ├── alpha.json │ │ │ └── beta.json │ │ └── nginx.conf │ │ ├── nginx │ │ └── deployment.yml │ │ └── redis │ │ └── deployment.yml │ ├── 004-probes │ ├── README.md │ ├── build │ │ └── jinja │ │ │ └── playground │ │ │ └── 004-probes │ │ │ ├── prod │ │ │ ├── nginx │ │ │ │ └── deployment.yml │ │ │ └── redis │ │ │ │ └── deployment.yml │ │ │ └── test │ │ │ ├── nginx │ │ │ └── deployment.yml │ │ │ └── redis │ │ │ └── deployment.yml │ ├── defaults.yml │ ├── namespaces │ │ └── playground │ │ │ ├── prod.yml │ │ │ └── test.yml │ └── templates │ │ ├── nginx │ │ └── deployment.yml │ │ └── redis │ │ └── deployment.yml │ ├── 005-labels │ ├── README.md │ ├── build │ │ └── jinja │ │ │ └── playground │ │ │ └── 005-labels │ │ │ ├── prod │ │ │ └── deployment.yml │ │ │ └── test │ │ │ └── deployment.yml │ ├── defaults.yml │ ├── namespaces │ │ └── playground │ │ │ ├── prod.yml │ │ │ └── test.yml │ └── templates │ │ └── deployment.yml │ ├── 006-nested-labels │ ├── README.md │ ├── build │ │ └── jinja │ │ │ └── playground │ │ │ └── 006-nested-labels │ │ │ ├── prod │ │ │ └── deployment.yml │ │ │ └── test │ │ │ └── deployment.yml │ ├── defaults.yml │ ├── namespaces │ │ └── playground │ │ │ ├── prod.yml │ │ │ └── test.yml │ └── templates │ │ └── deployment.yml │ └── 007-resources │ ├── README.md │ ├── build │ └── jinja │ │ └── playground │ │ └── 007-resources │ │ ├── prod │ │ ├── nginx │ │ │ └── deployment.yml │ │ └── redis │ │ │ └── deployment.yml │ │ └── test │ │ ├── nginx │ │ └── deployment.yml │ │ └── redis │ │ └── deployment.yml │ ├── defaults.yml │ ├── namespaces │ └── playground │ │ ├── prod.yml │ │ └── test.yml │ └── templates │ ├── nginx │ └── deployment.yml │ └── redis │ └── deployment.yml ├── mkdocs.yml ├── pyproject.toml ├── requirements.txt ├── runner.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | /build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | .hypothesis/ 49 | .pytest_cache/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | db.sqlite3 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .env 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | env.bak/ 92 | venv.bak/ 93 | 94 | # Spyder project settings 95 | .spyderproject 96 | .spyproject 97 | 98 | # Rope project settings 99 | .ropeproject 100 | 101 | # mkdocs documentation 102 | /site 103 | 104 | # mypy 105 | .mypy_cache/ 106 | 107 | .idea/ 108 | -------------------------------------------------------------------------------- /DEVELOP.md: -------------------------------------------------------------------------------- 1 | # adeploy 2 | 3 | This doc is for developers. 4 | 5 | ## Setup for development usage 6 | 7 | Get the source code: 8 | 9 | ```bash 10 | $ git clone https://gitlab.awesome-it.de/tools/adeploy.git ~/path/to/atracker 11 | ``` 12 | Setup a virtualenv using `Python3` and activate it: 13 | 14 | ```bash 15 | $ virtualenv -p python3 ~/.virtualenvs/adeploy 16 | $ source ~/.virtualenvs/adeploy/bin/activate 17 | # alternatively install it in your project directory 18 | $ cd ~/path/to/adeploy 19 | $ virtualenv -p python3 env3 20 | $ source env3/bin/activate 21 | (adeploy)$ 22 | ``` 23 | 24 | Install requirements: 25 | 26 | ```bash 27 | (adeploy)$ pip install -r requirements.txt 28 | ``` 29 | #### Usage while developing 30 | 31 | There are two ways you can invoke adeploy while developing (i.e. while in your virtualenv). 32 | 33 | 1. There is a wrapper that can be used to run it from your PATH. This is only intended for quick usage while development, 34 | not as a binary (i.e. don't link to it or anything; have a look at the next topic). 35 | ```bash 36 | $ ./runner.py 37 | ``` 38 | 39 | 2. The second way is via pip. Pip can install a python package in edit-mode. If you do this all code changes will 40 | immediately take effect. To skip the virtualenv, you can append "--user" to pip in order to install adeploy using the user scheme. 41 | ```bash 42 | $ cd ~/path/to/adeploy 43 | $ pip install [--user] -e . 44 | $ adeploy 45 | # make changes 46 | $ adeploy 47 | # new behaviour, changes take effect immediately. 48 | ```` 49 | 50 | ## Writing Documentation 51 | 52 | The docs are build via [MkDocs Material](https://squidfunk.github.io/mkdocs-material/), the markdown files are located in the `docs` subfolder. 53 | 54 | In order to create the docs, you need to install `mkdocs-material` and dependencies as follows: 55 | 56 | ```bash 57 | pipx install mkdocs-material 58 | pipx inject mkdocs-material beautifulsoup4 # Required for hooks/asciinema.py 59 | pipx inject mkdocs-material "mkdocstrings[python]" # Required to read docstrings from python files i.e. filters.py 60 | ``` 61 | 62 | Now you run the `mkdocs` live preview at http://127.0.0.1:8000/ as follows: 63 | 64 | ```bash 65 | mkdocs serve 66 | ``` 67 | 68 | Or generate static docs as: 69 | 70 | ```bash 71 | mkdocs build 72 | ``` 73 | 74 | ### Terminal records via `asciinema` 75 | 76 | Install `asciinema` as follows: 77 | 78 | ```bash 79 | pipx install asciinema 80 | ``` 81 | 82 | To record you terminal sessions, use the following: 83 | 84 | ```bash 85 | asciinema rec -c "bash --rcfile ~/.bashrc-asciinema" --rows 10 --cols 75 .cast 86 | ``` 87 | 88 | Make sure to set your `PS1` variable to `$ ` in your `~/.bashrc-asciinema`. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, awesome information technology GmbH 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # adeploy 2 | 3 | 4 | 5 | We build `adeploy`, an universal deployment tool for Kubernetes that supports rendering and deployment of lightweight 6 | Jinja templated k8s manifests and also Helm charts. 7 | 8 | We’ve added support for ... 9 | 10 | * using **Jinja variables** from per cluster, namespaces or release configuration 11 | * easy **secret management** based on [Gopass](https://github.com/gopasspw/gopass) or other command line based password managers 12 | * running deployment tests in **CI/CD pipelines** 13 | * **previewing** and **patching** upstream [Helm Charts](https://artifacthub.io/) before deploying 14 | * **extending** upstream Helm Charts with custom Jinja-templates manifests 15 | * handy templating for **labels, annotations, probes, resource limits** and other metadata 16 | 17 | ... and even more to make your daily work with k8s easier. 18 | 19 | 20 | 21 | ## Documentation & Support 22 | 23 | * `adeploy` is Open Source and hosted on GitHub: [https://github.com/awesome-it/adeploy](https://github.com/awesome-it/adeploy). 24 | * You can report issues on GitHub: [https://github.com/awesome-it/adeploy/issues](https://github.com/awesome-it/adeploy/issues). 25 | * Find the documentation at [https://awesome-it.de/docs/adeploy/latest](https://awesome-it.de/docs/adeploy/latest). 26 | 27 | ## Examples 28 | 29 | This is how you can render, test (preview) and deploy a Helm Chart: 30 | [![asciicast](https://asciinema.org/a/iToqBOzT8t2Up6x6lRhjF0sk2.svg)](https://asciinema.org/a/iToqBOzT8t2Up6x6lRhjF0sk2) 31 | 32 | Or you can render, test (preview) and deploy Jinja-templated manifests: 33 | [![asciicast](https://asciinema.org/a/li2ZqLa5pnh6pj1KWoOrUIHOe.svg)](https://asciinema.org/a/li2ZqLa5pnh6pj1KWoOrUIHOe) 34 | 35 | You'll find some examples in the [example](https://github.com/awesome-it/adeploy/tree/master/examples) directory. 36 | 37 | ## Getting Started 38 | 39 | 40 | 41 | You can find `adeploy` on [GitHub](https://github.com/awesome-it/adeploy). But it is recommended to install 42 | or upgrade [adeploy](https://pipy.org/project/adeploy) using `pip`: 43 | 44 | ```shell 45 | $ pip install adeploy 46 | ``` 47 | 48 | Or use [pipx](https://github.com/pypa/pipx) to install, upgrade and run `adeploy` in an isolated environment: 49 | 50 | ```shell 51 | $ pipx install adeploy 52 | $ pipx upgrade adeploy 53 | ``` 54 | 55 | You should now be able to run `adeploy` from the command line: 56 | 57 | ```shell 58 | adeploy --help 59 | ``` 60 | 61 | You can now start to use `adeploy`. 62 | 63 | 64 | 65 | See the [usage documentation](https://awesome-it.de/docs/adeploy/latest/usage/) to start using `adeploy`. 66 | 67 | ## Read More 68 | 69 | * https://awesome-it.de/2020/09/11/adeploy-an-universal-deployment-tool-for-kubernetes/ -------------------------------------------------------------------------------- /adeploy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/adeploy/__init__.py -------------------------------------------------------------------------------- /adeploy/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/adeploy/common/__init__.py -------------------------------------------------------------------------------- /adeploy/common/colors.py: -------------------------------------------------------------------------------- 1 | from colorama import Style, Fore 2 | 3 | _skip_colors = False 4 | 5 | 6 | def skip_colors(skip=True): 7 | global _skip_colors 8 | _skip_colors = skip 9 | 10 | 11 | def blue(text): 12 | return f'{Fore.BLUE}{text}{Fore.RESET}' if not _skip_colors else text 13 | 14 | 15 | def green(text): 16 | return f'{Fore.GREEN}{text}{Fore.RESET}' if not _skip_colors else text 17 | 18 | 19 | def red(text): 20 | return f'{Fore.RED}{text}{Fore.RESET}' if not _skip_colors else text 21 | 22 | 23 | def orange(text): 24 | return f'{Fore.YELLOW}{text}{Fore.RESET}' if not _skip_colors else text 25 | 26 | 27 | def gray(text): 28 | # Fore.Gray is not readable in some terminals. 29 | return f'{Fore.RESET}{text}' if not _skip_colors else text 30 | 31 | 32 | def bold(text): 33 | return f'{Style.BRIGHT}{text}{Style.NORMAL}' if not _skip_colors else text 34 | 35 | 36 | def red_bold(text): 37 | return bold(red(text)) 38 | 39 | 40 | def green_bold(text): 41 | return bold(green(text)) 42 | 43 | 44 | def blue_bold(text): 45 | return bold(blue(text)) 46 | 47 | 48 | def orange_bold(text): 49 | return bold(orange(text)) -------------------------------------------------------------------------------- /adeploy/common/errors.py: -------------------------------------------------------------------------------- 1 | class Error(Exception): 2 | """Base class for exceptions in this module.""" 3 | pass 4 | 5 | 6 | class InputError(Error): 7 | """Exception raised for errors in the user input.""" 8 | pass 9 | 10 | 11 | class RenderError(Error): 12 | """ Exception raised for errors in the renderer.""" 13 | pass 14 | 15 | 16 | class TestError(Error): 17 | """ Exception raised for errors in the tester.""" 18 | pass 19 | 20 | 21 | class DeployError(Error): 22 | """ Exception raised for errors in the tester.""" 23 | pass 24 | 25 | 26 | class WrongClusterError(Error): 27 | """ Exception raised if wrong cluster is targeted.""" 28 | pass 29 | 30 | class EmptySecretError(Error): 31 | """ Exception raised if a secret is empty.""" 32 | pass 33 | 34 | if __name__ == '__main__': 35 | pass 36 | -------------------------------------------------------------------------------- /adeploy/common/helpers.py: -------------------------------------------------------------------------------- 1 | import collections.abc 2 | import os 3 | import sys 4 | import pkgutil 5 | import importlib.util 6 | import subprocess 7 | import yaml 8 | 9 | from collections import namedtuple 10 | from adeploy import providers 11 | 12 | import adeploy.common.colors as colors 13 | import adeploy.common.jinja.env as jinja_env 14 | 15 | 16 | def get_submodules(pkg): 17 | modules = [] 18 | for module_finder, name, ispkg in pkgutil.iter_modules([os.path.dirname(pkg.__file__)]): 19 | module_spec = module_finder.find_spec(name) 20 | module = module_spec.loader.load_module() 21 | class_name = list(filter(lambda m: module.__name__ == m.lower(), dir(module)))[0] 22 | modules.append((module, class_name)) 23 | 24 | return modules 25 | 26 | 27 | def get_provider(name): 28 | return get_providers().get(name, None) 29 | 30 | 31 | def get_providers() -> dict: 32 | found = {} 33 | for module_finder, name, ispkg in pkgutil.iter_modules([os.path.dirname(providers.__file__)]): 34 | if ispkg: 35 | module_spec = module_finder.find_spec(name) 36 | module = module_spec.loader.load_module() 37 | found[name] = namedtuple('Provider', 'renderer tester deployer watcher')( 38 | renderer=getattr(module, 'Renderer'), 39 | tester=getattr(module, 'Tester'), 40 | deployer=getattr(module, 'Deployer'), 41 | watcher=getattr(module, 'Watcher') 42 | ) 43 | return found 44 | 45 | 46 | def get_defaults(defaults_file, deployment=None, log=None, template_values=None): 47 | env = jinja_env.create([defaults_file.parent], deployment=deployment, log=log) 48 | # Make best to load defaults 49 | template_values_default = { 50 | 'name': deployment.name if deployment else 'undefined', 51 | 'namespace': deployment.namespace if deployment else 'undefined', 52 | } 53 | return yaml.load(env.get_template(defaults_file.name).render(template_values if template_values else template_values_default), Loader=yaml.FullLoader) 54 | 55 | 56 | def run_command(log, cmd) -> subprocess.CompletedProcess: 57 | # Convert possible Pathes to strings 58 | cmd = [str(c) for c in cmd] 59 | log.debug(f'Executing command {colors.bold(" ".join(cmd))}') 60 | result = subprocess.run(cmd, capture_output=True, text=True) 61 | result.check_returncode() 62 | return result 63 | 64 | 65 | def dict_update_recursive(d: dict, u: dict) -> dict: 66 | if u is not None: 67 | for k, v in u.items(): 68 | if isinstance(v, collections.abc.Mapping): 69 | sub = {} 70 | if d and k in d and d[k] and len(d[k]) > 0: 71 | sub = d[k] 72 | d[k] = dict_update_recursive(sub, v) 73 | # We don't merge lists! List will be overwritten completely. 74 | #elif isinstance(v, list): 75 | # d[k] = (d[k] if k in d else []) + v 76 | else: 77 | d[k] = v 78 | return d -------------------------------------------------------------------------------- /adeploy/common/jinja/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/adeploy/common/jinja/__init__.py -------------------------------------------------------------------------------- /adeploy/common/jinja/dict.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | class JinjaDict(dict): 5 | 6 | delimiter = None 7 | 8 | def __init__(self, dict, delimiter: str = None): 9 | super().__init__(dict) 10 | if delimiter: 11 | self.delimiter = re.compile(delimiter) 12 | else: 13 | self.delimiter = re.compile('\.|:') 14 | 15 | def get(self, key, default=None): 16 | data = super().get(key) 17 | 18 | if data is None: 19 | data = self.get_path(key)\ 20 | 21 | if data is None: 22 | data = default 23 | 24 | return JinjaDict(data) if isinstance(data, dict) else data 25 | 26 | def get_path(self, key): 27 | data = None 28 | for sub_key in re.split(self.delimiter, key): 29 | if not data: 30 | data = super().get(sub_key) 31 | continue 32 | 33 | if sub_key not in data: 34 | return None 35 | 36 | data = data.get(sub_key) 37 | 38 | return data 39 | 40 | def get_dict(self): 41 | obj = {} 42 | for n, v in self.items(): 43 | obj[n] = v 44 | return obj -------------------------------------------------------------------------------- /adeploy/common/jinja/env.py: -------------------------------------------------------------------------------- 1 | from inspect import getmembers, isfunction, ismethod, getfile 2 | from logging import Logger 3 | from pathlib import Path 4 | from typing import List 5 | 6 | import jinja2 7 | 8 | import adeploy.common.jinja.globals as globals 9 | import adeploy.common.jinja.filters as filters 10 | 11 | 12 | def create(pathes: List[str or Path] = None, log: Logger = None, deployment=None, 13 | templates_dir=None) -> jinja2.Environment: 14 | env = jinja2.Environment( 15 | # This is to load macros from template dir and the parent dir 16 | loader=jinja2.FileSystemLoader([str(p) for p in pathes]), 17 | autoescape=jinja2.select_autoescape(['json']), 18 | # Add support for expressions statements, see https://stackoverflow.com/a/39858522/381166 19 | extensions=['jinja2.ext.do'], 20 | ) 21 | 22 | # Register filters from common.filters 23 | for name, func in [f for f in getmembers(filters) if isfunction(f[1])]: 24 | if log: 25 | log.debug(f'Registering filter "{name}" from "{getfile(func)}"') 26 | env.filters[name] = func 27 | 28 | register_globals(env, deployment, log, templates_dir) 29 | 30 | return env 31 | 32 | 33 | def register_globals(env: jinja2.Environment, deployment=None, log: Logger = None, templates_dir=None): 34 | handler = globals.Handler(env, deployment, log, templates_dir) 35 | for name, method in getmembers(handler, predicate=ismethod): 36 | 37 | if name == '__init__': 38 | continue 39 | 40 | if log: 41 | log.debug(f'Registering global function "{name}" ' + 42 | (f'for deployment "{str(deployment)}" ' if deployment else '') + 43 | f'from "{getfile(method)}"') 44 | 45 | env.globals.update({name: method}) 46 | 47 | # TODO: Legacy support, remove this since this can't be documented. 48 | for name, func_creator in [f for f in getmembers(globals) if isfunction(f[1])]: 49 | 50 | if '__' not in name: 51 | continue 52 | 53 | if log: 54 | log.debug(f'Registering global function "{name}" ' + 55 | (f'for deployment "{str(deployment)}" ' if deployment else '') + 56 | f'from "{getfile(func_creator)}"') 57 | 58 | env.globals.update( 59 | {name.split('__')[1]: func_creator(deployment, log=log, env=env, templates_dir=templates_dir)}) 60 | -------------------------------------------------------------------------------- /adeploy/common/logging.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from adeploy.common import colors 4 | 5 | 6 | def setup(args): 7 | colors.skip_colors(args.skip_colors) 8 | 9 | if args.debug: 10 | loglevel = logging.DEBUG 11 | else: 12 | loglevel = logging.INFO 13 | 14 | if args.logfile: 15 | logging.basicConfig(level=loglevel, filename=args.logfile, format=get_log_format(args, loglevel)) 16 | else: 17 | logging.basicConfig(level=loglevel, format=get_log_format(args, loglevel)) 18 | 19 | logging.getLogger("urllib3").setLevel(logging.WARNING) 20 | logging.getLogger("requests").setLevel(logging.WARNING) 21 | 22 | 23 | def get_logger(name: str = None): 24 | return logging.getLogger(name) 25 | 26 | 27 | def get_log_format(args, loglevel): 28 | 29 | if args.logfile: 30 | return '%(asctime)s %(levelname)-8s %(name)s %(message)s' 31 | 32 | if loglevel == logging.DEBUG: 33 | return '%(levelname)-8s ' + colors.bold('%(name)s') + ' %(message)s' 34 | 35 | return colors.bold('%(name)s') + ' %(message)s' -------------------------------------------------------------------------------- /adeploy/common/version.py: -------------------------------------------------------------------------------- 1 | from importlib.metadata import version, PackageNotFoundError 2 | from subprocess import Popen, PIPE 3 | 4 | 5 | def get_package_version(): 6 | try: 7 | return version('adeploy') 8 | except PackageNotFoundError: 9 | pass 10 | 11 | try: 12 | # Fallback to package name on test.pypi.org 13 | return version('adeploy_awesomeit') 14 | except PackageNotFoundError: 15 | pass 16 | 17 | 18 | def call_git_describe(abbrev=4): 19 | try: 20 | p = Popen(['git', 'describe', '--tags', '--abbrev=%d' % abbrev], 21 | stdout=PIPE, stderr=PIPE, universal_newlines=True) 22 | p.stderr.close() 23 | line = p.stdout.readlines()[0] 24 | return line.strip() 25 | 26 | except: 27 | return None 28 | 29 | 30 | def get_git_version(abbrev=4): 31 | # Try to get the current version using “git describe”. 32 | git_version = call_git_describe(abbrev) 33 | if git_version is None: 34 | print("Cannot find the version number!") 35 | return None 36 | 37 | # Remove potential git appendix 38 | return git_version.split('-')[0] 39 | -------------------------------------------------------------------------------- /adeploy/common/yaml/__init__.py: -------------------------------------------------------------------------------- 1 | from adeploy.common.yaml.update import update 2 | 3 | __all__ = ['update'] -------------------------------------------------------------------------------- /adeploy/common/yaml/find.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | 4 | def find(d, tags: Union[str,list]): 5 | 6 | if not d: 7 | return [] 8 | 9 | if isinstance(tags, str): 10 | tags = [tags] 11 | 12 | for tag in tags: 13 | if tag in d: 14 | yield d[tag] 15 | 16 | for k, v in d.items(): 17 | if isinstance(v, dict): 18 | for i in find(v, tags): 19 | yield i -------------------------------------------------------------------------------- /adeploy/common/yaml/labels.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | from adeploy.common.helpers import dict_update_recursive 3 | 4 | 5 | def update_labels(log, doc, deployment): 6 | 7 | # Skip if no default labels configuration was found 8 | default_labels = deployment.config.get('_labels', False) 9 | if default_labels: 10 | for label in find_labels(doc): 11 | dict_update_recursive(label, default_labels) 12 | 13 | 14 | def find_labels(doc: Union[list,dict], kind=None, labels=None): 15 | 16 | if labels is None: 17 | labels = [] 18 | 19 | if kind is None: 20 | kind = doc.get('kind') 21 | 22 | if isinstance(doc, list): 23 | for elem in doc: 24 | find_labels(elem, kind, labels) 25 | 26 | elif isinstance(doc, dict): 27 | for k in doc: 28 | v = doc[k] 29 | 30 | if k == 'metadata': 31 | 32 | # Create labels if they do not exist 33 | if not 'labels' in v: 34 | v['labels'] = {} 35 | 36 | labels.append(v.get('labels')) 37 | 38 | # Selectors in services 39 | elif kind.lower() == 'service' and k == 'spec' and v.get('selector', False): 40 | labels.append(v.get('selector')) 41 | 42 | # Match labels in deployments/statefulsets/daemonsets 43 | elif kind.lower() in ['deployment', 'statefulset', 'daemonset'] and k == 'selector': 44 | labels.append(v.get('matchLabels')) 45 | 46 | else: 47 | find_labels(v, kind, labels) 48 | 49 | return labels -------------------------------------------------------------------------------- /adeploy/common/yaml/probes.py: -------------------------------------------------------------------------------- 1 | import copy 2 | from adeploy.common import colors 3 | from adeploy.common.helpers import dict_update_recursive 4 | 5 | 6 | def update_probes(log, doc, deployment): 7 | 8 | # Skip if no default probes configuration was found 9 | default_probes = deployment.config.get('_probes', False) 10 | if default_probes: 11 | for type in ['readiness', 'liveness', 'startup']: 12 | probe = find_probe(doc, f'{type}Probe') 13 | if probe: 14 | doc_name = doc.get('metadata', {}).get('name', None) 15 | default_probes = copy.deepcopy(default_probes) 16 | default_probe = dict_update_recursive(default_probes.get(type, None), 17 | default_probes.get(doc_name, {}).get(type, None)) 18 | if default_probe: 19 | log.debug(f"...... Updating {colors.bold(type)} probe " 20 | f"for \"{colors.bold(doc_name)}\": {str(default_probe)}") 21 | 22 | for k, v in default_probe.items(): 23 | probe[to_camel_case(k)] = v 24 | 25 | 26 | def find_probe(doc, probe): 27 | if isinstance(doc, list): 28 | for elem in doc: 29 | x = find_probe(elem, probe) 30 | if x is not None: 31 | return x 32 | elif isinstance(doc, dict): 33 | for k in doc: 34 | v = doc[k] 35 | if k == probe: 36 | return v 37 | x = find_probe(v, probe) 38 | if x is not None: 39 | return x 40 | return None 41 | 42 | 43 | def to_camel_case(snake_str): 44 | components = snake_str.split('_') 45 | # We capitalize the first letter of each component except the first one 46 | # with the 'title' method and join them together. 47 | return components[0] + ''.join(x.title() for x in components[1:]) 48 | -------------------------------------------------------------------------------- /adeploy/common/yaml/resources.py: -------------------------------------------------------------------------------- 1 | import json 2 | from adeploy.common import colors 3 | from adeploy.common.yaml.find import find 4 | 5 | 6 | def update_resources(log, doc, deployment): 7 | 8 | default_resource = deployment.config.get('_resources', False) 9 | if default_resource: 10 | 11 | for containers in find(doc, ['containers', 'initContainers']): 12 | for container in containers: 13 | 14 | doc_name = doc.get('metadata').get('name') 15 | container_name = container.get('name') 16 | resources = container.get('resources', {}) 17 | container['resources'] = resources # Update in case of newly created resource object! 18 | 19 | log.debug(f'...... Updating limits and requests for {colors.blue(doc_name + "/" + container_name)} ...') 20 | for type in ['limits', 'requests']: 21 | 22 | r = {} 23 | 24 | # These are defaults and can be overwritten by the manifest 25 | r.update(default_resource.get(type, {})) 26 | r.update(default_resource.get(doc_name, {}).get(type, {})) 27 | 28 | # Add resources from the manifest 29 | r.update(resources.get(type, {})) 30 | 31 | # The following explicitly overwrites the values from the doc 32 | r.update(default_resource.get(doc_name, {}).get(container_name, {}).get(type, {})) 33 | 34 | resources[type] = r 35 | log.debug(f'......... Setting {type}: {json.dumps(r)}') 36 | -------------------------------------------------------------------------------- /adeploy/common/yaml/update.py: -------------------------------------------------------------------------------- 1 | from logging import Logger 2 | 3 | from adeploy.common.deployment import Deployment 4 | from adeploy.common.yaml.labels import update_labels 5 | from adeploy.common.yaml.probes import update_probes 6 | from adeploy.common.yaml.resources import update_resources 7 | from ruamel.yaml.comments import CommentedMap 8 | 9 | 10 | def update(log: Logger, data: CommentedMap, deployment: Deployment): 11 | update_probes(log, data, deployment) 12 | update_labels(log, data, deployment) 13 | update_resources(log, data, deployment) 14 | return data 15 | -------------------------------------------------------------------------------- /adeploy/main.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import logging 4 | import os 5 | import sys 6 | 7 | from colorama import init 8 | 9 | from . import steps 10 | from .common import colors 11 | from .common.args import parse, setup_parser 12 | from .common.errors import InputError, Error 13 | from .common.helpers import get_provider, get_submodules, get_providers 14 | from .common.logging import setup as setup_logging, get_logger 15 | from .common.kubectl import kubectl_init 16 | from .common.version import get_package_version 17 | 18 | log = get_logger('adeploy') 19 | 20 | 21 | def main(): 22 | 23 | if not os.getenv('CI', False): 24 | init(autoreset=True) 25 | 26 | parser = setup_parser() 27 | args, unknown_args = parse(parser) 28 | setup_logging(args) 29 | kubectl_init(args) 30 | module = None 31 | 32 | try: 33 | 34 | if args.list_providers: 35 | list_providers() 36 | sys.exit(0) 37 | 38 | if args.version: 39 | version = get_package_version() 40 | if version: 41 | print(version) 42 | sys.exit(0) 43 | else: 44 | print("0.0.0") 45 | sys.exit(1) 46 | 47 | # Load renderer from provider 48 | provider = get_provider(args.provider) 49 | 50 | if provider is None: 51 | log.error(colors.red(f'Cannot find supported provider type "{args.provider}". ') + 52 | f'Type "--providers" to get a list of supported providers.') 53 | sys.exit(1) 54 | 55 | # Execute steps 56 | for (module, class_name) in get_submodules(steps): 57 | getattr(module, class_name)(provider, args, unknown_args, logging.getLogger(f'adeploy.{class_name}')) 58 | 59 | except InputError as e: 60 | log.error(colors.red(colors.bold(f'Input error in module "{module}": {str(e)}'))) 61 | sys.exit(1) 62 | except Error as e: 63 | log.error(colors.red(colors.bold(f'Error in module "{module}": {str(e)}'))) 64 | sys.exit(1) 65 | 66 | parser.print_help() 67 | sys.exit(1) 68 | 69 | 70 | def list_providers(): 71 | log.info(colors.bold('Providers:')) 72 | for name, provider in get_providers().items(): 73 | description = provider.renderer.get_parser().format_help().split('\n').pop(0) 74 | log.info(colors.bold(colors.blue(name)) + ': ' + description) 75 | -------------------------------------------------------------------------------- /adeploy/providers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/adeploy/providers/__init__.py -------------------------------------------------------------------------------- /adeploy/providers/helm/README.md: -------------------------------------------------------------------------------- 1 | # Deployment Provider: Helm 2 | 3 | ## Structure 4 | 5 | ``` 6 | /mydeployment/ 7 | 8 | /mydeployment/chart 9 | /mydeployment/hooks 10 | 11 | /mydeployment/namespaces 12 | /mydeployment/namespaces/mynamespace/prod.yml 13 | /mydeployment/namespaces/mynamespace/test.yml 14 | 15 | /mydeployment/defaults.yml 16 | ``` 17 | 18 | * A Helm deployment consists of an optional `chart` folder containing a Helm chart, 19 | * a `default.yml` file i.e. containing versions and 20 | * a `namespaces` directory containing [deployment configuration for different namespaces and releases](../../README.md#Deployment Configurations). 21 | 22 | ### Charts 23 | 24 | The Helm chart in the `chart` folder (default value of `--chart-dir`) will be installed with variables for each namespace and deployment-release merged with the variables from `defaults.yml`.: 25 | 26 | ```bash 27 | $ adeploy -p helm render . [--chart-dir ./chart] 28 | ``` 29 | 30 | The chart name is given by the deployment name i.e. the folder name (here: `mydeployment`) or you specify another name using 31 | `--name` parameter. 32 | 33 | If no chart folder is given, an upstream chart can be automatically downloaded using `--repo-url URL` in the render step: 34 | 35 | ```bash 36 | $ adeploy [--name customer_chart_name] -p helm render . --repo-url https://chart.url 37 | ``` 38 | 39 | Chart repository URL, name and the chart version can be set in the `defaults.yml` (or `defaults/.yml`) for the appropriate deployments: 40 | 41 | ```yaml 42 | _chart: 43 | repo_url: https://chart.url 44 | name: chart-name 45 | version: 0.0.0 46 | ``` 47 | 48 | ### Hooks 49 | 50 | Since 0.4.0 adeploy executes scripts from the `/mydeployment/hooks` folder as: 51 | ```bash 52 | $ cd /mydeployment/hooks 53 | $ ./script.sh /mydeployment/build/helm/charts// 54 | ``` 55 | You can use this i.e. to patch Helm Charts without touching upstream repos for quick and dirty fixes. -------------------------------------------------------------------------------- /adeploy/providers/helm/__init__.py: -------------------------------------------------------------------------------- 1 | from .renderer import Renderer 2 | from .tester import Tester 3 | from .deployer import Deployer 4 | from .watcher import Watcher 5 | -------------------------------------------------------------------------------- /adeploy/providers/helm/common/__init__.py: -------------------------------------------------------------------------------- 1 | from .helm import * 2 | from .helm_output import * 3 | from .helm_provider import * -------------------------------------------------------------------------------- /adeploy/providers/helm/common/helm_output.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | class HelmOutput: 5 | 6 | info: dict = None 7 | status: str = None 8 | first_deployed: str = None 9 | last_deployed: str = None 10 | description: str = None 11 | chart: dict = None 12 | chart_version: str = None 13 | app_version: str = None 14 | 15 | def __init__(self, stdout): 16 | 17 | result = json.loads(stdout) 18 | self.info = result.get('info') 19 | self.status = self.info.get('status') 20 | self.first_deployed = self.info.get('first_deployed') 21 | self.last_deployed = self.info.get('last_deployed') 22 | self.description = self.info.get('description') 23 | 24 | self.chart = result.get('chart') 25 | self.chart_version = self.chart.get('metadata').get('version') 26 | self.app_version = self.chart.get('metadata').get('appVersion') -------------------------------------------------------------------------------- /adeploy/providers/helm/common/helm_provider.py: -------------------------------------------------------------------------------- 1 | from abc import ABC 2 | 3 | from adeploy.common.helpers import get_defaults 4 | from adeploy.common.provider import Provider 5 | 6 | 7 | class HelmProvider(Provider, ABC): 8 | def get_chart_dir(self): 9 | return self.build_dir.joinpath('charts').joinpath(self.name) 10 | 11 | def get_chart_version(self): 12 | defaults = get_defaults(self.get_defaults_file(), log=self.log) 13 | return defaults.get('_chart', {}).get('version', None) if defaults else None 14 | -------------------------------------------------------------------------------- /adeploy/providers/helm/watcher.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | 4 | from .common import HelmProvider 5 | 6 | 7 | class Watcher(HelmProvider): 8 | 9 | @staticmethod 10 | def get_parser(): 11 | parser = argparse.ArgumentParser(description='Helm v3 renderer for k8s manifests', 12 | usage=argparse.SUPPRESS) 13 | return parser 14 | 15 | def parse_args(self, args: dict): 16 | pass 17 | 18 | def run(self): 19 | 20 | self.log.error(f'Watch mode is not supported by the helm provider...') 21 | sys.exit(1) 22 | -------------------------------------------------------------------------------- /adeploy/providers/jinja/__init__.py: -------------------------------------------------------------------------------- 1 | from .renderer import Renderer 2 | from .tester import Tester 3 | from .deployer import Deployer 4 | from .watcher import Watcher -------------------------------------------------------------------------------- /adeploy/providers/jinja/deployer.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import glob 3 | import os.path 4 | 5 | from pathlib import Path 6 | from subprocess import CalledProcessError 7 | 8 | import yaml 9 | 10 | from adeploy.common import colors 11 | from adeploy.common.kubectl import kubectl_apply, parse_kubectrl_apply 12 | from adeploy.common.errors import DeployError 13 | from adeploy.common.provider import Provider 14 | 15 | 16 | class Deployer(Provider): 17 | 18 | @staticmethod 19 | def manifest_is_configmap(manifest_path) -> bool: 20 | try: 21 | with open(manifest_path, 'r') as f: 22 | deployment_data = yaml.safe_load(f.read()) 23 | return deployment_data.get('kind', '') == 'ConfigMap' 24 | except yaml.YAMLError as e: 25 | raise DeployError(f'Error parsing manifest file "{manifest_path}": {e}') 26 | 27 | 28 | @staticmethod 29 | def get_parser(): 30 | parser = argparse.ArgumentParser(description='Deploys k8s manifests written in Jinja', 31 | usage=argparse.SUPPRESS) 32 | return parser 33 | 34 | def parse_args(self, args: dict): 35 | return 36 | 37 | def deploy_manifest(self, manifest_path, prefix=''): 38 | try: 39 | result = kubectl_apply(self.log, manifest_path) 40 | parse_kubectrl_apply(self.log, result.stdout, prefix=prefix) 41 | 42 | except CalledProcessError as e: 43 | raise DeployError(f'Error in manifest dir "{manifest_path}": {e.stderr}') 44 | 45 | def run(self): 46 | 47 | self.log.debug(f'Working on deployment "{self.name}" ...') 48 | 49 | for deployment in self.load_deployments(): 50 | 51 | if not self.verify_current_cluster_is_last_cluster(deployment): 52 | continue 53 | 54 | self.log.info(f'Applying manifests for deployment "{colors.blue(deployment)}" in "{deployment.manifests_dir}" ...') 55 | 56 | if not deployment.manifests_dir.exists(): 57 | self.log.info(f'... skip deployment without manifests') 58 | continue 59 | 60 | files = [] 61 | for ext in ['yaml', 'yml']: 62 | files.extend(glob.glob(f'{deployment.manifests_dir}/**/*.{ext}', recursive=True)) 63 | 64 | configmap_files = [file for file in files if self.manifest_is_configmap(file)] 65 | non_configmap_files = [file for file in files if not self.manifest_is_configmap(file)] 66 | 67 | for manifest_path in configmap_files: 68 | self.deploy_manifest(manifest_path) 69 | 70 | for manifest_path in non_configmap_files: 71 | self.deploy_manifest(manifest_path) 72 | 73 | self.save_current_cluster_as_last_cluster(deployment) 74 | -------------------------------------------------------------------------------- /adeploy/providers/jinja/tester.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import glob 3 | import json 4 | import string 5 | 6 | from pathlib import Path 7 | from random import random 8 | from subprocess import CalledProcessError 9 | 10 | from adeploy.common import colors 11 | from adeploy.common.kubectl import kubectl_apply, parse_kubectrl_apply, kubectl_get_default_namespace, \ 12 | kubectl_set_default_namespace, kubectl_get_namespaces, kubectl_set_fake_namespace 13 | from adeploy.common.errors import TestError 14 | from adeploy.common.provider import Provider 15 | 16 | 17 | class Tester(Provider): 18 | @staticmethod 19 | def get_parser(): 20 | parser = argparse.ArgumentParser(description='Jinja tester for k8s manifests written in Jinja', 21 | usage=argparse.SUPPRESS) 22 | return parser 23 | 24 | def parse_args(self, args: dict): 25 | return 26 | 27 | def test_maifest(self, manifest_path, prefix=''): 28 | try: 29 | 30 | default_ns, fake_ns = kubectl_set_fake_namespace(self.log) 31 | manifests = kubectl_apply(self.log, manifest_path, dry_run='client', output='json') 32 | kubectl_set_default_namespace(self.log, default_ns) 33 | 34 | result = kubectl_apply(self.log, manifest_path, dry_run='server') 35 | parse_kubectrl_apply(self.log, result.stdout, manifests=json.loads(manifests.stdout), 36 | fake_ns=fake_ns, 37 | default_ns=default_ns, 38 | prefix=prefix) 39 | 40 | except CalledProcessError as e: 41 | raise TestError(f'Error in manifest dir "{manifest_path}": {e.stderr}') 42 | 43 | def run(self): 44 | 45 | self.log.debug(f'Working on deployment "{self.name}" ...') 46 | 47 | for deployment in self.load_deployments(): 48 | 49 | manifests_dir = Path(self.build_dir) \ 50 | .joinpath(deployment.namespace) \ 51 | .joinpath(self.name) \ 52 | .joinpath(deployment.release) 53 | 54 | self.log.info(f'Testing manifests for deployment "{colors.blue(deployment)}" in "{manifests_dir}" ...') 55 | 56 | files = [] 57 | for ext in ['yaml', 'yml']: 58 | files.extend(glob.glob(f'{manifests_dir}/**/*.{ext}', recursive=True)) 59 | 60 | for manifest_path in files: 61 | self.test_maifest(manifest_path) 62 | -------------------------------------------------------------------------------- /adeploy/steps/__init__.py: -------------------------------------------------------------------------------- 1 | from .watch import Watch 2 | from .render import Render 3 | from .test import Test 4 | from .deploy import Deploy 5 | from .config import Config 6 | -------------------------------------------------------------------------------- /adeploy/steps/config.py: -------------------------------------------------------------------------------- 1 | import json 2 | import logging 3 | import os 4 | import sys 5 | from pathlib import Path 6 | from adeploy.common import colors 7 | from adeploy.common.errors import TestError, Error, InputError 8 | 9 | 10 | class Config: 11 | 12 | def __init__(self, provider, args, config_args, log): 13 | self.args = args 14 | self.log = log 15 | 16 | if 'config' in self.args: 17 | for src_dir in self.args.src_dirs: 18 | 19 | # Only log errors if config goes to stdout 20 | if not self.args.config_out: 21 | self.log.setLevel(logging.WARNING) 22 | 23 | src_dir = os.path.realpath(src_dir) 24 | name = self.args.deployment_name or os.path.basename(src_dir) 25 | build_dir = Path(self.args.build_dir).joinpath(self.args.provider) 26 | 27 | if not os.path.isdir(src_dir): 28 | continue 29 | 30 | try: 31 | renderer = provider.renderer( 32 | name=name, 33 | src_dir=src_dir, 34 | build_dir=build_dir, 35 | namespaces_dir=self.args.namespaces_dir, 36 | defaults_path=self.args.defaults_path, 37 | args=self.args, 38 | log=self.log, 39 | **vars(provider.renderer.get_parser().parse_args(config_args))) 40 | 41 | config = {} 42 | for deployment in renderer.load_deployments(): 43 | config.update({deployment.release: deployment.config}) 44 | 45 | if not args.config_out: 46 | print(json.dumps(config)) 47 | else: 48 | with open(args.config_out, 'w+') as fd: 49 | json.dump(config, fd) 50 | fd.close() 51 | self.log.info(f'Namespace configurations stored to "{colors.bold(args.config_out)}"') 52 | 53 | except Error as e: 54 | self.log.error(colors.red(f'Unexpected error in source directory "{src_dir}":')) 55 | self.log.error(colors.red_bold(str(e))) 56 | sys.exit(1) 57 | 58 | sys.exit(0) 59 | 60 | 61 | if __name__ == '__main__': 62 | pass 63 | -------------------------------------------------------------------------------- /adeploy/steps/render.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from pathlib import Path 4 | 5 | from adeploy.common import colors 6 | from adeploy.common.errors import RenderError 7 | from adeploy.common.secret import Secret 8 | 9 | 10 | class Render: 11 | 12 | def __init__(self, provider, args, render_args, log): 13 | self.args = args 14 | self.log = log 15 | 16 | if 'render' in self.args: 17 | 18 | num_warnings = 0 19 | 20 | for src_dir in self.args.src_dirs: 21 | 22 | src_dir = os.path.realpath(src_dir) 23 | name = self.args.deployment_name or os.path.basename(src_dir) 24 | build_dir = Path(self.args.build_dir).joinpath(self.args.provider) 25 | 26 | if not os.path.isdir(src_dir): 27 | self.log.warning(colors.orange(f'"{src_dir}" is not a directory, skip')) 28 | num_warnings += 1 29 | continue 30 | 31 | try: 32 | renderer = provider.renderer( 33 | name=name, 34 | src_dir=src_dir, 35 | build_dir=build_dir, 36 | namespaces_dir=self.args.namespaces_dir, 37 | defaults_path=self.args.defaults_path, 38 | args=self.args, 39 | log=self.log, 40 | **vars(provider.renderer.get_parser().parse_args(render_args))) 41 | 42 | self.log.info( 43 | colors.green_bold('Rendering ') + colors.bold(src_dir) + ' in ' + 44 | colors.bold(self.args.build_dir) + ' using the provider ' + 45 | colors.bold(self.args.provider) 46 | ) 47 | 48 | renderer.run() 49 | 50 | # Clean and store secret info in build dir. 51 | # Note that this affects only secrets that have been registered in the previous 52 | # rendering. Secrets from deployments excluded by user filters are not stored and existing secrets 53 | # won't be removed. So any testing/deployment should also explicitly respect the user filters to 54 | # exclude secrets as well. 55 | Secret.clean_build_secrets(build_dir) 56 | for secret in Secret.get_registered(): 57 | secret.store(build_dir) 58 | 59 | except RenderError as e: 60 | self.log.error(colors.red(f'Render error in source directory "{src_dir}":')) 61 | self.log.error(colors.red_bold(str(e))) 62 | sys.exit(1) 63 | 64 | if num_warnings > 0: 65 | self.log.warning(colors.orange(f'Rendering finished with {num_warnings} warnings')) 66 | else: 67 | self.log.info(colors.green_bold(f'Rendering finished')) 68 | 69 | sys.exit(0) 70 | 71 | 72 | if __name__ == '__main__': 73 | pass 74 | -------------------------------------------------------------------------------- /docs/assets/css/badges.css: -------------------------------------------------------------------------------- 1 | .mdx-badge { 2 | border: 1px solid #999; 3 | color: black; 4 | border-radius: 5px; 5 | padding: 2px 4px; 6 | font-size: small; 7 | margin-right: 8px; 8 | } 9 | 10 | .mdx-badge .mdx-badge__icon { 11 | padding-right: 4px; 12 | } 13 | 14 | .mdx-badge--version .mdx-badge__icon { 15 | color: #1e96da; 16 | } 17 | .mdx-badge--provider .mdx-badge__icon { 18 | color: #60da1e; 19 | } -------------------------------------------------------------------------------- /docs/assets/css/docstrings.css: -------------------------------------------------------------------------------- 1 | /* 2 | There is no option to skip showing the source code of the complete referenced object (i.e. globals.GlobalsHandler) 3 | so we just hide the source code as a dirty workaround. 4 | */ 5 | .doc.doc-object .first > details.quote { 6 | display: none; 7 | } -------------------------------------------------------------------------------- /docs/assets/css/footer.css: -------------------------------------------------------------------------------- 1 | .awesome-footer { 2 | flex-grow: 1; 3 | display: flex; 4 | flex-direction: row; 5 | justify-content: space-between; 6 | align-items: center; 7 | } 8 | 9 | .awesome-footer img { 10 | height: 45px; 11 | } 12 | 13 | .awesome-footer > a { 14 | display: flex; 15 | } -------------------------------------------------------------------------------- /docs/assets/download.sh: -------------------------------------------------------------------------------- 1 | ASCIINEMA_PLAYER_VERSION=3.7.0 2 | 3 | wget https://github.com/asciinema/asciinema-player/releases/download/v${ASCIINEMA_PLAYER_VERSION}/asciinema-player.css -O css/asciinema-player.css 4 | wget https://github.com/asciinema/asciinema-player/releases/download/v${ASCIINEMA_PLAYER_VERSION}/asciinema-player.min.js -O js/asciinema-player.min.js 5 | -------------------------------------------------------------------------------- /docs/assets/img/awesome-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/docs/assets/img/awesome-logo.png -------------------------------------------------------------------------------- /docs/assets/js/asciinema-init.js: -------------------------------------------------------------------------------- 1 | function asciinema_create_player(src, element, options) { 2 | //console.log('asccinema_create_player', { src, element, options }) 3 | if (window.AsciinemaPlayer) { 4 | AsciinemaPlayer.create(src, element, options); 5 | } 6 | } -------------------------------------------------------------------------------- /docs/common/_more.md: -------------------------------------------------------------------------------- 1 | Hava a look at the [common topic](../common/index.md) for more `adeploy` features that can be used in both, Helm chart 2 | templates and Jinja deployment templates i.e. to manage labels, secrets, resource limits or to run automated deployment 3 | pipelines. -------------------------------------------------------------------------------- /docs/common/filters.md: -------------------------------------------------------------------------------- 1 | # Jinja Filters 2 | 3 | 4 | ::: adeploy.common.jinja.filters 5 | handler: python 6 | options: 7 | show_bases: false 8 | show_root_heading: false 9 | show_source: true 10 | -------------------------------------------------------------------------------- /docs/common/functions.md: -------------------------------------------------------------------------------- 1 | # Jinja Functions 2 | 3 | 4 | ::: adeploy.common.jinja.globals.Handler 5 | handler: python 6 | options: 7 | show_bases: false 8 | show_root_heading: false 9 | show_source: true 10 | -------------------------------------------------------------------------------- /docs/common/index.md: -------------------------------------------------------------------------------- 1 | # Common 2 | 3 | `adeploy` has useful features that can be used in both, Helm chart templates and Jinja deployment templates. 4 | 5 | ## [Secrets](secrets.md) 6 | --8<-- "docs/common/secrets.md:summary" 7 | 8 | ## [Includes](includes.md) 9 | --8<-- "docs/common/includes.md:summary" 10 | 11 | ## [Manage Labels](labels.md) 12 | --8<-- "docs/common/labels.md:summary" 13 | 14 | ## [Resource Limits](resource-limits.md) 15 | --8<-- "docs/common/resource-limits.md:summary" 16 | 17 | ## [Probes](probes.md) 18 | --8<-- "docs/common/probes.md:summary" 19 | 20 | ## Jinja Helpers 21 | 22 | Next to the features from above, you can use the complete Jinja templating support when creating Jinja deployment or 23 | Helm chart templates using `adeploy`. Please see the official [Jinja documentation](https://jinja.palletsprojects.com/) 24 | for details. 25 | 26 | Next to the full Jinja templating support, we've added some very useful functions and filters that can be used when 27 | creating Jinja deployment or Helm chart templates using `adeploy`: 28 | 29 | * [Jinja Functions](functions.md) 30 | * [Jinja Filters](filters.md) 31 | * [Jinja Macros](macros.md) -------------------------------------------------------------------------------- /docs/common/labels.md: -------------------------------------------------------------------------------- 1 | # Labels 2 | 3 | 4 | `adeploy` provides functions and mechanisms to create default and custom labels following best practises in a single 5 | place of your default or namespace/release configuration. 6 | 7 | 8 | ## Default Labels 9 | 10 | 11 | You can use the Jinja function [`create_labels()`](functions.md#create_labels) to create set of default labels plus 12 | additional labels that you can specify in your `defaults.yml` or namespace/release configuration as follows: 13 | 14 | ```{.yaml title="defaults.yml"} 15 | --8<-- "examples/jinja/005-labels/defaults.yml:create_labels" 16 | ``` 17 | 18 | In your Jinja deployment template, you can use the `labels` variable as follows: 19 | 20 | ```{.yaml title="deployment.yml" hl_lines="6 9 18"} 21 | --8<-- "examples/jinja/005-labels/templates/deployment.yml:use_labels" 22 | ``` 23 | 24 | See [`create_labels()`](functions.md#adpeloy.common.jinja.globals.Handler.create_labels) for usage and parameters. 25 | 26 | ### Nested Labels 27 | 28 | 29 | You can use `create_labels()` to define global labels i.e. in your `defaults.yml`: 30 | 31 | ```{.yaml title="defaults.yml"} 32 | --8<-- "examples/jinja/006-nested-labels/defaults.yml:create_labels" 33 | ``` 34 | 35 | And use `create_labels()` another time to add object related labels i.e. in your template files: 36 | 37 | ```{.yaml title="templates/deployment.yml" hl_lines="6 9 18"} 38 | --8<-- "examples/jinja/006-nested-labels/templates/deployment.yml:use_labels" 39 | ``` 40 | 41 | This will result in the following labels: 42 | 43 | ```{.yaml title="build/jinja/.../prod/deployment.yml"} 44 | apiVersion: apps/v1 45 | kind: Deployment 46 | metadata: 47 | name: 006-nested-labels-prod 48 | namespace: playground 49 | labels: 50 | app.kubernetes.io/name: "nginx" 51 | app.kubernetes.io/instance: "prod" 52 | app.kubernetes.io/component: "my-deployment" 53 | app.kubernetes.io/part-of: "006-nested-labels" 54 | app.kubernetes.io/managed-by: "adeploy" 55 | ``` 56 | 57 | 58 | 59 | See [`create_labels()`](functions.md#adpeloy.common.jinja.globals.Handler.create_labels) for usage and parameters. 60 | 61 | ## Global Label Configuration 62 | 63 | Similar to [probes](probes.md) or [resource-limits](resource-limits.md), you can specify a global labels configuration 64 | in `defaults.yml` or in the namespace/release configuration as follows: 65 | 66 | ```{.yaml title="defaults.yml"} 67 | --8<-- "examples/jinja/005-labels/defaults.yml:global_labels" 68 | ``` 69 | 70 | These labels will be added to all appropriate `metadata`, `matchLabels` and `selector` properties. 71 | 72 | !!!tip 73 | Note that you can use Jinja variables in the labels, too. 74 | 75 | -------------------------------------------------------------------------------- /docs/common/macros.md: -------------------------------------------------------------------------------- 1 | # Jinja Macros 2 | 3 | 4 | You can add and use custom [Jinja Macros](https://jinja.palletsprojects.com/en/3.0.x/templates/#macros) in your 5 | `defaults.yml`, the namespace/release configuration or in your Jinja templates. 6 | 7 | You can add Jinja files containing your macros at the following places: 8 | 9 | * the current dir 10 | * the current parent dir 11 | * the directory of the template 12 | * the parent directory of the template. 13 | 14 | ## Example 15 | 16 | You can define the following macro to create a `ServiceMonitor`: 17 | 18 | ```{.jinja title="templates/macros/create_servicemonitor.jinja"} 19 | {% macro create_servicemonitor(service, labels) -%} 20 | --- 21 | apiVersion: monitoring.coreos.com/v1 22 | kind: ServiceMonitor 23 | metadata: 24 | name: {{ service.name if 'name' in service else service }} 25 | namespace: {{ namespace }} 26 | labels: 27 | {{ create_labels(component='monitoring', labels=labels) }} 28 | spec: 29 | selector: 30 | matchLabels: 31 | {{ labels }} 32 | endpoints: 33 | - port: http 34 | path: /actuator/prometheus 35 | {%- endmacro %} 36 | ``` 37 | Now you can use this macro in your template as follows: 38 | 39 | ```{.jinja title="templates/service.yaml"} 40 | {% from "macros/create_servicemonitor.jinja" import create_servicemonitor with context %} 41 | 42 | {{ create_servicemonitor(service.name, service.labels) }} 43 | ``` -------------------------------------------------------------------------------- /docs/common/probes.md: -------------------------------------------------------------------------------- 1 | # Probes 2 | 3 | 4 | Next to labels and resources, `adeploy` also allows to update liveness, readiness and startup probes on a global or 5 | workload scope at a single point in the default or namespace/release configuration. 6 | 7 | 8 | ## Global Probes Configuration 9 | 10 | 11 | `adeploy` introduces the reserved variable `__probes` that allows to update probes on a global or workload scope. 12 | 13 | !!!warning 14 | `adeploy` will only update your probe definitions, but it won't add any new probes to your manifest! This feature is 15 | thought to define the execution part of the probe in the manifest and set the probe parameters (i.e. timeouts etc.) 16 | at a single point in your configuration. 17 | 18 | If you want to define also the execution part, you need to add the following minimal probe snippets to your manifest: 19 | 20 | ```{.yaml title="templates/deployment.yml" hl_lines="4-6"} 21 | containers: 22 | - name: main 23 | image: registry.k8s.io/busybox 24 | livenessProbe: {} 25 | readinesProbe: {} 26 | startupProbe: {} 27 | ``` 28 | 29 | !!!note 30 | You can either use snake casing (í.e. `period_seconds`) or camel casing as in the 31 | [official k8s docs](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) 32 | (i.e. `periodSeconds`). 33 | 34 | ### Global Scope 35 | 36 | To update probes for all compatible API objects (`Deployment`, `StatefulSet`, `ReplicaSet`, ...) in your deployment, add 37 | the following to the `defaults.yml` or the namespace/release configuration: 38 | 39 | ```{.yaml title="defaults.yml"} 40 | _probes: 41 | --8<-- "examples/jinja/004-probes/defaults.yml:global-scope" 42 | ``` 43 | 44 | This will update all probes in the generated manifest files and overwrite it with the given values. 45 | 46 | ### Workload Scope 47 | 48 | To update the probe definition for a specific workload object queried by its name (i.e. `{{ name }}-{{ release }}-redis`), add the following: 49 | 50 | ```{.yaml title="defaults.yml"} 51 | _resources: 52 | --8<-- "examples/jinja/004-probes/defaults.yml:workload-scope" 53 | ``` -------------------------------------------------------------------------------- /docs/common/resource-limits.md: -------------------------------------------------------------------------------- 1 | # Resource Limits 2 | 3 | 4 | For larger deployments it is sometimes hard to keep track of the defined resource limits. For example a deployment for a 5 | distributed system having lots of similar workloads are suitable for a global definition of resource limits. `adeploy` 6 | does support such a global definition at a single point in your default or namespace/release configuration. 7 | 8 | 9 | ## Global Resources Configuration 10 | 11 | 12 | `adeploy` introduces the reserved variable `__resources` that allows to define resource limits for all workloads on a 13 | global, workload or container scope. 14 | 15 | ### Global Scope 16 | 17 | To set resource limits for all compatible API objects (`Deployment`, `StatefulSet`, `ReplicaSet`, ...) in your deployment, add 18 | the following to the `defaults.yml` or the namespace/release configuration: 19 | 20 | ```{.yaml title="defaults.yml"} 21 | _resources: 22 | --8<-- "examples/jinja/007-resources/defaults.yml:global-scope" 23 | ``` 24 | 25 | !!!note 26 | These globally set limits are ignored, if limits are already defined in the manifest files for the workload objects 27 | in the `templates` folder. 28 | 29 | ### Workload Scope 30 | 31 | To set resource limits for a specific API object queried by its name (i.e. `nginx`), add the following: 32 | 33 | ```{.yaml title="defaults.yml"} 34 | _resources: 35 | --8<-- "examples/jinja/007-resources/defaults.yml:workload-scope" 36 | ``` 37 | 38 | !!!note 39 | These globally set limits are ignored, if limits are already defined in the manifest file for the workload object 40 | `nginx` in the `templates` folder. 41 | 42 | ### Container Scope 43 | 44 | To set resource limits for a specific container queried by its name (i.e. `main`) and the workload object 45 | (i.e. `redis`), add the following: 46 | 47 | ```{.yaml title="defaults.yml"} 48 | _resources: 49 | --8<-- "examples/jinja/007-resources/defaults.yml:container-scope" 50 | ``` 51 | 52 | !!!warning 53 | These globally set limits take precedence and will overwrite any limit that is defined in the manifest file for the 54 | image `main` of the workload object `redis`. -------------------------------------------------------------------------------- /docs/helm/helm-render.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 90, "height": 12, "timestamp": 1708513670, "env": {"SHELL": "/bin/zsh", "TERM": "xterm"}} 2 | [0.068133, "o", "\u001b[?2004h$ "] 3 | [0.929736, "o", "a"] 4 | [1.025724, "o", "d"] 5 | [1.121917, "o", "e"] 6 | [1.145856, "o", "p"] 7 | [1.21005, "o", "l"] 8 | [1.313825, "o", "o"] 9 | [1.378324, "o", "y"] 10 | [1.44985, "o", " "] 11 | [1.561999, "o", "-"] 12 | [1.633958, "o", "p"] 13 | [1.729933, "o", " "] 14 | [2.569958, "o", "h"] 15 | [2.753695, "o", "e"] 16 | [2.873948, "o", "l"] 17 | [2.945923, "o", "m"] 18 | [3.05782, "o", " "] 19 | [3.169876, "o", "r"] 20 | [3.31384, "o", "e"] 21 | [3.369915, "o", "n"] 22 | [3.481955, "o", "d"] 23 | [3.553979, "o", "e"] 24 | [3.617963, "o", "r"] 25 | [3.673955, "o", " "] 26 | [3.738013, "o", "."] 27 | [3.897663, "o", "\r\n"] 28 | [3.897794, "o", "\u001b[?2004l\r"] 29 | [4.32009, "o", "\u001b[1madeploy.Render\u001b[22m \u001b[1m\u001b[32mRendering \u001b[39m\u001b[22m\u001b[1m/home/daniel/workspace/adeploy/examples/helm\u001b[22m in \u001b[1m./build\u001b[22m using the provider \u001b[1mhelm\u001b[22m\r\n\u001b[0m"] 30 | [4.322261, "o", "\u001b[1madeploy.Render\u001b[22m Adding chart repo from \u001b[34mhttps://helm.github.io/examples\u001b[39m ...\r\n\u001b[0m"] 31 | [5.043588, "o", "\u001b[1madeploy.Render\u001b[22m Using defaults from \"\u001b[1m/home/daniel/workspace/adeploy/examples/helm/defaults.yml\u001b[22m\" ...\r\n\u001b[0m"] 32 | [5.061598, "o", "\u001b[1madeploy.Render\u001b[22m Rendering chart \"\u001b[1mhello-world\u001b[22m\" version \u001b[1m0.1.0\u001b[22m and values for deployment \"\u001b[34mplayground/hello-world-test\u001b[39m\" in \"\u001b[1mbuild/helm/playground/hello-world/test\u001b[22m\" ...\r\n\u001b[0m"] 33 | [5.816712, "o", "\u001b[1madeploy.Render\u001b[22m \u001b[1m\u001b[32mRendering finished\u001b[39m\u001b[22m\r\n\u001b[0m"] 34 | [5.816841, "o", "\u001b[0m"] 35 | [5.855795, "o", "\u001b[?2004h$ "] -------------------------------------------------------------------------------- /docs/helm/helm-test.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 90, "height": 15, "timestamp": 1708514639, "env": {"SHELL": "/bin/zsh", "TERM": "xterm"}} 2 | [0.064528, "o", "\u001b[?2004h$ "] 3 | [0.615071, "o", "a"] 4 | [0.711438, "o", "d"] 5 | [0.791159, "o", "e"] 6 | [0.854988, "o", "p"] 7 | [0.935108, "o", "l"] 8 | [1.023138, "o", "o"] 9 | [1.103046, "o", "y"] 10 | [1.182994, "o", " "] 11 | [1.247027, "o", "-"] 12 | [1.351048, "o", "p"] 13 | [1.447069, "o", " "] 14 | [1.599108, "o", "h"] 15 | [1.759036, "o", "e"] 16 | [1.838951, "o", "l"] 17 | [1.894995, "o", "m"] 18 | [1.967026, "o", " "] 19 | [2.463121, "o", "t"] 20 | [2.583177, "o", "e"] 21 | [2.647108, "o", "s"] 22 | [2.695047, "o", "t"] 23 | [2.775092, "o", " "] 24 | [2.847076, "o", "."] 25 | [3.007082, "o", "\r\n"] 26 | [3.007128, "o", "\u001b[?2004l\r"] 27 | [3.443062, "o", "\u001b[1madeploy.Test\u001b[22m \u001b[1m\u001b[32mTesting \u001b[39m\u001b[22m\u001b[1m/home/daniel/workspace/adeploy/examples/helm\u001b[22m in \u001b[1m./build\u001b[22m using the provider \u001b[1mhelm\u001b[22m\r\n\u001b[0m"] 28 | [3.44438, "o", "\u001b[1madeploy.Test\u001b[22m Using defaults from \"\u001b[1m/home/daniel/workspace/adeploy/examples/helm/defaults.yml\u001b[22m\" ...\r\n\u001b[0m"] 29 | [3.455201, "o", "\u001b[1madeploy.Test\u001b[22m Testing Helm deployment \"\u001b[34mplayground/hello-world-test\u001b[39m\" ...\r\n\u001b[0m"] 30 | [4.397501, "o", "\u001b[1madeploy.Test\u001b[22m ... Chart version \u001b[1m0.1.0\u001b[22m, app version \u001b[1m1.16.0\u001b[22m, last deployed \u001b[1m2024-02-21T12:24:03.762735593+01:00\u001b[22m: \u001b[1m\u001b[32mDry run complete\u001b[39m\u001b[22m, status \u001b[1m\u001b[32mpending-upgrade\u001b[39m\u001b[22m\r\n\u001b[0m"] 31 | [4.397722, "o", "\u001b[1madeploy.Test\u001b[22m ... Testing raw manifests from \"\u001b[1mbuild/helm/playground/hello-world/test/manifest.yml\u001b[22m\" (may fail) ...\r\n\u001b[0m"] 32 | [5.716408, "o", "\u001b[1madeploy.Test\u001b[22m ...... namespace: \u001b[1mplayground\u001b[22m resource: \u001b[1mserviceaccount\u001b[22m, name: \u001b[1mtest-hello-world\u001b[22m: \u001b[32mconfigured\u001b[39m\r\n\u001b[0m"] 33 | [6.990495, "o", "\u001b[1madeploy.Test\u001b[22m ...... namespace: \u001b[1mplayground\u001b[22m resource: \u001b[1mservice\u001b[22m, name: \u001b[1mtest-hello-world\u001b[22m: \u001b[32mconfigured\u001b[39m\r\n\u001b[0m"] 34 | [8.262611, "o", "\u001b[1madeploy.Test\u001b[22m ...... namespace: \u001b[1mplayground\u001b[22m resource: \u001b[1mdeployment.apps\u001b[22m, name: \u001b[1mtest-hello-world\u001b[22m: \u001b[32mcreated\u001b[39m\r\n\u001b[0m"] 35 | [8.262928, "o", "\u001b[1madeploy.Test\u001b[22m \u001b[1m\u001b[32mTesting finished\u001b[39m\u001b[22m\r\n\u001b[0m"] 36 | [8.263089, "o", "\u001b[0m"] 37 | [8.299775, "o", "\u001b[?2004h$ "] 38 | -------------------------------------------------------------------------------- /docs/helm/hooks.md: -------------------------------------------------------------------------------- 1 | # Helm Deployment 2 | 3 | ## Hooks 4 | 5 | 6 | During rendering the Helm deployment templates, `adeploy` will run hooks (i.e. executables scripts) from the `hooks` 7 | directory after the Helm chart was downloaded and extracted. 8 | 9 | The `hooks` directory is used as current working directory. 10 | 11 | The path to the extracted Helm chart will be passed as argument to the executed hook: 12 | 13 | ```{.bash} 14 | ./hooks/script.sh /mydeployment/build/helm/charts// 15 | ``` 16 | 17 | This can be used i.e. to patch Helm charts without touching the upstream repos for quick and dirty fixes: 18 | 19 | ``` {.shell title="hooks/patch.sh"} 20 | --8<-- "examples/helm/002-hooks/hooks/patch.sh" 21 | ``` 22 | 23 | Now patches added to `hooks/patches.d` will be automatically applied to the Helm chart on each `adeploy -p helm render .`. 24 | 25 | !!!tip 26 | 27 | The stdout of your hooks is supressed by default but printed out in error cases. If you want to see the stdout of 28 | your hooks, run `adeploy` in verbose mode i.e. `adeploy -d -p helm render .`. -------------------------------------------------------------------------------- /docs/hooks/asciinema.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import json 3 | from bs4 import BeautifulSoup 4 | 5 | 6 | def to_camel_case(snake_str): 7 | camel_case_str = "".join(x.capitalize() for x in snake_str.lower().split("_")) 8 | return camel_case_str[0].lower() + camel_case_str[1:] 9 | 10 | 11 | def on_post_page(output, page, config): 12 | if 'alt="asciicast"' not in output: 13 | return output 14 | 15 | soup = BeautifulSoup(output, 'html.parser') 16 | asciicast_elements = soup.findAll("img", {"alt": "asciicast"}) 17 | asciicasts = [] 18 | for idx, element in enumerate(asciicast_elements): 19 | asciicast_id = f'asciicast-{idx}' 20 | asciicast_src = element.attrs['src'] 21 | 22 | # asciinema options, see https://docs.asciinema.org/manual/player/options/ 23 | options = {"fit": "width", "preload": True} 24 | 25 | for key, value in element.attrs.items(): 26 | 27 | if key in ["src"]: 28 | continue 29 | 30 | if value == "true": 31 | value = True 32 | elif value == "false": 33 | value = False 34 | 35 | options[to_camel_case(key)] = value 36 | 37 | div_tag = soup.new_tag("div", id=asciicast_id) 38 | element.replace_with(div_tag) 39 | asciicasts.append( 40 | f'asciinema_create_player("{asciicast_src}", ' 41 | f'document.getElementById("{asciicast_id}"), {json.dumps(options)});') 42 | 43 | asciicast_script = soup.new_tag("script") 44 | asciicast_script.append("\n".join(asciicasts)) 45 | soup.body.append(asciicast_script) 46 | 47 | return str(soup) 48 | -------------------------------------------------------------------------------- /docs/hooks/badges.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import posixpath 4 | import re 5 | 6 | from mkdocs.config.defaults import MkDocsConfig 7 | from mkdocs.structure.files import Files 8 | from mkdocs.structure.pages import Page 9 | from re import Match 10 | 11 | 12 | # ----------------------------------------------------------------------------- 13 | # Hooks 14 | # ----------------------------------------------------------------------------- 15 | 16 | 17 | def on_page_markdown( 18 | markdown: str, *, page: Page, config: MkDocsConfig, files: Files 19 | ): 20 | # Replace callback 21 | def replace(match: Match): 22 | type, args = match.groups() 23 | args = args.strip() 24 | if type == "version": 25 | return _badge_for_version(args, page, files) 26 | elif type == "provider": 27 | return _badge_for_provider(args, page, files) 28 | 29 | # Otherwise, raise an error 30 | raise RuntimeError(f"Unknown shortcode: {type}") 31 | 32 | # Find and replace all external asset URLs in current page 33 | return re.sub( 34 | r"", 35 | replace, markdown, flags=re.I | re.M 36 | ) 37 | 38 | 39 | # Create badge for version 40 | def _badge_for_version(version: str, page: Page, files: Files): 41 | # Return badge 42 | icon = "material-tag-outline" 43 | tooltip = f"Minimum Version: {version}" 44 | return _badge(icon=icon, text=f"{version}", tooltip=tooltip, type="version") 45 | 46 | 47 | # Create badge for version 48 | def _badge_for_provider(provider: str, page: Page, files: Files): 49 | # Return badge 50 | icon = "material-cog" 51 | tooltip = f"Supported by {provider.capitalize()} provider" 52 | return _badge(icon=icon, text=provider, tooltip=tooltip, type="provider") 53 | 54 | 55 | # Create badge 56 | def _badge(icon: str, text: str = "", tooltip: str = "", type: str = ""): 57 | classes = f"mdx-badge mdx-badge--{type}" if type else "mdx-badge" 58 | text = f"{text}{{ data-preview='' }}" if text.endswith(")") else text 59 | return "".join([ 60 | f"", 61 | *([f":{icon}:"] if icon else []), 62 | *([f"{text}"] if text else []), 63 | f"", 64 | ]) 65 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | --8<-- "README.md:intro" 4 | 5 | ## Examples 6 | 7 | This is how you can render, test (preview) and deploy a Helm Chart: 8 | ![asciicast](helm.cast){ auto_play="true" loop="true" } 9 | 10 | Or you can render, test (preview) and deploy Jinja-templated manifests: 11 | ![asciicast](jinja.cast){ auto_play="true" loop="true" } 12 | 13 | You'll find some examples in the [example](https://github.com/awesome-it/adeploy/tree/master/examples) directory. 14 | 15 | ## Getting Started 16 | 17 | Follow the [install guide](install.md) to get started. -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | # Quickstart 2 | 3 | ## Install 4 | 5 | --8<-- "README.md:install" 6 | 7 | If you're new to `adeploy` continue to read [howto use `adeploy`](usage.md). -------------------------------------------------------------------------------- /docs/jinja/jinja-deploy.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 75, "height": 10, "timestamp": 1708601769, "env": {"SHELL": "/bin/zsh", "TERM": "xterm"}} 2 | [0.171876, "o", "\u001b[?2004h$ "] 3 | [1.118319, "o", "a"] 4 | [1.230363, "o", "d"] 5 | [1.326377, "o", "e"] 6 | [1.43024, "o", "p"] 7 | [1.550291, "o", "l"] 8 | [1.646343, "o", "o"] 9 | [1.710153, "o", "y"] 10 | [1.814356, "o", " "] 11 | [1.942475, "o", "-"] 12 | [2.10229, "o", "p"] 13 | [2.238185, "o", " "] 14 | [2.374373, "o", "j"] 15 | [2.478413, "o", "i"] 16 | [2.646332, "o", "n"] 17 | [2.758317, "o", "j"] 18 | [2.822321, "o", "a"] 19 | [3.006191, "o", " "] 20 | [3.230198, "o", "d"] 21 | [3.334377, "o", "e"] 22 | [3.390292, "o", "p"] 23 | [3.502181, "o", "l"] 24 | [3.590363, "o", "o"] 25 | [3.686385, "o", "y"] 26 | [3.846299, "o", "\r\n"] 27 | [3.846467, "o", "\u001b[?2004l\r"] 28 | [4.325537, "o", "\u001b[1madeploy.Deploy\u001b[22m \u001b[1m\u001b[32mDeploying \u001b[39m\u001b[22m\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure\u001b[22m in \u001b[1m./build\u001b[22m using the provider \u001b[1mjinja\u001b[22m\r\n\u001b[0m"] 29 | [4.326587, "o", "\u001b[1madeploy.Deploy\u001b[22m Using defaults from \"\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure/defaults.yml\u001b[22m\" ...\r\n\u001b[0m"] 30 | [4.349022, "o", "\u001b[1madeploy.Deploy\u001b[22m Using defaults from \"\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure/defaults.yml\u001b[22m\" ...\r\n\u001b[0m"] 31 | [4.356842, "o", "\u001b[1madeploy.Deploy\u001b[22m Applying manifests for deployment \"\u001b[34mplayground/001-general-structure-prod\u001b[39m\" in \"build/jinja/playground/001-general-structure/prod\" ...\r\n\u001b[0m"] 32 | [5.325171, "o", "\u001b[1madeploy.Deploy\u001b[22m resource: \u001b[1mdeployment.apps\u001b[22m, name: \u001b[1m001-general-structure-prod\u001b[22m: \u001b[32mcreated\u001b[39m\r\n\u001b[0m"] 33 | [5.325415, "o", "\u001b[1madeploy.Deploy\u001b[22m Saving current cluster as last deployed cluster\r\n\u001b[0m"] 34 | [5.325844, "o", "\u001b[1madeploy.Deploy\u001b[22m Applying manifests for deployment \"\u001b[34mplayground/001-general-structure-test\u001b[39m\" in \"build/jinja/playground/001-general-structure/test\" ...\r\n\u001b[0m"] 35 | [6.390163, "o", "\u001b[1madeploy.Deploy\u001b[22m resource: \u001b[1mdeployment.apps\u001b[22m, name: \u001b[1m001-general-structure-test\u001b[22m: \u001b[32mcreated\u001b[39m\r\n\u001b[0m"] 36 | [6.390371, "o", "\u001b[1madeploy.Deploy\u001b[22m Saving current cluster as last deployed cluster\r\n\u001b[0m"] 37 | [6.390794, "o", "\u001b[1madeploy.Deploy\u001b[22m \u001b[1m\u001b[32mDeployment finished\u001b[39m\u001b[22m\r\n\u001b[0m"] 38 | [6.390996, "o", "\u001b[0m"] 39 | [6.471577, "o", "\u001b[?2004h$ "] -------------------------------------------------------------------------------- /docs/jinja/jinja-render.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 75, "height": 20, "timestamp": 1708594482, "env": {"SHELL": "/bin/zsh", "TERM": "xterm"}} 2 | [0.097089, "o", "\u001b[?2004h$ "] 3 | [2.062784, "o", "a"] 4 | [2.142612, "o", "d"] 5 | [2.230599, "o", "e"] 6 | [2.286734, "o", "p"] 7 | [2.358506, "o", "l"] 8 | [2.438562, "o", "o"] 9 | [2.542562, "o", "y"] 10 | [2.622308, "o", " "] 11 | [2.734885, "o", "-"] 12 | [2.854497, "o", "p"] 13 | [2.967695, "o", " "] 14 | [3.09456, "o", "j"] 15 | [3.174436, "o", "i"] 16 | [3.310558, "o", "n"] 17 | [3.390415, "o", "j"] 18 | [3.454454, "o", "a"] 19 | [3.542483, "o", " "] 20 | [3.662511, "o", "r"] 21 | [3.790376, "o", "e"] 22 | [3.887107, "o", "n"] 23 | [3.982534, "o", "d"] 24 | [4.006607, "o", "e"] 25 | [4.078373, "o", "r"] 26 | [4.167468, "o", " "] 27 | [4.262557, "o", "."] 28 | [4.422574, "o", "\r\n"] 29 | [4.422633, "o", "\u001b[?2004l\r"] 30 | [5.02304, "o", "\u001b[1madeploy.Render\u001b[22m \u001b[1m\u001b[32mRendering \u001b[39m\u001b[22m\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure\u001b[22m in \u001b[1m./build\u001b[22m using the provider \u001b[1mjinja\u001b[22m\r\n\u001b[0m"] 31 | [5.026159, "o", "\u001b[1madeploy.Render\u001b[22m Using defaults from \"\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure/defaults.yml\u001b[22m\" ...\r\n\u001b[0m"] 32 | [5.046589, "o", "\u001b[1madeploy.Render\u001b[22m Using defaults from \"\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure/defaults.yml\u001b[22m\" ...\r\n\u001b[0m"] 33 | [5.054769, "o", "\u001b[1madeploy.Render\u001b[22m Rendering deployment \"\u001b[34mplayground/001-general-structure-prod\u001b[39m\" ...\r\n\u001b[0m"] 34 | [5.055264, "o", "\u001b[1madeploy.Render\u001b[22m ... render \"\u001b[1mdeployment.yml\u001b[22m\" in \"\u001b[1mbuild/jinja/playground/001-general-structure/prod/deployment.yml\u001b[22m\" ...\r\n\u001b[0m"] 35 | [5.115822, "o", "\u001b[1madeploy.Render\u001b[22m Rendering deployment \"\u001b[34mplayground/001-general-structure-test\u001b[39m\" ...\r\n\u001b[0m"] 36 | [5.116337, "o", "\u001b[1madeploy.Render\u001b[22m ... render \"\u001b[1mdeployment.yml\u001b[22m\" in \"\u001b[1mbuild/jinja/playground/001-general-structure/test/deployment.yml\u001b[22m\" ...\r\n\u001b[0m"] 37 | [5.165001, "o", "\u001b[1madeploy.Render\u001b[22m \u001b[1m\u001b[32mRendering finished\u001b[39m\u001b[22m\r\n\u001b[0m"] 38 | [5.165168, "o", "\u001b[0m"] 39 | [5.231859, "o", "\u001b[?2004h$ "] 40 | -------------------------------------------------------------------------------- /docs/jinja/jinja-test.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 75, "height": 20, "timestamp": 1708601422, "env": {"SHELL": "/bin/zsh", "TERM": "xterm"}} 2 | [0.107973, "o", "\u001b[?2004h$ "] 3 | [0.867361, "o", "a"] 4 | [0.939112, "o", "d"] 5 | [1.027515, "o", "e"] 6 | [1.067251, "o", "p"] 7 | [1.139011, "o", "l"] 8 | [1.206312, "o", "o"] 9 | [1.283319, "o", "y"] 10 | [1.363571, "o", " "] 11 | [1.442975, "o", "-"] 12 | [1.555042, "o", "p"] 13 | [1.659162, "o", " "] 14 | [1.787668, "o", "j"] 15 | [1.875132, "o", "i"] 16 | [2.01144, "o", "n"] 17 | [2.083303, "o", "j"] 18 | [2.163238, "o", "a"] 19 | [2.219138, "o", " "] 20 | [2.299099, "o", "t"] 21 | [2.395179, "o", "e"] 22 | [2.451248, "o", "s"] 23 | [2.515101, "o", "t"] 24 | [2.603301, "o", "\r\n"] 25 | [2.603472, "o", "\u001b[?2004l\r"] 26 | [3.246917, "o", "\u001b[1madeploy.Test\u001b[22m \u001b[1m\u001b[32mTesting \u001b[39m\u001b[22m\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure\u001b[22m in \u001b[1m./build\u001b[22m using the provider \u001b[1mjinja\u001b[22m\r\n\u001b[0m"] 27 | [3.248173, "o", "\u001b[1madeploy.Test\u001b[22m Using defaults from \"\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure/defaults.yml\u001b[22m\" ...\r\n\u001b[0m"] 28 | [3.267626, "o", "\u001b[1madeploy.Test\u001b[22m Using defaults from \"\u001b[1m/home/daniel/workspace/adeploy/examples/jinja/001-general-structure/defaults.yml\u001b[22m\" ...\r\n\u001b[0m"] 29 | [3.273362, "o", "\u001b[1madeploy.Test\u001b[22m Testing manifests for deployment \"\u001b[34mplayground/001-general-structure-prod\u001b[39m\" in \"build/jinja/playground/001-general-structure/prod\" ...\r\n\u001b[0m"] 30 | [5.512342, "o", "\u001b[1madeploy.Test\u001b[22m namespace: \u001b[1mplayground\u001b[22m resource: \u001b[1mdeployment.apps\u001b[22m, name: \u001b[1m001-general-structure-prod\u001b[22m: \u001b[32mcreated\u001b[39m\r\n\u001b[0m"] 31 | [5.512542, "o", "\u001b[1madeploy.Test\u001b[22m Testing manifests for deployment \"\u001b[34mplayground/001-general-structure-test\u001b[39m\" in \"build/jinja/playground/001-general-structure/test\" ...\r\n\u001b[0m"] 32 | [7.589509, "o", "\u001b[1madeploy.Test\u001b[22m namespace: \u001b[1mplayground\u001b[22m resource: \u001b[1mdeployment.apps\u001b[22m, name: \u001b[1m001-general-structure-test\u001b[22m: \u001b[32mcreated\u001b[39m\r\n\u001b[0m"] 33 | [7.589665, "o", "\u001b[1madeploy.Test\u001b[22m \u001b[1m\u001b[32mTesting finished\u001b[39m\u001b[22m\r\n\u001b[0m"] 34 | [7.589818, "o", "\u001b[0m"] 35 | [7.650733, "o", "\u001b[?2004h$ "] -------------------------------------------------------------------------------- /docs/overrides/partials/copyright.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/.exclude-from-test: -------------------------------------------------------------------------------- 1 | # Exclude binary secret files that will differ 2 | secret-* -------------------------------------------------------------------------------- /examples/helm/001-quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Helm Example 2 | 3 | This is a hello-world Helm chart how to deploy Helm charts using `adeploy`. 4 | 5 | Since Helm the repository URL, chart name and version are defined in `defaults.yml`, you just need to the following to 6 | render the chart: 7 | 8 | ```bash 9 | $ adeploy -p helm render 10 | ``` 11 | 12 | You can check what would be deployed as follows: 13 | 14 | ```bash 15 | $ adeploy -p helm test 16 | ``` 17 | 18 | You can now deploy the Helm chart by using `adeploy` as follows: 19 | 20 | ```bash 21 | $ adeploy -p helm deploy 22 | ``` 23 | 24 | Note that `adeploy` is internally still using `helm install`. So you can fallback to your default helm commands 25 | to maintain this installation. -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | appVersion: 1.16.0 3 | description: A Helm chart for Kubernetes 4 | name: hello-world 5 | type: application 6 | version: 0.1.0 7 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/README.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if contains "NodePort" .Values.service.type }} 3 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "hello-world.fullname" . }}) 4 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 5 | echo http://$NODE_IP:$NODE_PORT 6 | {{- else if contains "LoadBalancer" .Values.service.type }} 7 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 8 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "hello-world.fullname" . }}' 9 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "hello-world.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 10 | echo http://$SERVICE_IP:{{ .Values.service.port }} 11 | {{- else if contains "ClusterIP" .Values.service.type }} 12 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "hello-world.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 13 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 14 | echo "Visit http://127.0.0.1:8080 to use your application" 15 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "hello-world.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "hello-world.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "hello-world.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "hello-world.labels" -}} 37 | helm.sh/chart: {{ include "hello-world.chart" . }} 38 | {{ include "hello-world.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "hello-world.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "hello-world.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "hello-world.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "hello-world.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "hello-world.fullname" . }} 5 | labels: 6 | {{- include "hello-world.labels" . | nindent 4 }} 7 | spec: 8 | replicas: {{ .Values.replicaCount }} 9 | selector: 10 | matchLabels: 11 | {{- include "hello-world.selectorLabels" . | nindent 6 }} 12 | template: 13 | metadata: 14 | labels: 15 | {{- include "hello-world.selectorLabels" . | nindent 8 }} 16 | spec: 17 | serviceAccountName: {{ include "hello-world.serviceAccountName" . }} 18 | containers: 19 | - name: {{ .Chart.Name }} 20 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 21 | imagePullPolicy: {{ .Values.image.pullPolicy }} 22 | ports: 23 | - name: http 24 | containerPort: 80 25 | protocol: TCP 26 | livenessProbe: 27 | httpGet: 28 | path: / 29 | port: http 30 | readinessProbe: 31 | httpGet: 32 | path: / 33 | port: http 34 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "hello-world.fullname" . }} 5 | labels: 6 | {{- include "hello-world.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "hello-world.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "hello-world.serviceAccountName" . }} 6 | labels: 7 | {{- include "hello-world.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/charts/hello-world/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for hello-world. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: "" 12 | 13 | nameOverride: "" 14 | fullnameOverride: "" 15 | 16 | serviceAccount: 17 | # Specifies whether a service account should be created 18 | create: true 19 | # Annotations to add to the service account 20 | annotations: {} 21 | # The name of the service account to use. 22 | # If not set and create is true, a name is generated using the fullname template 23 | name: "" 24 | 25 | service: 26 | type: ClusterIP 27 | port: 80 28 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/playground/hello-world/test/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Source: hello-world/templates/serviceaccount.yaml 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: test-hello-world 7 | labels: 8 | helm.sh/chart: hello-world-0.1.0 9 | app.kubernetes.io/name: hello-world 10 | app.kubernetes.io/instance: test 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | --- 14 | # Source: hello-world/templates/service.yaml 15 | apiVersion: v1 16 | kind: Service 17 | metadata: 18 | name: test-hello-world 19 | labels: 20 | helm.sh/chart: hello-world-0.1.0 21 | app.kubernetes.io/name: hello-world 22 | app.kubernetes.io/instance: test 23 | app.kubernetes.io/version: "1.16.0" 24 | app.kubernetes.io/managed-by: Helm 25 | spec: 26 | type: ClusterIP 27 | ports: 28 | - port: 80 29 | targetPort: http 30 | protocol: TCP 31 | name: http 32 | selector: 33 | app.kubernetes.io/name: hello-world 34 | app.kubernetes.io/instance: test 35 | --- 36 | # Source: hello-world/templates/deployment.yaml 37 | apiVersion: apps/v1 38 | kind: Deployment 39 | metadata: 40 | name: test-hello-world 41 | labels: 42 | helm.sh/chart: hello-world-0.1.0 43 | app.kubernetes.io/name: hello-world 44 | app.kubernetes.io/instance: test 45 | app.kubernetes.io/version: "1.16.0" 46 | app.kubernetes.io/managed-by: Helm 47 | spec: 48 | replicas: 1 49 | selector: 50 | matchLabels: 51 | app.kubernetes.io/name: hello-world 52 | app.kubernetes.io/instance: test 53 | template: 54 | metadata: 55 | labels: 56 | app.kubernetes.io/name: hello-world 57 | app.kubernetes.io/instance: test 58 | spec: 59 | serviceAccountName: test-hello-world 60 | containers: 61 | - name: hello-world 62 | image: "nginx:1.16.0" 63 | imagePullPolicy: IfNotPresent 64 | ports: 65 | - name: http 66 | containerPort: 80 67 | protocol: TCP 68 | livenessProbe: 69 | httpGet: 70 | path: / 71 | port: http 72 | readinessProbe: 73 | httpGet: 74 | path: / 75 | port: http 76 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/build/helm/playground/hello-world/test/values.yml: -------------------------------------------------------------------------------- 1 | _chart: 2 | name: hello-world 3 | repo_url: https://helm.github.io/examples 4 | version: 0.1.0 5 | fullnameOverride: '' 6 | image: 7 | pullPolicy: IfNotPresent 8 | repository: nginx 9 | tag: '' 10 | nameOverride: '' 11 | replicaCount: 1 12 | service: 13 | port: 80 14 | type: ClusterIP 15 | serviceAccount: 16 | annotations: {} 17 | create: true 18 | name: '' 19 | -------------------------------------------------------------------------------- /examples/helm/001-quickstart/defaults.yml: -------------------------------------------------------------------------------- 1 | _chart: 2 | repo_url: https://helm.github.io/examples 3 | name: hello-world 4 | version: 0.1.0 5 | 6 | # The following are default values from values.yaml of the Helm Chart, 7 | # see https://github.com/helm/examples/blob/main/charts/hello-world/values.yaml. 8 | 9 | replicaCount: 1 10 | 11 | image: 12 | repository: nginx 13 | pullPolicy: IfNotPresent 14 | # Overrides the image tag whose default is the chart appVersion. 15 | tag: "" 16 | 17 | nameOverride: "" 18 | fullnameOverride: "" 19 | 20 | serviceAccount: 21 | # Specifies whether a service account should be created 22 | create: false 23 | # Annotations to add to the service account 24 | annotations: {} 25 | # The name of the service account to use. 26 | # If not set and create is true, a name is generated using the fullname template 27 | name: "" 28 | 29 | service: 30 | type: ClusterIP 31 | port: 80 -------------------------------------------------------------------------------- /examples/helm/001-quickstart/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # These are the default values taken from values.yaml. 2 | # You can use the namespace configuration to overwrite them for this namespace: 3 | 4 | replicaCount: 1 5 | 6 | image: 7 | repository: nginx 8 | pullPolicy: IfNotPresent 9 | # Overrides the image tag whose default is the chart appVersion. 10 | tag: "" 11 | 12 | nameOverride: "" 13 | fullnameOverride: "" 14 | 15 | serviceAccount: 16 | # Specifies whether a service account should be created 17 | create: true 18 | # Annotations to add to the service account 19 | annotations: {} 20 | # The name of the service account to use. 21 | # If not set and create is true, a name is generated using the fullname template 22 | name: "" 23 | 24 | service: 25 | type: ClusterIP 26 | port: 80 -------------------------------------------------------------------------------- /examples/helm/002-hooks/README.md: -------------------------------------------------------------------------------- 1 | # Helm Example 2 | 3 | This is a hello-world Helm chart how to deploy Helm charts using `adeploy`. 4 | 5 | Since Helm the repository URL, chart name and version are defined in `defaults.yml`, you just need to the following to 6 | render the chart: 7 | 8 | ```bash 9 | $ adeploy -p helm render 10 | ``` 11 | 12 | You can check what would be deployed as follows: 13 | 14 | ```bash 15 | $ adeploy -p helm test 16 | ``` 17 | 18 | You can now deploy the Helm chart by using `adeploy` as follows: 19 | 20 | ```bash 21 | $ adeploy -p helm deploy 22 | ``` 23 | 24 | Note that `adeploy` is internally still using `helm install`. So you can fallback to your default helm commands 25 | to maintain this installation. -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | appVersion: 1.16.0 3 | description: A Helm chart for Kubernetes 4 | name: hello-world 5 | type: application 6 | version: 0.1.0 7 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/README.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if contains "NodePort" .Values.service.type }} 3 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "hello-world.fullname" . }}) 4 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 5 | echo http://$NODE_IP:$NODE_PORT 6 | {{- else if contains "LoadBalancer" .Values.service.type }} 7 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 8 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "hello-world.fullname" . }}' 9 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "hello-world.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 10 | echo http://$SERVICE_IP:{{ .Values.service.port }} 11 | {{- else if contains "ClusterIP" .Values.service.type }} 12 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "hello-world.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 13 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 14 | echo "Visit http://127.0.0.1:8080 to use your application" 15 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "hello-world.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "hello-world.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "hello-world.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "hello-world.labels" -}} 37 | helm.sh/chart: {{ include "hello-world.chart" . }} 38 | {{ include "hello-world.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "hello-world.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "hello-world.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "hello-world.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "hello-world.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "hello-world.fullname" . }} 5 | labels: 6 | {{- include "hello-world.labels" . | nindent 4 }} 7 | spec: 8 | replicas: {{ .Values.replicaCount }} 9 | selector: 10 | matchLabels: 11 | {{- include "hello-world.selectorLabels" . | nindent 6 }} 12 | template: 13 | metadata: 14 | labels: 15 | {{- include "hello-world.selectorLabels" . | nindent 8 }} 16 | spec: 17 | serviceAccountName: {{ include "hello-world.serviceAccountName" . }} 18 | containers: 19 | - name: {{ .Chart.Name }} 20 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 21 | imagePullPolicy: {{ .Values.image.pullPolicy }} 22 | env: 23 | - name: MY_ENV 24 | value: MY_VALUE 25 | ports: 26 | - name: http 27 | containerPort: 80 28 | protocol: TCP 29 | livenessProbe: 30 | httpGet: 31 | path: / 32 | port: http 33 | readinessProbe: 34 | httpGet: 35 | path: / 36 | port: http 37 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "hello-world.fullname" . }} 5 | labels: 6 | {{- include "hello-world.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "hello-world.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "hello-world.serviceAccountName" . }} 6 | labels: 7 | {{- include "hello-world.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/charts/hello-world/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for hello-world. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: "" 12 | 13 | nameOverride: "" 14 | fullnameOverride: "" 15 | 16 | serviceAccount: 17 | # Specifies whether a service account should be created 18 | create: true 19 | # Annotations to add to the service account 20 | annotations: {} 21 | # The name of the service account to use. 22 | # If not set and create is true, a name is generated using the fullname template 23 | name: "" 24 | 25 | service: 26 | type: ClusterIP 27 | port: 80 28 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/playground/hello-world/test/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Source: hello-world/templates/serviceaccount.yaml 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: test-hello-world 7 | labels: 8 | helm.sh/chart: hello-world-0.1.0 9 | app.kubernetes.io/name: hello-world 10 | app.kubernetes.io/instance: test 11 | app.kubernetes.io/version: "1.16.0" 12 | app.kubernetes.io/managed-by: Helm 13 | --- 14 | # Source: hello-world/templates/service.yaml 15 | apiVersion: v1 16 | kind: Service 17 | metadata: 18 | name: test-hello-world 19 | labels: 20 | helm.sh/chart: hello-world-0.1.0 21 | app.kubernetes.io/name: hello-world 22 | app.kubernetes.io/instance: test 23 | app.kubernetes.io/version: "1.16.0" 24 | app.kubernetes.io/managed-by: Helm 25 | spec: 26 | type: ClusterIP 27 | ports: 28 | - port: 80 29 | targetPort: http 30 | protocol: TCP 31 | name: http 32 | selector: 33 | app.kubernetes.io/name: hello-world 34 | app.kubernetes.io/instance: test 35 | --- 36 | # Source: hello-world/templates/deployment.yaml 37 | apiVersion: apps/v1 38 | kind: Deployment 39 | metadata: 40 | name: test-hello-world 41 | labels: 42 | helm.sh/chart: hello-world-0.1.0 43 | app.kubernetes.io/name: hello-world 44 | app.kubernetes.io/instance: test 45 | app.kubernetes.io/version: "1.16.0" 46 | app.kubernetes.io/managed-by: Helm 47 | spec: 48 | replicas: 1 49 | selector: 50 | matchLabels: 51 | app.kubernetes.io/name: hello-world 52 | app.kubernetes.io/instance: test 53 | template: 54 | metadata: 55 | labels: 56 | app.kubernetes.io/name: hello-world 57 | app.kubernetes.io/instance: test 58 | spec: 59 | serviceAccountName: test-hello-world 60 | containers: 61 | - name: hello-world 62 | image: "nginx:1.16.0" 63 | imagePullPolicy: IfNotPresent 64 | env: 65 | - name: MY_ENV 66 | value: MY_VALUE 67 | ports: 68 | - name: http 69 | containerPort: 80 70 | protocol: TCP 71 | livenessProbe: 72 | httpGet: 73 | path: / 74 | port: http 75 | readinessProbe: 76 | httpGet: 77 | path: / 78 | port: http 79 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/build/helm/playground/hello-world/test/values.yml: -------------------------------------------------------------------------------- 1 | _chart: 2 | name: hello-world 3 | repo_url: https://helm.github.io/examples 4 | version: 0.1.0 5 | fullnameOverride: '' 6 | image: 7 | pullPolicy: IfNotPresent 8 | repository: nginx 9 | tag: '' 10 | nameOverride: '' 11 | replicaCount: 1 12 | service: 13 | port: 80 14 | type: ClusterIP 15 | serviceAccount: 16 | annotations: {} 17 | create: true 18 | name: '' 19 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/defaults.yml: -------------------------------------------------------------------------------- 1 | _chart: 2 | repo_url: https://helm.github.io/examples 3 | name: hello-world 4 | version: 0.1.0 5 | 6 | # The following are default values from values.yaml of the Helm Chart, 7 | # see https://github.com/helm/examples/blob/main/charts/hello-world/values.yaml. 8 | 9 | replicaCount: 1 10 | 11 | image: 12 | repository: nginx 13 | pullPolicy: IfNotPresent 14 | # Overrides the image tag whose default is the chart appVersion. 15 | tag: "" 16 | 17 | nameOverride: "" 18 | fullnameOverride: "" 19 | 20 | serviceAccount: 21 | # Specifies whether a service account should be created 22 | create: false 23 | # Annotations to add to the service account 24 | annotations: {} 25 | # The name of the service account to use. 26 | # If not set and create is true, a name is generated using the fullname template 27 | name: "" 28 | 29 | service: 30 | type: ClusterIP 31 | port: 80 -------------------------------------------------------------------------------- /examples/helm/002-hooks/hooks/patch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | for p in patches.d/* 4 | do 5 | echo "Patching $p ..."; 6 | patch -d "$1" -p0 < $p 7 | done -------------------------------------------------------------------------------- /examples/helm/002-hooks/hooks/patches.d/001-add-env.patch: -------------------------------------------------------------------------------- 1 | --- templates/deployment.yaml.orig 2024-02-21 16:01:21.572456859 +0100 2 | +++ templates/deployment.yaml 2024-02-21 16:01:41.272583136 +0100 3 | @@ -19,6 +19,9 @@ 4 | - name: {{ .Chart.Name }} 5 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 6 | imagePullPolicy: {{ .Values.image.pullPolicy }} 7 | + env: 8 | + - name: MY_ENV 9 | + value: MY_VALUE 10 | ports: 11 | - name: http 12 | containerPort: 80 13 | -------------------------------------------------------------------------------- /examples/helm/002-hooks/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # These are the default values taken from values.yaml. 2 | # You can use the namespace configuration to overwrite them for this namespace: 3 | 4 | replicaCount: 1 5 | 6 | image: 7 | repository: nginx 8 | pullPolicy: IfNotPresent 9 | # Overrides the image tag whose default is the chart appVersion. 10 | tag: "" 11 | 12 | nameOverride: "" 13 | fullnameOverride: "" 14 | 15 | serviceAccount: 16 | # Specifies whether a service account should be created 17 | create: true 18 | # Annotations to add to the service account 19 | annotations: {} 20 | # The name of the service account to use. 21 | # If not set and create is true, a name is generated using the fullname template 22 | name: "" 23 | 24 | service: 25 | type: ClusterIP 26 | port: 80 -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/.exclude-from-test: -------------------------------------------------------------------------------- 1 | job.yml -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/README.md: -------------------------------------------------------------------------------- 1 | # General Structure 2 | 3 | This is the general structure for a Jinja based `adeploy` project that includes: 4 | 5 | * namespace `playground` and 6 | * two releases: `prod` and `test` 7 | 8 | Deploy as follows: 9 | 10 | ``` 11 | $ kubectl create namespace playground 12 | $ adeploy -p jinja [-n ] render . 13 | $ adeploy -p jinja [-n ] test 14 | $ adeploy -p jinja [-n ] deploy 15 | ``` 16 | 17 | By default `adeploy` is using the project folder as deployment name (i.e. `001-general-structure`). 18 | If you want to use another deployment name, pass it with `-n `. 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/build/jinja/playground/001-general-structure/prod/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 001-general-structure-prod 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 001-general-structure 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 001-general-structure 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 001-general-structure 26 | app.kubernetes.io/instance: prod 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: registry.awesome-it.de/upstream-docker/library/nginx:1.22 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | initialDelaySeconds: 3 44 | timeoutSeconds: 2 45 | failureThreshold: 2 46 | readinessProbe: 47 | httpGet: 48 | path: / 49 | port: 80 50 | initialDelaySeconds: 3 51 | timeoutSeconds: 2 52 | failureThreshold: 2 53 | -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/build/jinja/playground/001-general-structure/prod/job.yml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: 001-general-structure-prod-ping-ee5831ae-9b5a-4c3e-9b4c-df15e7c724d7 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 001-general-structure 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | template: 12 | metadata: 13 | name: 001-general-structure-prod-ping-7b66dbc3-5c6d-4a58-a0ef-4f908a75ced2 14 | labels: 15 | app.kubernetes.io/part-of: 001-general-structure 16 | app.kubernetes.io/instance: prod 17 | app.kubernetes.io/component: nginx 18 | spec: 19 | restartPolicy: OnFailure 20 | containers: 21 | - name: ping 22 | image: registry.awesome-it.de/upstream-docker/library/nginx:1.22 23 | imagePullPolicy: Always 24 | command: ["/bin/true"] 25 | args: [] 26 | -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/build/jinja/playground/001-general-structure/test/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 001-general-structure-test 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 001-general-structure 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 001-general-structure 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 001-general-structure 26 | app.kubernetes.io/instance: test 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: nginx:1.23 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | initialDelaySeconds: 3 44 | timeoutSeconds: 2 45 | failureThreshold: 2 46 | readinessProbe: 47 | httpGet: 48 | path: / 49 | port: 80 50 | initialDelaySeconds: 3 51 | timeoutSeconds: 2 52 | failureThreshold: 2 53 | -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/build/jinja/playground/001-general-structure/test/job.yml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: 001-general-structure-test-ping-e5f499bd-339f-4a0a-b197-e98d5de0eb32 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 001-general-structure 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | template: 12 | metadata: 13 | name: 001-general-structure-test-ping-e6a604b3-c758-4ad1-a9cf-fd565cb2c860 14 | labels: 15 | app.kubernetes.io/part-of: 001-general-structure 16 | app.kubernetes.io/instance: test 17 | app.kubernetes.io/component: nginx 18 | spec: 19 | restartPolicy: OnFailure 20 | containers: 21 | - name: ping 22 | image: nginx:1.23 23 | imagePullPolicy: Always 24 | command: ["/bin/true"] 25 | args: [] 26 | -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/defaults.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.23 3 | 4 | nginx: 5 | image: nginx 6 | listen: 0.0.0.0:80 7 | locations: 8 | - name: default 9 | upstream: 0.0.0.0:8000 10 | -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/namespaces/playground/prod.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.22 3 | 4 | nginx: 5 | image: registry.awesome-it.de/upstream-docker/library/nginx 6 | locations: 7 | {% for name in ["service-1", "service-2"] %} 8 | - name: {{ name }} 9 | upstream: 0.0.0.0:{{ 8000 + loop.index0 }} 10 | {% endfor %} -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # Inherit from defaults.yml 2 | #versions: 3 | # nginx: -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/templates/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }} 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: {{ name }} 26 | app.kubernetes.io/instance: {{ release }} 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: {{ nginx.image }}:{{ version('nginx') }} 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | initialDelaySeconds: 3 44 | timeoutSeconds: 2 45 | failureThreshold: 2 46 | readinessProbe: 47 | httpGet: 48 | path: / 49 | port: 80 50 | initialDelaySeconds: 3 51 | timeoutSeconds: 2 52 | failureThreshold: 2 53 | -------------------------------------------------------------------------------- /examples/jinja/001-general-structure/templates/job.yml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: {{ name }}-{{ release }}-ping-{{ uuid() }} 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | template: 12 | metadata: 13 | name: {{ name }}-{{ release }}-ping-{{ uuid() }} 14 | labels: 15 | app.kubernetes.io/part-of: {{ name }} 16 | app.kubernetes.io/instance: {{ release }} 17 | app.kubernetes.io/component: nginx 18 | spec: 19 | restartPolicy: OnFailure 20 | containers: 21 | - name: ping 22 | image: {{ nginx.image }}:{{ version('nginx') }} 23 | imagePullPolicy: Always 24 | command: ["/bin/true"] 25 | args: [] -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/README.md: -------------------------------------------------------------------------------- 1 | # Create Secrets 2 | 3 | An example deployment that creates secrets for a Jinja based `adeploy` project that includes: 4 | 5 | * namespace `playground`, 6 | * two releases: `prod`,`test` and 7 | * an `ImagePullSecret`, an environment variable `my_secret` and 8 | * an `Ingress` with a TLS Secret created by `adeploy`. 9 | 10 | For demonstration purpose, we are using `cat secrets/*` to retrieve secrets. But in practise this should be replaced 11 | with a password tool i.e. `gopass`, `Ansible Vault` or `Vault by HashiCorp` or by a command to generate random 12 | passwords. 13 | 14 | Deploy as follows: 15 | 16 | ``` 17 | $ kubectl create namespace playground 18 | $ adeploy -p jinja [-n ] render . 19 | $ adeploy -p jinja [-n ] test 20 | $ adeploy -p jinja [-n ] deploy 21 | ``` 22 | 23 | By default `adeploy` is using the project folder as deployment name (i.e. `002-secrets`). 24 | If you want to use another deployment name, pass it with `-n `. 25 | 26 | ## More Info 27 | 28 | * https://github.com/awesome-it/adeploy#jinja-secret-functions -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/prod/secret-6e1adb2c4c075e35335e851dd6ebc5f0f7397a80: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/prod/secret-6e1adb2c4c075e35335e851dd6ebc5f0f7397a80 -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/prod/secret-7e33ba97416ba4d45b6ce4c6c68b6aace36eacc5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/prod/secret-7e33ba97416ba4d45b6ce4c6c68b6aace36eacc5 -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/prod/secret-e5e0c551a537d65bcea7c18eb47badaf9c09c349: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/prod/secret-e5e0c551a537d65bcea7c18eb47badaf9c09c349 -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/test/secret-7929a442fae0ceee9eef9558a9a2ef02cc9d4421: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/test/secret-7929a442fae0ceee9eef9558a9a2ef02cc9d4421 -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/test/secret-dcf2a6e7bd78ee395f73f6434b19a9044790c00a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/test/secret-dcf2a6e7bd78ee395f73f6434b19a9044790c00a -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/test/secret-f310a9ad786b3fb5f7160436346e69795693b951: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets-ingress/build/jinja/002-secrets-ingress/secrets/playground/test/secret-f310a9ad786b3fb5f7160436346e69795693b951 -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/playground/002-secrets-ingress/prod/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 002-secrets-ingress-prod 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 002-secrets-ingress 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 002-secrets-ingress 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 002-secrets-ingress 26 | app.kubernetes.io/instance: prod 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | imagePullSecrets: 31 | - name: secret-7e33ba97416ba4d45b6ce4c6c68b6aace36eacc5 32 | containers: 33 | - name: main 34 | image: nginx:1.22 35 | imagePullPolicy: Always 36 | env: 37 | - name: MY_SECRET 38 | valueFrom: 39 | secretKeyRef: {'name': 'secret-e5e0c551a537d65bcea7c18eb47badaf9c09c349', 40 | 'key': 'my_secret'} 41 | ports: 42 | - name: http 43 | containerPort: 80 44 | - name: https 45 | containerPort: 443 46 | livenessProbe: 47 | httpGet: 48 | path: / 49 | port: 80 50 | initialDelaySeconds: 3 51 | timeoutSeconds: 2 52 | failureThreshold: 2 53 | readinessProbe: 54 | httpGet: 55 | path: / 56 | port: 80 57 | initialDelaySeconds: 3 58 | timeoutSeconds: 2 59 | failureThreshold: 2 60 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/playground/002-secrets-ingress/prod/ingress.yml: -------------------------------------------------------------------------------- 1 | kind: Ingress 2 | apiVersion: networking.k8s.io/v1 3 | metadata: 4 | name: 002-secrets-ingress-prod-ingress 5 | namespace: playground 6 | annotations: 7 | nginx.ingress.kubernetes.io/proxy-send-timeout: "300" 8 | nginx.ingress.kubernetes.io/proxy-read-timeout: "300" 9 | nginx.ingress.kubernetes.io/proxy-body-size: "50m" 10 | labels: 11 | app.kubernetes.io/part-of: 002-secrets-ingress 12 | app.kubernetes.io/instance: prod 13 | app.kubernetes.io/component: ingress 14 | # --8<-- [start:example-filter-yaml] 15 | spec: 16 | ingressClassName: external 17 | 18 | tls: 19 | - hosts: 20 | - mydomain.com 21 | secretName: secret-6e1adb2c4c075e35335e851dd6ebc5f0f7397a80 22 | 23 | 24 | # --8<-- [end:example-filter-yaml] 25 | rules: 26 | - host: mydomain.com 27 | http: 28 | paths: 29 | - path: / 30 | pathType: Prefix 31 | backend: 32 | service: 33 | name: myservice 34 | port: 35 | name: http 36 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/playground/002-secrets-ingress/test/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 002-secrets-ingress-test 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 002-secrets-ingress 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 002-secrets-ingress 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 002-secrets-ingress 26 | app.kubernetes.io/instance: test 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | imagePullSecrets: 31 | - name: secret-7929a442fae0ceee9eef9558a9a2ef02cc9d4421 32 | containers: 33 | - name: main 34 | image: nginx:1.23 35 | imagePullPolicy: Always 36 | env: 37 | - name: MY_SECRET 38 | valueFrom: 39 | secretKeyRef: {'name': 'secret-f310a9ad786b3fb5f7160436346e69795693b951', 40 | 'key': 'my_secret'} 41 | ports: 42 | - name: http 43 | containerPort: 80 44 | - name: https 45 | containerPort: 443 46 | livenessProbe: 47 | httpGet: 48 | path: / 49 | port: 80 50 | initialDelaySeconds: 3 51 | timeoutSeconds: 2 52 | failureThreshold: 2 53 | readinessProbe: 54 | httpGet: 55 | path: / 56 | port: 80 57 | initialDelaySeconds: 3 58 | timeoutSeconds: 2 59 | failureThreshold: 2 60 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/build/jinja/playground/002-secrets-ingress/test/ingress.yml: -------------------------------------------------------------------------------- 1 | kind: Ingress 2 | apiVersion: networking.k8s.io/v1 3 | metadata: 4 | name: 002-secrets-ingress-test-ingress 5 | namespace: playground 6 | annotations: 7 | nginx.ingress.kubernetes.io/proxy-send-timeout: "300" 8 | nginx.ingress.kubernetes.io/proxy-read-timeout: "300" 9 | nginx.ingress.kubernetes.io/proxy-body-size: "50m" 10 | labels: 11 | app.kubernetes.io/part-of: 002-secrets-ingress 12 | app.kubernetes.io/instance: test 13 | app.kubernetes.io/component: ingress 14 | # --8<-- [start:example-filter-yaml] 15 | spec: 16 | ingressClassName: external 17 | 18 | tls: 19 | - hosts: 20 | - mydomain.com 21 | secretName: secret-dcf2a6e7bd78ee395f73f6434b19a9044790c00a 22 | 23 | 24 | # --8<-- [end:example-filter-yaml] 25 | rules: 26 | - host: test.mydomain.com 27 | http: 28 | paths: 29 | - path: / 30 | pathType: Prefix 31 | backend: 32 | service: 33 | name: myservice 34 | port: 35 | name: http 36 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/defaults.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.23 3 | 4 | nginx: 5 | image: nginx -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/namespaces/playground/prod.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.22 3 | 4 | secrets: 5 | # See https://github.com/awesome-it/adeploy#jinja-secret-functions 6 | registry: {{ create_docker_registry_secret( 7 | server='registry.awesome-it.de', 8 | username='sa_registry_ro', 9 | custom_cmd=True, 10 | password='cat namespaces/playground/secrets/my_secret_prod') }} 11 | 12 | my_secret: {{ create_secret(as_ref=True, custom_cmd=True, my_secret='cat namespaces/playground/secrets/my_secret_prod') }} 13 | 14 | ingress: 15 | className: external 16 | annotations: 17 | nginx.ingress.kubernetes.io/proxy-send-timeout: 300 18 | nginx.ingress.kubernetes.io/proxy-read-timeout: 300 19 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 20 | hosts: 21 | - mydomain.com 22 | tls: 23 | - hosts: 24 | - mydomain.com 25 | secretName: {{ create_tls_secret( 26 | custom_cmd=True, 27 | cert='cat namespaces/playground/secrets/domain_prod/mydomain.com.crt', 28 | key='cat namespaces/playground/secrets/domain_prod/mydomain.com.key') }} -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/namespaces/playground/secrets/domain_prod/mydomain.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEDTCCAfUCFAGFXSSH5VQqWAOkjXbbsFU+89CQMA0GCSqGSIb3DQEBCwUAMEMx 3 | CzAJBgNVBAYTAkRFMQswCQYDVQQIDAJCVzESMBAGA1UEBwwJS2FybHNydWhlMRMw 4 | EQYDVQQKDApEdW1teSBJbmMuMB4XDTIxMDEwNzExNTExMloXDTIyMDUyMjExNTEx 5 | MlowQzELMAkGA1UEBhMCREUxCzAJBgNVBAgMAkJXMRIwEAYDVQQHDAlLYXJsc3J1 6 | aGUxEzARBgNVBAoMCkR1bW15IEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 7 | ggEKAoIBAQDXtmzy3L2FNlvPu/u8wu6arC7GnXkhIkOtuS3HydrSrfzcO/YjUafr 8 | o9Yw9SfYK1gfHcTYCCCKr1DOLOVmyU5ZkVUtJpljmg97l4ljvoNX6P4STWbOmCRE 9 | mPuOOlBruqabc478QUTz840RVRpUOEg3BDTgZ/AgetqJUcVJW+FBk3kIlO8AaEKx 10 | n9jZPhlZovuWJZdxk4qjsM1xnTs4Xlj/QyJzYsxuD7tXbNvWflQh1AKLkZ5aOj9x 11 | 4XhV2hizB82Lszn5lX6SReAKeR9BH6SfEjGHlNoC3DKRC82fJVUAhdLFcbl2if3r 12 | GneeIQ/ghkOXc+eXPU6vN4xqBFyBp/J/AgMBAAEwDQYJKoZIhvcNAQELBQADggIB 13 | AIJ2ta5YPwqYlCb4N3AkqLURC0a3BxRqeElLsGQRVekLGzUn/rp+vGJ3B38reC/7 14 | lW6LKXFU8D96hWPggzYJjVBIkrv5EZo12DfXv0z7UPOgy2piaRvrfpmkiwCgEZPQ 15 | R+d34rPY3rYcs7YIa7kbO0wAKSwdeUMhz1fhQuiJKgIKr0vFRrLHOdM5G0czPL7d 16 | Qc3QGfJ8Y8nJjg8DcbRNKNWuL5BWmCXD/WWFS9N3EUzVsnOQu4/4d0zXxw1LVIH8 17 | nClhhu92PgeFd067hWNH6iRTI79a/8mI3M5J+2OE71IIDqj5JNDKvD0bMf8oLuQj 18 | znNXTwH/V9z3iemsJXbqzzRLf8Uqt81V28L6fPdAShUnLCCXS1rz6RHYpkBqbUso 19 | hEY2wbvYl6SPvrsqCJ5PMzqH0EZcbx86V1Fd+CqbBlKMS1/rMBUQ+12/gxsJ0WcY 20 | IKFHyhNFgeUNpZt3uo2KmiotrCFS+IOd/Jdcjbn9O3JvhTQFXmdXaP2Pdqm6rVeu 21 | KxcQayRbw5HSQp9T08xJFuUfF2i5Vk6xgMlwWx9qNzHslKJjmcT5bYkDCv/L7cS6 22 | 6IWEggQai1pEs++U8rTHZHKBSL3Q63LgLMVSEgEsXLNPS+VQkU+2tLIsqFFR6FiP 23 | YZFF4v0S0UKute95q56ftVLEQhDJGrofWy3sZKlla52b 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/namespaces/playground/secrets/domain_prod/mydomain.com.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA17Zs8ty9hTZbz7v7vMLumqwuxp15ISJDrbktx8na0q383Dv2 3 | I1Gn66PWMPUn2CtYHx3E2Aggiq9QzizlZslOWZFVLSaZY5oPe5eJY76DV+j+Ek1m 4 | zpgkRJj7jjpQa7qmm3OO/EFE8/ONEVUaVDhINwQ04GfwIHraiVHFSVvhQZN5CJTv 5 | AGhCsZ/Y2T4ZWaL7liWXcZOKo7DNcZ07OF5Y/0Mic2LMbg+7V2zb1n5UIdQCi5Ge 6 | Wjo/ceF4VdoYswfNi7M5+ZV+kkXgCnkfQR+knxIxh5TaAtwykQvNnyVVAIXSxXG5 7 | don96xp3niEP4IZDl3Pnlz1OrzeMagRcgafyfwIDAQABAoIBAF0/RLVvapWtO97+ 8 | 2gFtGovOJqJA7F3AXBU62Wll/qvX/liNqwb1g2s/dZXQRBsUEZHR4oeoa7jHtFyL 9 | 19ao6q+ZPYK5DtGZhVvd08xETK6xzzLGNszTw8nLf+Kpnp4TH3ZPa93rsQzrmW2G 10 | pk0Fz2HI9bqT8592vAVkTa46g5M+izV/A4OuuY+hdUXaBq8r04EfuLFiSkh7HOA2 11 | Ht2GYtVmGnWzThlReDdTWHKTjkXXWwR871omiz3zK24gZC6VKcGSsPFbxYxKYw4S 12 | dIR5Rrl+r7v6U0dbNFdNxnBfuspZDQkyeQO+3g2X0kcnW/uH/ReHChk7X5ZR2o6+ 13 | NQ3o7uECgYEA+H3BKbcVfCozi1t2UjzkUefcIA3PLSsPMRku5L+1U2161MYxJXan 14 | N/BdDLRbGInOkFduscCaK+pwvew6hBeNtix5KtNcvkn17guGTfCfew03vlTG89Ur 15 | ArnNdJPAdGFKZy9kR4llNFtrCy+MDrC9EwnsFzoZaGnjrbqD6b4uFkkCgYEA3jsb 16 | QdZXsrfUpXm9CanMNhRCnlOQpN6aXo+ZFo0ktUrbTJNspLOjtKS/dbp0VeCDqH7Z 17 | dce/cBxyNzqna9g1CErtVfnPgWgs0V7YxP+gibEIuR2j/sdAanbOdkRJEjHbg5D/ 18 | IShL+IcxNHOzLQFEWX3uvcz6nTABwfHNuqNAoocCgYEAqBgBjCOCkCzIE3Q6lSUF 19 | 2nY7DR/qTwa6zx7W/vzEP3xmw/qSEmKyeX/KoiZ7HR1Ts4bBpdLBOAXuYDul1edN 20 | ALgS+yphqYPErlPzdVPZvlbRp5oXv6gq4TwpRLwSS2fo+eYwMsg5wvI4diei2ekq 21 | 7e8fWxL9Twmab9IlHAB/kqkCgYBKT+OGeYFr7tL53qKbB5+U+eNpBDKbHyDpvAUK 22 | KHp88SIyEh5DWRrF/k1TtdzPFruP7ZMUMo5OlASReVig1HSvaDbDCD0eXdKW1KuR 23 | /JUXVg6/sCy1trVQpJfXrm/s2KU58pON5+a3naWTj5j71K+haV4bM98eDv6Xdx8/ 24 | aPXlIwKBgQDz9TGYW2nM3GWVQSds/y78He/9p8wsbKgvjSyU0JfulK88eYGNsNho 25 | lnUqJtp1zChmcVqRN2f8m9XX59Kgt90RnlCQ0Vl010ovo+y8bCmbsjHzI2SlZ012 26 | 4jzbJHDRq1er3/Euz59jAoELTecROcMno/Sm+VTLLc6E2ufzXB5JGw== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/namespaces/playground/secrets/domain_test/mydomain.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEDTCCAfUCFAGFXSSH5VQqWAOkjXbbsFU+89CQMA0GCSqGSIb3DQEBCwUAMEMx 3 | CzAJBgNVBAYTAkRFMQswCQYDVQQIDAJCVzESMBAGA1UEBwwJS2FybHNydWhlMRMw 4 | EQYDVQQKDApEdW1teSBJbmMuMB4XDTIxMDEwNzExNTExMloXDTIyMDUyMjExNTEx 5 | MlowQzELMAkGA1UEBhMCREUxCzAJBgNVBAgMAkJXMRIwEAYDVQQHDAlLYXJsc3J1 6 | aGUxEzARBgNVBAoMCkR1bW15IEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 7 | ggEKAoIBAQDXtmzy3L2FNlvPu/u8wu6arC7GnXkhIkOtuS3HydrSrfzcO/YjUafr 8 | o9Yw9SfYK1gfHcTYCCCKr1DOLOVmyU5ZkVUtJpljmg97l4ljvoNX6P4STWbOmCRE 9 | mPuOOlBruqabc478QUTz840RVRpUOEg3BDTgZ/AgetqJUcVJW+FBk3kIlO8AaEKx 10 | n9jZPhlZovuWJZdxk4qjsM1xnTs4Xlj/QyJzYsxuD7tXbNvWflQh1AKLkZ5aOj9x 11 | 4XhV2hizB82Lszn5lX6SReAKeR9BH6SfEjGHlNoC3DKRC82fJVUAhdLFcbl2if3r 12 | GneeIQ/ghkOXc+eXPU6vN4xqBFyBp/J/AgMBAAEwDQYJKoZIhvcNAQELBQADggIB 13 | AIJ2ta5YPwqYlCb4N3AkqLURC0a3BxRqeElLsGQRVekLGzUn/rp+vGJ3B38reC/7 14 | lW6LKXFU8D96hWPggzYJjVBIkrv5EZo12DfXv0z7UPOgy2piaRvrfpmkiwCgEZPQ 15 | R+d34rPY3rYcs7YIa7kbO0wAKSwdeUMhz1fhQuiJKgIKr0vFRrLHOdM5G0czPL7d 16 | Qc3QGfJ8Y8nJjg8DcbRNKNWuL5BWmCXD/WWFS9N3EUzVsnOQu4/4d0zXxw1LVIH8 17 | nClhhu92PgeFd067hWNH6iRTI79a/8mI3M5J+2OE71IIDqj5JNDKvD0bMf8oLuQj 18 | znNXTwH/V9z3iemsJXbqzzRLf8Uqt81V28L6fPdAShUnLCCXS1rz6RHYpkBqbUso 19 | hEY2wbvYl6SPvrsqCJ5PMzqH0EZcbx86V1Fd+CqbBlKMS1/rMBUQ+12/gxsJ0WcY 20 | IKFHyhNFgeUNpZt3uo2KmiotrCFS+IOd/Jdcjbn9O3JvhTQFXmdXaP2Pdqm6rVeu 21 | KxcQayRbw5HSQp9T08xJFuUfF2i5Vk6xgMlwWx9qNzHslKJjmcT5bYkDCv/L7cS6 22 | 6IWEggQai1pEs++U8rTHZHKBSL3Q63LgLMVSEgEsXLNPS+VQkU+2tLIsqFFR6FiP 23 | YZFF4v0S0UKute95q56ftVLEQhDJGrofWy3sZKlla52b 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/namespaces/playground/secrets/domain_test/mydomain.com.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA17Zs8ty9hTZbz7v7vMLumqwuxp15ISJDrbktx8na0q383Dv2 3 | I1Gn66PWMPUn2CtYHx3E2Aggiq9QzizlZslOWZFVLSaZY5oPe5eJY76DV+j+Ek1m 4 | zpgkRJj7jjpQa7qmm3OO/EFE8/ONEVUaVDhINwQ04GfwIHraiVHFSVvhQZN5CJTv 5 | AGhCsZ/Y2T4ZWaL7liWXcZOKo7DNcZ07OF5Y/0Mic2LMbg+7V2zb1n5UIdQCi5Ge 6 | Wjo/ceF4VdoYswfNi7M5+ZV+kkXgCnkfQR+knxIxh5TaAtwykQvNnyVVAIXSxXG5 7 | don96xp3niEP4IZDl3Pnlz1OrzeMagRcgafyfwIDAQABAoIBAF0/RLVvapWtO97+ 8 | 2gFtGovOJqJA7F3AXBU62Wll/qvX/liNqwb1g2s/dZXQRBsUEZHR4oeoa7jHtFyL 9 | 19ao6q+ZPYK5DtGZhVvd08xETK6xzzLGNszTw8nLf+Kpnp4TH3ZPa93rsQzrmW2G 10 | pk0Fz2HI9bqT8592vAVkTa46g5M+izV/A4OuuY+hdUXaBq8r04EfuLFiSkh7HOA2 11 | Ht2GYtVmGnWzThlReDdTWHKTjkXXWwR871omiz3zK24gZC6VKcGSsPFbxYxKYw4S 12 | dIR5Rrl+r7v6U0dbNFdNxnBfuspZDQkyeQO+3g2X0kcnW/uH/ReHChk7X5ZR2o6+ 13 | NQ3o7uECgYEA+H3BKbcVfCozi1t2UjzkUefcIA3PLSsPMRku5L+1U2161MYxJXan 14 | N/BdDLRbGInOkFduscCaK+pwvew6hBeNtix5KtNcvkn17guGTfCfew03vlTG89Ur 15 | ArnNdJPAdGFKZy9kR4llNFtrCy+MDrC9EwnsFzoZaGnjrbqD6b4uFkkCgYEA3jsb 16 | QdZXsrfUpXm9CanMNhRCnlOQpN6aXo+ZFo0ktUrbTJNspLOjtKS/dbp0VeCDqH7Z 17 | dce/cBxyNzqna9g1CErtVfnPgWgs0V7YxP+gibEIuR2j/sdAanbOdkRJEjHbg5D/ 18 | IShL+IcxNHOzLQFEWX3uvcz6nTABwfHNuqNAoocCgYEAqBgBjCOCkCzIE3Q6lSUF 19 | 2nY7DR/qTwa6zx7W/vzEP3xmw/qSEmKyeX/KoiZ7HR1Ts4bBpdLBOAXuYDul1edN 20 | ALgS+yphqYPErlPzdVPZvlbRp5oXv6gq4TwpRLwSS2fo+eYwMsg5wvI4diei2ekq 21 | 7e8fWxL9Twmab9IlHAB/kqkCgYBKT+OGeYFr7tL53qKbB5+U+eNpBDKbHyDpvAUK 22 | KHp88SIyEh5DWRrF/k1TtdzPFruP7ZMUMo5OlASReVig1HSvaDbDCD0eXdKW1KuR 23 | /JUXVg6/sCy1trVQpJfXrm/s2KU58pON5+a3naWTj5j71K+haV4bM98eDv6Xdx8/ 24 | aPXlIwKBgQDz9TGYW2nM3GWVQSds/y78He/9p8wsbKgvjSyU0JfulK88eYGNsNho 25 | lnUqJtp1zChmcVqRN2f8m9XX59Kgt90RnlCQ0Vl010ovo+y8bCmbsjHzI2SlZ012 26 | 4jzbJHDRq1er3/Euz59jAoELTecROcMno/Sm+VTLLc6E2ufzXB5JGw== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/namespaces/playground/secrets/my_secret_prod: -------------------------------------------------------------------------------- 1 | super_secret -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/namespaces/playground/secrets/my_secret_test: -------------------------------------------------------------------------------- 1 | super_secret -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # Inherit from defaults.yml 2 | #versions: 3 | # nginx: 4 | 5 | secrets: 6 | registry: {{ create_docker_registry_secret( 7 | server='registry.awesome-it.de', 8 | username='sa_registry_ro', 9 | custom_cmd=True, 10 | password='cat namespaces/playground/secrets/my_secret_test') }} 11 | 12 | my_secret: {{ create_secret(as_ref=True, custom_cmd=True, my_secret='cat namespaces/playground/secrets/my_secret_test') }} 13 | 14 | 15 | ingress: 16 | className: external 17 | annotations: 18 | nginx.ingress.kubernetes.io/proxy-send-timeout: 300 19 | nginx.ingress.kubernetes.io/proxy-read-timeout: 300 20 | nginx.ingress.kubernetes.io/proxy-body-size: 50m 21 | hosts: 22 | - test.mydomain.com 23 | tls: 24 | - hosts: 25 | - mydomain.com 26 | secretName: {{ create_tls_secret( 27 | custom_cmd=True, 28 | cert='cat namespaces/playground/secrets/domain_test/mydomain.com.crt', 29 | key='cat namespaces/playground/secrets/domain_test/mydomain.com.key') }} -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/templates/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }} 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: {{ name }} 26 | app.kubernetes.io/instance: {{ release }} 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | imagePullSecrets: 31 | - name: {{ secrets.registry }} 32 | containers: 33 | - name: main 34 | image: {{ nginx.image }}:{{ version('nginx') }} 35 | imagePullPolicy: Always 36 | env: 37 | - name: MY_SECRET 38 | valueFrom: 39 | secretKeyRef: {{ secrets.my_secret }} 40 | ports: 41 | - name: http 42 | containerPort: 80 43 | - name: https 44 | containerPort: 443 45 | livenessProbe: 46 | httpGet: 47 | path: / 48 | port: 80 49 | initialDelaySeconds: 3 50 | timeoutSeconds: 2 51 | failureThreshold: 2 52 | readinessProbe: 53 | httpGet: 54 | path: / 55 | port: 80 56 | initialDelaySeconds: 3 57 | timeoutSeconds: 2 58 | failureThreshold: 2 59 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets-ingress/templates/ingress.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Ingress 3 | apiVersion: networking.k8s.io/v1 4 | metadata: 5 | name: {{ name }}-{{ release }}-ingress 6 | namespace: {{ namespace }} 7 | annotations: 8 | {% for name, value in ingress.get('annotations', deployment.get('ingress.annotations', {})).items() %} 9 | {{ name }}: "{{ value }}" 10 | {% endfor %} 11 | labels: 12 | app.kubernetes.io/part-of: {{ name }} 13 | app.kubernetes.io/instance: {{ release }} 14 | app.kubernetes.io/component: ingress 15 | # --8<-- [start:example-filter-yaml] 16 | spec: 17 | ingressClassName: {{ ingress.className }} 18 | {% if ingress.get('tls', False) %} 19 | tls: 20 | {{ ingress.get('tls') | yaml(false) | indent(4) }} 21 | {% endif %} 22 | # --8<-- [end:example-filter-yaml] 23 | rules: 24 | {% for host in ingress.get('hosts') %} 25 | - host: {{ host }} 26 | http: 27 | paths: 28 | - path: / 29 | pathType: Prefix 30 | backend: 31 | service: 32 | name: myservice 33 | port: 34 | name: http 35 | {% endfor %} -------------------------------------------------------------------------------- /examples/jinja/002-secrets/README.md: -------------------------------------------------------------------------------- 1 | # Create Secrets 2 | 3 | An example deployment that creates secrets for a Jinja based `adeploy` project that includes: 4 | 5 | * namespace `playground`, 6 | * two releases: `prod`,`test` and 7 | * an `ImagePullSecret` and an environment variable `my_secret` that was added by `adeploy`. 8 | 9 | For demonstration purpose, we are using `cat secrets/my_secret` to retrieve secrets. But in practise this 10 | should be replaced with a password tool i.e. `gopass`, `Ansible Vault` or `Vault by HashiCorp` or by a command 11 | to generate random passwords. 12 | 13 | Deploy as follows: 14 | 15 | ``` 16 | $ kubectl create namespace playground 17 | $ adeploy -p jinja [-n ] render . 18 | $ adeploy -p jinja [-n ] test 19 | $ adeploy -p jinja [-n ] deploy 20 | ``` 21 | 22 | By default `adeploy` is using the project folder as deployment name (i.e. `002-secrets`). 23 | If you want to use another deployment name, pass it with `-n `. 24 | 25 | ## More Info 26 | 27 | * https://github.com/awesome-it/adeploy#jinja-secret-functions -------------------------------------------------------------------------------- /examples/jinja/002-secrets/build/jinja/002-secrets/secrets/playground/prod/secret-7e33ba97416ba4d45b6ce4c6c68b6aace36eacc5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets/build/jinja/002-secrets/secrets/playground/prod/secret-7e33ba97416ba4d45b6ce4c6c68b6aace36eacc5 -------------------------------------------------------------------------------- /examples/jinja/002-secrets/build/jinja/002-secrets/secrets/playground/prod/secret-e5e0c551a537d65bcea7c18eb47badaf9c09c349: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets/build/jinja/002-secrets/secrets/playground/prod/secret-e5e0c551a537d65bcea7c18eb47badaf9c09c349 -------------------------------------------------------------------------------- /examples/jinja/002-secrets/build/jinja/002-secrets/secrets/playground/test/secret-7929a442fae0ceee9eef9558a9a2ef02cc9d4421: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets/build/jinja/002-secrets/secrets/playground/test/secret-7929a442fae0ceee9eef9558a9a2ef02cc9d4421 -------------------------------------------------------------------------------- /examples/jinja/002-secrets/build/jinja/002-secrets/secrets/playground/test/secret-f310a9ad786b3fb5f7160436346e69795693b951: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-it/adeploy/ce0a1c70b6baab8f08ad6fe7a1d12c27cd727a3a/examples/jinja/002-secrets/build/jinja/002-secrets/secrets/playground/test/secret-f310a9ad786b3fb5f7160436346e69795693b951 -------------------------------------------------------------------------------- /examples/jinja/002-secrets/build/jinja/playground/002-secrets/prod/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 002-secrets-prod 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 002-secrets 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 002-secrets 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 002-secrets 26 | app.kubernetes.io/instance: prod 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | imagePullSecrets: 31 | - name: secret-7e33ba97416ba4d45b6ce4c6c68b6aace36eacc5 32 | containers: 33 | - name: main 34 | image: nginx:1.22 35 | imagePullPolicy: Always 36 | # --8<-- [start:example-ref] 37 | env: 38 | - name: MY_SECRET 39 | valueFrom: 40 | secretKeyRef: {'name': 'secret-e5e0c551a537d65bcea7c18eb47badaf9c09c349', 41 | 'key': 'my_secret'} 42 | # --8<-- [end:example-ref] 43 | ports: 44 | - name: http 45 | containerPort: 80 46 | - name: https 47 | containerPort: 443 48 | livenessProbe: 49 | httpGet: 50 | path: / 51 | port: 80 52 | initialDelaySeconds: 3 53 | timeoutSeconds: 2 54 | failureThreshold: 2 55 | readinessProbe: 56 | httpGet: 57 | path: / 58 | port: 80 59 | initialDelaySeconds: 3 60 | timeoutSeconds: 2 61 | failureThreshold: 2 62 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets/build/jinja/playground/002-secrets/test/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 002-secrets-test 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 002-secrets 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 002-secrets 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 002-secrets 26 | app.kubernetes.io/instance: test 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | imagePullSecrets: 31 | - name: secret-7929a442fae0ceee9eef9558a9a2ef02cc9d4421 32 | containers: 33 | - name: main 34 | image: nginx:1.23 35 | imagePullPolicy: Always 36 | # --8<-- [start:example-ref] 37 | env: 38 | - name: MY_SECRET 39 | valueFrom: 40 | secretKeyRef: {'name': 'secret-f310a9ad786b3fb5f7160436346e69795693b951', 41 | 'key': 'my_secret'} 42 | # --8<-- [end:example-ref] 43 | ports: 44 | - name: http 45 | containerPort: 80 46 | - name: https 47 | containerPort: 443 48 | livenessProbe: 49 | httpGet: 50 | path: / 51 | port: 80 52 | initialDelaySeconds: 3 53 | timeoutSeconds: 2 54 | failureThreshold: 2 55 | readinessProbe: 56 | httpGet: 57 | path: / 58 | port: 80 59 | initialDelaySeconds: 3 60 | timeoutSeconds: 2 61 | failureThreshold: 2 62 | -------------------------------------------------------------------------------- /examples/jinja/002-secrets/defaults.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.23 3 | 4 | nginx: 5 | image: nginx -------------------------------------------------------------------------------- /examples/jinja/002-secrets/namespaces/playground/prod.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.22 3 | 4 | secrets: 5 | registry: {{ create_docker_registry_secret( 6 | server='registry.awesome-it.de', 7 | username='sa_registry_ro', 8 | custom_cmd=True, 9 | password='cat namespaces/playground/secrets/my_secret_prod') }} 10 | 11 | # --8<-- [start:example-ref] 12 | my_secret: {{ create_secret(as_ref=True, custom_cmd=True, my_secret='cat namespaces/playground/secrets/my_secret_prod') }} 13 | # --8<-- [end:example-ref] -------------------------------------------------------------------------------- /examples/jinja/002-secrets/namespaces/playground/secrets/my_secret_prod: -------------------------------------------------------------------------------- 1 | super_secret -------------------------------------------------------------------------------- /examples/jinja/002-secrets/namespaces/playground/secrets/my_secret_test: -------------------------------------------------------------------------------- 1 | super_secret -------------------------------------------------------------------------------- /examples/jinja/002-secrets/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # Inherit from defaults.yml 2 | #versions: 3 | # nginx: 4 | 5 | secrets: 6 | registry: {{ create_docker_registry_secret( 7 | server='registry.awesome-it.de', 8 | username='sa_registry_ro', 9 | custom_cmd=True, 10 | password='cat namespaces/playground/secrets/my_secret_test') }} 11 | 12 | my_secret: {{ create_secret(as_ref=True, custom_cmd=True, my_secret='cat namespaces/playground/secrets/my_secret_test') }} -------------------------------------------------------------------------------- /examples/jinja/002-secrets/templates/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }} 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: {{ name }} 26 | app.kubernetes.io/instance: {{ release }} 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | imagePullSecrets: 31 | - name: {{ secrets.registry }} 32 | containers: 33 | - name: main 34 | image: {{ nginx.image }}:{{ version('nginx') }} 35 | imagePullPolicy: Always 36 | # --8<-- [start:example-ref] 37 | env: 38 | - name: MY_SECRET 39 | valueFrom: 40 | secretKeyRef: {{ secrets.my_secret }} 41 | # --8<-- [end:example-ref] 42 | ports: 43 | - name: http 44 | containerPort: 80 45 | - name: https 46 | containerPort: 443 47 | livenessProbe: 48 | httpGet: 49 | path: / 50 | port: 80 51 | initialDelaySeconds: 3 52 | timeoutSeconds: 2 53 | failureThreshold: 2 54 | readinessProbe: 55 | httpGet: 56 | path: / 57 | port: 80 58 | initialDelaySeconds: 3 59 | timeoutSeconds: 2 60 | failureThreshold: 2 61 | -------------------------------------------------------------------------------- /examples/jinja/003-include/README.md: -------------------------------------------------------------------------------- 1 | # Create Secrets 2 | 3 | A Jinja based `adeploy` project that includes: 4 | 5 | * namespace `playground`, 6 | * two releases: `prod`,`test` and 7 | * two deployments that are using a shared, single environment file using `include_file()` and 8 | * a config map that includes files from the folder `files`. 9 | 10 | Deploy as follows: 11 | 12 | ``` 13 | $ kubectl create namespace playground 14 | $ adeploy -p jinja [-n ] render . 15 | $ adeploy -p jinja [-n ] test 16 | $ adeploy -p jinja [-n ] deploy 17 | ``` 18 | 19 | By default `adeploy` is using the project folder as deployment name (i.e. `003-include-files`). 20 | If you want to use another deployment name, pass it with `-n `. 21 | 22 | ## More Info 23 | 24 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja -------------------------------------------------------------------------------- /examples/jinja/003-include/build/jinja/playground/003-include/prod/common/configmap.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: 003-include-prod-config 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 003-include 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: config 10 | data: 11 | nginx.conf: | 12 | user nginx; 13 | worker_processes auto; 14 | 15 | error_log /var/log/nginx/error.log notice; 16 | pid /var/run/nginx.pid; 17 | 18 | 19 | events { 20 | worker_connections 1024; 21 | } 22 | 23 | 24 | http { 25 | include /etc/nginx/mime.types; 26 | default_type application/octet-stream; 27 | 28 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 29 | '$status $body_bytes_sent "$http_referer" ' 30 | '"$http_user_agent" "$http_x_forwarded_for"'; 31 | 32 | access_log /var/log/nginx/access.log main; 33 | 34 | sendfile on; 35 | #tcp_nopush on; 36 | 37 | keepalive_timeout 65; 38 | 39 | #gzip on; 40 | 41 | include /etc/nginx/conf.d/*.conf; 42 | } 43 | 44 | alpha.json: | 45 | { 46 | "name": "Alpha", 47 | "content": "This is a config file to include in configmap.yml" 48 | } 49 | 50 | beta.json: | 51 | { 52 | "name": "Beta", 53 | "content": "This is a another config file to include in configmap.yml" 54 | } 55 | -------------------------------------------------------------------------------- /examples/jinja/003-include/build/jinja/playground/003-include/prod/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 003-include-prod-nginx 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 003-include 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 003-include 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | # --8<-- [start:template] --> 23 | # --8<-- [start:example-sha256] --> 24 | template: 25 | metadata: 26 | labels: 27 | app.kubernetes.io/part-of: 003-include 28 | app.kubernetes.io/instance: prod 29 | app.kubernetes.io/component: nginx 30 | annotations: 31 | checksum/config: | 32 | d5a2d45ba64a1c3d60f8f762cb416a2869dfad97e34fa74f05b4fad2a208a86e 33 | # --8<-- [end:example-sha256] --> 34 | spec: 35 | affinity: 36 | podAffinity: 37 | requiredDuringSchedulingIgnoredDuringExecution: 38 | - labelSelector: 39 | matchExpressions: 40 | - key: app.kubernetes.io/instance 41 | operator: In 42 | values: 43 | - prod 44 | - key: app.kubernetes.io/component 45 | operator: In 46 | values: 47 | - back 48 | - key: app.kubernetes.io/part-of 49 | operator: In 50 | values: 51 | - 003-include 52 | topologyKey: "kubernetes.io/hostname" 53 | containers: 54 | - name: main 55 | image: nginx:1.22 56 | imagePullPolicy: Always 57 | 58 | env: 59 | - name: VAR1 60 | value: "my_common_var" 61 | - name: VAR2 62 | value: "this_is_my_variable" 63 | - name: VAR2 64 | value: "Scripts or keys including newslines are supported by Jinja" 65 | volumeMounts: 66 | - mountPath: /etc/nginx/nginx.conf 67 | name: config 68 | subPath: nginx.conf 69 | readOnly: true 70 | volumes: 71 | - name: config 72 | configMap: 73 | name: 003-include-prod-config 74 | # --8<-- [end:template] --> 75 | -------------------------------------------------------------------------------- /examples/jinja/003-include/build/jinja/playground/003-include/prod/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 003-include-prod-redis 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 003-include 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 003-include 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | # --8<-- [start:template] --> 23 | template: 24 | metadata: 25 | labels: 26 | app.kubernetes.io/part-of: 003-include 27 | app.kubernetes.io/instance: prod 28 | app.kubernetes.io/component: redis 29 | annotations: 30 | checksum/config: | 31 | d5a2d45ba64a1c3d60f8f762cb416a2869dfad97e34fa74f05b4fad2a208a86e 32 | spec: 33 | affinity: 34 | podAffinity: 35 | requiredDuringSchedulingIgnoredDuringExecution: 36 | - labelSelector: 37 | matchExpressions: 38 | - key: app.kubernetes.io/instance 39 | operator: In 40 | values: 41 | - prod 42 | - key: app.kubernetes.io/component 43 | operator: In 44 | values: 45 | - back 46 | - key: app.kubernetes.io/part-of 47 | operator: In 48 | values: 49 | - 003-include 50 | topologyKey: "kubernetes.io/hostname" 51 | containers: 52 | - name: main 53 | image: redis:7 54 | imagePullPolicy: Always 55 | 56 | env: 57 | - name: VAR1 58 | value: "my_common_var" 59 | - name: VAR2 60 | value: "this_is_my_variable" 61 | - name: VAR2 62 | value: "Scripts or keys including newslines are supported by Jinja" 63 | ports: 64 | - name: redis 65 | containerPort: 6379 66 | livenessProbe: 67 | exec: 68 | command: 69 | - redis-cli 70 | - ping 71 | initialDelaySeconds: 5 72 | timeoutSeconds: 5 73 | readinessProbe: 74 | exec: 75 | command: 76 | - redis-cli 77 | - ping 78 | initialDelaySeconds: 5 79 | timeoutSeconds: 5 80 | # --8<-- [end:template] --> 81 | -------------------------------------------------------------------------------- /examples/jinja/003-include/build/jinja/playground/003-include/test/common/configmap.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: 003-include-test-config 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 003-include 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: config 10 | data: 11 | nginx.conf: | 12 | user nginx; 13 | worker_processes auto; 14 | 15 | error_log /var/log/nginx/error.log notice; 16 | pid /var/run/nginx.pid; 17 | 18 | 19 | events { 20 | worker_connections 1024; 21 | } 22 | 23 | 24 | http { 25 | include /etc/nginx/mime.types; 26 | default_type application/octet-stream; 27 | 28 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 29 | '$status $body_bytes_sent "$http_referer" ' 30 | '"$http_user_agent" "$http_x_forwarded_for"'; 31 | 32 | access_log /var/log/nginx/access.log main; 33 | 34 | sendfile on; 35 | #tcp_nopush on; 36 | 37 | keepalive_timeout 65; 38 | 39 | #gzip on; 40 | 41 | include /etc/nginx/conf.d/*.conf; 42 | } 43 | 44 | alpha.json: | 45 | { 46 | "name": "Alpha", 47 | "content": "This is a config file to include in configmap.yml" 48 | } 49 | 50 | beta.json: | 51 | { 52 | "name": "Beta", 53 | "content": "This is a another config file to include in configmap.yml" 54 | } 55 | -------------------------------------------------------------------------------- /examples/jinja/003-include/build/jinja/playground/003-include/test/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 003-include-test-nginx 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 003-include 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 003-include 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | # --8<-- [start:template] --> 23 | # --8<-- [start:example-sha256] --> 24 | template: 25 | metadata: 26 | labels: 27 | app.kubernetes.io/part-of: 003-include 28 | app.kubernetes.io/instance: test 29 | app.kubernetes.io/component: nginx 30 | annotations: 31 | checksum/config: | 32 | 03f8a593782c48c9746a99f2797d1ea8b8755a3957b85e55a640919c8beee1ce 33 | # --8<-- [end:example-sha256] --> 34 | spec: 35 | affinity: 36 | podAffinity: 37 | requiredDuringSchedulingIgnoredDuringExecution: 38 | - labelSelector: 39 | matchExpressions: 40 | - key: app.kubernetes.io/instance 41 | operator: In 42 | values: 43 | - test 44 | - key: app.kubernetes.io/component 45 | operator: In 46 | values: 47 | - back 48 | - key: app.kubernetes.io/part-of 49 | operator: In 50 | values: 51 | - 003-include 52 | topologyKey: "kubernetes.io/hostname" 53 | containers: 54 | - name: main 55 | image: nginx:1.23 56 | imagePullPolicy: Always 57 | 58 | env: 59 | - name: VAR1 60 | value: "my_common_var" 61 | - name: VAR2 62 | value: "this_is_my_variable" 63 | - name: VAR2 64 | value: "Scripts or keys including newslines are supported by Jinja" 65 | volumeMounts: 66 | - mountPath: /etc/nginx/nginx.conf 67 | name: config 68 | subPath: nginx.conf 69 | readOnly: true 70 | volumes: 71 | - name: config 72 | configMap: 73 | name: 003-include-test-config 74 | # --8<-- [end:template] --> 75 | -------------------------------------------------------------------------------- /examples/jinja/003-include/build/jinja/playground/003-include/test/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 003-include-test-redis 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 003-include 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 003-include 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | # --8<-- [start:template] --> 23 | template: 24 | metadata: 25 | labels: 26 | app.kubernetes.io/part-of: 003-include 27 | app.kubernetes.io/instance: test 28 | app.kubernetes.io/component: redis 29 | annotations: 30 | checksum/config: | 31 | 03f8a593782c48c9746a99f2797d1ea8b8755a3957b85e55a640919c8beee1ce 32 | spec: 33 | affinity: 34 | podAffinity: 35 | requiredDuringSchedulingIgnoredDuringExecution: 36 | - labelSelector: 37 | matchExpressions: 38 | - key: app.kubernetes.io/instance 39 | operator: In 40 | values: 41 | - test 42 | - key: app.kubernetes.io/component 43 | operator: In 44 | values: 45 | - back 46 | - key: app.kubernetes.io/part-of 47 | operator: In 48 | values: 49 | - 003-include 50 | topologyKey: "kubernetes.io/hostname" 51 | containers: 52 | - name: main 53 | image: redis:7 54 | imagePullPolicy: Always 55 | 56 | env: 57 | - name: VAR1 58 | value: "my_common_var" 59 | - name: VAR2 60 | value: "this_is_my_variable" 61 | - name: VAR2 62 | value: "Scripts or keys including newslines are supported by Jinja" 63 | ports: 64 | - name: redis 65 | containerPort: 6379 66 | livenessProbe: 67 | exec: 68 | command: 69 | - redis-cli 70 | - ping 71 | initialDelaySeconds: 5 72 | timeoutSeconds: 5 73 | readinessProbe: 74 | exec: 75 | command: 76 | - redis-cli 77 | - ping 78 | initialDelaySeconds: 5 79 | timeoutSeconds: 5 80 | # --8<-- [end:template] --> 81 | -------------------------------------------------------------------------------- /examples/jinja/003-include/defaults.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.23 3 | redis: 7 4 | 5 | nginx: 6 | image: nginx 7 | 8 | redis: 9 | image: redis 10 | 11 | common: 12 | my_env_var: this_is_my_variable 13 | another_env_var: | 14 | Scripts or keys including newslines 15 | are supported by Jinja -------------------------------------------------------------------------------- /examples/jinja/003-include/namespaces/playground/prod.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.22 -------------------------------------------------------------------------------- /examples/jinja/003-include/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # Inherit from defaults.yml 2 | #versions: 3 | # nginx: -------------------------------------------------------------------------------- /examples/jinja/003-include/templates/common/__affinity.yml: -------------------------------------------------------------------------------- 1 | affinity: 2 | podAffinity: 3 | requiredDuringSchedulingIgnoredDuringExecution: 4 | - labelSelector: 5 | matchExpressions: 6 | - key: app.kubernetes.io/instance 7 | operator: In 8 | values: 9 | - {{ release }} 10 | - key: app.kubernetes.io/component 11 | operator: In 12 | values: 13 | - back 14 | - key: app.kubernetes.io/part-of 15 | operator: In 16 | values: 17 | - {{ name }} 18 | topologyKey: "kubernetes.io/hostname" -------------------------------------------------------------------------------- /examples/jinja/003-include/templates/common/__env.yml: -------------------------------------------------------------------------------- 1 | env: 2 | - name: VAR1 3 | value: "my_common_var" 4 | - name: VAR2 5 | value: "{{ common.my_env_var }}" 6 | - name: VAR2 7 | value: "{{ common.another_env_var }}" -------------------------------------------------------------------------------- /examples/jinja/003-include/templates/common/configmap.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ name }}-{{ release }}-config 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: config 10 | data: 11 | nginx.conf: {{ include_file('files/nginx.conf', render=False) }} 12 | {% for name, content in list_dir('files/conf.d', render=False).items() %} 13 | {{ name }}: {{ content }} 14 | {% endfor %} -------------------------------------------------------------------------------- /examples/jinja/003-include/templates/files/conf.d/alpha.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Alpha", 3 | "content": "This is a config file to include in configmap.yml" 4 | } -------------------------------------------------------------------------------- /examples/jinja/003-include/templates/files/conf.d/beta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Beta", 3 | "content": "This is a another config file to include in configmap.yml" 4 | } -------------------------------------------------------------------------------- /examples/jinja/003-include/templates/files/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes auto; 3 | 4 | error_log /var/log/nginx/error.log notice; 5 | pid /var/run/nginx.pid; 6 | 7 | 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | 23 | sendfile on; 24 | #tcp_nopush on; 25 | 26 | keepalive_timeout 65; 27 | 28 | #gzip on; 29 | 30 | include /etc/nginx/conf.d/*.conf; 31 | } -------------------------------------------------------------------------------- /examples/jinja/003-include/templates/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }}-nginx 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | # --8<-- [start:template] --> 23 | # --8<-- [start:example-sha256] --> 24 | template: 25 | metadata: 26 | labels: 27 | app.kubernetes.io/part-of: {{ name }} 28 | app.kubernetes.io/instance: {{ release }} 29 | app.kubernetes.io/component: nginx 30 | annotations: 31 | checksum/config: | 32 | {{ include_file("common/configmap.yml") | sha256sum }} 33 | # --8<-- [end:example-sha256] --> 34 | spec: 35 | {{ include_file('common/__affinity.yml', direct=True, indent=6) }} 36 | containers: 37 | - name: main 38 | image: {{ nginx.image }}:{{ version('nginx') }} 39 | imagePullPolicy: Always 40 | {{ include_file('common/__env.yml', direct=True, indent=10) }} 41 | volumeMounts: 42 | - mountPath: /etc/nginx/nginx.conf 43 | name: config 44 | subPath: nginx.conf 45 | readOnly: true 46 | volumes: 47 | - name: config 48 | configMap: 49 | name: {{ name }}-{{ release }}-config 50 | # --8<-- [end:template] --> -------------------------------------------------------------------------------- /examples/jinja/003-include/templates/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }}-redis 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | # --8<-- [start:template] --> 23 | template: 24 | metadata: 25 | labels: 26 | app.kubernetes.io/part-of: {{ name }} 27 | app.kubernetes.io/instance: {{ release }} 28 | app.kubernetes.io/component: redis 29 | annotations: 30 | checksum/config: | 31 | {{ include_file("common/configmap.yml") | sha256sum }} 32 | spec: 33 | {{ include_file('common/__affinity.yml', direct=True, indent=6) }} 34 | containers: 35 | - name: main 36 | image: {{ redis.image }}:{{ version('redis') }} 37 | imagePullPolicy: Always 38 | {{ include_file('common/__env.yml', direct=True, indent=10) }} 39 | ports: 40 | - name: redis 41 | containerPort: 6379 42 | livenessProbe: 43 | exec: 44 | command: 45 | - redis-cli 46 | - ping 47 | initialDelaySeconds: 5 48 | timeoutSeconds: 5 49 | readinessProbe: 50 | exec: 51 | command: 52 | - redis-cli 53 | - ping 54 | initialDelaySeconds: 5 55 | timeoutSeconds: 5 56 | # --8<-- [end:template] --> -------------------------------------------------------------------------------- /examples/jinja/004-probes/README.md: -------------------------------------------------------------------------------- 1 | # Create Secrets 2 | 3 | A Jinja based `adeploy` project that includes: 4 | 5 | * namespace `playground`, 6 | * two releases: `prod`,`test` and 7 | * a global probes configuration for all deployments defined in `defaults.yml`. 8 | 9 | Note that a global probes configuration makes sense if you deploy a larger number of similar deployments 10 | like microservices etc. or if you need different probe parameters for different namespaces or releases i.e. test vs. prod. 11 | 12 | Deploy as follows: 13 | 14 | ``` 15 | $ kubectl create namespace playground 16 | $ adeploy -p jinja [-n ] render . 17 | $ adeploy -p jinja [-n ] test 18 | $ adeploy -p jinja [-n ] deploy 19 | ``` 20 | 21 | By default `adeploy` is using the project folder as deployment name (i.e. `004-probes`). 22 | If you want to use another deployment name, pass it with `-n `. 23 | 24 | ## More Info 25 | 26 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja 27 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja#global-probes-configuration -------------------------------------------------------------------------------- /examples/jinja/004-probes/build/jinja/playground/004-probes/prod/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 004-probes-prod-nginx 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 004-probes 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 004-probes 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 004-probes 26 | app.kubernetes.io/instance: prod 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: nginx:1.22 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | # This is now defined in defaults.yml (or namespace configurations) 44 | # initialDelaySeconds: 3 45 | # timeoutSeconds: 2 46 | # failureThreshold: 2 47 | exec: 48 | command: 49 | - /tmp/health.sh 50 | initialDelaySeconds: 60 51 | periodSeconds: 30 52 | timeoutSeconds: 5 53 | failureThreshold: 5 54 | successThreshold: 1 55 | readinessProbe: 56 | httpGet: 57 | path: / 58 | port: 80 59 | # initialDelaySeconds: 3 60 | # timeoutSeconds: 2 61 | # failureThreshold: 2 62 | initialDelaySeconds: 5 63 | periodSeconds: 5 64 | timeoutSeconds: 5 65 | failureThreshold: 10 66 | successThreshold: 1 67 | -------------------------------------------------------------------------------- /examples/jinja/004-probes/build/jinja/playground/004-probes/prod/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 004-probes-prod-redis 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 004-probes 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 004-probes 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 004-probes 26 | app.kubernetes.io/instance: prod 27 | app.kubernetes.io/component: redis 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: redis:7 33 | imagePullPolicy: Always 34 | ports: 35 | - name: redis 36 | containerPort: 6379 37 | livenessProbe: 38 | exec: 39 | command: 40 | - /tmp/health.sh 41 | initialDelaySeconds: 60 42 | periodSeconds: 30 43 | timeoutSeconds: 5 44 | failureThreshold: 5 45 | successThreshold: 1 46 | readinessProbe: 47 | exec: 48 | command: 49 | - redis-cli 50 | - ping 51 | # This is now defined in defaults.yml (or namespace configurations) 52 | # initialDelaySeconds: 5 53 | # timeoutSeconds: 5 54 | initialDelaySeconds: 10 55 | periodSeconds: 5 56 | timeoutSeconds: 5 57 | failureThreshold: 10 58 | successThreshold: 1 59 | -------------------------------------------------------------------------------- /examples/jinja/004-probes/build/jinja/playground/004-probes/test/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 004-probes-test-nginx 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 004-probes 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 004-probes 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 004-probes 26 | app.kubernetes.io/instance: test 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: nginx:1.23 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | # This is now defined in defaults.yml (or namespace configurations) 44 | # initialDelaySeconds: 3 45 | # timeoutSeconds: 2 46 | # failureThreshold: 2 47 | exec: 48 | command: 49 | - /tmp/health.sh 50 | initialDelaySeconds: 60 51 | periodSeconds: 30 52 | timeoutSeconds: 5 53 | failureThreshold: 5 54 | successThreshold: 1 55 | readinessProbe: 56 | httpGet: 57 | path: / 58 | port: 80 59 | # initialDelaySeconds: 3 60 | # timeoutSeconds: 2 61 | # failureThreshold: 2 62 | initialDelaySeconds: 5 63 | periodSeconds: 5 64 | timeoutSeconds: 5 65 | failureThreshold: 10 66 | successThreshold: 1 67 | -------------------------------------------------------------------------------- /examples/jinja/004-probes/build/jinja/playground/004-probes/test/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 004-probes-test-redis 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 004-probes 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 004-probes 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 004-probes 26 | app.kubernetes.io/instance: test 27 | app.kubernetes.io/component: redis 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: redis:7 33 | imagePullPolicy: Always 34 | ports: 35 | - name: redis 36 | containerPort: 6379 37 | livenessProbe: 38 | exec: 39 | command: 40 | - /tmp/health.sh 41 | initialDelaySeconds: 60 42 | periodSeconds: 30 43 | timeoutSeconds: 5 44 | failureThreshold: 5 45 | successThreshold: 1 46 | readinessProbe: 47 | exec: 48 | command: 49 | - redis-cli 50 | - ping 51 | # This is now defined in defaults.yml (or namespace configurations) 52 | # initialDelaySeconds: 5 53 | # timeoutSeconds: 5 54 | initialDelaySeconds: 10 55 | periodSeconds: 5 56 | timeoutSeconds: 5 57 | failureThreshold: 10 58 | successThreshold: 1 59 | -------------------------------------------------------------------------------- /examples/jinja/004-probes/defaults.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.23 3 | redis: 7 4 | 5 | nginx: 6 | image: nginx 7 | 8 | redis: 9 | image: redis 10 | 11 | # See https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja#global-probes-configuration 12 | _probes: 13 | # --8<-- [start:global-scope] --> 14 | liveness: 15 | exec: 16 | command: ["/tmp/health.sh"] 17 | initial_delay_seconds: 60 18 | period_seconds: 30 19 | timeout_seconds: 5 20 | failure_threshold: 5 21 | success_threshold: 1 22 | 23 | readiness: 24 | initial_delay_seconds: 5 25 | period_seconds: 5 26 | timeout_seconds: 5 27 | failure_threshold: 10 28 | success_threshold: 1 29 | # --8<-- [end:global-scope] --> 30 | 31 | # Some custom definitions for a selected deployment: 32 | # --8<-- [start:workload-scope] --> 33 | {{ name }}-{{ release }}-redis: 34 | readiness: 35 | initial_delay_seconds: 10 36 | # --8<-- [end:workload-scope] --> -------------------------------------------------------------------------------- /examples/jinja/004-probes/namespaces/playground/prod.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.22 -------------------------------------------------------------------------------- /examples/jinja/004-probes/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # Inherit from defaults.yml 2 | #versions: 3 | # nginx: -------------------------------------------------------------------------------- /examples/jinja/004-probes/templates/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }}-nginx 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: {{ name }} 26 | app.kubernetes.io/instance: {{ release }} 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: {{ nginx.image }}:{{ version('nginx') }} 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | # This is now defined in defaults.yml (or namespace configurations) 44 | # initialDelaySeconds: 3 45 | # timeoutSeconds: 2 46 | # failureThreshold: 2 47 | readinessProbe: 48 | httpGet: 49 | path: / 50 | port: 80 51 | # initialDelaySeconds: 3 52 | # timeoutSeconds: 2 53 | # failureThreshold: 2 -------------------------------------------------------------------------------- /examples/jinja/004-probes/templates/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }}-redis 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: {{ name }} 26 | app.kubernetes.io/instance: {{ release }} 27 | app.kubernetes.io/component: redis 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: {{ redis.image }}:{{ version('redis') }} 33 | imagePullPolicy: Always 34 | ports: 35 | - name: redis 36 | containerPort: 6379 37 | livenessProbe: 38 | exec: 39 | command: 40 | - redis-cli 41 | - ping 42 | # This is now defined in defaults.yml (or namespace configurations) 43 | # initialDelaySeconds: 5 44 | # timeoutSeconds: 5 45 | readinessProbe: 46 | exec: 47 | command: 48 | - redis-cli 49 | - ping 50 | # This is now defined in defaults.yml (or namespace configurations) 51 | # initialDelaySeconds: 5 52 | # timeoutSeconds: 5 53 | -------------------------------------------------------------------------------- /examples/jinja/005-labels/README.md: -------------------------------------------------------------------------------- 1 | # General Structure 2 | 3 | This is a Jinja based `adeploy` project that includes: 4 | 5 | * namespace `playground`, 6 | * two releases: `prod`, `test` and 7 | * a deployment that is using 8 | * a global label configuration and 9 | * best practise labels generated by `adeploy`. 10 | 11 | Deploy as follows: 12 | 13 | ``` 14 | $ kubectl create namespace playground 15 | $ adeploy -p jinja [-n ] render . 16 | $ adeploy -p jinja [-n ] test 17 | $ adeploy -p jinja [-n ] deploy 18 | ``` 19 | 20 | By default `adeploy` is using the project folder as deployment name (i.e. `005-labels`). 21 | If you want to use another deployment name, pass it with `-n `. 22 | 23 | ## More Info 24 | 25 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja 26 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja#global-labels-configurations -------------------------------------------------------------------------------- /examples/jinja/005-labels/build/jinja/playground/005-labels/prod/deployment.yml: -------------------------------------------------------------------------------- 1 | # --8<-- [start:use_labels] --> 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: 005-labels-prod 6 | namespace: playground 7 | labels: {'app.kubernetes.io/name': 'nginx', 'app.kubernetes.io/instance': '005-labels-prod', 8 | 'app.kubernetes.io/part-of': '005-labels', 'app.kubernetes.io/managed-by': 'adeploy', 9 | app.kubernetes.io/component: nginx, my.custom.labels/test: my-label} 10 | spec: 11 | selector: 12 | matchLabels: {'app.kubernetes.io/name': 'nginx', 'app.kubernetes.io/instance': '005-labels-prod', 13 | 'app.kubernetes.io/part-of': '005-labels', 'app.kubernetes.io/managed-by': 'adeploy', 14 | app.kubernetes.io/component: nginx, my.custom.labels/test: my-label} 15 | replicas: 1 16 | strategy: 17 | type: RollingUpdate 18 | rollingUpdate: 19 | maxSurge: 1 20 | maxUnavailable: 0 21 | template: 22 | metadata: 23 | labels: {'app.kubernetes.io/name': 'nginx', 'app.kubernetes.io/instance': '005-labels-prod', 24 | 'app.kubernetes.io/part-of': '005-labels', 'app.kubernetes.io/managed-by': 'adeploy', 25 | app.kubernetes.io/component: nginx, my.custom.labels/test: my-label} 26 | # --8<-- [end:use_labels] --> 27 | spec: 28 | terminationGracePeriodSeconds: 60 29 | containers: 30 | - name: main 31 | image: nginx:1.22 32 | imagePullPolicy: Always 33 | ports: 34 | - name: http 35 | containerPort: 80 36 | - name: https 37 | containerPort: 443 38 | livenessProbe: 39 | httpGet: 40 | path: / 41 | port: 80 42 | initialDelaySeconds: 3 43 | timeoutSeconds: 2 44 | failureThreshold: 2 45 | readinessProbe: 46 | httpGet: 47 | path: / 48 | port: 80 49 | initialDelaySeconds: 3 50 | timeoutSeconds: 2 51 | failureThreshold: 2 52 | -------------------------------------------------------------------------------- /examples/jinja/005-labels/build/jinja/playground/005-labels/test/deployment.yml: -------------------------------------------------------------------------------- 1 | # --8<-- [start:use_labels] --> 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: 005-labels-test 6 | namespace: playground 7 | labels: {'app.kubernetes.io/name': 'nginx', 'app.kubernetes.io/instance': '005-labels-test', 8 | 'app.kubernetes.io/part-of': '005-labels', 'app.kubernetes.io/managed-by': 'adeploy', 9 | app.kubernetes.io/component: nginx, my.custom.labels/test: my-label} 10 | spec: 11 | selector: 12 | matchLabels: {'app.kubernetes.io/name': 'nginx', 'app.kubernetes.io/instance': '005-labels-test', 13 | 'app.kubernetes.io/part-of': '005-labels', 'app.kubernetes.io/managed-by': 'adeploy', 14 | app.kubernetes.io/component: nginx, my.custom.labels/test: my-label} 15 | replicas: 1 16 | strategy: 17 | type: RollingUpdate 18 | rollingUpdate: 19 | maxSurge: 1 20 | maxUnavailable: 0 21 | template: 22 | metadata: 23 | labels: {'app.kubernetes.io/name': 'nginx', 'app.kubernetes.io/instance': '005-labels-test', 24 | 'app.kubernetes.io/part-of': '005-labels', 'app.kubernetes.io/managed-by': 'adeploy', 25 | app.kubernetes.io/component: nginx, my.custom.labels/test: my-label} 26 | # --8<-- [end:use_labels] --> 27 | spec: 28 | terminationGracePeriodSeconds: 60 29 | containers: 30 | - name: main 31 | image: nginx:1.23 32 | imagePullPolicy: Always 33 | ports: 34 | - name: http 35 | containerPort: 80 36 | - name: https 37 | containerPort: 443 38 | livenessProbe: 39 | httpGet: 40 | path: / 41 | port: 80 42 | initialDelaySeconds: 3 43 | timeoutSeconds: 2 44 | failureThreshold: 2 45 | readinessProbe: 46 | httpGet: 47 | path: / 48 | port: 80 49 | initialDelaySeconds: 3 50 | timeoutSeconds: 2 51 | failureThreshold: 2 52 | -------------------------------------------------------------------------------- /examples/jinja/005-labels/defaults.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.23 3 | 4 | nginx: 5 | image: nginx 6 | 7 | # Create best practise labels for nginx deployment 8 | # --8<-- [start:create_labels] --> 9 | labels: 10 | nginx: {{ create_labels(name='nginx') }} 11 | # --8<-- [end:create_labels] --> 12 | 13 | # Set global labels for all resources of this adeploy project, 14 | # --8<-- [start:global_labels] --> 15 | _labels: 16 | app.kubernetes.io/component: nginx 17 | app.kubernetes.io/instance: {{ name }}-{{ release }} 18 | app.kubernetes.io/part-of: {{ name }} 19 | my.custom.labels/test: my-label 20 | # --8<-- [end:global_labels] --> -------------------------------------------------------------------------------- /examples/jinja/005-labels/namespaces/playground/prod.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.22 -------------------------------------------------------------------------------- /examples/jinja/005-labels/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # Inherit from defaults.yml 2 | #versions: 3 | # nginx: -------------------------------------------------------------------------------- /examples/jinja/005-labels/templates/deployment.yml: -------------------------------------------------------------------------------- 1 | # --8<-- [start:use_labels] --> 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ name }}-{{ release }} 6 | namespace: {{ namespace }} 7 | labels: {{ labels.nginx }} 8 | spec: 9 | selector: 10 | matchLabels: {{ labels.nginx }} 11 | replicas: 1 12 | strategy: 13 | type: RollingUpdate 14 | rollingUpdate: 15 | maxSurge: 1 16 | maxUnavailable: 0 17 | template: 18 | metadata: 19 | labels: {{ labels.nginx }} 20 | # --8<-- [end:use_labels] --> 21 | spec: 22 | terminationGracePeriodSeconds: 60 23 | containers: 24 | - name: main 25 | image: {{ nginx.image }}:{{ version('nginx') }} 26 | imagePullPolicy: Always 27 | ports: 28 | - name: http 29 | containerPort: 80 30 | - name: https 31 | containerPort: 443 32 | livenessProbe: 33 | httpGet: 34 | path: / 35 | port: 80 36 | initialDelaySeconds: 3 37 | timeoutSeconds: 2 38 | failureThreshold: 2 39 | readinessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | initialDelaySeconds: 3 44 | timeoutSeconds: 2 45 | failureThreshold: 2 46 | -------------------------------------------------------------------------------- /examples/jinja/006-nested-labels/README.md: -------------------------------------------------------------------------------- 1 | # General Structure 2 | 3 | This is a Jinja based `adeploy` project that includes: 4 | 5 | * namespace `playground`, 6 | * two releases: `prod`, `test` and 7 | * a deployment that is using 8 | * a global label configuration and 9 | * best practise labels generated by `adeploy`. 10 | 11 | Deploy as follows: 12 | 13 | ``` 14 | $ kubectl create namespace playground 15 | $ adeploy -p jinja [-n ] render . 16 | $ adeploy -p jinja [-n ] test 17 | $ adeploy -p jinja [-n ] deploy 18 | ``` 19 | 20 | By default `adeploy` is using the project folder as deployment name (i.e. `005-labels`). 21 | If you want to use another deployment name, pass it with `-n `. 22 | 23 | ## More Info 24 | 25 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja 26 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja#global-labels-configurations -------------------------------------------------------------------------------- /examples/jinja/006-nested-labels/build/jinja/playground/006-nested-labels/prod/deployment.yml: -------------------------------------------------------------------------------- 1 | # --8<-- [start:use_labels] --> 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: 006-nested-labels-prod 6 | namespace: playground 7 | labels: {"app.kubernetes.io/instance": "prod", "app.kubernetes.io/component": "my-deployment", 8 | "app.kubernetes.io/part-of": "006-nested-labels", "app.kubernetes.io/managed-by": "adeploy", 9 | "app.kubernetes.io/name": "nginx"} 10 | spec: 11 | selector: 12 | matchLabels: {"app.kubernetes.io/instance": "prod", "app.kubernetes.io/component": "my-deployment", 13 | "app.kubernetes.io/part-of": "006-nested-labels", "app.kubernetes.io/managed-by": "adeploy", 14 | "app.kubernetes.io/name": "nginx"} 15 | replicas: 1 16 | strategy: 17 | type: RollingUpdate 18 | rollingUpdate: 19 | maxSurge: 1 20 | maxUnavailable: 0 21 | template: 22 | metadata: 23 | labels: {"app.kubernetes.io/instance": "prod", "app.kubernetes.io/component": "my-deployment", 24 | "app.kubernetes.io/part-of": "006-nested-labels", "app.kubernetes.io/managed-by": "adeploy", 25 | "app.kubernetes.io/name": "nginx"} 26 | # --8<-- [end:use_labels] --> 27 | spec: 28 | terminationGracePeriodSeconds: 60 29 | containers: 30 | - name: main 31 | image: nginx:1.22 32 | imagePullPolicy: Always 33 | ports: 34 | - name: http 35 | containerPort: 80 36 | - name: https 37 | containerPort: 443 38 | livenessProbe: 39 | httpGet: 40 | path: / 41 | port: 80 42 | initialDelaySeconds: 3 43 | timeoutSeconds: 2 44 | failureThreshold: 2 45 | readinessProbe: 46 | httpGet: 47 | path: / 48 | port: 80 49 | initialDelaySeconds: 3 50 | timeoutSeconds: 2 51 | failureThreshold: 2 52 | -------------------------------------------------------------------------------- /examples/jinja/006-nested-labels/build/jinja/playground/006-nested-labels/test/deployment.yml: -------------------------------------------------------------------------------- 1 | # --8<-- [start:use_labels] --> 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: 006-nested-labels-test 6 | namespace: playground 7 | labels: {"app.kubernetes.io/instance": "test", "app.kubernetes.io/component": "my-deployment", 8 | "app.kubernetes.io/part-of": "006-nested-labels", "app.kubernetes.io/managed-by": "adeploy", 9 | "app.kubernetes.io/name": "nginx"} 10 | spec: 11 | selector: 12 | matchLabels: {"app.kubernetes.io/instance": "test", "app.kubernetes.io/component": "my-deployment", 13 | "app.kubernetes.io/part-of": "006-nested-labels", "app.kubernetes.io/managed-by": "adeploy", 14 | "app.kubernetes.io/name": "nginx"} 15 | replicas: 1 16 | strategy: 17 | type: RollingUpdate 18 | rollingUpdate: 19 | maxSurge: 1 20 | maxUnavailable: 0 21 | template: 22 | metadata: 23 | labels: {"app.kubernetes.io/instance": "test", "app.kubernetes.io/component": "my-deployment", 24 | "app.kubernetes.io/part-of": "006-nested-labels", "app.kubernetes.io/managed-by": "adeploy", 25 | "app.kubernetes.io/name": "nginx"} 26 | # --8<-- [end:use_labels] --> 27 | spec: 28 | terminationGracePeriodSeconds: 60 29 | containers: 30 | - name: main 31 | image: nginx:1.23 32 | imagePullPolicy: Always 33 | ports: 34 | - name: http 35 | containerPort: 80 36 | - name: https 37 | containerPort: 443 38 | livenessProbe: 39 | httpGet: 40 | path: / 41 | port: 80 42 | initialDelaySeconds: 3 43 | timeoutSeconds: 2 44 | failureThreshold: 2 45 | readinessProbe: 46 | httpGet: 47 | path: / 48 | port: 80 49 | initialDelaySeconds: 3 50 | timeoutSeconds: 2 51 | failureThreshold: 2 52 | -------------------------------------------------------------------------------- /examples/jinja/006-nested-labels/defaults.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.23 3 | 4 | nginx: 5 | image: nginx 6 | 7 | # Create labels to updated them using nested create_label() calls. 8 | # --8<-- [start:create_labels] --> 9 | labels: {{ create_labels(component="my-deployment") }} 10 | # --8<-- [end:create_labels] --> -------------------------------------------------------------------------------- /examples/jinja/006-nested-labels/namespaces/playground/prod.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.22 -------------------------------------------------------------------------------- /examples/jinja/006-nested-labels/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # Inherit from defaults.yml 2 | #versions: 3 | # nginx: -------------------------------------------------------------------------------- /examples/jinja/006-nested-labels/templates/deployment.yml: -------------------------------------------------------------------------------- 1 | # --8<-- [start:use_labels] --> 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ name }}-{{ release }} 6 | namespace: {{ namespace }} 7 | labels: {{ create_labels(name="nginx", labels=labels) }} 8 | spec: 9 | selector: 10 | matchLabels: {{ create_labels(name="nginx", labels=labels) }} 11 | replicas: 1 12 | strategy: 13 | type: RollingUpdate 14 | rollingUpdate: 15 | maxSurge: 1 16 | maxUnavailable: 0 17 | template: 18 | metadata: 19 | labels: {{ create_labels(name="nginx", labels=labels) }} 20 | # --8<-- [end:use_labels] --> 21 | spec: 22 | terminationGracePeriodSeconds: 60 23 | containers: 24 | - name: main 25 | image: {{ nginx.image }}:{{ version('nginx') }} 26 | imagePullPolicy: Always 27 | ports: 28 | - name: http 29 | containerPort: 80 30 | - name: https 31 | containerPort: 443 32 | livenessProbe: 33 | httpGet: 34 | path: / 35 | port: 80 36 | initialDelaySeconds: 3 37 | timeoutSeconds: 2 38 | failureThreshold: 2 39 | readinessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | initialDelaySeconds: 3 44 | timeoutSeconds: 2 45 | failureThreshold: 2 46 | -------------------------------------------------------------------------------- /examples/jinja/007-resources/README.md: -------------------------------------------------------------------------------- 1 | # General Structure 2 | 3 | This is a Jinja based `adeploy` project that includes: 4 | 5 | * namespace `playground`, 6 | * two releases: `prod`, `test` and 7 | * two deployments for `nginx` and `redis` that is using 8 | * a global resources configuration. 9 | 10 | Note that this makes sense, if you don't want to modify your Jinja or Helm templates or 11 | if you need to set the same resources for similar services i.e. microservices. 12 | 13 | Deploy as follows: 14 | 15 | ``` 16 | $ kubectl create namespace playground 17 | $ adeploy -p jinja [-n ] render . 18 | $ adeploy -p jinja [-n ] test 19 | $ adeploy -p jinja [-n ] deploy 20 | ``` 21 | 22 | By default `adeploy` is using the project folder as deployment name (i.e. `006-resources`). 23 | If you want to use another deployment name, pass it with `-n `. 24 | 25 | ## More Info 26 | 27 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja 28 | * https://github.com/awesome-it/adeploy/tree/master/adeploy/providers/jinja#global-resources-configurations -------------------------------------------------------------------------------- /examples/jinja/007-resources/build/jinja/playground/007-resources/prod/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 007-resources-prod-nginx 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 007-resources 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 007-resources 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 007-resources 26 | app.kubernetes.io/instance: prod 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: nginx:1.22 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | readinessProbe: 44 | httpGet: 45 | path: / 46 | port: 80 47 | resources: 48 | limits: 49 | cpu: 1000m 50 | memory: 265Mi 51 | requests: 52 | cpu: 500m 53 | memory: 128Mi 54 | -------------------------------------------------------------------------------- /examples/jinja/007-resources/build/jinja/playground/007-resources/prod/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 007-resources-prod-redis 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 007-resources 8 | app.kubernetes.io/instance: prod 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 007-resources 14 | app.kubernetes.io/instance: prod 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 007-resources 26 | app.kubernetes.io/instance: prod 27 | app.kubernetes.io/component: redis 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: redis:7 33 | imagePullPolicy: Always 34 | ports: 35 | - name: redis 36 | containerPort: 6379 37 | livenessProbe: 38 | exec: 39 | command: 40 | - redis-cli 41 | - ping 42 | readinessProbe: 43 | exec: 44 | command: 45 | - redis-cli 46 | - ping 47 | resources: 48 | limits: 49 | cpu: 1000m 50 | memory: 265Mi 51 | requests: 52 | cpu: 500m 53 | memory: 128Mi 54 | -------------------------------------------------------------------------------- /examples/jinja/007-resources/build/jinja/playground/007-resources/test/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 007-resources-test-nginx 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 007-resources 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 007-resources 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 007-resources 26 | app.kubernetes.io/instance: test 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: nginx:1.23 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | readinessProbe: 44 | httpGet: 45 | path: / 46 | port: 80 47 | resources: 48 | limits: 49 | cpu: 1000m 50 | memory: 265Mi 51 | requests: 52 | cpu: 500m 53 | memory: 128Mi 54 | -------------------------------------------------------------------------------- /examples/jinja/007-resources/build/jinja/playground/007-resources/test/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: 007-resources-test-redis 5 | namespace: playground 6 | labels: 7 | app.kubernetes.io/part-of: 007-resources 8 | app.kubernetes.io/instance: test 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: 007-resources 14 | app.kubernetes.io/instance: test 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: 007-resources 26 | app.kubernetes.io/instance: test 27 | app.kubernetes.io/component: redis 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: redis:7 33 | imagePullPolicy: Always 34 | ports: 35 | - name: redis 36 | containerPort: 6379 37 | livenessProbe: 38 | exec: 39 | command: 40 | - redis-cli 41 | - ping 42 | readinessProbe: 43 | exec: 44 | command: 45 | - redis-cli 46 | - ping 47 | resources: 48 | limits: 49 | cpu: 1000m 50 | memory: 265Mi 51 | requests: 52 | cpu: 500m 53 | memory: 128Mi 54 | -------------------------------------------------------------------------------- /examples/jinja/007-resources/defaults.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.23 3 | redis: 7 4 | 5 | nginx: 6 | image: nginx 7 | 8 | redis: 9 | image: redis 10 | 11 | 12 | # Set global resource configuration 13 | _resources: 14 | 15 | # Default resources, can be overwritten by the resources in the manifest (1) 16 | # --8<-- [start:global-scope] --> 17 | limits: 18 | cpu: 1000m 19 | memory: 265Mi 20 | requests: 21 | cpu: 500m 22 | memory: 128Mi 23 | # --8<-- [end:global-scope] --> 24 | 25 | # Resources for a specific object (deployment, statefulset, replicaset, ...), can be overwritten by the resources in the manifest (2) 26 | # --8<-- [start:workload-scope] --> 27 | nginx: 28 | limits: 29 | cpu: 1000m 30 | memory: 265Mi 31 | requests: 32 | cpu: 500m 33 | memory: 128Mi 34 | # --8<-- [end:workload-scope] --> 35 | 36 | # Resources for a specific container, can't be overwritten by the manifest (3) 37 | # --8<-- [start:container-scope] --> 38 | redis: 39 | main: 40 | limits: 41 | cpu: 1000m 42 | memory: 265Mi 43 | requests: 44 | cpu: 500m 45 | memory: 128Mi 46 | # --8<-- [end:container-scope] --> -------------------------------------------------------------------------------- /examples/jinja/007-resources/namespaces/playground/prod.yml: -------------------------------------------------------------------------------- 1 | versions: 2 | nginx: 1.22 -------------------------------------------------------------------------------- /examples/jinja/007-resources/namespaces/playground/test.yml: -------------------------------------------------------------------------------- 1 | # Inherit from defaults.yml 2 | #versions: 3 | # nginx: -------------------------------------------------------------------------------- /examples/jinja/007-resources/templates/nginx/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }}-nginx 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: nginx 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: nginx 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: {{ name }} 26 | app.kubernetes.io/instance: {{ release }} 27 | app.kubernetes.io/component: nginx 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: {{ nginx.image }}:{{ version('nginx') }} 33 | imagePullPolicy: Always 34 | ports: 35 | - name: http 36 | containerPort: 80 37 | - name: https 38 | containerPort: 443 39 | livenessProbe: 40 | httpGet: 41 | path: / 42 | port: 80 43 | readinessProbe: 44 | httpGet: 45 | path: / 46 | port: 80 -------------------------------------------------------------------------------- /examples/jinja/007-resources/templates/redis/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ name }}-{{ release }}-redis 5 | namespace: {{ namespace }} 6 | labels: 7 | app.kubernetes.io/part-of: {{ name }} 8 | app.kubernetes.io/instance: {{ release }} 9 | app.kubernetes.io/component: redis 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/part-of: {{ name }} 14 | app.kubernetes.io/instance: {{ release }} 15 | app.kubernetes.io/component: redis 16 | replicas: 1 17 | strategy: 18 | type: RollingUpdate 19 | rollingUpdate: 20 | maxSurge: 1 21 | maxUnavailable: 0 22 | template: 23 | metadata: 24 | labels: 25 | app.kubernetes.io/part-of: {{ name }} 26 | app.kubernetes.io/instance: {{ release }} 27 | app.kubernetes.io/component: redis 28 | spec: 29 | terminationGracePeriodSeconds: 60 30 | containers: 31 | - name: main 32 | image: {{ redis.image }}:{{ version('redis') }} 33 | imagePullPolicy: Always 34 | ports: 35 | - name: redis 36 | containerPort: 6379 37 | livenessProbe: 38 | exec: 39 | command: 40 | - redis-cli 41 | - ping 42 | readinessProbe: 43 | exec: 44 | command: 45 | - redis-cli 46 | - ping -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: adeploy 2 | extra: 3 | homepage: https://awesome-it.de 4 | social: 5 | - icon: fontawesome/brands/github 6 | link: https://github.com/awesome-it/adeploy 7 | 8 | theme: 9 | name: material 10 | custom_dir: docs/overrides 11 | features: 12 | - navigation.indexes 13 | - navigation.footer 14 | 15 | markdown_extensions: 16 | - admonition 17 | - footnotes 18 | - pymdownx.details 19 | - toc: 20 | permalink: true 21 | - attr_list 22 | - def_list 23 | - md_in_html 24 | - pymdownx.superfences 25 | - pymdownx.highlight: 26 | anchor_linenums: true 27 | line_spans: __span 28 | pygments_lang_class: true 29 | - pymdownx.inlinehilite 30 | - pymdownx.snippets 31 | - pymdownx.superfences 32 | - pymdownx.tabbed: 33 | alternate_style: true 34 | - pymdownx.emoji: 35 | emoji_index: !!python/name:material.extensions.emoji.twemoji 36 | emoji_generator: !!python/name:material.extensions.emoji.to_svg 37 | 38 | hooks: 39 | - docs/hooks/badges.py 40 | - docs/hooks/asciinema.py 41 | 42 | extra_css: 43 | - assets/css/footer.css 44 | - assets/css/badges.css 45 | - assets/css/asciinema-player.css 46 | - assets/css/docstrings.css 47 | 48 | extra_javascript: 49 | - assets/js/asciinema-init.js 50 | - assets/js/asciinema-player.min.js 51 | 52 | plugins: 53 | - search 54 | - mkdocstrings: 55 | handlers: 56 | python: 57 | options: 58 | docstring_style: google 59 | docstring_section_style: spacy 60 | parameter_headings: true 61 | show_symbol_type_heading: true 62 | separate_signature: true 63 | show_signature_annotations: true 64 | 65 | nav: 66 | - About: 'index.md' 67 | - Install: 'install.md' 68 | - Usage: 'usage.md' 69 | - Jinja Deployment: 70 | - 'jinja/index.md' 71 | - Helm Deployment: 72 | - 'helm/index.md' 73 | - Hooks: 'helm/hooks.md' 74 | - Common: 75 | - 'common/index.md' 76 | - Secrets: 'common/secrets.md' 77 | - Includes: 'common/includes.md' 78 | - Labels: 'common/labels.md' 79 | - Resource Limits: 'common/resource-limits.md' 80 | - Probes: 'common/probes.md' 81 | - Jinja Functions: 'common/functions.md' 82 | - Jinja Filters: 'common/filters.md' 83 | - Jinja Macros: 'common/macros.md' 84 | 85 | exclude_docs: | 86 | _*.md -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | # Consider all git-tracked files as data-files 3 | # https://stackoverflow.com/a/73062301 4 | requires = [ 5 | "setuptools>=60", 6 | "setuptools-scm>=8.0"] 7 | 8 | # Add _version.py to package data 9 | [tool.setuptools.package-data] 10 | adeploy = ["_version.py"] 11 | 12 | # See https://setuptools-scm.readthedocs.io/en/latest/usage/ 13 | [tool.setuptools_scm] 14 | git_describe_command = "git describe --tags --abbrev=4" 15 | 16 | [project] 17 | name = "adeploy" 18 | dynamic = ["version", "dependencies"] 19 | authors = [ 20 | { name="Daniel Morlock", email="daniel.morlock@awesome-it.de" }, 21 | { name="Daniel Bross", email="daniel.bross@awesome-it.de" }, 22 | { name="Robin Lutz", email="robin.lutz@awesome-it.de" }, 23 | { name="Adrian Vielsack", email="adrian.vielsack@awesome-it.de" }, 24 | { name="Philip Flohr", email="philip.flohr@awesome-it.de" } 25 | ] 26 | description = "Universal deployment tool for Kubernetes that supports rendering and deployment of lightweight Jinja templated k8s manifests as well as complex Helm charts." 27 | readme = "README.md" 28 | requires-python = ">=3.8" 29 | classifiers = [ 30 | "Programming Language :: Python :: 3", 31 | "License :: OSI Approved :: BSD License", 32 | "Operating System :: OS Independent" 33 | ] 34 | 35 | # Read dependencies from requirementx.txt: https://stackoverflow.com/a/73600610 36 | [ tool.setuptools.dynamic ] 37 | dependencies = {file = ["requirements.txt"]} 38 | 39 | [project.scripts] 40 | adeploy = "adeploy.main:main" 41 | 42 | [project.urls] 43 | Homepage = "https://awesome-it.de" 44 | Source = "https://github.com/awesome-it/adeploy" 45 | Issues = "https://github.com/awesome-it/adeploy/issues" 46 | Documentation = "https://awesome-it.de/docs/adeploy/latest" 47 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | colorama>=0.4.3 2 | Jinja2 3 | PyYAML 4 | ruamel.yaml>=0.16.12 5 | ruamel.yaml.clib>=0.2.2 6 | packaging>=20.4 7 | shortuuid>=1.0.1 8 | watchdog>=3.0.0 -------------------------------------------------------------------------------- /runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Convenience wrapper for running directly from source tree, without installation via setuptools.""" 3 | from adeploy.main import main 4 | 5 | if __name__ == '__main__': 6 | main() -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | from codecs import open 3 | from os import path 4 | from adeploy.common.version import get_git_version 5 | 6 | here = path.abspath(path.dirname(__file__)) 7 | 8 | setup( 9 | name='adeploy', 10 | version=get_git_version(), 11 | description='An universal deployment tool for k8s deployments', 12 | author='awesome IT', 13 | author_email='daniel.morlock@awesome-it.de', 14 | packages=find_packages(), 15 | install_requires=open('%s/requirements.txt' % here, 'r',).readlines(), 16 | entry_points={ 17 | 'console_scripts': [ 18 | 'adeploy=adeploy.main:main', 19 | ], 20 | }) --------------------------------------------------------------------------------