diff options
author | Stephen Wong <stephen.kf.wong@gmail.com> | 2018-08-19 07:18:24 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@opnfv.org> | 2018-08-19 07:18:24 +0000 |
commit | e35bd25993a9bce37f17cf4353f0aa97d20e9c13 (patch) | |
tree | 29b31e3558830d6ca427810b6c1e75cdf027e888 | |
parent | 94cd16d7b0dc898e0c54ebe0f8378f27ded67e14 (diff) | |
parent | f38f41124db707b390e8f21c1a91e1022b3633ab (diff) |
Merge "Implement initial clover-controller service"
22 files changed, 771 insertions, 0 deletions
diff --git a/clover/controller/__init__.py b/clover/controller/__init__.py new file mode 100644 index 0000000..d67a6c0 --- /dev/null +++ b/clover/controller/__init__.py @@ -0,0 +1,11 @@ +from flask import Flask, Response + + +app = Flask(__name__) + +@app.route("/") +def index(): + return Response("It works!"), 200 + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clover/controller/build.sh b/clover/controller/build.sh new file mode 100755 index 0000000..b552fec --- /dev/null +++ b/clover/controller/build.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +IMAGE_PATH=${IMAGE_PATH:-"localhost:5000"} +IMAGE_NAME=${IMAGE_NAME:-"clover-controller"} + +docker build -f docker/Dockerfile -t $IMAGE_NAME . +docker tag $IMAGE_NAME $IMAGE_PATH/$IMAGE_NAME +docker push $IMAGE_PATH/$IMAGE_NAME diff --git a/clover/controller/control/__init__.py b/clover/controller/control/__init__.py new file mode 100644 index 0000000..d67a6c0 --- /dev/null +++ b/clover/controller/control/__init__.py @@ -0,0 +1,11 @@ +from flask import Flask, Response + + +app = Flask(__name__) + +@app.route("/") +def index(): + return Response("It works!"), 200 + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clover/controller/control/api/__init__.py b/clover/controller/control/api/__init__.py new file mode 100644 index 0000000..d67a6c0 --- /dev/null +++ b/clover/controller/control/api/__init__.py @@ -0,0 +1,11 @@ +from flask import Flask, Response + + +app = Flask(__name__) + +@app.route("/") +def index(): + return Response("It works!"), 200 + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clover/controller/control/api/collector.py b/clover/controller/control/api/collector.py new file mode 100644 index 0000000..c82c543 --- /dev/null +++ b/clover/controller/control/api/collector.py @@ -0,0 +1,131 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +from flask import Blueprint, request, jsonify, Response +import grpc +import pickle +import collector_pb2 +import collector_pb2_grpc +import redis +import logging + + +collector = Blueprint('collector', __name__) + +grpc_port = '50054' +pod_name = 'clover-collector' +collector_grpc = pod_name + ':' + grpc_port +channel = grpc.insecure_channel(collector_grpc) +stub = collector_pb2_grpc.ControllerStub(channel) +CASSANDRA_HOSTS = pickle.dumps(['cassandra.default']) + +HOST_IP = 'redis' + + +@collector.route("/collector/init") +def init(): + try: + response = stub.InitVisibility(collector_pb2.ConfigCassandra( + cassandra_hosts=CASSANDRA_HOSTS, cassandra_port=9042)) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting via gRPC", status=400) + else: + return Response("Error initializing visibility", status=400) + return response.message + + +@collector.route("/collector/truncate") +def truncate(): + try: + schemas = pickle.dumps(['spans', 'traces', 'metrics']) + response = stub.TruncateVisibility(collector_pb2.Schemas( + schemas=schemas, cassandra_hosts=CASSANDRA_HOSTS, + cassandra_port=9042)) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting via gRPC", status=400) + else: + return Response("Error truncating visibility", status=400) + return response.message + + +@collector.route("/collector/start", methods=['GET', 'POST']) +def start(): + try: + p = request.json + if not p: + sample_interval = '5' + t_host = 'jaeger-deployment.istio-system' + t_port = '16686' + m_host = 'prometheus.istio-system' + m_port = '9090' + else: + try: + sample_interval = p['sample_interval'] + t_host = p['t_host'] + t_port = p['t_port'] + m_host = p['m_host'] + m_port = p['m_port'] + except (KeyError, ValueError) as e: + logging.debug(e) + return Response("Invalid value in json/yaml", status=400) + response = stub.StartCollector(collector_pb2.ConfigCollector( + t_port=t_port, t_host=t_host, + m_port=m_port, m_host=m_host, + c_port='9042', c_hosts=CASSANDRA_HOSTS, + sinterval=sample_interval)) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting via gRPC", status=400) + else: + return Response("Error starting visibility", status=400) + return response.message + + +@collector.route("/collector/stop") +def stop(): + try: + response = stub.StopCollector(collector_pb2.ConfigCollector()) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting via gRPC", status=400) + else: + return Response("Error stopping visibility", status=400) + return response.message + + +@collector.route("/collector/stats", methods=['GET', 'POST']) +def stats(): + try: + p = request.json + if not p: + stat_type = 'toplevel' + else: + stat_type = p['stat_type'] + r = redis.StrictRedis(host=HOST_IP, port=6379, db=0) + content = {} + content['proxy_rt'] = r.get('proxy_rt') + content['trace_count'] = r.get('trace_count') + content['span_urls'] = list(r.smembers('span_urls')) + response = jsonify(content) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting via gRPC", status=400) + else: + return Response("Error getting visibility stats", status=400) + return response + + +@collector.route("/collector/test") +def test(): + return "<h1 style='color:blue'>Collector API Test Response</h1>" diff --git a/clover/controller/control/api/file_upload.py b/clover/controller/control/api/file_upload.py new file mode 100644 index 0000000..a479c30 --- /dev/null +++ b/clover/controller/control/api/file_upload.py @@ -0,0 +1,28 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +from flask import Blueprint, request, Response +import redis +import logging + +file_upload = Blueprint('file_upload', __name__) + +HOST_IP = 'redis' + + +@file_upload.route("/upload", methods=['GET', 'POST']) +def upload_meta(): + try: + content = request.form + r = redis.StrictRedis(host=HOST_IP, port=6379, db=0) + response = content.get('upload.name') + r.set('upload_meta', response) + except Exception as e: + logging.debug(e) + r.set('upload_meta', "failure") + return Response('Unable to write file metadata to redis', status=400) + return response diff --git a/clover/controller/control/api/jmeter.py b/clover/controller/control/api/jmeter.py new file mode 100644 index 0000000..09625f5 --- /dev/null +++ b/clover/controller/control/api/jmeter.py @@ -0,0 +1,101 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +from flask import Blueprint, request, Response +import grpc +import jmeter_pb2 +import jmeter_pb2_grpc +import pickle +import logging + + +jmeter = Blueprint('jmeter', __name__) + +grpc_port = '50054' +pod_name = 'clover-jmeter-master' +jmeter_grpc = pod_name + ':' + grpc_port +channel = grpc.insecure_channel(jmeter_grpc) +stub = jmeter_pb2_grpc.ControllerStub(channel) + + +@jmeter.route("/jmeter/gen", methods=['GET', 'POST']) +def gentest(): + try: + p = request.json + u_list = [] + u_names = [] + u_methods = [] + try: + for u in p['url_list']: + u_list.append(u['url']) + u_names.append(u['name']) + u_methods.append(u['method']) + url_list = pickle.dumps(u_list) + url_names = pickle.dumps(u_names) + url_methods = pickle.dumps(u_methods) + num_threads = p['load_spec']['num_threads'] + ramp_time = p['load_spec']['ramp_time'] + loops = p['load_spec']['loops'] + except (KeyError, ValueError) as e: + logging.debug(e) + return Response('Invalid value in test plan json/yaml', status=400) + response = stub.GenTest(jmeter_pb2.ConfigJmeter( + url_list=url_list, url_names=url_names, url_methods=url_methods, + num_threads=str(num_threads), ramp_time=str(ramp_time), + loops=str(loops))) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting to jmeter via gRPC", status=400) + else: + return Response("Error generating test plan", status=400) + return response.message + + +@jmeter.route("/jmeter/start", methods=['GET', 'POST']) +def start(): + try: + p = request.json + if not p: + slave_list = '' + num_slaves = '0' + else: + slave_list = p['slave_list'] + num_slaves = p['num_slaves'] + response = stub.StartTest(jmeter_pb2.TestParams( + num_slaves=num_slaves, test_plan='test.jmx', + slave_ips=slave_list)) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting to jmeter via gRPC", status=400) + else: + return Response("Error starting jmeter test", status=400) + return response.message + + +@jmeter.route("/jmeter/results/<r_type>", methods=['GET']) +def results(r_type): + try: + if not r_type: + r_file = 'results' + else: + r_file = r_type + response = stub.GetResults(jmeter_pb2.JResults( + r_format='csv', r_file=r_file)) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting to jmeter via gRPC", status=400) + else: + return Response("Error returning results", status=400) + return response.message + + +@jmeter.route("/jmeter/test") +def test(): + return "<h1 style='color:blue'>Jmeter API Test Response</h1>" diff --git a/clover/controller/control/api/nginx.py b/clover/controller/control/api/nginx.py new file mode 100644 index 0000000..ba99b94 --- /dev/null +++ b/clover/controller/control/api/nginx.py @@ -0,0 +1,51 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +from flask import Blueprint, request, Response +import grpc +import nginx_pb2 +import nginx_pb2_grpc +import pickle +import logging + +nginx = Blueprint('nginx', __name__) + + +@nginx.route("/nginx/slb", methods=['GET', 'POST']) +def slblist(): + grpc_port = '50054' + try: + p = request.json + try: + slb_name = p['slb_name'] + nginx_grpc = slb_name + ':' + grpc_port + channel = grpc.insecure_channel(nginx_grpc) + stub = nginx_pb2_grpc.ControllerStub(channel) + + s_list = [] + for s in p['slb_list']: + s_list.append(s['url']) + slb_list = pickle.dumps(s_list) + response = stub.ModifyLB(nginx_pb2.ConfigLB( + server_port=p['server_port'], server_name=p['server_name'], + slb_list=slb_list, + slb_group=p['slb_group'], lb_path=p['lb_path'])) + except (KeyError, ValueError) as e: + logging.debug(e) + return Response('Invalid value in test plan json/yaml', status=400) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting to LB via gRPC", status=400) + else: + return Response("Error modifying LB server list", status=400) + return response.message + + +@nginx.route("/nginx/test") +def test(): + return "<h1 style='color:blue'>Nginx API Test Response</h1>" diff --git a/clover/controller/control/api/snort.py b/clover/controller/control/api/snort.py new file mode 100644 index 0000000..e2177be --- /dev/null +++ b/clover/controller/control/api/snort.py @@ -0,0 +1,99 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +from flask import Blueprint, request, Response +import grpc +import snort_pb2 +import snort_pb2_grpc +import logging +import redis + +snort = Blueprint('snort', __name__) + +grpc_port = '50052' +pod_name = 'snort-ids' +snort_grpc = pod_name + ':' + grpc_port +channel = grpc.insecure_channel(snort_grpc) +stub = snort_pb2_grpc.ControllerStub(channel) + +HOST_IP = 'redis' + + +@snort.route("/snort/addrule", methods=['GET', 'POST']) +def addrule(): + try: + try: + p = request.json + if p['content'] != "": + response = stub.AddRules(snort_pb2.AddRule( + protocol=p['protocol'], dest_port=p['dest_port'], + dest_ip=p['dest_ip'], src_port=p['src_port'], + src_ip=p['src_ip'], msg=p['msg'], sid=p['sid'], + rev=p['rev'], content=p['content'])) + else: + response = stub.AddRules(snort_pb2.AddRule( + protocol=p['protocol'], dest_port=p['dest_port'], + dest_ip=p['dest_ip'], src_port=p['src_port'], + src_ip=p['src_ip'], msg=p['msg'], sid=p['sid'], + rev=p['rev'])) + except (KeyError, ValueError) as e: + logging.debug(e) + return Response('Invalid value in IDS rule json/yaml', status=400) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting to IDS via gRPC", status=400) + else: + return Response("Error adding IDS rule", status=400) + return response.message + + +@snort.route("/snort/start") +def start(): + try: + response = stub.StartSnort(snort_pb2.ControlSnort(pid='0')) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting to jmeter via gRPC", status=400) + else: + return Response("Error starting IDS", status=400) + return response.message + + +@snort.route("/snort/stop") +def stop(): + try: + response = stub.StopSnort(snort_pb2.ControlSnort(pid='0')) + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting to jmeter via gRPC", status=400) + else: + return Response("Error stopping IDS", status=400) + return response.message + + +@snort.route("/snort/get_events", methods=['GET']) +def get_events(): + try: + p = request.json + r = redis.StrictRedis(host=HOST_IP, port=6379, db=0) + event_data = r.hget(p['event_key'], p['field']) + response = event_data + except Exception as e: + logging.debug(e) + if e.__class__.__name__ == "_Rendezvous": + return Response("Error connecting to jmeter via gRPC", status=400) + else: + return Response("Error returning IDS event", status=400) + return response + + +@snort.route("/snort/test") +def test(): + return "<h1 style='color:blue'>Snort API Test Response</h1>" diff --git a/clover/controller/control/control.py b/clover/controller/control/control.py new file mode 100644 index 0000000..54f713a --- /dev/null +++ b/clover/controller/control/control.py @@ -0,0 +1,55 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +from flask import Flask, request, jsonify +from views.dashboard import simple_page +from api.collector import collector +from api.snort import snort +from api.nginx import nginx +from api.jmeter import jmeter +from api.file_upload import file_upload +import logging + +logging.basicConfig(filename='flask.log', level=logging.DEBUG) + +application = Flask(__name__) + +try: + # Register blueprints + application.register_blueprint(simple_page) + application.register_blueprint(collector) + application.register_blueprint(snort) + application.register_blueprint(nginx) + application.register_blueprint(jmeter) + application.register_blueprint(file_upload) +except Exception as e: + logging.debug(e) + + +@application.route("/") +def test(): + return "<h1 style='color:blue'>clover-controller up</h1>" + + +@application.route("/config_server/<server>") +def show_server(server): + return "User %s" % server + + +@application.route("/get_json", methods=['GET', 'POST']) +def get_json(): + try: + content = request.json + cmd = content["cmd"] + resp = jsonify({"cmd": cmd}) + except Exception as e: + resp = e + return resp + + +if __name__ == "__main__": + application.run(host='0.0.0.0') diff --git a/clover/controller/control/templates/home.html b/clover/controller/control/templates/home.html new file mode 100644 index 0000000..6de644e --- /dev/null +++ b/clover/controller/control/templates/home.html @@ -0,0 +1,6 @@ +<!doctype html> +<html> + <body> + <h1>Clover Dashboard</h1> + </body> +</html> diff --git a/clover/controller/control/views/__init__.py b/clover/controller/control/views/__init__.py new file mode 100644 index 0000000..d67a6c0 --- /dev/null +++ b/clover/controller/control/views/__init__.py @@ -0,0 +1,11 @@ +from flask import Flask, Response + + +app = Flask(__name__) + +@app.route("/") +def index(): + return Response("It works!"), 200 + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clover/controller/control/views/dashboard.py b/clover/controller/control/views/dashboard.py new file mode 100644 index 0000000..8b6969c --- /dev/null +++ b/clover/controller/control/views/dashboard.py @@ -0,0 +1,19 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +from flask import Blueprint, render_template, abort +from jinja2 import TemplateNotFound + +simple_page = Blueprint('simple_page', __name__) + + +@simple_page.route('/dashboard', defaults={'page': 'index'}) +def show(page): + try: + return render_template('home.html') + except TemplateNotFound: + abort(404) diff --git a/clover/controller/control/wsgi.py b/clover/controller/control/wsgi.py new file mode 100644 index 0000000..b787e5f --- /dev/null +++ b/clover/controller/control/wsgi.py @@ -0,0 +1,4 @@ +from control import application + +if __name__ == "__main__": + application.run() diff --git a/clover/controller/docker/Dockerfile b/clover/controller/docker/Dockerfile new file mode 100644 index 0000000..52d4673 --- /dev/null +++ b/clover/controller/docker/Dockerfile @@ -0,0 +1,41 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y \ + nginx \ + python-pip \ + git \ + python-dev + +# Install required python packages +RUN python -m pip install gunicorn flask \ + grpcio protobuf jinja2 redis + +COPY /control /control +COPY /process /process + +COPY process/nginx.conf /etc/nginx/nginx.conf + +# Get all grpc files +RUN mkdir /grpc_temp +WORKDIR /grpc_temp +RUN git config --global http.sslVerify false +RUN git clone https://github.com/opnfv/clover.git +RUN cp clover/samples/services/snort_ids/docker/grpc/snort_pb2_grpc.py /control/api +RUN cp clover/samples/services/snort_ids/docker/grpc/snort_pb2.py /control/api +RUN cp clover/samples/services/nginx/docker/grpc/nginx_pb2_grpc.py /control/api +RUN cp clover/samples/services/nginx/docker/grpc/nginx_pb2.py /control/api +RUN cp clover/clover/collector/grpc/collector_pb2_grpc.py /control/api +RUN cp clover/clover/collector/grpc/collector_pb2.py /control/api +RUN cp clover/clover/tools/jmeter/jmeter-master/grpc/jmeter_pb2_grpc.py /control/api +RUN cp clover/clover/tools/jmeter/jmeter-master/grpc/jmeter_pb2.py /control/api +RUN rm -rf /grpc_temp + +WORKDIR /process +CMD ./start_process.sh diff --git a/clover/controller/process/__init__.py b/clover/controller/process/__init__.py new file mode 100644 index 0000000..d67a6c0 --- /dev/null +++ b/clover/controller/process/__init__.py @@ -0,0 +1,11 @@ +from flask import Flask, Response + + +app = Flask(__name__) + +@app.route("/") +def index(): + return Response("It works!"), 200 + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clover/controller/process/gunicorn_process.sh b/clover/controller/process/gunicorn_process.sh new file mode 100755 index 0000000..033596f --- /dev/null +++ b/clover/controller/process/gunicorn_process.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +# + +gunicorn --bind 0.0.0.0:8000 --chdir /control wsgi diff --git a/clover/controller/process/nginx.conf b/clover/controller/process/nginx.conf new file mode 100644 index 0000000..5b26922 --- /dev/null +++ b/clover/controller/process/nginx.conf @@ -0,0 +1,18 @@ +worker_processes auto; +pid /run/nginx.pid; + +events { + worker_connections 768; +} + + +http { + server { + listen 80; + + location / { + include proxy_params; + proxy_pass http://localhost:8000; + } + } +} diff --git a/clover/controller/process/nginx_process.sh b/clover/controller/process/nginx_process.sh new file mode 100755 index 0000000..953719d --- /dev/null +++ b/clover/controller/process/nginx_process.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +# + +service nginx restart diff --git a/clover/controller/process/start_process.sh b/clover/controller/process/start_process.sh new file mode 100755 index 0000000..0c8ce11 --- /dev/null +++ b/clover/controller/process/start_process.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +# + +# Start nginx +./nginx_process.sh + +# Start gunicorn +./gunicorn_process.sh diff --git a/clover/controller/yaml/manifest.template b/clover/controller/yaml/manifest.template new file mode 100644 index 0000000..d8cb8b0 --- /dev/null +++ b/clover/controller/yaml/manifest.template @@ -0,0 +1,38 @@ +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: {{ deploy_name }} + labels: + app: {{ deploy_name }} +spec: + template: + metadata: + labels: + app: {{ deploy_name }} + spec: + containers: + - name: {{ deploy_name }} + image: {{ image_path }}/{{ image_name }}:{{ image_tag }} + ports: + - containerPort: {{ snort_grpc_port }} + - containerPort: {{ nginx_grpc_port }} + - containerPort: {{ redis_port }} + - containerPort: {{ cass_port }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ deploy_name }} + labels: + app: {{ deploy_name }} +spec: + type: NodePort + ports: + - name: http + port: 80 + targetPort: 80 + nodePort: {{ node_port }} + protocol: TCP + selector: + app: {{ deploy_name }} diff --git a/clover/controller/yaml/render_yaml.py b/clover/controller/yaml/render_yaml.py new file mode 100644 index 0000000..4795a9c --- /dev/null +++ b/clover/controller/yaml/render_yaml.py @@ -0,0 +1,73 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import argparse + +from jinja2 import Template + + +def render_yaml(args): + template_file = 'manifest.template' + out_file = args['deploy_name'] + '.yaml' + + try: + with open(template_file) as f: + tmpl = Template(f.read()) + output = tmpl.render( + image_path=args['image_path'], + image_name=args['image_name'], + image_tag=args['image_tag'], + deploy_name=args['deploy_name'], + snort_grpc_port=args['snort_grpc_port'], + nginx_grpc_port=args['nginx_grpc_port'], + redis_port=args['redis_port'], + cass_port=args['cass_port'], + node_port=args['node_port'] + ) + with open(out_file, "wb") as fh: + fh.write(output) + return "Generated manifest for {}".format(args['deploy_name']) + except Exception as e: + print(e) + return "Unable to generate manifest for {}".format( + args['deploy_name']) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--image_name', default='clover-controller', + help='The image name to use') + parser.add_argument( + #'--image_path', default='opnfv', + '--image_path', default='localhost:5000', + help='The path to the image to use') + parser.add_argument( + #'--image_tag', default='opnfv-6.0.0', + '--image_tag', default='latest', + help='The image tag to use') + parser.add_argument( + '--deploy_name', default='clover-controller', + help='The k8s deploy name to use') + parser.add_argument( + '--redis_port', default='6379', + help='The redis port to connect for management') + parser.add_argument( + '--snort_grpc_port', default='50052', + help='The GRPC port for snort service') + parser.add_argument( + '--nginx_grpc_port', default='50054', + help='The GRPC port for nginx services') + parser.add_argument( + '--node_port', default='32044', + help='Default nodePort port number') + parser.add_argument( + '--cass_port', default='9042', + help='The Cassandra port') + + args = parser.parse_args() + print(render_yaml(vars(args))) |