diff --git a/.gitignore b/.gitignore index 0526ddf..8a40dd0 100644 --- a/.gitignore +++ b/.gitignore @@ -161,9 +161,28 @@ cython_debug/ #Helm charts/ +Chart.lock #gitrepos +vnext/ mojaloop/ ph/ fineract/ -apps/ \ No newline at end of file +apps/ +repos/ + +# OS generated files # +###################### +.DS_Store +.settings +.Spotlight-V100 +.Trashes +.terraform +ehthumbs.db +Thumbs.db +.project +.cproject +.pydevproject +.idea +*.swp +sds_* \ No newline at end of file diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e69de29..bd92a2d 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -0,0 +1,21 @@ +## Mifos Gazelle Architecture + +Mifos Gazelle is primarily a deployment tool it allows for deployment of multiple DPGs. This architecture document outlines the architecture of Mifos Gazelle it does not outline the architecture of the DPGs it deploys you should refer to their architecture documentation for this. + + +## Dependencies + + + +## DPGs deployable + +- MifosX vx.x.x. including Apache Fineract vx.x.x +- Payment Hub Enterprise Edition (PHEE) v1.13.0 +- Mojaloop vNext Beta1 + + +## Languages and modules used + + + +This architecture document is currently a work in progress \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cfd9e01..d7b6693 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,47 +1,47 @@ ---- +# Contributing to Mifos Gazelle + Thank you for your interest in contributing to the Mifos Gazelle repository! Your contributions are important and will help to improve the project for everyone. Before you begin, please consider the guidelines below. -Thank you for your interest in contributing to the Mojafos repository! Your contributions are important and will help to improve the project for everyone. Before you begin, please consider the guidelines below. +## Branches + +* Master - contains released versions of the Mifos Gazelle product +* Dev - Where all contributions should be raised as PRs +* ... - Individual branches used by contributors for pre-staging or testing + +Please always contribute to Dev. We then compile accepted PRs from Dev into releases within the community and publish these every 3 months. ## Getting Started - Make sure you have [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) installed on your machine. - Fork the repository and clone it locally. - - ``` - git clone https://github.com/openMF/mojafos.git - ``` - + +git clone --branch dev https://github.com/openMF/mifos-gazelle.git + + - Create a new branch for your contributions - - ``` - git checkout -b feature-branch-name - ``` +git checkout -b feature-branch-name + ## Making Changes -- Before making changes, ensure that you're working on the latest version of the `master` branch - - ``` - git pull origin master - ``` +- Before making changes, ensure that you're working on the latest version of the `dev` branch + +git pull origin dev + ## Committing Changes - Stage your changes: - - ``` - git add file-name(s) - ``` + +git add file-name(s) + - Commit your changes with a descriptive message: - - ``` - git commit -m "Add feature" - ``` + +git commit -m "Add feature" + - Push your changes to your forked repository: - - ``` - git push origin feature-branch-name - ``` + +git push origin feature-branch-name + ## Submitting a Pull Request @@ -51,18 +51,23 @@ Thank you for your interest in contributing to the Mojafos repository! Your cont - After submitting your PR, our team will review your changes. - Address any feedback or requested changes promptly. -- Once approved, your PR will be merged into the `master` branch. +- Once approved, your PR will be merged into the `dev` branch. +- Every 3 months we will release from the 'dev' branch to the 'master' branch ## Finding a Task -- Check out the issues [here](https://github.com/openMF/mojafos/issues) -- Have a look at the README.md Can it be improved? Do you see any typos? You may initiate a PR. + +- Check out the issues [here](https://github.com/openMF/mifos-gazelle/issues) +- Join Mifos Slack +- Subscribe to the #mifos-gazelle slack channel (used for support on release versions) +- Request to join the Mifos-gazelle-dev slack channel +- Have a look at the README.md and our other documentation in /docs/ Can it be improved? Do you see any typos? You may initiate a PR. ## Reporting Issues -If you find any bugs or have recommendations for improvements, please feel free to [open an issue](https://github.com/openMF/mojafos/issues) with a detailed explanation of changes. + +If you find any bugs or have recommendations for improvements, please feel free to [open an issue](https://github.com/openMF/mifos-gazelle/issues) with a detailed explanation of changes. ## Contact -- For further assistance or questions regarding contributions, feel free to join our Slack channel [here](https://mifos.slack.com/ssb/redirect) -Thank you for contributing to [Mojafos](https://github.com/openMF/mojafos)! We look forward to your contributions. +- For further assistance or questions regarding contributions, feel free to join our Slack channel [here](https://mifos.slack.com/ssb/redirect) ---- +Thank you again for your interest in [Mifos Gazelle](https://github.com/openMF/mifos-gazelle)! We look forward to your contributions. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a612ad9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/README.md b/README.md index c5e9773..02b3c4c 100644 --- a/README.md +++ b/README.md @@ -1,206 +1,54 @@ -# A Deployable Package for Mifos/Fineract, Payment Hub EE, and Mojaloop (Mojafos) - -## Introduction - -The deployable package is intended to simplify and automate the deployment process of three software applications, namely Mojaloop, PaymentHub, and Fineract, onto a Kubernetes cluster. This package aims to streamline the deployment process, reduce manual errors, and enable someone to demo how these softwares can work together. - - -## Pre-requisites -Make sure you have the following before you go through this guide. -- You should be running Ubuntu 20.04 LTS on the machine where you are running this script -- 32GB of RAM -- 30GB+ free space in your home directory - -# Quick Start -> NOTE: The deployment made by this script is meant for demo purposes and not for production - -## Clone the repository -To use Mojafos, you need to clone the repository to be able to run the software scripts. -Clone the repository into a directory of your choice. -After cloning the repository, you need to change the directory into the cloned repository. -``` -git clone https://github.com/openMF/mojafos.git -``` - -Inside the directory run the following command to execute the script. - -```bash -sudo ./run.sh -u $USER -m deploy -d true -a all -f 2 -e local -``` -### Options -- `-u` This is used to pass in the user the script should use to execute it's commands. The value passed in is `$USER` which the current user of the shell -- `-m` This option specifies the mode in which the script should execute. The available values are - - `deploy` - Deploy applications - - `cleanup` - Undo what deploy did and clean up resources -- `-d` This flag tells the sccript whether to execute in verbose mode or not. The available values are : - - true - Output should provide as much information as possible - - false - Output should not be minimal -- `-a` This flag tells the script in which mode the depoloyment should be made. It is an optional flag therefore if it is not provided,the default deployment mode is all apps -- `-f` This flag specifies the number of fineract instances to deployed. If not specified, the default number of instances is 2 -- `-e` This flag specifies the environment into which the applications should be deployed. If not specified, it will deploy into k3s locally. - - -# App Deployment Modes -a -There are three modes of deployment currently supported by Mojafos. This is relevant for the -a option -- Only Mojaloop `moja` -- Only Fineract `fin` -- Only Payment Hub `ph` -- All Apps `all` - - -# Target Environment -e -You can set the environment into which the applications should be deployed by setting the -e argument at the point of executing the script. - -To use a remote kubernetes cluster, use the value `remote` and to create a local k8s cluster, use `local` ->Currently the tool is only tested on local kubernetes deployments but work is being done to test it on - - -After the script has successfully executed it will print the following output - -``` -======================================================================== -Thank you for installing Mojaloop, Paymenthub and Fineract using Mojafos -======================================================================== - - -TESTING -sudo ./run -u $USER -m test ml #For testing mojaloop -sudo ./run -u $USER -m test ph #For testing payment hub -sudo ./run -u $USER -m test fin #For testing fineract - - - -CHECK DEPLOYMENTS USING kubectl -kubectl get pods -n mojaloop #For testing mojaloop -kubectl get pods -n paymenthub #For testing paymenthub -kubectl get pods -n fineract-n #For testing fineract. n is a number of a fineract instance - - -Copyright © 2023 The Mifos Initiative -``` - -# USING THE DEPLOYED APPS - -## Accessing Mojaloop -The Mojafos scripts add the required host names to the 127.0.0.1 entry in the /etc/hosts of the "install system" i.e. the system where mojafos is run. To access Mojaloop from beyond this system it is necessary to:- - -ensure that http / port 80 is accessible on the install system. For instance if mojafos has installed Mojaloop onto a VM in the cloud then it will be necessary to ensure that the cloud network security rules allow inbound traffic on port 80 to that VM. - -## MacOs and Linux -add the hosts listed below to an entry for the external/public ip address of that install system in the /etc/hosts file of the laptop you are using. -For example if Mojaloop vNext is installed on a cloud VM with a public IP of 192.168.56.100 Then add an entry to your laptop's /etc/hosts similar to ... -```bash -192.168.56.100 vnextadmin.local elasticsearch.local kibana.local mongoexpress.local kafkaconsole.local fspiop.local bluebank.local greenbank.local -``` - -You should now be able to browse or curl to Mojaloop vNext admin url using http://vnextadmin you can also access the deloyed instances of the Mojaloop testing toolkit at http://bluebank.local and http://greenbank.local or access the mongo and kafka consoles. - -## Windows -- open Notepad -- Right click on Notepad and then Run as Administrator. -- allow this app to make changes to your device? type Yes. -- In Notepad, choose File then Open C:\Windows\System32\drivers\etc\hosts or click the address bar at the top and paste in the path and choose Enter. If you don’t see the host file in the /etc directory then select All files from the File name: drop-down list, then click on the hosts file. -- Add the IP from your VM or system and then add a host from the list of required hosts (see example below) -- flush your DNS cache. Click the Windows button and search command prompt, in the command prompt:- -```bash -ipconfig /flushdns -``` -Note you can only have one host per line so on windows 10 your hosts file should look something like: - -```bash -192.168.56.100 vnextadmin.local -192.168.56.100 elasticsearch.local -192.168.56.100 kibana.local -192.168.56.100 mongoexpress.local -192.168.56.100 kafkaconsole.local -192.168.56.100 fspiop.local -192.168.56.100 bluebank.local -192.168.56.100 greenbank.local -``` - -## Accessing Paymenthub - -To access paymenthub, you would follow a similar set of instructions just like for accessing mojaloop. - -## MacOs and Linux -add the hosts listed below to an entry for the external/public ip address of that install system in the /etc/hosts file of the laptop you are using. -For example if Paymenthub is installed on a cloud VM with a public IP of 192.168.56.100 Then add an entry to your laptop's /etc/hosts similar to ... - -```bash -192.168.56.100 ops.sandbox.mifos.io -``` - -You should now be able to browse or curl to Paymenthub Operations Web portal url using http://ops.sandbox.mifos.io . - -## Windows -- open Notepad -- Right click on Notepad and then Run as Administrator. -- allow this app to make changes to your device? type Yes. -- In Notepad, choose File then Open C:\Windows\System32\drivers\etc\hosts or click the address bar at the top and paste in the path and choose Enter. If you don’t see the host file in the /etc directory then select All files from the File name: drop-down list, then click on the hosts file. -- Add the IP from your VM or system and then add a host from the list of required hosts (see example below) -- flush your DNS cache. Click the Windows button and search command prompt, in the command prompt:- -```bash -ipconfig /flushdns -``` -Note you can only have one host per line so on windows 10 your hosts file should look something like: - -```bash -192.168.56.100 ops.sandbox.mifos.io -``` - -# Accessing Fineract -To access the fineract instances you just deployed using mojafos, you will needs to make similar edits to your hosts file configuration of your computer. - -## MacOs and Linux -add the hosts listed below to an entry for the external/public ip address of that install system in the /etc/hosts file of the laptop you are using. -For example if one of the instances of fineract is installed on a cloud VM with a public IP of 192.168.56.100 Then add an entry to your laptop's /etc/hosts similar to ... - -```bash -192.168.56.100 1-communityapp.sandbox.fynarfin.io 1-fynams.sandbox.fynarfin.io -``` -Notice the 1 at the begining of the host name. This is automatically prepended at the begining of a fineract instance's host names to form it's ingress domain name. - -If you set the number of fineract instances to 3, you would have domains ranging from `1-xxx.sandbox.fynarfin.io` to `3-xxx.fynarfin.io` - -After editing your hosts config with the number of fineract instances you deployed, you should now be able to browse or curl to Community App url using http://1-communityapp.sandbox.fynarfin.io and fineract at http://1-fynams.sandbox.fynarfin.io - -## Windows -- open Notepad -- Right click on Notepad and then Run as Administrator. -- allow this app to make changes to your device? type Yes. -- In Notepad, choose File then Open C:\Windows\System32\drivers\etc\hosts or click the address bar at the top and paste in the path and choose Enter. If you don’t see the host file in the /etc directory then select All files from the File name: drop-down list, then click on the hosts file. -- Add the IP from your VM or system and then add a host from the list of required hosts (see example below) -- flush your DNS cache. Click the Windows button and search command prompt, in the command prompt:- -```bash -ipconfig /flushdns -``` -Note you can only have one host per line so on windows 10 your hosts file should look something like: - -```bash -192.168.56.100 1-communityapp.sandbox.fynarfin.io -192.168.56.100 1-fynams.sandbox.fynarfin.io -``` -# Clean Up - -To tear down the infrastructure and all installed apps. You can run this command. - -```bash -sudo ./run.sh -u $USER -m cleanup -d true -e local -``` - -This will delete all resources in the created namespaces and if the kubernetes cluster is `k3s` it will delete it as well. - -Please note that cleaning up the resources will take some time. - -## CONTRIBUTION - -Find the contributing guidelines [here](./CONTRIBUTING.md) - -## CONCLUSION - -This tool is intended to simplify the deployment process for Payment Hub EE, Mojaloop and Fineract for testing purposes. - - - +# Mifos Gazelle +[![Mifos](https://img.shields.io/badge/Mifos-Gazelle-blue)](https://github.com/openMF/mifos-gazelle) +> Deployment utilities for MifosX (including Fineract backend), Payment Hub EE, and Mojaloop vNext (as of December 2024) + +## Quick Links +- [Mifos Gazelle README](docs/MIFOS-GAZELLE-README.md) - Deploy and run MifosX, Mifos Payment Hub EE and vNext +- [vNext README](docs/VNEXT-README.md) - Deploy and run vNext on its own + +## Overview +This repository contains the Mifos Gazelle deployment utilities + +## Getting Started +1. Review the [Mifos Gazelle README](docs/MIFOS-GAZELLE-README.md) for detailed usage and installation instructions +2. Follow the prerequisites and system requirements + + +## Repository Structure (wip) +``` +mifos-gazelle/ +├── ARCHITECTURE.md +├── CONTRIBUTING.md +├── LICENSE +├── README.md +├── config/ +│ ├── fin_values.yaml +│ ├── mifos-tenant-config.csv +│ ├── nginx_values.yaml +│ ├── ph_values.yaml +├── performance-testing/ +│ ├── paymentHubEE.jmx +│ └── README.md +├── postman/ +│ └── phee-example-batch-2.csv +├── repos/ +│ ├── mifosx/ +│ ├── ph_template/ +│ ├── phlabs/ +│ └── vnext/ +└── src/ + ├── environmentSetup + ├── deployer + ├── commandline/ + ├── configurationManager/ + └── utils/ + + +``` + +## Additional Resources +- [Contributing Guidelines](CONTRIBUTING.md) +- [License Information](LICENSE.md) +- [Architecture](ARCHITECTURE.md) diff --git a/config/mifos-tenant-config.csv b/config/mifos-tenant-config.csv new file mode 100644 index 0000000..e6eed59 --- /dev/null +++ b/config/mifos-tenant-config.csv @@ -0,0 +1,10 @@ +# Mifos Gazelle / Mifos tenants to add to the Mifos/fineract-server database +# this file is used by the mifos-gazelle/src/utils/update-mifos-tenants-setup.sh script +# note the default Mifos tenant of "default" is not touched by this script +# see https://fineract-academy.com/how-to-configure-multi-tenancy-for-fineract.html +# +# schema: +# tenant_id,tenant_identifier,tenant_name,tenant_timezone,db_host,db_port,db_name,db_user,db_password +# +2,greenbank,Greenbank tenant,Australia/Adelaide,mysql.infra.svc.cluster.local,3306,greenbank,root,mysqlpw +3,bluebank,Bluebank tenant,Australia/Adelaide,mysql.infra.svc.cluster.local,3306,bluebank,root,mysqlpw \ No newline at end of file diff --git a/config/nginx_values.yaml b/config/nginx_values.yaml new file mode 100644 index 0000000..546dcfe --- /dev/null +++ b/config/nginx_values.yaml @@ -0,0 +1,14 @@ +## nginx configuration +## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/index.md +## + +controller: + ingressClassResource: + name: nginx + # extraArgs: + # default-ssl-certificate: "paymenthub/toms-secret-2" + # config: + # hsts: "false" + # hsts-max-age: "0" + # hsts-include-subdomains: "false" + # hsts-preload: "false" \ No newline at end of file diff --git a/config/ph_values.yaml b/config/ph_values.yaml new file mode 100644 index 0000000..d7ac603 --- /dev/null +++ b/config/ph_values.yaml @@ -0,0 +1,411 @@ +ph-ee-engine: + global: + imagePullPolicy: IfNotPresent + tenants: "greenbank,bluebank" + DFSPIDS: "greenbank,bluebank" + + elasticsearch: + esJavaOpts: "-Xms512m -Xmx512m" + resources: + requests: + cpu: "100m" + memory: "128k" + limits: + cpu: "1000m" + memory: "1000M" + ingress: + enabled: true + className: nginx + pathtype: ImplementationSpecific + hosts: + - host: elastic-phee.mifos.gazelle.test + paths: + - path: / + + kibana: + elasticsearchHosts: http://ph-ee-elasticsearch:9200 + ingress: + enabled: true + className: nginx + pathtype: ImplementationSpecific + hosts: + - host: kibana-phee.mifos.gazelle.test + paths: + - path: / + + + # Operations app + operations_app: + image: docker.io/openmf/ph-ee-operations-app:v1.17.1 + ingress: + enabled: false + className: nginx + + operations_web: + # Note 'fred' and 'FRED' are development hooks as we continue to work on end to end integration flows. + enabled: true + image: docker.io/openmf/ph-ee-operations-web:dev1 + backend: + PH_OPS_BACKEND_SERVER_URL: https://ops.mifos.gazelle.test/api/v1 + PH_VOU_BACKEND_SERVER_URL: https://ops.mifos.gazelle.test/api/v1 + PH_ACT_BACKEND_SERVER_URL: https://ops.mifos.gazelle.test + PH_OPS_BULK_CONNECTOR_URL: https://bulk-connector.mifos.gazelle.test + PH_OPS_SIGNATURE_URL: https://ops.mifos.gazelle.test/api/v1/util/x-signature + PH_PLATFORM_TENANT_ID: greenbank + PH_PLATFORM_TENANT_IDS: "greenbank,bluebank" + auth: + PH_AUTH_ENABLED: false + PH_OAUTH_ENABLED: false + PH_OAUTH_TYPE: keycloak + PH_OAUTH_SERVER_URL: http://keycloak.mifos.gazelle.test/auth + PH_OAUTH_REALM: fred + PH_OAUTH_CLIENT_ID: fred2 + PH_OAUTH_CLIENT_SECRET: Y2xpZW50Og== + PH_OAUTH_BASIC_AUTH: true + PH_OAUTH_BASIC_AUTH_TOKEN: Y2xpZW50Og== + PH_DEFAULT_LANGUAGE: en + PH_SUPPORTED_LANGUAGES: en,fr,es + #hostname: "operations-web" + ingress: + annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/cors-allow-headers: content-type,platform-tenantid,privatekey,x-correlationid,x-correlation-id,purpose,type,x-callback-url,x-program-id,x-registering-institution-id,x-signature + nginx.ingress.kubernetes.io/cors-allow-methods: PUT, GET, POST, OPTIONS, DELETE + nginx.ingress.kubernetes.io/cors-allow-origin: '*' + nginx.ingress.kubernetes.io/enable-cors: "true" + enabled: true + tls: + - secretName: sandbox-secret + hosts: + - host: ops.mifos.gazelle.test + paths: + - path: "/" + backend: + service: + name: "ph-ee-operations-web" + port: + number: 80 + - path: "/paymenthub" + backend: + service: + name: "ph-ee-operations-web" + port: + number: 80 + - path: "/api/v1" + backend: + service: + name: "ph-ee-operations-app" + port: + number: 80 + - path: "/oauth" + backend: + service: + name: "ph-ee-operations-app" + port: + number: 80 + # - path: "/batchtransactions" + # backend: + # service: + # name: "ph-ee-connector-bulk" + # port: + # number: 8443 + # - path: "/bulk" + # backend: + # service: + # name: "ph-ee-connector-bulk" + # port: + # number: 8443 + - path: /benficiary + backend: + service: + name: ph-ee-identity-account-mapper + port: + number: 80 + + camunda-platform: + enabled: true + + operate: + enabled: false + ingress: + ## @param operate.ingress.enabled if true, an ingress resource is deployed with the Operate deployment. Only useful if an ingress controller is available, like nginx. Warning, separated ingress is deprecated and will be removed in the next release, please use global.ingress instead. + enabled: true + ## @param operate.ingress.className defines the class or configuration of ingress which should be used by the controller + className: nginx + annotations: + ingress.kubernetes.io/rewrite-target: '/' + nginx.ingress.kubernetes.io/ssl-redirect: 'false' + nginx.ingress.kubernetes.io/proxy-buffer-size: '128k' + nginx.ingress.kubernetes.io/proxy-buffering: 'on' + path: / + pathType: Prefix + host: zeebe-operate.mifos.gazelle.test + tls: + enabled: false + + zeebe-gateway: + ingress: + enabled: true + className: nginx + host: zeebe-gateway.mifos.gazelle.test + + zeebe: + # removes dependency of https://fynarfin.io for exporter jarfile + # TODO move this to mifos artifactory !!! + extraInitContainers: + - name: init-ph-ee-kafka-exporter + image: busybox:1.28 + command: ['/bin/sh', '-c'] + #args: ['wget -O /exporters/ph-ee-kafka-exporter.jar "http://10.0.0.4:8000/exporter-1.0.0-SNAPSHOT.jar"; ls -al /exporters/'] + args: ['wget -O /exporters/ph-ee-kafka-exporter.jar "https://paymenthub-ee-dev.s3.us-east-2.amazonaws.com/jars/exporter-1.0.0-SNAPSHOT.jar"; ls -al /exporters/'] + volumeMounts: + - name: exporters + mountPath: /exporters/ + # volumeClaimTemplate: + # storageClassName: "local-path" + + # Zeebe operations + zeebe_ops: + ingress: + enabled: true + className: nginx + # note limts and requests should be in the ph-ee-engine values.yaml + # so safe to take out now + limits: + memory: "1000M" + cpu: "1000m" + requests: + memory: "128k" + cpu: "50m" + + # Vouchers + vouchers: + enabled: true + ingress: + enabled: true + className: nginx + + # # Kibana + # kibana: + # ingress: + # enabled: true + # hosts: + # - host: kibana.mifos.gazelle.test + + # Notifications + notifications: + # enabled: true + # imagePullPolicy: "Always" + # SPRING_PROFILES_ACTIVE: "bb" + # LOGGING_LEVEL_ROOT: "INFO" + # MESSAGEGATEWAYCONFIG_HOST: "message-gateway-1" + # NOTIFICATION_LOCAL_HOST: "ph-ee-connector-notifications" + # NOTIFICATION_SUCCESS_ENABLED: "false" + # NOTIFICATION_FAILURE_ENABLED: "true" + hostname: "notifications.mifos.gazelle.test" + includeResources: false + ingress: + enabled: true + className: nginx + deployment: + annotations: + deployTime: "{{ .Values.deployTime }}" + + # PH-EE Connector Mojaloop + # Note 'fred' and 'FRED' are development hooks as we continue to work on end to end integration flows. + ph_ee_connector_mojaloop: + # the following 2 entries used only for dev/test of mojaloop connector + # image: mojaloop-connector:gazelle + # imagePullPolicy: "Never" + image: openmf/ph-ee-connector-mojaloop:v1.5.0 + ingress: + enabled: true + className: nginx + switch: + quotes: + host: "" + service: "" + als: + host: "fspiop.mifos.gazelle.test" + service: "fspiop.mifos.gazelle.test" + transfers: + host: "fspiop.mifos.gazelle.test" + service: "" + transactions: + host: "fspiop.mifos.gazelle.test" + service: "" + oracle: + host: "fspiop.mifos.gazelle.test" + deployment: + extraEnvs: + - name: parties_0_domain + value: "https://fynams.fred.io/" + - name: parties_1_domain + value: "mojaloop.fred.io" + - name: parties_2_domain + value: "mojaloop.fred.io" + - name: parties_3_domain + value: "mojaloop.fred.io" + - name: parties_0_tenantId + value: "greenbank" + - name: parties_1_tenantId + value: "bluebank" + + ph_ee_connector_ams_mifos: + ams_local_enabled: true + ams_local_interop_host: "fineract-server" + ams_local_account_host: "fineract-server" + ams_local_customer_host: "fineract-server" + ams_local_auth_host: "fineract-server" + ingress: + enabled: true + className: nginx + + # Mockpayment + mockpayment: + hostname: "mockpayment.mifos.gazelle.test" + ingress: + enabled: true + className: nginx + annotations: + kubernetes.io/ingress.class: nginx + tls: + - secretName: sandbox-secret + hosts: + - host: mockpayment.mifos.gazelle.test + paths: + - path: "/" + backend: + service: + name: ph-ee-connector-mock-payment-schema + port: + number: 80 + deployment: + annotations: + deployTime: "{{ .Values.deployTime }}" + + # CRM + crm: + ingress: + enabled: true + className: nginx + annotations: + kubernetes.io/ingress.class: nginx + + # Channel + channel: + ingress: + enabled: true + className: nginx + annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + + connector_bulk: + enabled: true + tenants: "greenbank,bluebank" + # deployment: + # annotations: + # rollme: "{{ randAlphaNum 5 | quote }}" + # operations_app: + # contactpoint: "https://ops-bk.mifos.gazelle.test/" + # endpoints: + # batch_transaction: "/api/v1/batch/transactions" + # identity_account_mapper: + # hostname: "http://ph-ee-identity-account-mapper:80" + ingress: + enabled: true + className: nginx + annotations: + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/cors-allow-headers: "content-type,platform-tenantid,purpose,type,x-callback-url,x-correlationid,x-program-id,x-registering-institution-id,x-signature" + nginx.ingress.kubernetes.io/cors-allow-methods: PUT, GET, POST, OPTIONS, DELETE + #nginx.ingress.kubernetes.io/cors-allow-origin: '*' + #nginx.ingress.kubernetes.io/cors-allow-origin-regex: "https?://ops\.mifos.gazelle.test:4200" + nginx.ingress.kubernetes.io/cors-allow-origin-regex: "https://ops.mifos.gazelle.test" + nginx.ingress.kubernetes.io/enable-cors: "true" + tls: + - secretName: sandbox-secret + hosts: + - host: bulk-connector.mifos.gazelle.test + paths: + - path: "/" + backend: + service: + name: "ph-ee-connector-bulk" + port: + number: 8443 + + # # Connector Bulk + # connector_bulk: + # ingress: + # enabled: true + # className: nginx + # annotations: + # nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + + # Bill Pay + billPay: + ingress: + enabled: false + className: nginx + annotations: + kubernetes.io/ingress.class: nginx + + # PH-EE Connector AMS Mifos + ingress: + enabled: true + className: nginx + + # Minio + minio: + ingress: + enabled: true + ingressClassName: nginx + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/backend-protocol: "HTTP" + hosts: + - minio.mifos.gazelle.test + + # Message Gateway + messagegateway: + ingress: + enabled: true + className: nginx + + post_installation_job: + enabled: false + + integration_test: + enableAMSTest: false + enableGOVTest: false + enableGazelleTest: true + imagePullPolicy: IfNotPresent + image: docker.io/openmf/ph-ee-integration-test:v1.6.2-gazelle + imagePullPolicy: IfNotPresent + testTags: "@gov and not @ext" + memoryRequest: "500k" + testResultsOutputDir: "/tmp" + +# Account Mapper +account_mapper: + enabled: true + ingress: + enabled: true + className: nginx + annotations: + kubernetes.io/ingress.class: nginx + # tls: + # - secretName: sandbox-secret + # hosts: + # - host: identity-mapper.mifos.gazelle.test + # paths: + # - path: "/" + # backend: + # service: + # name: ph-ee-identity-account-mapper + # port: + # number: 80 + diff --git a/src/mojafos/configurationManager/mojaloop_values.json b/config/vnext_values.json similarity index 83% rename from src/mojafos/configurationManager/mojaloop_values.json rename to config/vnext_values.json index fff606d..c87b41a 100644 --- a/src/mojafos/configurationManager/mojaloop_values.json +++ b/config/vnext_values.json @@ -13,6 +13,6 @@ }, { "old_value": "value: http:\\/\\/infra-elasticsearch:9200", - "new_value": "value: http:\\/\\/mojafos-infra-elasticsearch.infra.svc.cluster.local:9200" + "new_value": "value: http:\\/\\/infra-elasticsearch.infra.svc.cluster.local:9200" } ] diff --git a/docs/MIFOS-GAZELLE-README.md b/docs/MIFOS-GAZELLE-README.md new file mode 100644 index 0000000..8966821 --- /dev/null +++ b/docs/MIFOS-GAZELLE-README.md @@ -0,0 +1,238 @@ +# Mifos Gazelle Deployment Guide + +[![Mifos](https://img.shields.io/badge/Mifos-Gazelle-blue)](https://github.com/openMF/mifos-gazelle) + +> Deployment utilities for MifosX, Payment Hub EE (PH-EE), and Mojaloop vNext ( December 2024 ) + +## Table of Contents +- [Goal](#goal-of-mifos-gazelle) +- [Prerequisites](#prerequisites) +- [Quick Start](#quick-start) +- [Deployment Options](#deployment-options) +- [Application Deployment Modes](#application-deployment-modes) +- [Cleanup](#cleanup) +- [What to do next](#what-to-do-next) +- [Accessing Deployed Applications](#accessing-deployed-applications-dpgs) + - [Mojaloop vNext](#accessing-mojaloop-vnext) + - [Payment Hub](#accessing-payment-hub-EE) + - [MifosX](#accessing-mifosx) +- [ Adding tenants to MifosX](#adding-tenants-to-mifosx) +- [Running helm test](#helm-test) +- [Development Status](#development-status) +- [Known Issues](#known-issues) +- [Version Information](#version-information) + + +## Goal of Mifos Gazelle +The aim of Mifos Gazelle is to provide a trivially simple installation and configuration mechanism for DPGs as part of a DPI construct. Initially this is focussed on Mifos applications for Core-Banking and Payment Orchestration and the Mojaloop vNext financial transactions switch. The idea is to create a rapidly deployable , understandable and cheap integration to serve as a showcase and a laboratory environment to enable others to build further on these DPI projects. As the project continues we have a roadmap of additional DPGs, demo cases and other features we want to implement, along with looking at how it could be used for production in-cloud and on-premise deployments. + +IMPORTANT NOTE: As Mifos-Gazelle is a deployment tool we make no statements or opinions on the base DPGs in terms of applicability, security etc we recommend all adopters read DPG base documentation to make their own assessment of these. Likewise at the moment for v1.0.0. release we recommend use solely for development, test and demonstration purposes as security assessment and hardening of Mifos Gazelle regardless of the base DPGs status has not occurred yet. + +## Gazelle features (benefits) +- Mifos Gazelle installs each or all 3 DPGs in a reliable , repeatable way using simple bash scripts. +- The bash scripts are designed to enable developers to understand and modify the configuration of each or all products. +- Enables installation of all 3 products is quick 15 mins or less with reasonable hardware +Fully functioning MifosX , with the addition of tools to simply add additional tenants +Fully functioning vNext (beta1) with integrated demo and test environment, admin UI and pre-loaded demo data +Installed and partially configured PHEE with deployed Web Client(note: see limitations under development status) + + +## Prerequisites +Before proceeding with the deployment, ensure your system meets the following requirements: + +- Ubuntu 22.04 or 24.04 LTS operating systems +- x86_64 architecture +- 32GB RAM minimum +- 30GB+ free space in home directory +- Non-root user with sudo privileges + +Note regarding memory use : +1. If you are installing just MifosX or just vNext then much less memory is required. + +## Quick Start +logged in as non-root user e.g. mifosu user +```bash +# Navigate to home directory +cd $HOME + +# For Installations of the latest release clone the repository (master branch) +git clone --branch master https://github.com/openMF/mifos-gazelle.git + +Or + +# For Installations of the latest development path clone the repository (dev branch) +git clone --branch dev https://github.com/openMF/mifos-gazelle.git + + +# Enter the project directory +cd mifos-gazelle + +# Deploy all components (MifosX, vNext, and PH-EE) +sudo ./run.sh -u $USER -m deploy -d true -a all +``` + +## Deployment Options + +| Option | Description | Values | +|--------|-------------|---------| +| `-h` | Display help message | - | +| `-u` | Non-root user for deployment | Current user (`$USER`) | +| `-m` | Execution mode | `deploy`, `cleanapps`, `cleanall` | +| `-d` | Verbose output | `true`, `false` | +| `-a` | Applications to deploy | `all`, `vnext`, `mifosx`, `phee` | + + +## What to do next +After the run.sh has finished and ```kubectl get pods -A``` shows all pods and containers running then MifosGazelle has finished installing and is ready for use and testing. Here are some suggestions for what to do next +- Install the k9s kubernetes utility using ``` ~/mifos-gazelle/src/utils/install-k9s.sh ``` then start k9s with ``` ~/local/bin/k9s ``` +- Examine the running MifosX database using ``` ~/mifos-gazelle/src/utils/mysql-client-mifos.sh ``` +- Examine the running PaymentHub database using ``` ~/mifos-gazelle/src/utils/mysql-client-mifos.sh -h operationsmysql.paymenthub.svc.cluster.local -p ethieTieCh8ahv -u root -d mysql ``` +- Access the deployed applications and consoles for MifosX, vNext and PaymentHub EE see [Accessing Deployed Applications](#accessing-deployed-applications) then browse to http://mifos.mifos.gazelle.test or http://vnextadmin.mifos.gazelle.test or http://ops.mifos.gazelle.test +- Consult the documentation for the DPGs + - vNext using the adminUI and sample account lookup, quotes and transfers : https://github.com/mojaloop/platform-shared-tools/blob/main/packages/deployment/docker-compose-apps/README.md#login-to-the-mojaloop-vnext-admin-ui + - MifosX for core banking : https://docs.mifos.org/core-banking-and-embedded-finance/core-banking + - PaymentHub EE : https://mifos.gitbook.io/docs +- if you haven't already join the mifos-gazelle channel on the Mifos Slack at https://mifos.slack.com + +## Application Deployment Modes + +Choose specific components to deploy using the `-a` flag: + +```bash +# Deploy only Mojaloop vNext +sudo ./run.sh -u $USER -m deploy -a vnext + +# Deploy only MifosX +sudo ./run.sh -u $USER -m deploy -a mifosx + +# Deploy only Payment Hub EE +sudo ./run.sh -u $USER -m deploy -a phee +``` + +## Cleanup + +Remove deployed components: + +```bash +# Remove everything including Kubernetes server +sudo ./run.sh -u $USER -m cleanall + +# Remove all applications from the Kubernetes server +sudo ./run.sh -u $USER -m cleanapps + +# Remove specific components +sudo ./run.sh -u $USER -m cleanapps -a mifosx # Remove MifosX +sudo ./run.sh -u $USER -m cleanapps -a phee # Remove PaymentHub EE +sudo ./run.sh -u $USER -m cleanapps -a vnext # Remove vNext switch +``` + +## Accessing Deployed Applications (DPGs) +Add the following entries to your hosts file on the laptop/desktop system where your web browser is running where (without the angle brackets) is the IP of the server or VM where Mifos Gazelle has been deployed. If your browser is running on Linux or MacOS then all hosts entries go on one line , if your browser is running on Windows then you need a separate line for each entry. + +Once you have added the hosts below for the DPGs you can access consoles with +- MifosX : http://mifos.mifos.gazelle.test +- vNext : http://vnextadmin.mifos.gazelle.test +- PaymentHub EE: http://ops.mifos.gazelle.test + + +### vNext host Configuration +```bash +# Linux/MacOS (/etc/hosts) + vnextadmin elasticsearch.mifos.gazelle.test kibana.mifos.gazelle.test mongoexpress.mifos.gazelle.test kafkaconsole.mifos.gazelle.test fspiop.mifos.gazelle.test bluebank.mifos.gazelle.test greenbank.mifos.gazelle.test + +# Windows (C:\Windows\System32\drivers\etc\hosts) + vnextadmin.mifos.gazelle.test + elasticsearch.mifos.gazelle.test + kibana.mifos.gazelle.test + mongoexpress.mifos.gazelle.test + kafkaconsole.mifos.gazelle.test + fspiop.mifos.gazelle.test + bluebank.mifos.gazelle.test + greenbank.mifos.gazelle.test +``` + +### Payment Hub EE host Configuration + +```bash +# Linux/MacOS (/etc/hosts) + ops.mifos.gazelle.test kibana-phee.mifos.gazelle.test zeebe-operate.mifos.gazelle.test + +# Windows (C:\Windows\System32\drivers\etc\hosts) + ops.mifos.gazelle.test + kibana-phee.mifos.gazelle.test + zeebe-operate.mifos.gazelle.test + +``` +### Accessing MifosX +By default the Mifos Gazelle installation only loads the "default" tenant into the database even though greenbank and bluebank are configured into the web client so when logging into Mifos use the default tenant and the default user=mifos and password=password. See [ Adding tenants to MifosX](#adding-tenants-to-mifosx) for instructions on adding tenants to MifosX database. To change the options for tenants in the web client , modify the FINERACT_PLATFORM_TENANTS_IDENTIFIER in ../src/repos/mifosx/kubernbetes/web-app-deployment.yaml file and redeploy the mifosx app using the Mifos Gazelle run.sh and the -a flag. + +#### Host Configuration + +```bash +# Linux/MacOS (/etc/hosts) + fineract.mifos.gazelle.test mifos.mifos.gazelle.test + +# Windows (C:\Windows\System32\drivers\etc\hosts) + mifos.mifos.gazelle.test + fineract.mifos.gazelle.test +``` + +## Helm test +Note the Payment Hub Helm tests are being reconfigured as we continue to work on end to end integration flows, therefore you may get significant errors due to naming at this present point in time (prior to the reconfiguration exercise though they were reporting 90%+ success). +Helm tests are currently enabled/disabled in the config/ph_values.yaml file , look for integration_tests. To execute the helm tests run +```bash +helm test phee +``` +then examine the logfiles using either k9s or +```bash +kubectl logs -n paymenthub ph-ee-integration-test-gazelle +``` +You can access the results by copying them from the pod to the /tmp directory of the server machine or VM using the script below. This will place the results into a directory similar to mydir.SzSauX i.e. of the form /tmp/mydir.XXXXXX. You will need to copy this directory from the server/VM to your desktop/laptop to browse the results , look for the subdirectory of tests/test/index.html as the top level for your browser. Note that the pod will time-out after 90 mins and you will need to remove the ph-ee-integration-test-gazelle pod before running helm test phee again. +```bash +~/mifos-gazelle/src/utils/copy-report-from-pod.sh +``` + +## Adding tenants to MifosX +By default MifosGazelle deploys MifosX with a single tenant called "default" +the process to add tenants to a MifosGazelle deployed MifosX deployment is a 2 part process +1. modify the example tenant configuration file mifos-gazelle/config/mifos-tenant-config.csv for your chosen tenant names +2. apply the example tenant configuration to add the new tenants by running (for example) ``` mifos-gazelle/src/utils/utils/update-mifos-tenants.sh -f ./config/mifos-tenant-config.csv ``` +3. in k9s locate and kill the fineract-server process in the MifosX namespace (use ```ctrl-k ``` from k9s) it will automatically be restarted by kubernetes. +When fineract-server is restarted the new tenants schemas tables and artefacts will be created. You can check the progress of the schema generation by looking at the fineract-server pod logs. Still using k9s, again locate the new fineract-server pod and press ```l``` for logs when that pod is highlighted. +4. Once the new fineract-server pod has finished creating the new schema , you can test this by logging in to the MifosX web-client using that tenant. + +## Development Status +Please note that limitations here are entirely those of the Mifos Gazelle configuration, and should not at all be interpreted as issues with the maturity or functionality of the deployed DPGs. +- Currently PH-EE operations-web UI https://ops.mifos.gazelle.test can access batches and transfers and can create and send batches to bulk. It is not yet clear that the batches are correctly processed on the back end, this of course is being worked on. +- ph-ee-integration-test docker image on dockerhub uses the tag v1.6.2-gazelle and corresponds to the v1.6.2-gazelle branch of the v1.6.2 integration-test repo. The helm tests as deployed by Gazelle reports approx 90% pass rate. +- PaymentHub EE v 1.13.0 is being provisioned by Mifos Gazelle and this is set in the config.sh script prior to deployment. This document defines all the sub chart releases that comprise the v1.13.0 release https://mifos.gitbook.io/docs/payment-hub-ee/release-notes/v1.13.0 +- There is a lot of tidying up to do once this is better tested, e.g. debug statements to remove and lots of redundant env vars to remove as well as commented out code to remove. +- It should be straightforward to integrate the Kubernetes operator work ( https://github.com/openMF/mifos-operators ) into this simplified single node deployment and this is planned for a future release +- vNext Beta1 functions and is tested on ARM64 there is a limitation on Raspberry Pi 4 (or less) with MongoDB due to requirement for ARMv8.2A. Whilst it is untested vNext Beta1 and its associated infrastructure layer deployed by Mifos Gazelle should "just work" Use ```sudo ./run.sh -u -m deploy -a vnext ``` on a clean install to try. In the future it should be straightforward and is planned to have MifosX and PaymentHub EE also working on ARM and Raspberry PI +- reducing memory usage for demo and test is a high priority project, it is anticipated that the 3 initial DPGs can all run on 16GB or less (i.e. about 50% of the current prerequisite ) +- The performance testing is still WIP and not fully operational + + +## Known Issues +- Currently testing is limited to only systems and environments that meet the pre-requisites +- Only single instance/node deployment currently supported , there is no reason for this except it is all that is currently tested. +- Some cleanup is likely needed (debug statements, redundant environment variables) but as some of this is in use that will happen in future releases +- PaymentHub EE Kubernetes operator has been developed and will be integrated in future releases +- Updated Operations web integration pending (pending in PH-EE too - https://github.com/openMF/ph-ee-operations-web/pull/98 and https://github.com/openMF/ph-ee-operations-web/pull/99 ) +- as part of Gazelle development the helm tests databases , tenants etc are being reconfigured and consequently helm tests are likely to report high failure rate +- PaymentHub EE integration with vNext and MifosX is not complete (no end-to-end txns yet) => Operations-Web UI is limited in function +- demonstration data is not currently loaded for MifosX (but this is readily available) +- The postman tests provided by the individual DPGs have not yet been fully adapted to the Mifos Gazelle deployment environment, again this will happen in future releases in a structure fashion. +- There are some issues on older (Intel/Opteron) hardware with nginx, MongoDB and ElasticSearch. +- Reminder Mifos Gazelle deployment of the 3 DPGs is *not at all secure*. (Note this is true no matter of the security status of the underlying DPGs). Security will necessarily become a major focus as we look to more production ready deployments in future releases. + +## Version information + +MifosX : i.e. Mifos and Mifos web-client uses docker container openmf/fineract:develop +vNext : vNext Beta1 release details see https://github.com/mojaloop/platform-shared-tools/blob/beta1/README.md +PaymentHub EE : v1.13.0 subcharts and versions as documented at https://mifos.gitbook.io/docs/payment-hub-ee/release-notes/v1.13.0 but with the following exceptions :- +- ph-ee-env-template : docker.io/openmf/ph-ee-env-template:v1.13.0-gazelle +- ph-ee-integration-test : docker.io/openmf/ph-ee-integration-test:v1.6.2-gazelle +- ph-ee-operations-web : docker.io/openmf/openmf/ph-ee-operations-web:dev1 + + diff --git a/docs/POSTMAN.md b/docs/POSTMAN.md new file mode 100644 index 0000000..2e772e9 --- /dev/null +++ b/docs/POSTMAN.md @@ -0,0 +1,38 @@ +# SETTING UP POSTMAN COLLECTIONS FOR MIFOS-GAZELLE (WIP) + +*LIMITATION: These instructions are currently only for Payment Hub EE + +We have a bash script `postman_setup.sh` under the [src](../src/utils/) directory that you can run to skip through the steps 1 and 5. +To run the script, you can do the following: +Go to the directory where the script is located and run the following command: + +Then run the script: +```bash +sudo ./postman_setup.sh -o +``` + +The `-o` flag is optional and is used to override the existing host entry in /etc/hosts file. If you want to override the existing host entry, then you can pass `true` as the value of the flag, otherwise you can pass `false`. + +NOTE: This script is intended to be run on a Linux system, specifically Ubuntu 22.04 or 24.02 If you are running on a different system, you can follow the steps below to setup the postman collections. + +## Step 1: Adding Hosts + +NOTE: See the detailed steps on how to configure your hosts, in the `ACCESSING DEPLOYED APPLICATIONS` section of the [MIFOS-GAZELLE-README](MIFOS-GAZELLE-README.md). + +## Step 2: Downloading Postman +You can download postman from [this](https://www.postman.com/downloads) link. + +## Step 3: Importing Collections +After downloading, open postman, go to collections. Then click on `import` and open the file: `repos/ph_template/PostmanCollections/Payment Hub.json`. + +NOTE: This directory and file appears only after you have run the installation, if you need to import the collections without running the deployment, then you can download from [here](https://raw.githubusercontent.com/openMF/ph-ee-env-template/master/PostmanCollections/Payment%20Hub.json). + + +## Step 4: Importing Environment +To import the environment for running the collection, you can go to Environments, then click on Import and then open the file `repos/ph_template/PostmanCollections/Environment/PHEE_G2P_Demo.postman_environment.json`. + +NOTE: You may need to change some of the environment variables if the hosts are different. + + +## Step 5: Setup Complete +After following the above steps correctly, you'll be able to run the postman collections smoothly. diff --git a/docs/VNEXT-README.md b/docs/VNEXT-README.md new file mode 100644 index 0000000..1c52edb --- /dev/null +++ b/docs/VNEXT-README.md @@ -0,0 +1,132 @@ +# Mifos Gazelle - standalone deployment of vNext Beta1 + +## Overview + Mifos Gazelle enables complete stand-alone deployment of vNext Beta1 this can serve as a useful tool for focussed vNext standalone testing and experimentation. For those familiar with mini-loop installation of vNext, Mifos Gazelle provides exactly the same function with the advantage that Mifos Gazelle is under active development. + +## vNext standalone installation using Mifos Gazelle +This is exactly the same process as for any Mifos Gazelle deployment but we use the -a flag as described in the main Mifos Gazelle README +logged in as non-root user e.g. mifosu user +```bash +# Navigate to home directory +cd $HOME + +# Clone the repository (dev branch) +git clone --branch dev https://github.com/openMF/mifos-gazelle.git + +# Enter the project directory +cd mifos-gazelle + +# Deploy only vNext and the underlying infrastructure services +sudo ./run.sh -u $USER -m deploy -d true -a vNext +``` + +> **Reminder**: currently Mifos Gazelle deployments including those of vNext Beta1 are not intended for production use. + +## Mifos Gazelle vNext deployment features +- **Realistic Environment**: Runs a complete Kubernetes stack for realistic testing +- **Simple Deployment**: Requires minimal command execution +- **Quick Setup**: Deploys in approximately 5-10 minutes with proper configuration +- **Automation-friendly**: Scripts can be integrated with CI/CD pipelines +- **Resource Efficient**: Optimized resource usage for testing environments +- **vNext only**: using the -a flag on the Mifos Gazelle installer + +## Supported Environments +- the Mifos Gazelle vNext Beta install works on Ubuntu 20.04 and 22.04 LTS on x86_64 or ARM64: + - Bare metal servers + - Virtual machines (VirtualBox, Parallels, UTM, QEMU) + - Cloud instances (AWS, GCP, Azure, etc.) + +## Prerequisites +As listed in the main Mifos Gazelle README.md but additionally this has been tested against +- Ubuntu 20.04 or 22.04 LTS +- x86_64 or ARM64 architecture + + +## Installation Steps for vNext only installation +to install vNext only using Mifos Gazelle +```bash +# Navigate to home directory +cd $HOME + +# Clone the repository (dev branch) +git clone --branch dev https://github.com/openMF/mifos-gazelle.git + +# Enter the project directory +cd mifos-gazelle + +# For ARM64 systems only +sudo ./ttk-interim-fix.sh + +# Deploy vNext only +sudo ./run.sh -u $USER -m deploy -d true -a vnext +``` + +## Accessing vNext Services + +### Local Access +The installation automatically configures local hostnames in `/etc/hosts` for the deployment system. + +### Remote Access +To access vNext services from another machine: + +1. Ensure port 80 is accessible on the deployment system +2. Add the following hostnames to the hosts file on the desktop or laptop where your browser is running: + +``` + vnextadmin.mifos.gazelle.test elasticsearch.mifos.gazelle.test kibana.mifos.gazelle.test mongoexpress.mifos.gazelle.test kafkaconsole.mifos.gazelle.test fspiop.mifos.gazelle.test bluebank.mifos.gazelle.test greenbank.mifos.gazelle.test +``` + +### Available vNext and support infrastructure Services +- Admin Interface: http://vnextadmin.mifos.gazelle.test +- Testing Toolkit: + - Blue Bank: http://bluebank.mifos.gazelle.test + - Green Bank: http://greenbank.mifos.gazelle.test +- Management Consoles: + - MongoDB Express: http://mongoexpress.mifos.gazelle.test + - Kafka Console: http://kafkaconsole.mifos.gazelle.test + +## Windows Users Guide + +### Modifying Windows Hosts File +1. Open Notepad as Administrator +2. Navigate to: `C:\Windows\System32\drivers\etc\hosts` +3. Add entries in this format (one host per line): +``` +192.168.56.100 vnextadmin.mifos.gazelle.test +192.168.56.100 elasticsearch.mifos.gazelle.test +192.168.56.100 kibana.mifos.gazelle.test +192.168.56.100 mongoexpress.mifos.gazelle.test +192.168.56.100 kafkaconsole.mifos.gazelle.test +192.168.56.100 fspiop.mifos.gazelle.test +192.168.56.100 bluebank.mifos.gazelle.test +192.168.56.100 greenbank.mifos.gazelle.test +``` +4. Flush DNS cache: +```cmd +ipconfig /flushdns +``` + +## Known Limitations of the vNext (Beta1 Release) +1. Beta status: Mifos Gazelle currently deploys the vNext Beta1 +2. Ubuntu version: Tested only on Ubuntu 20.04 and 22.04 LTS +3. Kubernetes: Currently supports k3s , this will be updated as Mifos Gazelle works across a wider variety of Kubernetes clusters e.g. EKS,AKS,GKE etc +4. Logging: Log format improvements planned for better CI/CD integration +5. DNS Configuration: Domain name configuration feature pending implementation localhosts is used currently +6. Endpoint Testing: Automated service validation to be implemented + +## Troubleshooting +1. Verify installation success by accessing http://vnextadmin.mifos.gazelle.test +2. Check pod status: `kubectl get pods -A or use k9s` +3. Review logs in `/tmp` directory (configurable location) +4. Watch for warning messages about pod startup times + +## Usage Notes +- Scripts provide deployment guidance through console messages +- Use `-h` flag with any script for detailed usage information +- Configuration can be customized for specific needs +- Ideal for development, testing, and educational purposes +- Not suitable for production deployments + +## Support +- Support for deployment issues through Mifos-Gazelle can be obtained through the Mifos Gazelle Slack channel https://mifos.slack.com/archives/C082PNLUCRK +- Support for issues with vNext Beta 1 should be directed to the Mojaloop Development Community. \ No newline at end of file diff --git a/performance-testing/README.md b/performance-testing/README.md new file mode 100644 index 0000000..2f83794 --- /dev/null +++ b/performance-testing/README.md @@ -0,0 +1,68 @@ +# PaymentHubEE API Testing with JMeter (WIP) + +This README provides instructions on how to set up and run the JMeter test plan for testing the APIs of PaymentHubEE. The test plan allows you to simulate multiple users, configure which APIs to test, and analyze the performance of the APIs. + +## Prerequisites + +Before you begin, ensure that you have the following installed: +- [Apache JMeter](https://jmeter.apache.org/download_jmeter.cgi) version 5.X.X (Recommended) + +## Steps to Run the Test on Your Local Computer + +### 1. Download and Install JMeter + +- Download JMeter from the official [JMeter website](https://jmeter.apache.org/download_jmeter.cgi). +- Extract the downloaded file and follow the installation instructions appropriate for your operating system. + +### 2. Update the Hosts File + +- Open your hosts file in a text editor with administrative privileges: + - **Windows:** `C:\Windows\System32\drivers\etc\hosts` + - **Mac/Linux:** `/etc/hosts` +- Add the necessary entries for the PaymentHubEE environment. For example: + ```plaintext + 127.0.0.1 paymenthub.local +- Save the file and close the editor. + +### 3. Copy the Test Plan from GitHub + - Clone the repository containing the JMeter test plan to your local machine: + ```plaintext + git clone https://github.com/openMF/mifos-gazelle.git + cd performance-testing + - Alternatively, you can download the .jmx file directly from GitHub. + +### 4. Open the Test Plan in JMeter + +In JMeter, navigate to `File > Open` and choose the `paymentHubEE.jmx` file from the cloned repository or the location where you downloaded it. + +### 5. Configure the Test Plan + +- **Number of Threads (Users):** + - In JMeter, navigate to the `Thread Group` section. + - Adjust the `Number of Threads (users)` and `Ramp-Up Period` as per your testing requirements. + - Increasing the number of threads simulates more users accessing the APIs simultaneously, which can help you test the performance under load. Reducing the number of threads simulates fewer users and allows you to test the system's behavior under lighter load conditions. + +- **Enable/Disable APIs:** + - Expand the test plan to view the API requests. + - Right-click on any API you want to disable and select `Disable`. + - You can also enable specific APIs if needed. This allows you to focus on testing individual APIs or a subset of APIs, which is useful for targeted performance testing and debugging. + +- **Output Configuration:** + - **Response Time:** To get detailed response times, add a listener such as `Summary Report` or `Aggregate Report`. These listeners provide insights into average, minimum, maximum, and median response times for each API request. + - **Error Reporting:** To capture any errors or failures during the test, add a `View Results Tree` listener. This will log each request and response, allowing you to analyze failed requests in detail. + - **Throughput Analysis:** To monitor the number of requests processed per second (throughput), use the `Throughput vs Threads` or `Graph Results` listeners. These will give you a visual representation of how the system handles concurrent users. + + - **Data Export:** You can export the results to a `.csv` or `.xml` file for further analysis. Right-click on the listener (e.g., `Aggregate Report`) and choose `Save Table Data` to export the data. + + By configuring these elements, you can tailor the test to your specific needs, whether you're looking to assess performance under load, analyze error rates, or fine-tune individual API endpoints. +### 6. Run the Test +Once your configuration is complete, click the green start button (triangle icon) in the JMeter interface to run the test. + +JMeter will execute the test plan based on your configurations. + +### 7. Analyze the Results +- View Results Tree: To see detailed logs of each request and response, right-click on the Test Plan or Thread Group and add a listener (e.g., View Results Tree). +- Aggregate Report: To get a summary of the test results, add an Aggregate Report listener. +- Review the results to identify any performance issues or API failures. + + diff --git a/performance-testing/paymentHubEE.jmx b/performance-testing/paymentHubEE.jmx new file mode 100644 index 0000000..3846a25 --- /dev/null +++ b/performance-testing/paymentHubEE.jmx @@ -0,0 +1,10956 @@ + + + + + + + + + + + + + host + paymentHub + = + + + scheme + https + = + + + + + + paymentHub + https + + + + + + + + + false + false + + + + 10 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /oauth/token?username=mifos&password=password&grant_type=password + true + POST + true + true + + + + false + {} + = + + + + + + + + + Authorization + Basic Y2xpZW50Og== + + + Platform-TenantId + rhino + + + Postman-Token + 64f5174b-5fab-499d-a23b-fb24f6538ff1 + + + Content-Type + text/plain + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /oauth/token?username=mifos&password=password&grant_type=password + true + POST + true + true + + + + false + {} + = + + + + + + + + + Authorization + Basic Y2xpZW50Og== + + + Referer + http://ops-bk.local/oauth/token?username=mifos&password=password&grant_type=password + + + Platform-TenantId + rhino + + + Postman-Token + 64f5174b-5fab-499d-a23b-fb24f6538ff1 + + + Content-Type + text/plain + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/transactionRequests?startTo=2022-08-19%2016:16:33&command=export + true + POST + true + true + + + + false + { + "errorDescription": ["Ams local is disabled"], + "transactionId": [], + "payerId": [], + "payeeId": [], + "externalId": [], + "workflowInstanceKey": [], + "state": [] +} + = + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Platform-TenantId + rhino + + + Postman-Token + 087ceaf4-1f15-42c7-834c-27ab91986823 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/transactionRequests?startTo=2022-08-19%2016:16:33&command=export + true + POST + true + true + + + + false + { + "errorDescription": ["Ams local is disabled"], + "transactionId": [], + "payerId": [], + "payeeId": [], + "externalId": [], + "workflowInstanceKey": [], + "state": [] +} + = + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Referer + http://ops-bk.local/api/v1/transactionRequests?startTo=2022-08-19%2016:16:33&command=export + + + Platform-TenantId + rhino + + + Postman-Token + 087ceaf4-1f15-42c7-834c-27ab91986823 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/errorcode/ + true + GET + true + false + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + 6a57c364-3892-4aff-86e4-73dbef597ce1 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/errorcode + true + GET + true + false + + + + + + + + + Referer + http://ops-bk.local/api/v1/errorcode/ + + + Platform-TenantId + rhino + + + Postman-Token + 6a57c364-3892-4aff-86e4-73dbef597ce1 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/errorcode/1 + true + GET + true + false + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + f2b3e3a6-428e-4092-8e7c-f2dbd7821af7 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/errorcode/1 + true + GET + true + false + + + + + + + + + Referer + http://ops-bk.local/api/v1/errorcode/1 + + + Platform-TenantId + rhino + + + Postman-Token + f2b3e3a6-428e-4092-8e7c-f2dbd7821af7 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/errorcode/1 + true + GET + true + false + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + 1a709d97-359c-4d4c-ba79-7151bf26c868 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/errorcode/1 + true + GET + true + false + + + + + + + + + Referer + http://ops-bk.local/api/v1/errorcode/1 + + + Platform-TenantId + rhino + + + Postman-Token + 1a709d97-359c-4d4c-ba79-7151bf26c868 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/errorcode/filter + true + GET + true + false + + + + false + value + 1037 + = + + + false + by + errorCode + = + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + fcd3c26a-0973-4be2-b04d-02103eb9ebe1 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/errorcode/filter + true + GET + true + false + + + + false + value + 1037 + = + + + false + by + errorCode + = + + + + + + + + + Referer + http://ops-bk.local/api/v1/errorcode/filter?value=1037&by=errorCode + + + Platform-TenantId + rhino + + + Postman-Token + fcd3c26a-0973-4be2-b04d-02103eb9ebe1 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/errorcode/filter + true + GET + true + false + + + + false + value + 1037 + = + + + false + by + errorCode + = + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + 4dc9af4e-f717-445f-8f27-12db9e693a9a + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/errorcode/filter + true + GET + true + false + + + + false + value + 1037 + = + + + false + by + errorCode + = + + + + + + + + + Referer + http://ops-bk.local/api/v1/errorcode/filter?value=1037&by=errorCode + + + Platform-TenantId + rhino + + + Postman-Token + 4dc9af4e-f717-445f-8f27-12db9e693a9a + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/errorcode/ + true + POST + true + true + + + + false + { + "transactionType": "COLLECTION-MPESA", + "errorMessage": "Request cancelled by user", + "errorCode": "1031", + "recoverable": false +} + = + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + 4453fd03-10a1-4484-833c-7751115c5844 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + utf-8 + /api/v1/errorcode + true + POST + true + true + + + + false + { + "transactionType": "COLLECTION-MPESA", + "errorMessage": "Request cancelled by user", + "errorCode": "1031", + "recoverable": false +} + = + + + + + + + + + Referer + http://ops-bk.local/api/v1/errorcode/ + + + Platform-TenantId + rhino + + + Postman-Token + 4453fd03-10a1-4484-833c-7751115c5844 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/errorcode/ + true + POST + true + true + + + + false + { + "transactionType": "COLLECTION-MPESA", + "errorMessage": "Request cancelled by user", + "errorCode": "1031", + "recoverable": false +} + = + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + e9db834a-12fe-4fe0-beb4-0eb5ddb70eb9 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + utf-8 + /api/v1/errorcode + true + POST + true + true + + + + false + { + "transactionType": "COLLECTION-MPESA", + "errorMessage": "Request cancelled by user", + "errorCode": "1031", + "recoverable": false +} + = + + + + + + + + + Referer + http://ops-bk.local/api/v1/errorcode/ + + + Platform-TenantId + rhino + + + Postman-Token + e9db834a-12fe-4fe0-beb4-0eb5ddb70eb9 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/transfers + true + GET + true + false + + + + false + size + 1 + = + + + false + page + 0 + = + + + false + clientCorrelationId + 123456789 + = + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Platform-TenantId + rhino + + + Postman-Token + d73a6b66-a7cc-447c-b478-83c6791c1f83 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/transfers + true + GET + true + false + + + + false + size + 1 + = + + + false + page + 0 + = + + + false + clientCorrelationId + 123456789 + = + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Referer + http://ops-bk.local/api/v1/transfers?size=1&page=0&clientCorrelationId=123456789 + + + Platform-TenantId + rhino + + + Postman-Token + d73a6b66-a7cc-447c-b478-83c6791c1f83 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/variables/21037e77-7227-4757-8e45-5c356f369b11 + true + GET + true + false + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + d6fceca4-c565-4ee5-90ea-93e807914409 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/variables/21037e77-7227-4757-8e45-5c356f369b11 + true + GET + true + false + + + + + + + + + Referer + http://ops-bk.local/api/v1/variables/21037e77-7227-4757-8e45-5c356f369b11 + + + Platform-TenantId + rhino + + + Postman-Token + d6fceca4-c565-4ee5-90ea-93e807914409 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + http + UTF-8 + /api/v1/transactionRequests/ + true + GET + true + false + + + + false + clientCorrelationId + 123 + = + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Platform-TenantId + rhino + + + Postman-Token + 34b61ecf-3dac-49f2-9dcd-3b001c0f5038 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + ops-bk.local + 0 + UTF-8 + /api/v1/transactionRequests/ + true + GET + true + false + + + + false + clientCorrelationId + 123 + = + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Referer + http://ops-bk.local/api/v1/transactionRequests/?clientCorrelationId=123 + + + Platform-TenantId + rhino + + + Postman-Token + 34b61ecf-3dac-49f2-9dcd-3b001c0f5038 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + https + UTF-8 + /api/v1/util/x-signature + true + POST + true + true + + + + false + [ + { + "creditParty": [ + { + "key": "msisdn", + "value": "8837461856" + } + ], + "debitParty": [ + { + "key": "accountnumber", + "value": "003001003874120160" + } + ], + "subType": "SLCB", + "amount": "820.00", + "currency": "RWF", + "descriptionText": "Test Payment" + }, + { + "creditParty": [ + { + "key": "msisdn", + "value": "32131461856" + } + ], + "debitParty": [ + { + "key": "accountnumber", + "value": "21314556003874120160" + } + ], + "subType": "SLCB", + "amount": "20.00", + "currency": "RWF", + "descriptionText": "Test Payment" + } +] + = + + + + + + + + + Purpose + test payment + + + Platform-TenantId + rhino + + + Postman-Token + 993c99be-6f5c-4c4a-9f03-6326025c5537 + + + type + raw + + + Accept + */* + + + privateKey + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC07fxdEQlsvWvggBgrork401cdyZ9MqV6FF/RgX6+Om23gP/rME5sE5//OoG61KU3dEj9phcHH845TuyNEyc4Vhqxe1gzl4VIZkOj+/2qxYvCsP1Sv3twTs+fDfFv5NA1ZXqiswTlgjR2Lpf1tevFQEOzB9WYvH/Bu9kgr2AlHMPV6+b7gcJij/7W1hndiCk2ahbi7oXjjODF4yEU9yNAhopibe4zzMX+FO4eFYpUmrjS5wvv6aAanfoeIMTwhF81Gj9V3rHf4UsD3VEx773q7GPuXlZSLyiNrUCdvxITh+dW8Y9ICuCTy3bFbp1/HzoPdzkkUlzPNKLlLiV2w4EcxAgMBAAECggEAMjqHfwbFyQxlMHQfQa3xIdd6LejVcqDqfqSB0Wd/A2YfAMyCQbmHpbsKh0B+u4h191OjixX5EBuLfa9MQUKNFejHXaSq+/6rnjFenbwm0IwZKJiEWDbUfhvJ0blqhypuMktXJG6YETfb5fL1AjnJWGL6d3Y7IgYJ56QzsQhOuxZidSqw468xc4sIF0CoTeJdrSC2yDCVuVlLNifm/2SXBJD8mgc1WCz0rkJhvvpW4k5G9rRSkS5f0013ZNfsfiDXoqiKkafoYNEbk7TZQNInqSuONm/UECn5GLm6IXdXSGfm1O2Lt0Kk7uxW/3W00mIPeZD+hiOObheRm/2HoOEKiQKBgQDreVFQihXAEDviIB2s6fphvPcMw/IonE8tX565i3303ubQMDIyZmsi3apN5pqSjm1TKq1KIgY2D4vYTu6vO5x9MhEO2CCZWNwC+awrIYa32FwiT8D8eZ9g+DJ4/IwXyz1fG38RCz/eIsJ0NsS9z8RKBIbfMmM+WnXRez3Fq+cbRwKBgQDEs35qXThbbFUYo1QkO0vIo85iczu9NllRxo1nAqQkfu1oTYQQobxcGk/aZk0B02r9kt2eob8zfG+X3LadIhQ0/LalnGNKI9jWLkdW4dxi7xMU99MYc3NRXmR49xGxgOVkLzKyGMisUvkTnE5v/S1nhu5uFr3JPkWcCScLOTjVxwKBgHNWsDq3+GFkUkC3pHF/BhJ7wbLyA5pavfmmnZOavO6FhB8zjFLdkdq5IuMXcl0ZAHm9LLZkJhCy2rfwKb+RflxgerR/rrAOM24Np4RU3q0MgEyaLhg85pFT4T0bzu8UsRH14O6TSQxgkEjmTsX+j9IFl56aCryPCKi8Kgy53/CfAoGAdV2kUFLPDb3WCJ1r1zKKRW1398ZKHtwO73xJYu1wg1Y40cNuyX23pj0M6IOh7zT24dZ/5ecc7tuQukw3qgprhDJFyQtHMzWwbBuw9WZO2blM6XX1vuEkLajkykihhggi12RSG3IuSqQ3ejwJkUi/jsYz/fwTwcAmSLQtV8UM5IECgYEAh4h1EkMx3NXzVFmLsb4QLMXw8+Rnn9oG+NGObldQ+nmknUPu7iz5kl9lTJy+jWtqHlHL8ZtV1cZZSZnFxX5WQH5/lcz/UD+GqWoSlWuTU34PPTJqLKSYgkoOJQDEZVMVphLySS9tuo+K/h10lRS1r9KDm3RZASa1JnnWopBZIz4= + + + X-CorrelationID + 1234 + + + Content-Type + text/plain + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/statemententries + true + GET + true + false + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + f222bc29-58a5-46fd-9fe5-fe1dce0f6189 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/statemententries + true + GET + true + false + + + + + + + + + Referer + http://channel.local/channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/statemententries + + + Platform-TenantId + ibank-usa + + + Postman-Token + f222bc29-58a5-46fd-9fe5-fe1dce0f6189 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/balance + true + GET + true + false + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + 4a43ef02-9568-45e4-bb42-f48c7b359d10 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/balance + true + GET + true + false + + + + + + + + + Referer + http://channel.local/channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/balance + + + Platform-TenantId + ibank-usa + + + Postman-Token + 4a43ef02-9568-45e4-bb42-f48c7b359d10 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/status + true + GET + true + false + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + fa6fdc8c-daac-4980-b3d7-a08ce17d6482 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + utf-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/status + true + GET + true + false + + + + + + + + + Referer + http://channel.local/channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/status + + + Platform-TenantId + ibank-usa + + + Postman-Token + fa6fdc8c-daac-4980-b3d7-a08ce17d6482 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/accountname + true + GET + true + false + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + d4db3d31-7ef6-481a-9ffc-572299ba2f28 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/accountname + true + GET + true + false + + + + + + + + + Referer + http://channel.local/channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/accountname + + + Platform-TenantId + ibank-usa + + + Postman-Token + d4db3d31-7ef6-481a-9ffc-572299ba2f28 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/transactions + true + GET + true + false + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + 991aa334-6ad9-44b2-8660-82b517bbfa23 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/transactions + true + GET + true + false + + + + + + + + + Referer + http://channel.local/channel/accounts/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/transactions + + + Platform-TenantId + ibank-usa + + + Postman-Token + 991aa334-6ad9-44b2-8660-82b517bbfa23 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/deposit + true + POST + true + true + + + + false + { + "amount": "304", + "type": "transfer", + "creditParty": [ + { + "key": "msisdn", + "value": "+919900878571" + } + ], + "currency": "USD" +} + = + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + 2fb6a82b-2c90-489a-aaba-4baaa6cd50ce + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/deposit + true + POST + true + true + + + + false + { + "amount": "304", + "type": "transfer", + "creditParty": [ + { + "key": "msisdn", + "value": "+919900878571" + } + ], + "currency": "USD" +} + = + + + + + + + + + Referer + http://channel.local/channel/deposit + + + Platform-TenantId + ibank-usa + + + Postman-Token + 2fb6a82b-2c90-489a-aaba-4baaa6cd50ce + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/customers/%7B%7BIdentifierType%7D%7D/%7B%7BIdentifierId%7D%7D/cpin + true + POST + true + true + + + + false + { + "existingPin": "String", + "pin": "String" +} + = + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + 362efaed-58f5-43f2-86f6-2497cb76eda8 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/customers + true + POST + true + true + + + + false + { + "identifierType": "String", + "IdentifierId": "String" +} + = + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + 90f53257-cc9d-4cf7-bc61-26088f1a6b22 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/heartbeat + true + GET + true + false + + + + + + + + + Postman-Token + 470ecb42-cdc3-4381-b0e5-52d0c803db0c + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/transfer/%7B%7BtransactionId%7D%7D + true + GET + true + false + + + + + + + + + Postman-Token + bc4060b4-71ef-4341-b606-24bf7cb10cc8 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/transfer + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710101999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710102999" + } + }, + "amount": { + "amount": 230, + "currency": "TZS" + } +} + = + + + + + + + + + Postman-Token + 8a3bd981-96b7-44a9-8b2e-de5932b8e823 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/transactionRequest + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710203999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710305999" + } + }, + "amount": { + "amount": 77, + "currency": "TZS" + } +} + = + + + + + + + + + Postman-Token + 4ef74e63-cfaa-4f34-9af7-3e32eba7ba6f + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/partyRegistration + true + POST + true + true + + + + false + { + "accountId":"9062b90de19b43989005", + "idType": "EMAIL", + "idValue": "test@test.hu" +} + = + + + + + + + + + Postman-Token + ff2e2956-7135-4769-850a-045905ac9526 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/transfer/%7B%7BtransactionId%7D%7D + true + GET + true + false + + + + + + + + + Platform-TenantId + {{PlatformTenant}} + + + Postman-Token + 848e386d-7546-418b-8c23-87503c70e55e + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/transfer/%7B%7BtransactionId%7D%7D + true + GET + true + false + + + + + + + + + Referer + http://channel.local/channel/transfer/%7B%7BtransactionId%7D%7D + + + Platform-TenantId + {{PlatformTenant}} + + + Postman-Token + 848e386d-7546-418b-8c23-87503c70e55e + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/transfer + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710101999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710102999" + } + }, + "amount": { + "amount": 230, + "currency": "TZS" + } +} + = + + + + + + + + + Platform-TenantId + {{PlatformTenant}} + + + Postman-Token + 9922539d-fc9a-4980-afe6-dd9bd1abc4db + + + X-PayeeDFSP-ID + {{payeeDFSPId}} + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/transfer + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710101999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710102999" + } + }, + "amount": { + "amount": 230, + "currency": "TZS" + } +} + = + + + + + + + + + Referer + http://channel.local/channel/transfer + + + Platform-TenantId + {{PlatformTenant}} + + + Postman-Token + 9922539d-fc9a-4980-afe6-dd9bd1abc4db + + + X-PayeeDFSP-ID + {{payeeDFSPId}} + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/transactionRequest + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710203999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710305999" + } + }, + "amount": { + "amount": 77, + "currency": "TZS" + } +} + = + + + + + + + + + Postman-Token + c57fec8b-cbb4-4864-a8c2-b481c175a361 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/transactionRequest + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710203999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "27710305999" + } + }, + "amount": { + "amount": 77, + "currency": "TZS" + } +} + = + + + + + + + + + Referer + http://channel.local/channel/transactionRequest + + + Postman-Token + c57fec8b-cbb4-4864-a8c2-b481c175a361 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/partyRegistration + true + POST + true + true + + + + false + { + "accountId":"9062b90de19b43989005", + "idType": "EMAIL", + "idValue": "test@test.hu" +} + = + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + 0890f80c-02f5-4179-9acb-173b1c4d00e6 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/partyRegistration + true + POST + true + true + + + + false + { + "accountId":"9062b90de19b43989005", + "idType": "EMAIL", + "idValue": "test@test.hu" +} + = + + + + + + + + + Referer + http://channel.local/channel/partyRegistration + + + Platform-TenantId + rhino + + + Postman-Token + 0890f80c-02f5-4179-9acb-173b1c4d00e6 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/txnState/%7B%7BX-CorrelationID%7D%7D + true + GET + true + false + + + + + + + + + requestType + transfers + + + Platform-TenantId + rhino + + + Postman-Token + 42cef3eb-a151-4977-a474-095bc27432a5 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/txnState/%7B%7BX-CorrelationID%7D%7D + true + GET + true + false + + + + + + + + + Referer + http://channel.local/channel/txnState/%7B%7BX-CorrelationID%7D%7D + + + requestType + transfers + + + Platform-TenantId + rhino + + + Postman-Token + 42cef3eb-a151-4977-a474-095bc27432a5 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/gsma/transfer + true + POST + true + true + + + + false + { + "requestingOrganisationTransactionReference": "string", + "originalTransactionReference": "string", + "subType": "string", + "type": "transfer", + "amount": "11.00", + "currency": "USD", + "descriptionText": "string", + "fees": [ + { + "feeType": "string", + "feeAmount": "11", + "feeCurrency": "USD" + } + ], + "geoCode": "37.423825,-122.082900", + "internationalTransferInformation": { + "quotationReference": "string", + "quoteId": "string", + "originCountry": "USA", + "deliveryMethod": "directtoaccount", + "receivingCountry": "USA", + "relationshipSender": "string", + "remittancePurpose": "string" + }, + "oneTimeCode": "string", + "receiverKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2000-11-20", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "senderKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2022-09-28T12:51:19.260+00:00", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "servicingIdentity": "string", + "requestDate": "2022-09-28T12:51:19.260+00:00", + "metadata": [ + { + "key": "string", + "value": "string" + } + ], + "creditParty": [ + { + "key": "msisdn", + "value": "+449999112" + } + ], + "debitParty": [ + { + "key": "msisdn", + "value": "+449999999" + } + ] +} + = + + + + + + + + + Platform-TenantId + rhino + + + X-CorrelationID + 12345 + + + Postman-Token + 44e387d4-015f-4427-80ec-c52116117d08 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/gsma/transfer + true + POST + true + true + + + + false + { + "requestingOrganisationTransactionReference": "string", + "originalTransactionReference": "string", + "subType": "string", + "type": "transfer", + "amount": "11.00", + "currency": "USD", + "descriptionText": "string", + "fees": [ + { + "feeType": "string", + "feeAmount": "11", + "feeCurrency": "USD" + } + ], + "geoCode": "37.423825,-122.082900", + "internationalTransferInformation": { + "quotationReference": "string", + "quoteId": "string", + "originCountry": "USA", + "deliveryMethod": "directtoaccount", + "receivingCountry": "USA", + "relationshipSender": "string", + "remittancePurpose": "string" + }, + "oneTimeCode": "string", + "receiverKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2000-11-20", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "senderKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2022-09-28T12:51:19.260+00:00", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "servicingIdentity": "string", + "requestDate": "2022-09-28T12:51:19.260+00:00", + "metadata": [ + { + "key": "string", + "value": "string" + } + ], + "creditParty": [ + { + "key": "msisdn", + "value": "+449999112" + } + ], + "debitParty": [ + { + "key": "msisdn", + "value": "+449999999" + } + ] +} + = + + + + + + + + + Referer + http://channel.local/channel/gsma/transfer + + + Platform-TenantId + rhino + + + X-CorrelationID + 12345 + + + Postman-Token + 44e387d4-015f-4427-80ec-c52116117d08 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/gsma/transaction + true + POST + true + true + + + + false + { + "requestingOrganisationTransactionReference": "string", + "subType": "inbound", + "type": "transfer", + "amount": "11", + "currency": "USD", + "descriptionText": "string", + "requestDate": "2022-09-28T12:51:19.260+00:00", + "customData": [ + { + "key": "string", + "value": "string" + } + ], + "payer": [ + { + "partyIdType": "MSISDN", + "partyIdIdentifier": "{{MSISDN}}" + } + ], + "payee": [ + { + "partyIdType": "accountId", + "partyIdIdentifier": "{{accountId}}" + } + ] +} + = + + + + + + + + + X-CorrelationID + 12345 + + + amsName + {{amsName}} + + + Postman-Token + efed9936-4031-4f72-9e6b-99894c4ad962 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + accountHoldingInstitutionId + {{accountHoldingInstitutionId}} + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/gsma/transaction + true + POST + true + true + + + + false + { + "requestingOrganisationTransactionReference": "string", + "subType": "inbound", + "type": "transfer", + "amount": "11", + "currency": "USD", + "descriptionText": "string", + "requestDate": "2022-09-28T12:51:19.260+00:00", + "customData": [ + { + "key": "string", + "value": "string" + } + ], + "payer": [ + { + "partyIdType": "MSISDN", + "partyIdIdentifier": "{{MSISDN}}" + } + ], + "payee": [ + { + "partyIdType": "accountId", + "partyIdIdentifier": "{{accountId}}" + } + ] +} + = + + + + + + + + + Referer + http://channel.local/channel/gsma/transaction + + + Postman-Token + efed9936-4031-4f72-9e6b-99894c4ad962 + + + Accept + */* + + + X-CorrelationID + 12345 + + + amsName + {{amsName}} + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + accountHoldingInstitutionId + {{accountHoldingInstitutionId}} + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/gsma/deposit + true + POST + true + true + + + + false + { + "requestingOrganisationTransactionReference": "string", + "originalTransactionReference": "string", + "subType": "string", + "type": "transfer", + "amount": "11.00", + "currency": "USD", + "descriptionText": "string", + "fees": [ + { + "feeType": "string", + "feeAmount": "11", + "feeCurrency": "USD" + } + ], + "geoCode": "37.423825,-122.082900", + "internationalTransferInformation": { + "quotationReference": "string", + "quoteId": "string", + "originCountry": "USA", + "deliveryMethod": "directtoaccount", + "receivingCountry": "USA", + "relationshipSender": "string", + "remittancePurpose": "string" + }, + "oneTimeCode": "string", + "receiverKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2000-11-20", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "senderKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2022-09-28T12:51:19.260+00:00", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "servicingIdentity": "string", + "requestDate": "2022-09-28T12:51:19.260+00:00", + "metadata": [ + { + "key": "string", + "value": "string" + } + ], + "creditParty": [ + { + "key": "msisdn", + "value": "+449999112" + } + ], + "debitParty": [ + { + "key": "msisdn", + "value": "+449999999" + } + ] +} + = + + + + + + + + + Platform-TenantId + {{PayeeTenantName}} + + + X-CorrelationID + 12345 + + + Postman-Token + 8d57472a-b1fd-4969-91b1-1d2e3b9c711a + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/gsma/deposit + true + POST + true + true + + + + false + { + "requestingOrganisationTransactionReference": "string", + "originalTransactionReference": "string", + "subType": "string", + "type": "transfer", + "amount": "11.00", + "currency": "USD", + "descriptionText": "string", + "fees": [ + { + "feeType": "string", + "feeAmount": "11", + "feeCurrency": "USD" + } + ], + "geoCode": "37.423825,-122.082900", + "internationalTransferInformation": { + "quotationReference": "string", + "quoteId": "string", + "originCountry": "USA", + "deliveryMethod": "directtoaccount", + "receivingCountry": "USA", + "relationshipSender": "string", + "remittancePurpose": "string" + }, + "oneTimeCode": "string", + "receiverKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2000-11-20", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "senderKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2022-09-28T12:51:19.260+00:00", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "servicingIdentity": "string", + "requestDate": "2022-09-28T12:51:19.260+00:00", + "metadata": [ + { + "key": "string", + "value": "string" + } + ], + "creditParty": [ + { + "key": "msisdn", + "value": "+449999112" + } + ], + "debitParty": [ + { + "key": "msisdn", + "value": "+449999999" + } + ] +} + = + + + + + + + + + Referer + http://channel.local/channel/gsma/deposit + + + Platform-TenantId + {{PayeeTenantName}} + + + X-CorrelationID + 12345 + + + Postman-Token + 8d57472a-b1fd-4969-91b1-1d2e3b9c711a + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/gsma/deposit + true + POST + true + true + + + + false + { + "requestingOrganisationTransactionReference": "string", + "originalTransactionReference": "string", + "subType": "string", + "type": "transfer", + "amount": "11.00", + "currency": "USD", + "descriptionText": "string", + "fees": [ + { + "feeType": "string", + "feeAmount": "11", + "feeCurrency": "USD" + } + ], + "geoCode": "37.423825,-122.082900", + "internationalTransferInformation": { + "quotationReference": "string", + "quoteId": "string", + "originCountry": "USA", + "deliveryMethod": "directtoaccount", + "receivingCountry": "USA", + "relationshipSender": "string", + "remittancePurpose": "string" + }, + "oneTimeCode": "string", + "receiverKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2000-11-20", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "senderKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2022-09-28T12:51:19.260+00:00", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "servicingIdentity": "string", + "requestDate": "2022-09-28T12:51:19.260+00:00", + "metadata": [ + { + "key": "string", + "value": "string" + } + ], + "creditParty": [ + { + "key": "msisdn", + "value": "+449999112" + } + ], + "debitParty": [ + { + "key": "msisdn", + "value": "+449999999" + } + ] +} + = + + + + + + + + + Platform-TenantId + {{PayeeTenantName}} + + + X-CorrelationID + 12345 + + + Postman-Token + 54cb6424-fb84-403f-b5e3-db8bf7091e18 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + channel.local + 0 + UTF-8 + /channel/gsma/deposit + true + POST + true + true + + + + false + { + "requestingOrganisationTransactionReference": "string", + "originalTransactionReference": "string", + "subType": "string", + "type": "transfer", + "amount": "11.00", + "currency": "USD", + "descriptionText": "string", + "fees": [ + { + "feeType": "string", + "feeAmount": "11", + "feeCurrency": "USD" + } + ], + "geoCode": "37.423825,-122.082900", + "internationalTransferInformation": { + "quotationReference": "string", + "quoteId": "string", + "originCountry": "USA", + "deliveryMethod": "directtoaccount", + "receivingCountry": "USA", + "relationshipSender": "string", + "remittancePurpose": "string" + }, + "oneTimeCode": "string", + "receiverKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2000-11-20", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "senderKyc": { + "birthCountry": "USA", + "contactPhone": "string", + "dateOfBirth": "2022-09-28T12:51:19.260+00:00", + "emailAddress": "string", + "employerName": "string", + "gender": "m", + "idDocument": [ + { + "idType": "passport", + "idNumber": "string", + "issueDate": "2022-09-28T12:51:19.260+00:00", + "expiryDate": "2022-09-28T12:51:19.260+00:00", + "issuer": "string", + "issuerPlace": "string", + "issuerCountry": "USA" + } + ], + "nationality": "USA", + "occupation": "string", + "postalAddress": { + "addressLine1": "string", + "addressLine2": "string", + "addressLine3": "string", + "city": "string", + "stateProvince": "string", + "postalCode": "string", + "country": "USA" + }, + "subjectName": { + "title": "string", + "firstName": "string", + "middleName": "string", + "lastName": "string", + "nativeName": "string" + } + }, + "servicingIdentity": "string", + "requestDate": "2022-09-28T12:51:19.260+00:00", + "metadata": [ + { + "key": "string", + "value": "string" + } + ], + "creditParty": [ + { + "key": "msisdn", + "value": "+449999112" + } + ], + "debitParty": [ + { + "key": "msisdn", + "value": "+449999999" + } + ] +} + = + + + + + + + + + Referer + http://channel.local/channel/gsma/deposit + + + Platform-TenantId + {{PayeeTenantName}} + + + X-CorrelationID + 12345 + + + Postman-Token + 54cb6424-fb84-403f-b5e3-db8bf7091e18 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel-gsma.local + 0 + http + UTF-8 + /heartbeat/ + true + GET + true + false + + + + + + + + + Postman-Token + 094c7d3c-2411-4a5b-8ad2-fc8ea2903960 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + Accept + application/json + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + Detected a redirect from the previous sample + channel-gsma.local + 0 + UTF-8 + /heartbeat + true + GET + true + false + + + + + + + + + Referer + http://channel-gsma.local/heartbeat/ + + + Postman-Token + 094c7d3c-2411-4a5b-8ad2-fc8ea2903960 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + Accept + application/json + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + false + + + + Detected the start of a redirect chain + channel-gsma.local + 0 + http + UTF-8 + /statemententries/%7B%7BtransactionReference%7D%7D + true + GET + true + false + + + + + + + + + X-Account-Holding-Institution-Identifier-Type + <string> + + + Postman-Token + ffdc28ae-f34c-4695-8ab2-0e558e08608f + + + Accept + application/json + + + X-User-Bearer + <string> + + + X-Account-Holding-Institution-Identifier + <string> + + + X-Client-Id + <string> + + + X-API-Key + <string> + + + X-Content-Hash + <string> + + + X-User-Credential-2 + <string> + + + X-Channel + <string> + + + X-User-Credential-1 + <string> + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + Detected a redirect from the previous sample + channel-gsma.local + 0 + UTF-8 + /statemententries/%7B%7BtransactionReference%7D%7D + true + GET + true + false + + + + + + + + + Referer + http://channel-gsma.local/statemententries/%7B%7BtransactionReference%7D%7D + + + X-Account-Holding-Institution-Identifier-Type + <string> + + + Postman-Token + ffdc28ae-f34c-4695-8ab2-0e558e08608f + + + Accept + application/json + + + X-User-Bearer + <string> + + + X-Account-Holding-Institution-Identifier + <string> + + + X-Client-Id + <string> + + + X-API-Key + <string> + + + X-Content-Hash + <string> + + + X-User-Credential-2 + <string> + + + X-Channel + <string> + + + X-User-Credential-1 + <string> + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + false + + + + Detected the start of a redirect chain + channel-gsma.local + 0 + http + UTF-8 + /bills/%7B%7BbillReference%7D%7D/payments + true + POST + true + true + + + + false + { + "serviceProviderPaymentReference": "string", + "requestingOrganisationTransactionReference": "string", + "paymentType": "partialpayment", + "amountPaid": "15.21", + "currency": "AED", + "customerReference": "string", + "requestingOrganisation": "string", + "supplementaryBillReferenceDetails": [ + { + "paymentReferenceType": "string", + "paymentReferenceValue": "string" + } + ], + "requestDate": "2022-09-29T07:45:19.744Z", + "customData": [ + { + "key": "string", + "value": "string" + } + ], + "metadata": [ + { + "key": "string", + "value": "string" + } + ], + "paidAmount": "15.21" +} + = + + + + + + + + + X-Account-Holding-Institution-Identifier-Type + <string> + + + Postman-Token + ba7c4b93-f387-4161-9ed6-4bbd60cb4286 + + + Accept + application/json + + + X-User-Bearer + <string> + + + X-Callback-URL + <uri> + + + X-Account-Holding-Institution-Identifier + <string> + + + X-CorrelationID + <string> + + + X-Client-Id + <string> + + + X-API-Key + <string> + + + X-Content-Hash + <string> + + + X-User-Credential-2 + <string> + + + X-Channel + <string> + + + Content-Type + application/json + + + X-User-Credential-1 + <string> + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + Detected a redirect from the previous sample + channel-gsma.local + 0 + UTF-8 + /bills/%7B%7BbillReference%7D%7D/payments + true + POST + true + true + + + + false + { + "serviceProviderPaymentReference": "string", + "requestingOrganisationTransactionReference": "string", + "paymentType": "partialpayment", + "amountPaid": "15.21", + "currency": "AED", + "customerReference": "string", + "requestingOrganisation": "string", + "supplementaryBillReferenceDetails": [ + { + "paymentReferenceType": "string", + "paymentReferenceValue": "string" + } + ], + "requestDate": "2022-09-29T07:45:19.744Z", + "customData": [ + { + "key": "string", + "value": "string" + } + ], + "metadata": [ + { + "key": "string", + "value": "string" + } + ], + "paidAmount": "15.21" +} + = + + + + + + + + + Referer + http://channel-gsma.local/bills/%7B%7BbillReference%7D%7D/payments + + + X-Account-Holding-Institution-Identifier-Type + <string> + + + Postman-Token + ba7c4b93-f387-4161-9ed6-4bbd60cb4286 + + + Accept + application/json + + + X-User-Bearer + <string> + + + X-Callback-URL + <uri> + + + X-Account-Holding-Institution-Identifier + <string> + + + X-CorrelationID + <string> + + + X-Client-Id + <string> + + + X-API-Key + <string> + + + X-Content-Hash + <string> + + + X-User-Credential-2 + <string> + + + X-Channel + <string> + + + Content-Type + application/json + + + X-User-Credential-1 + <string> + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + false + + + + Detected the start of a redirect chain + channel-gsma.local + 0 + http + UTF-8 + /responses/12345 + true + GET + true + false + + + + + + + + + Postman-Token + 61eac0a6-8b85-44f7-9546-9e8f3a449c19 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + Accept + application/json + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + Detected a redirect from the previous sample + channel-gsma.local + 0 + UTF-8 + /responses/12345 + true + GET + true + false + + + + + + + + + Referer + http://channel-gsma.local/responses/12345 + + + Postman-Token + 61eac0a6-8b85-44f7-9546-9e8f3a449c19 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + Accept + application/json + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/%7B%7Bprovider%7D%7D/transfer + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+449999999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+449999112" + } + }, + "amount": { + "amount": 6, + "currency": "TZS" + } +} + = + + + + + + + + + Platform-TenantId + tn05 + + + Postman-Token + 76c6bb14-6f0f-400c-8339-5a6ea2cd8766 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/%7B%7Bprovider%7D%7D/merchantpay + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+449999999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+449999112" + } + }, + "amount": { + "amount": 6, + "currency": "TZS" + } +} + = + + + + + + + + + Platform-TenantId + tn05 + + + Postman-Token + f977707c-b977-482b-9fa5-e833b259af11 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/%7B%7Bprovider%7D%7D/merchantpay/authcode/%7B%7BauthorizationCode%7D%7D + true + POST + true + true + + + + false + { + "payer": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+449999999" + } + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+449999112" + } + }, + "amount": { + "amount": 6, + "currency": "TZS" + } +} + = + + + + + + + + + Platform-TenantId + tn05 + + + Postman-Token + a7de37be-edf8-408d-9ae9-345d69e76da9 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/%7B%7Bprovider%7D%7D/inttransfer + true + POST + true + true + + + + false + { + "amount": "54", + "type": "transfer", + "requestingLei": "ibank-usa", + "receivingLei": "ibank-india", + "creditParty": [ + { + "key": "msisdn", + "value": "919900878571" + } + ], + "currency": "USD", + "debitParty": [ + { + "key": "msisdn", + "value": "7543010" + } + ], + "internationalTransferInformation":{ + "originCountry":"US", + "receivingCountry":"IN", + "receivingCurrency":"INR", + "currencyPair":"INR/USD" + } +} + = + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + 2b296a14-c085-4c72-929c-57def13a87e6 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + http + UTF-8 + /channel/%7B%7Bprovider%7D%7D/deposit + true + POST + true + true + + + + false + { + "amount": "304", + "type": "transfer", + "creditParty": [ + { + "key": "msisdn", + "value": "+919900878571" + } + ], + "currency": "USD" +} + = + + + + + + + + + Platform-TenantId + ibank-usa + + + Postman-Token + 1652a7a4-806b-4467-b24c-af66d77f00e0 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + bulk-connector.local + 0 + https + UTF-8 + /channel/bulk/transfer/ph-ee-bulk-demo-8.csv + true + GET + true + false + + + + + + + + + Platform-TenantId + rhino + + + X-CorrelationID + 12345 + + + Postman-Token + 65fcb18b-ecc5-4325-8339-4743c4257e0e + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + bulk-connector.local + 0 + https + UTF-8 + /batchtransactions + true + POST + true + false + + + + + + + + + Purpose + test payment + + + Platform-TenantId + rhino + + + Postman-Token + c9719591-8016-4833-a556-550826915001 + + + X-PayeeDFSP-ID + {{payeeDFSPId}} + + + type + csv + + + Accept + */* + + + filename + ph-ee-bulk-demo-7.csv + + + X-CorrelationID + 1234 + + + X-Signature + TvahZAr7Mruj4IuSDqDmZIT+3FxtbgloQENlihURwIA4v2C71aGMNeHf86gh5UogkjW+cGuVBDp/wxVJAcBF9UTl3izi0kyc/ukDtaDlBZlMoymTFWF7AldXZ40nNiKOzCIgCmOi/Xdq+D2LQTTHAJdH9Zn0VJrynJv31UlctL6P+ToALKO92k8vbuhihnLRSyhl63wDw5v+Ww+q+dAoE56y7XUt1ypOZEQrBV80QqF+yrKWKmCgtWZSMD3H6tm2AXrUbKeIProm8Q2J++AHGRpVwW85O6cTAL6U3RjIqa7upG9ANcoiHluAJ7VvtyA4LA8i6lbeNkgJAyHHw3iISg== + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + + + + + + false + + + + Detected the start of a redirect chain + bulk-connector.local + 0 + http + UTF-8 + /batchtransactions + true + POST + true + true + + + + false + [ + { + "creditParty": [ + { + "key": "msisdn", + "value": "8837461856" + } + ], + "debitParty": [ + { + "key": "accountnumber", + "value": "003001003874120160" + } + ], + "subType": "SLCB", + "amount": "820.00", + "currency": "RWF", + "descriptionText": "Test Payment" + }, + { + "creditParty": [ + { + "key": "msisdn", + "value": "32131461856" + } + ], + "debitParty": [ + { + "key": "accountnumber", + "value": "21314556003874120160" + } + ], + "subType": "SLCB", + "amount": "20.00", + "currency": "RWF", + "descriptionText": "Test Payment" + } +] + = + + + + + + + + + Purpose + test payment + + + Platform-TenantId + rhino + + + Postman-Token + 1ba5c123-37c2-4c0b-b33c-cf5240181b2a + + + type + raw + + + Accept + */* + + + X-CorrelationID + 1234 + + + X-Signature + TvahZAr7Mruj4IuSDqDmZIT+3FxtbgloQENlihURwIA4v2C71aGMNeHf86gh5UogkjW+cGuVBDp/wxVJAcBF9UTl3izi0kyc/ukDtaDlBZlMoymTFWF7AldXZ40nNiKOzCIgCmOi/Xdq+D2LQTTHAJdH9Zn0VJrynJv31UlctL6P+ToALKO92k8vbuhihnLRSyhl63wDw5v+Ww+q+dAoE56y7XUt1ypOZEQrBV80QqF+yrKWKmCgtWZSMD3H6tm2AXrUbKeIProm8Q2J++AHGRpVwW85O6cTAL6U3RjIqa7upG9ANcoiHluAJ7VvtyA4LA8i6lbeNkgJAyHHw3iISg== + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + + + + + Detected the start of a redirect chain + bulk-connector.local + 0 + https + UTF-8 + /bulk/transfer/742caccd-58d4-4c7d-bc5a-7b030c8b3afa/ph-ee-bulk-demo-6.csv + true + POST + true + false + + + + + + + + + X-Callback-URL + bulk-connector.local/simulate + + + Platform-TenantId + rhino + + + X-CorrelationID + 12345 + + + Postman-Token + 95fbb4b3-03b2-4706-8d11-cae768ebbe88 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + https + UTF-8 + /channel/bulk/lookup + true + POST + true + true + true + false + + + + false + requestId + 3a4dfab5-0f4f-4e78-b6b5-1aff3859d4e8 + = + true + + + false + purpose + iliydufkgiku + = + true + + + + + + + + + Platform-TenantId + rhino + + + X-CorrelationID + 12345 + + + Postman-Token + 9d2174ed-762e-4df6-855b-f880dfa85164 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + https + UTF-8 + /api/v1/batch + true + GET + true + false + + + + false + batchId + null + = + true + + + false + X-CorrelationID + 12345 + = + true + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Platform-TenantId + rhino + + + Postman-Token + 2c6c2944-297a-45b8-b06f-ced1e8a0cc65 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + https + UTF-8 + /api/v1/batch/detail + true + GET + true + false + + + + false + batchId + null + = + true + + + true + pageSize + {{pageSize}} + = + true + + + false + X-CorrelationID + 12345 + = + true + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Referer + http://localhost:4200/ + + + Accept-Language + en-US,en;q=0.5 + + + Platform-TenantId + rhino + + + Postman-Token + 0de1fc3d-2a72-4978-ab92-2820c339d699 + + + Origin + http://localhost:4200 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:90.0) Gecko/20100101 Firefox/90.0 + + + Accept + application/json, text/plain, */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + https + UTF-8 + /api/v1/batch/detail + true + GET + true + false + + + + false + batchId + null + = + true + + + true + pageNo + {{pageNo}} + = + true + + + true + pageSize + {{pageSize}} + = + true + + + true + status + {{status}} + = + true + + + false + X-CorrelationID + 12345 + = + true + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Referer + http://localhost:4200/ + + + Accept-Language + en-US,en;q=0.5 + + + Platform-TenantId + rhino + + + Postman-Token + 4e745eef-cd1b-43d6-bf79-c1f2007f22d3 + + + Origin + http://localhost:4200 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:90.0) Gecko/20100101 Firefox/90.0 + + + Accept + application/json, text/plain, */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + https + UTF-8 + /api/v1/batches + true + GET + true + false + + + + false + page + 2 + = + true + + + false + size + 10 + = + true + + + false + sortedBy + requestFile + = + true + + + false + sortedOrder + asc + = + true + + + false + X-CorrelationID + 12345 + = + true + + + + + + + + + Authorization + Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaWRlbnRpdHktcHJvdmlkZXIiLCJyaGlubyJdLCJ1c2VyX25hbWUiOiJtaWZvcyIsInNjb3BlIjpbImlkZW50aXR5Il0sImV4cCI6MTcyNTUyOTYzMCwiYXV0aG9yaXRpZXMiOlsiUkVGVU5EIiwiQUxMX0ZVTkNUSU9OUyJdLCJqdGkiOiJZckJlQlNJRTVLQ1hkTDdsbkZ6Z1dNVExNTDQ9IiwiY2xpZW50X2lkIjoiY2xpZW50In0.z3G3AnlXIFanzVa22w1fjWhIn0DYkhYmJqsy0WbhQI2xsoLqWcai15pkJQaaY5m0QfR_Rp-tmc9vRiX9i93kdSs20gTTnwmQVSwJviQJ67k_PU2CgFDkVMSBwib-LSmj1MNdSzYYBisD6Ix3_suWX5zzNNBfqEOZpUpQOQhDgJSvXGYJ7cCRw0fWRHITTCq7hM0mfbC4Ojg67Ku_RXycYCvrXp65w1wdPBK5MrAS3ynbP63IABivnPLPtrgB1VJx10V2g524hyuLoEAyUnzhHK1PBPuV_AmFY0dsbe_7q460xTt6K30D34cJ6L1E7dlhxjnCF2Rli07QyKB5L0P2Zg + + + Platform-TenantId + rhino + + + Postman-Token + 2c54d24a-c477-474b-a652-d2d5a1559688 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + ops-bk.local + 0 + https + UTF-8 + /api/v1/batches/null + true + GET + true + false + + + + false + associations + all + = + true + + + + + + + + + Platform-TenantId + rhino + + + Postman-Token + a3151384-f812-42a6-8101-b2c759b26b64 + + + X-Correlation-ID + 12345 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + bulk-connector.local + 0 + https + UTF-8 + /batchtransactions + true + POST + true + true + + + + false + [ + { + "creditParty": [ + { + "key": "msisdn", + "value": "8837461856" + } + ], + "debitParty": [ + { + "key": "accountnumber", + "value": "003001003874120160" + } + ], + "subType": "SLCB", + "amount": "820.00", + "currency": "RWF", + "descriptionText": "Test Payment" + }, + { + "creditParty": [ + { + "key": "msisdn", + "value": "32131461856" + } + ], + "debitParty": [ + { + "key": "accountnumber", + "value": "21314556003874120160" + } + ], + "subType": "SLCB", + "amount": "20.00", + "currency": "RWF", + "descriptionText": "Test Payment" + } +] + = + + + + + + + + + Purpose + test payment + + + Platform-TenantId + rhino + + + Postman-Token + b34b42d2-6696-40a6-b02f-b47ba45b6350 + + + type + raw + + + Accept + */* + + + X-CorrelationID + 1234 + + + X-Signature + pTd1iTG6K0wkqXsAwO23atDMf24ve3S0LH9D6tzMkc5jQ7zknESerWoKun17gAR8X+cSerAIZ5T6xuWd3AYvRx/nHNintXWCON1optFfmWSYcY7LMkZ0Prn0RUkEhzMKeHf27/DVbgP/A6RwInIKnbd/+jjqG0fjIMYM6r7DZVz76kEUwprWBkThWeKDB5g8Vyb9pdL3KlDWEoTpFYZoxn+R4KRoGEvpNBvtABOmLK22DTEgH1E9xBYIITLV8pLj1dM9Tm9QHhLW3W1t4gtWVkadQ0p4AD7qu91ClhJxDSXqbCaalkKxye3fiX+wGJCghV4iDyA2Os2ggJCWNOWwlw== + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + channel.local + 0 + https + UTF-8 + /channel/collection + true + POST + true + true + + + + false + { + "payer": [ + { + "key": "MSISDN", + "value": "254708374149" + }, + { + "key": "ACCOUNTID", + "value": "24450523" + } + ], + "amount": { + "amount": "1", + "currency": "USD" + }, + "transactionType": { + "scenario": "MPESA", + "subScenario": "BUYGOODS", + "initiator": "PAYEE", + "initiatorType": "BUSINESS" + } +} + = + + + + + + + + + Platform-TenantId + rhino + + + X-CorrelationID + 12345 + + + Postman-Token + 4d7e7a24-283b-4d93-8879-5b5da9e7dba3 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + {{mpesahostname}} + 0 + http + UTF-8 + /buygoods/callback + true + POST + true + true + + + + false + { + "Body": { + "stkCallback": { + "MerchantRequestID": "61034-2694171-1", + "CheckoutRequestID": "ws_CO_101120211333024994", + "ResultCode": 1037, + "ResultDesc": "DS timeout." + }, + "CallbackMetadata":{ + "Item":[ + { + "Name":"Amount", + "Value":10 + }, + { + "Name":"MpesaReceiptNumber", + "Value":"MRLSJHDH9" + } + ] + } + } +} + = + + + + + + + + + Postman-Token + 425399e5-cad0-4f48-8e4c-4e99388c74d6 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + notifications.local + 0 + http + UTF-8 + /sms/callback + true + POST + true + true + + + + false + [ + { + "id": "201", + "externalId": "SM7b1b75ffa3f5737a", + "deliveredOnDate": "2022-01-11", + "deliveryStatus": 300, + "hasError": false, + "errorMessage": null, + "bridgeId": 2, + "tenantId": 1 + } +] + = + + + + + + + + + X-CorrelationID + {{clientCorrelationId}} + + + Postman-Token + cb28eb06-26bd-45de-9465-e978cadda847 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + messagegateway.local + 0 + http + UTF-8 + /sms + true + POST + true + true + + + + false + [ + { + "internalId": "20", + "mobileNumber": "+15005550012", + "message": "Random Message", + "providerId": 2 + } +] + = + + + + + + + + + Fineract-Platform-TenantId + default + + + Fineract-Tenant-App-Key + 123456543234abdkdkdkd + + + X-CorrelationID + {{clientCorrelationId}} + + + Postman-Token + 3d26cdee-9d82-4bb9-bf16-e9400f7909d9 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + messagegateway.local + 0 + http + UTF-8 + /telerivet/report/ + true + POST + true + true + + + + false + { + "contact_id": "CT190322d3246e0a2f", + "contact[conversation_status]": "closed", + "contact[id]": "CT190322d3246e0a2f", + "contact[incoming_message_count]": 0, + "contact[last_message_id]": "SM8edad9e1caf03b04", + "contact[last_message_time]": 1641306324, + "contact[last_outgoing_message_time]": 1641306324, + "contact[message_count]": 17, + "contact[name]": "+15005550012", + "contact[outgoing_message_count]": 17, + "contact[phone_number]": "+15005550012", + "contact[project_id]": "PJ5ff552ce01d2978c", + "contact[send_blocked]": 0, + "contact[time_created]": 1641227864, + "contact[time_updated]": 1641227864, + "content": "The transaction for account number:$account for amount:$amount has failed on $date with following transaction id: $transactionid", + "direction": "outgoing", + "error_message": " ", + "event": "send_status", + "from_number": "555-1212", + "id": "SM8edad9e1caf03b04", + "message_type": "sms", + "phone_id": "PNa2d2c147eb96c34d", + "priority": 1, + "project_id": "PJ5ff552ce01d2978c", + "secret": " ", + "simulated": 1, + "source": "api", + "starred": 0, + "status": "delivered", + "time_created": 1641306324, + "time_sent": 1641306324, + "time_updated": 1641306324, + "to_number": "+15005550012", + "track_clicks": 0, + "user_id": "URfabcdb9eb26ca257" +} + = + + + + + + + + + X-CorrelationID + {{clientCorrelationId}} + + + Postman-Token + d79f0153-16e6-4eee-aee0-290182baa9f0 + + + Content-Type + application/x-www-form-urlencoded + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /channel/workflow/%7B%7BBpmnProcessId%7D%7D + true + POST + true + true + + + + false + { + "var1": "val1", + "var2": "val2", + "var3": "val3" +} + = + + + + + + + + + Postman-Token + 96ec7eea-3d6d-4f08-b589-22a1c35a337b + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /zeebe/upload + true + POST + true + false + + + + + + + + + Postman-Token + 8a60e248-3cd9-47d1-9c49-34d94b3a511e + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /channel/workflow/ + true + PUT + true + true + + + + false + { + "processId": [123, 456, 789] +} + = + + + + + + + + + Postman-Token + 3e10320a-6711-4d05-b949-1688506ca795 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /es/health + true + GET + true + false + + + + + + + + + Postman-Token + b2b46363-ce10-4f50-8366-bdeaa6ba567a + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /channel/process + true + GET + true + false + + + + + + + + + Postman-Token + 86440e6d-ecc8-4937-99a0-257cb5a8de4a + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /channel/workflow/cancelbyvalue + true + POST + true + true + + + + false + { + "key": "initiatorFspId", + "value": "\"ibank-usa\"" +} + = + + + + + + + + + Postman-Token + b267c7b7-58d8-4514-bf52-c181934c470a + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /channel/process/variable/%7B%7BProcessInstanceKey%7D%7D + true + GET + true + false + + + + + + + + + Postman-Token + 38e202d1-b01d-4bd9-9809-dadf42cf2126 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /channel/process/%7B%7BProcessDefinitionKey%7D%7D/task/ + true + GET + true + false + + + + + + + + + Postman-Token + 627835ae-b793-4546-9d86-9f75a7cea61a + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /channel/process/%7B%7BProcessInstanceId%7D%7D + true + GET + true + false + + + + + + + + + Postman-Token + 1fcde1a7-fa34-4dcc-92b0-9e586c03bbda + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + zeebeops.local + 0 + http + UTF-8 + /channel/workflow/%7B%7BWorkflowInstanceKey%7D%7D/cancel + true + POST + true + false + + + + + + + + + Postman-Token + 423c483b-bfaa-4fd7-8622-a503aa73cc49 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + {{mpesahostname}} + 0 + http + UTF-8 + /validation + true + POST + true + true + + + + false + { + "TransactionType":"Pay Bill", + "TransID":"8335b60090979AvUefSR", + "TransTime":"20191122063845", + "TransAmount":"1", + "BusinessShortCode":"24322607", + "BillRefNumber":"24322607", + "InvoiceNumber":"", + "OrgAccountBalance":"49197.00", + "ThirdPartyTransID":"", + "MSISDN":"254797668592", + "FirstName":"John" +} + = + + + + + + + + + Postman-Token + 757a8f57-1198-4f87-9c23-dfe498452541 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + {{mpesahostname}} + 0 + http + UTF-8 + /confirmation + true + POST + true + true + + + + false + { + "TransactionType":"Pay Bill", + "TransID":"8335b60090979AvUefSR", + "TransTime":"20191122063845", + "TransAmount":"1", + "BusinessShortCode":"24322607", + "BillRefNumber":"24322607", + "InvoiceNumber":"", + "OrgAccountBalance":"49197", + "ThirdPartyTransID":"", + "MSISDN":"254797668592", + "FirstName":"John" +} + = + + + + + + + + + Postman-Token + 66679e56-2b97-4da2-a845-7e37dea75855 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 10 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + identity-mapper.local + 0 + https + UTF-8 + /beneficiary + true + POST + true + true + + + + false + { + "requestID": "915251236706", + "beneficiaries": [ + { + "payeeIdentity": "27713803912", + "paymentModality": "01", + "financialAddress": "589", + "bankingInstitutionCode": "gorilla" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 06712ae1-ef0a-43a2-af00-cfb3fa78d94e + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + identity-mapper.local + 0 + https + UTF-8 + /beneficiary + true + POST + true + true + + + + false + { + "requestID": "915251236706", + "beneficiaries": [ + { + "payeeIdentity": "27713803912", + "paymentModality": "01", + "financialAddress": "589", + "bankingInstitutionCode": "gorilla" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 6da444f6-3597-4849-92ac-592dd84567b4 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + identity-mapper.local + 0 + https + UTF-8 + /beneficiary + true + POST + true + true + + + + false + { + "requestID": "915251236706", + "beneficiaries": [ + { + "payeeIdentity": "27713803912", + "paymentModality": "01", + "financialAddress": "589", + "bankingInstitutionCode": "gorilla" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 25a27ddf-93ec-4b58-9264-7d85f6b05bc4 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + identity-mapper.local + 0 + https + UTF-8 + /beneficiary + true + POST + true + true + + + + false + { + "requestID": "915251236706", + "beneficiaries": [ + { + "payeeIdentity": "27713803912", + "paymentModality": "01", + "financialAddress": "589", + "bankingInstitutionCode": "gorilla" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + dea3357f-fbc1-4d72-a1c0-f6d06b00d0b6 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + identity-mapper.local + 0 + https + UTF-8 + /beneficiary + true + POST + true + true + + + + false + { + "requestID": "915251236706", + "beneficiaries": [ + { + "payeeIdentity": "27713803912", + "paymentModality": "01", + "financialAddress": "589", + "bankingInstitutionCode": "gorilla" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 759f09f6-5c80-4add-9ece-4f4d53f11059 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + identity-mapper.local + 0 + https + UTF-8 + /beneficiary + true + POST + true + true + + + + false + { + "requestID": "915251236706", + "beneficiaries": [ + { + "payeeIdentity": "27713803912", + "paymentModality": "01", + "financialAddress": "589", + "bankingInstitutionCode": "gorilla" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + c060b047-50a0-495f-8f15-b3fc606d7843 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + identity-mapper.local + 0 + https + UTF-8 + /beneficiary + true + POST + true + true + + + + false + { + "requestID": "915251236706", + "beneficiaries": [ + { + "payeeIdentity": "27713803912", + "paymentModality": "01", + "financialAddress": "589", + "bankingInstitutionCode": "gorilla" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 17d53ec5-4864-40e3-810d-bd51bbcea096 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + identity-mapper.local + 0 + https + UTF-8 + /beneficiary + true + POST + true + true + + + + false + { + "requestID": "915251236706", + "beneficiaries": [ + { + "payeeIdentity": "27713803912", + "paymentModality": "01", + "financialAddress": "589", + "bankingInstitutionCode": "gorilla" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 9e178b8f-a1d4-45a4-8ef7-49f2c707dc71 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 10 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers + true + POST + true + true + + + + false + { + "requestID": "849324499155", + "batchID": "045155518258", + "voucherInstructions": [ + { + "instructionID": "1202383344325434", + "groupCode": "021", + "currency": "USD", + "amount": 5009, + "payeeFunctionalID": "63310590322288932633", + "narration": "Social Support Payment for the Month of Jan" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 84d31ab8-9641-4727-a243-9f0dff3c32cc + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers?command=activate + true + PUT + true + true + + + + false + { + "requestID": "849324499155", + "batchID": "045155518258", + "voucherInstructions": [ + { + "serialNumber": "16939790248654", + "status": "02" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + b833cfad-dca2-457c-8f80-bf76f3d7e1de + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers?command=suspend + true + PUT + true + true + + + + false + { + "requestID": "849324499155", + "batchID": "045155518258", + "voucherInstructions": [ + { + "serialNumber": "16895906640276", + "status": "06" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 86fc3b3b-6b2a-44fc-bfe3-c5a8bdf2c413 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers?command=cancel + true + POST + true + true + + + + false + { + "requestID": "849324499155", + "batchID": "045155518258", + "voucherInstructions": [ + { + "serialNumber": "16895845478866", + "status": "03" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + aec32a1a-6b75-4115-892a-b4e8b38c8e2e + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers?command=reactivate + true + PUT + true + true + + + + false + { + "requestID": "849324499155", + "batchID": "045155518258", + "voucherInstructions": [ + { + "serialNumber": "16895906640276", + "status": "02" + } + ] +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + e87d4847-bcba-488d-a1fd-5dee215e064b + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers?command=redeem + true + POST + true + true + + + + false + { + "requestId": "849324499155", + "agentId": "1234567890", + "voucherSecretNumber": "168959066402710531" + } + + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 4443f85b-f8b1-4128-af54-e1837cc194b1 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers?command=redeemPay + true + PUT + true + true + + + + false + { + "requestId": "849324499155", + "agentId": "1234567890", + "voucherSecretNumber": "168975377470710722" + } + + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 5f0ac987-5dc6-4a4c-b467-c0ba7b1df9f9 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /voucher/validity + true + GET + true + false + + + + false + isValid + true + = + true + + + false + serialNumber + 16939790248654 + = + true + + + + + + + + + X-CallbackURL + http://example.com/callback + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + a3e64bb0-40ed-49cb-98f9-00256b5b3d5b + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers/%7B%7BvoucherNumber%7D%7D + true + GET + true + false + + + + + + + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + 802397c2-1287-4a97-bcd2-c3806bd4abbf + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + vouchers.local + 0 + http + UTF-8 + /vouchers + true + GET + true + false + + + + false + page + 0 + = + true + + + false + size + 10 + = + true + + + + + + + + + X-Registering-Institution-ID + my-institution-id + + + Postman-Token + d5292fec-6a5b-41e7-af16-cf61c074a725 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.40.0 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + 1 + 1 + true + continue + + 1 + false + + + + + + + false + + + + Detected the start of a redirect chain + bill-pay.local + 0 + http + UTF-8 + /bills/%7B%7BbillId%7D%7D + true + GET + true + false + + + + + + + + + X-CallbackURL + http://example.com/callback + + + Platform-TenantId + rhino + + + X-CorrelationID + 1234 + + + Payer-FSP-Id + {{PayeeTenantName}} + + + Postman-Token + d11c1ee1-03ca-4b05-b26e-5be628050984 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + Detected a redirect from the previous sample + bill-pay.local + 0 + UTF-8 + /bills/%7B%7BbillId%7D%7D + true + GET + true + false + + + + + + + + + Referer + http://bill-pay.local/bills/%7B%7BbillId%7D%7D + + + X-CallbackURL + http://example.com/callback + + + Platform-TenantId + rhino + + + X-CorrelationID + 1234 + + + Payer-FSP-Id + {{PayeeTenantName}} + + + Postman-Token + d11c1ee1-03ca-4b05-b26e-5be628050984 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + Detected the start of a redirect chain + bill-pay.local + 0 + http + UTF-8 + /paymentNotifications + true + POST + true + true + + + + false + { + "billInquiryRequestId": "12e2cedc-73", + "billId": "001", + "paymentReferenceID": "8f353842-451c-4" +} + = + + + + + + + + + X-CallbackURL + http://example.com/callback + + + Postman-Token + d7291560-e0cb-4049-b3d1-af067129a133 + + + Accept + */* + + + X-CorrelationID + 1234 + + + X-Platform-TenantId + rhino + + + X-PayerFSP-Id + {{PayeeTenantName}} + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + Detected a redirect from the previous sample + bill-pay.local + 0 + UTF-8 + /paymentNotifications + true + POST + true + true + + + + false + { + "billInquiryRequestId": "12e2cedc-73", + "billId": "001", + "paymentReferenceID": "8f353842-451c-4" +} + = + + + + + + + + + Referer + http://bill-pay.local/paymentNotifications + + + X-CallbackURL + http://example.com/callback + + + Postman-Token + d7291560-e0cb-4049-b3d1-af067129a133 + + + Accept + */* + + + X-CorrelationID + 1234 + + + X-Platform-TenantId + rhino + + + X-PayerFSP-Id + {{PayeeTenantName}} + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + false + + + + Detected the start of a redirect chain + bill-pay.local + 0 + http + UTF-8 + /billTransferRequests + true + POST + true + true + + + + false + { + "clientCorrelationId": "123445", + "billID": "12345", + "requestType": "00", + "payerFspDetails": { + "payerFSPID": "lion", + "financialAddress": "1223455" + }, + "alias": null, + "billDetails": { + "billerName": "Test", + "amount": 100.0 + } +} + = + + + + + + + + + X-Biller-Id + GovBill + + + Postman-Token + 4d3ce05e-5778-4cdf-947b-e2d86bfa2581 + + + Accept + */* + + + X-Callback-URL + http://example.com/callback + + + X-Platform-TenantId + rhino + + + Content-Type + application/json + + + X-Client-Correlation-ID + 12345 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + Detected a redirect from the previous sample + bill-pay.local + 0 + UTF-8 + /billTransferRequests + true + POST + true + true + + + + false + { + "clientCorrelationId": "123445", + "billID": "12345", + "requestType": "00", + "payerFspDetails": { + "payerFSPID": "lion", + "financialAddress": "1223455" + }, + "alias": null, + "billDetails": { + "billerName": "Test", + "amount": 100.0 + } +} + = + + + + + + + + + Referer + http://bill-pay.local/billTransferRequests + + + X-Biller-Id + GovBill + + + Postman-Token + 4d3ce05e-5778-4cdf-947b-e2d86bfa2581 + + + Accept + */* + + + X-Callback-URL + http://example.com/callback + + + X-Platform-TenantId + rhino + + + Content-Type + application/json + + + X-Client-Correlation-ID + 12345 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + false + + + + Detected the start of a redirect chain + bill-pay.local + 0 + http + UTF-8 + /billTransferRequests + true + PUT + true + true + + + + false + { + "clientCorrelationId": "123445", + "billId": "12345", + "requestType": "00", + "payerFspDetail": { + "payerFspId": "lion", + "financialAddress": "1223455" + }, + "alias": null, + "bill": { + "billerName": "Test", + "amount": 100.0 + } +} + = + + + + + + + + + X-Biller-Id + GovBill + + + Postman-Token + 014e4c9f-b6ed-4b3e-960a-95624ec34cb8 + + + Accept + */* + + + X-Callback-URL + http://example.com/callback + + + X-Platform-TenantId + rhino + + + Content-Type + application/json + + + X-Client-Correlation-ID + 12345 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + Detected a redirect from the previous sample + bill-pay.local + 0 + UTF-8 + /billTransferRequests + true + PUT + true + true + + + + false + { + "clientCorrelationId": "123445", + "billId": "12345", + "requestType": "00", + "payerFspDetail": { + "payerFspId": "lion", + "financialAddress": "1223455" + }, + "alias": null, + "bill": { + "billerName": "Test", + "amount": 100.0 + } +} + = + + + + + + + + + Referer + http://bill-pay.local/billTransferRequests + + + X-Biller-Id + GovBill + + + Postman-Token + 014e4c9f-b6ed-4b3e-960a-95624ec34cb8 + + + Accept + */* + + + X-Callback-URL + http://example.com/callback + + + X-Platform-TenantId + rhino + + + Content-Type + application/json + + + X-Client-Correlation-ID + 12345 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + false + + + + {{connectorbulkhostname}} + 0 + http + UTF-8 + /billTransferRequests + true + POST + true + true + + + + false + { + +} + = + + + + + + + + + X-Biller-Id + GovBill + + + Postman-Token + b6eb5106-68fe-41b9-895b-1b63ab8bf2c2 + + + Accept + */* + + + X-Callback-URL + http://example.com/callback + + + X-Platform-TenantId + rhino + + + Content-Type + application/json + + + X-Client-Correlation-ID + 12345 + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + + + + + + false + + + + {{connectorcrmhostname}} + 0 + http + UTF-8 + /bills/%7B%7BbillId%7D%7D + true + GET + true + false + + + + + + + + + X-CallbackURL + http://example.com/callback + + + Platform-TenantId + rhino + + + X-CorrelationID + f56caf0b-377d-4a1f-8ac1-715859a83eee + + + X-PayerFSP-Id + {{PayeeTenantName}} + + + Postman-Token + fc7b0904-7996-440f-b5ad-eda42909168c + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + false + + + + {{connectorcrmhostname}} + 0 + http + UTF-8 + /paymentNotifications + true + POST + true + true + + + + false + { + "billInquiryRequestId": "12e2cedc-7372-4208-8079-7d46d691fca4", + "billId": "001", + "paymentReferenceID": "8f353842-451c-4231-afc9-58289afdc396" +} + = + + + + + + + + + Platform-TenantId + rhino + + + X-CorrelationID + f56caf0b-377d-4a1f-8ac1-715859a83eee + + + X-PayerFSP-Id + {{PayeeTenantName}} + + + Postman-Token + 60d73540-20c7-4772-9808-8ec68e255e99 + + + Content-Type + application/json + + + Cache-Control + no-cache + + + Accept-Encoding + gzip, deflate, br + + + User-Agent + PostmanRuntime/7.41.2 + + + Accept + */* + + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + false + false + true + false + false + false + false + true + false + false + true + true + 0 + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + /home/res + true + 11 + 1 + false + 1 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + 8889 + + (?i).*\.(bmp|css|js|gif|ico|jpe?g|png|swf|eot|otf|ttf|mp4|woff|woff2) + www\.download\.windowsupdate\.com.* + toolbarqueries\.google\..* + clients.*\.google.* + api\.bing\.com.* + (?i).*\.(bmp|css|js|gif|ico|jpe?g|png|swf|eot|otf|ttf|mp4|woff|woff2)[\?;].* + us\.update\.toolbar\.yahoo\.com.* + safebrowsing.*\.google\.com.* + g\.msn.* + .*msg\.yahoo\.com.* + tiles.*\.mozilla\.com.* + sqm\.microsoft\.com.* + geo\.yahoo\.com.* + .*yimg\.com.* + www\.google-analytics\.com.* + http?://self-repair\.mozilla\.org.* + windowsupdate\.microsoft\.com.* + .*detectportal\.firefox\.com.* + .*toolbar\.yahoo\.com.* + .*\.google\.com.*/safebrowsing/.* + toolbar\.google\.com.* + pgq\.yahoo\.com.* + toolbar\.avg\.com/.* + toolbar\.msn\.com.* + + + true + 4 + false + + false + true + true + false + true + + + false + GSMA Stub- Request + 1 + + true + UTF-8 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + true + true + true + true + true + true + false + true + true + true + true + 0 + true + true + true + true + true + true + true + true + + + recording.xml + + + + + + diff --git a/postman/phee-example-batch-2.csv b/postman/phee-example-batch-2.csv new file mode 100644 index 0000000..4f99d4f --- /dev/null +++ b/postman/phee-example-batch-2.csv @@ -0,0 +1,4 @@ +Request,CreditParty Key,CreditParty Value,DebitParty Key,DebitParty Value,SubType,Payment Mode,Currency,Amount,Description +8.7988E+11,msisdn,837461856,accountnumber,3.001E+15,,mojaloop,USD,500,test1 +8.7988E+11,msisdn,837461856,accountnumber,3.001E+15,,mojaloop,USD,501,test2 +8.7988E+11,msisdn,837461856,accountnumber,3.001E+15,,mojaloop,USD,502,test3 \ No newline at end of file diff --git a/run.sh b/run.sh index 557f749..b96104b 100755 --- a/run.sh +++ b/run.sh @@ -1,5 +1,6 @@ #!/bin/bash -source ./src/utils/logger.sh -source ./src/mojafos/commandline/commandline.sh +RUN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # the directory that this script is in +source "$RUN_DIR/src/utils/logger.sh" +source "$RUN_DIR/src/commandline/commandline.sh" diff --git a/src/commandline/commandline.sh b/src/commandline/commandline.sh new file mode 100755 index 0000000..ba79304 --- /dev/null +++ b/src/commandline/commandline.sh @@ -0,0 +1,154 @@ +#!/usr/bin/env bash + +source "$RUN_DIR/src/configurationManager/config.sh" +source "$RUN_DIR/src/environmentSetup/environmentSetup.sh" +source "$RUN_DIR/src/deployer/deployer.sh" + +function welcome { + echo -e "${BLUE}" + echo -e " ██████ █████ ███████ ███████ ██ ██ ███████ " + echo -e "██ ██ ██ ███ ██ ██ ██ ██ " + echo -e "██ ███ ███████ ███ █████ ██ ██ █████ " + echo -e "██ ██ ██ ██ ███ ██ ██ ██ ██ " + echo -e " ██████ ██ ██ ███████ ███████ ███████ ███████ ███████ " + echo -e "${RESET}" +} +function showUsage { + echo " +USAGE: $0 -m [mode] -u [user] -a [apps] -e [environment] -d [true/false] +Example 1 : sudo $0 -m deploy -u \$USER -d true # install mifos-gazelle with debug mode and user \$USER +Example 2 : sudo $0 -m cleanapps -u \$USER -d true # delete apps, leave environment with debug mode and user \$USER +Example 3 : sudo $0 -m cleanall -u \$USER # delete all apps, all Kubernetes artifacts, and server +Example 4 : sudo $0 -m deploy -u \$USER -a phee # install PHEE only, user \$USER +Example 5 : sudo $0 -m deploy -u \$USER -a all # install all apps (vNext, PHEE, and MifosX) with user \$USER + +Options: + -m mode ................ deploy|cleanapps|cleanall (required) + -u user ................ (non root) user that the process will use for execution (required) + -a apps ................ vnext|phee|mifosx (apps that can be independently deployed) (optional) + -e environment ......... currently, 'local' is the only value supported and is the default (optional) + -d debug ............... enable debug mode (true|false) (optional default=false) + -r redeploy ............ force redeployment of apps (true|false) (optional, default=true) + -h|H ................... display this message +" +} + +function validateInputs { + if [[ -z "$mode" || -z "$k8s_user" ]]; then + echo "Error: Required options -m (mode) and -u (user) must be provided." + showUsage + exit 1 + fi + + if [[ "$mode" != "deploy" && "$mode" != "cleanapps" && "$mode" != "cleanall" ]]; then + echo "Error: Invalid mode '$mode'. Must be one of: deploy, cleanapps, cleanall." + showUsage + exit 1 + fi + + if [[ "$mode" == "deploy" || "$mode" == "cleanapps" ]]; then + if [[ -z "$apps" ]]; then + echo "No specific apps provided with -a flag. Defaulting to 'all'." + apps="all" + elif [[ "$apps" != "infra" && "$apps" != "vnext" && "$apps" != "phee" && "$apps" != "mifosx" && "$apps" != "all" ]]; then + echo "Error: Invalid value for apps. Must be one of: infra, vnext, phee, mifosx, all." + showUsage + exit 1 + fi + fi + + if [[ -n "$debug" && "$debug" != "true" && "$debug" != "false" ]]; then + echo "Error: Invalid value for debug. Use 'true' or 'false'." + showUsage + exit 1 + fi + + if [[ -n "$redeploy" && "$redeploy" != "true" && "$redeploy" != "false" ]]; then + echo "Error: Invalid value for redeploy. Use 'true' or 'false'." + showUsage + exit 1 + fi + + # Set default values + environment="${environment:-local}" + debug="${debug:-false}" + redeploy="${redeploy:-true}" +} + + +function getOptions { + while getopts "m:k:d:a:e:v:u:r:hH" OPTION ; do + case "${OPTION}" in + m) mode="${OPTARG}" ;; + k) k8s_distro="${OPTARG}" ;; + d) debug="${OPTARG}" ;; + a) apps="${OPTARG}" ;; + v) k8s_user_version="${OPTARG}" ;; + u) k8s_user="${OPTARG}" ;; + r) redeploy="${OPTARG}" ;; + h|H) showUsage + exit 0 ;; + *) echo "Unknown option: -${OPTION}" + showUsage + exit 1 ;; + esac + done +} + +# this function is called when Ctrl-C is sent +function cleanUp () +{ + # perform cleanup here + echo -e "${RED}Performing graceful clean up${RESET}" + + mode="cleanup" + echo "Doing cleanup" + envSetupMain "$mode" "k3s" "1.26" "$environment" + + # exit shell script with error code 2 + # if omitted, shell script will continue execution + exit 2 +} + +function trapCtrlc { + echo + echo -e "${RED}Ctrl-C caught...${RESET}" + cleanUp +} + +# initialise trap to call trap_ctrlc function +# when signal 2 (SIGINT) is received +trap "trapCtrlc" 2 + +########################################################################### +# MAIN +########################################################################### +function main { + welcome + getOptions "$@" + validateInputs + + if [ $mode == "deploy" ]; then + echo -e "${YELLOW}" + echo -e "======================================================================================================" + echo -e "The deployment made by this script is currently recommended for demo, test and educational purposes " + echo -e "======================================================================================================" + echo -e "${RESET}" + envSetupMain "$mode" "k3s" "1.30" "$environment" + deployApps "$mifosx_instances" "$apps" "$redeploy" + elif [ $mode == "cleanapps" ]; then + logWithVerboseCheck $debug info "Cleaning up Mifos Gazelle applications only" + deleteApps "$mifosx_instances" "$apps" + elif [ $mode == "cleanall" ]; then + logWithVerboseCheck $debug info "Cleaning up all traces of Mifos Gazelle " + deleteApps "$mifosx_instances" "all" + envSetupMain "$mode" "k3s" "1.30" "$environment" + else + showUsage + fi +} + +########################################################################### +# CALL TO MAIN +########################################################################### +main "$@" \ No newline at end of file diff --git a/src/configurationManager/config.sh b/src/configurationManager/config.sh new file mode 100755 index 0000000..aa83f76 --- /dev/null +++ b/src/configurationManager/config.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +######################################################################## +# GLOBAL VARS +######################################################################## +BASE_DIR=$( cd $(dirname "$0") ; pwd ) +APPS_DIR="$BASE_DIR/repos" +CONFIG_DIR="$BASE_DIR/config" +INFRA_NAMESPACE="infra" +INFRA_RELEASE_NAME="infra" +INFRA_CHART_DIR="$BASE_DIR/src/deployer/helm/infra" +NGINX_VALUES_FILE="$CONFIG_DIR/nginx_values.yaml" +GAZELLE_DOMAIN="mifos.gazelle.test" + +# Mojaloop vNext +VNEXTBRANCH="beta1" +VNEXTREPO_DIR="vnext" +VNEXT_NAMESPACE="vnext" +VNEXT_REPO_LINK="https://github.com/mojaloop/platform-shared-tools.git" +VNEXT_LAYER_DIRS=("$APPS_DIR/vnext/packages/installer/manifests/crosscut" "$APPS_DIR/vnext/packages/installer/manifests/ttk" "$APPS_DIR/vnext/packages/installer/manifests/apps" "$APPS_DIR/vnext/packages/installer/manifests/reporting") +VNEXT_VALUES_FILE="$CONFIG_DIR/vnext_values.json" +VNEXT_MONGODB_DATA_DIR="$APPS_DIR/$VNEXTREPO_DIR/packages/deployment/docker-compose-apps/ttk_files/mongodb" +VNEXT_TTK_FILES_DIR="$APPS_DIR/$VNEXTREPO_DIR/packages/deployment/docker-compose-apps/ttk_files" + +#PaymentHub EE +PHBRANCH="master" +PHREPO_DIR="phlabs" +PH_NAMESPACE="paymenthub" +PH_RELEASE_NAME="phee" +PH_VALUES_FILE="$CONFIG_DIR/ph_values.yaml" +PH_REPO_LINK="https://github.com/openMF/ph-ee-env-labs.git" +PH_EE_ENV_TEMPLATE_REPO_LINK="https://github.com/openMF/ph-ee-env-template.git" +PH_EE_ENV_TEMPLATE_REPO_BRANCH="v1.13.0-gazelle" +PH_EE_ENV_TEMPLATE_REPO_DIR="ph_template" + +# Define Kubernetes service and MySQL connection details +MYSQL_SERVICE_NAME="mysql" # Replace with your MySQL service name +MYSQL_SERVICE_PORT="3306" # Replace with the MySQL service port +LOCAL_PORT="3307" # Local port to forward to +MAX_WAIT_SECONDS=60 + +# MySQL Connection Details +MYSQL_USER="root" +MYSQL_PASSWORD="ethieTieCh8ahv" +MYSQL_HOST="127.0.0.1" # This is the localhost because we are port forwarding +SQL_FILE="$BASE_DIR/src/deployer/setup.sql" + +#MifosX +MIFOSX_NAMESPACE="mifosx" +MIFOSX_MANIFESTS_DIR="$APPS_DIR/mifosx/kubernetes/manifests" +MIFOSX_BRANCH="mifos-gazelle_1" +MIFOSX_REPO_LINK="https://github.com/openMF/mifosx-docker.git" +MIFOSX_REPO_DIR="mifosx" + +######################################################################## +# FUNCTIONS FOR CONFIGURATION MANAGEMENT +######################################################################## +function replaceValuesInFiles() { + local directories=("$@") + local json_file="$VNEXT_VALUES_FILE" + + # Check if jq is installed, if not, exit with an error message + if ! command -v jq &>/dev/null; then + echo "Error: 'jq' is not installed. Please install it (https://stedolan.github.io/jq/) and make sure it's in your PATH." + return 1 + fi + + # Check if the JSON file exists + if [ ! -f "$json_file" ]; then + echo "Error: JSON file '$json_file' does not exist." + return 1 + fi + + # Read the JSON file and create an associative array + declare -A replacements + while IFS= read -r json_object; do + local old_value new_value + old_value=$(echo "$json_object" | jq -r '.old_value') + new_value=$(echo "$json_object" | jq -r '.new_value') + replacements["$old_value"]="$new_value" + done < <(jq -c '.[]' "$json_file") + + # Loop through the directories and process each file + for dir in "${directories[@]}"; do + if [ -d "$dir" ]; then + find "$dir" -type f | while read -r file; do + local changed=false + for old_value in "${!replacements[@]}"; do + if grep -q "$old_value" "$file"; then + #sed -i "s|$old_value|${replacements[$old_value]}|g" "$file" + #sed -i "s|.*$old_value.*|${replacements[$old_value]}|g" "$file" + sed -i "s|^\(.*\)$old_value.*|\1${replacements[$old_value]}|g" "$file" + changed=true + fi + done + if $changed; then + echo "Updated: $file" >> /dev/null 2>&1 + fi + done + else + echo "Directory $dir does not exist." + fi + done +} + +function configurevNext() { + replaceValuesInFiles "${VNEXT_LAYER_DIRS[0]}" "${VNEXT_LAYER_DIRS[2]}" "${VNEXT_LAYER_DIRS[3]}" + # Iterate over each directory in VNEXT_LAYER_DIRS + for dir in "${VNEXT_LAYER_DIRS[@]}"; do + # Find all YAML files in the directory + find "$dir" -type f -name "*.yaml" | while read -r file; do + # Perform the in-place substitution for ingressClassName + perl -pi -e 's/ingressClassName:\s*nginx-ext/ingressClassName: nginx/' "$file" + + # Perform the in-place substitution for domain name .local to mifos.gazelle.test + perl -pi -e 's/- host:\s*(\S+)\.local/- host: $1.mifos.gazelle.test/' "$file" + perl -pi -e 's/(\S+)bank\.local/$1bank.mifos.gazelle.test/' "$file" + + done + done +} + +function configureMifosx(){ + echo -e "${BLUE}Configuring MifosX ${RESET}" +} \ No newline at end of file diff --git a/src/deployer/deployer.sh b/src/deployer/deployer.sh new file mode 100755 index 0000000..1df06ca --- /dev/null +++ b/src/deployer/deployer.sh @@ -0,0 +1,720 @@ +#!/usr/bin/env bash + +# Function to check and handle command execution errors +check_command_execution() { + local msg=$1 + if [ $? -ne 0 ]; then + echo "Error: $1 failed" + exit 1 + fi +} + +function isPodRunning() { + local podname="$1" + local namespace="$2" + + # Get the pod status + local pod_status + pod_status=$(kubectl get pod "$podname" -n "$namespace" -o jsonpath='{.status.phase}') + + # Check if the pod is running + if [[ "$pod_status" == "Running" ]]; then + echo "true" + else + echo "false" + fi +} + +function isDeployed { + local app_name="$1" + if [[ "$app_name" == "infra" ]]; then + # Check if the namespace exists + if ! kubectl get namespace "$INFRA_NAMESPACE" > /dev/null 2>&1; then + echo "false" + return + fi + # namespace exists so Check if the infra Helm chart is deployed and running in the $INFRA_NAMESPACE + helm_status=$(helm status infra -n "$INFRA_NAMESPACE" 2>&1) + #echo "helm status is $helm_status" + if echo "$helm_status" | awk '/^STATUS:/ {if ($2 == "deployed") exit 0; else exit 1}'; then + echo "true" + else + echo "false" + fi + elif [[ "$app_name" == "phee" ]]; then + # Check if the namespace exists + if ! kubectl get namespace "$PH_NAMESPACE" > /dev/null 2>&1; then + echo "false" + return + fi + helm_status=$(helm status phee -n "$PHEE_NAMESPACE" 2>&1) + if echo "$helm_status" | awk '/^STATUS:/ {if ($2 == "deployed") exit 0; else exit 1}'; then + echo "true" + else + echo "false" + fi + elif [[ "$app_name" == "vnext" ]]; then + # Check if the namespace exists + if ! kubectl get namespace "$VNEXT_NAMESPACE" > /dev/null 2>&1; then + echo "false" + return + fi + # assume if greenbank-backend-0 is running ok then vnext is installed + local podname="greenbank-backend-0" + if [[ "$(isPodRunning "$podname" "$VNEXT_NAMESPACE")" == "true" ]]; then + echo "true" + else + echo "false" + fi + elif [[ "$app_name" == "mifosx" ]]; then + # MifosX installs so quickly we just redeploy each time + echo "false" + fi +} + +deployBPMS() { + local host="https://zeebeops.mifos.gazelle.test/zeebe/upload" + local DEBUG=false + local bpms_to_deploy=38 + local successful_uploads=0 + local BPMNS_DIR="$APPS_DIR/$PHREPO_DIR" + printf "Deploying BPMN diagrams " + # Find each .bpmn file in the specified directories and iterate over them + for file in "$BPMNS_DIR/orchestration/feel/"*.bpmn "$BPMNS_DIR/orchestration/feel/example/"*.bpmn; do + # Check if the glob expanded to an actual file or just returned the pattern + if [ -f "$file" ]; then + # Construct and execute the curl command for each file + local cmd="curl --insecure --location --request POST $host \ + --header 'Platform-TenantId: greenbank' \ + --form 'file=@\"$file\"' \ + -s -o /dev/null -w '%{http_code}'" + + if [ "$DEBUG" = true ]; then + echo "Executing: $cmd" + http_code=$(eval "$cmd") + exit_code=$? + echo "HTTP Code: $http_code" + echo "Exit code: $exit_code" + else + http_code=$(eval "$cmd") + exit_code=$? + + if [ "$exit_code" -eq 0 ] && [ "$http_code" -eq 200 ]; then + #echo "File: $file - Upload successful" + ((successful_uploads++)) + fi + fi + else + echo " ** Warning : No BPMN files found in $file" # Notify if no files are found in a location + fi + done + + # Check if the number of successful uploads meets the required threshold + if [ "$successful_uploads" -ge "$bpms_to_deploy" ]; then + echo " [ok] " + else + echo "Warning: there was an issue deploying the BPMN diagrams." + echo " run ./src/utils/deployBpmn-gazelle.sh to investigate" + fi +} + +function createIngressSecret { + local namespace="$1" + local domain_name="$2" + local secret_name="$3" + key_dir="$HOME/.ssh" + + # Generate private key + openssl genrsa -out "$key_dir/$domain_name.key" 2048 >> /dev/null 2>&1 + + # Generate self-signed certificate + openssl req -x509 -new -nodes -key "$key_dir/$domain_name.key" -sha256 -days 365 -out "$key_dir/$domain_name.crt" -subj "/CN=$domain_name" -extensions v3_req -config <( + cat < /dev/null 2>&1 + # Verify the certificate + openssl x509 -in "$key_dir/$domain_name.crt" -noout -text > /dev/null 2>&1 + + # Create the Kubernetes TLS secret + kubectl create secret tls "$secret_name" --cert="$key_dir/$domain_name.crt" --key="$key_dir/$domain_name.key" -n "$namespace" > /dev/null 2>&1 + + if [ $? -eq 0 ]; then + echo " Self-signed certificate and secret $secret_name created successfully in namespace $namespace " + else + echo " ** Error creating Self-signed certificate and secret $secret_name in namespace $namespace " + exit 1 + fi +} + +function manageElasticSecrets { + local action="$1" + local namespace="$2" + local certdir="$3" # location of the .p12 and .pem files + local password="XVYgwycNuEygEEEI0hQF" #see + + # Create a temporary directory to store the generated files + temp_dir=$(mktemp -d) + + if [[ "$action" == "create" ]]; then + echo " creating elastic and kibana secrets in namespace $namespace" + # Convert the certificates and store them in the temporary directory + openssl pkcs12 -nodes -passin pass:'' -in $certdir/elastic-certificates.p12 -out "$temp_dir/elastic-certificate.pem" >> /dev/null 2>&1 + openssl x509 -outform der -in "$certdir/elastic-certificate.pem" -out "$temp_dir/elastic-certificate.crt" >> /dev/null 2>&1 + + # Create the ES secrets in the specified namespace + kubectl create secret generic elastic-certificates --namespace="$namespace" --from-file="$certdir/elastic-certificates.p12" >> /dev/null 2>&1 + kubectl create secret generic elastic-certificate-pem --namespace="$namespace" --from-file="$temp_dir/elastic-certificate.pem" >> /dev/null 2>&1 + kubectl create secret generic elastic-certificate-crt --namespace="$namespace" --from-file="$temp_dir/elastic-certificate.crt" >> /dev/null 2>&1 + kubectl create secret generic elastic-credentials --namespace="$namespace" --from-literal=password="$password" --from-literal=username=elastic >> /dev/null 2>&1 + + local encryptionkey=MMFI5EFpJnib4MDDbRPuJ1UNIRiHuMud_r_EfBNprx7qVRlO7R + kubectl create secret generic kibana --namespace="$namespace" --from-literal=encryptionkey=$encryptionkey >> /dev/null 2>&1 + + elif [[ "$action" == "delete" ]]; then + echo "Deleting elastic and kibana secrets" + # Delete the secrets from the specified namespace + kubectl delete secret elastic-certificates --namespace="$namespace" >> /dev/null 2>&1 + kubectl delete secret elastic-certificate-pem --namespace="$namespace" >> /dev/null 2>&1 + kubectl delete secret elastic-certificate-crt --namespace="$namespace" >> /dev/null 2>&1 + kubectl delete secret elastic-credentials --namespace="$namespace" >> /dev/null 2>&1 + kubectl delete secret kibana --namespace="$namespace" >> /dev/null 2>&1 + else + echo "Invalid action. Use 'create' or 'delete'." + rm -rf "$temp_dir" # Clean up the temporary directory + return 1 + fi + + # Clean up the temporary directory + rm -rf "$temp_dir" +} + +function cloneRepo() { + if [ "$#" -ne 4 ]; then + echo "Usage: cloneRepo " + return 1 + fi + local branch="$1" + local repo_link="$2" + local target_directory="$3" + local cloned_directory_name="$4" + local repo_path="$target_directory/$cloned_directory_name" + + # Check if the target directory exists; if not, create it. + if [ ! -d "$target_directory" ]; then + mkdir -p "$target_directory" + fi + chown -R "$k8s_user" "$target_directory" + + # Check if the repository already exists. + if [ -d "$repo_path" ]; then + #echo "Repository $repo_path already exists. Checking for updates..." + + cd "$repo_path" || exit + + # Fetch the latest changes. + su - "$k8s_user" -c "git fetch origin $branch" >> /dev/null 2>&1 + + # Compare local branch with the remote branch. + LOCAL=$(git rev-parse @) + REMOTE=$(git rev-parse @{u}) + + if [ "$LOCAL" != "$REMOTE" ]; then + echo -e "${YELLOW}Repository $repo_path has updates. Recloning...${RESET}" + rm -rf "$repo_path" + su - "$k8s_user" -c "git clone -b $branch $repo_link $repo_path" >> /dev/null 2>&1 + else + echo " Repository $repo_path is up-to-date. No need to reclone." + fi + else + # Clone the repository if it doesn't exist locally. + su - "$k8s_user" -c "git clone -b $branch $repo_link $repo_path" >> /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo " Repository $repo_path cloned successfully." + else + echo "** Error Failed to clone the repository." + fi + fi +} + +function deleteResourcesInNamespaceMatchingPattern() { + local pattern="$1" + # Check if the pattern is provided + if [ -z "$pattern" ]; then + echo "Pattern not provided." + return 1 + fi + + # Get namespaces matching the pattern + local namespaces=$(kubectl get namespaces -o name | grep "$pattern") + if [ -z "$namespaces" ]; then + echo "No namespaces found matching pattern: $pattern" + return 0 + fi + + echo "$namespaces" | while read -r namespace; do + namespace=$(echo "$namespace" | cut -d'/' -f2) + if [[ $namespace == "default" ]]; then + local deployment_name="prometheus-operator" + deployment_available=$(kubectl get deployment "$deployment_name" -n "default" -o jsonpath='{.status.conditions[?(@.type=="Available")].status}') + if [[ "$deployment_available" == "True" ]]; then + printf "Deleting Prometheus Operator resources in default namespace" + LATEST=$(curl -s https://api.github.com/repos/prometheus-operator/prometheus-operator/releases/latest | jq -cr .tag_name) + su - "$k8s_user" -c "curl -sL https://github.com/prometheus-operator/prometheus-operator/releases/download/${LATEST}/bundle.yaml | kubectl -n default delete -f -" >/dev/null 2>&1 + if [ $? -eq 0 ]; then + echo " [ok] " + else + echo "Warning: there was an issue uninstalling Prometheus Operator resources in default namespace." + echo " you can ignore this if Prometheus was not expected to be already running." + fi + fi + else + printf "Deleting all resources in namespace $namespace " + kubectl delete all --all -n "$namespace" >> /dev/null 2>&1 + kubectl delete ns "$namespace" >> /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo " [ok] " + else + echo "Error deleting resources in namespace $namespace." + fi + fi + done +} + +function deployHelmChartFromDir() { + # Check if the chart directory exists + local chart_dir="$1" + local namespace="$2" + local release_name="$3" + if [ ! -d "$chart_dir" ]; then + echo "Chart directory '$chart_dir' does not exist." + exit 1 + fi + # Check if a values file has been provided + values_file="$4" + + # TODO Determine whether to install or upgrade the chart also check whether to apply a values file + #su - $k8s_user -c "helm list -n $namespace" + if [ -n "$values_file" ]; then + echo "Installing Helm chart using values: $values_file..." + su - $k8s_user -c "helm install $release_name $chart_dir -n $namespace -f $values_file" + else + echo "Installing Helm chart using default values file ..." + su - $k8s_user -c "helm install $release_name $chart_dir -n $namespace " + fi + + # todo : is the chart really deployed ok, need a test + # Use kubectl to get the resource count in the specified namespace + resource_count=$(sudo -u $k8s_user kubectl get pods -n "$namespace" --ignore-not-found=true 2>/dev/null | grep -v "No resources found" | wc -l) + # Check if the deployment was successful + if [ $resource_count -gt 0 ]; then + echo "Helm chart deployed successfully." + else + echo -e "${RED}Helm chart deployment failed.${RESET}" + cleanUp + fi + +} + +function preparePaymentHubChart(){ + # Clone the repositories + cloneRepo "$PHBRANCH" "$PH_REPO_LINK" "$APPS_DIR" "$PHREPO_DIR" # needed for kibana and elastic secrets only + cloneRepo "$PH_EE_ENV_TEMPLATE_REPO_BRANCH" "$PH_EE_ENV_TEMPLATE_REPO_LINK" "$APPS_DIR" "$PH_EE_ENV_TEMPLATE_REPO_DIR" + + # Update helm dependencies and repo index for ph-ee-engine + echo " updating dependencies ph-ee-engine chart " + phEEenginePath="$APPS_DIR/$PH_EE_ENV_TEMPLATE_REPO_DIR/helm/ph-ee-engine" + su - $k8s_user -c "cd $phEEenginePath; helm dep update" >> /dev/null 2>&1 + su - $k8s_user -c "cd $phEEenginePath; helm repo index ." + + # Update helm dependencies and repo index for gazelle i.e. parent chart of ph-ee-engine + echo " updating dependencies gazelle chart " + gazelleChartPath="$APPS_DIR/$PH_EE_ENV_TEMPLATE_REPO_DIR/helm/gazelle" + su - $k8s_user -c "cd $gazelleChartPath ; helm dep update >> /dev/null 2>&1 " + su - $k8s_user -c "cd $gazelleChartPath ; helm repo index ." +} + +function checkPHEEDependencies() { + printf " Installing Prometheus " + # Install Prometheus Operator if needed as it is a PHEE dependency + local deployment_name="prometheus-operator" + deployment_available=$(kubectl get deployment "$deployment_name" -n "default" -o jsonpath='{.status.conditions[?(@.type=="Available")].status}' > /dev/null 2>&1) + if [[ "$deployment_available" == "True" ]]; then + echo -e "${RED} prometheus already installed -skipping install. ${RESET}" + return 0 + fi + LATEST=$(curl -s https://api.github.com/repos/prometheus-operator/prometheus-operator/releases/latest | jq -cr .tag_name) + su - $k8s_user -c "curl -sL https://github.com/prometheus-operator/prometheus-operator/releases/download/${LATEST}/bundle.yaml | kubectl create -f - " >/dev/null 2>&1 + if [ $? -eq 0 ]; then + echo " [ok] " + else + echo " Failed to install prometheus" + exit 1 + fi +} + +function deployPhHelmChartFromDir(){ + # Parameters + local namespace="$1" + local chartDir="$2" # Directory containing the Helm chart + local valuesFile="$3" # Values file for the Helm chart + + # Install the Helm chart from the local directory + if [ -z "$valuesFile" ]; then + echo "default values file > $k8s_user -c helm install $PH_RELEASE_NAME $chartDir -n $namespace" + su - "$k8s_user" -c "helm install $PH_RELEASE_NAME $chartDir -n $namespace" >> /dev/null 2>&1 + else + echo " deploying using values file > $k8s_user -c helm install $PH_RELEASE_NAME $chartDir -n $namespace -f $valuesFile " + su - "$k8s_user" -c "helm install $PH_RELEASE_NAME $chartDir -n $namespace -f $valuesFile " >> /dev/null 2>&1 + fi + + # Check deployment status + # TODO: should strengthen this check for deployment success + resource_count=$(kubectl get pods -n "$namespace" --ignore-not-found=true 2>/dev/null | grep -v "No resources found" | wc -l) + if [ "$resource_count" -gt 0 ]; then + echo "PaymentHub EE Helm chart deployed successfully." + else + echo -e "${RED}Helm chart deployment failed.${RESET}" + cleanUp + fi +} + +function deployPH(){ + if [[ "$(isDeployed "phee" )" == "true" ]]; then + if [[ "$redeploy" == "false" ]]; then + echo "$PH_RELEASE_NAME is already deployed. Skipping deployment." + return + else # need to delete prior to redeploy + deleteResourcesInNamespaceMatchingPattern "$PH_NAMESPACE" + deleteResourcesInNamespaceMatchingPattern "default" #just removes prometheus at the moment + manageElasticSecrets delete "$INFRA_NAMESPACE" "$APPS_DIR/$PHREPO_DIR/helm/es-secret" + fi + fi + echo "Deploying PaymentHub EE" + createNamespace "$PH_NAMESPACE" + checkPHEEDependencies + preparePaymentHubChart + manageElasticSecrets create "$PH_NAMESPACE" "$APPS_DIR/$PHREPO_DIR/helm/es-secret" + manageElasticSecrets create "$INFRA_NAMESPACE" "$APPS_DIR/$PHREPO_DIR/helm/es-secret" + createIngressSecret "$PH_NAMESPACE" "$GAZELLE_DOMAIN" sandbox-secret + + # now deploy the helm chart + deployPhHelmChartFromDir "$PH_NAMESPACE" "$gazelleChartPath" "$PH_VALUES_FILE" + # now load the BPMS diagrams we do it here not in the helm chart so that + # we can count the sucessful BPMN uploads and be confident that they are working + deployBPMS + echo -e "\n${GREEN}============================" + echo -e "Paymenthub Deployed" + echo -e "============================${RESET}\n" +} + +function createNamespace () { + local namespace=$1 + printf " Creating namespace $namespace " + # Check if the namespace already exists + if kubectl get namespace "$namespace" >> /dev/null 2>&1; then + echo -e "${RED}Namespace $namespace already exists -skipping creation.${RESET}" + return 0 + fi + + # Create the namespace + kubectl create namespace "$namespace" >> /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo -e " [ok] " + else + echo "Failed to create namespace $namespace." + fi +} + +function deployInfrastructure () { + local redeploy="$1" + printf "==> Deploying infrastructure \n" + if [[ "$(isDeployed "infra")" == "true" ]]; then + if [[ "$redeploy" == "false" ]]; then + echo " infrastructure is already deployed. Skipping deployment." + return + else # need to delete and deploy + deleteResourcesInNamespaceMatchingPattern "$INFRA_NAMESPACE" + fi + fi + createNamespace $INFRA_NAMESPACE + + # Update helm dependencies and repo index for infra chart + printf " updating dependencies for infra helm chart " + su - $k8s_user -c "cd $INFRA_CHART_DIR; helm dep update" >> /dev/null 2>&1 + check_command_execution "Updating dependencies for infra chart" + echo " [ok] " + + #su - $k8s_user -c "cd $INFRA_CHART_DIR; helm repo index ." + printf " Deploying infra helm chart " + if [ "$debug" = true ]; then + deployHelmChartFromDir "$RUN_DIR/src/deployer/helm/infra" "$INFRA_NAMESPACE" "$INFRA_RELEASE_NAME" + else + deployHelmChartFromDir "$RUN_DIR/src/deployer/helm/infra" "$INFRA_NAMESPACE" "$INFRA_RELEASE_NAME" >> /dev/null 2>&1 + fi + check_command_execution "Deploying infra helm chart" + echo " [ok] " + echo -e "\n${GREEN}============================" + echo -e "Infrastructure Deployed" + echo -e "============================${RESET}\n" +} + +function applyKubeManifests() { + if [ "$#" -ne 2 ]; then + echo "Usage: applyKubeManifests " + return 1 + fi + + local directory="$1" + local namespace="$2" + + # Check if the directory exists. + if [ ! -d "$directory" ]; then + echo "Directory '$directory' not found." + return 1 + fi + + # Use 'kubectl apply' to apply manifests in the specified directory. + su - $k8s_user -c "kubectl apply -f $directory -n $namespace" >> /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo -e " Kubernetes manifests applied successfully." + else + echo -e "${RED}Failed to apply Kubernetes manifests.${RESET}" + fi +} + + +function addKubeConfig(){ + K8sConfigDir="$k8s_user_home/.kube" + + if [ ! -d "$K8sConfigDir" ]; then + su - $k8s_user -c "mkdir -p $K8sConfigDir" + echo "K8sConfigDir created: $K8sConfigDir" + else + echo "K8sConfigDir already exists: $K8sConfigDir" + fi + su - $k8s_user -c "cp $k8s_user_home/k3s.yaml $K8sConfigDir/config" +} + +function vnext_restore_demo_data { + local mongo_data_dir=$1 + local namespace=$2 + printf " restoring vNext mongodb demonstration/test data " + mongopod=`kubectl get pods --namespace $namespace | grep -i mongodb |awk '{print $1}'` + mongo_root_pw=`kubectl get secret --namespace $namespace mongodb -o jsonpath='{.data.mongodb-root-password}'| base64 -d` + kubectl cp $mongo_data_dir/mongodump-beta.gz $mongopod:/tmp/mongodump.gz --namespace $namespace >/dev/null 2>&1 # copy the demo / test data into the mongodb pod + kubectl exec --namespace $namespace --stdin --tty $mongopod -- mongorestore -u root -p $mongo_root_pw \ + --gzip --archive=/tmp/mongodump.gz --authenticationDatabase admin >/dev/null 2>&1 + printf " [ ok ] \n" +} + +function vnext_configure_ttk { + local ttk_files_dir=$1 + local namespace=$2 + local warning_issued=false + printf "\n==> Configuring the Testing Toolkit... " + + # Check if BlueBank pod is running + local bb_pod_status + bb_pod_status=$(kubectl get pods bluebank-backend-0 --namespace "$namespace" --no-headers 2>/dev/null | awk '{print $3}') + + if [[ "$bb_pod_status" != "Running" ]]; then + printf " - TTK pod is not running; skipping configuration (may not support arm64).\n" + return 0 + fi + + #printf " Configuring TTK data and environment...\n" + + # Define TTK pod destinations + local ttk_pod_env_dest="/opt/app/examples/environments" + local ttk_pod_spec_dest="/opt/app/spec_files" + + # Function to check and report on kubectl cp command success + check_kubectl_cp() { + if ! kubectl cp "$1" "$2" --namespace "$namespace" 2>/dev/null; then + printf " [WARNING] Failed to copy %s to %s\n" "$1" "$2" + warning_issued=true + fi + } + + # Copy BlueBank files + check_kubectl_cp "$ttk_files_dir/environment/hub_local_environment.json" "bluebank-backend-0:$ttk_pod_env_dest/hub_local_environment.json" + check_kubectl_cp "$ttk_files_dir/environment/dfsp_local_environment.json" "bluebank-backend-0:$ttk_pod_env_dest/dfsp_local_environment.json" + check_kubectl_cp "$ttk_files_dir/spec_files/user_config_bluebank.json" "bluebank-backend-0:$ttk_pod_spec_dest/user_config.json" + check_kubectl_cp "$ttk_files_dir/spec_files/default.json" "bluebank-backend-0:$ttk_pod_spec_dest/rules_callback/default.json" + + # Copy GreenBank files + check_kubectl_cp "$ttk_files_dir/environment/hub_local_environment.json" "greenbank-backend-0:$ttk_pod_env_dest/hub_local_environment.json" + check_kubectl_cp "$ttk_files_dir/environment/dfsp_local_environment.json" "greenbank-backend-0:$ttk_pod_env_dest/dfsp_local_environment.json" + check_kubectl_cp "$ttk_files_dir/spec_files/user_config_greenbank.json" "greenbank-backend-0:$ttk_pod_spec_dest/user_config.json" + check_kubectl_cp "$ttk_files_dir/spec_files/default.json" "greenbank-backend-0:$ttk_pod_spec_dest/rules_callback/default.json" + + # Final status message + if [[ "$warning_issued" == false ]]; then + printf " [ ok ] \n" + else + printf " [ WARNING ] Some files failed to copy. Check warnings above.\n" + fi +} + + +function deployvNext() { + printf "\n==> Deploying Mojaloop vNext application \n" + + if [[ "$(isDeployed "vnext" )" == "true" ]]; then + if [[ "$redeploy" == "false" ]]; then + echo " vNext application is already deployed. Skipping deployment." + return + else # need to delete prior to redeploy + deleteResourcesInNamespaceMatchingPattern "$VNEXT_NAMESPACE" + fi + fi + createNamespace "$VNEXT_NAMESPACE" + cloneRepo "$VNEXTBRANCH" "$VNEXT_REPO_LINK" "$APPS_DIR" "$VNEXTREPO_DIR" + # remove the TTK-CLI pod as it is not needed and comes up in error mode + rm -f "$APPS_DIR/$VNEXTREPO_DIR/packages/installer/manifests/ttk/ttk-cli.yaml" + + configurevNext # make any local mods to manifests + vnext_restore_demo_data $VNEXT_MONGODB_DATA_DIR $INFRA_NAMESPACE + for index in "${!VNEXT_LAYER_DIRS[@]}"; do + folder="${VNEXT_LAYER_DIRS[index]}" + applyKubeManifests "$folder" "$VNEXT_NAMESPACE" >/dev/null 2>&1 + if [ "$index" -eq 0 ]; then + echo -e "${BLUE} Waiting for vnext cross cutting concerns to come up${RESET}" + sleep 10 + echo -e " Proceeding ..." + fi + done + vnext_configure_ttk $VNEXT_TTK_FILES_DIR $VNEXT_NAMESPACE # configure in the TTKs as participants + + echo -e "\n${GREEN}============================" + echo -e "vnext Deployed" + echo -e "============================${RESET}\n" + +} + +function DeployMifosXfromYaml() { + manifests_dir=$1 + echo "==> Deploying MifosX i.e. web-app and Fineract via application manifests" + createNamespace "$MIFOSX_NAMESPACE" + cloneRepo "$MIFOSX_BRANCH" "$MIFOSX_REPO_LINK" "$APPS_DIR" "$MIFOSX_REPO_DIR" + applyKubeManifests "$manifests_dir" "$MIFOSX_NAMESPACE" + + echo -e "\n${GREEN}=====================================" + echo -e "MifosX (fineract + web app) Deployed" + echo -e "=====================================${RESET}\n" +} + +function test_vnext { + echo "TODO" #TODO Write function to test apps +} + +function test_phee { + echo "TODO" +} + +function test_mifosx { + local instance_name=$1 +} + +function printEndMessage { + echo -e "=================================" + echo -e "Thank you for using Mifos Gazelle" + echo -e "=================================\n\n" + echo -e "CHECK DEPLOYMENTS USING kubectl" + echo -e "kubectl get pods -n vnext #For testing mojaloop vNext" + echo -e "kubectl get pods -n paymenthub #For testing PaymentHub EE " + echo -e "kubectl get pods -n mifosx # for testing MifosX" + echo -e "or install k9s by executing ./src/utils/install-k9s.sh in this terminal window\n\n" +} + +function deleteApps { + appsToDelete="$2" + if [[ "$appsToDelete" == "all" ]]; then + deleteResourcesInNamespaceMatchingPattern "$MIFOSX_NAMESPACE" + deleteResourcesInNamespaceMatchingPattern "$VNEXT_NAMESPACE" + deleteResourcesInNamespaceMatchingPattern "$PH_NAMESPACE" + deleteResourcesInNamespaceMatchingPattern "$INFRA_NAMESPACE" + deleteResourcesInNamespaceMatchingPattern "default" + elif [[ "$appsToDelete" == "vnext" ]];then + deleteResourcesInNamespaceMatchingPattern "$VNEXT_NAMESPACE" + elif [[ "$appsToDelete" == "mifosx" ]]; then + deleteResourcesInNamespaceMatchingPattern "$MIFOSX_NAMESPACE" + elif [[ "$appsToDelete" == "phee" ]]; then + deleteResourcesInNamespaceMatchingPattern "$PH_NAMESPACE" + echo "Handling Prometheus Operator resources in the default namespace" + LATEST=$(curl -s https://api.github.com/repos/prometheus-operator/prometheus-operator/releases/latest | jq -cr .tag_name) + su - "$k8s_user" -c "curl -sL https://github.com/prometheus-operator/prometheus-operator/releases/download/${LATEST}/bundle.yaml | kubectl -n default delete -f -" > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "Warning: there was an issue uninstalling Prometheus Operator resources in default namespace." + echo " you can ignore this if Prometheus was not expected to be already running." + fi + + elif [[ "$appsToDelete" == "infra" ]]; then + deleteResourcesInNamespaceMatchingPattern "$INFRA_NAMESPACE" + else + echo -e "${RED}Invalid -a option ${RESET}" + showUsage + exit + fi +} + +function deployApps { + appsToDeploy="$2" + redeploy="$3" + + echo "redeploy is $redeploy" + + if [[ "$appsToDeploy" == "all" ]]; then + echo -e "${BLUE}Deploying all apps ...${RESET}" + deployInfrastructure "$redeploy" + deployvNext + deployPH + DeployMifosXfromYaml "$MIFOSX_MANIFESTS_DIR" + elif [[ "$appsToDeploy" == "infra" ]];then + deployInfrastructure + elif [[ "$appsToDeploy" == "vnext" ]];then + deployInfrastructure "false" + deployvNext + elif [[ "$appsToDeploy" == "mifosx" ]]; then + if [[ "$redeploy" == "true" ]]; then + echo "removing current mifosx and redeploying" + deleteApps 1 "mifosx" + fi + deployInfrastructure "false" + DeployMifosXfromYaml "$MIFOSX_MANIFESTS_DIR" + # here we need to add the second tenant to the mysql database + # this is how to check to see how many rows are in a schema + # can use this to determine when mifos has finished creating tables + # 249 seems to be the magic number for fineract_default schema for openmf/fineract:develop + # kubectl run mysql-client --rm -it --image=mysql:5.6 --restart=Never -- mysql -h mysql.infra.svc.cluster.local -u root -pmysqlpw \ + # -B -e 'SELECT count(*) AS TOTALNUMBEROFTABLES FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = "fineract_default" ' + # kubectl -n $INFRA_NAMESPACE cp $CONFIG_DIR/mifos-multi-tenant.sql mysql-0:/tmp + # kubectl -n $INFRA_NAMESPACE exec mysql-0 + # TODO: add the automation above BUT for now use + # src/utils/update-mifos-tenants.sh and do this after run.sh has completed and pods are up + # NOTE: the reason I am hesitating to add this now i.e. v1.0.0 is the time it takes then for the fineract-server pod to come online + # I need to see what the perf hit is *also* I am thiking we should simply export/import the mysql database + # as part of the infra startup + + elif [[ "$appsToDeploy" == "phee" ]]; then + deployPH + else + echo -e "${RED}Invalid option ${RESET}" + showUsage + exit + fi + addKubeConfig >> /dev/null 2>&1 + printEndMessage +} diff --git a/src/mojafos/deployer/helm/infra/Chart.yaml b/src/deployer/helm/infra/Chart.yaml similarity index 76% rename from src/mojafos/deployer/helm/infra/Chart.yaml rename to src/deployer/helm/infra/Chart.yaml index 9e690f0..30c79df 100644 --- a/src/mojafos/deployer/helm/infra/Chart.yaml +++ b/src/deployer/helm/infra/Chart.yaml @@ -1,15 +1,17 @@ apiVersion: v2 -description: Helm chart for mojafos infrastructure services -name: mojafos-infra -version: 15.0.0 -appVersion: "kafka: 19.0.2; console: 0.6.6; mongodb: 13.3.1; mongo-express: 3.1.1; elasticsearch:19.9.2; redis: 17.11.6" -home: https://summerofcode.withgoogle.com/programs/2023/projects/oQk6Gmup -icon: https://summerofcode.withgoogle.com/assets/media/logo.svg +description: Helm chart formifos-gazelle infrastructure services +name: gazelle-infra +version: 0.1.0 +appVersion: "kafka: 19.0.2; console: 0.6.6; mongodb: 13.3.1; mongo-express: 1.0.2; elasticsearch:19.9.2; redis: 17.11.6" +home: https://github.com/openMF/mifos-gazelle +#icon: sources: -- https://github.com/elijah0kello/mojafos +- https://github.com/openMF/mifos-gazelle maintainers: - name: Elijah Okello email: elijahokello90@gmail.com +- name: Tom Daly + email: tdaly61@gmail.com dependencies: ## kafka - name: kafka @@ -17,7 +19,7 @@ dependencies: condition: kafka.enabled repository: https://charts.bitnami.com/bitnami tags: - - mojafos + - gazelle - dependency - kafka version: 19.0.2 @@ -27,7 +29,7 @@ dependencies: condition: console.enabled repository: https://charts.redpanda.com tags: - - mojafos + - gazelle - dependency - kafka - redpanda @@ -38,7 +40,7 @@ dependencies: condition: mongodb.enabled repository: https://charts.bitnami.com/bitnami tags: - - mojafos + - gazelle - dependency - mongodb version: 13.3.1 @@ -48,17 +50,17 @@ dependencies: condition: mongo-express.enabled repository: https://cowboysysop.github.io/charts/ tags: - - mojafos + - gazelle - dependency - mongodb - version: 3.1.1 + version: 6.5.2 ## redis - name: redis alias: redis condition: redis.enabled repository: https://charts.bitnami.com/bitnami tags: - - mojafos + - gazelle - dependency - mongodb version: 17.11.6 @@ -68,7 +70,7 @@ dependencies: condition: elasticsearch.enabled repository: https://charts.bitnami.com/bitnami tags: - - mojafos + - gazelle - dependency - elasticsearch version: 19.9.2 @@ -78,7 +80,7 @@ dependencies: condition: mysql.enabled repository: https://charts.bitnami.com/bitnami tags: - - mojafos + - gazelle - dependency - mysql version: 9.4.5 diff --git a/src/mojafos/deployer/helm/infra/values.yaml b/src/deployer/helm/infra/values.yaml similarity index 74% rename from src/mojafos/deployer/helm/infra/values.yaml rename to src/deployer/helm/infra/values.yaml index 11d0bfd..9f001a1 100644 --- a/src/mojafos/deployer/helm/infra/values.yaml +++ b/src/deployer/helm/infra/values.yaml @@ -97,7 +97,7 @@ redpanda-console: enabled: true className: nginx hosts: - - host: redpanda-console.local + - host: redpanda-console.mifos.gazelle.test paths: - path: / pathType: ImplementationSpecific @@ -133,9 +133,16 @@ mongo-express: fullnameOverride: mongo-express enabled: true + image: + tag: 1.0.2 + ingress: enabled: true ingressClassName: nginx + hosts: + - host: mongoexpress.mifos.gazelle.test + paths: + - / mongodbEnableAdmin: true mongodbAdminPassword: mongoDbPas42 @@ -183,6 +190,45 @@ elasticsearch: enabled: true # hostname: es01 +kibana: + enabled: true + imageTag: 7.16.3 + fullnameOverride: "ph-ee-kibana" + elasticsearchHosts: "http://ph-ee-elasticsearch:9200/" + protocol: http + kibanaConfig: + kibana.yml: | + monitoring.enabled: false + xpack.encryptedSavedObjects.encryptionKey: 5f4dcc3b5aa765d61d8327deb882cf99 + server.ssl: + enabled: false + key: /usr/share/kibana/config/certs/elastic-certificate.pem + certificate: /usr/share/kibana/config/certs/elastic-certificate.pem + xpack.security.encryptionKey: ${KIBANA_ENCRYPTION_KEY} + elasticsearch.ssl: + certificateAuthorities: /usr/share/kibana/config/certs/elastic-certificate.pem + verificationMode: certificate + secretMounts: + - name: elastic-certificate-pem + secretName: elastic-certificate-pem + path: /usr/share/kibana/config/certs + extraEnvs: + - name: 'ELASTICSEARCH_USERNAME' + valueFrom: + secretKeyRef: + name: elastic-credentials + key: username + - name: 'ELASTICSEARCH_PASSWORD' + valueFrom: + secretKeyRef: + name: elastic-credentials + key: password + - name: 'KIBANA_ENCRYPTION_KEY' + valueFrom: + secretKeyRef: + name: kibana + key: encryptionkey + ############### MySQL #################### mysql: fullnameOverride: "mysql" @@ -191,27 +237,22 @@ mysql: database: "tenants" username: "mifos" password: "password" - rootPassword: "ethieTieCh8ahv" + rootPassword: "mysqlpw" + # rootPassword: "ethieTieCh8ahv" image: tag: "5.7" debug: false initdbScripts: setup.sql: |- - CREATE DATABASE messagegateway; - CREATE DATABASE `rhino`; - CREATE DATABASE `gorilla`; - CREATE DATABASE `lion`; - CREATE DATABASE `identity_account_mapper`; - CREATE DATABASE `voucher_management`; - GRANT ALL PRIVILEGES ON `rhino`.* TO 'mifos'; - GRANT ALL PRIVILEGES ON `gorilla`.* TO 'mifos'; - GRANT ALL PRIVILEGES ON `lion`.* TO 'mifos'; - GRANT ALL ON *.* TO 'root'@'%'; + CREATE DATABASE IF NOT EXISTS messagegateway; + CREATE DATABASE IF NOT EXISTS `identity_account_mapper`; + CREATE DATABASE IF NOT EXISTS `voucher_management`; + CREATE DATABASE IF NOT EXISTS `fineract_tenants`; + CREATE DATABASE IF NOT EXISTS `fineract_default`; GRANT ALL PRIVILEGES ON messagegateway.* TO 'mifos'; GRANT ALL PRIVILEGES ON `identity_account_mapper`.* TO 'mifos'; GRANT ALL PRIVILEGES ON `voucher_management`.* TO 'mifos'; - CREATE DATABASE IF NOT EXISTS `fineract_tenants`; - CREATE DATABASE IF NOT EXISTS `fineract_default`; - GRANT ALL ON *.* TO 'root'@'%'; GRANT ALL PRIVILEGES ON `fineract_tenants`.* TO 'mifos'; GRANT ALL PRIVILEGES ON `fineract_default`.* TO 'mifos'; + GRANT ALL ON *.* TO 'root'@'%'; + diff --git a/src/mojafos/environmentSetup/environmentSetup.sh b/src/environmentSetup/environmentSetup.sh similarity index 72% rename from src/mojafos/environmentSetup/environmentSetup.sh rename to src/environmentSetup/environmentSetup.sh index 65e5627..1eb22c2 100755 --- a/src/mojafos/environmentSetup/environmentSetup.sh +++ b/src/environmentSetup/environmentSetup.sh @@ -2,7 +2,7 @@ function check_arch_ok { if [[ ! "$k8s_arch" == "x86_64" ]]; then - printf " **** Warning : mojafos only works properly with x86_64 today but vNext should be ok *****\n" + printf " **** Warning : mifos-gazelle only works properly with x86_64 today but vNext should be ok *****\n" fi } @@ -14,18 +14,32 @@ function check_resources_ok { # Check RAM if [[ "$total_ram" -lt "$MIN_RAM" ]]; then - printf " ** Error : mojafos currently requires $MIN_RAM GBs to run properly \n" - printf " Please increase RAM available before trying to run mojafos \n" + printf " ** Error : mifos-gazelle currently requires $MIN_RAM GBs to run properly \n" + printf " Please increase RAM available before trying to run mifos-gazelle \n" exit 1 fi # Check free space if [[ "$free_space" -lt "$MIN_FREE_SPACE" ]] ; then - printf " ** Warning : mojafos currently requires %sGBs free storage in %s home directory \n" "$MIN_FREE_SPACE" "$k8s_user" + printf " ** Warning : mifos-gazelle currently requires %sGBs free storage in %s home directory \n" "$MIN_FREE_SPACE" "$k8s_user" printf " but only found %sGBs free storage \n" "$free_space" - printf " mojafos installation will continue , but beware it might fail later due to insufficient storage \n" + printf " mifos-gazelle installation will continue , but beware it might fail later due to insufficient storage \n" fi } +function checkHelmandKubectl { + # Check if Helm is installed + if ! command -v helm &>/dev/null; then + echo "Helm is not installed. Please install Helm first." + exit 1 + fi + + # Check if kubectl is installed + if ! command -v kubectl &>/dev/null; then + echo "kubectl is not installed. Please install kubectl first." + exit 1 + fi +} + function set_user { # set the k8s_user # k8s_user=`whoami | cut -d " " -f1` @@ -34,14 +48,15 @@ function set_user { function k8s_already_installed { if [[ -f "/usr/local/bin/k3s" ]]; then - printf "** Error , k3s is already installed , please delete before reinstalling kubernetes **\n" - exit 1 + printf "==> k3s is already installed **\n" + return 0 fi #check to ensure microk8s isn't already installed when installing k3s if [[ -f "/snap/bin/microk8s" ]]; then - printf "** Error , microk8s is already installed, please delete before reinstalling kubernetes **\n" - exit 1 + printf "** warning , microk8s is already installed, using existing deployment **\n" + return 0 fi + return 1 } function set_linux_os_distro { @@ -57,11 +72,11 @@ function set_linux_os_distro { } function check_os_ok { - printf "\r==> checking OS and kubernetes distro is tested with mojafos scripts\n" + printf "\r==> checking OS and kubernetes distro is tested with mifos-gazelle scripts\n" set_linux_os_distro if [[ ! $LINUX_OS == "Ubuntu" ]]; then - printf "** Error , mojafos $MINILOOP_VERSION is only tested with Ubuntu OS at this time **\n" + printf "** Error , Mifos Gazelle is only tested with Ubuntu OS at this time **\n" exit 1 fi } @@ -127,23 +142,41 @@ function install_prerequisites { logWithVerboseCheck $debug debug "jq is already installed\n" fi fi -} -function add_hosts { - printf "==> Mojafos : update hosts file \n" - ENDPOINTSLIST=(127.0.0.1 ml-api-adapter.local central-ledger.local account-lookup-service.local account-lookup-service-admin.local - quoting-service.local central-settlement-service.local transaction-request-service.local central-settlement.local bulk-api-adapter.local - moja-simulator.local sim-payerfsp.local sim-payeefsp.local sim-testfsp1.local sim-testfsp2.local sim-testfsp3.local sim-testfsp4.local - mojaloop-simulators.local finance-portal.local operator-settlement.local settlement-management.local testing-toolkit.local - testing-toolkit-specapi.local apachehost - mongohost.local mongo-express.local vnextadmin elasticsearch.local redpanda-console.local fspiop.local bluebank.local greenbank.local bluebank-specapi.local greenbank-specapi.local ) - export ENDPOINTS=`echo ${ENDPOINTSLIST[*]}` +} +function add_hosts { + printf "==> Mifos-gazelle : update hosts file \n" + VNEXTHOSTS=( mongohost.mifos.gazelle.test mongo-express.mifos.gazelle.test \ + vnextadmin.mifos.gazelle.test kafkaconsole.mifos.gazelle.test elasticsearch.mifos.gazelle.test redpanda-console.mifos.gazelle.test \ + fspiop.mifos.gazelle.test bluebank.mifos.gazelle.test greenbank.mifos.gazelle.test \ + bluebank-specapi.mifos.gazelle.test greenbank-specapi.mifos.gazelle.test ) + + PHEEHOSTS=( ops.mifos.gazelle.test ops-bk.mifos.gazelle.test \ + bulk-connector.mifos.gazelle.test messagegateway.mifos.gazelle.test \ + minio.mifos.gazelle.test ams-mifos.mifos.gazelle.test \ + bill-pay.mifos.gazelle.test channel.mifos.gazelle.test \ + channel-gsma.mifos.gazelle.test crm.mifos.gazelle.test \ + mockpayment.mifos.gazelle.test mojaloop.mifos.gazelle.test \ + identity-mapper.mifos.gazelle.test vouchers.mifos.gazelle.test \ + zeebeops.mifos.gazelle.test zeebe-operate.mifos.gazelle.test zeebe-gateway.mifos.gazelle.test \ + elastic-phee.mifos.gazelle.test kibana-phee.mifos.gazelle.test \ + notifications.mifos.gazelle.test ) + + MIFOSXHOSTS=( mifos.mifos.gazelle.test fineract.mifos.gazelle.test ) + + ALLHOSTS=( "127.0.0.1" "localhost" "${PHEEHOSTS[@]}" "${VNEXTHOSTS[@]}" ) + + export ENDPOINTS=`echo ${ALLHOSTS[*]}` + # remove any existing extra hosts from 127.0.0.1 entry in localhost + perl -pi -e 's/^(127\.0\.0\.1\s+)(.*)/$1localhost/' /etc/hosts + + # add all the gazelle hosts to the 127.0.0.1 localhost entry of /etc/hosts perl -p -i.bak -e 's/127\.0\.0\.1.*localhost.*$/$ENV{ENDPOINTS} /' /etc/hosts # TODO check the ping actually works > suggest cloud network rules if it doesn't # also for cloud VMs might need to use something other than curl e.g. netcat ? - # ping -c 2 account-lookup-service-admin.local + # ping -c 2 account-lookup-service-admin.mifos.gazelle.test } function set_k8s_distro { @@ -173,7 +206,7 @@ function set_k8s_version { # printf "========================================================================================\n" # printf " set the k8s version to install \n" # printf "========================================================================================\n\n" - # Users who want to run non-current versions of kubernetes will need to use earlier releases of mojafos and + # Users who want to run non-current versions of kubernetes will need to use earlier releases of mifos-gazelle and # and be aware that these are not being actively maintained if [ ! -z ${k8s_user_version+x} ] ; then # strip off any leading characters @@ -206,27 +239,24 @@ function do_microk8s_install { # TODO : Microk8s can complain that This is insecure. Location: /var/snap/microk8s/2952/credentials/client.config printf "==> Installing Kubernetes MicroK8s & enabling tools (helm,ingress etc) \n" - echo "==> Mojaloop Microk8s Install: installing microk8s release $k8s_user_version ... " + echo "==> Microk8s Install: installing microk8s release $k8s_user_version ... " # ensure k8s_user has clean .kube/config rm -rf $k8s_user_home/.kube >> /dev/null 2>&1 snap install microk8s --classic --channel=$K8S_VERSION/stable microk8s.status --wait-ready - #echo "==> Mojaloop Microk8s Install: enable helm ... " microk8s.enable helm3 - #echo "==> Mojaloop Microk8s Install: enable dns ... " microk8s.enable dns - echo "==> Mojaloop: enable storage ... " + echo "==> enable storage ... " microk8s.enable storage - #echo "==> Mojaloop: enable ingress ... " microk8s.enable ingress - echo "==> Mojaloop: add convenient aliases..." + echo "==> add convenient aliases..." snap alias microk8s.kubectl kubectl snap alias microk8s.helm3 helm - echo "==> Mojaloop: add $k8s_user user to microk8s group" + echo "==> add $k8s_user user to microk8s group" usermod -a -G microk8s $k8s_user # ensure .kube/config points to this new cluster and KUBECONFIG is not set in .bashrc @@ -238,7 +268,7 @@ function do_microk8s_install { function do_k3s_install { printf "========================================================================================\n" - printf "Mojafos k3s install : Installing Kubernetes k3s engine and tools (helm/ingress etc) \n" + printf "Mifos-gazelle k3s install : Installing Kubernetes k3s engine and tools (helm/ingress etc) \n" printf "========================================================================================\n" # ensure k8s_user has clean .kube/config rm -rf $k8s_user_home/.kube >> /dev/null 2>&1 @@ -297,25 +327,57 @@ function do_k3s_install { printf "** Error : helm install seems to have failed ** \n" exit 1 fi +} - #install nginx - printf "\r==> installing nginx ingress chart and wait for it to be ready " - su - $k8s_user -c "helm install --wait --timeout 300s ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx" > /dev/null 2>&1 - # TODO : check to ensure that the ingress is indeed running - nginx_pod_name=$(kubectl get pods | grep nginx | awk '{print $1}') +function check_nginx_running { + # Get the first nginx pod name + nginx_pod_name=$(kubectl get pods --no-headers -o custom-columns=":metadata.name" | grep nginx | head -n 1) if [ -z "$nginx_pod_name" ]; then - printf "** Error : helm install of nginx seems to have failed , no nginx pod found ** \n" - exit 1 + # No nginx pod found + return 1 fi # Check if the Nginx pod is running - if kubectl get pods $nginx_pod_name | grep -q "Running"; then - printf "[ok]\n" + pod_status=$(kubectl get pod $nginx_pod_name -o jsonpath='{.status.phase}') + if [ "$pod_status" == "Running" ]; then + # nginx is running + return 0 else - printf "** Error : helm install of nginx seems to have failed , nginx pod is not running ** \n" - exit 1 + # nginx is not running + return 1 fi +} +function install_nginx () { + local cluster_type=$1 + local k8s_distro=$2 + #install nginx + printf "\r==> installing nginx ingress chart and wait for it to be ready " + if check_nginx_running; then + printf "[ nginx already installed and running ] \n" + return 0 + fi + # echo "\n nope cluster is not running" + # echo "cluster_type=$cluster_type" + # echo "k8s_distro=$k8s_distro" + if [[ $cluster_type == "local" ]]; then + if [[ $k8s_distro == "microk8s" ]]; then + microk8s.enable ingress + printf "[ok]\n" + else # i.e. k3s + su - $k8s_user -c "helm delete ingress-nginx -n default " > /dev/null 2>&1 + su - $k8s_user -c "helm install --wait --timeout 1200s ingress-nginx ingress-nginx \ + --repo https://kubernetes.github.io/ingress-nginx \ + -n default -f $NGINX_VALUES_FILE" > /dev/null 2>&1 + # Check if the Nginx pod is running + if check_nginx_running; then + printf "[ok]\n" + else + printf "** Error : helm install of nginx seems to have failed , nginx pod is not running ** \n" + exit 1 + fi + fi + fi } function install_k8s_tools { @@ -331,8 +393,7 @@ function install_k8s_tools { } function add_helm_repos { - # see readme at https://github.com/mojaloop/helm for required helm libs - printf "\r==> add the helm repos required to install and run infrastructure for Mojaloop, Paymenthub EE and Fineract\n" + printf "\r==> add the helm repos required to install and run infrastructure for vNext, Paymenthub EE and MifosX\n" su - $k8s_user -c "helm repo add kiwigrid https://kiwigrid.github.io" > /dev/null 2>&1 su - $k8s_user -c "helm repo add kokuwa https://kokuwaio.github.io/helm-charts" > /dev/null 2>&1 #fluentd su - $k8s_user -c "helm repo add elastic https://helm.elastic.co" > /dev/null 2>&1 @@ -341,14 +402,12 @@ function add_helm_repos { su - $k8s_user -c "helm repo add mojaloop http://mojaloop.io/helm/repo/" > /dev/null 2>&1 su - $k8s_user -c "helm repo add cowboysysop https://cowboysysop.github.io/charts/" > /dev/null 2>&1 # mongo-express su - $k8s_user -c "helm repo add redpanda-data https://charts.redpanda.com/ " > /dev/null 2>&1 # kafka console - su - $k8s_user -c "helm repo add $PH_CHART_REPO_NAME $PH_HELM_REPO_LINK" > /dev/null 2>&1 #g2p-sandbox - su - $k8s_user -c "helm repo update" > /dev/null 2>&1 } function configure_k8s_user_env { - start_message="# ML_START start of config added by mojafos #" - grep "start of config added by mojafos" $k8s_user_home/.bashrc >/dev/null 2>&1 + start_message="# GAZELLE_START start of config added by mifos-gazelle #" + grep "start of config added by mifos-gazelle" $k8s_user_home/.bashrc >/dev/null 2>&1 if [[ $? -ne 0 ]]; then printf "==> Adding configuration for %s to %s .bashrc\n" "$k8s_distro" "$k8s_user" printf "%s\n" "$start_message" >> $k8s_user_home/.bashrc @@ -357,8 +416,8 @@ function configure_k8s_user_env { echo "complete -F __start_kubectl k " >> $k8s_user_home/.bashrc echo "alias ksetns=\"kubectl config set-context --current --namespace\" " >> $k8s_user_home/.bashrc echo "alias ksetuser=\"kubectl config set-context --current --user\" " >> $k8s_user_home/.bashrc - echo "alias cdml=\"cd $k8s_user_home/mojafos\" " >> $k8s_user_home/.bashrc - printf "#ML_END end of config added by mojafos #\n" >> $k8s_user_home/.bashrc + echo "alias cdml=\"cd $k8s_user_home/mifos-gazelle\" " >> $k8s_user_home/.bashrc + printf "#GAZELLE_END end of config added by mifos-gazelle #\n" >> $k8s_user_home/.bashrc else printf "\r==> Configuration for .bashrc for %s for user %s already exists ..skipping\n" "$k8s_distro" "$k8s_user" fi @@ -411,15 +470,14 @@ function delete_k8s { fi fi # remove config from user .bashrc - perl -i -ne 'print unless /START_ML/ .. /END_ML/' $k8s_user_home/.bashrc + perl -i -ne 'print unless /START_GAZELLE/ .. /END_GAZELLE/' $k8s_user_home/.bashrc } -function check_k8s_installed { +function checkClusterConnection { printf "\r==> Check the cluster is available and ready from kubectl " k8s_ready=`su - $k8s_user -c "kubectl get nodes" | perl -ne 'print if s/^.*Ready.*$/Ready/'` if [[ ! "$k8s_ready" == "Ready" ]]; then - printf "** Error : kubernetes is not installed , please run $0 -m install -u $k8s_user \n" - printf " before trying to install mojaloop \n " + printf "** Error : kubernetes is not reachable ** " exit 1 fi printf " [ ok ] \n" @@ -432,39 +490,12 @@ function print_end_message { } function print_end_message_tear_down { - echo -e "\n\n==============================================" - echo -e "Thank you for using Mojafos cleanup successful" - echo -e "==============================================\n\n" + echo -e "\n\n==================================================" + echo -e "Thank you for using Mifos-gazelle cleanup successful" + echo -e "======================================================\n\n" echo -e "Copyright © 2023 The Mifos Initiative" } -################################################################################ -# Function: showUsage -################################################################################ -# Description: Display usage message -# Arguments: none -# Return values: none -# -function showUsage { - if [ $# -ne 0 ] ; then - echo "Incorrect number of arguments passed to function $0" - exit 1 - else -echo "USAGE: $0 -m [mode] -u [user] -v [k8 version] -k [distro] [-f] -Example 1 : run -m install -v 1.25 -k k3s # install k8s k3s version 1.24 -Example 2 : run -m delete -v 1.26 -k microk8s # delete k8s microk8s version 1.26 -Example 3 : run -m install -k microk8s -v 1.26 -k k3s # install k8s microk8s distro version 1.26 - -Options: --m mode ............... install|delete (-m is required) --k kubernetes distro... microk8s|k3s (default=k3s as it installs across multiple linux distros) --v k8s version ........ 1.24|1.25|1.26 i.e. current k8s releases at time if this mojafos release --h|H .................. display this message -" - fi - -} - function setup_k8s_cluster { cluster_type="$2" @@ -500,17 +531,24 @@ function setup_k8s_cluster { fi } +# function deleteAppResources(){ +# deleteResourcesInNamespaceMatchingPattern "$FIN_NAMESPACE" +# deleteResourcesInNamespaceMatchingPattern "$VNEXT_NAMESPACE" +# deleteResourcesInNamespaceMatchingPattern "$PH_NAMESPACE" +# deleteResourcesInNamespaceMatchingPattern "$INFRA_NAMESPACE" +# deleteResourcesInNamespaceMatchingPattern "default" +# } + ################################################################################ # MAIN ################################################################################ function envSetupMain { - DEFAULT_K8S_DISTRO="k3s" # default to microk8s as this is what is in the mojaloop linux deploy docs. + DEFAULT_K8S_DISTRO="k3s" #only k3s is currently being tested K8S_VERSION="" - MINILOOP_VERSION="vNext" HELM_VERSION="3.12.0" # Feb 2023 OS_VERSIONS_LIST=( 20 22 ) - K8S_CURRENT_RELEASE_LIST=( "1.26" "1.27" ) + K8S_CURRENT_RELEASE_LIST=( "1.29" "1.30" ) CURRENT_RELEASE="false" k8s_user_home="" k8s_arch=`uname -p` # what arch @@ -544,32 +582,31 @@ function envSetupMain { verify_user if [[ "$mode" == "deploy" ]] ; then - BASE_DIR=$( cd $(dirname "$0")/../.. ; pwd ) - RUN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # the directory that this script is run from check_resources_ok set_k8s_distro set_k8s_version - k8s_already_installed - check_os_ok # todo add check to this once tested across other OS's more fully - install_prerequisites - add_hosts - setup_k8s_cluster $k8s_distro $environment - install_k8s_tools - add_helm_repos - configure_k8s_user_env - check_k8s_installed - printf "\r==> kubernetes distro:[%s] version:[%s] is now configured for user [%s] and ready for mojaloop deployment \n" \ + if ! k8s_already_installed; then + check_os_ok # todo add check to this once tested across other OS's more fully + install_prerequisites + add_hosts + setup_k8s_cluster $k8s_distro $environment + install_nginx $environment $k8s_distro + install_k8s_tools + add_helm_repos + configure_k8s_user_env + else + checkHelmandKubectl # ensure things really are in place properly + fi + install_nginx $environment $k8s_distro # will skip if already running + checkClusterConnection + printf "\r==> kubernetes distro:[%s] version:[%s] is now configured for user [%s] and ready for Mifos Gazelle deployment \n" \ "$k8s_distro" "$K8S_VERSION" "$k8s_user" print_end_message - elif [[ "$mode" == "cleanup" ]] ; then - deleteResourcesInNamespsceMatchingPattern "fineract" - deleteResourcesInNamespsceMatchingPattern "mojaloop" - deleteResourcesInNamespsceMatchingPattern "paymenthub" - deleteResourcesInNamespsceMatchingPattern "infra" + elif [[ "$mode" == "cleanall" ]] ; then if [[ "$environment" == "local" ]]; then echo "Deleting local kubernetes cluster..." delete_k8s - echo "Local Kubernetes deleted" + echo "Local Kubernetes deleted" fi print_end_message_tear_down else diff --git a/src/mojafos/commandline/commandline.sh b/src/mojafos/commandline/commandline.sh deleted file mode 100755 index ede03fc..0000000 --- a/src/mojafos/commandline/commandline.sh +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env bash - -source ./src/mojafos/configurationManager/config.sh -source ./src/mojafos/environmentSetup/environmentSetup.sh -source ./src/mojafos/deployer/deployer.sh - -function welcome { - echo -e "${BLUE}" - echo -e "███ ███ ██████ ██ █████ ███████ ██████ ███████ " - echo -e "████ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ " - echo -e "██ ████ ██ ██ ██ ██ ███████ █████ ██ ██ ███████ " - echo -e "██ ██ ██ ██ ██ █ ██ ██ ██ ██ ██ ██ ██ " - echo -e "██ ██ ██████ █████ ██ ██ ██ ██████ ███████ " - echo -e " " - echo -e " ${RESET}" -} - -function showUsage { - if [ $# -ne 0 ] ; then - echo "Incorrect number of arguments passed to function $0" - exit 1 - else -echo "USAGE: $0 -m [mode] -u [user] -d [true/false] -Example 1 : sudo $0 -m deploy -u \$USER -d true # install mojafos with debug mode and user \$USER -Example 2 : sudo $0 -m cleanup -u \$USER -d true # delete mojafos with debug mode and user \$USER -Example 3 : sudo $0 -m deploy -u \$USER -d false # install mojafos without debug mode and user \$USER - -Options: --m mode ............... install|delete (-m is required) --u user................ user that the process will use for execution --d debug............... debug mode. if set debug is true, if not set debug is false --h|H .................. display this message -" - fi - -} - -function getoptions { - local mode_opt - - while getopts "m:k:d:a:f:e:u:hH" OPTION ; do - case "${OPTION}" in - m) mode_opt="${OPTARG}" - ;; - k) k8s_distro="${OPTARG}" - ;; - d) debug="${OPTARG}" - ;; - a) apps="${OPTARG}" - ;; - f) fineract_instansces="${OPTARG}" - ;; - e) environment="${OPTARG}" - ;; - v) k8s_user_version="${OPTARG}" - ;; - u) k8s_user="${OPTARG}" - ;; - h|H) showUsage - exit 0 - ;; - *) echo "unknown option" - showUsage - exit 1 - ;; - esac - done - - if [ -z "$mode_opt" ]; then - echo "Error: Mode argument is required." - showUsage - exit 1 - fi - - if [ -z "$debug" ]; then - debug=false - fi - - mode="$mode_opt" -} - -# this function is called when Ctrl-C is sent -function cleanUp () -{ - # perform cleanup here - echo -e "${RED}Performing graceful clean up${RESET}" - - mode="cleanup" - echo "Doing cleanup" - envSetupMain "$mode" "k3s" "1.26" "$environment" - - # exit shell script with error code 2 - # if omitted, shell script will continue execution - exit 2 -} - -function trapCtrlc { - echo - echo -e "${RED}Ctrl-C caught...${RESET}" - cleanUp -} - -# initialise trap to call trap_ctrlc function -# when signal 2 (SIGINT) is received -trap "trapCtrlc" 2 - -########################################################################### -# MAIN -########################################################################### -function main { - welcome - getoptions "$@" - if [ $mode == "deploy" ]; then - echo -e "${YELLOW}" - echo -e "====================================================================================" - echo -e "The deployment made by this script is meant for demo purposes and not for production" - echo -e "====================================================================================" - echo -e "${RESET}" - envSetupMain "$mode" "k3s" "1.26" "$environment" - deployApps "$fineract_instansces" "$apps" - elif [ $mode == "cleanup" ]; then - logWithVerboseCheck $debug info "Cleaning up all traces of Mojafos" - envSetupMain "$mode" "k3s" "1.26" "$environment" - else - showUsage - fi -} - -########################################################################### -# CALL TO MAIN -########################################################################### -main "$@" diff --git a/src/mojafos/configurationManager/config.sh b/src/mojafos/configurationManager/config.sh deleted file mode 100755 index db35517..0000000 --- a/src/mojafos/configurationManager/config.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env bash - -######################################################################## -# GLOBAL VARS -######################################################################## -BASE_DIR=$(pwd) -APPS_DIR="$BASE_DIR/src/mojafos/deployer/apps/" -INFRA_NAMESPACE="infra" -INFRA_RELEASE_NAME="mojafos-infra" -#mojaloop -MOJALOOPBRANCH="beta1" -MOJALOOPREPO_DIR="mojaloop" -MOJALOOP_NAMESPACE="mojaloop" -MOJALOOP_REPO_LINK="https://github.com/mojaloop/platform-shared-tools.git" -MOJALOOP_LAYER_DIRS=("$BASE_DIR/src/mojafos/deployer/apps/mojaloop/packages/installer/manifests/crosscut" "$BASE_DIR/src/mojafos/deployer/apps/mojaloop/packages/installer/manifests/ttk" "$BASE_DIR/src/mojafos/deployer/apps/mojaloop/packages/installer/manifests/apps" "$BASE_DIR/src/mojafos/deployer/apps/mojaloop/packages/installer/manifests/reporting") -MOJALOOP_VALUES_FILE="$BASE_DIR/src/mojafos/configurationManager/mojaloop_values.json" -#paymenthubee -PHBRANCH="v1.2.0-release" -PHREPO_DIR="ph" -PH_NAMESPACE="paymenthub" -PH_RELEASE_NAME="moja-ph" -PH_VALUES_FILE="$BASE_DIR/src/mojafos/deployer/ph_values.yaml" -PH_REPO_LINK="https://github.com/openMF/ph-ee-env-labs.git" -PH_HELM_REPO_LINK="https://fynarfin.io/images/ph-ee-g2psandbox-1.5.0/" -PH_G2P_CHART_VERSION="1.5.0" -PH_CHART_REPO_NAME="g2p-sandbox-1-5" -PH_EE_ENV_LABS_REPO_LINK="https://github.com/openMF/ph-ee-env-labs.git" -PH_EE_ENV_LABS_REPO_BRANCH="master" -PH_EE_ENV_LABS_REPO_DIR="ph_env_labs" -PH_EE_ENV_TEMPLATE_REPO_LINK="https://github.com/openMF/ph-ee-env-template.git" -PH_EE_ENV_TEMPLATE_REPO_BRANCH="master" -PH_EE_ENV_TEMPLATE_REPO_DIR="ph_template" -# Define Kubernetes service and MySQL connection details -MYSQL_SERVICE_NAME="mysql" # Replace with your MySQL service name -MYSQL_SERVICE_PORT="3306" # Replace with the MySQL service port -LOCAL_PORT="3307" # Local port to forward to -MAX_WAIT_SECONDS=60 -# MySQL Connection Details -MYSQL_USER="root" -MYSQL_PASSWORD="ethieTieCh8ahv" -MYSQL_HOST="127.0.0.1" # This is the localhost because we are port forwarding -SQL_FILE="$BASE_DIR/src/mojafos/deployer/setup.sql" - -#fineract -FIN_NAMESPACE="fineract" -FIN_BRANCH="master" -FIN_REPO_LINK="https://github.com/fynarfin/fineract-env.git" -FIN_REPO_DIR="fineract" -FIN_NAMESPACE="fineract" -FIN_RELEASE_NAME="fineract" -FIN_VALUES_FILE="$BASE_DIR/src/mojafos/deployer/fin_values.yaml" - - -######################################################################## -# FUNCTIONS FOR CONFIGURATION MANAGEMENT -######################################################################## -function replaceValuesInFiles() { - local directories=("$@") - local json_file="$MOJALOOP_VALUES_FILE" - - # Check if jq is installed, if not, exit with an error message - if ! command -v jq &>/dev/null; then - echo "Error: 'jq' is not installed. Please install it (https://stedolan.github.io/jq/) and make sure it's in your PATH." - return 1 - fi - - # Check if the JSON file exists - if [ ! -f "$json_file" ]; then - echo "Error: JSON file '$json_file' does not exist." - return 1 - fi - - # Read the JSON file and create an associative array - declare -A replacements - while IFS= read -r json_object; do - local old_value new_value - old_value=$(echo "$json_object" | jq -r '.old_value') - new_value=$(echo "$json_object" | jq -r '.new_value') - replacements["$old_value"]="$new_value" - done < <(jq -c '.[]' "$json_file") - - # Loop through the directories and process each file - for dir in "${directories[@]}"; do - if [ -d "$dir" ]; then - find "$dir" -type f | while read -r file; do - local changed=false - for old_value in "${!replacements[@]}"; do - if grep -q "$old_value" "$file"; then - sed -i "s|$old_value|${replacements[$old_value]}|g" "$file" - changed=true - fi - done - if $changed; then - echo "Updated: $file" - fi - done - else - echo "Directory $dir does not exist." - fi - done -} - -function configureMojaloop() { - replaceValuesInFiles "${MOJALOOP_LAYER_DIRS[0]}" "${MOJALOOP_LAYER_DIRS[2]}" "${MOJALOOP_LAYER_DIRS[3]}" -} - - -function createSecret(){ - local namespace="$1" - echo -e "Creating secrets in the $namespace namespace" - if make secrets -e NAMESPACE="$namespace" >> /dev/null 2>&1 ; then - echo -e "${GREEN}Created secrets in the $namespace namespace${RESET}" - return 0 - else - echo -e "${RED}Creating secrets in the $namespace namespace${RESET} failed" - exit 1 - fi -} - -function configurePH() { - local ph_chart_dir=$1 - local previous_dir="$PWD" # Save the current working directory - echo -e "${BLUE}Configuring Payment Hub ${RESET}" - - cd $ph_chart_dir || exit 1 - - # Check if make is installed - if ! command -v make &> /dev/null; then - logWithVerboseCheck $debug info "make is not installed. Installing ..." - sudo apt update >> /dev/null 2>&1 - sudo apt install -y make >> /dev/null 2>&1 - logWithVerboseCheck $debug info "ok" - else - logWithVerboseCheck $debug info "make is installed. Proceeding to configure" - fi - # create secrets for paymenthub namespace and infra namespace - cd es-secret || exit 1 - createSecret "$PH_NAMESPACE" - createSecret "$INFRA_NAMESPACE" - cd .. - cd kibana-secret || exit 1 - createSecret "$PH_NAMESPACE" - createSecret "$INFRA_NAMESPACE" - cd .. - # kubectl create secret generic moja-ph-redis --from-literal=redis-password="" -n "$PH_NAMESPACE" - - # check if the configuration was successful - if [ $? -eq 0 ]; then - echo -e "${GREEN}Configuration of Paymenthub Successful${RESET}" - else - echo -e "${RED}Configuration of Paymenthub Failed${RESET}" - exit 1 - fi - - # Return to the previous working directory - cd "$previous_dir" || return 1 -} - -function configureFineract(){ - echo -e "${BLUE}Configuring fineract ${RESET}" -} \ No newline at end of file diff --git a/src/mojafos/deployer/deployer.sh b/src/mojafos/deployer/deployer.sh deleted file mode 100755 index 630af21..0000000 --- a/src/mojafos/deployer/deployer.sh +++ /dev/null @@ -1,498 +0,0 @@ -#!/usr/bin/env bash - - -function deleteResourcesInNamespsceMatchingPattern(){ - local pattern="$1" - - # Check if the pattern is provided - if [ -z "$pattern" ]; then - echo "Pattern not provided." - exit 1 - fi - - # Get the list of namespaces and filter them based on the pattern - namespaces=$(kubectl get namespaces -o=name | grep "$pattern") - - # Loop through the filtered namespaces and delete resources in each one - while IFS= read -r namespace; do - namespace=$(echo "$namespace" | cut -d'/' -f2) - kubectl delete all --all -n "$namespace" - if [ $? -eq 0 ]; then - echo "All resources in namespace $namespace deleted successfully." - else - echo "Error deleting resources in namespace $namespace." - fi - done <<< "$namespaces" -} - -function deployHelmChartFromDir() { - # Check if Helm is installed - if ! command -v helm &>/dev/null; then - echo "Helm is not installed. Please install Helm first." - exit 1 - fi - - # Check if the chart directory exists - local chart_dir="$1" - local namespace="$2" - local release_name="$3" - if [ ! -d "$chart_dir" ]; then - echo "Chart directory '$chart_dir' does not exist." - exit 1 - fi - - # Check if a values file has been provided - values_file="$4" - - # Enter the chart directory - cd "$chart_dir" || exit 1 - - # Run helm dependency update to fetch dependencies - echo "Updating Helm chart dependencies..." - helm dependency update >> /dev/null 2>&1 - echo -e "==> Helm chart updated" - - # Run helm dependency build - echo "Building Helm chart dependencies..." - helm dependency build . >> /dev/null 2>&1 - echo -e "==> Helm chart dependencies built" - - # Determine whether to install or upgrade the chart also check whether to apply a values file - if [ -n "$values_file" ]; then - if helm list -n "$namespace" | grep -q "$release_name"; then - echo "Upgrading Helm chart..." - helm upgrade --install "$release_name" . -n "$namespace" -f "$values_file" - echo -e "==> Helm chart upgraded" - else - echo "Installing Helm chart..." - helm install "$release_name" . -n "$namespace" -f "$values_file" - echo -e "==> Helm chart installed" - fi - else - if helm list -n "$namespace" | grep -q "$release_name"; then - echo "Upgrading Helm chart..." - helm upgrade --install "$release_name" . -n "$namespace" - echo -e "==> Helm chart upgraded" - else - echo "Installing Helm chart..." - helm install "$release_name" . -n "$namespace" - echo -e "==> Helm chart installed" - fi - fi - - # Use kubectl to get the resource count in the specified namespace - resource_count=$(kubectl get pods -n "$namespace" --ignore-not-found=true 2>/dev/null | grep -v "No resources found" | wc -l) - - # Check if the deployment was successful - if [ $resource_count -gt 0 ]; then - echo "Helm chart deployed successfully." - else - echo -e "${RED}Helm chart deployment failed.${RESET}" - cleanUp - fi - - # Exit the chart directory - cd - || exit 1 - -} - -function preparePaymentHubChart(){ - # Clone the repositories - cloneRepo "$PH_EE_ENV_LABS_REPO_BRANCH" "$PH_EE_ENV_LABS_REPO_LINK" "$APPS_DIR" "$PH_EE_ENV_LABS_REPO_DIR" - cloneRepo "$PH_EE_ENV_TEMPLATE_REPO_BRANCH" "$PH_EE_ENV_TEMPLATE_REPO_LINK" "$APPS_DIR" "$PH_EE_ENV_TEMPLATE_REPO_DIR" - - # Update helm dependencies and repo index for ph-ee-engine - phEEenginePath="$APPS_DIR$PH_EE_ENV_TEMPLATE_REPO_DIR/helm/ph-ee-engine" - pushd "$phEEenginePath" - helm dep update - helm repo index . - popd - - # Update helm dependencies and repo index for g2p-sandbox in ph-ee-env-template - g2pSandboxChartPath="$APPS_DIR$PH_EE_ENV_TEMPLATE_REPO_DIR/helm/g2p-sandbox" - awk '/repository:/ && c == 0 {sub(/repository: .*/, "repository: file://../ph-ee-engine"); c++} {print}' "$g2pSandboxChartPath/Chart.yaml" > "$g2pSandboxChartPath/Chart.yaml.tmp" && mv "$g2pSandboxChartPath/Chart.yaml.tmp" "$g2pSandboxChartPath/Chart.yaml" - pushd "$g2pSandboxChartPath" - helm dep update - helm repo index . - popd - - # Update helm dependencies and repo index for g2p-sandbox-fynarfin-SIT in ph-ee-env-labs - g2pSandboxFinalChartPath="$APPS_DIR$PH_EE_ENV_LABS_REPO_DIR/helm/g2p-sandbox-fynarfin-SIT" - awk '/repository:/ && c == 0 {sub(/repository: .*/, "repository: file://../../../'$PH_EE_ENV_TEMPLATE_REPO_DIR'/helm/g2p-sandbox"); c++} {print}' "$g2pSandboxFinalChartPath/Chart.yaml" > "$g2pSandboxFinalChartPath/Chart.yaml.tmp" && mv "$g2pSandboxFinalChartPath/Chart.yaml.tmp" "$g2pSandboxFinalChartPath/Chart.yaml" - pushd "$g2pSandboxFinalChartPath" - helm dep update - helm repo index . - popd -} - -function deployPhHelmChartFromDir(){ - # Parameters - local namespace="$1" - local chartDir="$2" # Directory containing the Helm chart - local valuesFile="$3" # Values file for the Helm chart - - # Check if Helm is installed - if ! command -v helm &>/dev/null; then - echo "Helm is not installed. Please install Helm first." - exit 1 - fi - - # Check if kubectl is installed - if ! command -v kubectl &>/dev/null; then - echo "kubectl is not installed. Please install kubectl first." - exit 1 - fi - - # Install Prometheus Operator as a dependency - LATEST=$(curl -s https://api.github.com/repos/prometheus-operator/prometheus-operator/releases/latest | jq -cr .tag_name) - su - "$k8s_user" -c "curl -sL https://github.com/prometheus-operator/prometheus-operator/releases/download/${LATEST}/bundle.yaml | kubectl create -f -" - - # Install the Helm chart from the local directory - if [ -z "$valuesFile" ]; then - su - "$k8s_user" -c "helm install $PH_RELEASE_NAME $chartDir -n $namespace" - else - su - "$k8s_user" -c "helm install $PH_RELEASE_NAME $chartDir -n $namespace -f $valuesFile" - fi - - # Check deployment status - resource_count=$(kubectl get pods -n "$namespace" --ignore-not-found=true 2>/dev/null | grep -v "No resources found" | wc -l) - - if [ "$resource_count" -gt 0 ]; then - echo "Helm chart deployed successfully." - else - echo -e "${RED}Helm chart deployment failed.${RESET}" - cleanUp - fi -} - -function createNamespace () { - local namespace=$1 - printf "==> Creating namespace $namespace \n" - # Check if the namespace already exists - if kubectl get namespace "$namespace" >> /dev/null 2>&1; then - echo -e "${RED}Namespace $namespace already exists.${RESET}" - exit 1 - fi - - # Create the namespace - kubectl create namespace "$namespace" - if [ $? -eq 0 ]; then - echo -e "==> Namespace $namespace created successfully." - else - echo "Failed to create namespace $namespace." - fi -} - -function deployInfrastructure () { - printf "==> Deploying infrastructure \n" - createNamespace $INFRA_NAMESPACE - if [ "$debug" = true ]; then - deployHelmChartFromDir "./src/mojafos/deployer/helm/infra" "$INFRA_NAMESPACE" "$INFRA_RELEASE_NAME" - else - deployHelmChartFromDir "./src/mojafos/deployer/helm/infra" "$INFRA_NAMESPACE" "$INFRA_RELEASE_NAME" >> /dev/null 2>&1 - fi - echo -e "\n${GREEN}============================" - echo -e "Infrastructure Deployed" - echo -e "============================${RESET}\n" -} - -function cloneRepo() { - if [ "$#" -ne 4 ]; then - echo "Usage: cloneRepo " - return 1 - fi - - # Store the current working directory - original_dir="$(pwd)" - - branch="$1" - repo_link="$2" - target_directory="$3" - cloned_directory_name="$4" - - # Check if the target directory exists; if not, create it. - if [ ! -d "$target_directory" ]; then - mkdir -p "$target_directory" - fi - - # Change to the target directory. - cd "$target_directory" || return 1 - - # Clone the repository with the specified branch into the specified directory. - if [ -d "$cloned_directory_name" ]; then - echo -e "${YELLOW}$cloned_directory_name Repo exists deleting and re-cloning ${RESET}" - rm -rf "$cloned_directory_name" - git clone -b "$branch" "$repo_link" "$cloned_directory_name" >> /dev/null 2>&1 - else - git clone -b "$branch" "$repo_link" "$cloned_directory_name" >> /dev/null 2>&1 - fi - - if [ $? -eq 0 ]; then - echo "==> Repository cloned successfully." - else - echo "Failed to clone the repository." - fi - - # Change back to the original directory - cd "$original_dir" || return 1 -} - -function applyKubeManifests() { - if [ "$#" -ne 2 ]; then - echo "Usage: applyKubeManifests " - return 1 - fi - - local directory="$1" - local namespace="$2" - - # Check if the directory exists. - if [ ! -d "$directory" ]; then - echo "Directory '$directory' not found." - return 1 - fi - - # Use 'kubectl apply' to apply manifests in the specified directory. - kubectl apply -f "$directory" -n "$namespace" >> /dev/null 2>&1 - - if [ $? -eq 0 ]; then - echo -e "==>Kubernetes manifests applied successfully." - else - echo -e "${RED}Failed to apply Kubernetes manifests.${RESET}" - fi -} - -function runFailedSQLStatements(){ - echo "Fxing Operations App MySQL Race condition" - operationsDeplName=$(kubectl get deploy --no-headers -o custom-columns=":metadata.name" -n $PH_NAMESPACE | grep operations-app) - kubectl exec -it mysql-0 -n infra -- mysql -h mysql -uroot -pethieTieCh8ahv < src/mojafos/deployer/setup.sql - - if [ $? -eq 0 ];then - echo "SQL File execution successful" - else - echo "SQL File execution failed" - exit 1 - fi - - echo "Restarting Deployment for Operations App" - kubectl rollout restart deploy/$operationsDeplName -n $PH_NAMESPACE - - if [ $? -eq 0 ];then - echo "Deployment Restart successful" - else - echo "Deployment Restart failed" - exit 1 - fi -} - -function addKubeConfig(){ - K8sConfigDir="$k8s_user_home/.kube" - - if [ ! -d "$K8sConfigDir" ]; then - su - $k8s_user -c "mkdir -p $K8sConfigDir" - echo "K8sConfigDir created: $K8sConfigDir" - else - echo "K8sConfigDir already exists: $K8sConfigDir" - fi - su - $k8s_user -c "cp $k8s_user_home/k3s.yaml $K8sConfigDir/config" -} - -#Function to run kong migrations in Kong init container -function runKongMigrations(){ - echo "Fixing Kong Migrations" - #StoreKongPods - kongPods=$(kubectl get pods --no-headers -o custom-columns=":metadata.name" -n $PH_NAMESPACE | grep moja-ph-kong) - dBcontainerName="wait-for-db" - for pod in $kongPods; - do - podName=$(kubectl get pod $pod --no-headers -o custom-columns=":metadata.labels.app" -n $PH_NAMESPACE) - if [[ "$podName" == "moja-ph-kong" ]]; then - initContainerStatus=$(kubectl get pod $pod --no-headers -o custom-columns=":status.initContainerStatuses[0].ready" -n $PH_NAMESPACE) - while [[ "$initContainerStatus" != "true" ]]; do - printf "\rReady State: $initContainerStatus Waiting for status to become true ..." - initContainerStatus=$(kubectl get pod $pod --no-headers -o custom-columns=":status.initContainerStatuses[0].ready" -n $PH_NAMESPACE) - sleep 5 - done - echo "Status is now true" - while kubectl get pod "$podName" -o jsonpath="{:status.initContainersStatuses[1].name}" | grep -q "$dBcontainerName" ; do - printf "\r Waiting for Init DB container to be created ..." - sleep 5 - done - - echo && echo $pod - statusCode=1 - while [ $statusCode -eq 1 ]; do - printf "\rRunning Migrations ..." - kubectl exec $pod -c $dBcontainerName -n $PH_NAMESPACE -- kong migrations bootstrap >> /dev/null 2>&1 - statusCode=$? - if [ $statusCode -eq 0 ]; then - echo "\nKong Migrations Successful" - fi - done - else - continue - fi - done -} - -function postPaymenthubDeploymentScript(){ - #Run migrations in Kong Pod - runKongMigrations - # Run failed MySQL statements. - runFailedSQLStatements -} - -function deployMojaloop() { - echo "Deploying Mojaloop vNext application manifests" - createNamespace "$MOJALOOP_NAMESPACE" - echo - cloneRepo "$MOJALOOPBRANCH" "$MOJALOOP_REPO_LINK" "$APPS_DIR" "$MOJALOOPREPO_DIR" - echo - # renameOffToYaml "${MOJALOOP_LAYER_DIRS[0]}" - echo - configureMojaloop - - for index in "${!MOJALOOP_LAYER_DIRS[@]}"; do - folder="${MOJALOOP_LAYER_DIRS[index]}" - echo "Deploying files in $folder" - applyKubeManifests "$folder" "$MOJALOOP_NAMESPACE" - if [ "$index" -eq 0 ]; then - echo -e "${BLUE}Waiting for Mojaloop cross cutting concerns to come up${RESET}" - sleep 10 - echo -e "Proceeding ..." - fi - done - - echo -e "\n${GREEN}============================" - echo -e "Mojaloop Deployed" - echo -e "============================${RESET}\n" -} - -function deployPaymentHubEE() { - echo "Deploying PaymentHub EE" - createNamespace "$PH_NAMESPACE" - cloneRepo "$PHBRANCH" "$PH_REPO_LINK" "$APPS_DIR" "$PHREPO_DIR" - configurePH "$APPS_DIR$PHREPO_DIR/helm" - - for((i=1; i<=2; i++)) - do - if [ "$debug" = true ]; then - deployHelmChartFromDir "$APPS_DIR$PHREPO_DIR/helm/g2p-sandbox-fynarfin-SIT" "$PH_NAMESPACE" "$PH_RELEASE_NAME" "$PH_VALUES_FILE" - else - deployHelmChartFromDir "$APPS_DIR$PHREPO_DIR/helm/g2p-sandbox-fynarfin-SIT" "$PH_NAMESPACE" "$PH_RELEASE_NAME" "$PH_VALUES_FILE" >> /dev/null 2>&1 - fi - done - - echo -e "\n${YELLOW}Fixing Paymenthub post deployment issues(might take a while)...${RESET}" - postPaymenthubDeploymentScript >> /dev/null 2>&1 - - echo -e "\n${GREEN}============================" - echo -e "Paymenthub Deployed" - echo -e "============================${RESET}\n" -} - -function deployPH(){ - echo "Deploying PaymentHub EE" - createNamespace "$PH_NAMESPACE" - cloneRepo "$PHBRANCH" "$PH_REPO_LINK" "$APPS_DIR" "$PHREPO_DIR" - configurePH "$APPS_DIR$PHREPO_DIR/helm" - # deployPhHelmChartFromRepo "$PH_NAMESPACE" - preparePaymentHubChart - deployPhHelmChartFromDir "$PH_NAMESPACE" "$g2pSandboxFinalChartPath" "$PH_VALUES_FILE" - - echo -e "\n${GREEN}============================" - echo -e "Paymenthub Deployed" - echo -e "============================${RESET}\n" -} - -function deployFineract() { - echo -e "${BLUE}Deploying Fineract${RESET}" - - cloneRepo "$FIN_BRANCH" "$FIN_REPO_LINK" "$APPS_DIR" "$FIN_REPO_DIR" - configureFineract - - num_instances=$1 - - if [[ -z "$num_instances" ]];then - num_instances=2 - fi - - echo -e "Deploying $num_instances instances of fineract" - - # Check if the input is a valid integer - for ((i=1; i<=num_instances; i++)) - do - sed -i "s/\([0-9]-\)\?fynams.sandbox.fynarfin.io/$i-fynams.sandbox.fynarfin.io/" "$FIN_VALUES_FILE" - sed -i "s/\([0-9]-\)\?communityapp.sandbox.fynarfin.io/$i-communityapp.sandbox.fynarfin.io/" "$FIN_VALUES_FILE" - sed -i "s/\([0-9]-\)\?webapp.sandbox.fynarfin.io/$i-webapp.sandbox.fynarfin.io/" "$FIN_VALUES_FILE" - createNamespace "$FIN_NAMESPACE-$i" - if [ "$debug" = true ]; then - deployHelmChartFromDir "$APPS_DIR$FIN_REPO_DIR/helm/fineract" "$FIN_NAMESPACE-$i" "$FIN_RELEASE_NAME-$i" "$FIN_VALUES_FILE" - else - deployHelmChartFromDir "$APPS_DIR$FIN_REPO_DIR/helm/fineract" "$FIN_NAMESPACE-$i" "$FIN_RELEASE_NAME-$i" "$FIN_VALUES_FILE" >> /dev/null 2>&1 - fi - - echo -e "\n${GREEN}============================" - echo -e "fineract-$i Deployed" - echo -e "============================${RESET}\n" - done -} - -function test_ml { - echo "TODO" #TODO Write function to test apps -} - -function test_ph { - echo "TODO" -} - -function test_fin { - local instance_name=$1 -} - -function printEndMessage { - echo -e "===========================" - echo -e "Thank you for using Mojafos" - echo -e "===========================\n\n" - echo -e "CHECK DEPLOYMENTS USING kubectl" - echo -e "kubectl get pods -n mojaloop #For testing mojaloop" - echo -e "kubectl get pods -n paymenthub #For testing paymenthub" - echo -e "kubectl get pods -n fineract-x #For testing fineract. x is a number of a fineract instance\n\n" - echo -e "Copyright © 2023 The Mifos Initiative" -} - -function deployApps { - fin_num_instances="$1" - appsToDeploy="$2" - - if [ -z "$appsToDeploy" ]; then - echo -e "${BLUE}Deploying all apps ...${RESET}" - deployInfrastructure - deployMojaloop - deployPH - deployFineract "$fin_num_instances" - elif [[ "$appsToDeploy" == "all" ]]; then - echo -e "${BLUE}Deploying all apps ...${RESET}" - deployInfrastructure - deployMojaloop - deployPH - deployFineract "$fin_num_instances" - elif [[ "$appsToDeploy" == "moja" ]];then - deployInfrastructure - deployMojaloop - elif [[ "$appsToDeploy" == "fin" ]]; then - deployInfrastructure - deployFineract "$fin_num_instances" - elif [[ "$appsToDeploy" == "ph" ]]; then - deployPH - else - echo -e "${RED}Invalid option ${RESET}" - echo "Defaulting to all... " - deployInfrastructure - deployMojaloop - deployPH - deployFineract "$fin_num_instances" - fi - addKubeConfig >> /dev/null 2>&1 - printEndMessage -} diff --git a/src/mojafos/deployer/fin_values.yaml b/src/mojafos/deployer/fin_values.yaml deleted file mode 100644 index 9cd2d7b..0000000 --- a/src/mojafos/deployer/fin_values.yaml +++ /dev/null @@ -1,115 +0,0 @@ -fineract: - enabled: true - db: fineract-mysql - DFSPIDS: "" - SPRING_PROFILES_ACTIVE: "bb" - image: "openmf/fineract:latest" - spec: - template: - spec: - containers: - env: - FINERACT_DEFAULT_TENANTDB_IDENTIFIER: "default" - FINERACT_DEFAULT_TENANTDB_NAME: "fineract_default" - FINERACT_DEFAULT_TENANTDB_HOSTNAME: "mysql.infra.svc.cluster.local" - FINERACT_DEFAULT_TENANTDB_PORT: "3306" - FINERACT_HIKARI_DRIVER_CLASS_NAME: org.mariadb.jdbc.Driver - FINERACT_HIKARI_JDBC_URL: jdbc:mariadb://mysql.infra.svc.cluster.local:3306/fineract_tenants - FINERACT_SERVER_PORT: 8443 - preStopScript: 'echo -e "******Fineract is stopping********";' - ingress: - enabled: true - hostname: "2-fynams.sandbox.fynarfin.io" - path: "/" - wildcardhostname: "*.sandbox.fynarfin.io" - annotations: - kubernetes.io/ingress.class: "nginx" - nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - resources: - limits: - cpu: "1000m" - memory: "2Gi" - requests: - cpu: "1m" - memory: "100m" - -communityapp: - enabled: true - lookforservice: true - image: "openmf/community-app:latest" - ingress: - enabled: true - hostname: "2-communityapp.sandbox.fynarfin.io" - path: "/" - wildcardhostname: "2-communityapp.sandbox.fynarfin.io" - annotations: - kubernetes.io/ingress.class: "nginx" - resources: - limits: - cpu: "500m" - memory: "1Gi" - requests: - cpu: "200m" - memory: "500m" - -webapp: - enabled: false - image: "fintecheando/web-app:master" - ingress: - enabled: true - hostname: "2-webapp.sandbox.fynarfin.io" - path: "/web" - annotations: - kubernetes.io/ingress.class: "nginx" - resources: - limits: - cpu: "500m" - memory: "1Gi" - requests: - cpu: "200m" - memory: "500m" - -selfservice: - image: "419830066942.dkr.ecr.ap-south-1.amazonaws.com/fineract/phee-ns/web-self-service-app:latest" - ingress: - enabled: false - hostname: "" - path: "/self" - annotations: {} - - -mariadb: - enabled: false - - -mysql: - fullnameOverride: fineract-mysql - enabled: false - image: - tag: "10.5.16-debian-11-r22" - debug: true - auth: - username: "mifos" - password: "password" - rootPassword: "4ET6ywqlGt" - initdbScripts: - setup.sql: |- - # create databases - CREATE DATABASE IF NOT EXISTS `fineract_tenants`; - CREATE DATABASE IF NOT EXISTS `fineract_default`; - # create root user and grant rights - GRANT ALL ON *.* TO 'root'@'%'; - GRANT ALL PRIVILEGES ON `fineract_tenants`.* TO 'mifos'; - GRANT ALL PRIVILEGES ON `fineract_default`.* TO 'mifos'; - primary: - resources: - requests: - memory: "500m" - cpu: "500m" - limits: - memory: "2Gi" - cpu: "1000m" - -wildcardhostname: "*.sandbox.fynarfin.io" - -tls: "" \ No newline at end of file diff --git a/src/mojafos/deployer/helm/infra/Chart.lock b/src/mojafos/deployer/helm/infra/Chart.lock deleted file mode 100644 index 3dd8d3d..0000000 --- a/src/mojafos/deployer/helm/infra/Chart.lock +++ /dev/null @@ -1,24 +0,0 @@ -dependencies: -- name: kafka - repository: https://charts.bitnami.com/bitnami - version: 19.0.2 -- name: console - repository: https://charts.redpanda.com - version: 0.6.6 -- name: mongodb - repository: https://charts.bitnami.com/bitnami - version: 13.3.1 -- name: mongo-express - repository: https://cowboysysop.github.io/charts/ - version: 3.1.1 -- name: redis - repository: https://charts.bitnami.com/bitnami - version: 17.11.6 -- name: elasticsearch - repository: https://charts.bitnami.com/bitnami - version: 19.9.2 -- name: mysql - repository: https://charts.bitnami.com/bitnami - version: 9.4.5 -digest: sha256:7ba3ea9a03eaa2abafee8c647e7976a22d7b82ad48fdd2a9dfbaa3bb65bbf910 -generated: "2023-09-06T11:55:49.830694633Z" diff --git a/src/mojafos/deployer/ph_values.yaml b/src/mojafos/deployer/ph_values.yaml deleted file mode 100644 index a2bd83e..0000000 --- a/src/mojafos/deployer/ph_values.yaml +++ /dev/null @@ -1,24 +0,0 @@ -ph-ee-engine: - elasticsearch: - volumeClaimTemplate: - storageClassName: "local-path" - - notifications: - limits: - cpu: "1000m" - memory: "2000M" - requests: - cpu: "1m" - memory: "1M" - - operations_web: - ingress: - enabled: true - - operations_app: - limits: - cpu: "1000m" - memory: "2000M" - requests: - cpu: "1m" - memory: "1M" \ No newline at end of file diff --git a/src/mojafos/deployer/setup.sql b/src/mojafos/deployer/setup.sql deleted file mode 100644 index e3dd5d8..0000000 --- a/src/mojafos/deployer/setup.sql +++ /dev/null @@ -1,6 +0,0 @@ -DROP DATABASE `tenants`; -CREATE DATABASE `tenants`; -GRANT ALL PRIVILEGES ON `tenants`.* TO 'mifos'; -GRANT ALL PRIVILEGES ON `rhino`.* TO 'mifos'; -GRANT ALL PRIVILEGES ON `gorilla`.* TO 'mifos'; -GRANT ALL ON *.* TO 'root'@'%'; diff --git a/src/utils/copy-report-from-pod.sh b/src/utils/copy-report-from-pod.sh new file mode 100755 index 0000000..107721f --- /dev/null +++ b/src/utils/copy-report-from-pod.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +#SRC=$HOME/debug/integration/ph-ee-integration-test +DEST="/ph-ee-connector-integration-test" +POD="ph-ee-integration-test-gazelle" + +# Create a unique directory in /tmp +unique_dir=$(mktemp -d /tmp/mydir.XXXXXX) +echo "savings reports to $unique_dir" + +# copy reports from pod +kubectl cp $POD:$DEST/cucumber-report "$unique_dir/cucumber-report" +kubectl cp $POD:$DEST/cucumber.json "$unique_dir/cucumber.json" +kubectl cp $POD:$DEST/build/reports "$unique_dir" + +# k exec -it tomtest -- ./gradlew test -Dcucumber.filter.tags="@gov and not @ext" \ No newline at end of file diff --git a/src/utils/curl-from-inside-cluster.sh b/src/utils/curl-from-inside-cluster.sh new file mode 100755 index 0000000..f9fa04c --- /dev/null +++ b/src/utils/curl-from-inside-cluster.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +POD_NAME=$1 +NAMESPACE=$2 +URL=$3 + +if [[ -z "$POD_NAME" || -z "$NAMESPACE" || -z "$URL" ]]; then + echo "Usage: $0 " + exit 1 +fi + +# Pull and run the curl container from Docker Hub inside the pod +#kubectl run curl-pod --rm -i --tty --image=curlimages/curl:latest --restart=Never -n "$NAMESPACE" -- curl -s "$URL" +kubectl run curl-pod --rm -i --tty --image=curlimages/curl:latest --restart=Never -n "$NAMESPACE" -- sleep 3600 diff --git a/src/utils/deployBpmn-gazelle.sh b/src/utils/deployBpmn-gazelle.sh new file mode 100755 index 0000000..0f355af --- /dev/null +++ b/src/utils/deployBpmn-gazelle.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# Define variables for the charts +SCRIPT_DIR=$( cd $(dirname "$0") ; pwd ) +BPMN_DIR="$( cd $(dirname "$SCRIPT_DIR")/../repos/phlabs ; pwd )" + +HOST="https://zeebeops.mifos.gazelle.test/zeebe/upload" +DEBUG=false +TENANT="bluebank" # Default tenant + +deploy() { + local file="$1" + local cmd="curl --insecure --location --request POST $HOST \ + --header 'Platform-TenantId:$TENANT' \ + --form 'file=@\"$file\"' \ + -s -o /dev/null -w '%{http_code}'" + + if [ "$DEBUG" = true ]; then + echo "Executing: $cmd" + http_code=$(eval $cmd) + exit_code=$? + echo "HTTP Code: $http_code" + echo "Exit code: $exit_code" + else + http_code=$(eval $cmd) + exit_code=$? + + if [ "$exit_code" -eq 0 ] && [ "$http_code" -eq 200 ]; then + echo "File: $file - Upload successful" + else + echo "File: $file - Upload failed (HTTP Code: $http_code)" + fi + fi +} + +usage() { + cat < Specify a single file to upload. + -t Specify the tenant name (default: bluebank). + -d Enable debug mode for detailed output. + -h Show this help message. + +Description: + This script uploads BPMN files to a Zeebe instance. If no file is specified, + it will upload all BPMN files from predefined locations. + +Examples: + $(basename "$0") -f myprocess.bpmn + $(basename "$0") -t mytenant +EOF + exit 0 +} + +# Parse command line arguments +while getopts ":f:t:dh" opt; do + case $opt in + f) + SINGLE_FILE="$OPTARG" + ;; + t) + TENANT="$OPTARG" + ;; + d) + DEBUG=true + ;; + h) + usage + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +# If a single file is specified, upload only that file +if [ -n "$SINGLE_FILE" ]; then + if [ -f "$SINGLE_FILE" ]; then + deploy "$SINGLE_FILE" + else + echo "Error: File '$SINGLE_FILE' not found." + exit 1 + fi +else + # Deploy files from predefined locations + for location in "$BPMN_DIR/orchestration/feel/"*.bpmn "$BPMN_DIR/orchestration/feel/example/"*.bpmn; do + [ -e "$location" ] || continue # Skip if no files match the glob + deploy "$location" + #sleep 20 + done +fi diff --git a/src/utils/g2pCleanup.sh b/src/utils/g2pCleanup.sh new file mode 100755 index 0000000..ee1cdc8 --- /dev/null +++ b/src/utils/g2pCleanup.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +kubectl get clusterroles -n paymenthub | grep '^ph-ee-' | awk '{print $1}' | xargs kubectl delete clusterrole +kubectl delete -n paymenthub clusterrole message-gateway-c-role + +kubectl delete -n paymenthub clusterrolebinding message-gateway-c-role-binding +kubectl get clusterrolebindings -n paymenthub | grep '^ph-ee-' | awk '{print $1}' | xargs kubectl delete clusterrolebinding + +k delete pvc --all -n paymenthub \ No newline at end of file diff --git a/src/utils/get-kube-logs.sh b/src/utils/get-kube-logs.sh new file mode 100755 index 0000000..2a6d300 --- /dev/null +++ b/src/utils/get-kube-logs.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# get all pod logs from the deployed applications +# copy them from the pods and put into a +# temporary directory in /tmp +# this enables easy access to all pod logs + +# Set variables +NAMESPACE="paymenthub" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +LOG_DIR="/tmp/kube_logs_${TIMESTAMP}" +INTEGRATION_REPORT_DIR="integration_report" +TEST_POD_PREFIX="g2p-sandbox-test-gov" + +# Function to check if kubectl is available +check_kubectl() { + if ! command -v kubectl &> /dev/null; then + echo "kubectl is not installed. Please install kubectl first." + exit 1 + fi +} + +# Function to check if namespace exists +check_namespace() { + if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then + echo "Namespace $NAMESPACE does not exist." + exit 1 + fi +} + +# Function to copy integration report +copy_integration_report() { + echo "Copying integration report..." + TEST_POD=$(kubectl get pods -n "$NAMESPACE" | grep "$TEST_POD_PREFIX" | cut -d " " -f1) + + if [ -z "$TEST_POD" ]; then + echo "No test pod found with prefix $TEST_POD_PREFIX" + return 1 + fi + + mkdir -p "$INTEGRATION_REPORT_DIR" + kubectl cp "$NAMESPACE/$TEST_POD:/ph-ee-connector-integration-test/build" "$INTEGRATION_REPORT_DIR/test-report" + + if [ $? -eq 0 ]; then + echo "Successfully copied integration report to $INTEGRATION_REPORT_DIR/test-report" + else + echo "Failed to copy integration report" + fi +} + +# Function to collect logs from all pods +collect_logs() { + echo "Collecting logs from all pods in namespace $NAMESPACE..." + + # Create unique directory for this run + mkdir -p "$LOG_DIR" + echo "Logs will be saved in: $LOG_DIR" + + # Create a summary file + SUMMARY_FILE="$LOG_DIR/_summary.txt" + echo "Log Collection Summary - $(date)" > "$SUMMARY_FILE" + echo "Namespace: $NAMESPACE" >> "$SUMMARY_FILE" + echo "----------------------------------------" >> "$SUMMARY_FILE" + + # Get all pods and collect logs + kubectl get pods -n "$NAMESPACE" --no-headers | while read -r pod_line; do + pod=$(echo "$pod_line" | cut -d " " -f1) + pod_status=$(echo "$pod_line" | awk '{print $3}') + containers=$(kubectl get pod "$pod" -n "$NAMESPACE" -o jsonpath='{.spec.containers[*].name}') + + echo "Collecting logs from pod: $pod" + echo "Pod: $pod - Status: $pod_status" >> "$SUMMARY_FILE" + + for container in $containers; do + log_file="$LOG_DIR/${pod}_${container}.log" + echo " Container: $container - Log file: $log_file" >> "$SUMMARY_FILE" + + echo "--------------------------------------------------------------------" > "$log_file" + echo "Pod: $pod - Container: $container" >> "$log_file" + echo "Status: $pod_status" >> "$log_file" + echo "Timestamp: $(date)" >> "$log_file" + echo "--------------------------------------------------------------------" >> "$log_file" + echo "" >> "$log_file" + + kubectl logs -n "$NAMESPACE" "$pod" -c "$container" >> "$log_file" 2>&1 + done + echo "" >> "$SUMMARY_FILE" + done + + # Create a tar archive of all logs + tar_file="/tmp/kube_logs_${TIMESTAMP}.tar.gz" + tar -czf "$tar_file" -C "/tmp" "kube_logs_${TIMESTAMP}" + + echo "----------------------------------------" >> "$SUMMARY_FILE" + echo "Log collection completed at $(date)" >> "$SUMMARY_FILE" + echo "Logs have been collected in: $LOG_DIR" + echo "Logs have been archived to: $tar_file" +} + +# Main execution +main() { + check_kubectl + check_namespace + + copy_integration_report + collect_logs + + echo "Script execution completed!" + echo "Log directory: $LOG_DIR" + echo "Log archive: /tmp/kube_logs_${TIMESTAMP}.tar.gz" +} + +# Run the script +main \ No newline at end of file diff --git a/src/utils/import-local-image-to-k3s.sh b/src/utils/import-local-image-to-k3s.sh new file mode 100755 index 0000000..adafb2c --- /dev/null +++ b/src/utils/import-local-image-to-k3s.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# publish local image to k3s kubernetes +# Author: Tom Daly +# Date: Oct 2024 +# Mainly useful for dev/test of Mifos Gazelle components + +# Default values +IMAGE_NAME="" +IMAGE_TAG="" +VERBOSE=false + +function showUsage() { + cat << EOF +Usage: $(basename $0) [OPTIONS] +Publish a local Docker image to k3s Kubernetes cluster. + +Required Options: + -n, --name Docker image name + -t, --tag Docker image tag + +Optional Options: + -v, --verbose Enable verbose output + -h, --help Show this help message + +Example: + $(basename $0) -n myapp -t latest + $(basename $0) --name myapp --tag v1.0.0 + +Note: This script must be run as root. +EOF + exit 1 +} + +function log() { + if [[ "$VERBOSE" == true ]]; then + echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" + fi +} + +function error() { + echo "ERROR: $1" >&2 + exit 1 +} + +function set_user() { + # set the k8s_user + k8s_user=$(who am i | cut -d " " -f1) + log "k8s_user = $k8s_user" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -n|--name) + IMAGE_NAME="$2" + shift 2 + ;; + -t|--tag) + IMAGE_TAG="$2" + shift 2 + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + -h|--help) + showUsage + ;; + *) + error "Unknown option: $1" + ;; + esac +done + +# Validate required parameters +[[ -z "$IMAGE_NAME" ]] && error "Image name is required. Use -n or --name" +[[ -z "$IMAGE_TAG" ]] && error "Image tag is required. Use -t or --tag" + +# Set directory variables +SCRIPTS_DIR="$(cd "$(dirname "$0")" || exit; pwd)" +BASE_DIR="$(cd "$(dirname "$0")/../../.." || exit; pwd)" + +# Check if running as root +[[ "$EUID" -ne 0 ]] && error "Please run as root" + +# Print header +printf "\n\n******************************************\n" +printf " -- publish local image to k3s -- \n" +printf "*************** << START >> *******************\n\n" + +# Set user +set_user + +# Define tarfile path +tarfile="/tmp/${IMAGE_NAME}.tar" + +# Clean up any existing tarfile +if [[ -f "$tarfile" ]]; then + log "Removing existing tarfile: $tarfile" + rm -f "$tarfile" +fi + +# Export Docker image +printf "==> export docker image using docker save --output %s %s \n" "$tarfile" "$IMAGE_NAME" +if ! su - "$k8s_user" -c "docker save --output $tarfile $IMAGE_NAME:$IMAGE_TAG"; then + error "Failed to save Docker image" +fi + +# Import image to k3s +printf "==> import image using: k3s ctr images import %s \n" "$tarfile" +if ! k3s ctr images import "$tarfile"; then + error "Failed to import image to k3s" +fi + +# Cleanup +printf "==> cleaning up, removing tarfile etc\n" +rm -f "$tarfile" + +# Success message +printf "\n ** images appear to have imported ok\n" +printf " You can check they exist by running.. \n" +printf " sudo k3s ctr images list | grep %s \n" "$IMAGE_NAME" \ No newline at end of file diff --git a/src/utils/install-k9s.sh b/src/utils/install-k9s.sh new file mode 100755 index 0000000..403f6de --- /dev/null +++ b/src/utils/install-k9s.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Check if the script is running on Ubuntu +if [[ "$(lsb_release -d | awk '{print $2}')" != "Ubuntu" ]]; then + echo "This script is only for Ubuntu systems." + exit 1 +fi + +# Create a temporary directory for downloads +tmp_dir="/tmp/k9s_download" +mkdir -p "$tmp_dir" + +# Download k9s tar.gz +url="https://github.com/derailed/k9s/releases/download/v0.32.5/k9s_Linux_amd64.tar.gz" + + +# Download URL with version and filename +download_url="https://github.com/derailed/k9s/releases/download/v0.32.5/k9s_Linux_amd64.tar.gz" + +# Attempt to get the latest version (optional) +# Uncomment these lines if you want to dynamically fetch the version +# latest_version=$(curl -sL https://github.com/derailed/k9s/releases/latest | grep -Eo ']*>([^<]*)' | head -n 1 | cut -d 'v' -f2) +# download_url="https://github.com/derailed/k9s/releases/download/v${latest_version}/k9s_Linux_amd64.tar.gz" + +# Download the k9s executable (fallback to static URL) +curl -L "$download_url" -o "$tmp_dir/k9s.tar.gz" + +# Extract the k9s executable (assuming it's a tar archive) +tar -xzf "$tmp_dir/k9s.tar.gz" -C "$tmp_dir" + +# Move k9s to the user's bin directory (assuming it's named k9s after extraction) +mkdir -p "$HOME/local/bin" +mv "$tmp_dir/k9s" "$HOME/local/bin/k9s" + +# Echo the path to add to bashrc +echo "To use k9s, add the following line to your .bashrc:" +echo "export PATH=\$HOME/local/bin:\$PATH" + +# Clean up the temporary directory +rm -rf "$tmp_dir" diff --git a/src/utils/integration-test-utils/exec-integration-tests-in-pod.sh b/src/utils/integration-test-utils/exec-integration-tests-in-pod.sh new file mode 100755 index 0000000..c599799 --- /dev/null +++ b/src/utils/integration-test-utils/exec-integration-tests-in-pod.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +SRC=$HOME/ph-ee-integration-test +DEST="/ph-ee-connector-integration-test" +POD=testpod + +kubectl cp $SRC/build.gradle $POD:$DEST +kubectl cp $SRC/src/test/java/org/mifos/integrationtest/cucumber/stepdef/GSMATransferDef.java $POD:$DEST/src/test/java/org/mifos/integrationtest/cucumber/stepdef/GSMATransferDef.java + +kubectl cp $SRC/src/test/java/org/mifos/integrationtest/cucumber/stepdef/GSMATransferStepDef.java $POD:$DEST/src/test/java/org/mifos/integrationtest/cucumber/stepdef/GSMATransferStepDef.java +kubectl cp $SRC/src/main/resources/application.yaml $POD:$DEST/src/main/resources/application.yaml + + +k exec -it testpod -- ./gradlew test -Dcucumber.filter.tags="@gov and not @ext" diff --git a/src/utils/integration-test-utils/run-integration-pod.yaml b/src/utils/integration-test-utils/run-integration-pod.yaml new file mode 100644 index 0000000..76c78d8 --- /dev/null +++ b/src/utils/integration-test-utils/run-integration-pod.yaml @@ -0,0 +1,125 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + helm.sh/hook: test-success + creationTimestamp: "2024-09-18T13:38:20Z" + labels: + app: testpod + name: testpod + namespace: paymenthub +spec: + containers: + - args: + - sleep 7200 + # - ./gradlew test -Dcucumber.filter.tags="@gov and not @ext" ; echo 'Test complete' + # ; sleep 300 ; echo 'pod terminate' + command: + - /bin/bash + - -c + env: + - name: OPERATIONS_APP_CONTACTPOINT + value: http://ph-ee-operations-app:80 + - name: BULK_PROCESSOR_CONTACTPOINT + value: https://ph-ee-connector-bulk:8443 + - name: CHANNEL_CONNECTOR_CONTACTPOINT + value: https://ph-ee-connector-channel:8443 + - name: LOGGING_LEVEL_ROOT + value: INFO + - name: MAX_RETRY_COUNT + value: "5" + - name: RETRY_INTERVAL + value: "15000" + - name: DEFAULTS_TENANT + value: gorilla + - name: DEFAULTS_AUTHORIZATION + value: Basic bWlmb3M6cGFzc3dvcmQ= + - name: CHANNEL_BASE-URL + value: https://ph-ee-connector-channel:8443 + - name: CHANNEL_CONTACTPOINT + value: https://ph-ee-connector-channel:8443 + - name: SAVINGS_CONTACTPOINT + value: https://fineract-server:8443 + - name: LOAN_CONTACTPOINT + value: https://fineract-server:8443 + - name: MOCK_SERVER_PORT + value: "53013" + - name: IDENTITY_ACCOUNT_MAPPER_CONTACTPOINT + value: http://ph-ee-identity-account-mapper:80 + - name: MIFOS_CONNECTOR_CONTACTPOINT + value: http://ph-ee-connector-ams-mifos:80 + - name: AMSMIFOS_MOCK_BASE_URL + value: http://ph-ee-connector-ams-mifos:70 + - name: MOCK_PAYMENT_SCHEMA_CONTACTPOINT + value: http://ph-ee-connector-mock-payment-schema:8080 + - name: MY_POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: CALLBACK_URL + value: http://$(MY_POD_IP):53013 + - name: PAYBILL_MPESA_CONNECTOR_CONTACTPOINT + - name: VOUCHER_MANAGEMENT_CONTACTPOINT + value: http://ph-ee-vouchers:80 + - name: BILLPAY_CONTACTPOINT + value: http://ph-ee-connector-bill-pay:8080 + - name: awaitly_maxWaitTime + value: "30" + - name: GLOBAL_WAIT_TIME_MS + value: "5000" + image: docker.io/openmf/ph-ee-integration-test:v1.6.2 + imagePullPolicy: Always + name: g2p-sandbox-test-gov + resources: + limits: + cpu: 500m + memory: 1536Mi + requests: + cpu: 100m + memory: 1Gi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /var/run/secrets/kubernetes.io/serviceaccount + name: kube-api-access-8twcj + readOnly: true + dnsPolicy: ClusterFirst + enableServiceLinks: true + preemptionPolicy: PreemptLowerPriority + priority: 0 + restartPolicy: Never + schedulerName: default-scheduler + securityContext: {} + serviceAccount: default + serviceAccountName: default + terminationGracePeriodSeconds: 30 + tolerations: + - effect: NoExecute + key: node.kubernetes.io/not-ready + operator: Exists + tolerationSeconds: 300 + - effect: NoExecute + key: node.kubernetes.io/unreachable + operator: Exists + tolerationSeconds: 300 + volumes: + - name: kube-api-access-8twcj + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + expirationSeconds: 3607 + path: token + - configMap: + items: + - key: ca.crt + path: ca.crt + name: kube-root-ca.crt + - downwardAPI: + items: + - fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + path: namespace + diff --git a/src/utils/mysql-client-mifos.sh b/src/utils/mysql-client-mifos.sh new file mode 100755 index 0000000..43ddfe4 --- /dev/null +++ b/src/utils/mysql-client-mifos.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# small utility to +# run mysql-client in k8s and connect to mysql inside cluster +# + +# MySQL connection credentials +MYSQL_USER="root" +MYSQL_PASSWORD="mysqlpw" +MYSQL_HOST="mysql.infra.svc.cluster.local" +MYSQL_DATABASE="mysql" +MYSQL_IMAGE="mysql:5.7" + +# Help function +show_help() { + echo "Usage: $0 [options]" + echo "Connect to MySQL instance in Kubernetes cluster" + echo "" + echo "Options:" + echo " -u, --user MySQL username (default: $MYSQL_USER)" + echo " -p, --password MySQL password" + echo " -h, --host MySQL host (default: $MYSQL_HOST)" + echo " -d, --database MySQL database (default: $MYSQL_DATABASE)" + echo " --help Show this help message" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -u|--user) + MYSQL_USER="$2" + shift 2 + ;; + -p|--password) + MYSQL_PASSWORD="$2" + shift 2 + ;; + -h|--host) + MYSQL_HOST="$2" + shift 2 + ;; + -d|--database) + MYSQL_DATABASE="$2" + shift 2 + ;; + --help) + show_help + exit 0 + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Construct the command +KUBECTL_CMD="kubectl run mysql-client --rm -it --image=${MYSQL_IMAGE} --restart=Never -- mysql -h ${MYSQL_HOST} -u ${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE}" + +# Echo the command (with password masked) +echo "Executing command:" +echo "${KUBECTL_CMD//-p${MYSQL_PASSWORD}/-p********}" +echo "---" + +# Run the kubectl command +eval "${KUBECTL_CMD}" \ No newline at end of file diff --git a/src/utils/new-tls-secret.sh b/src/utils/new-tls-secret.sh new file mode 100755 index 0000000..e93cf6d --- /dev/null +++ b/src/utils/new-tls-secret.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# utility script to show how to create self-signed +# TLS secrets for kubernetes ingress +# + +set -e + +# Function to print usage information +usage() { + echo "Usage: $0 [-d domain_name] [-s secret_name] [-n namespace]" + echo " -d domain_name Specify the domain name (required)" + echo " -s secret_name Specify the secret name (default: tls-secret)" + echo " -n namespace Specify the namespace (default: default)" + exit 1 +} + +# Parse command-line options +while getopts ":d:s:n:" opt; do + case "$opt" in + d) domain_name="$OPTARG" ;; + s) secret_name="$OPTARG" ;; + n) namespace="$OPTARG" ;; + \?) usage ;; + esac +done + +# Check if domain name is provided +if [[ -z "$domain_name" ]]; then + echo "Error: Domain name is required. Use -d option." + usage +else + echo "Using domain name : $domain_name" +fi + + +# Default values +secret_name=${secret_name:-"tls-secret"} +namespace=${namespace:-"default"} +key_dir="$HOME/.ssh" + +# Generate private key +openssl genrsa -out "$key_dir/$domain_name.key" 2048 +domain_name=${domain_name:-"your_default_domain"} + +# Generate self-signed certificate + +openssl req -x509 -new -nodes -key "$key_dir/$domain_name.key" -sha256 -days 365 -out "$key_dir/$domain_name.crt" -subj "/CN=$domain_name" -extensions v3_req -config <( +cat <&2 + exit 1 +fi + +# Check if IP address is provided +if [ $# -lt 1 ]; then + echo "Usage: $0 [-o true/false]" + echo " -o: Override option. If true, overrides existing entry for the IP. Default is false." + exit 1 +fi + +welcome + +# Initialize variables +ip_address=$1 +override=false + +# Parse arguments +shift +while [[ $# -gt 0 ]]; do + case $1 in + -o) + if [[ $2 == "true" ]]; then + override=true + fi + shift 2 + ;; + *) + shift + ;; + esac +done + +# Hardcoded list of hostnames +hostnames=( + "vnextadmin.local" + "elasticsearch.local" + "kibana.local" + "mongoexpress.local" + "kafkaconsole.local" + "fspiop.local" + "bluebank.local" + "greenbank.local" + "mifos.local" + "ops.local" + "ops-bk.local" + "bulk-connector.local" + "messagegateway.local" + "minio.local" + "ams-mifos.local" + "bill-pay.local" + "channel.local" + "channel-gsma.local" + "crm.local" + "mockpayment.local" + "mojaloop.local" + "identity-mapper.local" + "analytics.local" + "vouchers.local" + "zeebeops.local" + "notifications.local" +) + +# Function to add or update hosts +add_or_update_hosts() { + local ip=$1 + local hosts="${hostnames[*]}" + local existing_line=$(grep -E "^$ip[[:space:]]" /etc/hosts) + + if [ -n "$existing_line" ]; then + if $override; then + sed -i "/^$ip[[:space:]]/c\\$ip $hosts" /etc/hosts + echo "Updated existing entry for $ip with hardcoded hostnames." + else + echo "$ip $hosts" >> /etc/hosts + echo "Added new entry for $ip as the override option was set to false." + fi + else + echo "$ip $hosts" >> /etc/hosts + echo "Added new entry for $ip." + fi +} + +# Call function with parsed arguments +add_or_update_hosts "$ip_address" + +echo -e "\e[32mFinished updating /etc/hosts\e[0m" + +# Uploading BPMN Diagrams + +HOST="http://zeebeops.local/zeebe/upload/" +deploy(){ + cmd="curl --insecure --location --connect-timeout 60 --max-time 120 --request POST $HOST \ + --header 'Platform-TenantId: gorilla' \ + --form 'file=@\"$PWD/$1\"'" + echo $cmd + eval $cmd + #If curl response is not 200 it should fail the eval cmd +} + +LOC1="$BASE_DIR/repos/ph_env_labs/orchestration/feel/*.bpmn" +#LOC1=../src/deployer/apps/ph_env_labs/orchestration/feel/*.bpmn +for f in $LOC1; do + deploy $f +done + +LOC2="$BASE_DIR/repos/ph_env_labs/orchestration/feel/example/*.bpmn" +#LOC2=../src/deployer/apps/ph_env_labs/orchestration/feel/example/*.bpmn +for f in $LOC2; do + deploy $f +done + +# write finished message in green color +echo -e "\e[32mFinished uploading BPMN diagrams\e[0m" diff --git a/src/utils/update-mifos-tenants.sh b/src/utils/update-mifos-tenants.sh new file mode 100755 index 0000000..0543e60 --- /dev/null +++ b/src/utils/update-mifos-tenants.sh @@ -0,0 +1,269 @@ +#!/bin/bash +# automate and document how to setup new tenants to the mifos/fineract +# T Daly , Nov 2024 +# Notes: +# #1 this script relies on the fineract-server to be up and running in a running kubernetes cluster +# see: @fineract GitHub repo under doc https://github.com/openMF/fineract/blob/develop/fineract-doc/src/docs/en/chapters/architecture/persistence.adoc +# #2 currently it also relies on the fineract-server to be using the image openMF/fineract-server:develop as this image has a version of the +# org.apache.fineract.infrastructure.core.service.database.DatabasePasswordEncryptor which prints the encrypted password for +# both the plain text password as specified in the .csv as db_password field as well as the master password hash +# + + +# Default settings +MYSQL_USER="root" +MYSQL_PASSWORD="mysqlpw" +MYSQL_HOST="mysql.infra.svc.cluster.local" +MYSQL_DATABASE="fineract_tenants" +MYSQL_IMAGE="mysql:5.7" +FINERACT_DEFAULT_TENANTDB_MASTER_PASSWORD="fineract" +NAMESPACE="mifosx" +CONFIG_FILE="" +SKIP_CONFIRM=0 +SILENT_MODE=false +SQL_FILE="/tmp/tenant_setup.sql" + +# Declare tenant storage +TENANTS=() + +# Show usage +usage() { + cat << EOF +Usage: $0 [options] -f tenant_config_file + +Options: + -u, --mysql-user MySQL username (default: $MYSQL_USER) + -p, --mysql-password MySQL password + -h, --mysql-host MySQL host (default: $MYSQL_HOST) + -d, --mysql-database MySQL database (default: $MYSQL_DATABASE) + -i, --mysql-image MySQL Docker image (default: $MYSQL_IMAGE) + -n, --namespace Kubernetes namespace (default: $NAMESPACE) + -m, --master-password Fineract master password (default: $FINERACT_DEFAULT_TENANTDB_MASTER_PASSWORD) + -f, --config-file Path to tenant configuration file (required) + -s, --silent silent mode + -y, --yes Skip confirmation prompt + --help Show this help message + +Tenant Configuration File Format (CSV): +The file should contain one tenant per line in the following format: + +tenant_id,tenant_identifier,tenant_name,tenant_timezone,db_host,db_port,db_name,db_user,db_password + +Examples: +2,gazelle1,"Tenant for Gazelle",Australia/Adelaide,mysql.host,3306,gazelle1_user,gazelle1_db,gazelle1_pw +3,gazelle2,"Second Tenant",UTC,mysql.host,3306,gazelle2_user,gazelle2_db,gazelle2_pw + +EOF +exit 1 +} + +validate_tenant_config() { + local line="$1" + local id identifier name timezone db_host db_port db_name db_user db_pass + IFS=',' read -r id identifier name timezone db_host db_port db_name db_user db_pass <<< "$line" + + # echo "Validating line: $line" + # echo "Fields: ID=$id, Identifier=$identifier, Name=$name, Timezone=$timezone, Host=$db_host, Port=$db_port, DB=$db_name, User=$db_user, Password=$db_pass" + + # Check required fields + if [ -z "$id" ]; then + echo "Error: Missing tenant ID" + return 1 + elif [ -z "$identifier" ]; then + echo "Error: Missing tenant identifier" + return 1 + elif [ -z "$name" ]; then + echo "Error: Missing tenant name" + return 1 + elif [ -z "$timezone" ]; then + echo "Error: Missing timezone" + return 1 + elif [ -z "$db_host" ]; then + echo "Error: Missing database host" + return 1 + elif [ -z "$db_port" ]; then + echo "Error: Missing database port" + return 1 + elif [ -z "$db_name" ]; then + echo "Error: Missing database name" + return 1 + elif [ -z "$db_user" ]; then + echo "Error: Missing database user" + return 1 + elif [ -z "$db_pass" ]; then + echo "Error: Missing database password" + return 1 + fi + + return 0 +} + + +TENANTS=() # Use a regular array + +check_environment() { + kubectl get nodes > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "Error: kubectl get nodes failed. Kubernetes cluster must be running and accessible " + exit 1 + fi +} + +check_fineract_server_running() { + log "Checking that a single fineract-server is up and running" + local fineract_pod_count + local fineract_pod + + fineract_pod_count=$(kubectl get pods -n "$NAMESPACE" --no-headers | grep ^fineract-server | wc -l) + fineract_pod=$(kubectl get pods -n "$NAMESPACE" --no-headers | grep ^fineract-server | awk '{print $1}' | head -1) + run_state=$(kubectl get pod "$fineract_pod" -n "$NAMESPACE" --no-headers | grep fineract | awk '{print $3}' ) + + if [[ -z "$fineract_pod" ]]; then + echo "Error: No Fineract server pod found in namespace $NAMESPACE" + exit 1 + fi + + if [[ $run_state != "Running" ]]; then + echo "Error: Fineract server pod in namespace $NAMESPACE is not Running" + exit 1 + fi +} + +read_tenant_configs() { + local config_file="$1" + if [[ ! -f "$config_file" ]]; then + echo "Error: Configuration file not found: $config_file" + exit 1 + fi + + while IFS= read -r line || [[ -n "$line" ]]; do + # Skip empty lines and comments + [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue + + log "Processing line: $line" # Debugging output + + if validate_tenant_config "$line"; then + TENANTS+=("$line") # Append the line to the array + else + exit 1 + fi + done < "$config_file" + + log "Total tenants processed: ${#TENANTS[@]}" # Debugging output +} + +get_encrypted_passwords() { + local db_password="$1" + local master_password="$2" + local fineract_pod + + fineract_pod=$(kubectl get pods -n "$NAMESPACE" --no-headers | grep ^fineract-server | awk '{print $1}' | head -1) + local output + output=$(kubectl exec -n "$NAMESPACE" "$fineract_pod" -- java -cp @/app/jib-classpath-file \ + org.apache.fineract.infrastructure.core.service.database.DatabasePasswordEncryptor \ + "$master_password" "$db_password") + + # Extract encrypted passwords directly + local db_password_hash + local master_password_hash + db_password_hash=$(echo "$output" | awk -F': ' '/The encrypted password:/ {print $2}') + master_password_hash=$(echo "$output" | awk -F': ' '/The master password hash is:/ {print $2}') + + # Return hashes in the expected format + echo "$db_password_hash:$master_password_hash" +} + +generate_tenant_sql() { + echo "-- Generated tenant setup SQL" > "$SQL_FILE" + + for tenant in "${TENANTS[@]}"; do + IFS=',' read -r id identifier name timezone db_host db_port db_name db_user db_pass <<< "$tenant" + #echo "Parsed fields: ID=$id, Identifier=$identifier, Name=$name, Timezone=$timezone, Host=$db_host, Port=$db_port, DB=$db_name, User=$db_user, Password=$db_pass" # Debugging + + local encrypted_passwords + encrypted_passwords=$(get_encrypted_passwords "$db_pass" "$FINERACT_DEFAULT_TENANTDB_MASTER_PASSWORD") + local db_password_hash master_password_hash + IFS=':' read -r db_password_hash master_password_hash <<< "$encrypted_passwords" + + if [[ -z "$db_password_hash" || -z "$master_password_hash" ]]; then + echo "Error: Failed to generate encrypted passwords for tenant $identifier (ID: $id)" + exit 1 + fi + cat << EOF >> "$SQL_FILE" + +-- Setup for tenant $identifier (ID: $id) +CREATE DATABASE IF NOT EXISTS $db_name; +DELETE FROM tenants WHERE id=$id; +DELETE FROM tenant_server_connections WHERE id=$id; + +INSERT INTO tenant_server_connections (id, schema_name, schema_server, schema_server_port, schema_username, schema_password, auto_update, master_password_hash) +VALUES ($id, '$db_name', '$db_host', '$db_port', '$db_user', '$db_password_hash', 1, '$master_password_hash'); + +INSERT INTO tenants (id, identifier, name, timezone_id, country_id, joined_date, created_date, lastmodified_date, oltp_id, report_id) +VALUES ($id, '$identifier', '$name', '$timezone', NULL, NOW(), NOW(), NOW(), $id, $id); +EOF + done +} + +# Execute SQL +execute_sql() { + echo "Executing sql to add tenants to fineract_tenants tables" + + if [[ "$SILENT_MODE" == true ]]; then + kubectl run gazelle-mysql-client --rm -i --image="$MYSQL_IMAGE" --restart=Never -- \ + mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" < "$SQL_FILE" >/dev/null 2>&1 + else + kubectl run gazelle-mysql-client --rm -i --image="$MYSQL_IMAGE" --restart=Never -- \ + mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" < "$SQL_FILE" && { + echo "SQL executed successfully." + } || { + echo "SQL execution failed." + exit 1 + } + fi +} + +log() { + if [[ "$SILENT_MODE" == false ]]; then + echo "$1" + fi +} + +confirm_execution() { + if [[ "$SILENT_MODE" == false ]]; then + read -rp "Proceed with SQL execution? (y/n): " confirm + if [[ "$confirm" != "y" ]]; then + log "Aborting." + exit 1 + fi + fi +} + +# Parse options +while [[ $# -gt 0 ]]; do + case "$1" in + -u|--mysql-user) MYSQL_USER="$2"; shift ;; + -p|--mysql-password) MYSQL_PASSWORD="$2"; shift ;; + -h|--mysql-host) MYSQL_HOST="$2"; shift ;; + -d|--mysql-database) MYSQL_DATABASE="$2"; shift ;; + -i|--mysql-image) MYSQL_IMAGE="$2"; shift ;; + -n|--namespace) NAMESPACE="$2"; shift ;; + -m|--master-password) FINERACT_DEFAULT_TENANTDB_MASTER_PASSWORD="$2"; shift ;; + -s|--silent) SILENT_MODE=true ;; + -y|--yes) SKIP_CONFIRM=1 ;; + -f|--config-file) CONFIG_FILE="$2"; shift ;; + --help) usage; exit 0 ;; + *) echo "Unknown option: $1"; usage; exit 1 ;; + esac + shift +done + +[[ -z "$CONFIG_FILE" ]] && { echo "Error: Configuration file is required."; usage; exit 1; } + +###### Main execution ###### +check_environment +check_fineract_server_running +read_tenant_configs "$CONFIG_FILE" +generate_tenant_sql +confirm_execution # exists if not confirmed. +execute_sql $SQL_FILE \ No newline at end of file diff --git a/tests/tests.sh b/tests/tests.sh deleted file mode 100644 index e69de29..0000000