[bug] fix-pep8-linting-issues

* fix lint issues in armada
* enabled travis lint
* check armada install
This commit is contained in:
gardlt 2017-02-23 11:32:53 -06:00
parent 9c02fcfc28
commit 214c4ff409
7 changed files with 106 additions and 79 deletions

View File

@ -4,7 +4,6 @@ sudo: required
python:
- "2.7"
- "3.6"
before_install:
- export LIGGIT2_VERSION=0.24.0
@ -19,10 +18,11 @@ before_install:
- cd ..
- pip install -r test-requirements.txt
- pip install -r requirements.txt
# - flake8
install:
- pip install .
script:
- armada -c examples/armada.yaml
- flake8
- armada -h
# - armada -c examples/armada.yaml -d

View File

@ -24,7 +24,6 @@ class Armada(object):
self.tiller = Tiller()
def find_release_chart(self, known_releases, name):
'''
Find a release given a list of known_releases and a release name
@ -33,7 +32,6 @@ class Armada(object):
if chart_name == name:
return chart, values
def sync(self):
'''
Syncronize Helm with the Armada Config(s)
@ -42,7 +40,8 @@ class Armada(object):
# extract known charts on tiller right now
known_releases = self.tiller.list_charts()
for release in known_releases:
LOG.debug("Release {}, Version {} found on tiller".format(release[0], release[1]))
LOG.debug("Release %s, Version %s found on tiller", release[0],
release[1])
for entry in self.config['armada']['charts']:
@ -52,8 +51,7 @@ class Armada(object):
if chart.release_name is None:
continue
# initialize helm chart and request a
# initialize helm chart and request a
# protoc helm chart object which will
# pull the sources down and walk the
# dependencies
@ -64,43 +62,61 @@ class Armada(object):
if chart.release_name in [x[0] for x in known_releases]:
# indicate to the end user what path we are taking
LOG.info("Upgrading release {}".format(chart.release_name))
LOG.info("Upgrading release %s", chart.release_name)
# extract the installed chart and installed values from the latest release so we can compare to the intended state
installed_chart, installed_values = self.find_release_chart(known_releases, chart.release_name)
# extract the installed chart and installed values from the
# latest release so we can compare to the intended state
installed_chart, installed_values = self.find_release_chart(
known_releases, chart.release_name)
# show delta for both the chart templates and the chart values
# TODO(alanmeadows) account for .files differences once we support those
self.show_diff(chart, installed_chart, installed_values, chartbuilder.dump(), values)
# TODO(alanmeadows) account for .files differences
# once we support those
self.show_diff(chart, installed_chart,
installed_values, chartbuilder.dump(), values)
# do actual update
self.tiller.update_release(protoc_chart, self.args.dry_run, chart.release_name, disable_hooks=chart.upgrade.no_hooks, values=yaml.safe_dump(values))
self.tiller.update_release(protoc_chart, self.args.dry_run,
chart.release_name,
disable_hooks=chart.
upgrade.no_hooks,
values=yaml.safe_dump(values))
# process install
else:
LOG.info("Installing release {}".format(chart.release_name))
self.tiller.install_release(protoc_chart, self.args.dry_run, chart.release_name, chart.namespace, values=yaml.safe_dump(values))
LOG.info("Installing release %s", chart.release_name)
self.tiller.install_release(protoc_chart,
self.args.dry_run,
chart.release_name,
chart.namespace,
values=yaml.safe_dump(values))
LOG.debug("Cleaning up chart source in {}".format(chartbuilder.source_directory))
LOG.debug("Cleaning up chart source in %s",
chartbuilder.source_directory)
chartbuilder.source_cleanup()
def show_diff(self, chart, installed_chart, installed_values, target_chart, target_values):
def show_diff(self, chart, installed_chart,
installed_values, target_chart, target_values):
'''
Produce a unified diff of the installed chart vs our intention
TODO(alanmeadows): This needs to be rewritten to produce better
TODO(alanmeadows): This needs to be rewritten to produce better
unified diff output and avoid the use of print
'''
chart_diff = list(difflib.unified_diff(installed_chart.SerializeToString().split('\n'), target_chart.split('\n')))
chart_diff = list(difflib.unified_diff(installed_chart
.SerializeToString()
.split('\n'),
target_chart.split('\n')))
if len(chart_diff) > 0:
LOG.info("Chart Unified Diff ({})".format(chart.release_name))
LOG.info("Chart Unified Diff (%s)", chart.release_name)
for line in chart_diff:
print line
values_diff = list(difflib.unified_diff(installed_values.split('\n'), yaml.safe_dump(target_values).split('\n')))
values_diff = list(difflib.unified_diff(installed_values.split('\n'),
yaml
.safe_dump(target_values)
.split('\n')))
if len(values_diff) > 0:
LOG.info("Values Unified Diff ({})".format(chart.release_name))
LOG.info("Values Unified Diff (%s)", chart.release_name)
for line in values_diff:
print line

View File

@ -12,7 +12,7 @@ import yaml
class ChartBuilder(object):
'''
This class handles taking chart intentions as a paramter and
This class handles taking chart intentions as a paramter and
turning those into proper protoc helm charts that can be
pushed to tiller.
@ -20,7 +20,6 @@ class ChartBuilder(object):
source from external resources where necessary
'''
def __init__(self, chart, parent=None):
'''
Initialize the ChartBuilder class
@ -55,15 +54,23 @@ class ChartBuilder(object):
tmpdir = tempfile.mkdtemp(prefix='armada', dir='/tmp')
self._source_tmp_dir = tmpdir
if self.parent:
LOG.info("Cloning {}/{} as dependency for {}".format(self.chart.source.location, self.chart.source.subpath, self.parent))
LOG.info("Cloning %s/%s as dependency for %s",
self.chart.source.location,
self.chart.source.subpath,
self.parent)
else:
LOG.info("Cloning {}/{} for release {}".format(self.chart.source.location, self.chart.source.subpath, self.chart.release_name))
LOG.info("Cloning %s/%s for release %s",
self.chart.source.location,
self.chart.source.subpath,
self.chart.release_name)
pygit2.clone_repository(self.chart.source.location, tmpdir)
return os.path.join(tmpdir, self.chart.source.subpath)
else:
LOG.exception("Unknown source type {} for chart {}" .format(self.chart.name, self.chart.source.type))
LOG.exception("Unknown source type %s for chart %s",
self.chart.name,
self.chart.source.type)
def source_cleanup(self):
'''
@ -71,13 +78,13 @@ class ChartBuilder(object):
'''
shutil.rmtree(self._source_tmp_dir)
def get_metadata(self):
'''
Process metadata
'''
# extract Chart.yaml to construct metadata
chart_yaml = dotify(yaml.load(open(os.path.join(self.source_directory, 'Chart.yaml')).read()))
chart_yaml = dotify(yaml.load(open(
os.path.join(self.source_directory, 'Chart.yaml')).read()))
# construct Metadata object
return Metadata(
@ -86,7 +93,6 @@ class ChartBuilder(object):
version=chart_yaml.version
)
def get_files(self):
'''
Return (non-template) files in this chart
@ -95,7 +101,6 @@ class ChartBuilder(object):
'''
return []
def get_values(self):
'''
Return the chart (default) values
@ -103,14 +108,15 @@ class ChartBuilder(object):
# create config object representing unmarshaled values.yaml
if os.path.exists(os.path.join(self.source_directory, 'values.yaml')):
raw_values = open(os.path.join(self.source_directory, 'values.yaml')).read()
raw_values = open(os.path.join(self.source_directory,
'values.yaml')).read()
else:
LOG.warn("No values.yaml in {}, using empty values".format(self.source_directory))
LOG.warn("No values.yaml in %s, using empty values",
self.source_directory)
raw_values = ''
return Config(raw=raw_values)
def get_templates(self):
'''
Return all the chart templates
@ -119,15 +125,19 @@ class ChartBuilder(object):
# process all files in templates/ as a template to attach to the chart
# building a Template object
templates = []
if not os.path.exists(os.path.join(self.source_directory, 'templates')):
LOG.warn("Chart {} has no templates directory, no templates will be deployed".format(self.chart.name))
for root, dirs, files in os.walk(os.path.join(self.source_directory, 'templates'), topdown=True):
for file in files:
templates.append(Template(name=file, data=open(os.path.join(root, file), 'r').read()))
if not os.path.exists(os.path.join(self.source_directory,
'templates')):
LOG.warn("Chart %s has no templates directory,"
"no templates will be deployed", self.chart.name)
for root, _, files in os.walk(os.path.join(self.source_directory,
'templates'), topdown=True):
for tpl_file in files:
templates.append(Template(name=tpl_file,
data=open(os.path.join(root,
tpl_file),
'r').read()))
return templates
def get_helm_chart(self):
'''
Return a helm chart object
@ -137,9 +147,11 @@ class ChartBuilder(object):
return self._helm_chart
# dependencies
# [process_chart(x, is_dependency=True) for x in chart.dependencies]
dependencies=[]
dependencies = []
for chart in self.chart.dependencies:
LOG.info("Building dependency chart {} for release {}".format(chart.name, self.chart.release_name))
LOG.info("Building dependency chart %s for release %s", chart.name,
self.chart.release_name)
dependencies.append(ChartBuilder(chart).get_helm_chart())
helm_chart = Chart(
@ -153,12 +165,11 @@ class ChartBuilder(object):
self._helm_chart = helm_chart
return helm_chart
def dump(self):
'''
This method is used to dump a chart object as a serialized string so that we can perform a diff
This method is used to dump a chart object as a
serialized string so that we can perform a diff
It should recurse into dependencies
'''
return self.get_helm_chart().SerializeToString()

View File

@ -1,9 +1,9 @@
from logutil import LOG
from kubernetes import client, config
class K8s(object):
'''
Object to obtain the local kube config file
'''
def __init__(self):
'''
Initialize connection to Kubernetes

View File

@ -1,17 +1,20 @@
# various utilties to support logging
import logging
from logging.handlers import SysLogHandler
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'
def setup_logging(args):
'''
:params args - logging information arguments in cli
various utilties to support logging
'''
level = logging.DEBUG if args.debug else logging.INFO
logging.basicConfig(level=level, format=LOG_FORMAT, date_fmt=LOG_DATE)
handler = SysLogHandler(address='/dev/log')
syslog_formatter = logging.Formatter('%(name)s: %(levelname)s %(message)s')
handler.setFormatter(syslog_formatter)
LOG.addHandler(handler)
LOG.addHandler(handler)

View File

@ -1,16 +1,16 @@
from hapi.services.tiller_pb2 import ReleaseServiceStub, ListReleasesRequest, InstallReleaseRequest, UpdateReleaseRequest
from hapi.services.tiller_pb2 import ReleaseServiceStub, ListReleasesRequest, \
InstallReleaseRequest, UpdateReleaseRequest
from hapi.chart.config_pb2 import Config
from logutil import LOG
from k8s import K8s
import grpc
TILLER_PORT=44134
TILLER_VERSION=b'2.1.3'
TILLER_TIMEOUT=300
TILLER_PORT = 44134
TILLER_VERSION = b'2.1.3'
TILLER_TIMEOUT = 300
class Tiller(object):
'''
The Tiller class supports communication and requests to the Tiller Helm
The Tiller class supports communication and requests to the Tiller Helm
service over gRPC
'''
@ -27,7 +27,6 @@ class Tiller(object):
# be fed at runtime as an override
self.timeout = TILLER_TIMEOUT
@property
def metadata(self):
'''
@ -35,7 +34,6 @@ class Tiller(object):
'''
return [(b'x-helm-api-client', TILLER_VERSION)]
def get_channel(self):
'''
Return a tiller channel
@ -44,7 +42,6 @@ class Tiller(object):
tiller_port = self._get_tiller_port()
return grpc.insecure_channel('%s:%s' % (tiller_ip, tiller_port))
def _get_tiller_pod(self):
'''
Search all namespaces for a pod beginning with tiller-deploy*
@ -55,7 +52,6 @@ class Tiller(object):
if i.metadata.name.startswith('tiller-deploy'):
return i
def _get_tiller_ip(self):
'''
Returns the tiller pod's IP address by searching all namespaces
@ -63,12 +59,10 @@ class Tiller(object):
pod = self._get_tiller_pod()
return pod.status.pod_ip
def _get_tiller_port(self):
'''Stub method to support arbitrary ports in the future'''
return TILLER_PORT
def list_releases(self):
'''
List Helm Releases
@ -77,7 +71,6 @@ class Tiller(object):
req = ListReleasesRequest()
return stub.ListReleases(req, self.timeout, metadata=self.metadata)
def list_charts(self):
'''
List Helm Charts from Latest Releases
@ -88,13 +81,15 @@ class Tiller(object):
for x in self.list_releases():
try:
latest_release = x.releases[-1]
charts.append((latest_release.name, latest_release.version, latest_release.chart, latest_release.config.raw))
charts.append((latest_release.name, latest_release.version,
latest_release.chart,
latest_release.config.raw))
except IndexError:
continue
return charts
def update_release(self, chart, dry_run, name, disable_hooks=False, values=None):
def update_release(self, chart, dry_run, name, disable_hooks=False,
values=None):
'''
Update a Helm Release
'''
@ -112,8 +107,8 @@ class Tiller(object):
disable_hooks=disable_hooks,
values=values,
name=name)
return stub.UpdateRelease(release_request, self.timeout, metadata=self.metadata)
return stub.UpdateRelease(release_request, self.timeout,
metadata=self.metadata)
def install_release(self, chart, dry_run, name, namespace, values=None):
'''
@ -133,4 +128,6 @@ class Tiller(object):
values=values,
name=name,
namespace=namespace)
return stub.InstallRelease(release_request, self.timeout, metadata=self.metadata)
return stub.InstallRelease(release_request,
self.timeout,
metadata=self.metadata)

View File

@ -10,5 +10,5 @@ setenv=
[flake8]
ignore=E302,H306
exclude= libgit2-0.24.0, .git, .idea, .tox, *.egg-info, *.eggs, bin, dist
exclude= libgit2-0.24.0, .git, .idea, .tox, *.egg-info, *.eggs, bin, dist, hapi