Add portainer.sh fix-git-auth for stacks with lost GitConfig credentials
The ollama stack's GitConfig.Authentication.Password had gone empty (same class of issue as the prior Gitea log-poisoning/token-rotation work), causing redeploy to fail with "Unable to clone git repository directory". This resupplies repositoryUsername/repositoryPassword from GITEA_USER/GITEA_TOKEN on redeploy, scoped to a new subcommand rather than changing default redeploy behavior for every stack. Claude-Session: https://claude.ai/code/session_01L7Rwa6guD5wK8F8tWQwcJX
This commit is contained in:
@@ -130,6 +130,61 @@ print(f'Done. ConfigHash: {hash}')
|
||||
" "$response"
|
||||
}
|
||||
|
||||
cmd_fix_git_auth() {
|
||||
local name="${1:-}"
|
||||
if [[ -z "$name" ]]; then
|
||||
echo "Usage: $0 fix-git-auth <stack-name>" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "${GITEA_USER:-}" || -z "${GITEA_TOKEN:-}" ]]; then
|
||||
echo "Error: GITEA_USER/GITEA_TOKEN not set in .credentials" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Looking up stack '$name'..."
|
||||
local stack_json
|
||||
if ! stack_json=$(get_stack_json_by_name "$name"); then
|
||||
echo "Error: stack '$name' not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
local stack_id
|
||||
stack_id=$(python3 -c "import json,sys; print(json.loads(sys.argv[1])['Id'])" "$stack_json")
|
||||
echo "Found stack ID: $stack_id"
|
||||
|
||||
# Re-supplies repository credentials that Portainer's stored GitConfig can
|
||||
# lose (empty Authentication.Password) — the symptom is git/redeploy
|
||||
# failing with "Unable to clone git repository directory".
|
||||
local payload
|
||||
payload=$(GITEA_USER="$GITEA_USER" GITEA_TOKEN="$GITEA_TOKEN" python3 -c "
|
||||
import json, os, sys
|
||||
stack = json.loads(sys.argv[1])
|
||||
env = stack.get('Env') or []
|
||||
print(json.dumps({
|
||||
'pullImage': True,
|
||||
'prune': False,
|
||||
'env': env,
|
||||
'repositoryAuthentication': True,
|
||||
'repositoryUsername': os.environ['GITEA_USER'],
|
||||
'repositoryPassword': os.environ['GITEA_TOKEN'],
|
||||
}))
|
||||
" "$stack_json")
|
||||
|
||||
echo "Re-authenticating and redeploying..."
|
||||
local response
|
||||
response=$(api_put "stacks/${stack_id}/git/redeploy?endpointId=${ENDPOINT_ID}" "$payload")
|
||||
|
||||
python3 -c "
|
||||
import json, sys
|
||||
d = json.loads(sys.argv[1])
|
||||
if 'message' in d and 'Id' not in d:
|
||||
print('Error:', d['message'])
|
||||
sys.exit(1)
|
||||
hash = d.get('GitConfig', {}).get('ConfigHash', 'unknown')[:10]
|
||||
pw_set = bool(d.get('GitConfig', {}).get('Authentication', {}).get('Password'))
|
||||
print(f'Done. ConfigHash: {hash}. Credential stored: {pw_set}')
|
||||
" "$response"
|
||||
}
|
||||
|
||||
cmd_deploy() {
|
||||
local name="${1:-}"
|
||||
local compose_path="${2:-}"
|
||||
@@ -292,6 +347,7 @@ command="${1:-}"
|
||||
case "$command" in
|
||||
list) cmd_list ;;
|
||||
redeploy) cmd_redeploy "${2:-}" ;;
|
||||
fix-git-auth) cmd_fix_git_auth "${2:-}" ;;
|
||||
deploy) cmd_deploy "${@:2}" ;;
|
||||
get-env) cmd_get_env "${2:-}" ;;
|
||||
set-env) cmd_set_env "${2:-}" "${@:3}" ;;
|
||||
@@ -304,6 +360,7 @@ case "$command" in
|
||||
echo " deploy <stack-name> <path> [K=V ...] Create new git-linked stack with optional env vars"
|
||||
echo " get-env <stack-name> Show env vars for a stack"
|
||||
echo " set-env <stack-name> KEY=VAL [...] Set env vars (redeploys without new image pull)"
|
||||
echo " fix-git-auth <stack-name> Re-supply git credentials when redeploy fails with 'Unable to clone'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user