Merge branch 'master' into feature/webpack

This commit is contained in:
Shuaib Yunus
2016-12-19 16:17:53 +01:00
5 changed files with 97 additions and 47 deletions

View File

@@ -3,9 +3,7 @@ FROM alpine:3.4
RUN apk add --no-cache python3 python3-dev alpine-sdk zlib-dev libffi-dev openssl-dev nodejs && \
python3 -m ensurepip && \
rm -r /usr/lib/python*/ensurepip && \
# compile gevent
pip3 install --upgrade pip setuptools gevent && \
# cleanup
apk del python3-dev alpine-sdk zlib-dev libffi-dev openssl-dev && \
rm -rf /var/cache/apk/* /root/.cache /tmp/*

View File

@@ -34,7 +34,7 @@ You can run the app locally:
$ pip3 install -r requirements.txt
$ kubectl proxy &
$ cd app && npm start
$ cd app && npm start &
$ cd -
$ ./app.py
@@ -56,6 +56,19 @@ Afterwards you can open "kube-ops-view" via the kubectl proxy:
Now direct your browser to http://localhost:8001/api/v1/proxy/namespaces/default/services/kube-ops-view/
Configuration
=============
The following environment variables are supported:
``CLUSTERS``
Comma separated list of Kubernetes API server URLs. It defaults to ``http://localhost:8001/`` (default endpoint of ``kubectl proxy``).
``CREDENTIALS_DIR``
Directory to read (OAuth) credentials from --- these credentials are only used for non-localhost cluster URLs.
``DEBUG``
Set to a non-empty value for local development to reload code changes.
Supported Browsers
==================

58
app.py
View File

@@ -8,11 +8,19 @@ import flask
import logging
import os
import requests
import tokens
from urllib.parse import urljoin
DEFAULT_CLUSTERS = 'http://localhost:8001/'
app = connexion.App(__name__)
session = requests.Session()
tokens.configure(from_file_only=True)
tokens.manage('read-only')
@app.app.route('/')
def index():
@@ -20,36 +28,42 @@ def index():
def get_clusters():
api_server_url = 'http://localhost:8001/'
response = session.get('{}/api/v1/nodes'.format(api_server_url), timeout=5)
response.raise_for_status()
nodes = []
nodes_by_name = {}
for node in response.json()['items']:
obj = {'name': node['metadata']['name'], 'labels': node['metadata']['labels'], 'status': node['status'], 'pods': []}
nodes.append(obj)
nodes_by_name[obj['name']] = obj
response = session.get('http://localhost:8001/api/v1/pods', timeout=5)
response.raise_for_status()
for pod in response.json()['items']:
if 'nodeName' in pod['spec']:
nodes_by_name[pod['spec']['nodeName']]['pods'].append(pod)
try:
response = session.get('{}/api/v1/namespaces/kube-system/services/heapster/proxy/apis/metrics/v1alpha1/nodes'.format(api_server_url), timeout=5)
clusters = []
for api_server_url in os.getenv('CLUSTERS', DEFAULT_CLUSTERS).split(','):
if 'localhost' not in api_server_url:
# TODO: hacky way of detecting whether we need a token or not
session.headers['Authorization'] = 'Bearer {}'.format(tokens.get('read-only'))
response = session.get(urljoin(api_server_url, '/api/v1/nodes'), timeout=5)
response.raise_for_status()
for metrics in response.json()['items']:
nodes_by_name[metrics['metadata']['name']]['usage'] = metrics['usage']
except:
logging.exception('Failed to get metrics')
nodes = []
nodes_by_name = {}
for node in response.json()['items']:
obj = {'name': node['metadata']['name'], 'labels': node['metadata']['labels'], 'status': node['status'], 'pods': []}
nodes.append(obj)
nodes_by_name[obj['name']] = obj
response = session.get(urljoin(api_server_url, '/api/v1/pods'), timeout=5)
response.raise_for_status()
for pod in response.json()['items']:
if 'nodeName' in pod['spec']:
nodes_by_name[pod['spec']['nodeName']]['pods'].append(pod)
return {'kubernetes_clusters': [{'nodes': nodes}]}
try:
response = session.get(urljoin(api_server_url, '/api/v1/namespaces/kube-system/services/heapster/proxy/apis/metrics/v1alpha1/nodes'), timeout=5)
response.raise_for_status()
for metrics in response.json()['items']:
nodes_by_name[metrics['metadata']['name']]['usage'] = metrics['usage']
except:
logging.exception('Failed to get metrics')
clusters.append({'api_server_url': api_server_url, 'nodes': nodes})
return {'kubernetes_clusters': clusters}
app.add_api('swagger.yaml')
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
if os.getenv('DEBUG', False):
kwargs = {'debug': True}
else:

View File

@@ -52,6 +52,46 @@ class Tooltip extends PIXI.Graphics {
}
}
class Cluster extends PIXI.Graphics {
constructor (cluster, tooltip) {
super()
this.cluster = cluster
this.tooltip = tooltip
}
draw () {
var rows = [10, 10]
for (var node of this.cluster.nodes) {
var nodeBox = new Node(node, tooltip)
nodeBox.draw()
if (nodeBox.isMaster()) {
nodeBox.x = rows[0]
rows[0] += nodeBox.width + 5
nodeBox.y = 20
} else {
nodeBox.x = rows[1]
rows[1] += nodeBox.width + 5
nodeBox.y = nodeBox.height + 25
}
this.addChild(nodeBox)
}
this.lineStyle(2, 0xaaaaff, 1);
const width = Math.max(rows[0], rows[1])
this.drawRect(0, 0, width, nodeBox.height * 2 + 30);
var topHandle = new PIXI.Graphics()
topHandle.beginFill(0xaaaaff, 1)
topHandle.drawRect(0, 0, width, 15)
topHandle.endFill()
var text = new PIXI.Text(this.cluster.api_server_url, {fontSize: 10, fill: 0x000000})
text.x = 2
text.y = 2
topHandle.addChild(text)
this.addChild(topHandle)
}
}
class Node extends PIXI.Graphics {
constructor (node, tooltip) {
super()
@@ -265,30 +305,14 @@ tooltip.draw()
function update(clusters) {
graphics.removeChildren();
graphics.lineStyle(2, 0xaaaaff, 1);
var x = 50;
var y = 50;
for (var cluster of clusters) {
var clusterBox = new PIXI.Graphics()
clusterBox.x = x
clusterBox.y = 50
var clusterBox = new Cluster(cluster, tooltip)
clusterBox.draw()
clusterBox.x = 50
clusterBox.y = y
graphics.addChild(clusterBox)
var rows = [10, 10]
for (var node of cluster.nodes) {
var nodeBox = new Node(node, tooltip)
nodeBox.draw()
if (nodeBox.isMaster()) {
nodeBox.x = rows[0]
rows[0] += nodeBox.width + 5
nodeBox.y = 10
} else {
nodeBox.x = rows[1]
rows[1] += nodeBox.width + 5
nodeBox.y = nodeBox.height + 15
}
clusterBox.addChild(nodeBox)
}
clusterBox.lineStyle(2, 0xaaaaff, 1);
clusterBox.drawRect(0, 0, Math.max(rows[0], rows[1]), nodeBox.height * 2 + 20);
x += 250;
y += 270;
}
graphics.addChild(tooltip)
}

View File

@@ -1,2 +1,3 @@
connexion
gevent
stups-tokens