[feature] implement-api-service

* created tiller status
* created apply api
* fixing prefix-issues
This commit is contained in:
gardlt 2017-04-26 15:29:28 -05:00
parent e01f4966b8
commit 629a118f49
17 changed files with 341 additions and 134 deletions

View File

@ -1,8 +1,9 @@
FROM ubuntu:16.04 FROM ubuntu:16.04
MAINTAINER bjozsa@att.com MAINTAINER Armada Team
ENV USER=armada \ ENV USER=armada \
VERSION=master VERSION=master \
REPO=https://github.com/att-comdev/armada.git
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y \ apt-get install -y \
@ -15,20 +16,18 @@ RUN apt-get update && \
gcc \ gcc \
libssl-dev \ libssl-dev \
libffi-dev \ libffi-dev \
libgit2-dev libgit2-dev \
RUN useradd -ms /bin/bash $USER RUN git clone -b $VERSION $REPO ${HOME}/armada
USER $USER WORKDIR /root/armada
WORKDIR /home/$USER RUN pip install -r requirements.txt \
&& sh scripts/libgit2.sh \
&& pip install --upgrade urllib3 \
&& pip install pygit2 \
&& python setup.py install
RUN git clone -b $VERSION https://github.com/att-comdev/armada.git ENTRYPOINT ["armada"]
WORKDIR /home/$USER/armada EXPOSE 8000
RUN virtualenv --no-site-packages /home/$USER/.armada && \
. /home/$USER/.armada/bin/activate
RUN /home/$USER/.armada/bin/pip install -r /home/$USER/armada/requirements.txt CMD gunicorn server:api -b :8000
RUN /home/$USER/.armada/bin/python ./setup.py install
ENTRYPOINT ["/home/$USER/.armada/bin/armada"]
CMD ["-h"]

View File

@ -24,7 +24,12 @@ Its functionality may extend beyond helm, assisting in interacting with kubernet
To use this container, use these simple instructions: To use this container, use these simple instructions:
``` ```
docker run quay.io/attcomdev/armada:latest docker build -t armada .
```
```
docker run -v ~/.kube/config:/root/.kube/config -v $(pwd)/examples/:/examples -v /tmp:/dev/log quay.io/attcomdev/armada:latest
``` ```
## Development ## Development

View File

@ -3,8 +3,8 @@ import yaml
from supermutes.dot import dotify from supermutes.dot import dotify
from handlers.chartbuilder import ChartBuilder from chartbuilder import ChartBuilder
from handlers.tiller import Tiller from tiller import Tiller
from logutil import LOG from logutil import LOG
class Armada(object): class Armada(object):
@ -13,13 +13,20 @@ class Armada(object):
workflows workflows
''' '''
def __init__(self, args): def __init__(self, config,
disable_update_pre=False,
disable_update_post=False,
enable_chart_cleanup=False,
dry_run=False):
''' '''
Initialize the Armada Engine and establish Initialize the Armada Engine and establish
a connection to Tiller a connection to Tiller
''' '''
self.args = args self.disable_update_pre = disable_update_pre
self.config = yaml.load(open(args.config).read()) self.disable_update_post = disable_update_post
self.enable_chart_cleanup = enable_chart_cleanup
self.dry_run = dry_run
self.config = yaml.load(config)
self.tiller = Tiller() self.tiller = Tiller()
def find_release_chart(self, known_releases, name): def find_release_chart(self, known_releases, name):
@ -34,6 +41,11 @@ class Armada(object):
''' '''
Syncronize Helm with the Armada Config(s) Syncronize Helm with the Armada Config(s)
''' '''
def release_prefix(prefix, chart):
'''
how to attach prefix to chart
'''
return "{}-{}".format(prefix, chart)
# extract known charts on tiller right now # extract known charts on tiller right now
known_releases = self.tiller.list_charts() known_releases = self.tiller.list_charts()
@ -63,19 +75,21 @@ class Armada(object):
# determine install or upgrade by examining known releases # determine install or upgrade by examining known releases
LOG.debug("RELEASE: %s", chart.release_name) LOG.debug("RELEASE: %s", chart.release_name)
if chart.release_name in [x[0] for x in known_releases]: if release_prefix(prefix, chart.release_name) in [x[0]
for x in
known_releases]:
# indicate to the end user what path we are taking # indicate to the end user what path we are taking
LOG.info("Upgrading release %s", chart.release_name) LOG.info("Upgrading release %s", chart.release_name)
# extract the installed chart and installed values from the # extract the installed chart and installed values from the
# latest release so we can compare to the intended state # latest release so we can compare to the intended state
installed_chart, installed_values = self.find_release_chart( installed_chart, installed_values = self.find_release_chart(
known_releases, chart.release_name) known_releases, release_prefix(prefix, chart.release_name))
if not self.args.disable_update_pre: if not self.disable_update_pre:
pre_actions = getattr(chart.upgrade, 'pre', {}) pre_actions = getattr(chart.upgrade, 'pre', {})
if not self.args.disable_update_post: if not self.disable_update_post:
post_actions = getattr(chart.upgrade, 'post', {}) post_actions = getattr(chart.upgrade, 'post', {})
# show delta for both the chart templates and the chart values # show delta for both the chart templates and the chart values
@ -91,34 +105,33 @@ class Armada(object):
continue continue
# do actual update # do actual update
self.tiller.update_release(protoc_chart, self.args.dry_run, self.tiller.update_release(protoc_chart,
chart.release_name, chart.namespace, self.dry_run,
prefix, pre_actions, post_actions, chart.release_name,
chart.namespace,
prefix, pre_actions,
post_actions,
disable_hooks=chart. disable_hooks=chart.
upgrade.no_hooks, upgrade.no_hooks,
values=yaml.safe_dump(values)) values=yaml.safe_dump(values))
# process install # process install
else: else:
try: LOG.info("Installing release %s", chart.release_name)
LOG.info("Installing release %s", chart.release_name) self.tiller.install_release(protoc_chart,
self.tiller.install_release(protoc_chart, self.dry_run,
self.args.dry_run, chart.release_name,
chart.release_name, chart.namespace,
chart.namespace, prefix,
prefix, values=yaml.safe_dump(values))
values=yaml.safe_dump(values))
except Exception:
LOG.error("Install failed, continuing.")
LOG.debug("Cleaning up chart source in %s", LOG.debug("Cleaning up chart source in %s",
chartbuilder.source_directory) chartbuilder.source_directory)
chartbuilder.source_cleanup() chartbuilder.source_cleanup()
if self.args.enable_chart_cleanup: if self.enable_chart_cleanup:
self.tiller.chart_cleanup(prefix, self.config['armada']['charts'], self.tiller.chart_cleanup(prefix, self.config['armada']['charts'])
known_releases)
def show_diff(self, chart, installed_chart, def show_diff(self, chart, installed_chart,
installed_values, target_chart, target_values): installed_values, target_chart, target_values):

View File

@ -7,8 +7,8 @@ from hapi.chart.metadata_pb2 import Metadata
from hapi.chart.config_pb2 import Config from hapi.chart.config_pb2 import Config
from supermutes.dot import dotify from supermutes.dot import dotify
from armada.logutil import LOG from logutil import LOG
from armada.utils.git import git_clone, source_cleanup from git import git_clone, source_cleanup
class ChartBuilder(object): class ChartBuilder(object):
@ -65,7 +65,8 @@ class ChartBuilder(object):
self._source_tmp_dir = git_clone(self.chart.source.location, self._source_tmp_dir = git_clone(self.chart.source.location,
self.chart.source.reference) self.chart.source.reference)
return os.path.join(self._source_tmp_dir, self.chart.source.subpath) return os.path.join(self._source_tmp_dir,
self.chart.source.subpath)
else: else:
LOG.exception("Unknown source type %s for chart %s", LOG.exception("Unknown source type %s for chart %s",

View File

@ -1,7 +1,7 @@
from kubernetes import client, config from kubernetes import client, config
from kubernetes.client.rest import ApiException from kubernetes.client.rest import ApiException
from armada.logutil import LOG from logutil import LOG
class K8s(object): class K8s(object):
''' '''

View File

@ -6,13 +6,13 @@ LOG = logging.getLogger('armada')
LOG_FORMAT = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s' LOG_FORMAT = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'
LOG_DATE = '%m-%d %H:%M' LOG_DATE = '%m-%d %H:%M'
def setup_logging(args): def setup_logging(debug):
''' '''
:params args - logging information arguments in cli :params args - logging information arguments in cli
various utilties to support logging various utilties to support logging
''' '''
level = logging.DEBUG if args.debug else logging.INFO level = logging.DEBUG if debug else logging.INFO
logging.basicConfig(level=level, format=LOG_FORMAT, date_fmt=LOG_DATE) logging.basicConfig(level=level, format=LOG_FORMAT, date_fmt=LOG_DATE)
handler = SysLogHandler(address='/dev/log') handler = SysLogHandler(address='/dev/log')
syslog_formatter = logging.Formatter('%(name)s: %(levelname)s %(message)s') syslog_formatter = logging.Formatter('%(name)s: %(levelname)s %(message)s')

View File

@ -3,8 +3,8 @@ from hapi.services.tiller_pb2 import ReleaseServiceStub, ListReleasesRequest, \
InstallReleaseRequest, UpdateReleaseRequest, UninstallReleaseRequest InstallReleaseRequest, UpdateReleaseRequest, UninstallReleaseRequest
from hapi.chart.config_pb2 import Config from hapi.chart.config_pb2 import Config
from armada.handlers.k8s import K8s from k8s import K8s
from armada.logutil import LOG from logutil import LOG
TILLER_PORT = 44134 TILLER_PORT = 44134
TILLER_VERSION = b'2.1.3' TILLER_VERSION = b'2.1.3'
@ -65,6 +65,15 @@ class Tiller(object):
'''Stub method to support arbitrary ports in the future''' '''Stub method to support arbitrary ports in the future'''
return TILLER_PORT return TILLER_PORT
def tiller_status(self):
'''
return if tiller exist or not
'''
if self._get_tiller_ip:
return True
return False
def list_releases(self): def list_releases(self):
''' '''
List Helm Releases List Helm Releases

View File

@ -1,77 +0,0 @@
endpoints: &endpoints
glance:
this: is an example
armada:
# results in "armada-keystone" release name below
# to avoid manipulating releases managed directtly
# with helm or other armadas
release_prefix: armada
charts:
# silent dependency
- chart: &helm-toolkit
name: helm-toolkit
release_name: null
namespace: null
values: {}
source:
type: git
location: git://github.com/att-comdev/openstack-helm
subpath: helm-toolkit
reference: master
dependencies: []
- chart: &mariadb
name: mariadb
release_name: mariadb
namespace: openstack
install:
no_hooks: false
upgrade:
no_hooks: false
pre:
delete: []
create: []
post:
delete: []
create: []
values:
endpoints: *endpoints
source:
type: git
location: git://github.com/att-comdev/openstack-helm
subpath: mariadb
reference: master
dependencies:
- *helm-toolkit
- chart: &keystone
name: keystone
release_name: keystone
namespace: openstack
install:
no_hooks: false
upgrade:
no_hooks: false
pre:
delete:
- name: keystone-db-sync
type: job
- name: keystone-db-init
type: job
create: []
post:
delete: []
create: []
values:
endpoints: *endpoints
source:
type: git
location: git://github.com/att-comdev/openstack-helm
subpath: keystone
reference: master
dependencies:
- *helm-toolkit

View File

@ -0,0 +1,176 @@
endpoints: &endpoints
hello-world:
this: is an example
armada:
# results in "armada-keystone" release name below
# to avoid manipulating releases managed directtly
# with helm or other armadas
release_prefix: armada
charts:
# silent dependency
- chart: &helm-toolkit
name: helm-toolkit
release_name: null
namespace: null
values: {}
source:
type: git
location: git://github.com/openstack/openstack-helm
subpath: helm-toolkit
reference: master
dependencies: []
- chart: &mariadb
name: mariadb
release_name: mariadb
namespace: openstack
install:
no_hooks: false
upgrade:
no_hooks: false
pre:
delete: []
create: []
post:
delete: []
create: []
values:
endpoints: *endpoints
replicas: 1
volume:
size: 1Gi
source:
type: git
location: git://github.com/openstack/openstack-helm
subpath: mariadb
reference: master
dependencies:
- *helm-toolkit
- chart: &memcached
name: memcached
release_name: memcached
namespace: openstack
install:
no_hooks: false
upgrade:
no_hooks: false
pre:
delete: []
create: []
post:
delete: []
create: []
values:
endpoints: *endpoints
source:
type: git
location: git://github.com/openstack/openstack-helm
subpath: memcached
reference: master
dependencies:
- *helm-toolkit
- chart: &etcd
name: etcd
release_name: etcd
namespace: openstack
install:
no_hooks: false
upgrade:
no_hooks: false
pre:
delete: []
create: []
post:
delete: []
create: []
values:
endpoints: *endpoints
source:
type: git
location: git://github.com/openstack/openstack-helm
subpath: etcd
reference: master
dependencies:
- *helm-toolkit
- chart: &rabbitmq
name: rabbitmq
release_name: rabbitmq
namespace: openstack
install:
no_hooks: false
upgrade:
no_hooks: false
pre:
delete: []
create: []
post:
delete: []
create: []
values:
endpoints: *endpoints
replicas: 1
source:
type: git
location: git://github.com/openstack/openstack-helm
subpath: rabbitmq
reference: master
dependencies:
- *helm-toolkit
- chart: &keystone
name: keystone
release_name: keystone
namespace: openstack
install:
no_hooks: false
upgrade:
no_hooks: false
post:
delete: []
create: []
pre:
delete:
- name: keystone-db-sync
type: job
- name: keystone-db-init
type: job
values:
endpoints: *endpoints
source:
type: git
location: git://github.com/openstack/openstack-helm
subpath: keystone
reference: master
dependencies:
- *helm-toolkit
- chart: &horizon
name: horizon
release_name: horizon
namespace: openstack
install:
no_hooks: false
upgrade:
no_hooks: false
pre:
delete: []
create: []
post:
delete: []
create: []
values:
endpoints: *endpoints
source:
type: git
location: git://github.com/openstack/openstack-helm
subpath: horizon
reference: master
dependencies:
- *helm-toolkit

View File

@ -5,3 +5,6 @@ kubernetes==1.0.0
protobuf==3.2.0 protobuf==3.2.0
PyYAML==3.12 PyYAML==3.12
supermutes==0.2.5 supermutes==0.2.5
falcon==1.1.0
gunicorn==19.7.1

View File

@ -30,14 +30,18 @@ def parse_args():
def run(args): def run(args):
armada = Armada(args) armada = Armada(open(args.config).read(),
args.disable_update_pre,
args.disable_update_post,
args.enable_chart_cleanup,
args.dry_run)
armada.sync() armada.sync()
if __name__ == '__main__': if __name__ == '__main__':
args = parse_args() args = parse_args()
setup_logging(args) setup_logging(args.debug)
try: try:
run(args) run(args)

View File

@ -2,9 +2,9 @@
# Ubuntu 16.04 Install only # Ubuntu 16.04 Install only
sudo apt install git cmake make -y apt install git cmake make wget -y
sudo apt-get install -y python-dev libffi-dev libssl-dev libxml2-dev libxslt1-dev libssh2-1 libgit2-dev python-pip libgit2-24 apt-get install -y python-dev libffi-dev libssl-dev libxml2-dev libxslt1-dev libssh2-1 libgit2-dev python-pip libgit2-24
sudo apt-get install -y pkg-config libssh2-1-dev libhttp-parser-dev libssl-dev libz-dev apt-get install -y pkg-config libssh2-1-dev libhttp-parser-dev libssl-dev libz-dev
LIBGIT_VERSION='0.25.0' LIBGIT_VERSION='0.25.0'
@ -13,6 +13,6 @@ tar xzf v${LIBGIT_VERSION}.tar.gz
cd libgit2-${LIBGIT_VERSION}/ cd libgit2-${LIBGIT_VERSION}/
cmake . cmake .
make make
sudo make install make install
sudo pip install pygit2==${LIBGIT_VERSION} pip install pygit2==${LIBGIT_VERSION}
sudo ldconfig ldconfig

18
scripts/libgit2_docker.sh Normal file
View File

@ -0,0 +1,18 @@
#!/bin/sh
# Ubuntu 16.04 Install only
apt install git cmake make -y
apt-get install -y python-dev libffi-dev libssl-dev libxml2-dev libxslt1-dev libssh2-1 libgit2-dev python-pip libgit2-24
apt-get install -y pkg-config libssh2-1-dev libhttp-parser-dev libssl-dev libz-dev
LIBGIT_VERSION='0.25.0'
wget https://github.com/libgit2/libgit2/archive/v${LIBGIT_VERSION}.tar.gz
tar xzf v${LIBGIT_VERSION}.tar.gz
cd libgit2-${LIBGIT_VERSION}/
cmake .
make
make install
pip install pygit2==${LIBGIT_VERSION}
ldconfig

56
server.py Normal file
View File

@ -0,0 +1,56 @@
import falcon
import json
from falcon import HTTP_200
from armada.tiller import Tiller as tillerHandler
from armada.armada import Armada as armadaHandler
from armada.logutil import setup_logging
class Tiller(object):
'''
tiller service endpoints
'''
def on_get(self, req, resp):
'''
get tiller status
'''
message = "Tiller Server is {}"
if tillerHandler().tiller_status():
resp.data = json.dumps({'message': message.format('Active')})
else:
resp.data = json.dumps({'message': message.format('Not Present')})
resp.content_type = 'application/json'
resp.status = HTTP_200
class Armada(object):
'''
apply armada endpoint service
'''
def on_post(self, req, resp):
armada = armadaHandler(req.stream.read())
print armada.tiller.k8s.get_namespace_pod()
armada.sync()
resp.data = json.dumps({'message': 'Success'})
resp.content_type = 'application/json'
resp.status = HTTP_200
wsgi_app = api = falcon.API()
# Routing
url_routes = (
('/tiller/status', Tiller()),
('/apply', Armada()),
)
for route, service in url_routes:
api.add_route(route, service)
setup_logging(False)