diff --git a/awx/main/management/commands/register_queue.py b/awx/main/management/commands/register_queue.py index 2fa931c88b1c..8f4c56427948 100644 --- a/awx/main/management/commands/register_queue.py +++ b/awx/main/management/commands/register_queue.py @@ -17,13 +17,14 @@ def __init__(self, message, changed, *args, **kwargs): class RegisterQueue: - def __init__(self, queuename, instance_percent, inst_min, hostname_list, is_container_group=None): + def __init__(self, queuename, instance_percent, inst_min, hostname_list, is_container_group=None, pod_spec_override=None): self.instance_not_found_err = None self.queuename = queuename self.instance_percent = instance_percent self.instance_min = inst_min self.hostname_list = hostname_list self.is_container_group = is_container_group + self.pod_spec_override = pod_spec_override def get_create_update_instance_group(self): created = False @@ -40,6 +41,10 @@ def get_create_update_instance_group(self): ig.is_container_group = self.is_container_group changed = True + if self.pod_spec_override and (ig.pod_spec_override != self.pod_spec_override): + ig.pod_spec_override = self.pod_spec_override + changed = True + if changed: ig.save() diff --git a/awx/main/managers.py b/awx/main/managers.py index 7b9164ef32c4..2091c365622c 100644 --- a/awx/main/managers.py +++ b/awx/main/managers.py @@ -179,7 +179,9 @@ def get_or_register(self): else: registered = self.register(ip_address=pod_ip, uuid=settings.SYSTEM_UUID) RegisterQueue(settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME, 100, 0, [], is_container_group=False).register() - RegisterQueue(settings.DEFAULT_EXECUTION_QUEUE_NAME, 100, 0, [], is_container_group=True).register() + RegisterQueue( + settings.DEFAULT_EXECUTION_QUEUE_NAME, 100, 0, [], is_container_group=True, pod_spec_override=settings.DEFAULT_EXECUTION_QUEUE_POD_SPEC_OVERRIDE + ).register() return registered else: return (False, self.me()) diff --git a/awx/main/scheduler/kubernetes.py b/awx/main/scheduler/kubernetes.py index 17b098a77b83..6e36226df556 100644 --- a/awx/main/scheduler/kubernetes.py +++ b/awx/main/scheduler/kubernetes.py @@ -9,29 +9,12 @@ from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ -from awx.main.utils.common import parse_yaml_or_json +from awx.main.utils.common import parse_yaml_or_json, deepmerge from awx.main.utils.execution_environments import get_default_pod_spec logger = logging.getLogger('awx.main.scheduler') -def deepmerge(a, b): - """ - Merge dict structures and return the result. - - >>> a = {'first': {'all_rows': {'pass': 'dog', 'number': '1'}}} - >>> b = {'first': {'all_rows': {'fail': 'cat', 'number': '5'}}} - >>> import pprint; pprint.pprint(deepmerge(a, b)) - {'first': {'all_rows': {'fail': 'cat', 'number': '5', 'pass': 'dog'}}} - """ - if isinstance(a, dict) and isinstance(b, dict): - return dict([(k, deepmerge(a.get(k), b.get(k))) for k in set(a.keys()).union(b.keys())]) - elif b is None: - return a - else: - return b - - class PodManager(object): def __init__(self, task=None): self.task = task @@ -183,7 +166,7 @@ def pod_definition(self): pod_spec_override = {} if self.task and self.task.instance_group.pod_spec_override: pod_spec_override = parse_yaml_or_json(self.task.instance_group.pod_spec_override) - pod_spec = {**default_pod_spec, **pod_spec_override} + pod_spec = deepmerge(default_pod_spec, pod_spec_override) if self.task: pod_spec['metadata'] = deepmerge( diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 9b155123de05..38855ae19198 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -3286,7 +3286,11 @@ def pod_definition(self): pod_spec_override = {} if self.task and self.task.instance.instance_group.pod_spec_override: pod_spec_override = parse_yaml_or_json(self.task.instance.instance_group.pod_spec_override) - pod_spec = {**default_pod_spec, **pod_spec_override} + # According to the deepmerge docstring, the second dictionary will override when + # they share keys, which is the desired behavior. + # This allows user to only provide elements they want to override, and for us to still provide any + # defaults they don't want to change + pod_spec = deepmerge(default_pod_spec, pod_spec_override) pod_spec['spec']['containers'][0]['image'] = ee.image pod_spec['spec']['containers'][0]['args'] = ['ansible-runner', 'worker', '--private-data-dir=/runner'] diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 49ba50efff3b..5fbc0dfd326b 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -986,5 +986,7 @@ def IS_TESTING(argv=None): # Name of the default task queue DEFAULT_EXECUTION_QUEUE_NAME = 'default' +# pod spec used when the default execution queue is a container group, e.g. when deploying on k8s/ocp with the operator +DEFAULT_EXECUTION_QUEUE_POD_SPEC_OVERRIDE = '' # Name of the default controlplane queue DEFAULT_CONTROL_PLANE_QUEUE_NAME = 'controlplane'