Compare commits
	
		
			1 Commits
		
	
	
		
			8.0.1
			...
			docker-ver
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 65ba113696 | 
| @ -6,12 +6,6 @@ steps: | ||||
|     image: koalaman/shellcheck-alpine:v0.7.1 | ||||
|     commands: | ||||
|       - shellcheck abra | ||||
|       - shellcheck bin/*.sh | ||||
|  | ||||
|   - name: run flake8 | ||||
|     image: alpine/flake8:3.9.0 | ||||
|     commands: | ||||
|       - flake8 --max-line-length 100 bin/app-json.py | ||||
|  | ||||
|   - name: run unit tests | ||||
|     image: decentral1se/docker-dind-bats-kcov | ||||
|  | ||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,2 +1,2 @@ | ||||
| /.venv | ||||
| coverage/ | ||||
| /.venv | ||||
|  | ||||
							
								
								
									
										63
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| > 🔥 🔥 🔥 Please note, while we are still in | ||||
| > [public alpha](https://docs.cloud.autonomic.zone/roadmap/), the `abra` release | ||||
| > 🔥 🔥 🔥 Please note, while we are still in [public | ||||
| > alpha](https://docs.cloud.autonomic.zone/roadmap/), the `abra` release | ||||
| > versioning scheme is not following [semver](https://semver.org/) conventions | ||||
| > because we are still in the exploratory phases of building this tool. Please | ||||
| > read the changes before upgrading your `abra` installation as there are | ||||
| @ -9,50 +9,6 @@ | ||||
|  | ||||
| # abra x.x.x (UNRELEASED) | ||||
|  | ||||
| # abra 8.0.1 (2021-05-31) | ||||
|  | ||||
| - Fix help for `... app ... volume ls` ([efad71c470](https://git.autonomic.zone/coop-cloud/abra/commits/branch/main)) | ||||
| - Only output secrets warnings once ([#143](https://git.autonomic.zone/coop-cloud/abra/issues/143)) | ||||
| - Migrate `abra` installation script to `coopcloud.tech` domain ([#150](https://git.autonomic.zone/coop-cloud/abra/issues/150)) | ||||
| - Add `--no-state-poll` to avoid success/failure forecasting on deployment ([#165](https://git.autonomic.zone/coop-cloud/abra/issues/165)) | ||||
|  | ||||
| # abra 8.0.0 (2021-05-30) | ||||
|  | ||||
| - Fix secret length generation ([f537417](https://git.autonomic.zone/coop-cloud/abra/commit/1b85bf3d37280e9632c315d759c0f2d09c039fef)) | ||||
| - Fix checking out new apps ([#164](https://git.autonomic.zone/coop-cloud/abra/issues/164) | ||||
| - Give up if YAML is invalid ([#154](https://git.autonomic.zone/coop-cloud/abra/issues/154)) | ||||
| - Switch from wget to cURL ([fc0caaa](https://git.autonomic.zone/coop-cloud/abra/commit/fc0caaa)) | ||||
| - Add Bash completion for `recipe ..` ([8c93d1a](https://git.autonomic.zone/coop-cloud/abra/commit/8c93d1a)) | ||||
| - Tweak README parsing in `app-json.py` ([b14219b](https://git.autonomic.zone/coop-cloud/abra/commit/b14219b)) | ||||
| - Add fallback names to `app.json` ([#157](https://git.autonomic.zone/coop-cloud/abra/issues/157)) | ||||
| - Remove duplicate message ([#155](https://git.autonomic.zone/coop-cloud/abra/issues/155)) | ||||
| - Add `deploy --fast` ([a7f7c96](https://git.autonomic.zone/coop-cloud/abra/commit/a7f7c96)) | ||||
| - Add `app .. volume` commands, fix volume deletion with `app .. delete --volumes` ([#161](https://git.autonomic.zone/coop-cloud/abra/issues/161)) | ||||
|  | ||||
| # abra 0.7.4 (2021-05-10) | ||||
|  | ||||
| - Sort `apps.json` when publishing ([39a7fc0](https://git.autonomic.zone/coop-cloud/abra/commit/39a7fc04fb5df1a6d78b84f51838530ab3eb76db)) | ||||
| - Fix publishing of rating for new apps ([0e28af9](https://git.autonomic.zone/coop-cloud/abra/commit/0e28af9eb1af6c6da705b4614ddd173c60576629)) | ||||
| - Detect compose filenames in `n+1` release generation ([ffc569e](https://git.autonomic.zone/coop-cloud/abra/commit/ffc569e275df7ca784a4db1a3331e17975fd8c87)) | ||||
| - Fix secret generation when specifying length ([3a353f4](https://git.autonomic.zone/coop-cloud/abra/commit/3a353f4062baccde2c9f175b03afb2db6d462ae4)) | ||||
|  | ||||
| # abra 0.7.3 (2021-04-28) | ||||
|  | ||||
| - Only check for pw(q)gen if we're actually trying to use them ([#147](https://git.autonomic.zone/coop-cloud/abra/issues/147)) | ||||
| - Use apps.coopcloud.tech for app data hosting & download ([75bd599](https://git.autonomic.zone/coop-cloud/abra/commit/75bd599)) | ||||
| - Choose latest commit messages for new tags ([#144](https://git.autonomic.zone/coop-cloud/abra/issues/144)) | ||||
| - Handle recipes without an `app` service in `recipe .. release` ([#151](https://git.autonomic.zone/coop-cloud/abra/issues/151)) | ||||
|  | ||||
| # abra 0.7.2 (2021-04-07) | ||||
|  | ||||
| - Fix installation script development installs (again! Thanks Bash!) ([4747d9b7](https://git.autonomic.zone/coop-cloud/abra/commit/4747d9b7fb5fba914f210b6570bfe2db0b53da23)) | ||||
|  | ||||
| # abra 0.7.1 (2021-04-07) | ||||
|  | ||||
| - Fix installation script development installs ([8f2fadb3c](https://git.autonomic.zone/coop-cloud/abra/commit/8f2fadb3c43c5915520f5ea531ea3815c2ba8531)) | ||||
|  | ||||
| # abra 0.7.0 (2021-04-07) | ||||
|  | ||||
| - Add `--force` to the `deploy` command to allow overriding deployment logic ([#105](https://git.autonomic.zone/coop-cloud/abra/issues/105)) | ||||
| - Handle undeployed apps in version summaries when deploying ([#104](https://git.autonomic.zone/coop-cloud/abra/issues/104)) | ||||
| - Add `--force` to `undeploy` command ([e5e98d5](https://git.autonomic.zone/coop-cloud/abra/commit/e5e98d5)) | ||||
| @ -62,20 +18,7 @@ | ||||
| - Show correct status for apps deployed on servers with missing context ([#99](https://git.autonomic.zone/coop-cloud/abra/issues/99)) | ||||
| - Search for subcommands in descending order of how many components there are ([#108](https://git.autonomic.zone/coop-cloud/abra/issues/108)) | ||||
| - Add specific app version checking command (`abra app <app> version`) ([#108](https://git.autonomic.zone/coop-cloud/abra/issues/108)) | ||||
| - Add docker version check (guestimating < v19 is a bad idea) ([#15](https://git.autonomic.zone/coop-cloud/abra/issues/15)) | ||||
| - Fix git branch handling when not passing `-b <branch>` ([#122](https://git.autonomic.zone/coop-cloud/abra/issues/122)) | ||||
| - Add work-around to correctly git clone non-master default branch app repositories ([#122](https://git.autonomic.zone/coop-cloud/abra/issues/122)) | ||||
| - Replace `--force` (except for the `deploy` command) with a global `--no-prompt` for avoiding interactive questions ([#118](https://git.autonomic.zone/coop-cloud/abra/issues/118)) | ||||
| - Use [docker-stack-wait-deploy](https://github.com/vitalets/docker-stack-wait-deploy) inspired logic to deploy apps ([#116](https://git.autonomic.zone/coop-cloud/abra/issues/116)) | ||||
| - Add a domain polling check when deploying apps ([#113](https://git.autonomic.zone/coop-cloud/abra/issues/113)) | ||||
| - Recognise when apps are already undeployed with `abra app <app> undeploy` ([#123](https://git.autonomic.zone/coop-cloud/abra/issues/123)) | ||||
| - Add `abra doctor` command to help diagnose setup issues ([#119](https://git.autonomic.zone/coop-cloud/abra/issues/119)) | ||||
| - Add apps version and feature catalogue generation script ([#121](https://git.autonomic.zone/coop-cloud/abra/issues/121)) | ||||
| - New `--skip-version-check` option to `deploy` ([df4e504](https://git.autonomic.zone/coop-cloud/abra/commit/df4e504)) | ||||
| - Look up local available version from compose files instead of `abra.sh` ([#131](https://git.autonomic.zone/coop-cloud/abra/issues/131)) | ||||
| - Improve domain polling logging and allow to skip the check altogether with `--no-domain-poll` ([#140](https://git.autonomic.zone/coop-cloud/abra/issues/140), [#141](https://git.autonomic.zone/coop-cloud/abra/issues/141)) | ||||
| - Support `ABRA_DIR` in the installer script ([4e94a424e94a42](https://git.autonomic.zone/coop-cloud/abra/commit/4e94a424e94a42)) | ||||
| - Support [abra-hetzner](https://git.autonomic.zone/coop-cloud/abra-hetzner) plugin ([#88](https://git.autonomic.zone/coop-cloud/abra/issues/88)) | ||||
| - Add docker version check (guestimating < v20 is a bad idea) ([#15](https://git.autonomic.zone/coop-cloud/abra/issues/15)) | ||||
|  | ||||
| # abra 0.6.0 (2021-03-17) | ||||
|  | ||||
|  | ||||
							
								
								
									
										56
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								README.md
									
									
									
									
									
								
							| @ -3,16 +3,16 @@ | ||||
| [](https://drone.autonomic.zone/coop-cloud/abra) | ||||
| [](undefined) | ||||
|  | ||||
| > https://coopcloud.tech | ||||
| > https://cloud.autonomic.zone | ||||
|  | ||||
| The cooperative cloud utility belt 🎩🐇 | ||||
|  | ||||
| `abra` is a command-line tool for managing your own [Co-op Cloud](https://coopcloud.tech). It can provision new servers, create applications, deploy them, run backup and restore operations and a whole lot of other things. It is the go-to tool for day-to-day operations when managing a Co-op Cloud instance. | ||||
| `abra` is a command-line tool for managing your own [Co-op Cloud](https://cloud.autonomic.zone). It can provision new servers, create applications, deploy them, run backup and restore operations and a whole lot of other things. It is the go-to tool for day-to-day operations when managing a Co-op Cloud instance. | ||||
|  | ||||
| ## Change log | ||||
|  | ||||
| > 🔥 🔥 🔥 Please note, while we are still in [public | ||||
| > alpha](https://docs.coopcloud.tech/roadmap/), the `abra` release | ||||
| > alpha](https://docs.cloud.autonomic.zone/roadmap/), the `abra` release | ||||
| > versioning scheme is not following [semver](https://semver.org/) conventions | ||||
| > because we are still in the exploratory phases of building this tool. Please | ||||
| > read the changes before upgrading your `abra` installation as there are | ||||
| @ -24,31 +24,23 @@ See [CHANGELOG.md](./CHANGELOG.md). | ||||
|  | ||||
| ## Documentation | ||||
|  | ||||
| > [docs.coopcloud.tech](https://docs.coopcloud.tech) | ||||
| > [docs.cloud.autonomic.zone](https://docs.cloud.autonomic.zone/) | ||||
|  | ||||
| ## Install | ||||
|  | ||||
| Requirements: | ||||
|  | ||||
| - `pwqgen` (optional) | ||||
| - `pwgen` (optional) | ||||
| - `curl` | ||||
| - `docker` | ||||
| - `bash` >= 4 | ||||
|  | ||||
| Install the latest stable release: | ||||
|  | ||||
| ```sh | ||||
| curl https://install.abra.coopcloud.tech | bash | ||||
| curl https://install.abra.autonomic.zone | bash | ||||
| ``` | ||||
|  | ||||
| or the bleeding-edge development version: | ||||
|  | ||||
| ```sh | ||||
| curl https://install.abra.coopcloud.tech | bash -s -- --dev | ||||
| curl https://install.abra.autonomic.zone | bash -s -- --dev | ||||
| ``` | ||||
|  | ||||
| The source for this script is [here](./deploy/install.abra.coopcloud.tech/installer). | ||||
| The source for this script is [here](./installer/installer). | ||||
|  | ||||
| ## Update | ||||
|  | ||||
| @ -61,41 +53,17 @@ To update the development version, run `abra upgrade --dev`. | ||||
|  | ||||
| It's written in Bash version 4 or greater! | ||||
|  | ||||
| Install it via `curl https://install.abra.coopcloud.tech | bash -s -- --dev`, then you can hack on the source in `~/.abra/src`. | ||||
| Install it via `curl https://install.abra.autonomic.zone | bash -s -- --dev`, then you can hack on the source in `~/.abra/src`. | ||||
|  | ||||
| The command-line interface is generated via [docopt](http://docopt.org/). If you add arguments then you need to run `make docopt` ro regenerate the parser. | ||||
|  | ||||
| Please remember to update the [CHANGELOG](./CHANGELOG.md) when you make a change. | ||||
|  | ||||
| ## Generating a new apps.json | ||||
|  | ||||
| You'll need to install the following requirements: | ||||
|  | ||||
| - [requests](https://docs.python-requests.org/en/master/) (`apt install python3-requests` / `pip install requests`) | ||||
| - [skopeo](https://github.com/containers/skopeo) (check [the install docs](https://github.com/containers/skopeo/blob/master/install.md)) | ||||
| - [jq](https://stedolan.github.io/jq/tutorial/) (`sudo apt-get install jq` or see [the install docs](https://stedolan.github.io/jq/download/)) | ||||
| - [yq](https://mikefarah.gitbook.io/yq/) (see [the install docs](https://mikefarah.gitbook.io/yq/#install)) | ||||
|  | ||||
| Then run `./bin/app-json.py` ([source](./bin/app-json.py)) and it will spit out the JSON file into [deploy/apps.coopcloud.tech/apps.json](./deploy/apps.coopcloud.tech/apps.json). | ||||
|  | ||||
| ## Releasing | ||||
|  | ||||
| ### `abra` | ||||
|  | ||||
| > [install.abra.coopcloud.tech](https://install.abra.coopcloud.tech) | ||||
| ## Release | ||||
|  | ||||
| - Change the `x.x.x` header in [CHANGELOG.md](./CHANGELOG.md) to reflect new version and mark date | ||||
| - Update the version in [abra](./abra) | ||||
| - Update the version in [deploy/install.abra.coopcloud.tech/installer](./deploy/install.abra.coopcloud.tech/installer) | ||||
| - Update versions in [installer/installer](./installer/installer) and [abra](./abra) | ||||
| - `git commit` the above changes and then tag it with `git tag <your-new-version>` | ||||
| - `git push` and `git push --tags` | ||||
| - Then `git push` and `git push --tags` | ||||
| - Deploy a new installer script `make release-installer` | ||||
| - Tell the world (CoTech forum, Matrix public channel, Autonomic mastodon, etc.) | ||||
|  | ||||
| ### apps.coopcloud.tech | ||||
|  | ||||
| > [apps.coopcloud.tech](https://apps.coopcloud.tech) | ||||
|  | ||||
| ```bash | ||||
| $ make release-apps | ||||
| ``` | ||||
| - Tell the world | ||||
|  | ||||
| @ -1,7 +1,4 @@ | ||||
| #!/bin/bash | ||||
| 
 | ||||
| # shellcheck disable=SC2119 | ||||
| 
 | ||||
| # Usage: ./app-catalogue.sh | ||||
| # | ||||
| # Gather metadata from Co-op Cloud apps in $ABRA_DIR/apps (default | ||||
| @ -10,7 +7,7 @@ | ||||
| 
 | ||||
| stack_dir="${ABRA_DIR:-$HOME/.abra}/apps/" | ||||
| 
 | ||||
| cd "$stack_dir" || exit | ||||
| cd "$stack_dir" | ||||
| 
 | ||||
| # load all README files into ENV_FILES array | ||||
| mapfile -t readmes < <(find -L . -name "README.md") | ||||
							
								
								
									
										42
									
								
								app-version.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										42
									
								
								app-version.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,42 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # Usage: ./app-version.sh <image> <service> | ||||
| # Example: ./app-version.sh drone/drone:1.10.1 app | ||||
| # | ||||
| # Accepts a full format hub.docker.com image tag which it pulls locally and | ||||
| # generates output which can be used to put in the abra.sh for app packaging. | ||||
| # Requires the yq program https://mikefarah.gitbook.io/yq/ | ||||
|  | ||||
| error() { | ||||
|   echo "$(tput setaf 1)ERROR: $*$(tput sgr0)" | ||||
|   exit 1 | ||||
| } | ||||
|  | ||||
| IMAGE="$1" | ||||
| SERVICE="$2" | ||||
|  | ||||
| if ! docker pull -q "$IMAGE" > /dev/null 2>&1; then | ||||
| 	error "Failed to download image, is the tag correct?" | ||||
| fi | ||||
|  | ||||
| version=$(echo "$IMAGE" | cut -d ':' -f2) | ||||
| digest=$(docker image inspect -f "{{.Id}}" "$IMAGE" | cut -d ':' -f2- | cut -c 1-8) | ||||
|  | ||||
| echo "--- Add the following to your abra.sh ---" | ||||
| echo "export ABRA_TYPE_${SERVICE^^}_VERSION=${version}" | ||||
| echo "export ABRA_TYPE_${SERVICE^^}_DIGEST=${digest}" | ||||
|  | ||||
| version_lookup="ABRA_TYPE_${SERVICE^^}_VERSION" | ||||
| digest_lookup="ABRA_TYPE_${SERVICE^^}_DIGEST" | ||||
|  | ||||
| label='- "coop-cloud.${STACK_NAME}.' | ||||
| label+="${SERVICE}" | ||||
| label+='.version=${' | ||||
| label+="${version_lookup}" | ||||
| label+='}-${' | ||||
| label+="${digest_lookup}" | ||||
| label+='}"' | ||||
|  | ||||
| echo | ||||
| echo "--- And don't forget to label the actual service in the compose file ---" | ||||
| echo "$label" | ||||
							
								
								
									
										299
									
								
								bin/app-json.py
									
									
									
									
									
								
							
							
						
						
									
										299
									
								
								bin/app-json.py
									
									
									
									
									
								
							| @ -1,299 +0,0 @@ | ||||
| #!/usr/bin/env python3 | ||||
|  | ||||
| # Usage: ./app-json.py | ||||
| # | ||||
| # Gather metadata from Co-op Cloud apps in $ABRA_DIR/apps (default | ||||
| # ~/.abra/apps), and format it as JSON so that it can be hosted here: | ||||
| # https://apps.coopcloud.tech | ||||
|  | ||||
| from json import dump | ||||
| from logging import DEBUG, basicConfig, getLogger | ||||
| from os import chdir, listdir, mkdir | ||||
| from os.path import basename, exists, expanduser | ||||
| from pathlib import Path | ||||
| from re import findall, search | ||||
| from shlex import split | ||||
| from subprocess import DEVNULL, check_output | ||||
| from sys import exit | ||||
|  | ||||
| from requests import get | ||||
|  | ||||
| HOME_PATH = expanduser("~/") | ||||
| CLONES_PATH = Path(f"{HOME_PATH}/.abra/apps").absolute() | ||||
| YQ_PATH = Path(f"{HOME_PATH}/.abra/vendor/yq") | ||||
| SCRIPT_PATH = Path(__file__).absolute().parent | ||||
| REPOS_TO_SKIP = ( | ||||
|     "abra", | ||||
|     "abra-apps", | ||||
|     "abra-gandi", | ||||
|     "abra-hetzner", | ||||
|     "backup-bot", | ||||
|     "coopcloud.tech", | ||||
|     "coturn", | ||||
|     "docker-cp-deploy", | ||||
|     "docker-dind-bats-kcov", | ||||
|     "docs.coopcloud.tech", | ||||
|     "example", | ||||
|     "gardening", | ||||
|     "organising", | ||||
|     "pyabra", | ||||
|     "radicle-seed-node", | ||||
|     "stack-ssh-deploy", | ||||
|     "swarm-cronjob", | ||||
| ) | ||||
|  | ||||
| log = getLogger(__name__) | ||||
| basicConfig() | ||||
| log.setLevel(DEBUG) | ||||
|  | ||||
|  | ||||
| def _run_cmd(cmd, shell=False, **kwargs): | ||||
|     """Run a shell command.""" | ||||
|     args = [split(cmd)] | ||||
|  | ||||
|     if shell: | ||||
|         args = [cmd] | ||||
|         kwargs = {"shell": shell} | ||||
|  | ||||
|     try: | ||||
|         return check_output(*args, **kwargs).decode("utf-8").strip() | ||||
|     except Exception as exception: | ||||
|         log.error(f"Failed to run {cmd}, saw {str(exception)}") | ||||
|         exit(1) | ||||
|  | ||||
|  | ||||
| def get_repos_json(): | ||||
|     """ Retrieve repo list from Gitea """ | ||||
|  | ||||
|     url = "https://git.autonomic.zone/api/v1/orgs/coop-cloud/repos" | ||||
|  | ||||
|     log.info(f"Retrieving {url}") | ||||
|  | ||||
|     repos = [] | ||||
|     response = True | ||||
|     page = 1 | ||||
|  | ||||
|     try: | ||||
|         while response: | ||||
|             log.info(f"Trying to fetch page {page}") | ||||
|             response = get(url + f"?page={page}", timeout=10).json() | ||||
|             repos.extend(response) | ||||
|             page += 1 | ||||
|  | ||||
|         return repos | ||||
|     except Exception as exception: | ||||
|         log.error(f"Failed to retrieve {url}, saw {str(exception)}") | ||||
|         exit(1) | ||||
|  | ||||
|  | ||||
| def get_published_apps_json(): | ||||
|     """Retrieve already published apps json.""" | ||||
|     url = "https://apps.coopcloud.tech" | ||||
|  | ||||
|     log.info(f"Retrieving {url}") | ||||
|  | ||||
|     try: | ||||
|         return get(url, timeout=5).json() | ||||
|     except Exception as exception: | ||||
|         log.error(f"Failed to retrieve {url}, saw {str(exception)}") | ||||
|         return {} | ||||
|  | ||||
|  | ||||
| def clone_all_apps(repos_json): | ||||
|     """Clone all Co-op Cloud apps to ~/.abra/apps.""" | ||||
|     if not exists(CLONES_PATH): | ||||
|         mkdir(CLONES_PATH) | ||||
|  | ||||
|     repos = [[p["name"], p["ssh_url"]] for p in repos_json] | ||||
|  | ||||
|     for name, url in repos: | ||||
|         if name in REPOS_TO_SKIP: | ||||
|             continue | ||||
|  | ||||
|         if not exists(f"{CLONES_PATH}/{name}"): | ||||
|             log.info(f"Retrieving {url}") | ||||
|             _run_cmd(f"git clone {url} {CLONES_PATH}/{name}") | ||||
|  | ||||
|             chdir(f"{CLONES_PATH}/{name}") | ||||
|             if not int(_run_cmd("git branch --list | wc -l", shell=True)): | ||||
|                 log.info(f"Guessing main branch is HEAD for {name}") | ||||
|                 _run_cmd("git checkout main") | ||||
|         else: | ||||
|             log.info(f"Updating {name}") | ||||
|             chdir(f"{CLONES_PATH}/{name}") | ||||
|             _run_cmd("git fetch -a") | ||||
|  | ||||
|  | ||||
| def generate_apps_json(repos_json): | ||||
|     """Generate the abra-apps.json application versions file.""" | ||||
|     apps_json = {} | ||||
|     cached_apps_json = get_published_apps_json() | ||||
|  | ||||
|     for app in listdir(CLONES_PATH): | ||||
|         if app in REPOS_TO_SKIP: | ||||
|             log.info(f"Skipping {app}") | ||||
|             continue | ||||
|  | ||||
|         repo_details = next(filter(lambda x: x["name"] == app, repos_json), {}) | ||||
|  | ||||
|         app_path = f"{CLONES_PATH}/{app}" | ||||
|         chdir(app_path) | ||||
|  | ||||
|         metadata = get_app_metadata(app_path) | ||||
|  | ||||
|         name = metadata.pop("name", app) | ||||
|  | ||||
|         log.info(f"Processing {app}") | ||||
|         apps_json[app] = { | ||||
|             "name": name, | ||||
|             "category": metadata.get("category", ""), | ||||
|             "repository": repo_details.get("clone_url", ""), | ||||
|             "default_branch": repo_details.get("default_branch", ""), | ||||
|             "description": repo_details.get("description", ""), | ||||
|             "website": repo_details.get("website", ""), | ||||
|             "features": metadata, | ||||
|             "versions": get_app_versions(app_path, cached_apps_json), | ||||
|             "icon": repo_details.get("avatar_url", ""), | ||||
|         } | ||||
|  | ||||
|     return apps_json | ||||
|  | ||||
|  | ||||
| def get_app_metadata(app_path): | ||||
|     """Parse metadata from app repo README files.""" | ||||
|     metadata = {} | ||||
|  | ||||
|     chdir(app_path) | ||||
|  | ||||
|     try: | ||||
|         with open(f"{app_path}/README.md", "r") as handle: | ||||
|             log.info(f"{app_path}/README.md") | ||||
|             contents = handle.read() | ||||
|     except Exception: | ||||
|         log.info(f"No {app_path}/README.md discovered, moving on") | ||||
|         return {} | ||||
|  | ||||
|     try: | ||||
|         for match in findall(r"\*\*.*", contents): | ||||
|             title = search(r"(?<=\*\*).*(?=\*\*)", match).group().lower() | ||||
|  | ||||
|             if title == "image": | ||||
|                 value = { | ||||
|                     "image": search(r"(?<=`).*(?=`)", match).group(), | ||||
|                     "url": search(r"(?<=\().*(?=\))", match).group(), | ||||
|                     "rating": match.split(",")[1].strip(), | ||||
|                     "source": match.split(",")[-1].replace("*", "").strip(), | ||||
|                 } | ||||
|             elif title == "status": | ||||
|                 value = {"❶💚": 1, "❷💛": 2, "❸🍎": 3, "❹💣": 4, "?": 5, "": 5}[ | ||||
|                     match.split(":")[-1].replace("*", "").strip() | ||||
|                 ] | ||||
|             else: | ||||
|                 value = match.split(":")[-1].replace("*", "").strip() | ||||
|  | ||||
|             metadata[title] = value | ||||
|         metadata["name"] = findall(r"^# (.*)", contents)[0] | ||||
|     except (IndexError, AttributeError): | ||||
|         log.info(f"Can't parse {app_path}/README.md") | ||||
|         return {} | ||||
|     finally: | ||||
|         _run_cmd("git checkout HEAD") | ||||
|  | ||||
|     log.info(f"Parsed {metadata}") | ||||
|  | ||||
|     return metadata | ||||
|  | ||||
|  | ||||
| def get_app_versions(app_path, cached_apps_json): | ||||
|     versions = {} | ||||
|  | ||||
|     chdir(app_path) | ||||
|  | ||||
|     tags = _run_cmd("git tag --list").split() | ||||
|  | ||||
|     if not tags: | ||||
|         log.info("No tags discovered, moving on") | ||||
|         return {} | ||||
|  | ||||
|     initial_branch = _run_cmd("git rev-parse --abbrev-ref HEAD") | ||||
|  | ||||
|     app_name = basename(app_path) | ||||
|  | ||||
|     try: | ||||
|         existing_tags = cached_apps_json[app_name]["versions"].keys() | ||||
|     except KeyError: | ||||
|         existing_tags = [] | ||||
|  | ||||
|     for tag in tags: | ||||
|         _run_cmd(f"git checkout {tag}", stderr=DEVNULL) | ||||
|  | ||||
|         services_cmd = f"{YQ_PATH} e '.services | keys | .[]' compose*.yml" | ||||
|         services = _run_cmd(services_cmd, shell=True).split() | ||||
|  | ||||
|         parsed_services = [] | ||||
|         service_versions = {} | ||||
|         for service in services: | ||||
|             if service in ("null", "---"): | ||||
|                 continue | ||||
|  | ||||
|             if ( | ||||
|                 tag in existing_tags | ||||
|                 and service in cached_apps_json[app_name]["versions"][tag] | ||||
|             ): | ||||
|                 log.info(f"Skipping {tag} because we've already processed it") | ||||
|                 existing_versions = cached_apps_json[app_name]["versions"][tag][service] | ||||
|                 service_versions[service] = existing_versions | ||||
|                 _run_cmd(f"git checkout {initial_branch}") | ||||
|                 continue | ||||
|  | ||||
|             if service in parsed_services: | ||||
|                 log.info(f"Skipped {service}, we've already parsed it locally") | ||||
|                 continue | ||||
|  | ||||
|             services_cmd = f"{YQ_PATH} e '.services.{service}.image' compose*.yml" | ||||
|             images = _run_cmd(services_cmd, shell=True).split() | ||||
|  | ||||
|             for image in images: | ||||
|                 if image in ("null", "---"): | ||||
|                     continue | ||||
|  | ||||
|                 images_cmd = f"skopeo inspect docker://{image} | jq '.Digest'" | ||||
|                 output = _run_cmd(images_cmd, shell=True) | ||||
|  | ||||
|                 service_version_info = { | ||||
|                     "image": image.split(":")[0], | ||||
|                     "tag": image.split(":")[-1], | ||||
|                     "digest": output.split(":")[-1][:8], | ||||
|                 } | ||||
|  | ||||
|                 log.info(f"Parsed {service_version_info}") | ||||
|                 service_versions[service] = service_version_info | ||||
|  | ||||
|             parsed_services.append(service) | ||||
|  | ||||
|         versions[tag] = service_versions | ||||
|  | ||||
|     _run_cmd(f"git checkout {initial_branch}") | ||||
|  | ||||
|     return versions | ||||
|  | ||||
|  | ||||
| def main(): | ||||
|     """Run the script.""" | ||||
|     repos_json = get_repos_json() | ||||
|     clone_all_apps(repos_json) | ||||
|  | ||||
|     target = f"{SCRIPT_PATH}/../deploy/apps.coopcloud.tech/apps.json" | ||||
|     with open(target, "w", encoding="utf-8") as handle: | ||||
|         dump( | ||||
|             generate_apps_json(repos_json), | ||||
|             handle, | ||||
|             ensure_ascii=False, | ||||
|             indent=4, | ||||
|             sort_keys=True, | ||||
|         ) | ||||
|  | ||||
|     log.info(f"Successfully generated {target}") | ||||
|  | ||||
|  | ||||
| main() | ||||
| @ -38,22 +38,6 @@ _abra_complete_apps() | ||||
|     mapfile -t COMPREPLY < <(compgen -W "$(_abra_apps)" -- "$1") | ||||
| } | ||||
|  | ||||
| _abra_recipes() | ||||
| { | ||||
|     shopt -s nullglob dotglob | ||||
|     local RECIPES=(~/.abra/apps/*) | ||||
|     shopt -u nullglob dotglob | ||||
|  | ||||
|     for RECIPE in "${RECIPES[@]}"; do | ||||
|         _abra_basename "${RECIPE%.env}" | ||||
|     done | ||||
| } | ||||
|  | ||||
| _abra_complete_recipes() | ||||
| { | ||||
|     mapfile -t COMPREPLY < <(compgen -W "$(_abra_recipes)" -- "$1") | ||||
| } | ||||
|  | ||||
| _abra_complete() | ||||
| { | ||||
|     compopt +o default +o nospace | ||||
| @ -62,7 +46,6 @@ _abra_complete() | ||||
|     local -r cmds=' | ||||
|         app | ||||
|         server | ||||
|         recipe | ||||
|     ' | ||||
|     local -r short_opts='-e      -h     -s      -v' | ||||
|     local -r long_opts='--env --help --stack --version' | ||||
| @ -118,12 +101,6 @@ _abra_complete() | ||||
|                     _abra_complete_apps "$cur" | ||||
|                 fi | ||||
|                 ;; | ||||
|             recipe) | ||||
|                 # Offer exactly one app completion. | ||||
|                 if (( COMP_CWORD == cmd_index + 1 )); then | ||||
|                     _abra_complete_recipes "$cur" | ||||
|                 fi | ||||
|                 ;; | ||||
|             #help) | ||||
|             #    # Offer exactly one command name completion. | ||||
|             #    if (( COMP_CWORD == cmd_index + 1 )); then | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,41 +0,0 @@ | ||||
| --- | ||||
| version: "3.8" | ||||
|  | ||||
| services: | ||||
|   app: | ||||
|     image: "nginx:stable" | ||||
|     configs: | ||||
|       - source: abra_conf | ||||
|         target: /etc/nginx/conf.d/abra.conf | ||||
|       - source: abra_apps_json | ||||
|         target: /var/www/abra-apps/apps.json | ||||
|     volumes: | ||||
|       - "public:/var/www/abra-apps" | ||||
|     networks: | ||||
|       - proxy | ||||
|     deploy: | ||||
|       update_config: | ||||
|         failure_action: rollback | ||||
|         order: start-first | ||||
|       labels: | ||||
|         - "traefik.enable=true" | ||||
|         - "traefik.http.services.abra-apps.loadbalancer.server.port=80" | ||||
|         - "traefik.http.routers.abra-apps.rule=Host(`apps.coopcloud.tech`, `abra-apps.cloud.autonomic.zone`)" | ||||
|         - "traefik.http.routers.abra-apps.entrypoints=web-secure" | ||||
|         - "traefik.http.routers.abra-apps.tls.certresolver=production" | ||||
|         - "traefik.http.routers.abra-apps.middlewares=abra-apps-redirect" | ||||
|         - "traefik.http.middlewares.abra-apps-redirect.headers.SSLForceHost=true" | ||||
|         - "traefik.http.middlewares.abra-apps-redirect.headers.SSLHost=apps.coopcloud.tech" | ||||
|  | ||||
| configs: | ||||
|   abra_apps_json: | ||||
|     file: apps.json | ||||
|   abra_conf: | ||||
|     file: nginx.conf | ||||
|  | ||||
| networks: | ||||
|   proxy: | ||||
|     external: true | ||||
|  | ||||
| volumes: | ||||
|   public: | ||||
| @ -1,10 +0,0 @@ | ||||
| server { | ||||
|   listen         80 default_server; | ||||
|   server_name    apps.coopcloud.tech; | ||||
|  | ||||
|   location / { | ||||
|     root /var/www/abra-apps; | ||||
|     add_header Content-Type application/json; | ||||
|     index apps.json; | ||||
|   } | ||||
| } | ||||
| @ -2,7 +2,7 @@ | ||||
| version: "3.8" | ||||
| 
 | ||||
| services: | ||||
|   app: | ||||
|   abra_installer: | ||||
|     image: "nginx:stable" | ||||
|     configs: | ||||
|       - source: abra_conf | ||||
| @ -20,7 +20,7 @@ services: | ||||
|       labels: | ||||
|         - "traefik.enable=true" | ||||
|         - "traefik.http.services.abra-installer.loadbalancer.server.port=80" | ||||
|         - "traefik.http.routers.abra-installer.rule=Host(`install.abra.autonomic.zone`,`install.abra.coopcloud.tech`)" | ||||
|         - "traefik.http.routers.abra-installer.rule=Host(`install.abra.autonomic.zone`)" | ||||
|         - "traefik.http.routers.abra-installer.entrypoints=web-secure" | ||||
|         - "traefik.http.routers.abra-installer.tls.certresolver=production" | ||||
| 
 | ||||
| @ -1,9 +1,8 @@ | ||||
| #!/bin/bash | ||||
| 
 | ||||
| ABRA_VERSION="8.0.1" | ||||
| ABRA_VERSION="0.6.0" | ||||
| GIT_URL="https://git.autonomic.zone/coop-cloud/abra" | ||||
| ABRA_SRC="$GIT_URL/raw/tag/$ABRA_VERSION/abra" | ||||
| ABRA_DIR="${ABRA_DIR:-$HOME/.abra/}" | ||||
| 
 | ||||
| function install_abra_release { | ||||
|   mkdir -p "$HOME/.local/bin" | ||||
| @ -13,13 +12,13 @@ function install_abra_release { | ||||
| } | ||||
| 
 | ||||
| function install_abra_dev { | ||||
|   mkdir -p "$ABRA_DIR/" | ||||
|   if [[ ! -d "$ABRA_DIR/src" ]]; then | ||||
|     git clone "$GIT_URL" "$ABRA_DIR/src" | ||||
|   mkdir -p "$HOME/.abra/" | ||||
|   if [[ ! -d "$HOME/.abra/src" ]]; then | ||||
|     git clone "$GIT_URL" "$HOME/.abra/src" | ||||
|   fi | ||||
|   (cd "$ABRA_DIR/src" && git pull origin main && cd - || exit) | ||||
|   ( cd "$HOME/.abra/src" && git pull origin main && cd -) | ||||
|   mkdir -p "$HOME/.local/bin" | ||||
|   ln -sf "$ABRA_DIR/src/abra" "$HOME/.local/bin/abra" | ||||
|   ln -sf "$HOME/.abra/src/abra" "$HOME/.local/bin/abra" | ||||
|   echo "abra installed to $HOME/.local/bin/abra (development bleeding edge)" | ||||
| } | ||||
| 
 | ||||
| @ -1,6 +1,6 @@ | ||||
| server { | ||||
|   listen         80 default_server; | ||||
|   server_name    install.abra.autonomic.zone install.abra.coopcloud.tech; | ||||
|   server_name    install.abra.autonomic.zone; | ||||
| 
 | ||||
|   location / { | ||||
|     root /var/www/abra-installer; | ||||
							
								
								
									
										22
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								makefile
									
									
									
									
									
								
							| @ -8,12 +8,12 @@ test: | ||||
| 		--name=abra-test-dind \ | ||||
| 		-e DOCKER_TLS_CERTDIR="" \ | ||||
| 		decentral1se/docker-dind-bats-kcov | ||||
| 	@DOCKER_CONTEXT=default sudo docker exec \ | ||||
| 	@DOCKER_CONTEXT=default docker exec \ | ||||
| 		-it \ | ||||
| 		abra-test-dind \ | ||||
| 		sh -c "cd /workdir && bats /workdir/tests" | ||||
| 	@DOCKER_CONTEXT=default sudo docker stop abra-test-dind | ||||
| 	@DOCKER_CONTEXT=default sudo docker rm abra-test-dind | ||||
| 	@DOCKER_CONTEXT=default docker stop abra-test-dind | ||||
| 	@DOCKER_CONTEXT=default docker rm abra-test-dind | ||||
|  | ||||
| shellcheck: | ||||
| 	@docker run \ | ||||
| @ -21,8 +21,7 @@ shellcheck: | ||||
| 		--rm \ | ||||
| 		-v $$(pwd):/workdir \ | ||||
| 		koalaman/shellcheck-alpine \ | ||||
| 		shellcheck /workdir/abra && \ | ||||
| 		shellcheck /workdir/bin/*.sh | ||||
| 		shellcheck /workdir/abra | ||||
|  | ||||
| docopt: | ||||
| 	@if [ ! -d ".venv" ]; then \ | ||||
| @ -46,13 +45,6 @@ codecov: | ||||
| 		-s coverage -t $$(pass show hosts/swarm.autonomic.zone/drone/codecov/token) | ||||
|  | ||||
| release-installer: | ||||
| 	@DOCKER_CONTEXT=swarm.autonomic.zone \ | ||||
| 		docker stack rm abra-installer-script && \ | ||||
| 		cd deploy/install.abra.coopcloud.tech && \ | ||||
| 		DOCKER_CONTEXT=swarm.autonomic.zone docker stack deploy -c compose.yml abra-installer-script | ||||
|  | ||||
| release-apps: | ||||
| 	@DOCKER_CONTEXT=swarm.autonomic.zone \ | ||||
| 		docker stack rm abra-apps-json && \ | ||||
| 		cd deploy/apps.coopcloud.tech && \ | ||||
| 		DOCKER_CONTEXT=swarm.autonomic.zone docker stack deploy -c compose.yml abra-apps-json | ||||
| 	@docker stack rm abra-installer-script && \ | ||||
| 		cd installer && \ | ||||
| 		docker stack deploy -c compose.yml abra-installer-script | ||||
|  | ||||
| @ -9,48 +9,44 @@ teardown() { | ||||
|     rm -rf "$ABRA_DIR" | ||||
| } | ||||
|  | ||||
| abra() { | ||||
|     ./abra -d $@ | ||||
| } | ||||
|  | ||||
| @test "abra server (add|rm)" { | ||||
|     abra server add swarm.test.com | ||||
|     ./abra server add swarm.test.com | ||||
|     docker context ls | grep swarm.test.com | ||||
|     [ -d $ABRA_DIR/servers/swarm.test.com ] | ||||
|     abra server swarm.test.com rm | ||||
|     ./abra server swarm.test.com rm | ||||
|  | ||||
|     abra server add swarm.test.com foobar 12345 | ||||
|     ./abra server add swarm.test.com foobar 12345 | ||||
|     [ -d $ABRA_DIR/servers/swarm.test.com ] | ||||
|     abra server swarm.test.com rm | ||||
|     ./abra server swarm.test.com rm | ||||
| } | ||||
|  | ||||
| @test "abra server init" { | ||||
|     abra server default init | ||||
|     ./abra server default init | ||||
| } | ||||
|  | ||||
| @test "abra app (new|rm)" { | ||||
|     abra app new --server default --domain traefik.test.com --app-name traefik_test_com traefik | ||||
|     ./abra app new --server default --domain traefik.test.com --app-name traefik_test_com traefik | ||||
|     [ -f $ABRA_DIR/servers/default/traefik_test_com.env ] | ||||
|  | ||||
|     # interactive prompt | ||||
|     echo "y" | abra app traefik_test_com delete | ||||
|     echo "y" | ./abra app traefik_test_com delete | ||||
|     [ ! -f $ABRA_DIR/servers/default/traefik_test_com.env ] | ||||
|  | ||||
|     # --no-prompt | ||||
|     abra app new --server default --domain traefik_test_com --app-name traefik_test_com traefik | ||||
|     abra --no-prompt app traefik_test_com delete | ||||
|     # --force | ||||
|     ./abra app new --server default --domain traefik_test_com --app-name traefik_test_com traefik | ||||
|     ./abra app traefik_test_com delete --force | ||||
|     [ ! -f $ABRA_DIR/servers/default/traefik_test_com.env ] | ||||
| } | ||||
|  | ||||
| @test "abra app <domain> secret (insert|generate|rm)" { | ||||
|     abra app new --server default --domain traefik_test_com --app-name traefik_test_com traefik | ||||
|     ./abra app new --server default --domain traefik_test_com --app-name traefik_test_com traefik | ||||
|  | ||||
|     abra app traefik_test_com secret insert foobar v1 "foobar" | ||||
|     ./abra app traefik_test_com secret insert foobar v1 "foobar" | ||||
|  | ||||
|     # interactive prompt | ||||
|     echo "y" | abra app traefik_test_com secret rm foobar | ||||
|     echo "y" | ./abra app traefik_test_com secret rm foobar | ||||
|  | ||||
|     abra app traefik_test_com secret insert foobar v1 "foobar" | ||||
|     ./abra app traefik_test_com secret insert foobar v1 "foobar" | ||||
|     #  prompt | ||||
|     abra --no-prompt app traefik_test_com secret rm foobar | ||||
|     ./abra app traefik_test_com secret rm foobar --force | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	