Add some fixes and a couple of quirky scripts (#88)

* Add fixes and tiny QoL improvements

* Add some quirky scripts

Primatily for illustrative purpose.
This commit is contained in:
Andrew Mayorov 2021-12-17 13:58:50 +03:00 committed by GitHub
parent ce9a3371af
commit c819da773c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 467 additions and 6 deletions

View File

@ -44,6 +44,6 @@ END
)
"${WOORL[@]:-woorl}" -s "${MGPROTO}/proto/state_processing.thrift" \
"http://${MACHINEGUN:-machinegun}:8022/v1/automaton" \
"http://${MACHINEGUN:-machinegun}:${MACHINEGUN_PORT:-8022}/v1/automaton" \
Automaton Call "${MACHINEDESC}" "${CALLARGS}" \
| grep -sqF 'MachineFailed'

View File

@ -31,7 +31,7 @@ PLANID="${1}"
BATCHID="${2}"
[ -z "${BATCHID}" ] && usage
ACCOUNTER="http://${SHUMWAY:-shumway}:8022/accounter"
ACCOUNTER="http://${SHUMWAY:-shumway}:${SHUMWAY_PORT:-8022}/accounter"
"${CWD}/get-posting-plan.sh" "${PLANID}" | \
jq ".batch_list[] | select(.id == ${BATCHID})"

View File

@ -28,7 +28,7 @@ function usage {
PLANID="${1}"
[ -z "${PLANID}" ] && usage
ACCOUNTER="http://${SHUMWAY:-shumway}:8022/accounter"
ACCOUNTER="http://${SHUMWAY:-shumway}:${SHUMWAY_PORT:-8022}/accounter"
"${WOORL[@]:-woorl}" -s "${DAMSEL}/proto/accounter.thrift" \
"${ACCOUNTER}" Accounter GetPlan "\"${PLANID}\""

View File

@ -5,6 +5,8 @@
set -e
CWD="$(dirname ${0})"
INVOICE="${1}"
PAYMENT="${2:-1}"

View File

@ -0,0 +1,91 @@
#!/bin/bash
#
# This little guy repairs an invoice machine and makes a specific refund fail.
#
set -e
CWD="$(dirname $0)"
source "${CWD}/lib/logging"
function usage {
echo -e "Given ID of an invoice and a payment make it look like the payment refunded has failed."
echo
echo -e "Usage: $(em ${SCRIPTNAME} invoice_id [payment_id] [refund_id])"
echo -e " $(em invoice_id) Invoice ID (string)."
echo -e " $(em payment_id) Payment ID (string), $(em 1) by default."
echo -e " $(em refund_id) Refund ID (string), last one by default."
echo
echo -e "More information:"
echo -e " https://github.com/rbkmoney/damsel/blob/master/proto/payment_processing.thrift"
exit 127
}
INVOICE="${1}"
PAYMENT="${2:-1}"
REFUND="${3}"
[ -z "${INVOICE}" -o -z "${PAYMENT}" ] && usage
STATE="$(${CWD}/hellgate/get-invoice-state.sh ${INVOICE})"
info "Going on with payment $(em ${PAYMENT}) ..."
PAYMENT_STATE=$(echo "${STATE}" | jq ".payments[] | select(.payment.id == \"${PAYMENT}\")")
if [ "${PAYMENT_STATE}" = "" ]; then
err "No such payment"
fi
PAYMENT_STATUS=$(echo "${PAYMENT_STATE}" | jq -r ".payment.status | keys[0]")
if [ "${PAYMENT_STATUS}" != "captured" ]; then
err "Payment status ($(em ${PAYMENT_STATUS})) looks wrong for this repair scenario"
fi
REFUND_STATE=$(echo "${PAYMENT_STATE}" | jq ".refunds[${REFUND:--1}]")
if [ "${REFUND_STATE}" = "null" ]; then
err "No refunds found"
fi
REFUND=$(echo "${REFUND_STATE}" | jq -r ".id")
info "Going on with refund $(em ${REFUND}) ..."
REFUND_STATUS=$(echo "${REFUND_STATE}" | jq -r ".status | keys[0]")
if [ "${REFUND_STATUS}" != "succeeded" ]; then
err "Refund status ($(em ${REFUND_STATUS})) looks wrong for this repair scenario"
fi
CHANGES=$(cat <<END
[
{
"invoice_payment_change": {
"id": "${PAYMENT}",
"payload": {
"invoice_payment_refund_change": {
"id": "${REFUND}",
"payload": {
"invoice_payment_refund_status_changed": {
"status": {"failed": {"failure": {
"failure": {
"code": "authorization_failed",
"sub": {"code": "unknown"}
}
}}}
}
}
}
}
}
}
]
END
)
PLANID="${INVOICE}.${PAYMENT}.refund_session-${REFUND}"
BATCH=$(${CWD}/get-posting-plan-batch.sh ${PLANID} 1)
${CWD}/fail-machine.sh "${INVOICE}"
${CWD}/repair-invoice.sh "${INVOICE}" "${CHANGES}"
${CWD}/submit-posting-plan.sh "${PLANID}-reverted" "$(${CWD}/revert-posting-batch.sh "${BATCH}")"

View File

@ -0,0 +1,91 @@
#!/bin/bash
set -e
CWD="$(dirname $0)"
SCRIPTNAME="$(basename $0)"
source "${CWD}/lib/logging"
# Actual work is going here
INVOICE="${1}"
PAYMENT="${2}"
case ${INVOICE} in
""|"-h"|"--help" )
echo -ne "Given ID of an invoice and a payment make it so that boss is angry no more. "
echo
echo
echo -e "Usage: ${SCRIPTNAME} invoice_id payment_id"
echo -e " invoice_id Invoice ID (string)."
echo -e " payment_id Payment ID (string)."
echo -e " -h, --help Show this help message."
echo
echo -e "More information:"
echo -e " https://github.com/rbkmoney/damsel/blob/master/proto/payment_processing.thrift"
exit 0
;;
* )
;;
esac
INVOICE_ST=$(${CWD}/hellgate/get-invoice-state.sh ${INVOICE})
if [ "$(echo "${INVOICE_ST}" | jq -r '.invoice.status.paid')" = "null" ]; then
err "Invoice looks wrong for this repair scenario"
fi
PAYMENT_ST="$(echo "${INVOICE_ST}" | jq -r ".payments[] | .payment | select(.id == \"${PAYMENT}\")")"
if [ "$(echo "${PAYMENT_ST}" | jq -r '.status.captured')" = "null" ]; then
err "Payment with id $(em "${PAYMENT}") looks wrong for this repair scenario"
fi
# Essentially we have to simulate the failed session has been restarted and then
# finished successfully.
CHANGES=$(cat <<END
[
{
"invoice_payment_change": {
"id": "${PAYMENT}",
"payload": {
"invoice_payment_status_changed": {
"status": {
"failed": {"failure": {
"failure": {
"code": "authorization_failed",
"sub": {"code": "unknown"},
"reason": "Manually marked as failed at $(date) by @${USER}"
}
}}
}
}
}
}
},
{
"invoice_status_changed": {
"status": {
"cancelled": {
"details": "Manually marked as cancelled at $(date) by @${USER}"
}
}
}
}
]
END
)
PLANID="${INVOICE}.${PAYMENT}"
BATCH=$(${CWD}/get-posting-plan-batch.sh ${PLANID} 1)
# First we need to explicitly make invoice failed again. Amen.
${CWD}/fail-machine.sh "${INVOICE}"
# Then we should stuff it with previously reconstructed history
${CWD}/repair-invoice.sh --force --unset-timer "${INVOICE}" "${CHANGES}"
# And finally we should reconcile the state of accounts of participating parties.
${CWD}/submit-posting-plan.sh "${PLANID}-reverted" "$(${CWD}/revert-posting-batch.sh "${BATCH}")"

View File

@ -0,0 +1,124 @@
#!/bin/bash
set -e
CWD="$(dirname $0)"
SCRIPTNAME="$(basename $0)"
source "${CWD}/lib/logging"
INVOICE="${1}"
PAYMENT="${2}"
REFUND="${3}"
case ${INVOICE} in
""|"-h"|"--help" )
echo -ne "Given ID of an invoice and a payment make it look like the payment capture succeeded and the "
echo -ne "invoice has been paid. No transaction info is bound or rebound."
echo
echo
echo -e "Usage: ${SCRIPTNAME} invoice_id payment_id refund_id"
echo -e " invoice_id Invoice ID (string)."
echo -e " payment_id Payment ID (string)."
echo -e " refund_id Refund ID (string)."
echo -e " -h, --help Show this help message."
echo
echo -e "More information:"
echo -e " https://github.com/rbkmoney/damsel/blob/master/proto/payment_processing.thrift"
exit 0
;;
* )
;;
esac
[ -z "${INVOICE}" ] && exit 127
[ -z "${PAYMENT}" ] && exit 127
[ -z "${REFUND}" ] && exit 127
STATUS=$(cat <<END
{
"failed": {"failure": {
"failure": {
"code": "authorization_failed",
"sub": {"code": "unknown"},
"reason": "Manually marked as failed at $(date) by @${USER}"
}
}}
}
END
)
CHANGES=$(cat <<END
[
{
"invoice_payment_change": {
"id": "${PAYMENT}",
"payload": {
"invoice_payment_refund_change": {
"id": "${REFUND}",
"payload": {
"invoice_payment_session_change": {
"target": {
"refunded": []
},
"payload": {
"session_started": []
}
}
}
}
}
}
},
{
"invoice_payment_change": {
"id": "${PAYMENT}",
"payload": {
"invoice_payment_refund_change": {
"id": "${REFUND}",
"payload": {
"invoice_payment_session_change": {
"target": {
"refunded": []
},
"payload": {
"session_finished": {
"result": ${STATUS}
}
}
}
}
}
}
}
},
{
"invoice_payment_change": {
"id": "${PAYMENT}",
"payload": {
"invoice_payment_refund_change": {
"id": "${REFUND}",
"payload": {
"invoice_payment_refund_status_changed": {
"status": ${STATUS}
}
}
}
}
}
}
]
END
)
PLANID="${INVOICE}.${PAYMENT}.refund_session-${REFUND}"
BATCH=$(${CWD}/get-posting-plan-batch.sh ${PLANID} 1)
# First we need to explicitly make invoice failed again. Amen.
echo ${CWD}/fail-machine.sh "${INVOICE}"
# Then we should stuff it with previously reconstructed history
echo ${CWD}/repair-invoice.sh --force "${INVOICE}" "${CHANGES}"
# And finally we should reconcile the state of accounts of participating parties.
echo ${CWD}/submit-posting-plan.sh "${PLANID}-reverted" "$(${CWD}/revert-posting-batch.sh "${BATCH}")"

View File

@ -0,0 +1,153 @@
#!/bin/env python
#
# Give me a list of party ids and I'll try to make first class contractor entities from those
# contractors defined only within context of historical contracts.
#
import os
import sys
import argparse
import subprocess
import itertools
import json
import uuid
import copy
escbw = "\x1b[1;37m"
escbr = "\x1b[1;31m"
escby = "\x1b[1;33m"
escrs = "\x1b[0m"
def em(arg):
return "{bw}{arg}{rs}".format(bw=escbw,arg=arg,rs=escrs)
def err(*args):
prefix = "{br}[ERROR]{rs}".format(br=escbr, rs=escrs)
print(prefix, *args)
def info(*args):
print(em("[INFO]"), *args)
cwd = os.path.dirname(os.path.realpath(__file__))
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--dry-run', action='store_true', default=False,
help="do not actually do anything")
parser.add_argument('-d', '--debug', action='store_true', default=False,
help="print command invocation traces")
parser.add_argument('-i', '--input-file', nargs='?',
type=argparse.FileType('r', encoding='UTF-8'),
help="a file to read party ids from")
parser.add_argument('party_id', nargs='*',
help="which parties to act upon?")
opts = parser.parse_args()
if opts.input_file:
parties = [l.strip() for l in opts.input_file.readlines()]
else:
parties = opts.party_id
def sh(*args):
if opts.debug:
print('[SHELL]', *args)
return subprocess.check_output(' '.join(args), shell=True, text=True, cwd=cwd)
def cmd(*args):
if opts.debug:
print('[CMD]', *args)
return subprocess.check_output(args, text=True, cwd=cwd)
woorl_cmd = sh('test -f ./woorlrc && source ./woorlrc ; echo ${WOORL[@]:-woorl}').strip('\n').split(' ')
def woorl(*args, dry_run_result=None):
if not opts.dry_run:
return cmd(*itertools.chain(woorl_cmd, args))
else:
return dry_run_result
def mk_contractor(contractor_id, contractor):
return {
'contractor_modification': {
'id': contractor_id,
'modification': {
'creation': contractor
}
}
}
def mk_change_contractor(contract_id, contractor_id):
return {
'contract_modification': {
'id': contract_id,
'modification': {
'contractor_modification': contractor_id
}
}
}
userinfo = {'id': 'woorl', 'type': {'service_user': {}}}
partymgmt_url = 'http://{host}:{port}/v1/processing/partymgmt'.format(
host=os.environ.get('HELLGATE', 'hellgate'),
port=os.environ.get('HELLGATE_PORT', 8022)
)
def migrate_party(party_id):
info("[%s]" % party_id, "migrating ...")
party = json.loads(sh('./hellgate/get-party-state.sh', party_id))
if 'blocked' in party['blocking']:
return err("[%s]" % party_id, "blocked")
changeset = []
contractors = {}
if len(party['contractors']) > 0:
contractors = copy.deepcopy(party['contractors'])
if len(party['contracts']) > 0:
for contract_id, contract in party['contracts'].items():
if 'contractor_id' not in contract:
contractor_next = contract['contractor']
for contractor_id, contractor in contractors.items():
if contractor == contractor_next:
changeset.append(mk_change_contractor(contract_id, contractor_id))
break
else:
contractor_id = str(uuid.uuid4())
contractors[contractor_id] = copy.deepcopy(contractor_next)
changeset.append(mk_contractor(contractor_id, contractor_next))
changeset.append(mk_change_contractor(contract_id, contractor_id))
if len(changeset) > 0:
info("[%s]" % party_id, "submitting changeset:", changeset)
claim = json.loads(woorl(
'-s', '../damsel/ebin/dmsl_payment_processing_thrift.beam',
partymgmt_url, 'PartyManagement', 'CreateClaim',
json.dumps(userinfo),
json.dumps(party_id),
json.dumps(changeset),
dry_run_result='{"id":42, "revision":1}'
))
info("[%s]" % party_id, "claim %s created, revision %i" % (claim['id'], claim['revision']))
woorl(
'-s', '../damsel/ebin/dmsl_payment_processing_thrift.beam',
partymgmt_url, 'PartyManagement', 'AcceptClaim',
json.dumps(userinfo),
json.dumps(party_id),
json.dumps(claim['id']),
json.dumps(claim['revision'])
)
info("[%s]" % party_id, "claim %s accepted" % claim['id'])
info("[%s]" % party_id, "done")
for party_id in parties:
migrate_party(party_id)

View File

@ -39,7 +39,7 @@ while true; do
case "$1" in
--force ) PARAMS='{"validate_transitions":false}' ; shift 1 ;;
--set-timeout ) ACTION="{\"timer\":{\"set_timer\":{\"timer\":{\"timeout\":$2}}}}" ; shift 2 ;;
--set-deadline ) ACTION="{\"timer\":{\"set_timer\":{\"timer\":{\"deadline\":$2}}}}" ; shift 2 ;;
--set-deadline ) ACTION="{\"timer\":{\"set_timer\":{\"timer\":{\"deadline\":\"$2\"}}}}" ; shift 2 ;;
--unset-timer ) ACTION="{\"timer\":{\"unset_timer\":{}}}" ; shift 1 ;;
-- ) shift 1 ; break ;;
* ) break ;;

View File

@ -28,7 +28,7 @@ PLANID="${1}"
BATCH="${2}"
[ -z "${BATCH}" ] && usage
ACCOUNTER="http://${SHUMWAY:-shumway}:8022/accounter"
ACCOUNTER="http://${SHUMWAY:-shumway}:${SHUMWAY_PORT:-8022}/accounter"
"${WOORL[@]:-woorl}" -s "${DAMSEL}/proto/accounter.thrift" \
"${ACCOUNTER}" Accounter Hold \

View File

@ -32,7 +32,7 @@ PLANID="${1}"
BATCH="${2}"
[ -z "${BATCH}" ] && usage
ACCOUNTER="http://${SHUMWAY:-shumway}:8022/accounter"
ACCOUNTER="http://${SHUMWAY:-shumway}:${SHUMWAY_PORT:-8022}/accounter"
"${WOORL[@]:-woorl}" -s "${DAMSEL}/proto/accounter.thrift" \
"${ACCOUNTER}" Accounter Hold \