Skip to content

Commit

Permalink
add docker rest api agent
Browse files Browse the repository at this point in the history
docker agent for api-agent #121
* support for node creation, start, stop, restart, deletion
* add crypto materials and integration test

Signed-off-by: Dixing (Dex) Xu <dixingxu@gmail.com>
  • Loading branch information
dexhunter committed Sep 19, 2020
1 parent ae053b6 commit c0b57be
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/agent/docker-rest-agent/README.md
@@ -0,0 +1 @@
## Pre-requisite
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
45 changes: 45 additions & 0 deletions 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)
Binary file not shown.
3 changes: 3 additions & 0 deletions src/agent/docker-rest-agent/requirements.txt
@@ -0,0 +1,3 @@
Flask
flask-restful
requests
79 changes: 79 additions & 0 deletions 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/<id>', 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)

0 comments on commit c0b57be

Please sign in to comment.