Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions kubetools/cli/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def deploy(
app_dirs = (os.getcwd(),)

build = Build(
env=ctx.meta['kube_context'],
context=ctx.meta['kube_context'],
namespace=namespace,
)

Expand Down Expand Up @@ -221,7 +221,7 @@ def remove(ctx, yes, force, do_cleanup, namespace, app_or_project_names):
'''

build = Build(
env=ctx.meta['kube_context'],
context=ctx.meta['kube_context'],
namespace=namespace,
)

Expand Down Expand Up @@ -272,7 +272,7 @@ def cleanup(ctx, yes, namespace):
'''

build = Build(
env=ctx.meta['kube_context'],
context=ctx.meta['kube_context'],
namespace=namespace,
)

Expand Down Expand Up @@ -324,7 +324,7 @@ def restart(ctx, yes, force, namespace, app_or_project_names):
'''

build = Build(
env=ctx.meta['kube_context'],
context=ctx.meta['kube_context'],
namespace=namespace,
)

Expand Down
10 changes: 5 additions & 5 deletions kubetools/cli/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ def show(ctx, namespace, app):

exists = False

env = ctx.meta['kube_context']
context = ctx.meta['kube_context']

if app:
click.echo(f'--> Filtering by app={app}')

services = list_services(env, namespace)
services = list_services(context, namespace)

if services:
exists = True
Expand All @@ -128,7 +128,7 @@ def show(ctx, namespace, app):
})
click.echo()

deployments = list_deployments(env, namespace)
deployments = list_deployments(context, namespace)

if deployments:
exists = True
Expand All @@ -145,7 +145,7 @@ def show(ctx, namespace, app):
click.echo()

if app:
replica_sets = list_replica_sets(env, namespace)
replica_sets = list_replica_sets(context, namespace)
replica_sets = [
r for r in replica_sets
if r.metadata.labels.get(NAME_LABEL_KEY) == app
Expand All @@ -158,7 +158,7 @@ def show(ctx, namespace, app):
})
click.echo()
else:
jobs = list_jobs(env, namespace)
jobs = list_jobs(context, namespace)
if jobs:
exists = True

Expand Down
115 changes: 88 additions & 27 deletions kubetools/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import yaml

from pkg_resources import parse_version
from pkg_resources import parse_version, Requirement

from . import __version__
from .exceptions import KubeConfigError
Expand All @@ -30,9 +30,10 @@ def load_kubetools_config(
directory=None,
app_name=None,
# Filters for config items
env=None,
context=None,
namespace=None,
dev=False, # when true disables env/namespace filtering (dev *only*)
test=False,
custom_config_file=False,
):
'''
Expand All @@ -41,13 +42,13 @@ def load_kubetools_config(
Filtering:
Most config items (deployments, dependencies, upgrades) can have conditions
attached to them (eg dev: true). If an item has conditions, *either* dev or
both env/namespace must match.
both context/namespace must match.

Args:
directory (str): directory to load ther config from (defaults to cwd)
app_name (str): name of the app we're trying to load
env (str): which envrionment to filter the config items by
namespace (str): which namespace to filter the config items by
context (str): which K8s context to filter the config items by
namespace (str): which K8s namespace to filter the config items by
dev (bool): filter config items by dev mode
'''

Expand Down Expand Up @@ -101,22 +102,34 @@ def load_kubetools_config(
config = yaml.safe_load(config)
config['_filename'] = filename

# Check Kubetools version?
config_version = config.get('configVersion', 0)

if 'requireKubetools' in config:
_check_kubetools_version(config['requireKubetools'])

# TODO: remove this in v13, compat w/v12
if 'minKubetoolsVersion' in config:
_check_min_version(config)
if config_version > 0:
raise KubeConfigError((
'`minKubetoolsVersion` is not valid in v1 config files, '
'please use `requireKubetools`!'
))
_check_kubetools_version(f'>={config["minKubetoolsVersion"]}')

# Apply an env name?
if env:
config['env'] = env
if context:
config['context'] = context
config['env'] = context

# Filter out config items according to our conditions
for key in TOP_LEVEL_CONDITION_KEYS:
if key in config:
config[key] = _filter_config_data(
key, config[key],
env=env,
context=context,
namespace=namespace,
dev=dev,
test=test,
use_legacy_conditions=config_version <= 0,
)

# De-nest/apply any contextContexts
Expand All @@ -133,28 +146,39 @@ def load_kubetools_config(
return config


def _check_min_version(config):
def _check_kubetools_version(version_requirement):
running_version = parse_version(__version__)
needed_version = parse_version(
# Version must be a string
str(config['minKubetoolsVersion']),
required_versions = Requirement.parse(
'kubetools{0}'.format(version_requirement),
)

if needed_version > running_version:
raise KubeConfigError(
'Minimum Kubetools version not met, need {0} but got {1}'.format(
needed_version, running_version,
),
)

if running_version not in required_versions:
raise KubeConfigError((
'Kubetools version requirement not met '
'(requires {0}, running {1})'
).format(version_requirement, __version__))


def _filter_config_data(
key,
items_or_object,
context,
namespace,
dev,
test,
use_legacy_conditions=False,
):
condition_checker = (
_legacy_conditions_match if use_legacy_conditions else _conditions_match
)

def _filter_config_data(key, items_or_object, env, namespace, dev):
def is_match(item):
return _conditions_match(
return condition_checker(
item.get('conditions'),
env=env,
context=context,
namespace=namespace,
dev=dev,
test=test,
)

if isinstance(items_or_object, list):
Expand All @@ -177,7 +201,8 @@ def is_match(item):
))


def _conditions_match(conditions, env, namespace, dev):
# TODO: remove this in v13, compat w/v12
def _legacy_conditions_match(conditions, context, namespace, dev, test):
# No conditions? We're good!
if conditions is None:
return True
Expand All @@ -191,7 +216,7 @@ def _conditions_match(conditions, env, namespace, dev):
return False

# If we have envs but our env isn't present, fail!
if 'envs' in conditions and env not in conditions['envs']:
if 'envs' in conditions and context not in conditions['envs']:
return False

# We have namespaces but our namespace isn't present, fail!
Expand All @@ -205,6 +230,42 @@ def _conditions_match(conditions, env, namespace, dev):
return True


def _conditions_match(conditions, context, namespace, dev, test):
if conditions is None:
return True

if dev:
return conditions.get('dev', True) is True

if test:
return conditions.get('test', True) is True

deploy_conditions = conditions.get('deploy', True)
if deploy_conditions is True:
return True

return any(
_condition_matches(condition, context, namespace)
for condition in deploy_conditions
)


def _condition_matches(condition, context, namespace):
if (
'context' in condition and context != condition['context']
or 'not_context' in condition and context == condition['not_context']
):
return False

if (
'namespace' in condition and namespace != condition['namespace']
or 'not_namespace' in condition and namespace == condition['not_namespace']
):
return False

return True


def _expand_containers(key, items_or_object, contexts, dev):
def do_expand(item):
return _expand_container(
Expand Down
4 changes: 2 additions & 2 deletions kubetools/deploy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class Build(object):

in_stage = False

def __init__(self, env, namespace):
self.env = env
def __init__(self, context, namespace):
self.context = context
self.namespace = namespace

def log_info(self, text, extra_detail=None, formatter=lambda s: s):
Expand Down
6 changes: 3 additions & 3 deletions kubetools/deploy/commands/cleanup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# If the cleanup removes all remaining objects, the namespace will be deleted too.

def get_cleanup_objects(build):
replica_sets = list_replica_sets(build.env, build.namespace)
replica_sets = list_replica_sets(build.context, build.namespace)
replica_set_names = set(get_object_name(replica_set) for replica_set in replica_sets)
replica_sets_to_delete = []
replica_set_names_to_delete = set()
Expand All @@ -34,7 +34,7 @@ def get_cleanup_objects(build):
if replica_set.metadata.deletion_timestamp:
replica_set_names_already_deleted.add(get_object_name(replica_set))

pods = list_pods(build.env, build.namespace)
pods = list_pods(build.context, build.namespace)
pod_names = set(get_object_name(pod) for pod in pods)
pods_to_delete = []
pod_names_to_delete = set()
Expand All @@ -54,7 +54,7 @@ def get_cleanup_objects(build):
if pod.metadata.deletion_timestamp:
pod_names_already_deleted.add(get_object_name(pod))

namespaces = list_namespaces(build.env)
namespaces = list_namespaces(build.context)
current_namespace = None
for namespace in namespaces:
if namespace.metadata.name == build.namespace:
Expand Down
Loading