Breaking Change: HTTPie is replaced by cURL

For smaller Docker images, faster execution and to be more portable
Running concurrently 'psu' commands should work now, by creating unique
temporary file names
This commit is contained in:
Tortue Torche 2021-09-14 13:41:15 +02:00
parent f9530c46fa
commit 54b0f3854a
8 changed files with 198 additions and 123 deletions

View File

@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Changed
- **Breaking Change**: [HTTPie](https://httpie.io/) is replaced by [cURL](https://curl.se), for smaller Docker images, faster execution and to be more portable
### Fixed
- Running concurrently `psu` commands should work now, by creating unique temporary file names
## [1.2.0] - 2021-09-14
### Added
- Add tests for `actions`, `containers` and `services` actions
@ -151,7 +157,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Debug mode
- Strict mode
[Unreleased]: https://gitlab.com/psuapp/psu/compare/v1.2.0...1-2-stable
[Unreleased]: https://gitlab.com/psuapp/psu/compare/v1.2.0...1-3-next
[1.2.0]: https://gitlab.com/psuapp/psu/-/tags/v1.2.0
[1.2.0-beta.1]: https://gitlab.com/psuapp/psu/-/tags/v1.2.0-beta.1
[1.2.0-alpha]: https://gitlab.com/psuapp/psu/-/tags/v1.2.0-alpha

View File

@ -2,7 +2,7 @@ FROM alpine:3.14
RUN set -e; \
apk add --no-cache \
bash ca-certificates docker-compose gettext httpie jq; \
bash ca-certificates curl docker-compose gettext jq; \
rm -rf $(find / -regex '.*\.py[co]')
ENV LANG="en_US.UTF-8" \

View File

@ -2,8 +2,7 @@ FROM alpine:3.14
RUN set -e; \
apk add --no-cache \
bash ca-certificates gettext httpie jq py3-setuptools; \
rm -rf $(find / -regex '.*\.py[co]')
bash ca-certificates curl gettext jq
ENV LANG="en_US.UTF-8" \
LC_ALL="C.UTF-8" \

View File

@ -5,12 +5,11 @@ ARG DOCKER_COMPOSE_VERSION=1.29.2
RUN set -e; \
apt-get update -yqq; \
apt-get install \
ca-certificates gettext-base httpie jq curl -yqq; \
ca-certificates curl gettext-base jq -yqq; \
\
curl -fL "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose; \
curl --fail --silent --location "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/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/*; \
rm -rf $(find / -regex '.*\.py[co]')

View File

@ -3,11 +3,10 @@ FROM debian:11-slim
RUN set -e; \
apt-get update -yqq; \
apt-get install \
ca-certificates gettext-base httpie jq -yqq; \
ca-certificates curl gettext-base jq -yqq; \
\
apt-get clean; \
rm -rf /var/lib/apt/lists/*; \
rm -rf $(find / -regex '.*\.py[co]')
rm -rf /var/lib/apt/lists/*
ENV LANG="en_US.UTF-8" \
LC_ALL="C.UTF-8" \

View File

@ -49,12 +49,15 @@ For detailed instructions, see [How to use](#how-to-use) section.
You will need these dependencies installed:
- [bash](https://www.gnu.org/software/bash/)
- [httpie](https://httpie.org/)
- [jq](https://stedolan.github.io/jq/)
- [timeout](https://man7.org/linux/man-pages/man1/timeout.1.html) <small>For macOS run: `brew install coreutils`</small>
- [bash](https://www.gnu.org/software/bash/)<sup title="required">*</sup> <small>(>= 5.0.3)</small>
- [curl](https://curl.se/)<sup title="required">*</sup> <small>(>= 7.64.0, but >= 7.76.0 is recommended)</small>
- [jq](https://stedolan.github.io/jq/)<sup title="required">*</sup> <small>(>= 1.5.1)</small>
- [timeout](https://man7.org/linux/man-pages/man1/timeout.1.html)<sup title="required">*</sup> <small>For macOS run: `brew install coreutils`</small>
- [uuidgen](https://man7.org/linux/man-pages/man1/uuidgen.1.html) only for some <abbr title="Operating System">OS</abbr> <small>(Debian and Alpine work fine without it)</small>
For Debian and similar apt-powered systems: `apt install bash httpie jq`
<sup>*</sup> = required
For Debian and similar apt-powered systems: `apt install bash curl jq`
### Docker image and variants

264
psu
View File

@ -115,12 +115,10 @@ main() {
# Get list of all stacks
echo_verbose "Getting stack $PORTAINER_STACK_NAME..."
STACKS=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
"$PORTAINER_URL/api/stacks" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN")
STACKS=$(curl_wrapper \
--request GET \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
"${PORTAINER_URL}/api/stacks")
check_for_errors $? "$STACKS"
echo_debug_safe_json "Get stacks response -> $(echo $STACKS | jq -C .)" "$STACKS"
@ -187,8 +185,7 @@ main() {
# or desired state == 'shutdown' and state == 'complete'
# Tasks should not have one of these states:
# 'failed', 'orphaned', 'remove'
timeout $TIMEOUT bash -c "until (export PORTAINER_SERVICE_NAME=$PORTAINER_SERVICE_NAME && export DEBUG_MODE=false && export VERBOSE_MODE=false && psu -a tasks:healthy -q) >/dev/null 2>&1; do echo -n \$(if [ \"\$VERBOSE_MODE\" == \"true\" ]; then echo -n .; fi) && sleep 1; done;"
timeout "$TIMEOUT" bash -c "until (export PORTAINER_SERVICE_NAME=$PORTAINER_SERVICE_NAME && psu --action=tasks:healthy --quiet --debug=false --verbose=false) >/dev/null 2>&1; do echo -n \$(if [ \"\$VERBOSE_MODE\" == \"true\" ]; then echo -n .; fi) && sleep 1; done;"
status=$?
if $(exit $status); then
@ -460,8 +457,10 @@ inputs() {
-C=*|-F=*|--compose-file-base64=*|--file-base64=*|-C|-F|--compose-file-base64|--file-base64)
local docker_compose_file_base64
docker_compose_file_base64=$(input_option "$1" "$2")
echo "$docker_compose_file_base64" | base64 -d > docker_compose_file_from_base64.yml
DOCKER_COMPOSE_FILE=docker_compose_file_from_base64.yml
local docker_compose_file_from_base64_path
docker_compose_file_from_base64_path="$(unique_temp_file_path)"
echo "$docker_compose_file_base64" | base64 -d > "$docker_compose_file_from_base64_path"
DOCKER_COMPOSE_FILE="$docker_compose_file_from_base64_path"
if [ -n "$2" ] && [[ ! $2 =~ ^-.+$ ]] ; then
# When the second argument is the value of the current option
shift
@ -484,8 +483,10 @@ inputs() {
-G=*|--env-file-base64=*|-G|--env-file-base64)
local env_file_base64
env_file_base64=$(input_option "$1" "$2")
echo "$env_file_base64" | base64 -d > env_file_from_base64
ENVIRONMENT_VARIABLES_FILE=env_file_from_base64
local env_file_from_base64_path
env_file_from_base64_path="$(unique_temp_file_path)"
echo "$env_file_base64" | base64 -d > "$env_file_from_base64_path"
ENVIRONMENT_VARIABLES_FILE="$env_file_from_base64_path"
if [ -n "$2" ] && [[ ! $2 =~ ^-.+$ ]] ; then
# When the second argument is the value of the current option
shift
@ -741,6 +742,7 @@ echo_error() {
local error_message="$@"
local red='\033[0;31m'
local nc='\033[0m'
echo -e "${red}[$(date +'%Y-%m-%dT%H:%M:%S%z')]: ${error_message}${nc}" >&2
}
@ -785,18 +787,15 @@ check_for_errors() {
local response=$2
if [ $exit_code -ne 0 ]; then
case $exit_code in
2) echo_error 'Request timed out!' ;;
3) echo_error 'Unexpected HTTP 3xx Redirection!' ;;
4)
echo_error 'HTTP 4xx Client Error!'
echo_error $response
22)
echo_error 'HTTP 4xx or 5xx Client Error!'
echo_error "$response"
;;
28) echo_error 'Request timed out!' ;;
47) echo_error 'Exceeded --max-redirs <n> redirects!' ;;
*)
echo_error 'Unholy Error!'
;;
5)
echo_error 'HTTP 5xx Server Error!'
echo_error $response
;;
6) echo_error 'Exceeded --max-redirects=<n> redirects!' ;;
*) echo_error 'Unholy Error!' ;;
esac
exit 1
fi
@ -819,10 +818,10 @@ echo_safe_json() {
# If the $json variable has an '.Env' entry
# We parse its content to mask sensitive values
if [ "$MASKED_VARIABLES" == "extended" ] && [ -n "$(echo "$json" | jq -j 'if type == "array" then .[] else . end | .Env // ""')" ]; then
temp_file=".stack_envs-$(echo "$(date +%s%3N)")"
temp_file="$(unique_temp_file_path)"
(
echo "$json" | jq -r 'if type == "array" then .[] else . end | .Env | map(.name = .name + "=" + .value) | map (.name) | .[]' | sed "s/\"/\\\\\"/g" | sed "s/^\([^=]\{1,\}=\)\(.* .*\)$/\1\"\2\"/" > $temp_file && \
. $temp_file && rm -f $temp_file && \
echo "$json" | jq -r 'if type == "array" then .[] else . end | .Env | map(.name = .name + "=" + .value) | map (.name) | .[]' | sed "s/\"/\\\\\"/g" | sed "s/^\([^=]\{1,\}=\)\(.* .*\)$/\1\"\2\"/" > "$temp_file" && \
. "$temp_file" && rm -f "$temp_file" && \
if [ "$type" == "debug" ]; then \
echo_debug "$message"; \
elif [ "$type" == "verbose" ]; then \
@ -906,6 +905,75 @@ mask_variables() {
echo "$message"
}
unique_temp_file_path() {
local file_prefix="psu"
local fallback_temp_path
local temp_path
local temp_file_path
fallback_temp_path="$(if [ -w "/tmp" ]; then echo "/tmp"; else pwd; fi)"
temp_path="${TMPDIR:-${TMP:-${TEMP:-$fallback_temp_path}}}"
if [ -w "$temp_path" ]; then
local file_uuid
# Generate universally unique identifier (UUID)
file_uuid=$(if [ -x "$(command -v uuidgen)" ]; then uuidgen; else cat /proc/sys/kernel/random/uuid; fi)
if [ -z "$file_uuid" ]; then
echo_error "You must install the 'uuidgen' program, to generate universally unique identifier"
exit 1
fi
# Unique temp file path
temp_file_path="${temp_path}/${file_prefix}_${file_uuid}.tmp"
else
echo_error "'${temp_path}' path is NOT WRITABLE!"
exit 1
fi
echo "$temp_file_path"
}
curl_wrapper() {
local result
# Use --fail-with-body cURL option if available
# And use environment variable to cache result
CURL_HAS_FAIL_WITH_BODY="${CURL_HAS_FAIL_WITH_BODY:-$(curl --help all | grep -w '\-\-fail\-with\-body' || true)}"
export CURL_HAS_FAIL_WITH_BODY
# Otherwise fallback to a temp result file storing
# Borrowed from: https://stackoverflow.com/a/55434980
local result_response_file
if [ -z "$CURL_HAS_FAIL_WITH_BODY" ]; then
result_response_file="$(unique_temp_file_path)"
fi
local curl_fail_params
curl_fail_params=$(if [ -n "$CURL_HAS_FAIL_WITH_BODY" ]; then echo --fail-with-body; else echo --output "$result_response_file" --write-out %\{http_code\}; fi)
result="$(curl \
$curl_fail_params \
--header "Content-Type: application/json" \
--silent \
$(if [ "$HTTPIE_VERIFY_SSL" == "no" ]; then echo --insecure; else $(if [ -f "$HTTPIE_VERIFY_SSL" ]; then echo --cacert "$HTTPIE_VERIFY_SSL"; else echo ''; fi); fi) \
"$@")"
result_exit_code="$?"
if [ -n "$result_response_file" ]; then
local response
response="$(cat "$result_response_file")"
rm -f "$result_response_file"
local response_result
response_result="$result"
result="$response"
echo "$result"
if [ "$response_result" -ge 400 ] && [ "$response_result" -le 599 ]; then
exit 22
fi
exit "$result_exit_code"
else
echo "$result"
exit "$result_exit_code"
fi
}
###################################################
############### actions section ###################
###################################################
@ -938,6 +1006,9 @@ deploy() {
echo_debug "DOCKER_COMPOSE_FILE -> $DOCKER_COMPOSE_FILE"
echo_debug "docker_compose_file_content -> $docker_compose_file_content"
local json_temp_path
json_temp_path="$(unique_temp_file_path)"
# If the stack does not exist
if [ -z "$STACK" ]; then
echo_verbose "Stack $PORTAINER_STACK_NAME does not exist."
@ -967,23 +1038,19 @@ deploy() {
fi
local data_prefix="{\"Name\":\"$PORTAINER_STACK_NAME\","
local data_suffix=",\"Env\":"$stack_envvars"}"
echo "$data_prefix$docker_compose_file_content$data_suffix" > json.tmp
echo "$data_prefix$docker_compose_file_content$data_suffix" > "$json_temp_path"
echo_debug_safe_json "Stack JSON -> $(echo $data_prefix$docker_compose_file_content$data_suffix | jq -C .)" "$data_prefix$docker_compose_file_content$data_suffix"
# Create stack for single Docker instance
echo_verbose "Creating stack $PORTAINER_STACK_NAME..."
local create
create=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
--timeout=300 \
"$PORTAINER_URL/api/stacks" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN" \
type==2 \
method==string \
endpointId==$PORTAINER_ENDPOINT \
@json.tmp)
create=$(curl_wrapper \
--max-time 300 \
--request POST \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
--data "@${json_temp_path}" \
"${PORTAINER_URL}/api/stacks?type=2&method=string&endpointId=${PORTAINER_ENDPOINT}")
check_for_errors $? "$create"
echo_debug "Create action response -> $(echo $create | jq -C .)"
else
@ -997,28 +1064,23 @@ deploy() {
fi
local data_prefix="{\"Name\":\"$PORTAINER_STACK_NAME\",\"SwarmID\":\"$swarm_id\","
local data_suffix=",\"Env\":"$stack_envvars"}"
echo "$data_prefix$docker_compose_file_content$data_suffix" > json.tmp
echo "$data_prefix$docker_compose_file_content$data_suffix" > "$json_temp_path"
echo_debug_safe_json "Stack JSON -> $(echo $data_prefix$docker_compose_file_content$data_suffix | jq -C .)" "$data_prefix$docker_compose_file_content$data_suffix"
# Create stack for Docker swarm
echo_verbose "Creating stack $PORTAINER_STACK_NAME..."
local create
create=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
--timeout=300 \
"$PORTAINER_URL/api/stacks" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN" \
type==1 \
method==string \
endpointId==$PORTAINER_ENDPOINT \
@json.tmp)
create=$(curl_wrapper \
--max-time 300 \
--request POST \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
--data "@${json_temp_path}" \
"${PORTAINER_URL}/api/stacks?type=1&method=string&endpointId=${PORTAINER_ENDPOINT}")
check_for_errors $? "$create"
echo_debug "Create action response -> $(echo $create | jq -C .)"
fi
rm json.tmp
rm -f "$json_temp_path"
else
if [ $STRICT_MODE == "true" ]; then
echo_error "Error: Stack $PORTAINER_STACK_NAME already exists."
@ -1038,25 +1100,22 @@ deploy() {
fi
local data_prefix="{\"Id\":\"$stack_id\","
local data_suffix=",\"Env\":"$stack_envvars",\"Prune\":$PORTAINER_PRUNE}"
echo "$data_prefix$docker_compose_file_content$data_suffix" > json.tmp
echo "$data_prefix$docker_compose_file_content$data_suffix" > "$json_temp_path"
echo_debug_safe_json "Stack JSON -> $(echo $data_prefix$docker_compose_file_content$data_suffix | jq -C .)" "$data_prefix$docker_compose_file_content$data_suffix"
# Update stack
echo_verbose "Updating stack $PORTAINER_STACK_NAME..."
local update
update=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
--timeout=300 \
PUT "$PORTAINER_URL/api/stacks/$stack_id" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN" \
endpointId==$PORTAINER_ENDPOINT \
@json.tmp)
update=$(curl_wrapper \
--max-time 300 \
--request PUT \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
--data "@${json_temp_path}" \
"${PORTAINER_URL}/api/stacks/${stack_id}?endpointId=${PORTAINER_ENDPOINT}")
check_for_errors $? "$update"
echo_debug "Update action response -> $(echo $update | jq -C .)"
rm json.tmp
rm -f "$json_temp_path"
fi
}
@ -1091,13 +1150,10 @@ undeploy() {
echo_verbose "Deleting stack $PORTAINER_STACK_NAME..."
local delete
delete=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
DELETE "$PORTAINER_URL/api/stacks/$stack_id" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN" \
endpointId==$PORTAINER_ENDPOINT)
delete=$(curl_wrapper \
--request DELETE \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
"${PORTAINER_URL}/api/stacks/${stack_id}?endpointId=${PORTAINER_ENDPOINT}")
check_for_errors $? "$delete"
echo_debug "Delete action response -> $(echo $delete | jq -C .)"
}
@ -1106,13 +1162,10 @@ undeploy() {
login() {
echo_verbose "Getting auth token..."
local auth_token_json
auth_token_json=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
$PORTAINER_URL/api/auth \
username=$PORTAINER_USER \
password=$PORTAINER_PASSWORD)
auth_token_json=$(curl_wrapper \
--request POST \
--data "{\"username\":\"${PORTAINER_USER}\",\"password\":\"${PORTAINER_PASSWORD}\"}" \
"${PORTAINER_URL}/api/auth")
check_for_errors $? "$auth_token_json"
PORTAINER_AUTH_TOKEN=$(echo $auth_token_json | jq -r .jwt)
echo_debug "Get auth token response -> $(echo $auth_token_json | jq -C .)"
@ -1126,12 +1179,10 @@ login() {
# Get Docker info
docker_info() {
local docker_info
docker_info=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
"$PORTAINER_URL/api/endpoints/$PORTAINER_ENDPOINT/docker/info" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN")
docker_info=$(curl_wrapper \
--request GET \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
"${PORTAINER_URL}/api/endpoints/${PORTAINER_ENDPOINT}/docker/info")
check_for_errors $? "$docker_info"
echo "$docker_info"
@ -1151,13 +1202,12 @@ tasks() {
local filters
filters="{$filter_service$(if [ -n "$filter_desired_state" ]; then echo ",$filter_desired_state"; fi)}"
local tasks
tasks=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
"$PORTAINER_URL/api/endpoints/$PORTAINER_ENDPOINT/docker/tasks" \
filters=="$filters" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN")
tasks=$(curl_wrapper \
--request GET \
--get \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
--data-urlencode "filters=${filters}" \
"${PORTAINER_URL}/api/endpoints/${PORTAINER_ENDPOINT}/docker/tasks")
check_for_errors $? "$tasks"
if [ -n "$state" ]; then
local filter_status
@ -1192,14 +1242,15 @@ tasks_healthy() {
services() {
local services
local filter_service
local filters
filter_service="\"label\":{\"com.docker.stack.namespace=$PORTAINER_STACK_NAME\":true}"
services=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
"$PORTAINER_URL/api/endpoints/$PORTAINER_ENDPOINT/docker/services" \
filters=="{$filter_service}" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN")
filters="{${filter_service}}"
services=$(curl_wrapper \
--request GET \
--get \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
--data-urlencode "filters=${filters}" \
"${PORTAINER_URL}/api/endpoints/${PORTAINER_ENDPOINT}/docker/services")
check_for_errors $? "$services"
local filter_mode
@ -1223,13 +1274,12 @@ containers() {
filter_service="\"label\":{\"com.docker.swarm.service.name=$service_name\":true}"
fi
filters="{$filter_stack$(if [ -n "$filter_service" ]; then echo ",$filter_service"; fi),$filter_task}"
containers=$(http \
--check-status \
--ignore-stdin \
--verify=$HTTPIE_VERIFY_SSL \
"$PORTAINER_URL/api/endpoints/$PORTAINER_ENDPOINT/docker/containers/json" \
filters=="$filters" \
"Authorization: Bearer $PORTAINER_AUTH_TOKEN")
containers=$(curl_wrapper \
--request GET \
--get \
--header "Authorization: Bearer ${PORTAINER_AUTH_TOKEN}" \
--data-urlencode "filters=${filters}" \
"${PORTAINER_URL}/api/endpoints/${PORTAINER_ENDPOINT}/docker/containers/json")
check_for_errors $? "$containers"
echo "$containers"
}
@ -1241,11 +1291,13 @@ lint() {
if [ -x "$(command -v docker-compose)" ]; then
echo_verbose "Linting Docker compose/stack file..."
docker_stack_error="error_docker_stack_is_invalid"
docker_stack_validation=$(docker-compose -f "$DOCKER_COMPOSE_FILE" config -q > docker_stack_validation_report 2>&1 || echo $docker_stack_error)
local docker_stack_validation_report
docker_stack_validation_report="$(unique_temp_file_path)"
docker_stack_validation=$(docker-compose -f "$DOCKER_COMPOSE_FILE" config -q > "$docker_stack_validation_report" 2>&1 || echo $docker_stack_error)
if [[ $docker_stack_validation =~ $docker_stack_error$ ]]; then
echo_error "Error: The '$DOCKER_COMPOSE_FILE' Docker compose/stack file is invalid:"
echo_error "$(cat docker_stack_validation_report)"
rm -f docker_stack_validation_report
echo_error "$(cat $docker_stack_validation_report)"
rm -f "$docker_stack_validation_report"
exit 1
else
if [ "$ACTION" == "lint" ]; then

View File

@ -118,7 +118,16 @@ PSU_AUTH_TOKEN=$(psu_wrapper login --user $PSU_USER --password $PSU_PASSWORD --u
# 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
curl \
--fail \
--silent \
--insecure \
--max-time 10 \
--request POST \
--header "Authorization: Bearer ${PSU_AUTH_TOKEN}" \
--header "Content-Type: application/json" \
--data "@gitlab-registry-final.json" \
"${PSU_URL}/api/registries"
# Add local endpoint to the Portainer instance
end_point_type_param=EndpointType
@ -126,7 +135,15 @@ if [[ "$PORTAINER_VERSION" == "latest" ]] || [ "$(version $PORTAINER_VERSION)" -
# See: https://github.com/portainer/portainer/issues/4602#issuecomment-746819197
end_point_type_param=EndpointCreationType
fi
http --check-status --ignore-stdin --verify=no --timeout=10 POST "$PSU_URL/api/endpoints" "Authorization: Bearer $PSU_AUTH_TOKEN" Name==local $end_point_type_param==1
curl \
--fail \
--silent \
--insecure \
--max-time 10 \
--request POST \
--header "Authorization: Bearer ${PSU_AUTH_TOKEN}" \
--header "Content-Type: application/json" \
"${PSU_URL}/api/endpoints?Name=local&${end_point_type_param}=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)