[feature] adding-pre-post-actions-to-yaml (#44)
* fix multiple release items * remove old configs in kubernetes * add skip flags
This commit is contained in:
parent
6355fee383
commit
e4f49e9f8a
|
@ -87,3 +87,4 @@ ENV/
|
||||||
|
|
||||||
# Rope project settings
|
# Rope project settings
|
||||||
.ropeproject
|
.ropeproject
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ class Armada(object):
|
||||||
|
|
||||||
chart = dotify(entry['chart'])
|
chart = dotify(entry['chart'])
|
||||||
values = entry['chart']['values']
|
values = entry['chart']['values']
|
||||||
|
pre_actions = {}
|
||||||
|
post_actions = {}
|
||||||
|
|
||||||
if chart.release_name is None:
|
if chart.release_name is None:
|
||||||
continue
|
continue
|
||||||
|
@ -61,16 +63,23 @@ class Armada(object):
|
||||||
protoc_chart = chartbuilder.get_helm_chart()
|
protoc_chart = chartbuilder.get_helm_chart()
|
||||||
|
|
||||||
# determine install or upgrade by examining known releases
|
# determine install or upgrade by examining known releases
|
||||||
|
LOG.debug("RELEASE: %s", chart.release_name)
|
||||||
|
|
||||||
if chart.release_name in [x[0] for x in known_releases]:
|
if 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, chart.release_name)
|
||||||
|
|
||||||
|
if not self.args.disable_update_pre:
|
||||||
|
pre_actions = getattr(chart.upgrade, 'pre', {})
|
||||||
|
|
||||||
|
if not self.args.disable_update_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
|
||||||
# TODO(alanmeadows) account for .files differences
|
# TODO(alanmeadows) account for .files differences
|
||||||
# once we support those
|
# once we support those
|
||||||
|
@ -85,7 +94,8 @@ class Armada(object):
|
||||||
|
|
||||||
# do actual update
|
# do actual update
|
||||||
self.tiller.update_release(protoc_chart, self.args.dry_run,
|
self.tiller.update_release(protoc_chart, self.args.dry_run,
|
||||||
chart.release_name,
|
chart.release_name, chart.namespace,
|
||||||
|
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))
|
||||||
|
@ -99,6 +109,15 @@ class Armada(object):
|
||||||
chart.namespace,
|
chart.namespace,
|
||||||
prefix,
|
prefix,
|
||||||
values=yaml.safe_dump(values))
|
values=yaml.safe_dump(values))
|
||||||
|
try:
|
||||||
|
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))
|
||||||
|
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)
|
||||||
|
|
|
@ -135,7 +135,11 @@ class ChartBuilder(object):
|
||||||
for root, _, files in os.walk(os.path.join(self.source_directory,
|
for root, _, files in os.walk(os.path.join(self.source_directory,
|
||||||
'templates'), topdown=True):
|
'templates'), topdown=True):
|
||||||
for tpl_file in files:
|
for tpl_file in files:
|
||||||
templates.append(Template(name=tpl_file,
|
tname = os.path.relpath(os.path.join(root, tpl_file),
|
||||||
|
os.path.join(self.source_directory,
|
||||||
|
'templates'))
|
||||||
|
|
||||||
|
templates.append(Template(name=tname,
|
||||||
data=open(os.path.join(root,
|
data=open(os.path.join(root,
|
||||||
tpl_file),
|
tpl_file),
|
||||||
'r').read()))
|
'r').read()))
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
from kubernetes import client, config
|
from kubernetes import client, config
|
||||||
|
from kubernetes.client.rest import ApiException
|
||||||
|
from logutil import LOG
|
||||||
|
|
||||||
class K8s(object):
|
class K8s(object):
|
||||||
'''
|
'''
|
||||||
|
@ -10,3 +12,33 @@ class K8s(object):
|
||||||
'''
|
'''
|
||||||
config.load_kube_config()
|
config.load_kube_config()
|
||||||
self.client = client.CoreV1Api()
|
self.client = client.CoreV1Api()
|
||||||
|
self.api_client = client.BatchV1Api()
|
||||||
|
|
||||||
|
def delete_job_action(self, name, namespace="default"):
|
||||||
|
'''
|
||||||
|
:params name - name of the job
|
||||||
|
:params namespace - name of pod that job
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
body = client.V1DeleteOptions()
|
||||||
|
self.api_client.delete_namespaced_job(name=name,
|
||||||
|
namespace=namespace,
|
||||||
|
body=body)
|
||||||
|
except ApiException as e:
|
||||||
|
LOG.error("Exception when deleting a job: %s", e)
|
||||||
|
|
||||||
|
def create_job_action(self, name, namespace="default"):
|
||||||
|
'''
|
||||||
|
:params name - name of the job
|
||||||
|
:params namespace - name of pod that job
|
||||||
|
'''
|
||||||
|
LOG.debug(" %s in namespace: %s", name, namespace)
|
||||||
|
|
||||||
|
def get_namespace_pod(self, namespace="default"):
|
||||||
|
'''
|
||||||
|
:params - namespace - pod namespace
|
||||||
|
|
||||||
|
This will return a list of objects req namespace
|
||||||
|
'''
|
||||||
|
res = self.client.list_namespaced_pod(namespace)
|
||||||
|
return res
|
||||||
|
|
|
@ -3,12 +3,13 @@ from hapi.services.tiller_pb2 import ReleaseServiceStub, ListReleasesRequest, \
|
||||||
from hapi.chart.config_pb2 import Config
|
from hapi.chart.config_pb2 import Config
|
||||||
import grpc
|
import grpc
|
||||||
|
|
||||||
from logutil import LOG
|
|
||||||
from k8s import K8s
|
from k8s import K8s
|
||||||
|
from logutil import LOG
|
||||||
|
|
||||||
TILLER_PORT = 44134
|
TILLER_PORT = 44134
|
||||||
TILLER_VERSION = b'2.1.3'
|
TILLER_VERSION = b'2.1.3'
|
||||||
TILLER_TIMEOUT = 300
|
TILLER_TIMEOUT = 300
|
||||||
|
RELEASE_LIMIT = 64
|
||||||
|
|
||||||
class Tiller(object):
|
class Tiller(object):
|
||||||
'''
|
'''
|
||||||
|
@ -48,8 +49,7 @@ class Tiller(object):
|
||||||
'''
|
'''
|
||||||
Search all namespaces for a pod beginning with tiller-deploy*
|
Search all namespaces for a pod beginning with tiller-deploy*
|
||||||
'''
|
'''
|
||||||
ret = self.k8s.client.list_pod_for_all_namespaces()
|
for i in self.k8s.get_namespace_pod('kube-system').items:
|
||||||
for i in ret.items:
|
|
||||||
# TODO(alanmeadows): this is a bit loose
|
# TODO(alanmeadows): this is a bit loose
|
||||||
if i.metadata.name.startswith('tiller-deploy'):
|
if i.metadata.name.startswith('tiller-deploy'):
|
||||||
return i
|
return i
|
||||||
|
@ -69,9 +69,14 @@ class Tiller(object):
|
||||||
'''
|
'''
|
||||||
List Helm Releases
|
List Helm Releases
|
||||||
'''
|
'''
|
||||||
|
releases = []
|
||||||
stub = ReleaseServiceStub(self.channel)
|
stub = ReleaseServiceStub(self.channel)
|
||||||
req = ListReleasesRequest()
|
req = ListReleasesRequest(limit=RELEASE_LIMIT)
|
||||||
return stub.ListReleases(req, self.timeout, metadata=self.metadata)
|
release_list = stub.ListReleases(req, self.timeout,
|
||||||
|
metadata=self.metadata)
|
||||||
|
for y in release_list:
|
||||||
|
releases.extend(y.releases)
|
||||||
|
return releases
|
||||||
|
|
||||||
def list_charts(self):
|
def list_charts(self):
|
||||||
'''
|
'''
|
||||||
|
@ -80,9 +85,8 @@ class Tiller(object):
|
||||||
Returns list of (name, version, chart, values)
|
Returns list of (name, version, chart, values)
|
||||||
'''
|
'''
|
||||||
charts = []
|
charts = []
|
||||||
for x in self.list_releases():
|
for latest_release in self.list_releases():
|
||||||
try:
|
try:
|
||||||
latest_release = x.releases[-1]
|
|
||||||
charts.append((latest_release.name, latest_release.version,
|
charts.append((latest_release.name, latest_release.version,
|
||||||
latest_release.chart,
|
latest_release.chart,
|
||||||
latest_release.config.raw))
|
latest_release.config.raw))
|
||||||
|
@ -90,8 +94,49 @@ class Tiller(object):
|
||||||
continue
|
continue
|
||||||
return charts
|
return charts
|
||||||
|
|
||||||
def update_release(self, chart, dry_run, name, disable_hooks=False,
|
def _pre_update_actions(self, actions, namespace):
|
||||||
values=None):
|
'''
|
||||||
|
:params actions - array of items actions
|
||||||
|
:params namespace - name of pod for actions
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
for action in actions.get('delete', []):
|
||||||
|
name = action.get("name")
|
||||||
|
action_type = action.get("type")
|
||||||
|
if "job" in action_type:
|
||||||
|
LOG.info("Deleting %s in namespace: %s", name, namespace)
|
||||||
|
self.k8s.delete_job_action(name, namespace)
|
||||||
|
continue
|
||||||
|
LOG.error("Unable to execute name: %s type: %s ", name, type)
|
||||||
|
except Exception:
|
||||||
|
LOG.debug("PRE: Could not delete anything, please check yaml")
|
||||||
|
|
||||||
|
try:
|
||||||
|
for action in actions.get('create', []):
|
||||||
|
name = action.get("name")
|
||||||
|
action_type = action.get("type")
|
||||||
|
if "job" in action_type:
|
||||||
|
LOG.info("Creating %s in namespace: %s", name, namespace)
|
||||||
|
self.k8s.create_job_action(name, action_type)
|
||||||
|
continue
|
||||||
|
except Exception:
|
||||||
|
LOG.debug("PRE: Could not create anything, please check yaml")
|
||||||
|
|
||||||
|
def _post_update_actions(self, actions, namespace):
|
||||||
|
try:
|
||||||
|
for action in actions.get('create', []):
|
||||||
|
name = action.get("name")
|
||||||
|
action_type = action.get("type")
|
||||||
|
if "job" in action_type:
|
||||||
|
LOG.info("Creating %s in namespace: %s", name, namespace)
|
||||||
|
self.k8s.create_job_action(name, action_type)
|
||||||
|
continue
|
||||||
|
except Exception:
|
||||||
|
LOG.debug("POST: Could not create anything, please check yaml")
|
||||||
|
|
||||||
|
def update_release(self, chart, dry_run, name, namespace,
|
||||||
|
pre_actions=None, post_actions=None,
|
||||||
|
disable_hooks=False, values=None):
|
||||||
'''
|
'''
|
||||||
Update a Helm Release
|
Update a Helm Release
|
||||||
'''
|
'''
|
||||||
|
@ -101,6 +146,8 @@ class Tiller(object):
|
||||||
else:
|
else:
|
||||||
values = Config(raw=values)
|
values = Config(raw=values)
|
||||||
|
|
||||||
|
self._pre_update_actions(pre_actions, namespace)
|
||||||
|
|
||||||
# build release install request
|
# build release install request
|
||||||
stub = ReleaseServiceStub(self.channel)
|
stub = ReleaseServiceStub(self.channel)
|
||||||
release_request = UpdateReleaseRequest(
|
release_request = UpdateReleaseRequest(
|
||||||
|
@ -109,8 +156,11 @@ class Tiller(object):
|
||||||
disable_hooks=disable_hooks,
|
disable_hooks=disable_hooks,
|
||||||
values=values,
|
values=values,
|
||||||
name=name)
|
name=name)
|
||||||
return stub.UpdateRelease(release_request, self.timeout,
|
|
||||||
metadata=self.metadata)
|
stub.UpdateRelease(release_request, self.timeout,
|
||||||
|
metadata=self.metadata)
|
||||||
|
|
||||||
|
self._post_update_actions(post_actions, namespace)
|
||||||
|
|
||||||
def install_release(self, chart, dry_run, name, namespace, prefix,
|
def install_release(self, chart, dry_run, name, namespace, prefix,
|
||||||
values=None):
|
values=None):
|
||||||
|
|
|
@ -11,9 +11,9 @@ armada:
|
||||||
|
|
||||||
charts:
|
charts:
|
||||||
|
|
||||||
# silent dependency
|
# silent dependency
|
||||||
- chart: &common
|
- chart: &helm-toolkit
|
||||||
name: common
|
name: helm-toolkit
|
||||||
release_name: null
|
release_name: null
|
||||||
namespace: null
|
namespace: null
|
||||||
values: {}
|
values: {}
|
||||||
|
@ -23,19 +23,53 @@ armada:
|
||||||
subpath: helm-toolkit
|
subpath: helm-toolkit
|
||||||
reference: master
|
reference: master
|
||||||
dependencies: []
|
dependencies: []
|
||||||
|
|
||||||
- chart: &keystone
|
- chart: &mariadb
|
||||||
name: keystone
|
name: mariadb
|
||||||
release_name: keystone
|
release_name: mariadb
|
||||||
namespace: openstack
|
namespace: openstack
|
||||||
install:
|
install:
|
||||||
no_hooks: false
|
no_hooks: false
|
||||||
upgrade:
|
upgrade:
|
||||||
no_hooks: false
|
no_hooks: false
|
||||||
pre:
|
pre:
|
||||||
delete:
|
delete: []
|
||||||
- Job/keystone-db-sync
|
create: []
|
||||||
- Job/keystone-db-init
|
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:
|
||||||
|
- name: keystone-db-sync
|
||||||
|
type: job
|
||||||
|
- name: keystone-db-init
|
||||||
|
type: job
|
||||||
|
post:
|
||||||
|
delete: []
|
||||||
|
create: []
|
||||||
values:
|
values:
|
||||||
endpoints: *endpoints
|
endpoints: *endpoints
|
||||||
source:
|
source:
|
||||||
|
@ -44,4 +78,4 @@ armada:
|
||||||
subpath: keystone
|
subpath: keystone
|
||||||
reference: master
|
reference: master
|
||||||
dependencies:
|
dependencies:
|
||||||
- *common
|
- *helm-toolkit
|
||||||
|
|
|
@ -19,6 +19,11 @@ def parse_args():
|
||||||
ap.add_argument('-d', '--dry-run', action='store_true', default=False,
|
ap.add_argument('-d', '--dry-run', action='store_true', default=False,
|
||||||
required=False, help='Enable dry-run flag on all Tiller'
|
required=False, help='Enable dry-run flag on all Tiller'
|
||||||
'Calls')
|
'Calls')
|
||||||
|
ap.add_argument('--disable-update-pre', action='store_true', default=False,
|
||||||
|
required=False, help='Disable pre update actions')
|
||||||
|
ap.add_argument('--disable-update-post', action='store_true',
|
||||||
|
default=False, required=False,
|
||||||
|
help='Disable post update actions')
|
||||||
|
|
||||||
return ap.parse_args()
|
return ap.parse_args()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue