TD-170: Add CI/CD (#4)

* added base ci cd files

* removed cds, kds, identdocstore, improved make, added compose

* fixed format

* fixed dialyzer

* added compose run

* changed to project_plugins

* fixed prometheus

* fixed lock

* fixed format

* removed deps

* added test fixes

* fixed lint

* fixed and removed old cfg

* removed unused app

* added requested changes

* fixed yamllint

* fixed

* removed expose

* updated party healthcheck

* updated compose

* removed version

* mb port?

* Revert "mb port?"

This reverts commit bf42f1c536.

* fixed
This commit is contained in:
Артем 2022-03-02 11:20:07 +03:00 committed by GitHub
parent 1862201e94
commit 32cc17e061
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 717 additions and 862 deletions

7
.dockerignore Normal file
View File

@ -0,0 +1,7 @@
/_build/
/.git/
/.github/
/.vscode/
/.idea/
erl_crash.dump
rebar3.crashdump

7
.env Normal file
View File

@ -0,0 +1,7 @@
# NOTE
# You SHOULD specify point releases here so that build time and run time Erlang/OTPs
# are the same. See: https://github.com/erlware/relx/pull/902
SERVICE_NAME=fistful-server
OTP_VERSION=24.2.0
REBAR_VERSION=3.18
THRIFT_VERSION=0.14.2.2

View File

@ -0,0 +1,54 @@
name: Build and push Docker image
on:
push:
branches: ['master']
env:
REGISTRY: ghcr.io
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Setup Buildx
uses: docker/setup-buildx-action@v1
# https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#setting-an-environment-variable
- name: Update environment variables
run: grep -v '^#' .env >> $GITHUB_ENV
- name: Log in to the Container registry
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Construct tags / labels for an image
id: meta
uses: docker/metadata-action@v3
with:
images: |
${{ env.REGISTRY }}/${{ github.repository }}
tags: |
type=sha
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
OTP_VERSION=${{ env.OTP_VERSION }}
THRIFT_VERSION=${{ env.THRIFT_VERSION }}
SERVICE_NAME=${{ env.SERVICE_NAME }}

View File

@ -1,39 +1,40 @@
name: Build Docker image
on:
push:
branches: [master]
pull_request:
branches: ["*"]
branches: ['**']
env:
REGISTRY: ghcr.io
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Buildx
uses: docker/setup-buildx-action@v1
# https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#setting-an-environment-variable
- name: Update environment variables
run: grep -v '^#' .env >> $GITHUB_ENV
- name: Construct tags / labels for an image
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
uses: docker/metadata-action@v3
with:
images: |
${{ env.REGISTRY }}/${{ github.repository }}
tags: |
type=sha
- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
- name: Build Docker image
uses: docker/build-push-action@v2
with:
push: ${{ github.event_name == 'push' }}
push: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
OTP_VERSION=${{ env.OTP_VERSION }}
THRIFT_VERSION=${{ env.THRIFT_VERSION }}
SERVICE_NAME=${{ env.SERVICE_NAME }}

38
.github/workflows/erlang-checks.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: Erlang CI Checks
on:
push:
branches:
- 'master'
pull_request:
branches: ['**']
jobs:
setup:
name: Load .env
runs-on: ubuntu-latest
outputs:
otp-version: ${{ steps.otp-version.outputs.version }}
rebar-version: ${{ steps.rebar-version.outputs.version }}
thrift-version: ${{ steps.thrift-version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@v2
- run: grep -v '^#' .env >> $GITHUB_ENV
- id: otp-version
run: echo "::set-output name=version::$OTP_VERSION"
- id: rebar-version
run: echo "::set-output name=version::$REBAR_VERSION"
- id: thrift-version
run: echo "::set-output name=version::$THRIFT_VERSION"
run:
name: Run checks
needs: setup
uses: valitydev/erlang-workflows/.github/workflows/erlang-parallel-build.yml@v1.0.1
with:
otp-version: ${{ needs.setup.outputs.otp-version }}
rebar-version: ${{ needs.setup.outputs.rebar-version }}
use-thrift: true
thrift-version: ${{ needs.setup.outputs.thrift-version }}
run-ct-with-compose: true

4
.gitignore vendored
View File

@ -4,6 +4,7 @@ log
/_checkouts/
*~
erl_crash.dump
rebar3.crashdump
.tags*
*.sublime-workspace
.edts
@ -11,3 +12,6 @@ erl_crash.dump
/.idea/
*.beam
/test/log/
# make stuff
/.image.*
Makefile.env

View File

@ -1,17 +1,39 @@
FROM ghcr.io/rbkmoney/build-erlang:785d48cbfa7e7f355300c08ba9edc6f0e78810cb AS builder
ARG OTP_VERSION
# Build the release
FROM docker.io/library/erlang:${OTP_VERSION} AS builder
ARG BUILDARCH
# Install thrift compiler
ARG THRIFT_VERSION
RUN wget -q -O- "https://github.com/valitydev/thrift/releases/download/${THRIFT_VERSION}/thrift-${THRIFT_VERSION}-linux-${BUILDARCH}.tar.gz" \
| tar -xvz -C /usr/local/bin/
# Copy sources
RUN mkdir /build
COPY . /build/
# Build the release
WORKDIR /build
RUN rebar3 compile
RUN rebar3 as prod release
# Keep in sync with Erlang/OTP version in build image
FROM erlang:24.1.3.0-slim
ENV SERVICE=fistful-server
# Make a runner image
FROM docker.io/library/erlang:${OTP_VERSION}-slim
ARG SERVICE_NAME
# Set env
ENV CHARSET=UTF-8
ENV LANG=C.UTF-8
COPY --from=builder /build/_build/prod/rel/${SERVICE} /opt/${SERVICE}
WORKDIR /opt/${SERVICE}
ENV SERVICE_NAME=${SERVICE_NAME}
# Set runtime
WORKDIR /opt/${SERVICE_NAME}
COPY --from=builder /build/_build/prod/rel/${SERVICE_NAME} /opt/${SERVICE_NAME}
ENTRYPOINT []
CMD /opt/${SERVICE}/bin/${SERVICE} foreground
EXPOSE 8022
CMD /opt/${SERVICE_NAME}/bin/${SERVICE_NAME} foreground

18
Dockerfile.dev Normal file
View File

@ -0,0 +1,18 @@
ARG OTP_VERSION
FROM docker.io/library/erlang:${OTP_VERSION}
ARG BUILDARCH
# Install thrift compiler
ARG THRIFT_VERSION
RUN wget -q -O- "https://github.com/valitydev/thrift/releases/download/${THRIFT_VERSION}/thrift-${THRIFT_VERSION}-linux-${BUILDARCH}.tar.gz" \
| tar -xvz -C /usr/local/bin/
# Set env
ENV CHARSET=UTF-8
ENV LANG=C.UTF-8
# Set runtime
CMD /bin/bash

134
Makefile
View File

@ -1,81 +1,107 @@
REBAR := $(shell which rebar3 2>/dev/null || which ./rebar3)
SUBMODULES = build-utils
SUBTARGETS = $(patsubst %,%/.git,$(SUBMODULES))
# HINT
# Use this file to override variables here.
# For example, to run with podman put `DOCKER=podman` there.
-include Makefile.env
UTILS_PATH := build-utils
TEMPLATES_PATH := .
# NOTE
# Variables specified in `.env` file are used to pick and setup specific
# component versions, both when building a development image and when running
# CI workflows on GH Actions. This ensures that tasks run with `wc-` prefix
# (like `wc-dialyze`) are reproducible between local machine and CI runners.
DOTENV := $(shell grep -v '^\#' .env)
# Name of the service
SERVICE_NAME := fistful-server
# Service image default tag
SERVICE_IMAGE_TAG ?= $(shell git rev-parse HEAD)
# The tag for service image to be pushed with
SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG)
# Development images
DEV_IMAGE_TAG = $(TEST_CONTAINER_NAME)-dev
DEV_IMAGE_ID = $(file < .image.dev)
# Base image for the service
BASE_IMAGE_NAME := service-erlang
BASE_IMAGE_TAG := ef20e2ec1cb1528e9214bdeb862b15478950d5cd
# Build image tag to be used
BUILD_IMAGE_NAME := build-erlang
BUILD_IMAGE_TAG := aaa79c2d6b597f93f5f8b724eecfc31ec2e2a23b
CALL_ANYWHERE := all submodules rebar-update compile xref lint dialyze plt_update \
release clean distclean format check_format
CALL_W_CONTAINER := $(CALL_ANYWHERE) test
DOCKER ?= docker
DOCKERCOMPOSE ?= docker-compose
DOCKERCOMPOSE_W_ENV = DEV_IMAGE_TAG=$(DEV_IMAGE_TAG) $(DOCKERCOMPOSE)
REBAR ?= rebar3
TEST_CONTAINER_NAME ?= testrunner
all: compile
-include $(UTILS_PATH)/make_lib/utils_container.mk
-include $(UTILS_PATH)/make_lib/utils_image.mk
.PHONY: dev-image clean-dev-image wc-shell test
.PHONY: $(CALL_W_CONTAINER)
dev-image: .image.dev
# CALL_ANYWHERE
$(SUBTARGETS): %/.git: %
git submodule update --init $<
touch $@
.image.dev: Dockerfile.dev .env
env $(DOTENV) $(DOCKERCOMPOSE_W_ENV) build $(TEST_CONTAINER_NAME)
$(DOCKER) image ls -q -f "reference=$(DEV_IMAGE_ID)" | head -n1 > $@
submodules: $(SUBTARGETS)
clean-dev-image:
ifneq ($(DEV_IMAGE_ID),)
$(DOCKER) image rm -f $(DEV_IMAGE_TAG)
rm .image.dev
endif
rebar-update:
$(REBAR) update
DOCKER_WC_OPTIONS := -v $(PWD):$(PWD) --workdir $(PWD)
DOCKER_WC_EXTRA_OPTIONS ?= --rm
DOCKER_RUN = $(DOCKER) run -t $(DOCKER_WC_OPTIONS) $(DOCKER_WC_EXTRA_OPTIONS)
compile: submodules rebar-update
DOCKERCOMPOSE_RUN = $(DOCKERCOMPOSE_W_ENV) run --rm $(DOCKER_WC_OPTIONS)
# Utility tasks
wc-shell: dev-image
$(DOCKER_RUN) --interactive --tty $(DEV_IMAGE_TAG)
wc-%: dev-image
$(DOCKER_RUN) $(DEV_IMAGE_TAG) make $*
wdeps-shell: dev-image
$(DOCKERCOMPOSE_RUN) $(TEST_CONTAINER_NAME) su; \
$(DOCKERCOMPOSE_W_ENV) down
wdeps-%: dev-image
$(DOCKERCOMPOSE_RUN) -T $(TEST_CONTAINER_NAME) make $*; \
res=$$?; \
$(DOCKERCOMPOSE_W_ENV) down; \
exit $$res
# Rebar tasks
rebar-shell:
$(REBAR) shell
compile:
$(REBAR) compile
xref: submodules
xref:
$(REBAR) xref
lint:
elvis rock -V
$(REBAR) lint
check_format:
check-format:
$(REBAR) fmt -c
dialyze:
$(REBAR) as test dialyzer
release:
$(REBAR) as prod release
eunit:
$(REBAR) eunit --cover
common-test:
$(REBAR) ct --cover
cover:
$(REBAR) covertool generate
format:
$(REBAR) fmt -w
dialyze: submodules
$(REBAR) as test dialyzer
plt_update:
$(REBAR) dialyzer -u true -s false
release: submodules
$(REBAR) as prod release
clean:
$(REBAR) clean
distclean:
distclean: clean-dev-image
rm -rf _build
rm -rf test/log
rm -f Dockerfile
rm -f docker-compose.yml
# CALL_W_CONTAINER
test: submodules
$(REBAR) do eunit, ct
test: eunit common-test
cover-report:
$(REBAR) cover

View File

@ -13,5 +13,5 @@
"Andrey Mayorov <a.mayorov@rbkmoney.com>"
]},
{licenses, ["Apache 2.0"]},
{links, ["https://github.com/rbkmoney/fistful-server"]}
{links, ["https://github.com/valitydev/fistful-server"]}
]}.

View File

@ -4,8 +4,6 @@
%%
-include_lib("cds_proto/include/cds_proto_storage_thrift.hrl").
-spec bank_card(binary(), {1..12, 2000..9999}, ct_helper:config()) ->
#{
token := binary(),
@ -14,26 +12,11 @@
exp_date => {integer(), integer()},
cardholder_name => binary()
}.
bank_card(PAN, ExpDate, C) ->
CardData = #cds_PutCardData{
pan = PAN
},
Client = ff_woody_client:new(maps:get('cds', ct_helper:cfg(services, C))),
WoodyCtx = ct_helper:get_woody_ctx(C),
Request = {{cds_proto_storage_thrift, 'Storage'}, 'PutCard', {CardData}},
case woody_client:call(Request, Client, WoodyCtx) of
{ok, #cds_PutCardResult{
bank_card = #cds_BankCard{
token = Token,
bin = BIN,
last_digits = Masked
}
}} ->
#{
token => Token,
bin => BIN,
masked_pan => Masked,
exp_date => ExpDate,
cardholder_name => <<"ct_cardholder_name">>
}
end.
bank_card(PAN, ExpDate, _C) ->
#{
token => PAN,
bin => binary:part(PAN, {0, 6}),
masked_pan => <<<<"*">> || <<_>> <= PAN>>,
exp_date => ExpDate,
cardholder_name => <<"ct_cardholder_name">>
}.

View File

@ -30,12 +30,12 @@
-include_lib("ff_cth/include/ct_domain.hrl").
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
-define(dtp(Type), dmsl_domain_thrift:Type()).
-define(DTP(Type), dmsl_domain_thrift:Type()).
-type object() ::
dmsl_domain_thrift:'DomainObject'().
-spec withdrawal_provider(?dtp('ProviderRef'), ?dtp('ProxyRef'), binary(), ct_helper:config()) -> object().
-spec withdrawal_provider(?DTP('ProviderRef'), ?DTP('ProxyRef'), binary(), ct_helper:config()) -> object().
withdrawal_provider(?prv(16) = Ref, ProxyRef, IdentityID, C) ->
AccountID = account(<<"RUB">>, C),
{provider, #domain_ProviderObject{
@ -176,7 +176,7 @@ withdrawal_provider(Ref, ProxyRef, IdentityID, C) ->
}
}}.
-spec withdrawal_terminal(?dtp('TerminalRef')) -> object().
-spec withdrawal_terminal(?DTP('TerminalRef')) -> object().
withdrawal_terminal(?trm(N) = Ref) when N > 0, N < 6 ->
{terminal, #domain_TerminalObject{
ref = Ref,
@ -246,7 +246,7 @@ withdrawal_terminal(?trm(8) = Ref) ->
}
}}.
-spec currency(?dtp('CurrencyRef')) -> object().
-spec currency(?DTP('CurrencyRef')) -> object().
currency(?cur(<<"EUR">> = SymCode) = Ref) ->
{currency, #domain_CurrencyObject{
ref = Ref,
@ -288,7 +288,7 @@ currency(?cur(<<"BTC">> = SymCode) = Ref) ->
}
}}.
-spec category(?dtp('CategoryRef'), binary(), ?dtp('CategoryType')) -> object().
-spec category(?DTP('CategoryRef'), binary(), ?DTP('CategoryType')) -> object().
category(Ref, Name, Type) ->
{category, #domain_CategoryObject{
ref = Ref,
@ -299,7 +299,7 @@ category(Ref, Name, Type) ->
}
}}.
-spec payment_method(?dtp('PaymentMethodRef')) -> object().
-spec payment_method(?DTP('PaymentMethodRef')) -> object().
payment_method(?pmt(_Type, Name) = Ref) when is_atom(Name) ->
payment_method(Name, Ref);
payment_method(?pmt(_Type, #domain_BankCardPaymentMethod{} = PM) = Ref) ->
@ -314,7 +314,7 @@ payment_method(Name, Ref) ->
}
}}.
-spec payment_system(?dtp('PaymentSystemRef'), binary()) -> object().
-spec payment_system(?DTP('PaymentSystemRef'), binary()) -> object().
payment_system(Ref, Name) ->
{payment_system, #domain_PaymentSystemObject{
ref = Ref,
@ -323,7 +323,7 @@ payment_system(Ref, Name) ->
}
}}.
-spec payment_service(?dtp('PaymentServiceRef'), binary()) -> object().
-spec payment_service(?DTP('PaymentServiceRef'), binary()) -> object().
payment_service(Ref, Name) ->
{payment_service, #domain_PaymentServiceObject{
ref = Ref,
@ -332,7 +332,7 @@ payment_service(Ref, Name) ->
}
}}.
-spec contract_template(?dtp('ContractTemplateRef'), ?dtp('TermSetHierarchyRef')) -> object().
-spec contract_template(?DTP('ContractTemplateRef'), ?DTP('TermSetHierarchyRef')) -> object().
contract_template(Ref, TermsRef) ->
contract_template(Ref, TermsRef, undefined, undefined).
@ -346,11 +346,11 @@ contract_template(Ref, TermsRef, ValidSince, ValidUntil) ->
}
}}.
-spec inspector(?dtp('InspectorRef'), binary(), ?dtp('ProxyRef')) -> object().
-spec inspector(?DTP('InspectorRef'), binary(), ?DTP('ProxyRef')) -> object().
inspector(Ref, Name, ProxyRef) ->
inspector(Ref, Name, ProxyRef, #{}).
-spec inspector(?dtp('InspectorRef'), binary(), ?dtp('ProxyRef'), ?dtp('ProxyOptions')) -> object().
-spec inspector(?DTP('InspectorRef'), binary(), ?DTP('ProxyRef'), ?DTP('ProxyOptions')) -> object().
inspector(Ref, Name, ProxyRef, Additional) ->
{inspector, #domain_InspectorObject{
ref = Ref,
@ -364,15 +364,15 @@ inspector(Ref, Name, ProxyRef, Additional) ->
}
}}.
-spec proxy(?dtp('ProxyRef'), Name :: binary()) -> object().
-spec proxy(?DTP('ProxyRef'), Name :: binary()) -> object().
proxy(Ref, Name) ->
proxy(Ref, Name, <<>>).
-spec proxy(?dtp('ProxyRef'), Name :: binary(), URL :: binary()) -> object().
-spec proxy(?DTP('ProxyRef'), Name :: binary(), URL :: binary()) -> object().
proxy(Ref, Name, URL) ->
proxy(Ref, Name, URL, #{}).
-spec proxy(?dtp('ProxyRef'), Name :: binary(), URL :: binary(), ?dtp('ProxyOptions')) -> object().
-spec proxy(?DTP('ProxyRef'), Name :: binary(), URL :: binary(), ?DTP('ProxyOptions')) -> object().
proxy(Ref, Name, URL, Opts) ->
{proxy, #domain_ProxyObject{
ref = Ref,
@ -384,7 +384,7 @@ proxy(Ref, Name, URL, Opts) ->
}
}}.
-spec system_account_set(?dtp('SystemAccountSetRef'), binary(), ?dtp('CurrencyRef'), ct_helper:config()) -> object().
-spec system_account_set(?DTP('SystemAccountSetRef'), binary(), ?DTP('CurrencyRef'), ct_helper:config()) -> object().
system_account_set(Ref, Name, ?cur(SymCode), C) ->
AccountID1 = account(SymCode, C),
AccountID2 = account(SymCode, C),
@ -402,7 +402,7 @@ system_account_set(Ref, Name, ?cur(SymCode), C) ->
}
}}.
-spec external_account_set(?dtp('ExternalAccountSetRef'), binary(), ?dtp('CurrencyRef'), ct_helper:config()) ->
-spec external_account_set(?DTP('ExternalAccountSetRef'), binary(), ?DTP('CurrencyRef'), ct_helper:config()) ->
object().
external_account_set(Ref, Name, ?cur(SymCode), C) ->
AccountID1 = account(SymCode, C),
@ -421,16 +421,16 @@ external_account_set(Ref, Name, ?cur(SymCode), C) ->
}
}}.
-spec term_set_hierarchy(?dtp('TermSetHierarchyRef')) -> object().
-spec term_set_hierarchy(?DTP('TermSetHierarchyRef')) -> object().
term_set_hierarchy(Ref) ->
term_set_hierarchy(Ref, []).
-spec term_set_hierarchy(?dtp('TermSetHierarchyRef'), [?dtp('TimedTermSet')]) -> object().
-spec term_set_hierarchy(?DTP('TermSetHierarchyRef'), [?DTP('TimedTermSet')]) -> object().
term_set_hierarchy(Ref, TermSets) ->
term_set_hierarchy(Ref, undefined, TermSets).
-spec term_set_hierarchy(Ref, ff_maybe:maybe(Ref), [?dtp('TimedTermSet')]) -> object() when
Ref :: ?dtp('TermSetHierarchyRef').
-spec term_set_hierarchy(Ref, ff_maybe:maybe(Ref), [?DTP('TimedTermSet')]) -> object() when
Ref :: ?DTP('TermSetHierarchyRef').
term_set_hierarchy(Ref, ParentRef, TermSets) ->
{term_set_hierarchy, #domain_TermSetHierarchyObject{
ref = Ref,
@ -440,14 +440,14 @@ term_set_hierarchy(Ref, ParentRef, TermSets) ->
}
}}.
-spec timed_term_set(?dtp('TermSet')) -> ?dtp('TimedTermSet').
-spec timed_term_set(?DTP('TermSet')) -> ?DTP('TimedTermSet').
timed_term_set(TermSet) ->
#domain_TimedTermSet{
action_time = #'TimestampInterval'{},
terms = TermSet
}.
-spec globals(?dtp('ExternalAccountSetRef'), [?dtp('PaymentInstitutionRef')]) -> object().
-spec globals(?DTP('ExternalAccountSetRef'), [?DTP('PaymentInstitutionRef')]) -> object().
globals(EASRef, PIRefs) ->
{globals, #domain_GlobalsObject{
ref = ?glob(),

View File

@ -1,49 +0,0 @@
-module(ct_identdocstore).
-export([rus_domestic_passport/1]).
-export([rus_retiree_insurance_cert/2]).
%%
-include_lib("identdocstore_proto/include/identdocstore_identity_document_storage_thrift.hrl").
-spec rus_domestic_passport(ct_helper:config()) -> {rus_domestic_passport, binary()}.
rus_domestic_passport(C) ->
Document = {
russian_domestic_passport,
#identdocstore_RussianDomesticPassport{
series = <<"1234">>,
number = <<"567890">>,
issuer = <<"Чаржбекистон УВД"/utf8>>,
issuer_code = <<"012345">>,
issued_at = <<"2012-12-22T12:42:11Z">>,
family_name = <<"Котлетка"/utf8>>,
first_name = <<"С"/utf8>>,
patronymic = <<"Пюрешкой"/utf8>>,
birth_date = <<"1972-03-12T00:00:00Z">>,
birth_place = <<"Чаржбечхала"/utf8>>
}
},
Client = ff_woody_client:new(maps:get('identdocstore', ct_helper:cfg(services, C))),
WoodyCtx = ct_helper:get_woody_ctx(C),
Request = {{identdocstore_identity_document_storage_thrift, 'IdentityDocumentStorage'}, 'Put', {Document}},
case ff_woody_client:call(Client, Request, WoodyCtx) of
{ok, Token} ->
{rus_domestic_passport, Token}
end.
-spec rus_retiree_insurance_cert(_Number :: binary(), ct_helper:config()) -> {rus_retiree_insurance_cert, binary()}.
rus_retiree_insurance_cert(Number, C) ->
Document = {
russian_retiree_insurance_certificate,
#identdocstore_RussianRetireeInsuranceCertificate{
number = Number
}
},
Client = ff_woody_client:new(maps:get('identdocstore', ct_helper:cfg(services, C))),
WoodyCtx = ct_helper:get_woody_ctx(C),
Request = {{identdocstore_identity_document_storage_thrift, 'IdentityDocumentStorage'}, 'Put', {Document}},
case ff_woody_client:call(Client, Request, WoodyCtx) of
{ok, Token} ->
{rus_retiree_insurance_cert, Token}
end.

View File

@ -1,112 +0,0 @@
-module(ct_keyring).
-include_lib("cds_proto/include/cds_proto_keyring_thrift.hrl").
-include_lib("jose/include/jose_jwk.hrl").
-include_lib("jose/include/jose_jws.hrl").
-define(THRESHOLD, 1).
-export([init/1]).
-type encrypted_master_key_share() :: #{
id := binary(),
owner := binary(),
encrypted_share := binary()
}.
-spec init(_) -> ok.
init(Config) ->
case get_state(Config) of
not_initialized ->
{ok, [EncryptedMasterKeyShare]} = start_init(?THRESHOLD, Config),
{ok, EncPrivateKey} = file:read_file("/opt/fistful-server/config/enc.1.priv.json"),
{ok, SigPrivateKey} = file:read_file("/opt/fistful-server/config/sig.1.priv.json"),
#{
id := ID,
encrypted_share := EncryptedShare
} = EncryptedMasterKeyShare,
DecryptedShare = private_decrypt(EncPrivateKey, <<"">>, EncryptedShare),
DecryptedMasterKeyShare = sign(SigPrivateKey, DecryptedShare),
ok = validate_init(ID, DecryptedMasterKeyShare, Config);
_ ->
ok
end.
get_state(Config) ->
{ok, #cds_KeyringState{status = Status}} = call('GetState', {}, Config),
Status.
start_init(Threshold, Config) ->
case call('StartInit', {Threshold}, Config) of
{ok, EncryptedShares} ->
{ok, decode_encrypted_shares(EncryptedShares)};
{exception, #cds_InvalidStatus{status = Status}} ->
{error, {invalid_status, Status}};
{exception, #cds_InvalidActivity{activity = Activity}} ->
{error, {invalid_activity, Activity}};
{exception, #cds_InvalidArguments{reason = Reason}} ->
{error, {invalid_arguments, Reason}}
end.
validate_init(ID, DecryptedMasterKeyShare, Config) ->
SignedShareKey = #cds_SignedMasterKeyShare{
id = ID,
signed_share = DecryptedMasterKeyShare
},
case call('ValidateInit', {SignedShareKey}, Config) of
{ok, {success, #cds_Success{}}} ->
ok;
{ok, {more_keys_needed, More}} ->
{more_keys_needed, More};
{exception, #cds_InvalidStatus{status = Status}} ->
{error, {invalid_status, Status}};
{exception, #cds_InvalidActivity{activity = Activity}} ->
{error, {invalid_activity, Activity}};
{exception, #cds_VerificationFailed{}} ->
{error, verification_failed};
{exception, #cds_OperationAborted{reason = Reason}} ->
{error, {operation_aborted, Reason}}
end.
call(Fun, Args, C) ->
Client = ff_woody_client:new(maps:get(kds, ct_helper:cfg(services, C))),
WoodyCtx = ct_helper:get_woody_ctx(C),
Request = {{cds_proto_keyring_thrift, 'KeyringManagement'}, Fun, Args},
woody_client:call(Request, Client, WoodyCtx).
%% DECODE
-spec decode_encrypted_shares([cds_proto_keyring_thrift:'EncryptedMasterKeyShare'()]) -> [encrypted_master_key_share()].
decode_encrypted_shares(EncryptedMasterKeyShares) ->
lists:map(fun decode_encrypted_share/1, EncryptedMasterKeyShares).
-spec decode_encrypted_share(cds_proto_keyring_thrift:'EncryptedMasterKeyShare'()) -> encrypted_master_key_share().
decode_encrypted_share(#cds_EncryptedMasterKeyShare{
id = Id,
owner = Owner,
encrypted_share = EncryptedShare
}) ->
#{
id => Id,
owner => Owner,
encrypted_share => EncryptedShare
}.
%%
%% DECRYPTION
%%
private_decrypt(PrivateKey, Password, JWECompacted) ->
{_Module, JWKPrivateKey} = jose_jwk:from(Password, PrivateKey),
{#{}, JWEPlain} = jose_jwe:expand(JWECompacted),
{Result, _JWE} = jose_jwk:block_decrypt(JWEPlain, JWKPrivateKey),
Result.
sign(PrivateKey, Plain) ->
JWKPrivateKey = jose_jwk:from(PrivateKey),
SignerWithoutKid = jose_jwk:signer(JWKPrivateKey),
Signer = SignerWithoutKid#{<<"kid">> => JWKPrivateKey#jose_jwk.fields},
{_JWKModule, SignedPlain} = jose_jwk:sign(Plain, Signer, JWKPrivateKey),
{_JWSModule, SignedCompacted} = jose_jws:compact(SignedPlain),
SignedCompacted.

View File

@ -62,9 +62,6 @@ do_setup(Options0, C0) ->
C1 = ct_helper:makeup_cfg([ct_helper:woody_ctx()], [{services, services(Options)} | C0]),
ok = ct_helper:set_context(C1),
ok = setup_dominant(Options, C1),
ok = ct_keyring:init(C1),
%% TODO rewrite timer , check keyring status from cds health checker
ok = timer:sleep(5000),
ok = configure_processing_apps(Options),
ok = ct_helper:unset_context(),
[{payment_system, Processing0} | C1].
@ -89,6 +86,10 @@ start_processing_apps(Options) ->
ip => {127, 0, 0, 1},
port => 8222,
handlers => [
{
<<"/bank">>,
{{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'}, {ff_ct_provider_handler, []}}
},
{
<<"/quotebank">>,
{{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'}, {ff_ct_provider_handler, []}}
@ -229,11 +230,7 @@ services(Options) ->
eventsink => "http://machinegun:8022/v1/event_sink",
automaton => "http://machinegun:8022/v1/automaton",
accounter => "http://shumway:8022/shumpune",
kds => "http://kds:8022/v2/keyring",
cds => "http://cds:8022/v2/storage",
identdocstore => "http://cds:8022/v1/identity_document_storage",
partymgmt => "http://party-management:8022/v1/processing/partymgmt",
identification => "http://identification:8022/v1/identification",
binbase => "http://localhost:8222/binbase"
},
maps:get(services, Options, Default).
@ -496,7 +493,7 @@ domain_config(Options, C) ->
{condition,
{payment_tool,
{digital_wallet, #domain_DigitalWalletCondition{
definition = {provider_is_deprecated, webmoney}
definition = {payment_service_is, ?pmtsrv(<<"webmoney">>)}
}}}},
then_ = {value, [?prv(3)]}
},
@ -550,7 +547,7 @@ domain_config(Options, C) ->
ct_domain:inspector(?insp(1), <<"Low Life">>, ?prx(1), #{<<"risk_score">> => <<"low">>}),
ct_domain:proxy(?prx(1), <<"Inspector proxy">>),
ct_domain:proxy(?prx(2), <<"Mocket proxy">>, <<"http://adapter-mocketbank:8022/proxy/mocketbank/p2p-credit">>),
ct_domain:proxy(?prx(2), <<"Mocket proxy">>, <<"http://localhost:8222/bank">>),
ct_domain:proxy(?prx(3), <<"Quote proxy">>, <<"http://localhost:8222/quotebank">>),
ct_domain:proxy(?prx(6), <<"Down proxy">>, <<"http://localhost:8222/downbank">>),
ct_domain:proxy(?prx(7), <<"Another down proxy">>, <<"http://localhost:8222/downbank2">>),

View File

@ -7,8 +7,7 @@
stdlib,
genlib,
woody,
damsel,
cds_proto
damsel
]},
{env, []},
{modules, []},
@ -16,5 +15,5 @@
"Andrey Mayorov <a.mayorov@rbkmoney.com>"
]},
{licenses, ["Apache 2.0"]},
{links, ["https://github.com/rbkmoney/fistful-server"]}
{links, ["https://github.com/valitydev/fistful-server"]}
]}.

View File

@ -8,12 +8,6 @@
-export([marshal/2]).
-export([unmarshal/2]).
%% Data transform
-define(to_session_event(SessionID, Payload),
{session, #{id => SessionID, payload => Payload}}
).
-spec marshal_deposit_state(ff_deposit:deposit_state(), ff_entity_context:context()) ->
ff_proto_deposit_thrift:'DepositState'().
marshal_deposit_state(DepositState, Context) ->

View File

@ -7,12 +7,6 @@
-export([marshal/2]).
-export([unmarshal/2]).
%% Data transform
-define(to_session_event(SessionID, Payload),
{session, #{id => SessionID, payload => Payload}}
).
%% API
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().

View File

@ -7,12 +7,6 @@
-export([marshal/2]).
-export([unmarshal/2]).
%% Data transform
-define(to_session_event(SessionID, Payload),
{session, #{id => SessionID, payload => Payload}}
).
%% API
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().

View File

@ -8,8 +8,6 @@
stdlib,
woody,
erl_health,
prometheus,
prometheus_cowboy,
scoper,
party_client,
fistful_proto,
@ -24,5 +22,5 @@
"Andrey Mayorov <a.mayorov@rbkmoney.com>"
]},
{licenses, ["Apache 2.0"]},
{links, ["https://github.com/rbkmoney/fistful-server"]}
{links, ["https://github.com/valitydev/fistful-server"]}
]}.

View File

@ -10,12 +10,6 @@
-export([marshal/2]).
-export([unmarshal/2]).
%% Data transform
-define(to_session_event(SessionID, Payload),
{session, #{id => SessionID, payload => Payload}}
).
%% API
-spec marshal_w2w_transfer_state(w2w_transfer:w2w_transfer_state(), ff_entity_context:context()) ->

View File

@ -46,10 +46,6 @@
-type group_name() :: ct_helper:group_name().
-type test_return() :: _ | no_return().
%% Macro helpers
-define(final_balance(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
%% API
-spec all() -> [test_case_name() | {group, group_name()}].

View File

@ -152,8 +152,6 @@ create_destination_ok(Resource, C) ->
IdentityID = Account#account_Account.identity,
#'CurrencyRef'{symbolic_code = Currency} = Account#account_Account.currency,
{unauthorized, #dst_Unauthorized{}} = Dst#dst_DestinationState.status,
{authorized, #dst_Authorized{}} = ct_helper:await(
{authorized, #dst_Authorized{}},
fun() ->

View File

@ -66,20 +66,20 @@ create_identity_ok(_C) ->
ProvID = <<"good-one">>,
Ctx = #{<<"NS">> => #{<<"owner">> => PartyID}},
Metadata = ff_entity_context_codec:marshal(#{<<"metadata">> => #{<<"some key">> => <<"some data">>}}),
Identity = create_identity(EID, Name, PartyID, ProvID, Ctx, Metadata),
IID = Identity#idnt_IdentityState.id,
{ok, Identity_} = call_api('Get', {IID, #'EventRange'{}}),
Identity0 = create_identity(EID, Name, PartyID, ProvID, Ctx, Metadata),
IID = Identity0#idnt_IdentityState.id,
{ok, Identity1} = call_api('Get', {IID, #'EventRange'{}}),
ProvID = Identity_#idnt_IdentityState.provider_id,
IID = Identity_#idnt_IdentityState.id,
Name = Identity_#idnt_IdentityState.name,
PartyID = Identity_#idnt_IdentityState.party_id,
unblocked = Identity_#idnt_IdentityState.blocking,
Metadata = Identity_#idnt_IdentityState.metadata,
ProvID = Identity1#idnt_IdentityState.provider_id,
IID = Identity1#idnt_IdentityState.id,
Name = Identity1#idnt_IdentityState.name,
PartyID = Identity1#idnt_IdentityState.party_id,
unblocked = Identity1#idnt_IdentityState.blocking,
Metadata = Identity1#idnt_IdentityState.metadata,
Ctx0 = Ctx#{
<<"com.rbkmoney.wapi">> => #{<<"name">> => Name}
},
Ctx0 = ff_entity_context_codec:unmarshal(Identity_#idnt_IdentityState.context),
Ctx0 = ff_entity_context_codec:unmarshal(Identity1#idnt_IdentityState.context),
ok.
get_event_unknown_identity_ok(_C) ->
@ -94,7 +94,7 @@ get_event_unknown_identity_ok(_C) ->
limit = 1,
'after' = undefined
},
{exception, {fistful_IdentityNotFound}} = call_api('GetEvents', {<<"bad id">>, Range}).
{exception, #'fistful_IdentityNotFound'{}} = call_api('GetEvents', {<<"bad id">>, Range}).
%%----------
%% INTERNAL

View File

@ -19,5 +19,5 @@
"Anton Belyaev <a.belyaev@rbkmoney.com>"
]},
{licenses, []},
{links, ["https://github.com/rbkmoney/fistful-server"]}
{links, ["https://github.com/valitydev/fistful-server"]}
]}.

View File

@ -1167,10 +1167,14 @@ construct_payment_tool({bank_card, #{bank_card := ResourceBankCard}}) ->
}};
construct_payment_tool({crypto_wallet, #{crypto_wallet := #{currency := {Currency, _}}}}) ->
{crypto_currency_deprecated, Currency};
construct_payment_tool({digital_wallet, #{digital_wallet := Wallet = #{
id := ID,
payment_service := PaymentService
}}}) ->
construct_payment_tool(
{digital_wallet, #{
digital_wallet := Wallet = #{
id := ID,
payment_service := PaymentService
}
}}
) ->
Token = maps:get(token, Wallet, undefined),
{digital_wallet, #domain_DigitalWallet{
id = ID,

View File

@ -32,10 +32,6 @@
-type group_name() :: ct_helper:group_name().
-type test_return() :: _ | no_return().
%% Macro helpers
-define(final_balance(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
%% API
-spec all() -> [test_case_name() | {group, group_name()}].

View File

@ -35,7 +35,7 @@
%% Macro helpers
-define(final_balance(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
-define(FINAL_BALANCE(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
%% API
@ -105,8 +105,8 @@ adjustment_can_change_status_to_failed_test(C) ->
wallet_id := WalletID,
source_id := SourceID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID)),
Failure = #{code => <<"test">>},
AdjustmentID = process_adjustment(DepositID, #{
change => {change_status, {failed, Failure}},
@ -117,8 +117,8 @@ adjustment_can_change_status_to_failed_test(C) ->
?assertEqual(<<"true_unique_id">>, ExternalID),
?assertEqual({failed, Failure}, get_deposit_status(DepositID)),
assert_adjustment_same_revisions(DepositID, AdjustmentID),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_source_balance(SourceID)).
-spec adjustment_can_change_failure_test(config()) -> test_return().
adjustment_can_change_failure_test(C) ->
@ -127,24 +127,24 @@ adjustment_can_change_failure_test(C) ->
wallet_id := WalletID,
source_id := SourceID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID)),
Failure1 = #{code => <<"one">>},
AdjustmentID1 = process_adjustment(DepositID, #{
change => {change_status, {failed, Failure1}}
}),
?assertEqual({failed, Failure1}, get_deposit_status(DepositID)),
assert_adjustment_same_revisions(DepositID, AdjustmentID1),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_source_balance(SourceID)),
Failure2 = #{code => <<"two">>},
AdjustmentID2 = process_adjustment(DepositID, #{
change => {change_status, {failed, Failure2}}
}),
?assertEqual({failed, Failure2}, get_deposit_status(DepositID)),
assert_adjustment_same_revisions(DepositID, AdjustmentID2),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_source_balance(SourceID)).
-spec adjustment_can_change_status_to_succeeded_test(config()) -> test_return().
adjustment_can_change_status_to_succeeded_test(C) ->
@ -152,8 +152,8 @@ adjustment_can_change_status_to_succeeded_test(C) ->
wallet_id := WalletID,
source_id := SourceID
} = prepare_standard_environment({5000000, <<"RUB">>}, C),
?assertEqual(?final_balance(5000000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-5000000, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(5000000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-5000000, <<"RUB">>), get_source_balance(SourceID)),
DepositID = generate_id(),
Params = #{
id => DepositID,
@ -169,8 +169,8 @@ adjustment_can_change_status_to_succeeded_test(C) ->
?assertMatch(succeeded, get_adjustment_status(DepositID, AdjustmentID)),
?assertMatch(succeeded, get_deposit_status(DepositID)),
assert_adjustment_same_revisions(DepositID, AdjustmentID),
?assertEqual(?final_balance(5000100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-5000100, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(5000100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-5000100, <<"RUB">>), get_source_balance(SourceID)).
-spec adjustment_can_not_change_status_to_pending_test(config()) -> test_return().
adjustment_can_not_change_status_to_pending_test(C) ->
@ -201,21 +201,21 @@ adjustment_sequence_test(C) ->
wallet_id := WalletID,
source_id := SourceID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID)),
MakeFailed = fun() ->
_ = process_adjustment(DepositID, #{
change => {change_status, {failed, #{code => <<"test">>}}}
}),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_source_balance(SourceID))
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_source_balance(SourceID))
end,
MakeSucceeded = fun() ->
_ = process_adjustment(DepositID, #{
change => {change_status, succeeded}
}),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID))
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID))
end,
MakeFailed(),
MakeSucceeded(),
@ -230,8 +230,8 @@ adjustment_idempotency_test(C) ->
wallet_id := WalletID,
source_id := SourceID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID)),
Params = #{
id => generate_id(),
change => {change_status, {failed, #{code => <<"test">>}}}
@ -242,8 +242,8 @@ adjustment_idempotency_test(C) ->
_ = process_adjustment(DepositID, Params),
Deposit = get_deposit(DepositID),
?assertMatch([_], ff_deposit:adjustments(Deposit)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_source_balance(SourceID)).
-spec no_parallel_adjustments_test(config()) -> test_return().
no_parallel_adjustments_test(C) ->

View File

@ -38,7 +38,7 @@
%% Macro helpers
-define(final_balance(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
-define(FINAL_BALANCE(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
%% API
@ -114,8 +114,8 @@ revert_ok_test(C) ->
RevertID = process_revert(DepositID, #{
body => {5000, <<"RUB">>}
}),
?assertEqual(?final_balance(5000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-5000, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(5000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-5000, <<"RUB">>), get_source_balance(SourceID)),
Revert = get_revert(RevertID, DepositID),
?assertEqual(undefined, ff_deposit_revert:reason(Revert)),
?assertEqual(undefined, ff_deposit_revert:external_id(Revert)),
@ -134,11 +134,11 @@ multiple_reverts_ok_test(C) ->
wallet_id := WalletID
} = prepare_standard_environment({10000, <<"RUB">>}, C),
_ = process_revert(DepositID, #{body => {1000, <<"RUB">>}}),
?assertEqual(?final_balance(9000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(9000, <<"RUB">>), get_wallet_balance(WalletID)),
_ = process_revert(DepositID, #{body => {1000, <<"RUB">>}}),
?assertEqual(?final_balance(8000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(8000, <<"RUB">>), get_wallet_balance(WalletID)),
_ = process_revert(DepositID, #{body => {1000, <<"RUB">>}}),
?assertEqual(?final_balance(7000, <<"RUB">>), get_wallet_balance(WalletID)).
?assertEqual(?FINAL_BALANCE(7000, <<"RUB">>), get_wallet_balance(WalletID)).
-spec multiple_parallel_reverts_ok_test(config()) -> test_return().
multiple_parallel_reverts_ok_test(C) ->
@ -154,8 +154,8 @@ multiple_parallel_reverts_ok_test(C) ->
end,
lists:seq(1, 10)
),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_source_balance(SourceID)).
-spec idempotency_test(config()) -> test_return().
idempotency_test(C) ->
@ -175,8 +175,8 @@ idempotency_test(C) ->
ok = ff_deposit_machine:start_revert(DepositID, Params),
RevertID = process_revert(DepositID, Params),
?assertEqual(1, erlang:length(get_reverts(DepositID))),
?assertEqual(?final_balance(5000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-5000, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(5000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-5000, <<"RUB">>), get_source_balance(SourceID)).
-spec optional_fields_test(config()) -> test_return().
optional_fields_test(C) ->
@ -191,8 +191,8 @@ optional_fields_test(C) ->
reason => <<"Why not">>,
external_id => <<"001">>
}),
?assertEqual(?final_balance(5000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-5000, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(5000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-5000, <<"RUB">>), get_source_balance(SourceID)),
Revert = get_revert(RevertID, DepositID),
?assertEqual(<<"Why not">>, ff_deposit_revert:reason(Revert)),
@ -259,16 +259,16 @@ wallet_limit_check_fail_test(C) ->
source_id := SourceID
} = prepare_standard_environment({1000, <<"RUB">>}, C),
ok = set_wallet_balance({900, <<"RUB">>}, WalletID),
?assertEqual(?final_balance(900, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-1000, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(900, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-1000, <<"RUB">>), get_source_balance(SourceID)),
RevertID = generate_id(),
ok = ff_deposit_machine:start_revert(DepositID, #{
id => RevertID,
body => {1000, <<"RUB">>}
}),
Status = await_final_revert_status(RevertID, DepositID),
?assertEqual(?final_balance(900, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-1000, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(900, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-1000, <<"RUB">>), get_source_balance(SourceID)),
?assertMatch({failed, _}, Status),
{failed, Failure} = Status,
?assertMatch(#{code := <<"unknown">>}, Failure).
@ -294,8 +294,8 @@ multiple_parallel_reverts_limit_fail_test(C) ->
end,
lists:seq(1, 10)
),
?final_balance(WalletBalance, <<"RUB">>) = get_wallet_balance(WalletID),
?final_balance(SourceBalance, <<"RUB">>) = get_source_balance(SourceID),
?FINAL_BALANCE(WalletBalance, <<"RUB">>) = get_wallet_balance(WalletID),
?FINAL_BALANCE(SourceBalance, <<"RUB">>) = get_source_balance(SourceID),
?assertEqual(-WalletBalance, SourceBalance + Lack),
?assert(WalletBalance >= 0).

View File

@ -37,7 +37,7 @@
%% Macro helpers
-define(final_balance(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
-define(FINAL_BALANCE(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
%% API
@ -109,8 +109,8 @@ adjustment_can_change_status_to_failed_test(C) ->
source_id := SourceID,
revert_id := RevertID
} = prepare_standard_environment({100, <<"RUB">>}, {50, <<"RUB">>}, C),
?assertEqual(?final_balance(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-50, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-50, <<"RUB">>), get_source_balance(SourceID)),
Failure = #{code => <<"test">>},
AdjustmentID = process_adjustment(DepositID, RevertID, #{
change => {change_status, {failed, Failure}},
@ -121,8 +121,8 @@ adjustment_can_change_status_to_failed_test(C) ->
?assertEqual(<<"true_unique_id">>, ExternalID),
?assertEqual({failed, Failure}, get_revert_status(DepositID, RevertID)),
assert_adjustment_same_revisions(DepositID, RevertID, AdjustmentID),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID)),
_ = process_revert(DepositID, #{body => {100, <<"RUB">>}}).
-spec adjustment_can_change_failure_test(config()) -> test_return().
@ -133,24 +133,24 @@ adjustment_can_change_failure_test(C) ->
source_id := SourceID,
revert_id := RevertID
} = prepare_standard_environment({100, <<"RUB">>}, {50, <<"RUB">>}, C),
?assertEqual(?final_balance(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-50, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-50, <<"RUB">>), get_source_balance(SourceID)),
Failure1 = #{code => <<"one">>},
AdjustmentID1 = process_adjustment(DepositID, RevertID, #{
change => {change_status, {failed, Failure1}}
}),
?assertEqual({failed, Failure1}, get_revert_status(DepositID, RevertID)),
assert_adjustment_same_revisions(DepositID, RevertID, AdjustmentID1),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID)),
Failure2 = #{code => <<"two">>},
AdjustmentID2 = process_adjustment(DepositID, RevertID, #{
change => {change_status, {failed, Failure2}}
}),
?assertEqual({failed, Failure2}, get_revert_status(DepositID, RevertID)),
assert_adjustment_same_revisions(DepositID, RevertID, AdjustmentID2),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID)).
-spec adjustment_can_change_status_to_succeeded_test(config()) -> test_return().
adjustment_can_change_status_to_succeeded_test(C) ->
@ -160,8 +160,8 @@ adjustment_can_change_status_to_succeeded_test(C) ->
source_id := SourceID
} = prepare_standard_environment({100, <<"RUB">>}, {50, <<"RUB">>}, C),
ok = set_wallet_balance({40, <<"RUB">>}, WalletID),
?assertEqual(?final_balance(40, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-50, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(40, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-50, <<"RUB">>), get_source_balance(SourceID)),
RevertID = generate_id(),
ok = ff_deposit_machine:start_revert(DepositID, #{
id => RevertID,
@ -174,8 +174,8 @@ adjustment_can_change_status_to_succeeded_test(C) ->
?assertMatch(succeeded, get_adjustment_status(DepositID, RevertID, AdjustmentID)),
?assertMatch(succeeded, get_revert_status(DepositID, RevertID)),
assert_adjustment_same_revisions(DepositID, RevertID, AdjustmentID),
?assertEqual(?final_balance(-10, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(-10, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_source_balance(SourceID)).
-spec adjustment_can_not_change_status_to_pending_test(config()) -> test_return().
adjustment_can_not_change_status_to_pending_test(C) ->
@ -209,21 +209,21 @@ adjustment_sequence_test(C) ->
source_id := SourceID,
revert_id := RevertID
} = prepare_standard_environment({100, <<"RUB">>}, {50, <<"RUB">>}, C),
?assertEqual(?final_balance(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-50, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-50, <<"RUB">>), get_source_balance(SourceID)),
MakeFailed = fun() ->
_ = process_adjustment(DepositID, RevertID, #{
change => {change_status, {failed, #{code => <<"test">>}}}
}),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID))
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID))
end,
MakeSucceeded = fun() ->
_ = process_adjustment(DepositID, RevertID, #{
change => {change_status, succeeded}
}),
?assertEqual(?final_balance(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-50, <<"RUB">>), get_source_balance(SourceID))
?assertEqual(?FINAL_BALANCE(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-50, <<"RUB">>), get_source_balance(SourceID))
end,
MakeFailed(),
MakeSucceeded(),
@ -239,8 +239,8 @@ adjustment_idempotency_test(C) ->
source_id := SourceID,
revert_id := RevertID
} = prepare_standard_environment({100, <<"RUB">>}, {50, <<"RUB">>}, C),
?assertEqual(?final_balance(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-50, <<"RUB">>), get_source_balance(SourceID)),
?assertEqual(?FINAL_BALANCE(50, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-50, <<"RUB">>), get_source_balance(SourceID)),
Params = #{
id => generate_id(),
change => {change_status, {failed, #{code => <<"test">>}}}
@ -251,8 +251,8 @@ adjustment_idempotency_test(C) ->
_ = process_adjustment(DepositID, RevertID, Params),
Revert = get_revert(DepositID, RevertID),
?assertMatch([_], ff_deposit_revert:adjustments(Revert)),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(-100, <<"RUB">>), get_source_balance(SourceID)).
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_source_balance(SourceID)).
-spec no_parallel_adjustments_test(config()) -> test_return().
no_parallel_adjustments_test(C) ->

View File

@ -53,7 +53,7 @@
%% Macro helpers
-define(final_balance(Cash), {
-define(FINAL_BALANCE(Cash), {
element(1, Cash),
{
{inclusive, element(1, Cash)},
@ -62,7 +62,7 @@
element(2, Cash)
}).
-define(final_balance(Amount, Currency), ?final_balance({Amount, Currency})).
-define(FINAL_BALANCE(Amount, Currency), ?FINAL_BALANCE({Amount, Currency})).
%% API
@ -186,7 +186,7 @@ session_fail_test(C) ->
ok = ff_withdrawal_machine:create(WithdrawalParams, ff_entity_context:new()),
Result = await_final_withdrawal_status(WithdrawalID),
?assertMatch({failed, #{code := <<"test_error">>}}, Result),
?assertEqual(?final_balance(WithdrawalCash), get_wallet_balance(WalletID)).
?assertEqual(?FINAL_BALANCE(WithdrawalCash), get_wallet_balance(WalletID)).
-spec quote_fail_test(config()) -> test_return().
quote_fail_test(C) ->
@ -214,7 +214,7 @@ quote_fail_test(C) ->
ok = ff_withdrawal_machine:create(WithdrawalParams, ff_entity_context:new()),
Result = await_final_withdrawal_status(WithdrawalID),
?assertMatch({failed, #{code := <<"unknown">>}}, Result),
?assertEqual(?final_balance(Cash), get_wallet_balance(WalletID)).
?assertEqual(?FINAL_BALANCE(Cash), get_wallet_balance(WalletID)).
-spec route_not_found_fail_test(config()) -> test_return().
route_not_found_fail_test(C) ->
@ -295,7 +295,7 @@ limit_check_fail_test(C) ->
}},
Result
),
?assertEqual(?final_balance(Cash), get_wallet_balance(WalletID)).
?assertEqual(?FINAL_BALANCE(Cash), get_wallet_balance(WalletID)).
-spec create_cashlimit_validation_error_test(config()) -> test_return().
create_cashlimit_validation_error_test(C) ->
@ -460,7 +460,7 @@ create_ok_test(C) ->
},
ok = ff_withdrawal_machine:create(WithdrawalParams, ff_entity_context:new()),
?assertEqual(succeeded, await_final_withdrawal_status(WithdrawalID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
Withdrawal = get_withdrawal(WithdrawalID),
?assertEqual(WalletID, ff_withdrawal:wallet_id(Withdrawal)),
?assertEqual(DestinationID, ff_withdrawal:destination_id(Withdrawal)),

View File

@ -36,7 +36,7 @@
%% Macro helpers
-define(final_balance(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
-define(FINAL_BALANCE(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
%% API
@ -106,8 +106,8 @@ adjustment_can_change_status_to_failed_test(C) ->
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(80, <<"RUB">>), get_destination_balance(DestinationID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(80, <<"RUB">>), get_destination_balance(DestinationID)),
Failure = #{code => <<"test">>},
AdjustmentID = process_adjustment(WithdrawalID, #{
change => {change_status, {failed, Failure}},
@ -118,8 +118,8 @@ adjustment_can_change_status_to_failed_test(C) ->
?assertEqual(<<"true_unique_id">>, ExternalID),
?assertEqual({failed, Failure}, get_withdrawal_status(WithdrawalID)),
assert_adjustment_same_revisions(WithdrawalID, AdjustmentID),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_destination_balance(DestinationID)).
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_destination_balance(DestinationID)).
-spec adjustment_can_change_failure_test(config()) -> test_return().
adjustment_can_change_failure_test(C) ->
@ -128,24 +128,24 @@ adjustment_can_change_failure_test(C) ->
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(80, <<"RUB">>), get_destination_balance(DestinationID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(80, <<"RUB">>), get_destination_balance(DestinationID)),
Failure1 = #{code => <<"one">>},
AdjustmentID1 = process_adjustment(WithdrawalID, #{
change => {change_status, {failed, Failure1}}
}),
?assertEqual({failed, Failure1}, get_withdrawal_status(WithdrawalID)),
assert_adjustment_same_revisions(WithdrawalID, AdjustmentID1),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_destination_balance(DestinationID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_destination_balance(DestinationID)),
Failure2 = #{code => <<"two">>},
AdjustmentID2 = process_adjustment(WithdrawalID, #{
change => {change_status, {failed, Failure2}}
}),
?assertEqual({failed, Failure2}, get_withdrawal_status(WithdrawalID)),
assert_adjustment_same_revisions(WithdrawalID, AdjustmentID2),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_destination_balance(DestinationID)).
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_destination_balance(DestinationID)).
-spec adjustment_can_change_status_to_succeeded_test(config()) -> test_return().
adjustment_can_change_status_to_succeeded_test(C) ->
@ -153,8 +153,8 @@ adjustment_can_change_status_to_succeeded_test(C) ->
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(80, <<"RUB">>), get_destination_balance(DestinationID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(80, <<"RUB">>), get_destination_balance(DestinationID)),
WithdrawalID = generate_id(),
Params = #{
id => WithdrawalID,
@ -170,8 +170,8 @@ adjustment_can_change_status_to_succeeded_test(C) ->
?assertMatch(succeeded, get_adjustment_status(WithdrawalID, AdjustmentID)),
?assertMatch(succeeded, get_withdrawal_status(WithdrawalID)),
assert_adjustment_same_revisions(WithdrawalID, AdjustmentID),
?assertEqual(?final_balance(-1000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(880, <<"RUB">>), get_destination_balance(DestinationID)).
?assertEqual(?FINAL_BALANCE(-1000, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(880, <<"RUB">>), get_destination_balance(DestinationID)).
-spec adjustment_can_not_change_status_to_pending_test(config()) -> test_return().
adjustment_can_not_change_status_to_pending_test(C) ->
@ -202,21 +202,21 @@ adjustment_sequence_test(C) ->
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(80, <<"RUB">>), get_destination_balance(DestinationID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(80, <<"RUB">>), get_destination_balance(DestinationID)),
MakeFailed = fun() ->
_ = process_adjustment(WithdrawalID, #{
change => {change_status, {failed, #{code => <<"test">>}}}
}),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_destination_balance(DestinationID))
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_destination_balance(DestinationID))
end,
MakeSucceeded = fun() ->
_ = process_adjustment(WithdrawalID, #{
change => {change_status, succeeded}
}),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(80, <<"RUB">>), get_destination_balance(DestinationID))
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(80, <<"RUB">>), get_destination_balance(DestinationID))
end,
MakeFailed(),
MakeSucceeded(),
@ -231,8 +231,8 @@ adjustment_idempotency_test(C) ->
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(80, <<"RUB">>), get_destination_balance(DestinationID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(80, <<"RUB">>), get_destination_balance(DestinationID)),
Params = #{
id => generate_id(),
change => {change_status, {failed, #{code => <<"test">>}}}
@ -243,8 +243,8 @@ adjustment_idempotency_test(C) ->
_ = process_adjustment(WithdrawalID, Params),
Withdrawal = get_withdrawal(WithdrawalID),
?assertMatch([_], ff_withdrawal:adjustments(Withdrawal)),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_destination_balance(DestinationID)).
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_destination_balance(DestinationID)).
-spec no_parallel_adjustments_test(config()) -> test_return().
no_parallel_adjustments_test(C) ->

View File

@ -48,7 +48,7 @@
%% Macro helpers
-define(final_balance(Cash), {
-define(FINAL_BALANCE(Cash), {
element(1, Cash),
{
{inclusive, element(1, Cash)},
@ -57,7 +57,7 @@
element(2, Cash)
}).
-define(final_balance(Amount, Currency), ?final_balance({Amount, Currency})).
-define(FINAL_BALANCE(Amount, Currency), ?FINAL_BALANCE({Amount, Currency})).
%% Common test API implementation
@ -159,7 +159,7 @@ adapter_unreachable_route_retryable_test(C) ->
},
ok = ff_withdrawal_machine:create(WithdrawalParams, ff_entity_context:new()),
?assertEqual(succeeded, await_final_withdrawal_status(WithdrawalID)),
?assertEqual(?final_balance(0, Currency), get_wallet_balance(WalletID)),
?assertEqual(?FINAL_BALANCE(0, Currency), get_wallet_balance(WalletID)),
Withdrawal = get_withdrawal(WithdrawalID),
?assertEqual(WalletID, ff_withdrawal:wallet_id(Withdrawal)),
?assertEqual(DestinationID, ff_withdrawal:destination_id(Withdrawal)),

View File

@ -543,15 +543,15 @@ construct_inaccessibilty({suspension, _}) ->
%%
-define(contractor_mod(ID, Mod),
-define(CONTRACTOR_MOD(ID, Mod),
{contractor_modification, #payproc_ContractorModificationUnit{id = ID, modification = Mod}}
).
-define(contract_mod(ID, Mod),
-define(CONTRACT_MOD(ID, Mod),
{contract_modification, #payproc_ContractModificationUnit{id = ID, modification = Mod}}
).
-define(wallet_mod(ID, Mod),
-define(WALLET_MOD(ID, Mod),
{wallet_modification, #payproc_WalletModificationUnit{id = ID, modification = Mod}}
).
@ -568,7 +568,7 @@ construct_contract_changeset(ContractID, #{
contractor_level := ContractorLevel
}) ->
[
?contractor_mod(
?CONTRACTOR_MOD(
ContractID,
{creation,
{private_entity,
@ -580,11 +580,11 @@ construct_contract_changeset(ContractID, #{
contact_info = #domain_ContactInfo{}
}}}}
),
?contractor_mod(
?CONTRACTOR_MOD(
ContractID,
{identification_level_modification, ContractorLevel}
),
?contract_mod(
?CONTRACT_MOD(
ContractID,
{creation, #payproc_ContractParams{
contractor_id = ContractID,
@ -596,7 +596,7 @@ construct_contract_changeset(ContractID, #{
construct_level_changeset(ContractID, ContractorLevel) ->
[
?contractor_mod(
?CONTRACTOR_MOD(
ContractID,
{identification_level_modification, ContractorLevel}
)

View File

@ -17,7 +17,6 @@
dmt_client,
shumpune_proto,
party_client,
id_proto,
binbase_proto
]},
{env, []},
@ -25,5 +24,5 @@
"Andrey Mayorov <a.mayorov@rbkmoney.com>"
]},
{licenses, ["Apache 2.0"]},
{links, ["https://github.com/rbkmoney/fistful-server"]}
{links, ["https://github.com/valitydev/fistful-server"]}
]}.

View File

@ -27,14 +27,14 @@ is_inside(Cash, CashRange = #domain_CashRange{lower = Lower, upper = Upper}) ->
error({misconfiguration, {'Invalid cash range specified', CashRange, Cash}})
end.
-define(cash(Amount, SymCode), #domain_Cash{
-define(CASH(Amount, SymCode), #domain_Cash{
amount = Amount,
currency = #domain_CurrencyRef{symbolic_code = SymCode}
}).
compare_cash(_, V, {inclusive, V}) ->
true;
compare_cash(F, ?cash(A, C), {_, ?cash(Am, C)}) ->
compare_cash(F, ?CASH(A, C), {_, ?CASH(Am, C)}) ->
F(A, Am);
compare_cash(_, _, _) ->
error.

View File

@ -37,7 +37,7 @@
%% Macro helpers
-define(final_balance(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
-define(FINAL_BALANCE(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
%% API
@ -110,8 +110,8 @@ adjustment_can_change_status_to_failed_test(C) ->
wallet_to_id := WalletToID,
wallet_from_id := WalletFromID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletToID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletToID)),
Failure = #{code => <<"test">>},
AdjustmentID = process_adjustment(W2WTransferID, #{
change => {change_status, {failed, Failure}},
@ -122,8 +122,8 @@ adjustment_can_change_status_to_failed_test(C) ->
?assertEqual(<<"true_unique_id">>, ExternalID),
?assertEqual({failed, Failure}, get_w2w_transfer_status(W2WTransferID)),
assert_adjustment_same_revisions(W2WTransferID, AdjustmentID),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletToID)).
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletToID)).
-spec adjustment_can_change_failure_test(config()) -> test_return().
adjustment_can_change_failure_test(C) ->
@ -132,24 +132,24 @@ adjustment_can_change_failure_test(C) ->
wallet_to_id := WalletToID,
wallet_from_id := WalletFromID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletToID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletToID)),
Failure1 = #{code => <<"one">>},
AdjustmentID1 = process_adjustment(W2WTransferID, #{
change => {change_status, {failed, Failure1}}
}),
?assertEqual({failed, Failure1}, get_w2w_transfer_status(W2WTransferID)),
assert_adjustment_same_revisions(W2WTransferID, AdjustmentID1),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletToID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletToID)),
Failure2 = #{code => <<"two">>},
AdjustmentID2 = process_adjustment(W2WTransferID, #{
change => {change_status, {failed, Failure2}}
}),
?assertEqual({failed, Failure2}, get_w2w_transfer_status(W2WTransferID)),
assert_adjustment_same_revisions(W2WTransferID, AdjustmentID2),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletToID)).
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletToID)).
-spec adjustment_can_change_status_to_succeeded_test(config()) -> test_return().
adjustment_can_change_status_to_succeeded_test(C) ->
@ -157,8 +157,8 @@ adjustment_can_change_status_to_succeeded_test(C) ->
wallet_to_id := WalletToID,
wallet_from_id := WalletFromID
} = prepare_standard_environment({50000, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(50000, <<"RUB">>), get_wallet_balance(WalletToID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(50000, <<"RUB">>), get_wallet_balance(WalletToID)),
W2WTransferID = generate_id(),
Params = #{
id => W2WTransferID,
@ -174,8 +174,8 @@ adjustment_can_change_status_to_succeeded_test(C) ->
?assertMatch(succeeded, get_adjustment_status(W2WTransferID, AdjustmentID)),
?assertMatch(succeeded, get_w2w_transfer_status(W2WTransferID)),
assert_adjustment_same_revisions(W2WTransferID, AdjustmentID),
?assertEqual(?final_balance(-100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(50100, <<"RUB">>), get_wallet_balance(WalletToID)).
?assertEqual(?FINAL_BALANCE(-100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(50100, <<"RUB">>), get_wallet_balance(WalletToID)).
-spec adjustment_can_not_change_status_to_pending_test(config()) -> test_return().
adjustment_can_not_change_status_to_pending_test(C) ->
@ -206,21 +206,21 @@ adjustment_sequence_test(C) ->
wallet_to_id := WalletToID,
wallet_from_id := WalletFromID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletToID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletToID)),
MakeFailed = fun() ->
_ = process_adjustment(W2WTransferID, #{
change => {change_status, {failed, #{code => <<"test">>}}}
}),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletToID))
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletToID))
end,
MakeSucceeded = fun() ->
_ = process_adjustment(W2WTransferID, #{
change => {change_status, succeeded}
}),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletToID))
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletToID))
end,
MakeFailed(),
MakeSucceeded(),
@ -235,8 +235,8 @@ adjustment_idempotency_test(C) ->
wallet_to_id := WalletToID,
wallet_from_id := WalletFromID
} = prepare_standard_environment({100, <<"RUB">>}, C),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletToID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletToID)),
Params = #{
id => generate_id(),
change => {change_status, {failed, #{code => <<"test">>}}}
@ -247,8 +247,8 @@ adjustment_idempotency_test(C) ->
_ = process_adjustment(W2WTransferID, Params),
W2WTransfer = get_w2w_transfer(W2WTransferID),
?assertMatch([_], w2w_transfer:adjustments(W2WTransfer)),
?assertEqual(?final_balance(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletToID)).
?assertEqual(?FINAL_BALANCE(100, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletToID)).
-spec no_parallel_adjustments_test(config()) -> test_return().
no_parallel_adjustments_test(C) ->

View File

@ -35,7 +35,7 @@
%% Macro helpers
-define(final_balance(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
-define(FINAL_BALANCE(Amount, Currency), {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency}).
%% API
@ -111,7 +111,7 @@ limit_check_fail_test(C) ->
wallet_to_id => WalletToID,
external_id => W2WTransferID
},
?assertEqual(?final_balance(50000, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(50000, <<"RUB">>), get_wallet_balance(WalletFromID)),
ok = w2w_transfer_machine:create(W2WTransferParams, ff_entity_context:new()),
Result = await_final_w2w_transfer_status(W2WTransferID),
?assertMatch(
@ -123,8 +123,8 @@ limit_check_fail_test(C) ->
}},
Result
),
?assertEqual(?final_balance(50000, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletToID)).
?assertEqual(?FINAL_BALANCE(50000, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletToID)).
-spec create_bad_amount_test(config()) -> test_return().
create_bad_amount_test(C) ->
@ -239,12 +239,12 @@ create_ok_test(C) ->
wallet_to_id => WalletToID,
external_id => W2WTransferID
},
?assertEqual(?final_balance(50000, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletToID)),
?assertEqual(?FINAL_BALANCE(50000, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletToID)),
ok = w2w_transfer_machine:create(W2WTransferParams, ff_entity_context:new()),
succeeded = await_final_w2w_transfer_status(W2WTransferID),
?assertEqual(?final_balance(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?final_balance(50000, <<"RUB">>), get_wallet_balance(WalletToID)),
?assertEqual(?FINAL_BALANCE(0, <<"RUB">>), get_wallet_balance(WalletFromID)),
?assertEqual(?FINAL_BALANCE(50000, <<"RUB">>), get_wallet_balance(WalletToID)),
W2WTransfer = get_w2w_transfer(W2WTransferID),
W2WTransferCash = w2w_transfer:body(W2WTransfer),
WalletFromID = w2w_transfer:wallet_from_id(W2WTransfer),

View File

@ -18,10 +18,12 @@
]},
{dmt_client, [
{cache_update_interval, 5000}, % milliseconds
% milliseconds
{cache_update_interval, 5000},
{max_cache_size, #{
elements => 20,
memory => 52428800 % 50Mb
% 50Mb
memory => 52428800
}},
{woody_event_handlers, [
{scoper_woody_event_handler, #{
@ -33,7 +35,7 @@
}}
]},
{service_urls, #{
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">>
}}
]},
@ -43,7 +45,8 @@
party_management => "http://party_management:8022/v1/processing/partymgmt"
}},
{woody, #{
cache_mode => safe, % disabled | safe | aggressive
% disabled | safe | aggressive
cache_mode => safe,
options => #{
woody_client => #{
event_handler =>
@ -75,13 +78,13 @@
{services, #{
'eventsink' => "http://machinegun:8022/v1/event_sink",
'automaton' => "http://machinegun:8022/v1/automaton",
'accounter' => "http://shumway:8022/shumpune",
'identification' => "http://identification:8022/v1/identification"
'accounter' => "http://shumway:8022/shumpune"
}}
]},
{ff_transfer, [
{max_session_poll_timeout, 14400}, %% 4h
%% 4h
{max_session_poll_timeout, 14400},
{withdrawal, #{
default_transient_errors => [
<<"authorization_failed:temporarily_unavailable">>
@ -112,9 +115,9 @@
}
}},
{health_check, #{
disk => {erl_health, disk, ["/", 99]},
memory => {erl_health, cg_memory, [99]},
service => {erl_health, service, [<<"fistful-server">>]}
disk => {erl_health, disk, ["/", 99]},
memory => {erl_health, cg_memory, [99]},
service => {erl_health, service, [<<"fistful-server">>]}
}},
{eventsink, #{
identity => #{

98
docker-compose.yml Normal file
View File

@ -0,0 +1,98 @@
services:
testrunner:
image: $DEV_IMAGE_TAG
build:
dockerfile: Dockerfile.dev
context: .
args:
OTP_VERSION: $OTP_VERSION
THRIFT_VERSION: $THRIFT_VERSION
volumes:
- .:$PWD
hostname: fistful-server
depends_on:
machinegun:
condition: service_healthy
dominant:
condition: service_healthy
party-management:
condition: service_healthy
shumway:
condition: service_healthy
working_dir: $PWD
command: /sbin/init
dominant:
image: ghcr.io/valitydev/dominant:sha-0b47590
command: /opt/dominant/bin/dominant foreground
depends_on:
machinegun:
condition: service_healthy
healthcheck:
test: "/opt/dominant/bin/dominant ping"
interval: 10s
timeout: 5s
retries: 10
machinegun:
image: docker.io/rbkmoney/machinegun:c05a8c18cd4f7966d70b6ad84cac9429cdfe37ae
command: /opt/machinegun/bin/machinegun foreground
volumes:
- ./test/machinegun/config.yaml:/opt/machinegun/etc/config.yaml
- ./test/machinegun/cookie:/opt/machinegun/etc/cookie
healthcheck:
test: "curl http://localhost:8022/"
interval: 5s
timeout: 1s
retries: 20
shumway:
image: docker.io/rbkmoney/shumway:44eb989065b27be619acd16b12ebdb2288b46c36
restart: unless-stopped
entrypoint:
- java
- -Xmx512m
- -jar
- /opt/shumway/shumway.jar
- --spring.datasource.url=jdbc:postgresql://shumway-db:5432/shumway
- --spring.datasource.username=postgres
- --spring.datasource.password=postgres
- --management.metrics.export.statsd.enabled=false
depends_on:
shumway-db:
condition: service_healthy
healthcheck:
test: "curl http://localhost:8023/actuator/health"
interval: 5s
timeout: 1s
retries: 20
party-management:
image: ghcr.io/valitydev/party-management:sha-e456e24
command: /opt/party-management/bin/party-management foreground
depends_on:
machinegun:
condition: service_healthy
dominant:
condition: service_started
shumway:
condition: service_healthy
healthcheck:
test: "/opt/party-management/bin/party-management ping"
interval: 10s
timeout: 5s
retries: 10
shumway-db:
image: docker.io/library/postgres:9.6
environment:
- POSTGRES_DB=shumway
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- SERVICE_NAME=shumway-db
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5

View File

@ -1,26 +1,22 @@
[
{elvis, [
{verbose, true},
{config, [
#{
dirs => ["apps/*/**"],
dirs => ["apps/**/src", "apps/**/include"],
filter => "*.erl",
ignore => ["apps/swag_.*", ".+_SUITE.erl"],
ruleset => erl_files,
rules => [
{elvis_text_style, line_length, #{limit => 120, skip_comments => false}},
{elvis_text_style, no_tabs},
{elvis_text_style, no_trailing_whitespace},
{elvis_style, macro_module_names},
{elvis_style, operator_spaces, #{rules => [{right, ","}, {right, "++"}, {left, "++"}]}},
%% Common settings
{elvis_text_style, line_length, #{limit => 120}},
{elvis_style, nesting_level, #{level => 3}},
{elvis_style, god_modules, #{limit => 30, ignore => [wapi_wallet_ff_backend]}},
{elvis_style, no_if_expression},
{elvis_style, invalid_dynamic_call, #{ignore => [ff_ct_provider_handler]}},
{elvis_style, used_ignored_variable},
{elvis_style, no_behavior_info},
{elvis_style, module_naming_convention, #{regex => "^[a-z]([a-z0-9]*_?)*(_SUITE)?$"}},
{elvis_style, atom_naming_convention, #{ignore => [ff_pipeline]}},
{elvis_style, function_naming_convention, #{regex => "^[a-z]([a-z0-9]*_?)*$"}},
{elvis_style, state_record_and_type, #{ignore => [machinery_gensrv_backend]}},
{elvis_style, no_spec_with_records},
{elvis_style, no_if_expression, disable},
{elvis_style, state_record_and_type, disable},
{elvis_style, god_modules, #{ignore => [ff_withdrawal]}},
%% Project settings
% Verbose authorization code triggers this otherwise
{elvis_style, dont_repeat_yourself, #{
min_complexity => 32,
ignore => [
@ -32,8 +28,26 @@
ff_withdrawal_machinery_schema,
ff_withdrawal_session_machinery_schema
]
}},
{elvis_style, no_debug_call, #{}}
}}
]
},
#{
dirs => ["apps/**/test"],
filter => "*.erl",
ruleset => erl_files,
rules => [
{elvis_text_style, line_length, #{limit => 120}},
{elvis_style, nesting_level, #{level => 3}},
{elvis_style, no_if_expression, disable},
{elvis_style, invalid_dynamic_call, #{ignore => [ff_ct_provider_handler]}},
% We want to use `ct:pal/2` and friends in test code.
{elvis_style, no_debug_call, disable},
% Assert macros can trigger use of ignored binding, yet we want them for better
% readability.
{elvis_style, used_ignored_variable, disable},
% Tests are usually more comprehensible when a bit more verbose.
{elvis_style, dont_repeat_yourself, #{min_complexity => 50}},
{elvis_style, god_modules, disable}
]
},
#{
@ -47,21 +61,22 @@
ruleset => elvis_config
},
#{
dirs => [".", "apps/*/*"],
dirs => [".", "apps/*"],
filter => "rebar.config",
ignore => ["apps/swag_*"],
ruleset => rebar_config,
rules => [
{elvis_text_style, line_length, #{limit => 120, skip_comments => false}},
{elvis_text_style, line_length, #{limit => 120}},
{elvis_text_style, no_tabs},
{elvis_text_style, no_trailing_whitespace}
{elvis_text_style, no_trailing_whitespace},
%% Temporarily disabled till regex pattern is available
{elvis_project, no_deps_master_rebar, disable}
]
},
#{
dirs => ["apps/**"],
dirs => ["apps/*/src"],
filter => "*.app.src",
ignore => ["apps/swag_*"],
rules => [
{elvis_text_style, line_length, #{limit => 120, skip_comments => false}},
{elvis_text_style, line_length, #{limit => 120}},
{elvis_text_style, no_tabs},
{elvis_text_style, no_trailing_whitespace}
]

View File

@ -38,7 +38,6 @@
{machinery, {git, "https://github.com/valitydev/machinery.git", {branch, "master"}}},
{damsel, {git, "https://github.com/valitydev/damsel.git", {branch, "master"}}},
{dmt_client, {git, "https://github.com/valitydev/dmt_client.git", {branch, master}}},
{id_proto, {git, "https://github.com/valitydev/identification-proto.git", {branch, "master"}}},
{fistful_proto, {git, "https://github.com/valitydev/fistful-proto.git", {branch, "master"}}},
{binbase_proto, {git, "https://github.com/valitydev/binbase-proto.git", {branch, "master"}}},
{party_client, {git, "https://github.com/valitydev/party_client_erlang.git", {branch, "master"}}},
@ -75,12 +74,12 @@
{profiles, [
{prod, [
{deps, [
{how_are_you, {git, "https://github.com/rbkmoney/how_are_you.git", {ref, "2fd80134"}}},
{woody_api_hay, {git, "https://github.com/rbkmoney/woody_api_hay.git", {ref, "4c39134cd"}}},
{how_are_you, {git, "https://github.com/valitydev/how_are_you.git", {ref, "2fd80134"}}},
{woody_api_hay, {git, "https://github.com/valitydev/woody_api_hay.git", {ref, "4c39134cd"}}},
% Introspect a node running in production
{recon, "2.5.2"},
{logger_logstash_formatter,
{git, "https://github.com/rbkmoney/logger_logstash_formatter.git", {ref, "87e52c7"}}},
{git, "https://github.com/valitydev/logger_logstash_formatter.git", {ref, "2c7b716"}}},
{iosetopts, {git, "https://github.com/valitydev/iosetopts.git", {ref, "edb445c"}}}
]},
{relx, [
@ -92,6 +91,8 @@
{tools, load},
{recon, load},
{logger_logstash_formatter, load},
prometheus,
prometheus_cowboy,
woody_api_hay,
how_are_you,
sasl,
@ -107,18 +108,18 @@
{test, [
{deps, [
{meck, "0.9.2"},
{jose, "1.11.2"},
{identdocstore_proto, {git, "https://github.com/rbkmoney/identdocstore-proto.git", {branch, "master"}}},
{cds_proto, {git, "https://github.com/rbkmoney/cds-proto.git", {branch, "master"}}}
{jose, "1.11.2"}
]},
{project_app_dirs, ["apps/*"]},
{cover_enabled, true},
{cover_excl_apps, [ff_cth]},
{dialyzer, [{plt_extra_apps, [eunit, common_test, meck, jose, identdocstore_proto]}]}
{dialyzer, [{plt_extra_apps, [eunit, common_test, meck, jose]}]}
]}
]}.
{plugins, [
{project_plugins, [
{rebar3_lint, "1.0.1"},
{covertool, "2.0.4"},
{erlfmt, "1.0.0"}
]}.
@ -130,6 +131,23 @@
"apps/machinery_extra/{src,include,test}/*.{hrl,erl,app.src}",
"apps/w2w/{src,include,test}/*.{hrl,erl,app.src}",
"rebar.config",
"elvis.config"
"elvis.config",
"config/sys.config",
"test/*/sys.config"
]}
]}.
{covertool, [
{coverdata_files, [
"eunit.coverdata",
"ct.coverdata"
]}
]}.
%% NOTE
%% It is needed to use rebar3 lint plugin
{overrides, [
{del, accept, [{plugins, [{rebar3_archive_plugin, "0.0.2"}]}]},
{del, prometheus_cowboy, [{plugins, [{rebar3_archive_plugin, "0.0.1"}]}]},
{del, prometheus_httpd, [{plugins, [{rebar3_archive_plugin, "0.0.1"}]}]}
]}.

View File

@ -1,6 +1,5 @@
{"1.2.0",
[{<<"accept">>,{pkg,<<"accept">>,<<"0.3.5">>},2},
{<<"binbase_proto">>,
[{<<"binbase_proto">>,
{git,"https://github.com/valitydev/binbase-proto.git",
{ref,"4c2e11c58bc3574540f729f6ddc88796dba119ce"}},
0},
@ -38,10 +37,6 @@
0},
{<<"gproc">>,{pkg,<<"gproc">>,<<"0.9.0">>},1},
{<<"hackney">>,{pkg,<<"hackney">>,<<"1.18.0">>},1},
{<<"id_proto">>,
{git,"https://github.com/valitydev/identification-proto.git",
{ref,"8e215c03c4193ef4a02a799b790a8cc14437ce26"}},
0},
{<<"idna">>,{pkg,<<"idna">>,<<"6.1.1">>},2},
{<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},1},
{<<"machinery">>,
@ -59,10 +54,6 @@
{git,"https://github.com/valitydev/party_client_erlang.git",
{ref,"8fc5595c4c61c0fe3d2dc29a61f48ba94e9bdef7"}},
0},
{<<"prometheus">>,{pkg,<<"prometheus">>,<<"4.8.1">>},0},
{<<"prometheus_cowboy">>,{pkg,<<"prometheus_cowboy">>,<<"0.1.8">>},0},
{<<"prometheus_httpd">>,{pkg,<<"prometheus_httpd">>,<<"2.1.11">>},1},
{<<"quantile_estimator">>,{pkg,<<"quantile_estimator">>,<<"0.2.1">>},1},
{<<"quickrand">>,
{git,"https://github.com/okeuday/quickrand.git",
{ref,"7fe89e9cfcc1378b7164e9dac4e7f02119110b68"}},
@ -100,7 +91,6 @@
0}]}.
[
{pkg_hash,[
{<<"accept">>, <<"B33B127ABCA7CC948BBE6CAA4C263369ABF1347CFA9D8E699C6D214660F10CD1">>},
{<<"cache">>, <<"B23A5FE7095445A88412A6E614C933377E0137B44FFED77C9B3FEF1A731A20B2">>},
{<<"certifi">>, <<"D4FB0A6BB20B7C9C3643E22507E42F356AC090A1DCEA9AB99E27E0376D695EBA">>},
{<<"cowboy">>, <<"865DD8B6607E14CF03282E10E934023A1BD8BE6F6BACF921A7E2A96D800CD452">>},
@ -112,15 +102,10 @@
{<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>},
{<<"mimerl">>, <<"67E2D3F571088D5CFD3E550C383094B47159F3EEE8FFA08E64106CDF5E981BE3">>},
{<<"parse_trans">>, <<"16328AB840CC09919BD10DAB29E431DA3AF9E9E7E7E6F0089DD5A2D2820011D8">>},
{<<"prometheus">>, <<"FA76B152555273739C14B06F09F485CF6D5D301FE4E9D31B7FF803D26025D7A0">>},
{<<"prometheus_cowboy">>, <<"CFCE0BC7B668C5096639084FCD873826E6220EA714BF60A716F5BD080EF2A99C">>},
{<<"prometheus_httpd">>, <<"F616ED9B85B536B195D94104063025A91F904A4CFC20255363F49A197D96C896">>},
{<<"quantile_estimator">>, <<"EF50A361F11B5F26B5F16D0696E46A9E4661756492C981F7B2229EF42FF1CD15">>},
{<<"ranch">>, <<"8C7A100A139FD57F17327B6413E4167AC559FBC04CA7448E9BE9057311597A1D">>},
{<<"ssl_verify_fun">>, <<"CF344F5692C82D2CD7554F5EC8FD961548D4FD09E7D22F5B62482E5AEAEBD4B0">>},
{<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}]},
{pkg_hash_ext,[
{<<"accept">>, <<"11B18C220BCC2EAB63B5470C038EF10EB6783BCB1FCDB11AA4137DEFA5AC1BB8">>},
{<<"cache">>, <<"44516CE6FA03594D3A2AF025DD3A87BFE711000EB730219E1DDEFC816E0AA2F4">>},
{<<"certifi">>, <<"6AC7EFC1C6F8600B08D625292D4BBF584E14847CE1B6B5C44D983D273E1097EA">>},
{<<"cowboy">>, <<"2C729F934B4E1AA149AFF882F57C6372C15399A20D54F65C8D67BEF583021BDE">>},
@ -132,10 +117,6 @@
{<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>},
{<<"mimerl">>, <<"F278585650AA581986264638EBF698F8BB19DF297F66AD91B18910DFC6E19323">>},
{<<"parse_trans">>, <<"07CD9577885F56362D414E8C4C4E6BDF10D43A8767ABB92D24CBE8B24C54888B">>},
{<<"prometheus">>, <<"6EDFBE928D271C7F657A6F2C46258738086584BD6CAE4A000B8B9A6009BA23A5">>},
{<<"prometheus_cowboy">>, <<"BA286BECA9302618418892D37BCD5DC669A6CC001F4EB6D6AF85FF81F3F4F34C">>},
{<<"prometheus_httpd">>, <<"0BBE831452CFDF9588538EB2F570B26F30C348ADAE5E95A7D87F35A5910BCF92">>},
{<<"quantile_estimator">>, <<"282A8A323CA2A845C9E6F787D166348F776C1D4A41EDE63046D72D422E3DA946">>},
{<<"ranch">>, <<"49FBCFD3682FAB1F5D109351B61257676DA1A2FDBE295904176D5E521A2DDFE5">>},
{<<"ssl_verify_fun">>, <<"BDB0D2471F453C88FF3908E7686F86F9BE327D065CC1EC16FA4540197EA04680">>},
{<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}]}

View File

@ -1,63 +0,0 @@
[
{cds, [
{ip, "::"},
{port, 8022},
{scrypt_opts, {16384, 8, 1}},
{storage, cds_storage_ets},
{session_cleaning, #{
interval => 3000,
batch_size => 5000,
session_lifetime => 3600
}},
{recrypting, #{
interval => 3000,
batch_size => 5000
}},
{keyring, #{
url => <<"http://kds:8023">>,
ssl_options => []
}},
{keyring_fetch_interval, 1000},
{health_check, #{
disk => {erl_health, disk, ["/", 99]},
memory => {erl_health, cg_memory, [99]},
service => {erl_health, service, [<<"cds">>]}
}}
]},
{scoper, [
{storage, scoper_storage_logger}
]},
{kernel, [
{logger_sasl_compatible, false},
{logger_level, debug},
{logger, [
{handler, default, logger_std_h, #{
config => #{
type => {file, "/var/log/cds/console.json"}
},
formatter => {logger_logstash_formatter, #{}}
}}
]}
]},
{os_mon, [
{disksup_posix_only, true}
]},
{how_are_you, [
{metrics_publishers, [
% {hay_statsd_publisher, #{
% key_prefix => <<"cds.">>,
% host => "localhost",
% port => 8125
% }}
]}
]},
{snowflake, [
{max_backward_clock_moving, 1000}, % 1 second
{machine_id, hostname_hash}
]}
].

View File

@ -49,11 +49,12 @@
% Should be greater than any other timeouts
idle_timeout => infinity
}},
{max_cache_size, 52428800}, % 50Mb
% 50Mb
{max_cache_size, 52428800},
{health_check, #{
disk => {erl_health, disk, ["/", 99]},
memory => {erl_health, cg_memory, [99]},
service => {erl_health, service, [<<"dominant">>]}
disk => {erl_health, disk, ["/", 99]},
memory => {erl_health, cg_memory, [99]},
service => {erl_health, service, [<<"dominant">>]}
}},
{services, #{
automaton => #{
@ -77,7 +78,8 @@
]},
{snowflake, [
{max_backward_clock_moving, 1000}, % 1 second
% 1 second
{max_backward_clock_moving, 1000},
{machine_id, hostname_hash}
]}
].

View File

@ -1,60 +0,0 @@
[
{kernel, [
{logger_level, info},
{logger, [
{handler, default, logger_std_h, #{
level => debug,
config => #{
type => {file, "/var/log/identification/console.json"},
sync_mode_qlen => 2000,
drop_mode_qlen => 2000,
flush_qlen => 3000
},
formatter => {logger_logstash_formatter, #{}}
}}
]}
]},
{scoper, [
{storage, scoper_storage_logger}
]},
{identification, [
{ip, "::"},
{port, 8022},
{protocol_opts, #{
request_timeout => 5000
}},
{handlers, #{
identification => #{
path => <<"/v1/identification">>
},
identification_judge => #{
path => <<"/v1/identification-judge">>
}
}},
{machines, #{
identity => #{
path => <<"/v1/stateproc/identity">>
},
claim => #{
path => <<"/v1/stateproc/identity-claim">>
}
}},
{clients, #{
automaton => #{
url => <<"http://machinegun:8022/v1/automaton">>,
namespaces => #{
identity => <<"identity">>,
claim => <<"identity-claim">>
}
},
proof_service => #{
url => <<"http://uprid:8080/v1/api">>
},
proof_storage => #{
url => <<"http://cds:8022/v1/identity_document_storage">>
}
}}
]}
].

View File

@ -1,86 +0,0 @@
[
{kds, [
{ip, "::"},
{management_port, 8022},
{storage_port, 8023},
{management_transport_opts, #{}},
{storage_transport_opts, #{}},
{protocol_opts, #{
request_timeout => 60000
}},
{new_key_security_parameters, #{
deduplication_hash_opts => #{
n => 16384,
r => 8,
p => 1
}
}},
{shutdown_timeout, 0},
{keyring_storage, kds_keyring_storage_file},
{keyring_storage_opts, #{
keyring_path => "/var/lib/kds/keyring"
}},
{health_check, #{
disk => {erl_health, disk, ["/", 99]},
memory => {erl_health, cg_memory, [99]},
service => {erl_health, service, [<<"kds">>]}
}},
{keyring_rotation_lifetime, 60000},
{keyring_initialize_lifetime, 180000},
{keyring_rekeying_lifetime, 180000},
{keyring_unlock_lifetime, 60000},
{shareholders, #{
<<"1">> => #{
owner => <<"ndiezel">>,
public_keys => #{
enc =>
<<"
{
\"use\": \"enc\",
\"kty\": \"RSA\",
\"kid\": \"KUb1fNMc5j9Ei_IV3DguhJh5UOH30uvO7qXq13uevnk\",
\"alg\": \"RSA-OAEP-256\",
\"n\": \"2bxkamUQjD4CN8rcq5BfNLJmRmosb-zY7ajPBJqtiLUTcqym23OkUIA1brBg34clmU2ZQmtd3LWi5kVJk_wr4WsMG_78jHK3wQA-HRhY4WZDZrULTsi4XWpNSwL4dCml4fs536RKy_TyrnpiXg0ug4JVVaEeo7VIZ593mVhCxC8Ev6FK8tZ2HGGOerUXLpgQdhcp9UwaI_l7jgoWNp1f7SuBqv1mfiw4ziC1yvwyXHTKy-37LjLmVB9EVyjqpkwZgzapaOvHc1ABqJpdOrUh-PyOgq-SduqSkMrvqZEdUeR_KbFVxqbxqWJMrqkl2HOJxOla9cHRowg5ObUBjeMoaTJfqie3t6uRUsFEFMzhIyvo6QMYHooxIdOdwpZ4tpzML6jv9o5DPtN375bKzy-UsjeshYbvad1mbrcxc8tYeiQkDZEIM0KeOdHm5C6neEyY6oF4s1vSYBNCnhE5O-R9dmp8Sk5KEseEkOH5u4G2RsIXBA9z1OTDoy6qF21EvRCGzsGfExfkmPAtzbnS-EHHxbMUiio0ZJoZshYo8dwJY6vSN7UsXBgW1v7GvIF9VsfzRmgkl_3rdemYy28DJKC0U2yufePcA3nUJEhtR3UO_tIlHxZvlDSX5eTx4vs5VkFfujNSiPsgH0PEeXABGBFbal7QxU1u0XHXIFwhW5cM8Fs\",
\"e\": \"AQAB\"
}
">>,
sig =>
<<"
{
\"crv\":\"Ed25519\",
\"kid\":\"K3ZpHNJw3IZYu4fefhImUtB47eSBD4nRmpjWIoGukyg\",
\"kty\":\"OKP\",
\"x\":\"hqoiLZvfBzgtFQop3mBzUACee1ycgaT3tJIcKQ2Ndjc\"
}
">>
}
}
}}
]},
{scoper, [
{storage, scoper_storage_logger}
]},
{kernel, [
{logger_sasl_compatible, false},
{logger_level, debug},
{logger, [
{handler, default, logger_std_h, #{
config => #{
type => {file, "/var/log/kds/console.json"}
},
formatter => {logger_logstash_formatter, #{}}
}}
]}
]},
{os_mon, [
{disksup_posix_only, true}
]},
{snowflake, [
{max_backward_clock_moving, 1000}, % 1 second
{machine_id, hostname_hash}
]}
].

View File

@ -3,94 +3,79 @@ erlang:
secret_cookie_file: "/opt/machinegun/etc/cookie"
namespaces:
# Party
party:
processor:
url: http://party-management:8022/v1/stateproc/party
domain-config:
processor:
url: http://dominant:8022/v1/stateproc
# Party
party:
processor:
url: http://party-management:8022/v1/stateproc/party
domain-config:
processor:
url: http://dominant:8022/v1/stateproc
# Identification
identity:
processor:
url: http://identification:8022/v1/stateproc/identity
identity-claim:
processor:
url: http://identification:8022/v1/stateproc/identity-claim
# Fistful
ff/identity:
event_sinks:
machine:
type: machine
machine_id: ff/identity
processor:
url: http://fistful-server:8022/v1/stateproc/ff/identity
ff/wallet_v2:
event_sinks:
machine:
type: machine
machine_id: ff/wallet_v2
processor:
url: http://fistful-server:8022/v1/stateproc/ff/wallet_v2
ff/source_v1:
event_sinks:
machine:
type: machine
machine_id: ff/source_v1
processor:
url: http://fistful-server:8022/v1/stateproc/ff/source_v1
ff/deposit_v1:
event_sinks:
machine:
type: machine
machine_id: ff/deposit_v1
processor:
url: http://fistful-server:8022/v1/stateproc/ff/deposit_v1
ff/destination_v2:
event_sinks:
machine:
type: machine
machine_id: ff/destination_v2
processor:
url: http://fistful-server:8022/v1/stateproc/ff/destination_v2
ff/withdrawal_v2:
event_sinks:
machine:
type: machine
machine_id: ff/withdrawal_v2
processor:
url: http://fistful-server:8022/v1/stateproc/ff/withdrawal_v2
ff/withdrawal/session_v2:
event_sinks:
machine:
type: machine
machine_id: ff/withdrawal/session_v2
processor:
url: http://fistful-server:8022/v1/stateproc/ff/withdrawal/session_v2
ff/w2w_transfer_v1:
event_sinks:
machine:
type: machine
machine_id: ff/w2w_transfer_v1
processor:
url: http://fistful-server:8022/v1/stateproc/ff/w2w_transfer_v1
# Fistful
ff/identity:
event_sinks:
machine:
type: machine
machine_id: ff/identity
processor:
url: http://fistful-server:8022/v1/stateproc/ff/identity
ff/wallet_v2:
event_sinks:
machine:
type: machine
machine_id: ff/wallet_v2
processor:
url: http://fistful-server:8022/v1/stateproc/ff/wallet_v2
ff/source_v1:
event_sinks:
machine:
type: machine
machine_id: ff/source_v1
processor:
url: http://fistful-server:8022/v1/stateproc/ff/source_v1
ff/deposit_v1:
event_sinks:
machine:
type: machine
machine_id: ff/deposit_v1
processor:
url: http://fistful-server:8022/v1/stateproc/ff/deposit_v1
ff/destination_v2:
event_sinks:
machine:
type: machine
machine_id: ff/destination_v2
processor:
url: http://fistful-server:8022/v1/stateproc/ff/destination_v2
ff/withdrawal_v2:
event_sinks:
machine:
type: machine
machine_id: ff/withdrawal_v2
processor:
url: http://fistful-server:8022/v1/stateproc/ff/withdrawal_v2
ff/withdrawal/session_v2:
event_sinks:
machine:
type: machine
machine_id: ff/withdrawal/session_v2
processor:
url: http://fistful-server:8022/v1/stateproc/ff/withdrawal/session_v2
ff/w2w_transfer_v1:
event_sinks:
machine:
type: machine
machine_id: ff/w2w_transfer_v1
processor:
url: http://fistful-server:8022/v1/stateproc/ff/w2w_transfer_v1
ff/sequence:
processor:
url: http://fistful-server:8022/v1/stateproc/ff/sequence
ff/external_id:
processor:
url: http://fistful-server:8022/v1/stateproc/ff/external_id
# Bender
bender_generator:
processor:
url: http://bender:8022/v1/stateproc/bender_generator
bender_sequence:
processor:
url: http://bender:8022/v1/stateproc/bender_sequence
# Bender
bender_generator:
processor:
url: http://bender:8022/v1/stateproc/bender_generator
bender_sequence:
processor:
url: http://bender:8022/v1/stateproc/bender_sequence
storage:
type: memory