Permalink
Browse files

Import Zpark, the Zabbix bot for Cisco Spark

Basic functionality established:
- Southbound API (to be consumed by Zabbix) which supports a basic
'ping' endpoint and an endpoint for creating a new alert
- Nothbound connectivity to Spark via its API for passing through a message
received on the SB API to a given Spark user

More to come.
  • Loading branch information...
knightjoel committed Aug 9, 2017
0 parents commit b54faeaf95c5afa76f2c08a7e57a294ca2b18f1b
Showing with 136 additions and 0 deletions.
  1. +19 −0 requirements.txt
  2. +19 −0 zpark/__init__.py
  3. +49 −0 zpark/api_common.py
  4. +5 −0 zpark/default_settings.py
  5. +44 −0 zpark/v1.py
@@ -0,0 +1,19 @@
aniso8601==1.2.1
certifi==2017.7.27.1
chardet==3.0.4
ciscosparkapi==0.6.1
click==6.7
Flask==0.12.2
Flask-RESTful==0.3.6
future==0.16.0
idna==2.5
itsdangerous==0.24
Jinja2==2.9.6
MarkupSafe==1.0
python-dateutil==2.6.1
pytz==2017.2
requests==2.18.3
requests-toolbelt==0.8.0
six==1.10.0
urllib3==1.22
Werkzeug==0.12.2
@@ -0,0 +1,19 @@
import os
from ciscosparkapi import CiscoSparkAPI
from flask import Flask
basedir = os.path.dirname(os.path.abspath(__file__))
basedir = os.path.abspath(basedir + '/../')
app = Flask(__name__, instance_path=basedir, instance_relative_config=True)
app.config.from_object('zpark.default_settings')
app.config.from_pyfile('app.cfg', silent=True)
spark_api = CiscoSparkAPI(access_token=app.config['SPARK_ACCESS_TOKEN'])
# API v1
from zpark.v1 import api_v1, api_v1_bp, API_VERSION_V1
app.register_blueprint(api_v1_bp, url_prefix='/api/v{}'.format(API_VERSION_V1))
@@ -0,0 +1,49 @@
from functools import wraps
from datetime import datetime as dt
from ciscosparkapi import SparkApiError
from flask import current_app, request
from flask_restful import abort
from zpark import spark_api
def newalert(sendto, subject, message):
try:
msg = spark_api.messages.create(
toPersonEmail=sendto,
text='\n\n'.join([subject, message]))
except SparkApiError as e:
# XXX log the error
abort(409)
return {
'to': msg.toPersonEmail,
'message': msg.text,
'message_id': msg.id,
'created': msg.created
}
def ping(api_version):
return {
'hello': 'Hello!',
'apiversion': api_version,
'utctime': str(dt.utcnow())
}
def requires_token(func):
@wraps(func)
def decorated(*args, **kwargs):
token = request.headers.get('Token', None)
if not token or not current_app.config['SB_API_TOKEN']:
abort(401)
if token == current_app.config['SB_API_TOKEN']:
return func(*args, **kwargs)
else:
abort(401)
return decorated
@@ -0,0 +1,5 @@
DEBUG = False
SB_API_TOKEN = None
SPARK_ACCESS_TOKEN = None
@@ -0,0 +1,44 @@
from flask import Blueprint
from flask_restful import Api, Resource, reqparse
from zpark import api_common
API_VERSION_V1=1
API_VERSION=API_VERSION_V1
api_v1_bp = Blueprint('api_v1', __name__)
api_v1 = Api(api_v1_bp)
class Alert(Resource):
@api_common.requires_token
def post(self):
parser = reqparse.RequestParser()
parser.add_argument('to', type=unicode, required=True,
location='json',
help='Identifier of person or Spark space to '
'send the alert to. Required.')
parser.add_argument('subject', type=unicode, required=True,
location='json',
help='The subject (ie, first line) of text sent '
'to the recipient. Required.')
parser.add_argument('message', type=unicode, required=False,
location='json',
help='The contents of the alert message. Optional.')
args = parser.parse_args()
return api_common.newalert(args['to'],
args['subject'],
args['message'])
class Ping(Resource):
@api_common.requires_token
def get(self):
return api_common.ping(api_version=API_VERSION)
api_v1.add_resource(Ping, '/ping')
api_v1.add_resource(Alert, '/alert')

0 comments on commit b54faea

Please sign in to comment.