[bug] fix-pep8-linting-issues
* fix lint issues in armada * enabled travis lint * check armada install
This commit is contained in:
parent
9c02fcfc28
commit
214c4ff409
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue