Skip to content

Commit

Permalink
Merge pull request #328 from sumesh-aot/event_listener
Browse files Browse the repository at this point in the history
Entity event listener to update transaction references
  • Loading branch information
sumesh-aot authored Sep 11, 2020
2 parents 24b4dc9 + 4384ae7 commit 8c13058
Show file tree
Hide file tree
Showing 45 changed files with 2,796 additions and 37 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/events-listener-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Events Listener Queue PR CI

on:
pull_request:
branches:
- development
paths:
- "queue_services/events-listener/**"

jobs:
events-listener-queue_service-check:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
working-directory: ./queue_services/events-listener

if: github.repository == 'bcgov/sbc-pay'
env:
DATABASE_TEST_URL: "postgresql://postgres:postgres@localhost:5432/postgres"
TEST_NATS_DOCKER: "YES"
STAN_CLUSTER_NAME: "test-cluster"

strategy:
matrix:
python-version: [3.8]
services:
postgres:
image: postgres:11
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
# needed because the postgres container does not provide a healthcheck
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements/dev.txt
- name: Lint with pylint
run: |
pylint --rcfile=setup.cfg --disable=C0301,W0511 src/events_listener
# - name: Lint with flake8
# run: |
# flake8 src/events_listener tests
- name: Test with pytest
run: |
pip install .
export PYTHONPATH=./src/
pytest
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
file: ./queue_services/events-listener/coverage.xml
flags: events_listener
name: codecov-events-listener
fail_ci_if_error: true
60 changes: 60 additions & 0 deletions .github/workflows/events-listener-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Events Listener Queue DEV CD

on:
push:
branches:
- development
paths:
- "queue_services/events-listener/**"

env:
IMAGE_NAME: events-listener
TAG_NAME: dev

jobs:
events-listener-dev:
runs-on: ubuntu-latest
if: github.repository == 'bcgov/sbc-pay'
steps:
- uses: actions/checkout@v2
- name: Install tools
run: |
./scripts/install_tools.sh
oc version
op --version
- name: Login Openshift
working-directory: ./queue_services/events-listener
run: |
oc login ${{ secrets.OPENSHIFT_LOGIN_REGISTRY }} --token=${{ secrets.OPENSHIFT_SA_TOKEN }}
- name: Set Deployment Environment Variables
working-directory: .
run: |
vaults='[{ "vault": "shared", "application": ["nats"]}, {"vault": "relationship","application": ["postgres-pay", "events-listener"]}]'
./scripts/1pass.sh ${{ secrets.op_parameters }} -m "secret" -e "${TAG_NAME}" -v "${vaults}" -a "${IMAGE_NAME}-${TAG_NAME}" -n ${{ secrets.OPENSHIFT_REPOSITORY_DEV}}
- name: Log into registry
run: echo "${{ secrets.OPENSHIFT_SA_TOKEN }}" | docker login ${{ secrets.OPENSHIFT_DOCKER_REGISTRY }} -u ${{ secrets.OPENSHIFT_SA_NAME}} --password-stdin
- name: Build image
working-directory: ./queue_services/events-listener
run: docker build . --file Dockerfile --tag image
- name: Push image
working-directory: ./queue_services/events-listener
run: |
IMAGE_ID=${{ secrets.OPENSHIFT_DOCKER_REGISTRY }}/${{ secrets.OPENSHIFT_REPOSITORY_TOOLS }}/$IMAGE_NAME
docker tag image $IMAGE_ID:latest
docker push $IMAGE_ID:latest
docker image tag $IMAGE_ID:latest $IMAGE_ID:$TAG_NAME
docker push $IMAGE_ID:$TAG_NAME
- name: Rollout new deployment
working-directory: ./queue_services/events-listener
run: |
oc rollout status dc/$IMAGE_NAME-${TAG_NAME} -n ${{ secrets.OPENSHIFT_REPOSITORY_DEV}} -w
- name: Rocket.Chat Notification
uses: RocketChat/Rocket.Chat.GitHub.Action.Notification@master
if: failure()
with:
type: ${{ job.status }}
job_name: "*Events Listener Build and Deploy to ${{env.TAG_NAME}}*"
channel: "#registries-bot"
url: ${{ secrets.ROCKETCHAT_WEBHOOK }}
commit: true
token: ${{ secrets.GITHUB_TOKEN }}
59 changes: 59 additions & 0 deletions .github/workflows/events-listener-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Events Listener Queue TEST CD

on:
push:
branches:
- master
paths:
- "queue_services/events-listener/**"
env:
IMAGE_NAME: events-listener
TAG_NAME: test

jobs:
events-listener-test:
runs-on: ubuntu-latest
if: github.repository == 'bcgov/sbc-pay'
steps:
- uses: actions/checkout@v2
- name: Install tools
run: |
./scripts/install_tools.sh
oc version
op --version
- name: Login Openshift
working-directory: ./queue_services/events-listener
run: |
oc login ${{ secrets.OPENSHIFT_LOGIN_REGISTRY }} --token=${{ secrets.OPENSHIFT_SA_TOKEN }}
- name: Set Deployment Environment Variables
working-directory: .
run: |
vaults='[{ "vault": "shared", "application": [nats"]}, {"vault": "relationship","application": ["postgres-pay", "events-listener"]}]'
./scripts/1pass.sh ${{ secrets.op_parameters }} -m "secret" -e "${TAG_NAME}" -v "${vaults}" -a "${IMAGE_NAME}-${TAG_NAME}" -n ${{ secrets.OPENSHIFT_REPOSITORY_TEST }}
- name: Log into registry
run: echo "${{ secrets.OPENSHIFT_SA_TOKEN }}" | docker login ${{ secrets.OPENSHIFT_DOCKER_REGISTRY }} -u ${{ secrets.OPENSHIFT_SA_NAME}} --password-stdin
- name: Build image
working-directory: ./queue_services/events-listener
run: docker build . --file Dockerfile --tag image
- name: Push image
working-directory: ./queue_services/events-listener
run: |
IMAGE_ID=${{ secrets.OPENSHIFT_DOCKER_REGISTRY }}/${{ secrets.OPENSHIFT_REPOSITORY_TOOLS }}/$IMAGE_NAME
docker tag image $IMAGE_ID:latest
docker push $IMAGE_ID:latest
docker image tag $IMAGE_ID:latest $IMAGE_ID:$TAG_NAME
docker push $IMAGE_ID:$TAG_NAME
- name: Rollout new deployment
working-directory: ./queue_services/events-listener
run: |
oc rollout status dc/$IMAGE_NAME-${TAG_NAME} -n ${{ secrets.OPENSHIFT_REPOSITORY_TEST}} -w
- name: Rocket.Chat Notification
uses: RocketChat/Rocket.Chat.GitHub.Action.Notification@master
if: failure()
with:
type: ${{ job.status }}
job_name: "*Events Listener Queue Build and Deploy to ${{env.TAG_NAME}}*"
channel: "#registries-bot"
url: ${{ secrets.ROCKETCHAT_WEBHOOK }}
commit: true
token: ${{ secrets.GITHUB_TOKEN }}
6 changes: 6 additions & 0 deletions codecov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ coverage:
- payapi
- bcolapi
- reportapi
- eventlistenerqueue

ignore:
- "^/tests/**/*" # ignore test harness code
Expand Down Expand Up @@ -47,3 +48,8 @@ flags:
paths:
- report-api/src/api
carryforward: true

eventlistenerqueue
paths:
- queue_services/events-listener/src/events_listener
carryforward: true
4 changes: 2 additions & 2 deletions pay-api/src/pay_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
from sbc_common_components.exception_handling.exception_handler import ExceptionHandler # noqa: I001
from sbc_common_components.utils.camel_case_response import convert_to_camel

import config
from config import _Config
import pay_api.config as config
from pay_api.config import _Config
from pay_api.models import db, ma
from pay_api.utils.auth import jwt
from pay_api.utils.cache import cache
Expand Down
77 changes: 44 additions & 33 deletions pay-api/config.py → pay-api/src/pay_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""All of the configuration for the service is captured here. All items are loaded, or have Constants defined here that are loaded into the Flask configuration. All modules and lookups get their configuration from the Flask config, rather than reading environment variables directly or by accessing this configuration directly.
"""All of the configuration for the service is captured here.
All items are loaded,
or have Constants defined here that are loaded into the Flask configuration.
All modules and lookups get their configuration from the Flask config,
rather than reading environment variables directly or by accessing this configuration directly.
"""

import json
import os
import sys

Expand All @@ -24,16 +28,16 @@
load_dotenv(find_dotenv())

CONFIGURATION = {
'development': 'config.DevConfig',
'testing': 'config.TestConfig',
'production': 'config.ProdConfig',
'default': 'config.ProdConfig',
'migration': 'config.MigrationConfig',
'development': 'pay_api.config.DevConfig',
'testing': 'pay_api.config.TestConfig',
'production': 'pay_api.config.ProdConfig',
'default': 'pay_api.config.ProdConfig',
'migration': 'pay_api.config.MigrationConfig',
}


def get_named_config(config_name: str = 'production'):
"""Return the configuration object based on the name
"""Return the configuration object based on the name.
:raise: KeyError: if an unknown configuration is requested
"""
Expand All @@ -60,8 +64,8 @@ def _get_config(config_key: str, **kwargs):
return value


class _Config(object): # pylint: disable=too-few-public-methods
"""Base class configuration that should set reasonable defaults for all the other configurations. """
class _Config(): # pylint: disable=too-few-public-methods
"""Base class configuration that should set reasonable defaults for all the other configurations."""

PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))

Expand Down Expand Up @@ -153,6 +157,8 @@ class _Config(object): # pylint: disable=too-few-public-methods


class DevConfig(_Config): # pylint: disable=too-few-public-methods
"""Dev config."""

TESTING = False
DEBUG = True

Expand Down Expand Up @@ -189,33 +195,37 @@ class TestConfig(_Config): # pylint: disable=too-few-public-methods
JWT_OIDC_TEST_JWKS_URI = _get_config('JWT_OIDC_TEST_JWKS_URI', default=None)

JWT_OIDC_TEST_KEYS = {
"keys": [
'keys': [
{
"kid": "sbc-auth-web",
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"n": "AN-fWcpCyE5KPzHDjigLaSUVZI0uYrcGcc40InVtl-rQRDmAh-C2W8H4_Hxhr5VLc6crsJ2LiJTV_E72S03pzpOOaaYV6-TzAjCou2GYJIXev7f6Hh512PuG5wyxda_TlBSsI-gvphRTPsKCnPutrbiukCYrnPuWxX5_cES9eStR",
"e": "AQAB"
'kid': 'sbc-auth-web',
'kty': 'RSA',
'alg': 'RS256',
'use': 'sig',
'n': 'AN-fWcpCyE5KPzHDjigLaSUVZI0uYrcGcc40InVtl-rQRDmAh-C2W8H4_Hxhr5VLc6crsJ2LiJTV_E72S03pzpOOaaYV6-'
'TzAjCou2GYJIXev7f6Hh512PuG5wyxda_TlBSsI-gvphRTPsKCnPutrbiukCYrnPuWxX5_cES9eStR',
'e': 'AQAB'
}
]
}

JWT_OIDC_TEST_PRIVATE_KEY_JWKS = {
"keys": [
'keys': [
{
"kid": "sbc-auth-web",
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"n": "AN-fWcpCyE5KPzHDjigLaSUVZI0uYrcGcc40InVtl-rQRDmAh-C2W8H4_Hxhr5VLc6crsJ2LiJTV_E72S03pzpOOaaYV6-TzAjCou2GYJIXev7f6Hh512PuG5wyxda_TlBSsI-gvphRTPsKCnPutrbiukCYrnPuWxX5_cES9eStR",
"e": "AQAB",
"d": "C0G3QGI6OQ6tvbCNYGCqq043YI_8MiBl7C5dqbGZmx1ewdJBhMNJPStuckhskURaDwk4-8VBW9SlvcfSJJrnZhgFMjOYSSsBtPGBIMIdM5eSKbenCCjO8Tg0BUh_xa3CHST1W4RQ5rFXadZ9AeNtaGcWj2acmXNO3DVETXAX3x0",
"p": "APXcusFMQNHjh6KVD_hOUIw87lvK13WkDEeeuqAydai9Ig9JKEAAfV94W6Aftka7tGgE7ulg1vo3eJoLWJ1zvKM",
"q": "AOjX3OnPJnk0ZFUQBwhduCweRi37I6DAdLTnhDvcPTrrNWuKPg9uGwHjzFCJgKd8KBaDQ0X1rZTZLTqi3peT43s",
"dp": "AN9kBoA5o6_Rl9zeqdsIdWFmv4DB5lEqlEnC7HlAP-3oo3jWFO9KQqArQL1V8w2D4aCd0uJULiC9pCP7aTHvBhc",
"dq": "ANtbSY6njfpPploQsF9sU26U0s7MsuLljM1E8uml8bVJE1mNsiu9MgpUvg39jEu9BtM2tDD7Y51AAIEmIQex1nM",
"qi": "XLE5O360x-MhsdFXx8Vwz4304-MJg-oGSJXCK_ZWYOB_FGXFRTfebxCsSYi0YwJo-oNu96bvZCuMplzRI1liZw"
'kid': 'sbc-auth-web',
'kty': 'RSA',
'alg': 'RS256',
'use': 'sig',
'n': 'AN-fWcpCyE5KPzHDjigLaSUVZI0uYrcGcc40InVtl-rQRDmAh-C2W8H4_Hxhr5VLc6crsJ2LiJTV_E72S03pzpOOaaYV6-'
'TzAjCou2GYJIXev7f6Hh512PuG5wyxda_TlBSsI-gvphRTPsKCnPutrbiukCYrnPuWxX5_cES9eStR',
'e': 'AQAB',
'd': 'C0G3QGI6OQ6tvbCNYGCqq043YI_8MiBl7C5dqbGZmx1ewdJBhMNJPStuckhskURaDwk4-'
'8VBW9SlvcfSJJrnZhgFMjOYSSsBtPGBIMIdM5eSKbenCCjO8Tg0BUh_'
'xa3CHST1W4RQ5rFXadZ9AeNtaGcWj2acmXNO3DVETXAX3x0',
'p': 'APXcusFMQNHjh6KVD_hOUIw87lvK13WkDEeeuqAydai9Ig9JKEAAfV94W6Aftka7tGgE7ulg1vo3eJoLWJ1zvKM',
'q': 'AOjX3OnPJnk0ZFUQBwhduCweRi37I6DAdLTnhDvcPTrrNWuKPg9uGwHjzFCJgKd8KBaDQ0X1rZTZLTqi3peT43s',
'dp': 'AN9kBoA5o6_Rl9zeqdsIdWFmv4DB5lEqlEnC7HlAP-3oo3jWFO9KQqArQL1V8w2D4aCd0uJULiC9pCP7aTHvBhc',
'dq': 'ANtbSY6njfpPploQsF9sU26U0s7MsuLljM1E8uml8bVJE1mNsiu9MgpUvg39jEu9BtM2tDD7Y51AAIEmIQex1nM',
'qi': 'XLE5O360x-MhsdFXx8Vwz4304-MJg-oGSJXCK_ZWYOB_FGXFRTfebxCsSYi0YwJo-oNu96bvZCuMplzRI1liZw'
}
]
}
Expand Down Expand Up @@ -244,9 +254,9 @@ class TestConfig(_Config): # pylint: disable=too-few-public-methods

SERVER_NAME = 'auth-web.dev.com'

REPORT_API_BASE_URL = "http://localhost:8080/reports-api/api/v1/reports"
REPORT_API_BASE_URL = 'http://localhost:8080/reports-api/api/v1/reports'

AUTH_API_ENDPOINT = "http://localhost:8080/auth-api/"
AUTH_API_ENDPOINT = 'http://localhost:8080/auth-api/'

NATS_SUBJECT = 'entity.filing.test'

Expand Down Expand Up @@ -278,7 +288,8 @@ class ProdConfig(_Config): # pylint: disable=too-few-public-methods


class MigrationConfig(): # pylint: disable=too-few-public-methods
"""Config for db migration """
"""Config for db migration."""

TESTING = False
DEBUG = True

Expand Down
5 changes: 5 additions & 0 deletions pay-api/src/pay_api/models/credit_payment_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ def find_by_corp_number_and_corp_type_and_auth_account_id(cls, corp_number: str,

return query.join(PaymentAccount).filter(PaymentAccount.auth_account_id == str(auth_account_id)).one_or_none()

@classmethod
def find_by_corp_number(cls, corp_number: str):
"""Find all payment accounts by corp number."""
return cls.query.filter_by(corp_number=corp_number).all()


class CreditPaymentAccountSchema(ma.ModelSchema): # pylint: disable=too-many-ancestors
"""Main schema used to serialize the Credit Payment System Account."""
Expand Down
5 changes: 5 additions & 0 deletions pay-api/src/pay_api/models/internal_payment_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ def find_by_corp_number_and_corp_type_and_account_id(cls, corp_number: str, corp

return account

@classmethod
def find_by_corp_number(cls, corp_number: str):
"""Find all payment accounts by corp number."""
return cls.query.filter_by(corp_number=corp_number).all()


class InternalPaymentAccountSchema(ma.ModelSchema): # pylint: disable=too-many-ancestors
"""Main schema used to serialize the Internal Payment System Account."""
Expand Down
5 changes: 5 additions & 0 deletions pay-api/src/pay_api/models/invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ def update_invoices_for_revenue_updates(cls, fee_distribution_id: int):
db.session.bulk_save_objects(invoices)
cls.commit()

@classmethod
def find_by_business_identifier(cls, business_identifier: str):
"""Find all payment accounts by business_identifier."""
return cls.query.filter_by(business_identifier=business_identifier).all()


class InvoiceSchema(AuditSchema, BaseSchema): # pylint: disable=too-many-ancestors
"""Main schema used to serialize the invoice."""
Expand Down
Loading

0 comments on commit 8c13058

Please sign in to comment.