diff --git a/src/agent/docker-rest-agent/README.md b/src/agent/docker-rest-agent/README.md new file mode 100644 index 000000000..69c9851c9 --- /dev/null +++ b/src/agent/docker-rest-agent/README.md @@ -0,0 +1 @@ +## Pre-requisite \ No newline at end of file diff --git a/src/agent/docker-rest-agent/intergration-test/block.zip b/src/agent/docker-rest-agent/intergration-test/block.zip new file mode 100644 index 000000000..461b2e8f1 Binary files /dev/null and b/src/agent/docker-rest-agent/intergration-test/block.zip differ diff --git a/src/agent/docker-rest-agent/intergration-test/msp.zip b/src/agent/docker-rest-agent/intergration-test/msp.zip new file mode 100644 index 000000000..5e001613b Binary files /dev/null and b/src/agent/docker-rest-agent/intergration-test/msp.zip differ diff --git a/src/agent/docker-rest-agent/intergration-test/orderer_config.zip b/src/agent/docker-rest-agent/intergration-test/orderer_config.zip new file mode 100644 index 000000000..5f2c42b7b Binary files /dev/null and b/src/agent/docker-rest-agent/intergration-test/orderer_config.zip differ diff --git a/src/agent/docker-rest-agent/intergration-test/peer_config.zip b/src/agent/docker-rest-agent/intergration-test/peer_config.zip new file mode 100644 index 000000000..5fea13e82 Binary files /dev/null and b/src/agent/docker-rest-agent/intergration-test/peer_config.zip differ diff --git a/src/agent/docker-rest-agent/intergration-test/test.py b/src/agent/docker-rest-agent/intergration-test/test.py new file mode 100644 index 000000000..afc24f13f --- /dev/null +++ b/src/agent/docker-rest-agent/intergration-test/test.py @@ -0,0 +1,45 @@ +from requests import put, get, post +import base64 +import docker +import json + +client = docker.from_env() + +with open('msp.zip', 'rb') as node_msp, open('tls.zip', 'rb') as tls, open('block.zip', 'rb') as block, open('peer_config.zip', 'rb') as peer_config, open('orderer_config.zip', 'rb') as orderer_config: + + data = { + 'msp':base64.b64encode(node_msp.read()), + 'tls':base64.b64encode(tls.read()), + 'bootstrap_block':base64.b64encode(block.read()), + 'peer_config_file':base64.b64encode(peer_config.read()), + 'orderer_config_file':base64.b64encode(orderer_config.read()), + 'img': 'yeasy/hyperledger-fabric:2.2.0', + 'cmd': 'bash /tmp/init.sh "peer node start"', + 'name': 'cello-hlf-peer' + } + +# Test creating a node +n = post('http://localhost:5001/api/v1/nodes', data=data) +print(n.text) +txt = json.loads(n.text) +nid = txt['data']['id'] + +# Test starting a node +data = {'action': 'start'} +response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +print(response.text) + +# Test restarting a node +data = {'action': 'restart'} +response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +print(response.text) + +# Test stopping a node +data = {'action': 'stop'} +response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +print(response.text) + +# Test deleting a node +data = {'action': 'delete'} +response = post('http://localhost:5001/api/v1/nodes/'+nid, data=data) +print(response.text) diff --git a/src/agent/docker-rest-agent/intergration-test/tls.zip b/src/agent/docker-rest-agent/intergration-test/tls.zip new file mode 100644 index 000000000..b7f4a2c9f Binary files /dev/null and b/src/agent/docker-rest-agent/intergration-test/tls.zip differ diff --git a/src/agent/docker-rest-agent/requirements.txt b/src/agent/docker-rest-agent/requirements.txt new file mode 100644 index 000000000..94f0dc9a6 --- /dev/null +++ b/src/agent/docker-rest-agent/requirements.txt @@ -0,0 +1,3 @@ +Flask +flask-restful +requests \ No newline at end of file diff --git a/src/agent/docker-rest-agent/server.py b/src/agent/docker-rest-agent/server.py new file mode 100644 index 000000000..136394019 --- /dev/null +++ b/src/agent/docker-rest-agent/server.py @@ -0,0 +1,79 @@ +from flask import Flask, jsonify, request +import docker +import sys +import logging + +app = Flask(__name__) +PASS_CODE = 'OK' +FAIL_CODE = 'Fail' + +client = docker.from_env() +res = {'code': '', 'data': {}, 'msg': ''} + +@app.route('/api/v1/networks', methods=['GET']) +def get_network(): + return jsonify({'networks': client.containers.list()}) + +@app.route('/api/v1/nodes', methods=['POST']) +def create_node(): + + env = { + 'HLF_NODE_MSP': request.form.get('msp'), + 'HLF_NODE_TLS':request.form.get('tls'), + 'HLF_NODE_BOOTSTRAP_BLOCK':request.form.get('bootstrap_block'), + 'HLF_NODE_PEER_CONFIG':request.form.get('peer_config_file'), + 'HLF_NODE_ORDERER_CONFIG':request.form.get('orderer_config_file'), + } + + + try: + # same as `docker run -dit yeasy/hyperledge-fabric:2.2.0 -e VARIABLES`` + container = client.containers.run(request.form.get('img'), request.form.get('cmd'), detach=True, tty=True, stdin_open=True, name=request.form.get('name'), environment=env) + except: + res['code'] = FAIL_CODE + res['data'] = sys.exc_info()[0] + res['msg'] = 'creation failed' + logging.debug(res) + raise + + res['code'] = PASS_CODE + res['data']['status'] = 'created' + res['data']['id'] = container.id + res['data']['public-grpc'] = '127.0.0.1:7050' # TODO: read the info from config file + res['data']['public-raft'] = '127.0.0.1:7052' + return jsonify(res) + +@app.route('/api/v1/nodes/', methods=['GET', 'POST']) +def operate_node(id): + + container = client.containers.get(id) + if request.method == 'POST': + act = request.form.get('action') # only with POST + + try: + if act == 'start': + container.start() + elif act == 'restart': + container.restart() + elif act == 'stop': + container.stop() + elif act == 'delete': + container.remove() + else: + res['msg'] = 'undefined action' + except: + res['code'] = FAIL_CODE + res['data'] = sys.exc_info()[0] + res['msg'] = act + 'failed' + logging.debug(res) + raise + else: + # GET + res['data']['status'] = container.status() + + res['code'] = PASS_CODE + return jsonify(res) + + +if __name__ == '__main__': + app.run(port=5001, debug=True)