mirror of
https://gitlab.com/psuapp/psu.git
synced 2024-08-30 18:12:34 +00:00
Merge GitLab integration
# Conflicts: # CHANGELOG.md # Dockerfile # README.md # psu
This commit is contained in:
parent
edde3e86c7
commit
aca3e69669
162
.gitlab-ci.yml
Normal file
162
.gitlab-ci.yml
Normal file
@ -0,0 +1,162 @@
|
||||
image: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/hub/auto-deploy-image:latest
|
||||
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay2
|
||||
TRAEFIK_VERSION: 1.7-alpine
|
||||
PORTAINER_VERSION: latest
|
||||
PSU_IMAGE: ${CI_REGISTRY_IMAGE}/builds
|
||||
PSU_TAG: $CI_COMMIT_SHA
|
||||
PSU_TAG_CORE: core-${CI_COMMIT_SHA}
|
||||
DOCKER_REGISTRY_IMAGE: $DOCKER_REGISTRY/$CI_PROJECT_PATH
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
.build_template: &build_definition
|
||||
stage: build
|
||||
services:
|
||||
- docker:dind
|
||||
except:
|
||||
refs:
|
||||
- gitlab-pages
|
||||
variables:
|
||||
- $CI_COMMIT_TAG == "dev"
|
||||
script:
|
||||
- setup_docker
|
||||
- registry_login
|
||||
- cd ${CONTAINER_FOLDER:-.}
|
||||
- docker pull $CONTAINER_IMAGE:${CONTAINER_VERSION:-latest} || true
|
||||
- docker build --pull $(if [[ -n "$DOCKER_CACHE_DISABLED" ]]; then echo "--no-cache "; else echo "--cache-from $CONTAINER_IMAGE:${CONTAINER_VERSION:-latest}"; fi) --file ${DOCKER_FILE:-Dockerfile} --tag $CONTAINER_IMAGE:${CONTAINER_COMMIT_SHA:-$CI_COMMIT_SHA} --tag $CONTAINER_IMAGE:${CONTAINER_VERSION:-latest} --build-arg HTTP_PROXY="$HTTP_PROXY" --build-arg http_proxy="$http_proxy" --build-arg HTTPS_PROXY="$HTTPS_PROXY" --build-arg https_proxy="$https_proxy" --build-arg FTP_PROXY="$FTP_PROXY" --build-arg ftp_proxy="$ftp_proxy" --build-arg NO_PROXY="$NO_PROXY" --build-arg no_proxy="$no_proxy" .
|
||||
- docker push $CONTAINER_IMAGE:${CONTAINER_COMMIT_SHA:-$CI_COMMIT_SHA}
|
||||
- docker push $CONTAINER_IMAGE:${CONTAINER_VERSION:-latest}
|
||||
|
||||
build:main:
|
||||
<<: *build_definition
|
||||
variables:
|
||||
CONTAINER_NAME: $CI_PROJECT_NAME
|
||||
CONTAINER_VERSION: $CI_COMMIT_REF_SLUG-build
|
||||
CONTAINER_IMAGE: ${CI_REGISTRY_IMAGE}/builds
|
||||
|
||||
build:debian:
|
||||
<<: *build_definition
|
||||
variables:
|
||||
CONTAINER_NAME: $CI_PROJECT_NAME
|
||||
CONTAINER_VERSION: $CI_COMMIT_REF_SLUG-build-debian
|
||||
CONTAINER_COMMIT_SHA: debian-$CI_COMMIT_SHA
|
||||
DOCKER_FILE: Dockerfile.debian
|
||||
CONTAINER_IMAGE: ${CI_REGISTRY_IMAGE}/builds
|
||||
|
||||
build:core:
|
||||
<<: *build_definition
|
||||
variables:
|
||||
CONTAINER_NAME: $CI_PROJECT_NAME
|
||||
CONTAINER_VERSION: $CI_COMMIT_REF_SLUG-build-core
|
||||
CONTAINER_COMMIT_SHA: core-$CI_COMMIT_SHA
|
||||
DOCKER_FILE: Dockerfile.core
|
||||
CONTAINER_IMAGE: ${CI_REGISTRY_IMAGE}/builds
|
||||
build:debian-core:
|
||||
<<: *build_definition
|
||||
variables:
|
||||
CONTAINER_NAME: $CI_PROJECT_NAME
|
||||
CONTAINER_VERSION: $CI_COMMIT_REF_SLUG-build-debian-core
|
||||
CONTAINER_COMMIT_SHA: debian-core-$CI_COMMIT_SHA
|
||||
DOCKER_FILE: Dockerfile.debian-core
|
||||
CONTAINER_IMAGE: ${CI_REGISTRY_IMAGE}/builds
|
||||
|
||||
.test_template: &test_definition
|
||||
stage: test
|
||||
services:
|
||||
- name: docker:dind
|
||||
alias: cluster
|
||||
except:
|
||||
refs:
|
||||
- gitlab-pages
|
||||
variables:
|
||||
- $TEST_DISABLED
|
||||
- $CI_COMMIT_TAG == "dev"
|
||||
script:
|
||||
- setup_docker
|
||||
- registry_login
|
||||
- bash scripts/test.sh
|
||||
|
||||
test:portainer-1.19.2:
|
||||
<<: *test_definition
|
||||
variables:
|
||||
PORTAINER_VERSION: 1.19.2
|
||||
|
||||
test:portainer-1.20.2:
|
||||
<<: *test_definition
|
||||
variables:
|
||||
PORTAINER_VERSION: 1.20.2
|
||||
|
||||
test:portainer-latest:
|
||||
<<: *test_definition
|
||||
|
||||
test:portainer-latest:debian:
|
||||
<<: *test_definition
|
||||
variables:
|
||||
PSU_TAG: debian-${CI_COMMIT_SHA}
|
||||
PSU_TAG_CORE: debian-core-${CI_COMMIT_SHA}
|
||||
|
||||
release:
|
||||
stage: deploy
|
||||
services:
|
||||
- docker:dind
|
||||
except:
|
||||
refs:
|
||||
- gitlab-pages
|
||||
variables:
|
||||
- $CI_COMMIT_TAG == "dev"
|
||||
script:
|
||||
- setup_docker
|
||||
- registry_login
|
||||
- external_registry_login
|
||||
# Tagging git repository and Docker images on successful builds and tests
|
||||
# First argument is the variant(s) of the Docker image
|
||||
# e.g. "core"
|
||||
# or for multiple variants: "core debian debian-core"
|
||||
- bash scripts/release.sh "core debian debian-core"
|
||||
|
||||
generate-docs:
|
||||
stage: deploy
|
||||
script:
|
||||
- mkdir -p public/$CI_COMMIT_REF_SLUG
|
||||
- cp -r docs/. public/$CI_COMMIT_REF_SLUG
|
||||
- mkdir public/$CI_COMMIT_REF_SLUG/repo
|
||||
- cp *.md public/$CI_COMMIT_REF_SLUG/repo
|
||||
- bash scripts/push-to-gitlab-pages.sh
|
||||
only:
|
||||
variables:
|
||||
- $CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_REF_NAME =~ /^.+-stable$/ && $CI_COMMIT_REF_PROTECTED == "true"
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
before_script:
|
||||
- echo ""
|
||||
script:
|
||||
# Gzip all static files before publishing GitLab Pages
|
||||
# Source: https://www.queryxchange.com/q/5_119670/how-do-you-serve-jekyll-pages-with-gzip-compression-on-gitlab-pages/
|
||||
- find public \( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.md' \) -print0 | xargs -0 gzip -9 -kv
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- gitlab-pages
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
|
||||
before_script:
|
||||
- set -e
|
||||
- source scripts/helpers.sh
|
||||
# Used for updating the Docker images, but not the psu code
|
||||
# Via Scheduling Pipelines
|
||||
# See: https://gitlab.com/help/user/project/pipelines/schedules
|
||||
- git_reset_from_tag
|
||||
# Used for updating Docker images, on release/stable branches, but not the psu code
|
||||
- git_reset_from_last_stable_tag
|
25
CHANGELOG.md
25
CHANGELOG.md
@ -5,10 +5,27 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- New actions: `ls`, `status`, `services`, `tasks`, `tasks:healthy`, `containers`, `login`, `lint`, `inspect`, `system:info`, `actions`, `help` and `version`
|
||||
- New options: `--auth-token=[AUTH_TOKEN]`, `--compose-file-base64=[BASE64]`, `--env-file-base64=[BASE64]`, `--timeout=[SECONDS]`, `--detect-job=[true|false]`, `--service=[SERVICE_NAME]`, `--insecure`, `--masked-variables`, `--quiet`, `--lint`, `--help` and `--version`
|
||||
- New flags: `-A`, `-C`, `-F`, `-G`, `-T`, `-j`, `-i`, `-S`, `-m`, `-q`, `-L`, `-h` and `-V`
|
||||
- New environment variables: `PORTAINER_AUTH_TOKEN`, `TIMEOUT`, `AUTO_DETECT_JOB`, `PORTAINER_SERVICE_NAME`, `MASKED_VARIABLES`, `QUIET_MODE` and `DOCKER_COMPOSE_LINT`
|
||||
- The Docker image include now `docker-compose` to be able to lint Docker compose/stack file
|
||||
- The `core` Docker image variant doesn't include `docker-compose`, so it's a bit smaller. But you can't lint Docker compose/stack file before deploying a stack
|
||||
- The `debian` and `debian-core` Docker image variants, use [Debian](https://www.debian.org) instead of [Alpine](https://alpinelinux.org/) as base image for `psu`
|
||||
- Online documentation via [docsify](https://docsify.js.org)
|
||||
- Tests who run automatically on each git push via [GitLab CI](https://docs.gitlab.com/ce/ci/)
|
||||
|
||||
### Changed
|
||||
- The `undeploy` action is now an aliased action. You should use `rm` action instead
|
||||
|
||||
### Deprecated
|
||||
- The `--secure=[yes|no]` option and `-s` flag are deprecated. Use the `--insecure` option instead (`psu <action> ... --inscure`)
|
||||
- The `--action=[ACTION_NAME]` option and `-a` flag are deprecated. Use `<action>` argument instead (`psu <action> ...`)
|
||||
|
||||
## [0.1.1] - 2019-06-05
|
||||
### Fixed
|
||||
- Fixed error when environment variables loaded from file contain spaces in their values [#14](https://github.com/greenled/portainer-stack-utils/pull/14)
|
||||
- Fixed error when environment variables loaded from file contain spaces in their values [#14](https://gitlab.com/psuapp/psu/merge_requests/14)
|
||||
|
||||
## [0.1.0] - 2019-05-24
|
||||
### Added
|
||||
@ -23,6 +40,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Debug mode
|
||||
- Strict mode
|
||||
|
||||
[Unreleased]: https://github.com/greenled/portainer-stack-utils/compare/0.1.1...HEAD
|
||||
[0.1.1]: https://github.com/greenled/portainer-stack-utils/releases/tag/0.1.1
|
||||
[0.1.0]: https://github.com/greenled/portainer-stack-utils/releases/tag/0.1.0
|
||||
[Unreleased]: https://gitlab.com/psuapp/psu/compare/v0.1.1...master
|
||||
[0.1.1]: https://gitlab.com/psuapp/psu/-/tags/v0.1.1
|
||||
[0.1.0]: https://gitlab.com/psuapp/psu/-/tags/v0.1.0
|
||||
|
14
Dockerfile
14
Dockerfile
@ -1,13 +1,13 @@
|
||||
FROM alpine:3.10
|
||||
|
||||
RUN apk add --no-cache \
|
||||
bash ca-certificates gettext httpie jq \
|
||||
py3-pip python3-dev libc-dev libffi-dev openssl-dev gcc make; \
|
||||
\
|
||||
pip3 --no-cache-dir install docker-compose; \
|
||||
\
|
||||
apk del python3-dev libc-dev libffi-dev openssl-dev gcc make; \
|
||||
rm -rf /tmp/src
|
||||
bash ca-certificates gettext httpie jq \
|
||||
py3-pip python3-dev libc-dev libffi-dev openssl-dev gcc make; \
|
||||
\
|
||||
pip3 --no-cache-dir install docker-compose; \
|
||||
\
|
||||
apk del python3-dev libc-dev libffi-dev openssl-dev gcc make; \
|
||||
rm -rf /tmp/src
|
||||
|
||||
ENV LANG="en_US.UTF-8" \
|
||||
LC_ALL="C.UTF-8" \
|
||||
|
36
Dockerfile.core
Normal file
36
Dockerfile.core
Normal file
@ -0,0 +1,36 @@
|
||||
FROM alpine:3.10
|
||||
|
||||
RUN apk add --no-cache \
|
||||
bash ca-certificates gettext httpie jq
|
||||
|
||||
ENV LANG="en_US.UTF-8" \
|
||||
LC_ALL="C.UTF-8" \
|
||||
LANGUAGE="en_US.UTF-8" \
|
||||
TERM="xterm" \
|
||||
ACTION="" \
|
||||
PORTAINER_USER="" \
|
||||
PORTAINER_PASSWORD="" \
|
||||
PORTAINER_AUTH_TOKEN="" \
|
||||
PORTAINER_URL="" \
|
||||
PORTAINER_STACK_NAME="" \
|
||||
PORTAINER_SERVICE_NAME="" \
|
||||
DOCKER_COMPOSE_FILE="" \
|
||||
DOCKER_COMPOSE_LINT="false" \
|
||||
ENVIRONMENT_VARIABLES_FILE="" \
|
||||
PORTAINER_ENDPOINT="1" \
|
||||
PORTAINER_PRUNE="false" \
|
||||
TIMEOUT=100 \
|
||||
AUTO_DETECT_JOB="true" \
|
||||
HTTPIE_VERIFY_SSL="yes" \
|
||||
VERBOSE_MODE="false" \
|
||||
DEBUG_MODE="false" \
|
||||
QUIET_MODE="false" \
|
||||
STRICT_MODE="false" \
|
||||
MASKED_VARIABLES="false" \
|
||||
PSU_CORE_EDITION="true"
|
||||
|
||||
COPY psu /usr/local/bin/
|
||||
|
||||
RUN chmod +x /usr/local/bin/psu
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/psu"]
|
43
Dockerfile.debian
Normal file
43
Dockerfile.debian
Normal file
@ -0,0 +1,43 @@
|
||||
FROM debian:9-slim
|
||||
|
||||
RUN apt-get update -yqq; \
|
||||
apt-get install \
|
||||
ca-certificates gettext-base httpie jq curl -yqq; \
|
||||
\
|
||||
curl -fL "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose; \
|
||||
chmod +x /usr/local/bin/docker-compose; \
|
||||
\
|
||||
apt-get purge curl -y; \
|
||||
apt-get clean; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV LANG="en_US.UTF-8" \
|
||||
LC_ALL="C.UTF-8" \
|
||||
LANGUAGE="en_US.UTF-8" \
|
||||
TERM="xterm" \
|
||||
ACTION="" \
|
||||
PORTAINER_USER="" \
|
||||
PORTAINER_PASSWORD="" \
|
||||
PORTAINER_AUTH_TOKEN="" \
|
||||
PORTAINER_URL="" \
|
||||
PORTAINER_STACK_NAME="" \
|
||||
PORTAINER_SERVICE_NAME="" \
|
||||
DOCKER_COMPOSE_FILE="" \
|
||||
DOCKER_COMPOSE_LINT="true" \
|
||||
ENVIRONMENT_VARIABLES_FILE="" \
|
||||
PORTAINER_ENDPOINT="1" \
|
||||
PORTAINER_PRUNE="false" \
|
||||
TIMEOUT=100 \
|
||||
AUTO_DETECT_JOB="true" \
|
||||
HTTPIE_VERIFY_SSL="yes" \
|
||||
VERBOSE_MODE="false" \
|
||||
DEBUG_MODE="false" \
|
||||
QUIET_MODE="false" \
|
||||
STRICT_MODE="false" \
|
||||
MASKED_VARIABLES="false"
|
||||
|
||||
COPY psu /usr/local/bin/
|
||||
|
||||
RUN chmod +x /usr/local/bin/psu
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/psu"]
|
40
Dockerfile.debian-core
Normal file
40
Dockerfile.debian-core
Normal file
@ -0,0 +1,40 @@
|
||||
FROM debian:9-slim
|
||||
|
||||
RUN apt-get update -yqq; \
|
||||
apt-get install \
|
||||
ca-certificates gettext-base httpie jq -yqq; \
|
||||
\
|
||||
apt-get clean; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV LANG="en_US.UTF-8" \
|
||||
LC_ALL="C.UTF-8" \
|
||||
LANGUAGE="en_US.UTF-8" \
|
||||
TERM="xterm" \
|
||||
ACTION="" \
|
||||
PORTAINER_USER="" \
|
||||
PORTAINER_PASSWORD="" \
|
||||
PORTAINER_AUTH_TOKEN="" \
|
||||
PORTAINER_URL="" \
|
||||
PORTAINER_STACK_NAME="" \
|
||||
PORTAINER_SERVICE_NAME="" \
|
||||
DOCKER_COMPOSE_FILE="" \
|
||||
DOCKER_COMPOSE_LINT="false" \
|
||||
ENVIRONMENT_VARIABLES_FILE="" \
|
||||
PORTAINER_ENDPOINT="1" \
|
||||
PORTAINER_PRUNE="false" \
|
||||
TIMEOUT=100 \
|
||||
AUTO_DETECT_JOB="true" \
|
||||
HTTPIE_VERIFY_SSL="yes" \
|
||||
VERBOSE_MODE="false" \
|
||||
DEBUG_MODE="false" \
|
||||
QUIET_MODE="false" \
|
||||
STRICT_MODE="false" \
|
||||
MASKED_VARIABLES="false" \
|
||||
PSU_CORE_EDITION="true"
|
||||
|
||||
COPY psu /usr/local/bin/
|
||||
|
||||
RUN chmod +x /usr/local/bin/psu
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/psu"]
|
236
README.md
236
README.md
@ -1,14 +1,31 @@
|
||||
# Portainer Stack Utils
|
||||
<h1>Portainer Stack Utils</h1>
|
||||
<div class="docsify-hidden">
|
||||
|
||||
[![Docker Automated build](https://img.shields.io/docker/automated/greenled/portainer-stack-utils.svg)](https://hub.docker.com/r/greenled/portainer-stack-utils/)
|
||||
[![Docker Pulls](https://img.shields.io/docker/pulls/greenled/portainer-stack-utils.svg)](https://hub.docker.com/r/greenled/portainer-stack-utils/)
|
||||
[![Microbadger](https://images.microbadger.com/badges/image/greenled/portainer-stack-utils.svg)](http://microbadger.com/images/greenled/portainer-stack-utils "Image size")
|
||||
[![Docker Pulls](https://img.shields.io/docker/pulls/psuapp/psu.svg)](https://hub.docker.com/r/psuapp/psu/)
|
||||
[![Microbadger](https://images.microbadger.com/badges/image/psuapp/psu.svg)](http://microbadger.com/images/psuapp/psu "Image size")
|
||||
[![pipeline status](https://gitlab.com/psuapp/psu/badges/master/pipeline.svg)](https://gitlab.com/psuapp/psu/commits/master)
|
||||
|
||||
Bash script to deploy/update/undeploy stacks in a [Portainer](https://portainer.io/) instance from a [docker-compose](https://docs.docker.com/compose) [yaml file](https://docs.docker.com/compose/compose-file). Based on previous work by [@vladbabii](https://github.com/vladbabii) on [docker-how-to/portainer-bash-scripts](https://github.com/docker-how-to/portainer-bash-scripts).
|
||||
Bash script to deploy/update/remove stacks in a [Portainer](https://portainer.io/) instance from a [docker-compose](https://docs.docker.com/compose) [yaml file](https://docs.docker.com/compose/compose-file).
|
||||
|
||||
## Supported Portainer API
|
||||
_Based on previous work by [@vladbabii](https://github.com/vladbabii) on [docker-how-to/portainer-bash-scripts](https://github.com/docker-how-to/portainer-bash-scripts)._
|
||||
|
||||
Script was created for the latest Portainer API, which at the time of writing is [1.19.2](https://app.swaggerhub.com/apis/deviantony/Portainer/1.19.2).
|
||||
<h2>Table of contents</h2>
|
||||
<!-- Generated by https://github.com/mcpride/atom-mdtoc -->
|
||||
<!-- MDTOC maxdepth:2 firsth1:2 numbering:0 flatten:0 bullets:1 updateOnSave:1 -->
|
||||
|
||||
- [How to install](#how-to-install)
|
||||
- [Standalone](#standalone)
|
||||
- [Docker image and variants](#docker-image-and-variants)
|
||||
- [How to use](#how-to-use)
|
||||
- [With options](#with-options)
|
||||
- [With flags](#with-flags)
|
||||
- [With envvars](#with-envvars)
|
||||
- [Documentation](#documentation)
|
||||
- [Supported Portainer API](#supported-portainer-api)
|
||||
- [License](#license)
|
||||
|
||||
<!-- /MDTOC -->
|
||||
</div>
|
||||
|
||||
## How to install
|
||||
|
||||
@ -17,9 +34,9 @@ Script was created for the latest Portainer API, which at the time of writing is
|
||||
Just clone the repo and use the script:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/greenled/portainer-stack-utils.git
|
||||
cd portainer-stack-utils
|
||||
./psu -a deploy ...
|
||||
git clone https://gitlab.com/psuapp/psu.git
|
||||
cd psu/
|
||||
bash ./psu deploy ...
|
||||
```
|
||||
|
||||
For detailed instructions, see [How to use](#how-to-use) section.
|
||||
@ -34,48 +51,122 @@ You will need these dependencies installed:
|
||||
|
||||
For Debian and similar apt-powered systems: `apt install bash httpie jq`.
|
||||
|
||||
### Docker image
|
||||
|
||||
Use [the published Docker image](https://hub.docker.com/r/greenled/portainer-stack-utils/):
|
||||
### Docker image and variants
|
||||
|
||||
If you don't want or can't install `psu` and its dependencies, you can run it with the default [published Docker image](https://hub.docker.com/r/psuapp/psu), like this:
|
||||
```bash
|
||||
docker run -e ACTION=deploy greenled/portainer-stack-utils ...
|
||||
docker run psuapp/psu deploy ...
|
||||
```
|
||||
|
||||
See the [With envvars](#with-envvars) section for a list of all supported environment variables.
|
||||
For detailed instructions, see [How to use](#how-to-use) section.
|
||||
|
||||
#### Supported tags
|
||||
|
||||
#### Tags
|
||||
Published Docker images are [tagged](https://hub.docker.com/r/psuapp/psu/tags) matching [GitLab tags](https://gitlab.com/psuapp/psu/-/tags):
|
||||
|
||||
Published images are [tagged](https://hub.docker.com/r/greenled/portainer-stack-utils/tags/) matching [GitHub releases](https://github.com/greenled/portainer-stack-utils/releases):
|
||||
- `dev` -> [`dev`](https://gitlab.com/psuapp/psu/-/tags/dev)
|
||||
<!-- - `1.1.0-alpha.1` -> [`v1.1.0-alpha.1`](https://gitlab.com/psuapp/psu/-/tags/v1.1.0-alpha.1) -->
|
||||
<!-- - `1`, `1.0`, `1.0.0`, `latest` -> [`v1.0.0`](https://gitlab.com/psuapp/psu/-/tags/v1.0.0) -->
|
||||
- `0.1.1`, `latest` -> [`v0.1.1`](https://gitlab.com/psuapp/psu/-/tags/v0.1.1)
|
||||
- `0.1.0` -> [`v0.1.0`](https://gitlab.com/psuapp/psu/-/tags/v0.1.0)
|
||||
|
||||
- `latest`, `0.1.1` -> `0.1.1`
|
||||
- `0.1.0` -> `0.1.0`
|
||||
- ...
|
||||
- `dev` -> `master`
|
||||
##### Variants
|
||||
|
||||
The `core` variant doesn't include `docker-compose`, so it's a bit smaller.
|
||||
But you can't lint Docker compose/stack file before deploying a stack.
|
||||
- `dev-core` -> [`dev`](https://gitlab.com/psuapp/psu/-/tags/dev)
|
||||
<!-- - `1-core`, `1.0-core`, `1.0.0-core`, `core` -> [`v1.0.0`](https://gitlab.com/psuapp/psu/-/tags/v1.0.0) -->
|
||||
|
||||
The `debian` and `debian-core` variants use [Debian](https://www.debian.org) instead of [Alpine](https://alpinelinux.org/) as base image for `psu`.
|
||||
- `dev-debian` -> [`dev`](https://gitlab.com/psuapp/psu/-/tags/dev)
|
||||
- `dev-debian-core` -> [`dev`](https://gitlab.com/psuapp/psu/-/tags/dev)
|
||||
<!-- - `1-debian`, `1.0-debian`, `1.0.0-debian`, `debian` -> [`v1.0.0`](https://gitlab.com/psuapp/psu/-/tags/v1.0.0) -->
|
||||
<!-- - `1-debian-core`, `1.0-debian-core`, `1.0.0-debian-core`, `debian-core` -> [`v1.0.0`](https://gitlab.com/psuapp/psu/-/tags/v1.0.0) -->
|
||||
|
||||
|
||||
#### Testing/debugging:
|
||||
|
||||
For testing/debugging, you can use this Docker image in interactive mode, to run any commands inside the container:
|
||||
```bash
|
||||
docker run -v $(pwd)/docker-compose.yml:/docker-compose.yml -it --rm --entrypoint bash psuapp/psu
|
||||
# Run any commands here! E.g.
|
||||
$ psu --version
|
||||
Portainer Stack Utils, version 1.0.0
|
||||
License GPLv3: GNU GPL version 3
|
||||
```
|
||||
|
||||
## How to use
|
||||
|
||||
The provided `psu` script allows to deploy/update/undeploy Portainer stacks. Settings can be passed through envvars and/or flags. Both envvars and flags can be mixed but flags will always overwrite envvar values. When deploying a stack, if it doesn't exist a new one is created, otherwise it's updated (unless strict mode is active).
|
||||
The provided `psu` script allows to deploy/update/remove... Portainer stacks. Settings can be passed through envvars and/or options and/or flags. Both envvars, options and flags can be mixed but options or flags will always overwrite envvar values. When deploying a stack, if it doesn't exist a new one is created, otherwise it's updated (unless strict mode is active).
|
||||
|
||||
### With options
|
||||
|
||||
This is more suitable for standalone script usage.
|
||||
|
||||
- `<action>` ("deploy", "rm", "ls"..., required): Whether to deploy, remove, list... the stack, _not an option but an argument_
|
||||
- `--user` (string, required): Username
|
||||
- `--password` (string, required): Password
|
||||
- `--url` (string, required): URL to Portainer
|
||||
- `--name` (string, required): Stack name
|
||||
- `--compose-file` (string, required if action=deploy): Path to docker-compose file
|
||||
|
||||
For detailed instructions, see the full [options list](docs/README.md#available-options).
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bash ./psu deploy --user admin --password password --url https://portainer.local --name mystack --compose-file /path/to/docker-compose.yml --env-file /path/to/env_vars_file
|
||||
```
|
||||
|
||||
```bash
|
||||
bash ./psu rm --user admin --password password --url https://portainer.local --name mystack
|
||||
```
|
||||
|
||||
**With Docker:**
|
||||
```bash
|
||||
docker run -v $(pwd)/docker-compose.yml:/docker-compose.yml -v $(pwd)/.env:/.env psuapp/psu deploy --user admin --password password --url https://portainer.local --name mystack --compose-file docker-compose.yml --env-file .env
|
||||
```
|
||||
|
||||
### With flags
|
||||
|
||||
This is more suitable for standalone script usage.
|
||||
|
||||
- `<action>` ("deploy", "rm", "ls"..., required): Whether to deploy, remove, list... the stack, _not a flag but an argument_
|
||||
- `-u` (string, required): Username
|
||||
- `-p` (string, required): Password
|
||||
- `-l` (string, required): URL to Portainer
|
||||
- `-n` (string, required): Stack name
|
||||
- `-c` (string, required if action=deploy): Path to docker-compose file
|
||||
|
||||
For detailed instructions, see the full [flags list](docs/README.md#available-options).
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bash ./psu deploy -u admin -p password -l https://portainer.local -n mystack -c /path/to/docker-compose.yml -g /path/to/env_vars_file
|
||||
```
|
||||
|
||||
```bash
|
||||
bash ./psu rm -u admin -p password -l https://portainer.local -n mystack
|
||||
```
|
||||
|
||||
**With Docker:**
|
||||
```bash
|
||||
docker run -v $(pwd)/docker-compose.yml:/docker-compose.yml -v $(pwd)/.env:/.env psuapp/psu deploy -u admin -p password -l https://portainer.local -n mystack -c docker-compose.yml -g .env
|
||||
```
|
||||
|
||||
### With envvars
|
||||
|
||||
This is particularly useful for CI/CD pipelines using Docker containers.
|
||||
This is particularly useful for [CI](https://en.wikipedia.org/wiki/Continuous_integration)/[CD](https://en.wikipedia.org/wiki/Continuous_deployment) pipelines using Docker containers.
|
||||
|
||||
- `ACTION` ("deploy" or "undeploy", required): Whether to deploy or undeploy the stack
|
||||
- `ACTION` ("deploy", "rm", "ls"..., required): Whether to deploy, remove, list... the stack
|
||||
- `PORTAINER_USER` (string, required): Username
|
||||
- `PORTAINER_PASSWORD` (string, required): Password
|
||||
- `PORTAINER_URL` (string, required): URL to Portainer
|
||||
- `PORTAINER_STACK_NAME` (string, required): Stack name
|
||||
- `DOCKER_COMPOSE_FILE` (string, required if action=deploy): Path to doker-compose file
|
||||
- `ENVIRONMENT_VARIABLES_FILE` (string, optional, only used when action=deploy or action=update): Path to file with environment variables to be used by the stack. See [stack environment variables](#stack-environment-variables) below.
|
||||
- `PORTAINER_PRUNE` ("true" or "false", optional): Whether to prune unused containers or not. Defaults to `"false"`.
|
||||
- `PORTAINER_ENDPOINT` (int, optional): Which endpoint to use. Defaults to `1`.
|
||||
- `HTTPIE_VERIFY_SSL` ("yes" or "no", optional): Whether to verify SSL certificate or not. Defaults to `"yes"`.
|
||||
- `VERBOSE_MODE` ("true" or "false", optional): Whether to activate verbose output mode or not. Defaults to `"false"`. See [verbose mode](#verbose-mode) below.
|
||||
- `DEBUG_MODE` ("true" or "false", optional): Whether to activate debug output mode or not. Defaults to `"false"`. See [debug mode](#debug-mode) below.
|
||||
- `STRICT_MODE` ("true" or "false", optional): Whether to activate strict mode or not. Defaults to `"false"`. See [strict mode](#strict-mode) below.
|
||||
|
||||
For detailed instructions, see the full [envvars list](docs/README.md#available-environment-variables).
|
||||
|
||||
#### Examples
|
||||
|
||||
@ -83,95 +174,40 @@ This is particularly useful for CI/CD pipelines using Docker containers.
|
||||
export ACTION="deploy"
|
||||
export PORTAINER_USER="admin"
|
||||
export PORTAINER_PASSWORD="password"
|
||||
export PORTAINER_URL="http://portainer.local"
|
||||
export PORTAINER_URL="https://portainer.local"
|
||||
export PORTAINER_STACK_NAME="mystack"
|
||||
export DOCKER_COMPOSE_FILE="/path/to/docker-compose.yml"
|
||||
export ENVIRONMENT_VARIABLES_FILE="/path/to/env_vars_file"
|
||||
|
||||
./psu
|
||||
bash ./psu
|
||||
```
|
||||
|
||||
```bash
|
||||
export ACTION="undeploy"
|
||||
export ACTION="rm"
|
||||
export PORTAINER_USER="admin"
|
||||
export PORTAINER_PASSWORD="password"
|
||||
export PORTAINER_URL="http://portainer.local"
|
||||
export PORTAINER_URL="https://portainer.local"
|
||||
export PORTAINER_STACK_NAME="mystack"
|
||||
|
||||
./psu
|
||||
bash ./psu
|
||||
```
|
||||
|
||||
### With flags
|
||||
|
||||
This is more suitable for standalone script usage.
|
||||
|
||||
- `-a` ("deploy" or "undeploy", required): Whether to deploy or undeploy the stack
|
||||
- `-u` (string, required): Username
|
||||
- `-p` (string, required): Password
|
||||
- `-l` (string, required): URL to Portainer
|
||||
- `-n` (string, required): Stack name
|
||||
- `-c` (string, required if action=deploy): Path to doker-compose file
|
||||
- `-g` (string, optional, only used when action=deploy or action=update): Path to file with environment variables to be used by the stack. See [stack environment variables](#stack-environment-variables) below.
|
||||
- `-r` ("true" or "false", optional): Whether to prune unused containers or not. Defaults to `"false"`.
|
||||
- `-e` (int, optional): Which endpoint to use. Defaults to `1`.
|
||||
- `-s` ("yes" or "no", optional): Whether to verify SSL certificate or not. Defaults to `"yes"`.
|
||||
- `-v` ("true" or "false", optional): Whether to activate verbose output mode or not. Defaults to `"false"`. See [verbose mode](#verbose-mode) below.
|
||||
- `-d` ("true" or "false", optional): Whether to activate debug output mode or not. Defaults to `"false"`. See [debug mode](#debug-mode) below.
|
||||
- `-t` ("true" or "false", optional): Whether to activate strict mode or not. Defaults to `"false"`. See [strict mode](#strict-mode) below.
|
||||
|
||||
#### Examples
|
||||
|
||||
**With Docker:**
|
||||
```bash
|
||||
./psu -a deploy -u admin -p password -l http://portainer.local -n mystack -c /path/to/docker-compose.yml -g /path/to/env_vars_file
|
||||
docker run -v $(pwd)/docker-compose.yml:/docker-compose.yml -v $(pwd)/.env:/.env -e ACTION="deploy" -e PORTAINER_USER="admin" -e PORTAINER_PASSWORD="password" -e PORTAINER_URL="https://portainer.local" -e PORTAINER_STACK_NAME="mystack" -e DOCKER_COMPOSE_FILE="docker-compose.yml" -e ENVIRONMENT_VARIABLES_FILE=".env" psuapp/psu
|
||||
```
|
||||
|
||||
```bash
|
||||
./psu -a undeploy -u admin -p password -l http://portainer.local -n mystack
|
||||
```
|
||||
## Documentation
|
||||
|
||||
### Stack environment variables
|
||||
<div class="docsify-hidden">
|
||||
For advanced usage, see the full <a href="https://psuapp.gitlab.io/psu/1-0-stable"><abbr title="Portainer Stack Utils">PSU</abbr> documentation</a>.
|
||||
</div>
|
||||
|
||||
There can be set environment variables for each stack, be it a new deployment or an update. For example:
|
||||
For detailed instructions, see the [CLI Commands](docs/README.md) documentation.
|
||||
|
||||
```bash
|
||||
touch .env
|
||||
echo "MYSQL_ROOT_PASSWORD=agoodpassword" >> .env
|
||||
echo "ALLOWED_HOSTS=*" >> .env
|
||||
./psu -a deploy -u admin -p password -l http://portainer.local -n django-stack -c /path/to/docker-compose.yml -g env_vars
|
||||
```
|
||||
## Supported Portainer API
|
||||
|
||||
Stack environment variables can be enabled through [ENVIRONMENT_VARIABLES_FILE envvar](#with-envvars) or [-g flag](#with-flags).
|
||||
|
||||
### Verbose mode
|
||||
|
||||
In verbose mode the script prints execution steps.
|
||||
|
||||
```text
|
||||
Getting auth token...
|
||||
Getting stack mystack...
|
||||
Stack mystack not found.
|
||||
Getting Docker info...
|
||||
Getting swarm cluster (if any)...
|
||||
Swarm cluster found.
|
||||
Preparing stack JSON...
|
||||
Creating stack mystack...
|
||||
```
|
||||
|
||||
Verbose mode can be enabled through [VERBOSE_MODE envvar](#with-envvars) or [-v flag](#with-flags).
|
||||
|
||||
### Debug mode
|
||||
|
||||
In debug mode the script prints as much information as possible to help diagnosing a malfunction.
|
||||
|
||||
**WARNING**: Debug mode will print configuration values (with Portainer credentials) and Portainer API responses (with sensitive information like authentication token and stacks environment variables). Avoid using debug mode in CI/CD pipelines, as pipeline logs are usually recorded.
|
||||
|
||||
Debug mode can be enabled through [DEBUG_MODE envvar](#with-envvars) or [-d flag](#with-flags).
|
||||
|
||||
### Strict mode
|
||||
|
||||
In strict mode the script never updates an existent stack nor removes an unexistent one, and instead exits with an error.
|
||||
|
||||
Strict mode can be enabled through [STRICT_MODE envvar](#with-envvars) or [-t flag](#with-flags).
|
||||
<abbr title="Portainer Stack Utils">PSU</abbr> was created for the latest versions of Portainer API, which at the time of writing are [1.19.2](https://app.swaggerhub.com/apis/deviantony/Portainer/1.19.2), [1.20.2](https://app.swaggerhub.com/apis/deviantony/Portainer/1.20.2) and [1.21.0](https://app.swaggerhub.com/apis/deviantony/Portainer/1.21.0).
|
||||
|
||||
## License
|
||||
|
||||
|
0
docs/.nojekyll
Normal file
0
docs/.nojekyll
Normal file
664
docs/README.md
Normal file
664
docs/README.md
Normal file
@ -0,0 +1,664 @@
|
||||
<h1>
|
||||
<div class="docsify-hidden">Portainer Stack Utils Docs</div>
|
||||
<abbr title="command-line interface">CLI</abbr> Commands
|
||||
</h1>
|
||||
<div class="docsify-hidden">
|
||||
|
||||
<h2>Table of contents</h2>
|
||||
<!-- Generated by https://github.com/mcpride/atom-mdtoc -->
|
||||
<!-- MDTOC maxdepth:2 firsth1:2 numbering:0 flatten:0 bullets:1 updateOnSave:1 -->
|
||||
|
||||
- [Available actions](#available-actions)
|
||||
- [Aliased actions](#aliased-actions)
|
||||
- [Available options](#available-options)
|
||||
- [Available environment variables](#available-environment-variables)
|
||||
- [Actions in details](#actions-in-details)
|
||||
- [`deploy`](#deploy)
|
||||
- [`rm`](#rm)
|
||||
- [`ls`](#ls)
|
||||
- [`status`](#status)
|
||||
- [`services`](#services)
|
||||
- [`tasks`](#tasks)
|
||||
- [`tasks:healthy`](#taskshealthy)
|
||||
- [`containers`](#containers)
|
||||
- [`login`](#login)
|
||||
- [`lint`](#lint)
|
||||
- [`inspect`](#inspect)
|
||||
- [`system:info`](#systeminfo)
|
||||
- [`actions`](#actions)
|
||||
- [`help`](#help)
|
||||
- [`version`](#version)
|
||||
- [Options in details](#options-in-details)
|
||||
- [Stack environment variables](#stack-environment-variables)
|
||||
- [Verbose mode](#verbose-mode)
|
||||
- [Debug mode](#debug-mode)
|
||||
- [Strict mode](#strict-mode)
|
||||
- [Quiet mode](#quiet-mode)
|
||||
|
||||
<!-- /MDTOC -->
|
||||
|
||||
</div>
|
||||
|
||||
## Available actions
|
||||
|
||||
| Name | Description |
|
||||
| --------------------------------- | ----------- |
|
||||
| [`deploy`](#deploy) | Deploy/update the given stack. |
|
||||
| [`rm`](#rm) | Remove/undeploy the given stack. |
|
||||
| [`ls`](#ls) | List stacks already deployed. |
|
||||
| [`status`](#status) | Check if the stack is running/deployed correctly. |
|
||||
| [`services`](#services) | List services already deployed in the current stack. |
|
||||
| [`tasks`](#tasks) | List tasks in the current stack. |
|
||||
| [`tasks:healthy`](#taskshealthy) | List tasks who are running correctly in the current stack. |
|
||||
| [`containers`](#containers) | List containers running in the current stack. |
|
||||
| [`login`](#login) | Log in to a Portainer instance. |
|
||||
| [`lint`](#lint) | Validate the Docker compose/stack file. |
|
||||
| [`inspect`](#inspect) | Display low-level information of the current stack. |
|
||||
| [`system:info`](#systeminfo) | Display Docker system-wide information. |
|
||||
| [`actions`](#actions) | List available actions for this program. |
|
||||
| [`help`](#help) | Display help message. |
|
||||
| [`version`](#version) | Display this program version. |
|
||||
|
||||
### Aliased actions
|
||||
|
||||
| Aliased action | Equivalent action |
|
||||
| ------------------ | ---------------------------------- |
|
||||
| `auth` | [`login`](#login) |
|
||||
| `docker:info` | [`system:info`](#systeminfo) |
|
||||
| `list` | [`ls`](#ls) |
|
||||
| `ps` | [`tasks`](#tasks) |
|
||||
| `ps:healthy` | [`tasks:healthy`](#taskshealthy) |
|
||||
| `remove` | [`rm`](#rm) |
|
||||
| `undeploy` | [`rm`](#rm) |
|
||||
| `update` | [`deploy`](#deploy) |
|
||||
| `validate` | [`lint`](#lint) |
|
||||
|
||||
## Available options
|
||||
|
||||
<!-- [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [lint](#lint), [inspect](#inspect), [system:info](#systeminfo), [actions](#actions), [help](#help), [version](#version) | -->
|
||||
|
||||
| Flag | Option | Description | Used in action(s) |
|
||||
| -----------| -------------------------------- | ----------- | ----------------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name | [deploy](#deploy), [rm](#rm), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [inspect](#inspect) |
|
||||
| `-c`, `-f` | `--compose-file=FILE_PATH` | Path to docker compose/stack file (required if action=deploy) | [deploy](#deploy), [lint](#lint) |
|
||||
| `-C`, `-F` | `--compose-file-base64=[BASE64]` | Content of docker compose/stack file, encoded in base64, useful with Docker in Docker (only used when action=deploy) | [deploy](#deploy), [lint](#lint) |
|
||||
| `-g` | `--env-file=[FILE_PATH]` | Path to a file of environment variables, to be used by the stack (only used when action=deploy) | [deploy](#deploy) |
|
||||
| `-G` | `--env-file-base64=[BASE64]` | Content of file with environment variables, encoded in base64, to be used by the stack, useful with Docker in Docker (only used when action=deploy) | [deploy](#deploy) |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `-r` | `--prune` | Whether to prune unused containers or not (only used when action=deploy). Defaults to `false` | [deploy](#deploy) |
|
||||
| `-T` | `--timeout=[SECONDS]` | Timeout, number of seconds before thrown an error (only used when action=status\|tasks\|tasks:healthy). Defaults to `100` | [status](#status), [tasks](#tasks), [tasks:healthy](#taskshealthy) |
|
||||
| `-j` | `--detect-job=[true\|false]` | Auto detect services who are jobs in the current stack. Defaults to `true` | [status](#status), [tasks](#tasks), [tasks:healthy](#taskshealthy) |
|
||||
| `-S` | `--service=[SERVICE_NAME]` | Filtering by a service name of the current stack (only used when action=status\|tasks\|tasks:healthy\|containers) | [status](#status), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers) |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [lint](#lint), [inspect](#inspect), [system:info](#systeminfo), [actions](#actions) |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [lint](#lint), [inspect](#inspect), [system:info](#systeminfo), [actions](#actions) |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `-q` | `--quiet` | Display the minimum of information or nothing, UNIX/Linux friendly. Defaults to `false` | [ls](#ls), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [inspect](#inspect) |
|
||||
| `-t` | `--strict` | Never updates an existent stack nor removes an inexistent one, and instead exits with an error. Defaults to `false` | [deploy](#deploy), [rm](#rm) |
|
||||
| `-L` | `--lint=[true\|false]` | Validate the Docker compose/stack file before deploying the stack (only used when action=deploy). Defaults to `true` | [deploy](#deploy) |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [lint](#lint), [inspect](#inspect), [system:info](#systeminfo), [actions](#actions), [version](#version) |
|
||||
| `-V` | `--version` | Display the version of this program | |
|
||||
| `-s` | `--secure=[yes\|no]` | **DEPRECATED**: Use the `--insecure` option instead. Enable or disable the host's SSL certificate verification. Defaults to `yes` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `-a` | `--action=[ACTION_NAME]` | **DEPRECATED**: Use `<action>` argument instead. The name of the action to execute | |
|
||||
|
||||
## Available environment variables
|
||||
|
||||
| Environment variable | Description | Used in action(s) |
|
||||
| ------------------------------------------- | -------------- | ----------------- |
|
||||
| `ACTION=ACTION_NAME` | The name of the action to execute | <abbr title="not applicable">n/a</abbr> |
|
||||
| `PORTAINER_URL=URL` | URL of the Portainer instance | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `PORTAINER_USER=USERNAME` | Username of the Portainer instance | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `PORTAINER_PASSWORD=PASSWORD` | Password of the Portainer instance | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `PORTAINER_AUTH_TOKEN=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `PORTAINER_STACK_NAME=STACK_NAME` | Stack name | [deploy](#deploy), [rm](#rm), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [inspect](#inspect) |
|
||||
| `DOCKER_COMPOSE_FILE=FILE_PATH` | Path to docker compose/stack file (required if action=deploy) | [deploy](#deploy), [lint](#lint) |
|
||||
| `ENVIRONMENT_VARIABLES_FILE=[FILE_PATH]` | Path to a file of environment variables, to be used by the stack (only used when action=deploy) | [deploy](#deploy) |
|
||||
| `PORTAINER_ENDPOINT=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `PORTAINER_PRUNE=[true\|false]` | Whether to prune unused containers or not (only used when action=deploy). Defaults to `false` | [deploy](#deploy) |
|
||||
| `TIMEOUT=[SECONDS]` | Timeout, number of seconds before thrown an error (only used when action=status\|tasks\|tasks:healthy). Defaults to `100` | [status](#status), [tasks](#tasks), [tasks:healthy](#taskshealthy) |
|
||||
| `AUTO_DETECT_JOB=[true\|false]` | Auto detect services who are jobs in the current stack. Defaults to `true` | [status](#status), [tasks](#tasks), [tasks:healthy](#taskshealthy) |
|
||||
| `PORTAINER_SERVICE_NAME=[SERVICE_NAME]` | Filtering by a service name of the current stack (only used when action=status\|tasks\|tasks:healthy\|containers) | [status](#status), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers) |
|
||||
| `HTTPIE_VERIFY_SSL=[yes\|no]` | Enable or disable the host's SSL certificate verification. Defaults to `yes` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `VERBOSE_MODE=[true\|false]` | Increase the verbosity of messages. Defaults to `false` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [lint](#lint), [inspect](#inspect), [system:info](#systeminfo), [actions](#actions) |
|
||||
| `DEBUG_MODE=[true\|false]` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [lint](#lint), [inspect](#inspect), [system:info](#systeminfo), [actions](#actions) |
|
||||
| `MASKED_VARIABLES=[true\|extended\|false]` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) |
|
||||
| `QUIET_MODE=[true\|false]` | Display the minimum of information or nothing, UNIX/Linux friendly. Defaults to `false` | [ls](#ls), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [inspect](#inspect) |
|
||||
| `STRICT_MODE=[true\|false]` | Never updates an existent stack nor removes an inexistent one, and instead exits with an error. Defaults to `false` | [deploy](#deploy), [rm](#rm) |
|
||||
| `DOCKER_COMPOSE_LINT=[true\|false]` | Validate the Docker compose/stack file before deploying the stack (only used when action=deploy). Defaults to `true` | [deploy](#deploy) |
|
||||
|
||||
<!-- | `PORTAINER_INSECURE=[true\|false]` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` | [deploy](#deploy), [rm](#rm), [ls](#ls), [status](#status), [services](#services), [tasks](#tasks), [tasks:healthy](#taskshealthy), [containers](#containers), [login](#login), [inspect](#inspect), [system:info](#systeminfo) | -->
|
||||
<!-- | `DOCKER_COMPOSE_BASE64=[BASE64]` | Content of docker compose/stack file, encoded in base64, useful with Docker in Docker (only used when action=deploy) | [deploy](#deploy), [lint](#lint) | -->
|
||||
<!-- | `ENVIRONMENT_VARIABLES_BASE64=[BASE64]` | Content of file with environment variables, encoded in base64, to be used by the stack, useful with Docker in Docker (only used when action=deploy) | [deploy](#deploy) | -->
|
||||
|
||||
## Actions in details
|
||||
|
||||
### `deploy`
|
||||
|
||||
Deploy/update the given stack.
|
||||
|
||||
#### Aliased action:
|
||||
`update`
|
||||
|
||||
#### Usage:
|
||||
`psu deploy [options]`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name |
|
||||
| `-c`, `-f` | `--compose-file=FILE_PATH` | Path to docker compose/stack file (required if action=deploy) |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-L` | `--lint=[true\|false]` | Validate the Docker compose/stack file before deploying the stack (only used when action=deploy). Defaults to `true` |
|
||||
| `-C`, `-F` | `--compose-file-base64=[BASE64]` | Content of docker compose/stack file, encoded in base64, useful with Docker in Docker (only used when action=deploy) |
|
||||
| `-g` | `--env-file=[FILE_PATH]` | Path to a file of environment variables, to be used by the stack (only used when action=deploy) |
|
||||
| `-G` | `--env-file-base64=[BASE64]` | Content of file with environment variables, encoded in base64, to be used by the stack, useful with Docker in Docker (only used when action=deploy) |
|
||||
| `-r` | `--prune` | Whether to prune unused containers or not (only used when action=deploy). Defaults to `false` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-t` | `--strict` | Never updates an existent stack nor removes an inexistent one, and instead exits with an error. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `rm`
|
||||
Remove/undeploy the given stack.
|
||||
|
||||
#### Aliased actions:
|
||||
`remove`, `undeploy`
|
||||
|
||||
#### Usage:
|
||||
`psu rm [options]`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-t` | `--strict` | Never updates an existent stack nor removes an inexistent one, and instead exits with an error. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `ls`
|
||||
List stacks already deployed.
|
||||
|
||||
#### Aliased actions:
|
||||
`list`
|
||||
|
||||
#### Usage:
|
||||
`psu ls [options]`
|
||||
|
||||
#### Examples:
|
||||
|
||||
```bash
|
||||
psu ls --user admin --password password --url https://portainer.local
|
||||
```
|
||||
|
||||
Output a JSON array of the stacks already deployed:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"Id": "mystack_jpofkc0i9uo9wtx1zesuk649w",
|
||||
"Name": "mystack",
|
||||
"Type": "1",
|
||||
"EndpointID": "1",
|
||||
"EntryPoint": "docker-compose.yml",
|
||||
"SwarmID": "jpofkc0i9uo9wtx1zesuk649w",
|
||||
"ProjectPath": "/data/compose/mystack_jpofkc0i9uo9wtx1zesuk649w",
|
||||
"Env": [
|
||||
{
|
||||
"name": "MYSQL_ROOT_PASSWORD",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "mysecondstack_i0649w9uo9wtx1zesujpofkck",
|
||||
"Name": "mysecondstack",
|
||||
"Type": "1",
|
||||
"EndpointID": "1",
|
||||
"EntryPoint": "docker-compose.yml",
|
||||
"SwarmID": "i0649w9uo9wtx1zesujpofkck",
|
||||
"ProjectPath": "/data/compose/mysecondstack_i0649w9uo9wtx1zesujpofkck"
|
||||
},
|
||||
{
|
||||
"Id": "mythirdstack_w9uo9wtxi064ujpofkck91zes",
|
||||
"Name": "mythirdstack",
|
||||
"Type": "1",
|
||||
"EndpointID": "1",
|
||||
"EntryPoint": "docker-compose.yml",
|
||||
"SwarmID": "mythirdstack_w9uo9wtxi064ujpofkck91zes",
|
||||
"ProjectPath": "/data/compose/mythirdstack_mythirdstack_w9uo9wtxi064ujpofkck91zes"
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
**With the `quiet` mode enabled**:
|
||||
```bash
|
||||
psu ls --user admin --password password --url https://portainer.local --quiet
|
||||
```
|
||||
|
||||
Output the name of the stacks already deployed:
|
||||
```bash
|
||||
mystack
|
||||
mysecondstack
|
||||
mythirdstack
|
||||
```
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-q` | `--quiet` | Display the minimum of information or nothing, UNIX/Linux friendly. Defaults to `false` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `status`
|
||||
Check if the stack is running/deployed correctly
|
||||
|
||||
#### Usage:
|
||||
`psu status [options]`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-S` | `--service=[SERVICE_NAME]` | Filtering by a service name of the current stack (only used when action=status\|tasks\|tasks:healthy\|containers) |
|
||||
| `-j` | `--detect-job=[true\|false]` | Auto detect services who are jobs in the current stack. Defaults to `true` |
|
||||
| `-T` | `--timeout=[SECONDS]` | Timeout, number of seconds before thrown an error (only used when action=status\|tasks\|tasks:healthy). Defaults to `100` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `services`
|
||||
List services already deployed in the current stack.
|
||||
|
||||
#### Usage:
|
||||
`psu services [options]`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-q` | `--quiet` | Display the minimum of information or nothing, UNIX/Linux friendly. Defaults to `false` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `tasks`
|
||||
List tasks in the current stack.
|
||||
|
||||
#### Usage:
|
||||
`psu tasks [options]`
|
||||
|
||||
#### Aliased action:
|
||||
`ps`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-S` | `--service=[SERVICE_NAME]` | Filtering by a service name of the current stack (only used when action=status\|tasks\|tasks:healthy\|containers) |
|
||||
| `-j` | `--detect-job=[true\|false]` | Auto detect services who are jobs in the current stack. Defaults to `true` |
|
||||
| `-T` | `--timeout=[SECONDS]` | Timeout, number of seconds before thrown an error (only used when action=status\|tasks\|tasks:healthy). Defaults to `100` |
|
||||
| `-q` | `--quiet` | Display the minimum of information or nothing, UNIX/Linux friendly. Defaults to `false` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `tasks:healthy`
|
||||
|
||||
List tasks who are running correctly in the current stack.
|
||||
|
||||
#### Usage:
|
||||
`psu tasks:healthy [options]`
|
||||
|
||||
#### Aliased action:
|
||||
`ps:healthy`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-S` | `--service=[SERVICE_NAME]` | Filtering by a service name of the current stack (only used when action=status\|tasks\|tasks:healthy\|containers) |
|
||||
| `-j` | `--detect-job=[true\|false]` | Auto detect services who are jobs in the current stack. Defaults to `true` |
|
||||
| `-T` | `--timeout=[SECONDS]` | Timeout, number of seconds before thrown an error (only used when action=status\|tasks\|tasks:healthy). Defaults to `100` |
|
||||
| `-q` | `--quiet` | Display the minimum of information or nothing, UNIX/Linux friendly. Defaults to `false` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `containers`
|
||||
List containers running in the current stack.
|
||||
|
||||
#### Usage:
|
||||
`psu containers [options]`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-S` | `--service=[SERVICE_NAME]` | Filtering by a service name of the current stack (only used when action=status\|tasks\|tasks:healthy\|containers) |
|
||||
| `-q` | `--quiet` | Display the minimum of information or nothing, UNIX/Linux friendly. Defaults to `false` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `login`
|
||||
Log in to a Portainer instance.
|
||||
|
||||
#### Usage:
|
||||
`psu login [options]`
|
||||
|
||||
|
||||
#### Aliased action:
|
||||
`auth`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `lint`
|
||||
Validate the Docker compose/stack file.
|
||||
|
||||
#### Usage:
|
||||
`psu lint [options]`
|
||||
|
||||
#### Aliased action:
|
||||
`validate`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-c`, `-f` | `--compose-file=FILE_PATH` | Path to docker compose/stack file (required if action=deploy) |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-C`, `-F` | `--compose-file-base64=[BASE64]` | Content of docker compose/stack file, encoded in base64, useful with Docker in Docker (only used when action=deploy) |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `inspect`
|
||||
Display low-level information of the current stack.
|
||||
|
||||
#### Usage:
|
||||
`psu inspect [options]`
|
||||
|
||||
#### Examples:
|
||||
```bash
|
||||
psu inspect --user admin --password password --url https://portainer.local --name mystack
|
||||
```
|
||||
|
||||
Output the JSON object of the stack if it's already deployed:
|
||||
```json
|
||||
{
|
||||
"Id": "mystack_jpofkc0i9uo9wtx1zesuk649w",
|
||||
"Name": "mystack",
|
||||
"Type": "1",
|
||||
"EndpointID": "1",
|
||||
"EntryPoint": "docker-compose.yml",
|
||||
"SwarmID": "jpofkc0i9uo9wtx1zesuk649w",
|
||||
"ProjectPath": "/data/compose/mystack_jpofkc0i9uo9wtx1zesuk649w",
|
||||
"Env": [
|
||||
{
|
||||
"name": "MYSQL_ROOT_PASSWORD",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**With the `quiet` mode enabled**:
|
||||
```bash
|
||||
psu inspect --user admin --password password --url https://portainer.local --name mystack --quiet
|
||||
```
|
||||
|
||||
Output the stack name if it's already deployed:
|
||||
```bash
|
||||
mystack
|
||||
```
|
||||
|
||||
**Check if the stack is already deployed**:
|
||||
```bash
|
||||
stack_exist=$(psu inspect --user admin --password password --url https://portainer.local --name mystack)
|
||||
|
||||
if [ -n "$stack_exist" ]; then
|
||||
echo OK
|
||||
else
|
||||
echo KO
|
||||
fi
|
||||
|
||||
## OR check the exit code of the last executed command:
|
||||
stack_exist=$(psu inspect --user admin --password password --url https://portainer.local --name mystack)
|
||||
|
||||
status=$?
|
||||
if $(exit $status); then
|
||||
echo OK
|
||||
else
|
||||
echo KO
|
||||
fi
|
||||
```
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
| `-n` | `--name=STACK_NAME` | Stack name |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-q` | `--quiet` | Display the minimum of information or nothing, UNIX/Linux friendly. Defaults to `false` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `system:info`
|
||||
Display Docker system-wide information.
|
||||
|
||||
#### Usage:
|
||||
`psu system:info [options]`
|
||||
|
||||
#### Aliased action:
|
||||
`docker:info`
|
||||
|
||||
#### Required options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-l` | `--url=URL` | URL of the Portainer instance |
|
||||
| `-u` | `--user=USERNAME` | Username of the Portainer instance |
|
||||
| `-p` | `--password=PASSWORD` | Password of the Portainer instance |
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-A` | `--auth-token=[AUTH_TOKEN]` | Use a Portainer auth token instead of `--user` and `--password` options, you can get it with the `psu login` command. Defaults to `null` |
|
||||
| `-e` | `--endpoint=[ENDPOINT_ID]` | Which Docker endpoint to use. Defaults to `1` |
|
||||
| `-i` | `--insecure` | Skip the host's SSL certificate verification, use at your own risk. Defaults to `false` |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-m` | `--masked-variables` | In debug/verbose mode, value of sensitive variables will be hidden, avoid leaking passwords/tokens in logs. Possible values: true\|extended\|false. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `actions`
|
||||
List available actions for this program.
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-v` | `--verbose` | Increase the verbosity of messages. Defaults to `false` |
|
||||
| `-d` | `--debug` | Print as much information as possible to help diagnosing a malfunction. Defaults to `false` |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
### `help`
|
||||
Display help message.
|
||||
|
||||
### `version`
|
||||
Display this program version.
|
||||
|
||||
#### Optional options:
|
||||
| Flag | Option | Description |
|
||||
| ---------- | -------------------------------- | ----------- |
|
||||
| `-h` | `--help` | Display help message. To display help of a given action, run: `psu <action> --help` |
|
||||
|
||||
## Options in details
|
||||
|
||||
### Stack environment variables
|
||||
|
||||
There can be set environment variables for each stack, be it a new deployment or an update. For example:
|
||||
|
||||
```bash
|
||||
touch .env
|
||||
echo "MYSQL_ROOT_PASSWORD=agoodpassword" >> .env
|
||||
echo "ALLOWED_HOSTS=*" >> .env
|
||||
psu deploy --user admin --password password --url https://portainer.local --name mystack --compose-file docker-compose.yml --env-file .env
|
||||
```
|
||||
|
||||
Stack environment variables can be enabled through `ENVIRONMENT_VARIABLES_FILE` envvar or `--env-file` option or `-g` flag.
|
||||
|
||||
### Verbose mode
|
||||
|
||||
In verbose mode the script prints execution steps.
|
||||
|
||||
```text
|
||||
Getting auth token...
|
||||
Getting stack mystack...
|
||||
Stack mystack not found.
|
||||
Getting Docker info...
|
||||
Getting swarm cluster (if any)...
|
||||
Swarm cluster found.
|
||||
Preparing stack JSON...
|
||||
Creating stack mystack...
|
||||
```
|
||||
|
||||
Verbose mode can be enabled through `VERBOSE_MODE` envvar or `--verbose` option or `-v` flag.
|
||||
|
||||
### Debug mode
|
||||
|
||||
In debug mode the script prints as much information as possible to help diagnosing a malfunction.
|
||||
|
||||
**WARNING**: Debug mode will print configuration values (with Portainer credentials) and Portainer API responses (with sensitive information like authentication token and stacks environment variables). Avoid using debug mode in CI/CD pipelines, as pipeline logs are usually recorded.
|
||||
|
||||
Debug mode can be enabled through `DEBUG_MODE` envvar or `--debug` option or `-d` flag.
|
||||
|
||||
### Strict mode
|
||||
|
||||
In strict mode the script never updates an existent stack nor removes an inexistent one, and instead exits with an error.
|
||||
|
||||
Strict mode can be enabled through `STRICT_MODE` envvar or `--strict` option or `-t` flag.
|
||||
|
||||
### Quiet mode
|
||||
|
||||
In quiet mode the script prints the minimum of informations or nothing.
|
||||
|
||||
It's inspired by the `--quiet` option of [`docker images`](https://docs.docker.com/engine/reference/commandline/images/#options) command.
|
||||
|
||||
Quiet mode can be enabled through `QUIET_MODE` envvar or `--quiet` option or `-q` flag.
|
6
docs/_coverpage.md
Normal file
6
docs/_coverpage.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Portainer Stack Utils Documentation
|
||||
|
||||
> Bash script to deploy/update/remove stacks in a [Portainer](https://portainer.io/) instance.
|
||||
|
||||
[GitLab](https://gitlab.com/psuapp/psu/ ":target=_blank View source on GitLab")
|
||||
<a href="#../README" title="Read documentation">Getting Started</a>
|
3
docs/_sidebar.md
Normal file
3
docs/_sidebar.md
Normal file
@ -0,0 +1,3 @@
|
||||
- [**Getting Started**](../README)
|
||||
- [**<abbr title="command-line interface">CLI</abbr> Commands**](docs/README)
|
||||
- [**Changelog**](CHANGELOG)
|
1
docs/assets/docsify.min.js
vendored
Normal file
1
docs/assets/docsify.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
docs/assets/docsify_plugins_search.min.js
vendored
Normal file
1
docs/assets/docsify_plugins_search.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
docs/assets/docsify_themes_vue.css
Normal file
1
docs/assets/docsify_themes_vue.css
Normal file
File diff suppressed because one or more lines are too long
1
docs/assets/prism-bash.min.js
vendored
Normal file
1
docs/assets/prism-bash.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e){var a={variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[\w#?*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)["']?(\w+?)["']?\s*\r?\n(?:[\s\S])*?\r?\n\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\1)[^\\])*\1/,greedy:!0,inside:a}],variable:a.variable,function:{pattern:/(^|[\s;|&])(?:add|alias|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|hash|head|help|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logout|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tail|tar|tee|test|time|timeout|times|top|touch|tr|traceroute|trap|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zip|zypper)(?=$|[\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&])(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|[\s;|&])/,lookbehind:!0},boolean:{pattern:/(^|[\s;|&])(?:true|false)(?=$|[\s;|&])/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<<?|>>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var t=a.variable[1].inside;t.string=e.languages.bash.string,t.function=e.languages.bash.function,t.keyword=e.languages.bash.keyword,t.boolean=e.languages.bash.boolean,t.operator=e.languages.bash.operator,t.punctuation=e.languages.bash.punctuation,e.languages.shell=e.languages.bash}(Prism);
|
1
docs/assets/prism-json.min.js
vendored
Normal file
1
docs/assets/prism-json.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
Prism.languages.json={comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,property:{pattern:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},number:/-?\d+\.?\d*(e[+-]?\d+)?/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}};
|
89
docs/index.html
Normal file
89
docs/index.html
Normal file
@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Portainer Stack Utils Documentation</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="description" content="Description">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<!-- <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css"> -->
|
||||
<link rel="stylesheet" href="assets/docsify_themes_vue.css">
|
||||
<style>
|
||||
.docsify-hidden {
|
||||
display: none;
|
||||
}
|
||||
/* source: https://gitlab-corners.bryce.io/ */
|
||||
.gitlab-corner-wrapper{overflow:hidden;width:100px;height:100px;position:fixed;top:0;right:0}.gitlab-corner{position:absolute;top:-16px;right:-50px;transform:rotate(45deg);background:#548;border:44px solid #548;border-bottom:none;border-top:#548 solid 16px}.gitlab-corner svg{width:60px;height:60px;margin-bottom:-4px}.cls-1{fill:#fc6d26}.cls-2{fill:#e24329}.cls-3{fill:#fca326}.gitlab-corner:hover .cls-1{animation:cycle .6s}.gitlab-corner:hover .cls-2{animation:cycleMid .6s}.gitlab-corner:hover .cls-3{animation:cycleEnd .6s}@keyframes cycle{100%,15%,60%{fill:#fc6d26}30%,75%{fill:#e24329}45%,90%{fill:#fca326}}@keyframes cycleMid{100%,15%,60%{fill:#e24329}30%,75%{fill:#fca326}45%,90%{fill:#fc6d26}}@keyframes cycleEnd{100%,15%,60%{fill:#fca326}30%,75%{fill:#fc6d26}45%,90%{fill:#e24329}}@media (max-width:500px){.gitlab-corner:hover .cls-1,.gitlab-corner:hover .cls-2,.gitlab-corner:hover .cls-3{animation:none}.gitlab-corner .cls-1{animation:cycle .6s}.gitlab-corner .cls-2{animation:cycleMid .6s}.gitlab-corner .cls-3{animation:cycleEnd .6s}}
|
||||
/* source: https://www.w3schools.com/howto/howto_js_scroll_to_top.asp */
|
||||
#top-btn{display:none;position:fixed;bottom:15px;right:20px;z-index:99;border:none;outline:none;background-color:#548;color:#fff;cursor:pointer;padding:10px;border-radius:5px;font-size:18px}#top-btn:hover{background-color:#555}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
name: '<abbr title="Portainer Stack Utils">PSU</abbr> Docs ',
|
||||
// repo: 'https://gitlab.com/psuapp/psu',
|
||||
coverpage: true,
|
||||
onlyCover: true,
|
||||
search: 'auto',
|
||||
maxLevel: 3,
|
||||
loadSidebar: true,
|
||||
subMaxLevel: 3,
|
||||
alias: {
|
||||
'/CHANGELOG': 'repo/CHANGELOG',
|
||||
'/../README': 'repo/README',
|
||||
'/docs/README': 'README',
|
||||
'/.*/_sidebar.md': '/_sidebar.md'
|
||||
},
|
||||
search : {
|
||||
paths: [
|
||||
'/docs/README', // => /README.md
|
||||
'/../README', // => /repo/README.md
|
||||
'/CHANGELOG', // => /repo/CHANGELOG.md
|
||||
],
|
||||
depth: 3
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<!-- <script src="//unpkg.com/docsify/lib/docsify.min.js"></script> -->
|
||||
<!-- <script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script> -->
|
||||
<!-- <script src="//unpkg.com/prismjs/components/prism-json.min.js"></script> -->
|
||||
<!-- <script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script> -->
|
||||
<script src="assets/docsify.min.js"></script>
|
||||
<script src="assets/prism-bash.min.js"></script>
|
||||
<script src="assets/prism-json.min.js"></script>
|
||||
<script src="assets/docsify_plugins_search.min.js"></script>
|
||||
<!-- source: https://www.w3schools.com/howto/howto_js_scroll_to_top.asp -->
|
||||
<script>
|
||||
(function () {
|
||||
// When the user scrolls down 100px from the top of the document, show the button
|
||||
var scrollFunction = function() {
|
||||
if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 100) {
|
||||
document.getElementById("top-btn").style.display = "block";
|
||||
} else {
|
||||
document.getElementById("top-btn").style.display = "none";
|
||||
}
|
||||
}
|
||||
// When the user clicks on the button, scroll to the top of the document
|
||||
window.topFunction = function () {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
window.addEventListener("scroll", function () {
|
||||
scrollFunction();
|
||||
}, false);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<button onclick="topFunction()" id="top-btn" title="Go top">↑</button>
|
||||
|
||||
<!-- source: https://gitlab-corners.bryce.io/ -->
|
||||
<div class="gitlab-corner-wrapper">
|
||||
<a href="https://gitlab.com/psuapp/psu" class="gitlab-corner" aria-label="View source on GitLab" title="View source on GitLab" target="_blank" rel="noopener">
|
||||
<svg id="logo_art" data-name="logo art" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 586 559">
|
||||
<g id="g44"><path id="path46" class="cls-1" d="M461.17,301.83l-18.91-58.12L404.84,128.43a6.47,6.47,0,0,0-12.27,0L355.15,243.64H230.82L193.4,128.43a6.46,6.46,0,0,0-12.26,0L143.78,243.64l-18.91,58.19a12.88,12.88,0,0,0,4.66,14.39L293,435,456.44,316.22a12.9,12.9,0,0,0,4.73-14.39"/></g><g id="g48"><path id="path50" class="cls-2" d="M293,434.91h0l62.16-191.28H230.87L293,434.91Z"/></g><g id="g56"><path id="path58" class="cls-1" d="M293,434.91,230.82,243.63h-87L293,434.91Z"/></g><g id="g64"><path id="path66" class="cls-3" d="M143.75,243.69h0l-18.91,58.12a12.88,12.88,0,0,0,4.66,14.39L293,435,143.75,243.69Z"/></g><g id="g72"><path id="path74" class="cls-2" d="M143.78,243.69h87.11L193.4,128.49a6.47,6.47,0,0,0-12.27,0l-37.35,115.2Z"/></g><g id="g76"><path id="path78" class="cls-1" d="M293,434.91l62.16-191.28H442.3L293,434.91Z"/></g><g id="g80"><path id="path82" class="cls-3" d="M442.24,243.69h0l18.91,58.12a12.85,12.85,0,0,1-4.66,14.39L293,434.91l149.2-191.22Z"/></g><g id="g84"><path id="path86" class="cls-2" d="M442.28,243.69h-87.1l37.42-115.2a6.46,6.46,0,0,1,12.26,0l37.42,115.2Z"/></g>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
134
scripts/helpers.sh
Normal file
134
scripts/helpers.sh
Normal file
@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
[[ "$TRACE" ]] && set -x
|
||||
|
||||
function registry_login() {
|
||||
if [[ -n "$CI_REGISTRY_USER" ]]; then
|
||||
echo "Logging to GitLab Container Registry with CI credentials..."
|
||||
docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
function external_registry_login() {
|
||||
if [[ -n "$DOCKER_USER" ]]; then
|
||||
echo "Logging to External Registry..."
|
||||
docker login -u "$DOCKER_USER" -p "$DOCKER_PASSWORD" "$DOCKER_REGISTRY"
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
function setup_docker() {
|
||||
if ! docker info &>/dev/null; then
|
||||
if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
|
||||
export DOCKER_HOST='tcp://localhost:2375'
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function git_tag_on_success() {
|
||||
local git_tag="${1:-dev}"
|
||||
local target_branch="${2:-master}"
|
||||
|
||||
if (
|
||||
[ "$CI_COMMIT_REF_NAME" == "$target_branch" ] &&
|
||||
[ -n "$GITLAB_API_TOKEN" ] &&
|
||||
[ -z "$GIT_RESET_TAG" ]
|
||||
); then
|
||||
# (re)write Protected Tag
|
||||
# TODO: rewrite these 'wget' commands with 'curl' commands
|
||||
wget -Y off -O response.txt --header='Accept-Charset: UTF-8' --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" --post-data '_method=delete' $CI_API_V4_URL/projects/$CI_PROJECT_ID/protected_tags/$git_tag || true
|
||||
wget -Y off -O response.txt --header='Accept-Charset: UTF-8' --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" --post-data '_method=delete' $CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/tags/$git_tag || true
|
||||
wget -Y off -O response.txt --header='Accept-Charset: UTF-8' --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" --post-data "tag_name=$git_tag&ref=$CI_COMMIT_SHA" $CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/tags
|
||||
wget -Y off -O response.txt --header='Accept-Charset: UTF-8' --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" --post-data "name=$git_tag&create_access_level=0" $CI_API_V4_URL/projects/$CI_PROJECT_ID/protected_tags
|
||||
else
|
||||
echo WARNING: \$GITLAB_API_TOKEN variable is missing
|
||||
fi
|
||||
}
|
||||
|
||||
function registry_tag_on_success() {
|
||||
local current_registry_tag="${1:-$CI_COMMIT_SHA}"
|
||||
local target_registry_tag="${2:-dev}"
|
||||
local target_branch="${3:-master}"
|
||||
local current_registry_image="${4:-$CI_REGISTRY_IMAGE/builds}"
|
||||
local target_registry_image="${5:-$CI_REGISTRY_IMAGE}"
|
||||
local target_external_registry_image="${6:-$DOCKER_REGISTRY_IMAGE}"
|
||||
|
||||
if [ "$CI_COMMIT_REF_NAME" == "$target_branch" ]; then
|
||||
docker pull "$current_registry_image:$current_registry_tag"
|
||||
docker tag "$current_registry_image:$current_registry_tag" "$target_registry_image:$target_registry_tag"
|
||||
docker push "$target_registry_image:$target_registry_tag"
|
||||
if [ -n "$target_external_registry_image" ]; then
|
||||
docker tag "$current_registry_image:$current_registry_tag" "$target_external_registry_image:$target_registry_tag"
|
||||
docker push "$target_external_registry_image:$target_registry_tag"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Reset the git repository to the target tag
|
||||
#
|
||||
# First argument pass to this function or the `GIT_RESET_TAG` CI variable
|
||||
# must be set
|
||||
# git_reset_from_tag dev
|
||||
# or:
|
||||
# GIT_RESET_TAG=dev
|
||||
# git_reset_from_tag
|
||||
function git_reset_from_tag() {
|
||||
local git_target_tag="${1:-$GIT_RESET_TAG}"
|
||||
|
||||
if (
|
||||
[ "$CI_PIPELINE_SOURCE" == "schedule" ] &&
|
||||
[ -n "$git_target_tag" ] && [ "$GIT_STRATEGY" != "none" ] &&
|
||||
[ -z "$CI_COMMIT_TAG" ]
|
||||
); then
|
||||
# Get specific tag
|
||||
git reset --hard $git_target_tag
|
||||
export CI_COMMIT_SHA=$(git rev-parse HEAD)
|
||||
export CI_COMMIT_SHORT_SHA=$(git rev-parse --short HEAD)
|
||||
else
|
||||
echo NOTICE: Not a Scheduling Pipeline, skip the git tag reset stuff... # debug
|
||||
fi
|
||||
}
|
||||
|
||||
# Get latest stable semantic versioning git tag
|
||||
# from a specific git branch
|
||||
#
|
||||
# First argument pass to this function or the `CI_COMMIT_REF_NAME` CI variable
|
||||
# must be set
|
||||
# get_git_last_stable_tag 1-0-stable
|
||||
# -> "v1.0.3"
|
||||
# or:
|
||||
# CI_COMMIT_REF_NAME=1-0-stable
|
||||
# get_git_last_stable_tag
|
||||
# -> "v1.0.3"
|
||||
#
|
||||
# see: https://semver.org
|
||||
function get_git_last_stable_tag() {
|
||||
local target_branch="${1:-$CI_COMMIT_REF_NAME}"
|
||||
|
||||
git fetch origin $target_branch
|
||||
git checkout -f -q $target_branch
|
||||
echo "$(git tag --merged $target_branch | grep -w '^v[0-9]\+\.[0-9]\+\.[0-9]\+$' | sort -r -V | head -n 1)"
|
||||
}
|
||||
|
||||
# Useful for updating Docker images, on release/stable branches, but not the psu code
|
||||
# See: https://docs.gitlab.com/ce/workflow/gitlab_flow.html#release-branches-with-gitlab-flow
|
||||
# You can create a scheduled pipeline with a targeted git branch ("master", "1-0-stable", ...)
|
||||
# and the CI variables below:
|
||||
# "GIT_RESET_LAST_STABLE_TAG=true"
|
||||
# "DOCKER_CACHE_DISABLED=true"
|
||||
# "TEST_DISABLED=" # no value to unset this variable
|
||||
# See: https://gitlab.com/help/user/project/pipelines/schedules
|
||||
function git_reset_from_last_stable_tag() {
|
||||
if [ "$GIT_RESET_LAST_STABLE_TAG" == "true" ]; then
|
||||
git_last_stable_tag="$(get_git_last_stable_tag)"
|
||||
if [ -n "$git_last_stable_tag" ]; then
|
||||
export CI_COMMIT_REF_PROTECTED="true"
|
||||
export CI_COMMIT_TAG="$git_last_stable_tag"
|
||||
export GIT_RESET_TAG="$git_last_stable_tag"
|
||||
git_reset_from_tag
|
||||
else
|
||||
echo WARNING: Last stable git tag not found
|
||||
fi
|
||||
fi
|
||||
}
|
63
scripts/push-to-gitlab-pages.sh
Normal file
63
scripts/push-to-gitlab-pages.sh
Normal file
@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Usage:
|
||||
# bash push-to-gitlab-pages.sh <target_branch_name> <path_to_push_in_the_branch>
|
||||
# bash push-to-gitlab-pages.sh
|
||||
# bash push-to-gitlab-pages.sh "gitlab-pages" "public"
|
||||
|
||||
set -e
|
||||
[[ "$TRACE" ]] && set -x
|
||||
|
||||
if [ -z "$GITLAB_WRITE_REPO_USER" ] || [ -z "$GITLAB_WRITE_REPO_TOKEN" ]; then
|
||||
echo "ERROR: \$GITLAB_WRITE_REPO_USER and/or \$GITLAB_WRITE_REPO_TOKEN CI variables must be set!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
current_path=$PWD
|
||||
project_path=$CI_PROJECT_DIR
|
||||
|
||||
# GitLab Pages branch name
|
||||
branch=${1:-gitlab-pages}
|
||||
# Path of the folder to push in GitLab Pages branch
|
||||
source_path=${2:-$project_path/public}
|
||||
|
||||
repository_path=$project_path/$branch
|
||||
# Path of the files to publish in GitLab Pages
|
||||
pages_path=$repository_path/public
|
||||
repository_url_path=$(echo $CI_PROJECT_URL | sed -E 's/^https?:\/\/(.+)$/\1/')
|
||||
repository_url_protocol=$(echo $CI_PROJECT_URL | sed -E 's/^(https?:\/\/).+$/\1/')
|
||||
repository_user=$GITLAB_WRITE_REPO_USER
|
||||
repository_password=$GITLAB_WRITE_REPO_TOKEN
|
||||
repository_url=${repository_url_protocol}${repository_user}:${repository_password}@${repository_url_path}
|
||||
last_commit_message=$(git log -1 -z --format="%s%n%ncommit %H%nAuthor: %an <%ae>%nDate: %ad" HEAD)
|
||||
|
||||
if ! $(git clone --quiet --branch=$branch --single-branch $repository_url $repository_path); then
|
||||
# Create $branch if needed
|
||||
git clone --quiet --depth=1 --single-branch $repository_url $repository_path
|
||||
cd $repository_path
|
||||
git config user.name "$repository_user"
|
||||
git config user.email "${repository_user}@users.noreply.gitlab.com"
|
||||
git checkout --orphan $branch
|
||||
git rm --quiet -rf .
|
||||
cp -pa $project_path/.gitlab-ci.yml .gitlab-ci.yml
|
||||
|
||||
echo "Git branch dedicated to [GitLab Pages](https://docs.gitlab.com/ce/user/project/pages/).
|
||||
|
||||
DO NOT EDIT THIS BRANCH BY HAND PLEASE" > README.md
|
||||
git add README.md .gitlab-ci.yml
|
||||
git commit -m "Git branch dedicated to GitLab Pages (https://docs.gitlab.com/ce/user/project/pages/)."
|
||||
fi
|
||||
|
||||
cd $current_path
|
||||
|
||||
if [ -d $source_path ]; then
|
||||
cp -Rpa $source_path/. $pages_path
|
||||
cd $repository_path
|
||||
git config user.name "$repository_user"
|
||||
git config user.email "${repository_user}@users.noreply.gitlab.com"
|
||||
# Update git '$branch' and push changes to the current repository
|
||||
git add --all
|
||||
git diff-index --quiet HEAD || git commit -m "$last_commit_message"
|
||||
git push --quiet origin $branch | true
|
||||
fi
|
||||
|
||||
cd $current_path
|
113
scripts/release.sh
Normal file
113
scripts/release.sh
Normal file
@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
[[ "$TRACE" ]] && set -x
|
||||
|
||||
source "$(dirname "$0")/helpers.sh"
|
||||
|
||||
# First argument is the variant(s) of the Docker image to be tagged
|
||||
# e.g. "core"
|
||||
# or "core debian debian-core" for multiple variants
|
||||
variant_input="$1"
|
||||
|
||||
# Split space (" ") character to new line "\n"
|
||||
variants="$(echo "$variant_input" | tr ' ' '\n')"
|
||||
|
||||
if [ "$GIT_RESET_LAST_STABLE_TAG" != "true" ]; then
|
||||
git_tag_on_success "dev"
|
||||
registry_tag_on_success $CI_COMMIT_SHA "dev"
|
||||
for variant in $variants; do
|
||||
registry_tag_on_success "${variant}-${CI_COMMIT_SHA}" "dev-${variant}"
|
||||
done
|
||||
fi
|
||||
|
||||
# Write current git tag to the Docker registry
|
||||
# if it starts with the 'v' character, followed by a number, e.g 'v1.0.2'
|
||||
# see: https://semver.org
|
||||
# You should set a 'v*' protected tags, in your GitLab project
|
||||
# see: https://gitlab.com/help/user/project/protected_tags#configuring-protected-tags
|
||||
if (
|
||||
[[ "$CI_COMMIT_TAG" =~ ^v[0-9][0-9a-z.\-]*$ ]] &&
|
||||
[ "$CI_COMMIT_REF_PROTECTED" == "true" ]
|
||||
); then
|
||||
# Remove the first letter ('v' character), for tagging Docker images
|
||||
target_registry_tag="${CI_COMMIT_TAG:1}"
|
||||
|
||||
registry_tag_on_success $CI_COMMIT_SHA $target_registry_tag $CI_COMMIT_REF_NAME
|
||||
for variant in $variants; do
|
||||
registry_tag_on_success "${variant}-${CI_COMMIT_SHA}" "${target_registry_tag}-${variant}" $CI_COMMIT_REF_NAME
|
||||
done
|
||||
|
||||
# If current git tag is a stable semantic version.
|
||||
# see: https://semver.org
|
||||
if [[ "$target_registry_tag" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
git fetch --all
|
||||
# e.g. " origin/master"
|
||||
master_branch="$(git branch --no-color --remotes --list 'origin/master')"
|
||||
|
||||
# e.g. " origin/1-0-stable
|
||||
# > origin/1-1-stable
|
||||
# > origin/2-0-stable
|
||||
# > origin/master"
|
||||
commit_in_branches="$(git branch --no-color --remotes --contains $CI_COMMIT_SHA | grep -w ' origin/master\| origin/.*-stable')"
|
||||
|
||||
# e.g. " origin/2-0-stable
|
||||
# > origin/1-1-stable
|
||||
# > origin/1-0-stable"
|
||||
stable_branches="$(echo "$commit_in_branches" | grep -vw ' origin/master' | sort -rV)"
|
||||
|
||||
# Extract the MAJOR and MAJOR.MINOR versions
|
||||
# Then tag and push them to Docker registry.
|
||||
# e.g. the "v1.3.7" git tag, will create/update "1" and "1.3" registry tags
|
||||
# For MAJOR tag on git stable branches, we use the latest stable branch
|
||||
# e.g. when there is 2 stable branches "1-0-stable" and "1-1-stable"
|
||||
# If there is a new minor git tag "v1.0.3", only on the "1-0-stable".
|
||||
# We don't have to update the registry tag "1".
|
||||
# Because only git tags on the "1-1-stable" git branch can do it.
|
||||
major_registry_tag=$(echo $target_registry_tag | sed -E 's/^([0-9]+)\.[0-9]+\.[0-9]+$/\1/')
|
||||
minor_registry_tag=$(echo $target_registry_tag | sed -E 's/^[0-9]+\.([0-9]+)\.[0-9]+$/\1/')
|
||||
major_minor_registry_tag=$major_registry_tag.$minor_registry_tag
|
||||
target_stable_branch="${major_registry_tag}-${minor_registry_tag}-stable"
|
||||
|
||||
# e.g. "1-1-stable"
|
||||
latest_major_branch="$(echo "$stable_branches"| grep -E "^ origin/$major_registry_tag-[0-9]+-stable$" | head -n 1 | sed -E 's/^ origin\/(.+)$/\1/')"
|
||||
|
||||
# If the git tag is only contained in master branch
|
||||
# or if it's contained in the latest stable branch who has the same MAJOR version
|
||||
# e.g. when there is 2 stable branches "1-0-stable" and "1-1-stable".
|
||||
# If git tag is "v1.0.1", the MAJOR registry tag "1" is NOT written.
|
||||
# Because the lastet stable branch is "1-1-stable".
|
||||
#
|
||||
# If git tag is "v1.1.3", the MAJOR registry tag "1" is written.
|
||||
# Because the lastet stable branch is "1-1-stable".
|
||||
if (
|
||||
([ -n "$master_branch" ] && [ "$master_branch" == "$commit_in_branches" ]) ||
|
||||
[ "$latest_major_branch" == "$target_stable_branch" ]
|
||||
); then
|
||||
registry_tag_on_success $CI_COMMIT_SHA $major_registry_tag $CI_COMMIT_REF_NAME
|
||||
fi
|
||||
|
||||
registry_tag_on_success $CI_COMMIT_SHA $major_minor_registry_tag $CI_COMMIT_REF_NAME
|
||||
for variant in $variants; do
|
||||
if (
|
||||
([ -n "$master_branch" ] && [ "$master_branch" == "$commit_in_branches" ]) ||
|
||||
[ "$latest_major_branch" == "$target_stable_branch" ]
|
||||
); then
|
||||
registry_tag_on_success "${variant}-${CI_COMMIT_SHA}" "${major_registry_tag}-${variant}" $CI_COMMIT_REF_NAME
|
||||
fi
|
||||
|
||||
registry_tag_on_success "${variant}-${CI_COMMIT_SHA}" "${major_minor_registry_tag}-${variant}" $CI_COMMIT_REF_NAME
|
||||
done
|
||||
|
||||
# The latest stable semantic versioning git tag on the "master" branch
|
||||
# is considered as the "latest" registry tag.
|
||||
# Check if the current git commit is only present in the "master" branch
|
||||
# and not in stable branches (e.g. "1-0-stable").
|
||||
# Non stable branches are skipped (e.g. "feature-better-performance").
|
||||
if [ -n "$master_branch" ] && [ "$master_branch" == "$commit_in_branches" ]; then
|
||||
registry_tag_on_success $CI_COMMIT_SHA "latest" $CI_COMMIT_REF_NAME
|
||||
for variant in $variants; do
|
||||
registry_tag_on_success "${variant}-${CI_COMMIT_SHA}" "${variant}" $CI_COMMIT_REF_NAME
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
5
scripts/test.sh
Normal file
5
scripts/test.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
[[ "$TRACE" ]] && set -x
|
||||
|
||||
bash "$(dirname "$0")/../tests/run.sh"
|
43
tests/dockerfiles/docker-stack-portainer.yml
Normal file
43
tests/dockerfiles/docker-stack-portainer.yml
Normal file
@ -0,0 +1,43 @@
|
||||
version: '3.6'
|
||||
|
||||
services:
|
||||
portainer:
|
||||
image: portainer/portainer:$PORTAINER_VERSION
|
||||
command: --admin-password-file '/run/secrets/portainer-password'
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.frontend.rule=Host:portainer.$BASE_DOMAIN
|
||||
- traefik.frontend.redirect.entryPoint=https
|
||||
- traefik.backend=portainer
|
||||
- traefik.port=9000
|
||||
networks:
|
||||
- traefik-net
|
||||
environment:
|
||||
- HTTP_PROXY
|
||||
- HTTPS_PROXY
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- NO_PROXY
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- portainer:/data
|
||||
secrets:
|
||||
- portainer-password
|
||||
deploy:
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
update_config:
|
||||
parallelism: 1
|
||||
delay: 10s
|
||||
|
||||
networks:
|
||||
traefik-net:
|
||||
driver: overlay
|
||||
external: true
|
||||
|
||||
secrets:
|
||||
portainer-password:
|
||||
external: true
|
||||
volumes:
|
||||
portainer:
|
45
tests/dockerfiles/docker-stack-traefik.yml
Normal file
45
tests/dockerfiles/docker-stack-traefik.yml
Normal file
@ -0,0 +1,45 @@
|
||||
version: '3.6'
|
||||
|
||||
services:
|
||||
reverse-proxy:
|
||||
image: traefik:$TRAEFIK_VERSION
|
||||
# Enables the web UI and tells Traefik to listen to docker
|
||||
command:
|
||||
- --api
|
||||
- --docker
|
||||
- --docker.watch
|
||||
- --defaultEntryPoints=http,https
|
||||
# IMPORTANT: The `retry.attempts` param is required to allow zero (1s) downtime deployment
|
||||
- --retry.attempts=10
|
||||
- "--entryPoints=Name:http Address::80"
|
||||
- "--entryPoints=Name:https Address::443 TLS WhiteList.UseXForwardedFor:true"
|
||||
- --docker.exposedbydefault=false
|
||||
environment:
|
||||
- HTTP_PROXY
|
||||
- HTTPS_PROXY
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- NO_PROXY
|
||||
ports:
|
||||
- "80:80"
|
||||
- 443:443
|
||||
# The Web UI (enabled by --api)
|
||||
- "8080:8080"
|
||||
networks:
|
||||
- traefik-net
|
||||
volumes:
|
||||
# So that Traefik can listen to the Docker events
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
deploy:
|
||||
mode: global
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
update_config:
|
||||
parallelism: 1
|
||||
delay: 10s
|
||||
|
||||
networks:
|
||||
traefik-net:
|
||||
driver: overlay
|
||||
name: traefik-net
|
65
tests/dockerfiles/docker-stack-web-app.yml
Normal file
65
tests/dockerfiles/docker-stack-web-app.yml
Normal file
@ -0,0 +1,65 @@
|
||||
version: '3.6'
|
||||
|
||||
services:
|
||||
job:
|
||||
image: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/hub/testing/psu-php-app:latest
|
||||
labels:
|
||||
job-name: job-web-app
|
||||
entrypoint: ["php"]
|
||||
command: -r 'echo date("d-m-Y H:i:s").PHP_EOL;'
|
||||
# command: -r 'sleep(20); echo date("d-m-Y H:i:s").PHP_EOL;'
|
||||
environment:
|
||||
- HTTP_PROXY
|
||||
- HTTPS_PROXY
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- NO_PROXY
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: none
|
||||
|
||||
app:
|
||||
image: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/hub/testing/psu-php-app:latest
|
||||
environment:
|
||||
- HTTP_PROXY
|
||||
- HTTPS_PROXY
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- NO_PROXY
|
||||
volumes:
|
||||
- php-runner:/var/run/php
|
||||
deploy:
|
||||
update_config:
|
||||
order: start-first
|
||||
failure_action: continue
|
||||
|
||||
web:
|
||||
image: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/hub/testing/psu-apache2:latest
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- "traefik.frontend.rule=Host:$PSU_STACK_NAME.$BASE_DOMAIN"
|
||||
- traefik.frontend.redirect.entryPoint=https
|
||||
- traefik.backend=web-php-app
|
||||
- traefik.port=5000
|
||||
environment:
|
||||
- HTTP_PROXY
|
||||
- HTTPS_PROXY
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- NO_PROXY
|
||||
volumes:
|
||||
- php-runner:/var/run/php
|
||||
stop_signal: SIGWINCH
|
||||
deploy:
|
||||
update_config:
|
||||
failure_action: rollback
|
||||
order: start-first
|
||||
networks:
|
||||
- traefik-net
|
||||
|
||||
networks:
|
||||
traefik-net:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
php-runner:
|
3
tests/dockerfiles/web-app.env
Normal file
3
tests/dockerfiles/web-app.env
Normal file
@ -0,0 +1,3 @@
|
||||
FOO=bar
|
||||
DB_MIGRATE="php artisan migrate --force"
|
||||
ENVS="( ONE TWO=two THREE=\"php artisan\" )"
|
8
tests/gitlab-registry.json
Normal file
8
tests/gitlab-registry.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Name": "gitlab-registry",
|
||||
"Type": 1,
|
||||
"URL": "registry.gitlab.com",
|
||||
"Authentication": true,
|
||||
"Username": "$CI_REGISTRY_USER",
|
||||
"Password": "$CI_REGISTRY_PASSWORD"
|
||||
}
|
140
tests/run.sh
Normal file
140
tests/run.sh
Normal file
@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
[[ "$TRACE" ]] && set -x
|
||||
|
||||
CLUSTER_IP=$(getent hosts cluster | awk '{ print $1 }')
|
||||
export BASE_DOMAIN="$CLUSTER_IP.nip.io"
|
||||
export PSU_STACK_NAME="web-app"
|
||||
PSU_URL="https://portainer.$BASE_DOMAIN"
|
||||
PSU_USER="admin"
|
||||
PSU_PASSWORD="mypassword"
|
||||
|
||||
# Change working directory to 'tests/'
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
function psu_wrapper() {
|
||||
docker run --rm $PSU_IMAGE:${PSU_TAG:-$CI_COMMIT_SHA} "$@"
|
||||
}
|
||||
|
||||
function psu_core_wrapper() {
|
||||
docker run --rm $PSU_IMAGE:${PSU_TAG_CORE:-core-$CI_COMMIT_SHA} "$@"
|
||||
}
|
||||
|
||||
function application_exists() {
|
||||
local stack_name="$1"
|
||||
local stack_info
|
||||
|
||||
stack_info=$(psu_wrapper inspect \
|
||||
--auth-token="$PSU_AUTH_TOKEN" \
|
||||
--url="$PSU_URL" \
|
||||
--name="$stack_name" \
|
||||
--insecure \
|
||||
--debug="false" \
|
||||
--verbose="false") || true
|
||||
|
||||
if [ -n "$stack_info" ]; then
|
||||
echo "true"
|
||||
else
|
||||
echo "false"
|
||||
fi
|
||||
}
|
||||
|
||||
# Init Docker Swarm
|
||||
docker swarm init
|
||||
|
||||
# Deploy Traefik test
|
||||
# Parse the Docker traefik stack file to deploy
|
||||
envsubst '$TRAEFIK_VERSION' < dockerfiles/docker-stack-traefik.yml > dockerfiles/docker-stack-traefik-final.yml
|
||||
docker stack deploy -c dockerfiles/docker-stack-traefik-final.yml traefik --with-registry-auth
|
||||
bash -c "timeout 20 bash -c 'while ! (echo > /dev/tcp/cluster/443 && curl -fs --max-time 2 http://cluster:8080/dashboard/) >/dev/null 2>&1; do sleep 1; done;'"
|
||||
|
||||
# Deploy Portainer test
|
||||
echo -n $PSU_PASSWORD | docker secret create portainer-password -
|
||||
# Parse the Docker portainer stack file to deploy
|
||||
envsubst '$PORTAINER_VERSION,$BASE_DOMAIN' < dockerfiles/docker-stack-portainer.yml > dockerfiles/docker-stack-portainer-final.yml
|
||||
docker stack deploy -c dockerfiles/docker-stack-portainer-final.yml portainer --with-registry-auth
|
||||
bash -c "timeout 20 bash -c 'while ! (curl -fkLs --max-time 2 $PSU_URL) >/dev/null 2>&1; do sleep 1; done;'"
|
||||
|
||||
# psu version test
|
||||
psu_wrapper --version | grep -E 'version v?[0-9]+\.[0-9]+\.[0-9]+'
|
||||
|
||||
# psu help test
|
||||
# Check if 4 terms present in the help message are visible when running the command
|
||||
[ "$(psu_wrapper --help | grep -E 'Usage|Arguments|Options|Available actions' | wc -l)" == "4" ]
|
||||
|
||||
# TODO: test 'actions' action
|
||||
# TODO: test 'services' action
|
||||
# TODO: test 'containers' action
|
||||
|
||||
# Portainer login test
|
||||
PSU_AUTH_TOKEN=$(psu_wrapper login --user $PSU_USER --password $PSU_PASSWORD --url $PSU_URL --insecure)
|
||||
|
||||
# Add GitLab Docker registry access to Portainer
|
||||
envsubst '$CI_REGISTRY_USER,$CI_REGISTRY_PASSWORD' < gitlab-registry.json > gitlab-registry-final.json
|
||||
http --check-status --ignore-stdin --verify=no --timeout=10 POST "$PSU_URL/api/registries" "Authorization: Bearer $PSU_AUTH_TOKEN" @gitlab-registry-final.json
|
||||
# Add local endpoint to the Portainer instance
|
||||
http --check-status --ignore-stdin --verify=no --timeout=10 POST "$PSU_URL/api/endpoints" "Authorization: Bearer $PSU_AUTH_TOKEN" Name==local EndpointType==1
|
||||
|
||||
# Docker system info from Portainer test
|
||||
docker_info=$(psu_wrapper system:info --user $PSU_USER --password $PSU_PASSWORD --url $PSU_URL --insecure --debug false --verbose false)
|
||||
[ "$(echo "$docker_info" | jq -j ".DockerRootDir")" == "/var/lib/docker" ]
|
||||
|
||||
# Parse the Docker compose/stack file to deploy
|
||||
envsubst '$CI_REGISTRY,$CI_PROJECT_NAMESPACE,$BASE_DOMAIN,$PSU_STACK_NAME' < dockerfiles/docker-stack-web-app.yml > dockerfiles/docker-stack-web-app-final.yml
|
||||
|
||||
# Convert docker compose/stack file in a base64 encoded string,
|
||||
# due to some limitations with Docker in Docker and volumes
|
||||
# see: https://stackoverflow.com/a/55481515
|
||||
docker_compose_base64="$(cat dockerfiles/docker-stack-web-app-final.yml | base64)"
|
||||
|
||||
# Lint the Docker compose/stack file to be deployed
|
||||
lint_result=$(psu_wrapper lint --compose-file-base64 "$docker_compose_base64" --debug false --verbose false)
|
||||
[ "$lint_result" == "[OK]" ]
|
||||
|
||||
# Stack deploy test
|
||||
# Check the 'web-app' stack isn't deployed yet
|
||||
[ "$(application_exists $PSU_STACK_NAME)" == "false" ]
|
||||
# Deploy the 'web-app' stack
|
||||
psu_core_wrapper deploy --user $PSU_USER --password $PSU_PASSWORD --url $PSU_URL --name $PSU_STACK_NAME --compose-file-base64 "$docker_compose_base64" --insecure $PORTAINER_DEPLOY_EXTRA_ARGS
|
||||
[ "$(application_exists $PSU_STACK_NAME)" == "true" ]
|
||||
# Ensure the deployed stack is running correctly
|
||||
psu_wrapper status --user=$PSU_USER --password=$PSU_PASSWORD --url=$PSU_URL --name=$PSU_STACK_NAME --insecure --timeout=30 $PORTAINER_DEPLOY_EXTRA_ARGS
|
||||
now=$(date -u +"%Y-%m-%d")
|
||||
curl -fks --max-time 6 https://$PSU_STACK_NAME.$BASE_DOMAIN | grep -w "OK<br>$now"
|
||||
# Ensure the deployed stack has no environment variables
|
||||
stack_info=$(psu_wrapper inspect --user=$PSU_USER --password=$PSU_PASSWORD --url=$PSU_URL --name=$PSU_STACK_NAME --debug=false --verbose=false --insecure)
|
||||
stack_envvars="$(echo -n "$stack_info" | jq ".Env" -jc)"
|
||||
[ "$stack_envvars" == "[]" ]
|
||||
|
||||
# List deployed stacks with quiet mode test
|
||||
stack_list="$(psu_wrapper ls --user $PSU_USER --password $PSU_PASSWORD --url $PSU_URL --insecure --debug false --verbose false --quiet)"
|
||||
[ "$stack_list" == "$PSU_STACK_NAME" ]
|
||||
|
||||
# Convert env file in a base64 encoded string,
|
||||
# due to some limitations with Docker in Docker and volumes
|
||||
# see: https://stackoverflow.com/a/55481515
|
||||
env_file_base64="$(cat dockerfiles/web-app.env | base64)"
|
||||
|
||||
# Stack update test
|
||||
psu_wrapper deploy --user $PSU_USER --password $PSU_PASSWORD --url $PSU_URL --name $PSU_STACK_NAME --compose-file-base64 "$docker_compose_base64" --env-file-base64 "$env_file_base64" --insecure $PORTAINER_DEPLOY_EXTRA_ARGS
|
||||
# Check the 'web-app' stack is already deployed
|
||||
[ "$(application_exists $PSU_STACK_NAME)" == "true" ]
|
||||
# Ensure the updated stack is running correctly
|
||||
psu_wrapper status --user=$PSU_USER --password=$PSU_PASSWORD --url=$PSU_URL --name=$PSU_STACK_NAME --insecure --timeout=30 $PORTAINER_DEPLOY_EXTRA_ARGS
|
||||
now=$(date -u +"%Y-%m-%d")
|
||||
curl -fks --max-time 6 https://$PSU_STACK_NAME.$BASE_DOMAIN | grep -w "OK<br>$now"
|
||||
# Ensure the updated stack has environment variables corresponding to the env file
|
||||
stack_info=$(psu_wrapper inspect --user=$PSU_USER --password=$PSU_PASSWORD --url=$PSU_URL --name=$PSU_STACK_NAME --debug=false --verbose=false --insecure)
|
||||
stack_envvars="$(echo -n "$stack_info" | jq ".Env" -jc)"
|
||||
[ "$stack_envvars" != "[]" ]
|
||||
env_foo_from_stack="$(echo -n "$stack_envvars" | jq ".[] | select(.name == \"FOO\") | .value" -r)"
|
||||
(. dockerfiles/web-app.env && [ "$FOO" == "$env_foo_from_stack" ])
|
||||
env_db_migrate_from_stack="$(echo -n "$stack_envvars" | jq ".[] | select(.name == \"DB_MIGRATE\") | .value" -r)"
|
||||
(. dockerfiles/web-app.env && [ "$DB_MIGRATE" == "$env_db_migrate_from_stack" ])
|
||||
|
||||
# Stack remove/undeploy test
|
||||
psu_wrapper rm --user $PSU_USER --password $PSU_PASSWORD --url $PSU_URL --name $PSU_STACK_NAME --insecure $PORTAINER_DEPLOY_EXTRA_ARGS
|
||||
[ "$(application_exists $PSU_STACK_NAME)" == "false" ]
|
||||
# Ensure the reverse proxy Traefik free the URL of the removed stack
|
||||
bash -c "timeout 20 bash -c 'while ! (curl -ks --max-time 2 https://$PSU_STACK_NAME.$BASE_DOMAIN | grep -w \"404 page not found\") >/dev/null 2>&1; do sleep 1; done;'"
|
||||
curl -ks --max-time 6 https://$PSU_STACK_NAME.$BASE_DOMAIN
|
Loading…
Reference in New Issue
Block a user