kubectl plugin kuryrvif

This plugin prints out nice information about the pods in the current
namespace. It also supports setting a selector and formatting for the
output.

Implements: blueprint kubectl-plugin
Change-Id: Id2afa262aa602765e1abf7fdd6ecda593b642ce0
Signed-off-by: Antoni Segura Puimedon <antonisp@celebdor.com>
This commit is contained in:
Antoni Segura Puimedon 2018-01-25 10:57:54 +01:00
parent cc3e128ff6
commit 3a70b0b803
No known key found for this signature in database
GPG Key ID: 9B08FFD846853B9D
4 changed files with 221 additions and 0 deletions

View File

@ -0,0 +1,24 @@
Kuryr kubectl plugin
====================
This plugin aims to bring kuryr introspection an interaction to the kubectl and
oc command line tools.
Installation
------------
Place the kuryr directory in your ~/.kube/plugins
Usage
-----
The way to use it is via the kubectl/oc plugin facility::
kubectl plugin kuryr get vif -o wide -l deploymentconfig=demo
Media
-----
You can see an example of its operation:
.. image:: kubectl_kuryr_plugin_1080.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@ -0,0 +1,182 @@
#!/usr/bin/env python
import argparse
import base64
import json
import os
from os.path import expanduser
import sys
import tempfile
import urllib
import yaml
import requests
from pprint import pprint
def _get_session_from_kubeconfig():
kubeconfig = expanduser('~/.kube/config')
with open(kubeconfig, 'r') as f:
conf = yaml.safe_load(f.read())
for context in conf['contexts']:
if context['name'] == conf['current-context']:
current_context = context
break
cluster_name = current_context['context']['cluster']
for cluster in conf['clusters']:
if cluster['name'] == cluster_name:
current_cluster = cluster
break
server = current_cluster['cluster']['server']
if server.startswith('https'):
ca_cert_data = current_cluster['cluster']['certificate-authority-data']
for user in conf['users']:
if user['name'] == current_context['context']['user']:
current_user = user
break
client_cert_data = current_user['user']['client-certificate-data']
client_key_data = current_user['user']['client-key-data']
client_cert_file = tempfile.NamedTemporaryFile(delete=False)
client_key_file = tempfile.NamedTemporaryFile(delete=False)
ca_cert_file = tempfile.NamedTemporaryFile(delete=False)
client_cert_file.write(base64.decodestring(client_cert_data.encode()))
client_cert_file.close()
client_key_file.write(base64.decodestring(client_key_data.encode()))
client_key_file.close()
ca_cert_file.write(base64.decodestring(ca_cert_data.encode()))
ca_cert_file.close()
session = requests.Session()
session.cert = (client_cert_file.name, client_key_file.name)
session.verify = ca_cert_file.name
else:
session = requests.Session()
return session, server
def get(args):
session, server = _get_session_from_kubeconfig()
namespace = os.getenv('KUBECTL_PLUGINS_CURRENT_NAMESPACE')
if args.resource in ('vif', 'vifs'):
vifs(session, server, namespace, args)
def _vif_formatted_output(vif_data, wide=False):
max_len = 12
padding = 4
vif_data.insert(0,
{'pod_name': 'POD NAME',
'vif_name': 'VIF NAME',
'host_ip': 'HOST IP',
'plugin': 'BINDING',
'active': 'ACTIVE',
'address': 'IP ADDRESS',
'port_id': 'PORT ID',
'mac_address': 'MAC ADDRESS',
'vlan_id': 'VLAN'})
short_format = ('{pod_name:{tab_len:d}s} {vif_name:{tab_len:d}s} '
'{plugin:10s} {address:{tab_len:d}s} {vlan_id:4}')
long_format = ('{pod_name:{tab_len:d}s} {vif_name:{tab_len:d}s} '
'{plugin:10s} {address:{tab_len:d}s} {vlan_id:4} '
'{active:6} {host_ip:{tab_len:d}s} '
'{mac_address:{tab_len:d}s} {port_id:{tab_len:d}s}')
for vif in vif_data:
active = vif['active']
if type(active) == bool:
vif['active'] = 'yes' if active else 'no'
if 'vlan_id' not in vif:
vif['vlan_id'] = ''
if wide:
print(long_format.format(tab_len=max_len+padding, **vif))
else:
print(short_format.format(tab_len=max_len+padding, **vif))
def vifs(session, server, namespace, args):
url = '%s/api/v1/namespaces/%s/pods' % (server, namespace)
selector = os.getenv('KUBECTL_PLUGINS_LOCAL_FLAG_SELECTOR')
if selector:
url += '?labelSelector=' + urllib.quote(selector)
output = os.getenv('KUBECTL_PLUGINS_LOCAL_FLAG_OUTPUT')
response = session.get(url)
if response.ok:
pods = response.json()
else:
sys.stderr.write('Failed to retrieve pod data')
sys.exit(1)
vif_data = []
for pod in pods['items']:
data = {'pod_name': pod['metadata']['name']}
if 'hostIP' in pod['status']:
data['host_ip'] = pod['status']['hostIP']
vif = pod['metadata']['annotations'].get('openstack.org/kuryr-vif')
if vif is None:
continue # not kuryr annotated
else:
vif = json.loads(vif)
network = (vif['versioned_object.data']['network']
['versioned_object.data'])
first_subnet = (network['subnets']['versioned_object.data']
['objects'][0]['versioned_object.data'])
first_subnet_ip = (first_subnet['ips']['versioned_object.data']
['objects'][0]['versioned_object.data']['address'])
first_subnet_prefix = first_subnet['cidr'].split('/')[1]
data['vif_name'] = vif['versioned_object.data']['vif_name']
data['plugin'] = vif['versioned_object.data']['plugin']
data['active'] = vif['versioned_object.data']['active']
data['address'] = '%s/%s' % (first_subnet_ip, first_subnet_prefix)
data['port_id'] = vif['versioned_object.data']['id']
data['mac_address'] = vif['versioned_object.data']['address']
vlan_id = vif['versioned_object.data'].get('vlan_id')
if vlan_id is not None:
data['vlan_id'] = vlan_id
vif_data.append(data)
if output == 'json':
pprint(vif_data)
elif output == 'tabular':
_vif_formatted_output(vif_data)
elif output == 'wide':
_vif_formatted_output(vif_data, wide=True)
else:
sys.stderr.write('Unrecognized output format')
sys.exit(1)
if __name__ == '__main__':
parser = argparse.ArgumentParser(usage='kuryr [command] [options]')
subparsers = parser.add_subparsers(title='Available commands', metavar='')
get_parser = subparsers.add_parser(
'get',
usage='kuryr get [resource] [options]',
help='Gets Kuryr managed resource information.')
get_parser.add_argument(
'resource',
action='store',
choices=('vif',),
help='Resource to return info for.')
get_parser.set_defaults(func=get)
args = parser.parse_args()
args.func(args)

View File

@ -0,0 +1,15 @@
name: kuryr
shortDesc: "OpenStack kuryr tools"
tree:
- name: get
shortDesc: "Retrieves Kuryr managed resources"
command: "./kuryr get"
flags:
- name: selector
shorthand: l
desc: "Selects which pods to find kuryr vif info for"
defValue: ""
- name: output
shorthand: o
desc: How to format the output
defValue: tabular