diff --git a/ascender/main/dispatch/worker/callback.py b/ascender/main/dispatch/worker/callback.py index 000abfee1..3ec3e96fd 100644 --- a/ascender/main/dispatch/worker/callback.py +++ b/ascender/main/dispatch/worker/callback.py @@ -140,7 +140,7 @@ def toggle_profiling(self, *args): logger.error(f'profiling is disabled, wrote {filepath}') def work_loop(self, *args, **kw): - if settings.AWX_CALLBACK_PROFILE: + if settings.ASCENDER_CALLBACK_PROFILE: signal.signal(signal.SIGUSR1, self.toggle_profiling) return super(CallbackBrokerWorker, self).work_loop(*args, **kw) diff --git a/ascender/main/management/commands/provision_instance.py b/ascender/main/management/commands/provision_instance.py index 40ec857b3..fe32158fe 100644 --- a/ascender/main/management/commands/provision_instance.py +++ b/ascender/main/management/commands/provision_instance.py @@ -30,7 +30,7 @@ def add_arguments(self, parser): def _register_hostname(self, hostname, node_type, uuid): if not hostname: - if not settings.AWX_AUTO_DEPROVISION_INSTANCES: + if not settings.ASCENDER_AUTO_DEPROVISION_INSTANCES: raise CommandError('Registering with values from settings only intended for use in K8s installs') from ascender.main.management.commands.register_queue import RegisterQueue diff --git a/ascender/main/managers.py b/ascender/main/managers.py index 76cdfc049..8479b07d0 100644 --- a/ascender/main/managers.py +++ b/ascender/main/managers.py @@ -197,7 +197,7 @@ def register( ip_address = "" with advisory_lock('instance_registration_%s' % hostname): - if settings.AWX_AUTO_DEPROVISION_INSTANCES: + if settings.ASCENDER_AUTO_DEPROVISION_INSTANCES: # detect any instances with the same IP address. # if one exists, set it to "" if ip_address: diff --git a/ascender/main/models/ha.py b/ascender/main/models/ha.py index 6aaeb0670..53b4a7304 100644 --- a/ascender/main/models/ha.py +++ b/ascender/main/models/ha.py @@ -211,7 +211,7 @@ def consumed_capacity(self): ) if self.node_type in ('hybrid', 'control'): capacity_consumed += ( - settings.AWX_CONTROL_NODE_TASK_IMPACT * UnifiedJob.objects.filter(controller_node=self.hostname, status__in=('running', 'waiting')).count() + settings.ASCENDER_CONTROL_NODE_TASK_IMPACT * UnifiedJob.objects.filter(controller_node=self.hostname, status__in=('running', 'waiting')).count() ) return capacity_consumed diff --git a/ascender/main/models/inventory.py b/ascender/main/models/inventory.py index 3ed02211b..47a7b3d3a 100644 --- a/ascender/main/models/inventory.py +++ b/ascender/main/models/inventory.py @@ -475,7 +475,7 @@ def schedule_deletion(self, user_id=None): delete_inventory.delay(self.pk, user_id) def _update_host_smart_inventory_memeberships(self): - if self.kind == 'smart' and settings.AWX_REBUILD_SMART_MEMBERSHIP: + if self.kind == 'smart' and settings.ASCENDER_REBUILD_SMART_MEMBERSHIP: def on_commit(): from ascender.main.tasks.system import update_host_smart_inventory_memberships @@ -649,7 +649,7 @@ def get_effective_host_name(self): return host_name def _update_host_smart_inventory_memeberships(self): - if settings.AWX_REBUILD_SMART_MEMBERSHIP: + if settings.ASCENDER_REBUILD_SMART_MEMBERSHIP: def on_commit(): from ascender.main.tasks.system import update_host_smart_inventory_memberships diff --git a/ascender/main/notifications/grafana_backend.py b/ascender/main/notifications/grafana_backend.py index 8195c4291..400c4f1e1 100644 --- a/ascender/main/notifications/grafana_backend.py +++ b/ascender/main/notifications/grafana_backend.py @@ -107,7 +107,7 @@ def send_messages(self, messages): json=grafana_data, headers=grafana_headers, verify=(not self.grafana_no_verify_ssl), - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) if r.status_code >= 400: logger.error(smart_str(_("Error sending notification grafana: {}").format(r.status_code))) diff --git a/ascender/main/notifications/mattermost_backend.py b/ascender/main/notifications/mattermost_backend.py index 5a5491166..6edf9d154 100644 --- a/ascender/main/notifications/mattermost_backend.py +++ b/ascender/main/notifications/mattermost_backend.py @@ -49,7 +49,7 @@ def send_messages(self, messages): "{}".format(m.recipients()[0]), json=payload, verify=(not self.mattermost_no_verify_ssl), - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) if r.status_code >= 400: logger.error(smart_str(_("Error sending notification mattermost: {}").format(r.status_code))) diff --git a/ascender/main/notifications/pagerduty_backend.py b/ascender/main/notifications/pagerduty_backend.py index 6d9c34624..a056d1528 100644 --- a/ascender/main/notifications/pagerduty_backend.py +++ b/ascender/main/notifications/pagerduty_backend.py @@ -96,7 +96,7 @@ def send_messages(self, messages): "client": m.from_email, }, headers=get_ascender_http_client_headers(), - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) r.raise_for_status() sent_messages += 1 diff --git a/ascender/main/notifications/rocketchat_backend.py b/ascender/main/notifications/rocketchat_backend.py index 56954a809..64b45dd87 100644 --- a/ascender/main/notifications/rocketchat_backend.py +++ b/ascender/main/notifications/rocketchat_backend.py @@ -47,7 +47,7 @@ def send_messages(self, messages): data=json.dumps(payload), headers=get_ascender_http_client_headers(), verify=(not self.rocketchat_no_verify_ssl), - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) if r.status_code >= 400: diff --git a/ascender/main/notifications/twilio_backend.py b/ascender/main/notifications/twilio_backend.py index 8cbac1741..e088c1205 100644 --- a/ascender/main/notifications/twilio_backend.py +++ b/ascender/main/notifications/twilio_backend.py @@ -51,7 +51,7 @@ def send_messages(self, messages): auth=(self.account_sid, self.account_token), data={"To": dest, "From": m.from_email, "Body": m.subject}, headers=get_ascender_http_client_headers(), - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) r.raise_for_status() sent_messages += 1 diff --git a/ascender/main/notifications/webhook_backend.py b/ascender/main/notifications/webhook_backend.py index 3938dd841..5463d80b2 100644 --- a/ascender/main/notifications/webhook_backend.py +++ b/ascender/main/notifications/webhook_backend.py @@ -95,7 +95,7 @@ def send_messages(self, messages): headers=headers, verify=(not self.disable_ssl_verification), allow_redirects=False, # override default behaviour for redirects - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) # either success or error reached if this conditional fires diff --git a/ascender/main/scheduler/kubernetes.py b/ascender/main/scheduler/kubernetes.py index 02ef4c737..b0885cd38 100644 --- a/ascender/main/scheduler/kubernetes.py +++ b/ascender/main/scheduler/kubernetes.py @@ -157,7 +157,7 @@ def kube_api(self): # in Configuration.__init__. Container group API traffic was never proxied # before that, and on OpenShift the injected cluster-wide proxy makes TLS # verification against the cluster CA fail, so this stays opt-in. - if not settings.AWX_CONTAINER_GROUP_K8S_API_USE_PROXY: + if not settings.ASCENDER_CONTAINER_GROUP_K8S_API_USE_PROXY: cfg.proxy = None cfg.proxy_headers = None diff --git a/ascender/main/scheduler/task_manager.py b/ascender/main/scheduler/task_manager.py index fcf7d192d..b66908fc9 100644 --- a/ascender/main/scheduler/task_manager.py +++ b/ascender/main/scheduler/task_manager.py @@ -74,7 +74,7 @@ def __init__(self, prefix=""): # We want to avoid calling settings in loops, so cache these settings at init time self.start_task_limit = settings.START_TASK_LIMIT self.task_manager_timeout = settings.TASK_MANAGER_TIMEOUT - self.control_task_impact = settings.AWX_CONTROL_NODE_TASK_IMPACT + self.control_task_impact = settings.ASCENDER_CONTROL_NODE_TASK_IMPACT for m in self.subsystem_metrics.METRICS: if m.startswith(self.prefix): diff --git a/ascender/main/scheduler/task_manager_models.py b/ascender/main/scheduler/task_manager_models.py index 1259ff4c8..bad8ebaea 100644 --- a/ascender/main/scheduler/task_manager_models.py +++ b/ascender/main/scheduler/task_manager_models.py @@ -51,7 +51,7 @@ def __init__(self, obj, task_manager_instances=None, **kwargs): self.instance_hostnames = tuple([instance.hostname for instance in _instances if instance.hostname in task_manager_instances]) self.max_concurrent_jobs = obj.max_concurrent_jobs self.max_forks = obj.max_forks - self.control_task_impact = kwargs.get('control_task_impact', settings.AWX_CONTROL_NODE_TASK_IMPACT) + self.control_task_impact = kwargs.get('control_task_impact', settings.ASCENDER_CONTROL_NODE_TASK_IMPACT) def consume_capacity(self, task): """We only consume capacity on an instance group level if it is a container group. Otherwise we consume capacity on an instance level.""" @@ -134,7 +134,7 @@ def __init__(self, instances=None, instance_fields=('node_type', 'capacity', 'ho self.instances_by_hostname = dict() self.instance_groups_container_group_jobs = dict() self.instance_groups_container_group_consumed_forks = dict() - self.control_task_impact = kwargs.get('control_task_impact', settings.AWX_CONTROL_NODE_TASK_IMPACT) + self.control_task_impact = kwargs.get('control_task_impact', settings.ASCENDER_CONTROL_NODE_TASK_IMPACT) if instances is None: instances = ( @@ -170,7 +170,7 @@ def __init__(self, task_manager_instances=None, instance_groups=None, instance_g self.task_manager_instances = task_manager_instances if task_manager_instances is not None else TaskManagerInstances() self.controlplane_ig = None self.pk_ig_map = dict() - self.control_task_impact = kwargs.get('control_task_impact', settings.AWX_CONTROL_NODE_TASK_IMPACT) + self.control_task_impact = kwargs.get('control_task_impact', settings.ASCENDER_CONTROL_NODE_TASK_IMPACT) self.controlplane_ig_name = kwargs.get('controlplane_ig_name', settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME) if instance_groups is not None: # for testing @@ -265,7 +265,7 @@ def get_instance_groups_from_task_cache(self, task): class TaskManagerModels: def __init__(self, **kwargs): # We want to avoid calls to settings over and over in loops, so cache this information here - kwargs['control_task_impact'] = kwargs.get('control_task_impact', settings.AWX_CONTROL_NODE_TASK_IMPACT) + kwargs['control_task_impact'] = kwargs.get('control_task_impact', settings.ASCENDER_CONTROL_NODE_TASK_IMPACT) kwargs['controlplane_ig_name'] = kwargs.get('controlplane_ig_name', settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME) self.instances = TaskManagerInstances(**kwargs) self.instance_groups = TaskManagerInstanceGroups(task_manager_instances=self.instances, **kwargs) diff --git a/ascender/main/tasks/jobs.py b/ascender/main/tasks/jobs.py index 467d23ab6..d5d94c6fb 100644 --- a/ascender/main/tasks/jobs.py +++ b/ascender/main/tasks/jobs.py @@ -572,7 +572,7 @@ def run(self, pk, **kwargs): 'playbook': self.build_playbook_path_relative_to_cwd(self.instance, private_data_dir), 'inventory': self.build_inventory(self.instance, private_data_dir), 'passwords': expect_passwords, - 'suppress_env_files': getattr(settings, 'AWX_RUNNER_OMIT_ENV_FILES', True), + 'suppress_env_files': getattr(settings, 'ASCENDER_RUNNER_OMIT_ENV_FILES', True), 'envvars': env, } @@ -604,7 +604,7 @@ def run(self, pk, **kwargs): runner_settings = { 'job_timeout': self.get_instance_timeout(self.instance), 'suppress_ansible_output': True, - 'suppress_output_file': getattr(settings, 'AWX_RUNNER_SUPPRESS_OUTPUT_FILE', True), + 'suppress_output_file': getattr(settings, 'ASCENDER_RUNNER_SUPPRESS_OUTPUT_FILE', True), } idle_timeout = getattr(settings, 'DEFAULT_JOB_IDLE_TIMEOUT', 0) diff --git a/ascender/main/tasks/receptor.py b/ascender/main/tasks/receptor.py index 099237da0..12c0ecc1f 100644 --- a/ascender/main/tasks/receptor.py +++ b/ascender/main/tasks/receptor.py @@ -475,7 +475,7 @@ def receptor_params(self): receptor_params = { "secret_kube_pod": spec_yaml, - "pod_pending_timeout": getattr(settings, 'AWX_CONTAINER_GROUP_POD_PENDING_TIMEOUT', "5m"), + "pod_pending_timeout": getattr(settings, 'ASCENDER_CONTAINER_GROUP_POD_PENDING_TIMEOUT', "5m"), } if self.credential: diff --git a/ascender/main/tasks/system.py b/ascender/main/tasks/system.py index 4d92b6ed4..ecb667f11 100644 --- a/ascender/main/tasks/system.py +++ b/ascender/main/tasks/system.py @@ -606,7 +606,7 @@ def cluster_node_heartbeat(dispatch_time=None, worker_tasks=None): elif (nowtime - last_last_seen) > timedelta(seconds=settings.CLUSTER_NODE_HEARTBEAT_PERIOD + 2): logger.warning(f'Heartbeat skew - interval={(nowtime - last_last_seen).total_seconds():.4f}, expected={settings.CLUSTER_NODE_HEARTBEAT_PERIOD}') else: - if settings.AWX_AUTO_DEPROVISION_INSTANCES: + if settings.ASCENDER_AUTO_DEPROVISION_INSTANCES: changed, this_inst = Instance.objects.register(ip_address=os.environ.get('MY_POD_IP'), node_type='control', node_uuid=settings.SYSTEM_UUID) if changed: logger.warning(f'Recreated instance record {this_inst.hostname} after unexpected removal') @@ -638,7 +638,7 @@ def cluster_node_heartbeat(dispatch_time=None, worker_tasks=None): except Exception: logger.exception('failed to reap jobs for {}'.format(other_inst.hostname)) try: - if settings.AWX_AUTO_DEPROVISION_INSTANCES and other_inst.node_type == "control": + if settings.ASCENDER_AUTO_DEPROVISION_INSTANCES and other_inst.node_type == "control": deprovision_hostname = other_inst.hostname other_inst.delete() # FIXME: what about associated inbound links? logger.info("Host {} Automatically Deprovisioned.".format(deprovision_hostname)) @@ -721,7 +721,7 @@ def awx_k8s_reaper(): logger.debug('{} is no longer active, reaping orphaned k8s pod'.format(job.log_format)) try: pm = PodManager(job) - pm.kube_api.delete_namespaced_pod(name=pods[job.id], namespace=pm.namespace, _request_timeout=settings.AWX_CONTAINER_GROUP_K8S_API_TIMEOUT) + pm.kube_api.delete_namespaced_pod(name=pods[job.id], namespace=pm.namespace, _request_timeout=settings.ASCENDER_CONTAINER_GROUP_K8S_API_TIMEOUT) except Exception: logger.exception("Failed to delete orphaned pod {} from {}".format(job.log_format, group)) diff --git a/ascender/main/tests/functional/commands/test_provision_instance.py b/ascender/main/tests/functional/commands/test_provision_instance.py index 394528c89..c2935dad9 100644 --- a/ascender/main/tests/functional/commands/test_provision_instance.py +++ b/ascender/main/tests/functional/commands/test_provision_instance.py @@ -27,7 +27,7 @@ def test_register_self_openshift(): assert not Instance.objects.exists() assert not InstanceGroup.objects.exists() - with override_settings(AWX_AUTO_DEPROVISION_INSTANCES=True, CLUSTER_HOST_ID='foo_node', SYSTEM_UUID='12345'): + with override_settings(ASCENDER_AUTO_DEPROVISION_INSTANCES=True, CLUSTER_HOST_ID='foo_node', SYSTEM_UUID='12345'): Command().handle() inst = Instance.objects.first() assert inst.hostname == 'foo_node' diff --git a/ascender/main/tests/functional/task_management/test_container_groups.py b/ascender/main/tests/functional/task_management/test_container_groups.py index b7e2ff874..e3ec557f6 100644 --- a/ascender/main/tests/functional/task_management/test_container_groups.py +++ b/ascender/main/tests/functional/task_management/test_container_groups.py @@ -154,5 +154,5 @@ def test_kube_api_ignores_proxy_environment(containerized_job, default_job_execu assert pm.kube_api.api_client.configuration.proxy is None del pm.__dict__['kube_api'] # drop the cached_property - with override_settings(AWX_CONTAINER_GROUP_K8S_API_USE_PROXY=True): + with override_settings(ASCENDER_CONTAINER_GROUP_K8S_API_USE_PROXY=True): assert pm.kube_api.api_client.configuration.proxy == 'http://proxy.example.com:3128' diff --git a/ascender/main/tests/functional/task_management/test_scheduler.py b/ascender/main/tests/functional/task_management/test_scheduler.py index b52708893..e79f9bf0c 100644 --- a/ascender/main/tests/functional/task_management/test_scheduler.py +++ b/ascender/main/tests/functional/task_management/test_scheduler.py @@ -237,7 +237,7 @@ def test_job_fails_to_launch_when_no_control_capacity(self, job_template, contro def test_hybrid_capacity(self, job_template, hybrid_instance): enough_capacity = job_template.create_unified_job() insufficient_capacity = job_template.create_unified_job() - expected_task_impact = enough_capacity.task_impact + settings.AWX_CONTROL_NODE_TASK_IMPACT + expected_task_impact = enough_capacity.task_impact + settings.ASCENDER_CONTROL_NODE_TASK_IMPACT all_ujs = [enough_capacity, insufficient_capacity] for uj in all_ujs: uj.signal_start() @@ -261,7 +261,7 @@ def test_hybrid_capacity(self, job_template, hybrid_instance): def test_project_update_capacity(self, project, hybrid_instance, instance_group_factory, controlplane_instance_group): pu = project.create_unified_job() instance_group_factory(name='second_ig', instances=[hybrid_instance]) - expected_task_impact = pu.task_impact + settings.AWX_CONTROL_NODE_TASK_IMPACT + expected_task_impact = pu.task_impact + settings.ASCENDER_CONTROL_NODE_TASK_IMPACT pu.signal_start() tm = TaskManager() diff --git a/ascender/main/tests/unit/notifications/test_grafana.py b/ascender/main/tests/unit/notifications/test_grafana.py index d4e426672..7d806e56b 100644 --- a/ascender/main/tests/unit/notifications/test_grafana.py +++ b/ascender/main/tests/unit/notifications/test_grafana.py @@ -33,7 +33,7 @@ def test_send_messages(): headers={'Content-Type': 'application/json', 'Authorization': 'Bearer testapikey'}, json={'text': 'test subject', 'isRegion': True, 'timeEnd': 120000, 'time': 60000}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 @@ -64,7 +64,7 @@ def test_send_messages_with_no_verify_ssl(): headers={'Content-Type': 'application/json', 'Authorization': 'Bearer testapikey'}, json={'text': 'test subject', 'isRegion': True, 'timeEnd': 120000, 'time': 60000}, verify=False, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 @@ -96,7 +96,7 @@ def test_send_messages_with_dashboardid(dashboardId): headers={'Content-Type': 'application/json', 'Authorization': 'Bearer testapikey'}, json={'text': 'test subject', 'isRegion': True, 'timeEnd': 120000, 'time': 60000, 'dashboardId': dashboardId}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 @@ -128,7 +128,7 @@ def test_send_messages_with_panelid(panelId): headers={'Content-Type': 'application/json', 'Authorization': 'Bearer testapikey'}, json={'text': 'test subject', 'isRegion': True, 'timeEnd': 120000, 'panelId': int(panelId), 'time': 60000}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 @@ -159,7 +159,7 @@ def test_send_messages_with_bothids(): headers={'Content-Type': 'application/json', 'Authorization': 'Bearer testapikey'}, json={'text': 'test subject', 'isRegion': True, 'timeEnd': 120000, 'panelId': 42, 'time': 60000, 'dashboardId': 42}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 @@ -190,7 +190,7 @@ def test_send_messages_with_emptyids(): headers={'Content-Type': 'application/json', 'Authorization': 'Bearer testapikey'}, json={'text': 'test subject', 'isRegion': True, 'timeEnd': 120000, 'time': 60000}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 @@ -221,6 +221,6 @@ def test_send_messages_with_tags(): headers={'Content-Type': 'application/json', 'Authorization': 'Bearer testapikey'}, json={'tags': ['ansible'], 'text': 'test subject', 'isRegion': True, 'timeEnd': 120000, 'time': 60000}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 diff --git a/ascender/main/tests/unit/notifications/test_mattermost.py b/ascender/main/tests/unit/notifications/test_mattermost.py index 320d00050..eef5bf2a7 100644 --- a/ascender/main/tests/unit/notifications/test_mattermost.py +++ b/ascender/main/tests/unit/notifications/test_mattermost.py @@ -29,6 +29,6 @@ def test_send_messages(): 'http://example.com', json={'text': 'test subject'}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 diff --git a/ascender/main/tests/unit/notifications/test_rocketchat.py b/ascender/main/tests/unit/notifications/test_rocketchat.py index 80c76cf49..b224bba1f 100644 --- a/ascender/main/tests/unit/notifications/test_rocketchat.py +++ b/ascender/main/tests/unit/notifications/test_rocketchat.py @@ -33,7 +33,7 @@ def test_send_messages(): data='{"text": "test subject"}', headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 @@ -120,6 +120,6 @@ def test_send_messages_with_no_verify_ssl(): data='{"text": "test subject"}', headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=False, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, ) assert sent_messages == 1 diff --git a/ascender/main/tests/unit/notifications/test_webhook.py b/ascender/main/tests/unit/notifications/test_webhook.py index 450c84dfe..a775830f1 100644 --- a/ascender/main/tests/unit/notifications/test_webhook.py +++ b/ascender/main/tests/unit/notifications/test_webhook.py @@ -34,7 +34,7 @@ def test_send_messages_as_POST(): data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'), headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, allow_redirects=False, ) assert sent_messages == 1 @@ -67,7 +67,7 @@ def test_send_messages_as_PUT(): data=json.dumps({'text': 'test body 2'}, ensure_ascii=False).encode('utf-8'), headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, allow_redirects=False, ) assert sent_messages == 1 @@ -100,7 +100,7 @@ def test_send_messages_with_username(): data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'), headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, allow_redirects=False, ) assert sent_messages == 1 @@ -133,7 +133,7 @@ def test_send_messages_with_password(): data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'), headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, allow_redirects=False, ) assert sent_messages == 1 @@ -166,7 +166,7 @@ def test_send_messages_with_username_and_password(): data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'), headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, allow_redirects=False, ) assert sent_messages == 1 @@ -199,7 +199,7 @@ def test_send_messages_with_no_verify_ssl(): data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'), headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=False, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, allow_redirects=False, ) assert sent_messages == 1 @@ -237,7 +237,7 @@ def test_send_messages_with_additional_headers(): 'X-Test-Header2': 'test-content-2', }, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, allow_redirects=False, ) assert sent_messages == 1 @@ -276,7 +276,7 @@ def test_send_messages_with_redirects_ok(): data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'), headers={'Content-Type': 'application/json', 'User-Agent': 'Ascender 0.0.1.dev (open)'}, verify=True, - timeout=settings.AWX_NOTIFICATION_REQUEST_TIMEOUT, + timeout=settings.ASCENDER_NOTIFICATION_REQUEST_TIMEOUT, allow_redirects=False, ) assert sent_messages == 1 diff --git a/ascender/main/tests/unit/settings/test_environment_names.py b/ascender/main/tests/unit/settings/test_environment_names.py new file mode 100644 index 000000000..4d3e12891 --- /dev/null +++ b/ascender/main/tests/unit/settings/test_environment_names.py @@ -0,0 +1,69 @@ +# Copyright (c) 2026 Ascender +# All Rights Reserved. +"""Settings the platform reads from the environment rather than a settings file. + +Four of them, and the alias table in production.py cannot reach any: it runs +after the settings modules have loaded, and two of these decide which settings +file loads at all. So they are read under both names directly. + +The AWX names are what the image, the three installers and anyone's own start +script pass today, which is why they keep answering rather than being given a +release to move in. +""" + +import pytest + +from ascender.settings.environment import environment_setting + + +@pytest.fixture +def clean_env(monkeypatch): + for prefix in ('ASCENDER_', 'AWX_'): + monkeypatch.delenv(prefix + 'LOGGING_MODE', raising=False) + return monkeypatch + + +def test_the_ascender_name_is_read(clean_env): + clean_env.setenv('ASCENDER_LOGGING_MODE', 'stdout') + + assert environment_setting('LOGGING_MODE', 'file') == 'stdout' + + +def test_the_awx_name_is_still_read(clean_env): + """What the image and the installers pass today.""" + clean_env.setenv('AWX_LOGGING_MODE', 'stdout') + + assert environment_setting('LOGGING_MODE', 'file') == 'stdout' + + +def test_the_ascender_name_wins(clean_env): + clean_env.setenv('AWX_LOGGING_MODE', 'stdout') + clean_env.setenv('ASCENDER_LOGGING_MODE', 'file') + + assert environment_setting('LOGGING_MODE', 'file') == 'file' + + +def test_neither_set_falls_back(clean_env): + assert environment_setting('LOGGING_MODE', 'file') == 'file' + + +def test_a_name_that_is_set_but_empty_still_wins(clean_env): + """Exporting an empty value is how a deployment says "not this", and + treating it as unset would quietly ignore that. + """ + clean_env.setenv('ASCENDER_LOGGING_MODE', '') + + assert environment_setting('LOGGING_MODE', 'file') == '' + + +@pytest.mark.parametrize('suffix', ['SETTINGS_FILE', 'SETTINGS_DIR', 'LOGGING_MODE', 'WEB_PROCESS']) +def test_every_environment_setting_is_read_through_the_helper(suffix): + """A direct os.environ.get for one of these would answer to one name only, + which is the bug this file exists to keep out. + """ + import pathlib + + settings_dir = pathlib.Path(environment_setting.__module__.replace('.', '/')).parent + sources = ' '.join(p.read_text() for p in pathlib.Path(settings_dir).glob('*.py') if p.name != 'environment.py') + + assert f"'AWX_{suffix}'" not in sources, f'AWX_{suffix} is read directly rather than through environment_setting' diff --git a/ascender/main/tests/unit/settings/test_logging_mode.py b/ascender/main/tests/unit/settings/test_logging_mode.py index eb2b9a525..a3abb9478 100644 --- a/ascender/main/tests/unit/settings/test_logging_mode.py +++ b/ascender/main/tests/unit/settings/test_logging_mode.py @@ -3,7 +3,7 @@ """ Where the logs go, which is half of one process per container. -AWX_LOGGING_MODE decides it: 'file' writes to /var/log/ascender, which is what a +ASCENDER_LOGGING_MODE decides it: 'file' writes to /var/log/ascender, which is what a VM install wants, and 'stdout' lets the container runtime collect them. The images set stdout, and these hold the settings to that so a handler added later cannot quietly start writing a file nobody reads inside a container. @@ -61,5 +61,5 @@ def test_the_console_is_open_in_the_container_and_gated_on_a_vm(): def test_the_mode_is_checked_rather_than_assumed(): - with pytest.raises(Exception, match="AWX_LOGGING_MODE must be 'file' or 'stdout'"): + with pytest.raises(Exception, match="ASCENDER_LOGGING_MODE must be 'file' or 'stdout'"): build_logging('syslog') diff --git a/ascender/main/utils/execution_environments.py b/ascender/main/utils/execution_environments.py index 1d92b88fa..041bee21a 100644 --- a/ascender/main/utils/execution_environments.py +++ b/ascender/main/utils/execution_environments.py @@ -32,7 +32,7 @@ def get_default_execution_environment(): def get_default_pod_spec(): - job_label: str = settings.AWX_CONTAINER_GROUP_DEFAULT_JOB_LABEL + job_label: str = settings.ASCENDER_CONTAINER_GROUP_DEFAULT_JOB_LABEL ee = get_default_execution_environment() if ee is None: raise RuntimeError("Unable to find an execution environment.") @@ -40,7 +40,7 @@ def get_default_pod_spec(): return { "apiVersion": "v1", "kind": "Pod", - "metadata": {"namespace": settings.AWX_CONTAINER_GROUP_DEFAULT_NAMESPACE, "labels": {job_label: ""}}, + "metadata": {"namespace": settings.ASCENDER_CONTAINER_GROUP_DEFAULT_NAMESPACE, "labels": {job_label: ""}}, "spec": { "serviceAccountName": "default", "automountServiceAccountToken": False, diff --git a/ascender/settings/connection_reuse.py b/ascender/settings/connection_reuse.py index ee388a812..c6dc85886 100644 --- a/ascender/settings/connection_reuse.py +++ b/ascender/settings/connection_reuse.py @@ -1,4 +1,4 @@ -import os +from ascender.settings.environment import environment_setting # Django's default is 0: open a connection for each request and close it when # the response is sent. For a process that serves one request after another @@ -22,7 +22,7 @@ def is_web_process(): supervisor programs set, and which is what will answer it if the server ever becomes daphne or uvicorn. ''' - if os.environ.get('AWX_WEB_PROCESS'): + if environment_setting('WEB_PROCESS'): return True try: import uwsgi # noqa: F401 diff --git a/ascender/settings/defaults.py b/ascender/settings/defaults.py index 8054d7dfe..43088ee1f 100644 --- a/ascender/settings/defaults.py +++ b/ascender/settings/defaults.py @@ -14,6 +14,7 @@ # python-ldap import ldap +from ascender.settings.environment import environment_setting DEBUG = True SQL_DEBUG = DEBUG @@ -98,7 +99,7 @@ # the K8S cluster where awx itself is running) IS_K8S = False -AWX_CONTAINER_GROUP_K8S_API_TIMEOUT = 10 +ASCENDER_CONTAINER_GROUP_K8S_API_TIMEOUT = 10 # Whether container group Kubernetes API calls should be routed through the # HTTP_PROXY/HTTPS_PROXY environment variables of the task container. The Python # Kubernetes client started honouring those on its own in 34.1, but this traffic @@ -106,14 +107,14 @@ # verification against the cluster CA (the client verifies against the cluster # credential's CA data or the service account CA, never the system trust store). # Leave disabled unless the cluster API really is only reachable through a proxy. -AWX_CONTAINER_GROUP_K8S_API_USE_PROXY = False -AWX_CONTAINER_GROUP_DEFAULT_NAMESPACE = os.getenv('MY_POD_NAMESPACE', 'default') -AWX_CONTAINER_GROUP_DEFAULT_JOB_LABEL = os.getenv('AWX_CONTAINER_GROUP_DEFAULT_JOB_LABEL', 'ansible_job') +ASCENDER_CONTAINER_GROUP_K8S_API_USE_PROXY = False +ASCENDER_CONTAINER_GROUP_DEFAULT_NAMESPACE = os.getenv('MY_POD_NAMESPACE', 'default') +ASCENDER_CONTAINER_GROUP_DEFAULT_JOB_LABEL = os.getenv('ASCENDER_CONTAINER_GROUP_DEFAULT_JOB_LABEL', 'ansible_job') # Timeout when waiting for pod to enter running state. If the pod is still in pending state , it will be terminated. Valid time units are "s", "m", "h". Example : "5m" , "10s". -AWX_CONTAINER_GROUP_POD_PENDING_TIMEOUT = "2h" +ASCENDER_CONTAINER_GROUP_POD_PENDING_TIMEOUT = "2h" # How much capacity controlling a task costs a hybrid or control node -AWX_CONTROL_NODE_TASK_IMPACT = 1 +ASCENDER_CONTROL_NODE_TASK_IMPACT = 1 # Internationalization # https://docs.djangoproject.com/en/dev/topics/i18n/ @@ -337,7 +338,7 @@ # Without it the dispatcher worker running send_notifications is held for as # long as the far end keeps the connection open. Matches the default timeout of # the email backend. -AWX_NOTIFICATION_REQUEST_TIMEOUT = 30 +ASCENDER_NOTIFICATION_REQUEST_TIMEOUT = 30 # Time out task managers if they take longer than this many seconds, plus TASK_MANAGER_TIMEOUT_GRACE_PERIOD # We have the grace period so the task manager can bail out before the timeout. @@ -766,7 +767,7 @@ GALAXY_TASK_ENV = {'ANSIBLE_FORCE_COLOR': 'false', 'GIT_SSH_COMMAND': "ssh -o StrictHostKeyChecking=no"} # Rebuild Host Smart Inventory memberships. -AWX_REBUILD_SMART_MEMBERSHIP = False +ASCENDER_REBUILD_SMART_MEMBERSHIP = False # By default, allow arbitrary Jinja templating in extra_vars defined on a Job Template ALLOW_JINJA_IN_EXTRA_VARS = 'template' @@ -817,7 +818,7 @@ ASCENDER_ANSIBLE_CALLBACK_PLUGINS = "" # Automatically remove nodes that have missed their heartbeats after some time -AWX_AUTO_DEPROVISION_INSTANCES = False +ASCENDER_AUTO_DEPROVISION_INSTANCES = False # Enable Pendo on the UI, possible values are 'off', 'anonymous', and 'detailed' # Note: This setting may be overridden by database settings. @@ -1100,9 +1101,9 @@ } # If running on a VM, we log to files. When running in a container, we log to stdout. -logging_mode = os.getenv('AWX_LOGGING_MODE', 'file') +logging_mode = environment_setting('LOGGING_MODE', 'file') if logging_mode not in ('file', 'stdout'): - raise Exception("AWX_LOGGING_MODE must be 'file' or 'stdout'") + raise Exception("ASCENDER_LOGGING_MODE must be 'file' or 'stdout'") for name, config in handler_config.items(): # Common log handler config. Don't define a level here, it's set by settings.LOG_AGGREGATOR_LEVEL @@ -1140,20 +1141,20 @@ # ~ yum install graphviz # ~ dot -o profile.png -Tpng /var/log/ascender/profile/some-profile-data.dot # -AWX_REQUEST_PROFILE_WITH_DOT = False +ASCENDER_REQUEST_PROFILE_WITH_DOT = False # Allow profiling callback workers via SIGUSR1 -AWX_CALLBACK_PROFILE = False +ASCENDER_CALLBACK_PROFILE = False # Delete temporary directories created to store playbook run-time ASCENDER_CLEANUP_PATHS = True # Allow ansible-runner to store env folder (may contain sensitive information) -AWX_RUNNER_OMIT_ENV_FILES = True +ASCENDER_RUNNER_OMIT_ENV_FILES = True # Allow ansible-runner to save ansible output # (changing to False may cause performance issues) -AWX_RUNNER_SUPPRESS_OUTPUT_FILE = True +ASCENDER_RUNNER_SUPPRESS_OUTPUT_FILE = True # https://github.com/ansible/ansible-runner/pull/1191/files # Interval in seconds between the last message and keep-alive messages that diff --git a/ascender/settings/development.py b/ascender/settings/development.py index d0e43ccf9..16b776a83 100644 --- a/ascender/settings/development.py +++ b/ascender/settings/development.py @@ -55,7 +55,7 @@ CLUSTER_HOST_ID = socket.gethostname() -AWX_CALLBACK_PROFILE = True +ASCENDER_CALLBACK_PROFILE = True # ======================!!!!!!! FOR DEVELOPMENT ONLY !!!!!!!================================= # Disable normal scheduled/triggered task managers (DependencyManager, TaskManager, WorkflowManager). diff --git a/ascender/settings/environment.py b/ascender/settings/environment.py new file mode 100644 index 000000000..fb1b0a9a8 --- /dev/null +++ b/ascender/settings/environment.py @@ -0,0 +1,32 @@ +# Copyright (c) 2026 Ascender +# All Rights Reserved. +"""Settings read from the environment, under either name. + +A handful of settings are read from the environment rather than from a settings +file, so the alias table in production.py cannot reach them: that table runs +after the settings modules have loaded, and two of these decide which settings +file loads at all. + +The Ascender name wins, the AWX one still answers, and the AWX one is what the +image, the installers and anyone's own start script pass today. They move when +it suits them rather than on the day of this change. +""" + +import os + +ASCENDER = 'ASCENDER_' +FORMER = 'AWX_' + + +def environment_setting(suffix, default=None): + """The `ASCENDER_` variable if set, else `AWX_`, else `default`. + + A name that is set but empty wins over the later one, matching what a plain + `os.environ.get(name, other)` chain did: exporting an empty value is how a + deployment says "not this", and treating it as unset would ignore that. + """ + for prefix in (ASCENDER, FORMER): + name = prefix + suffix + if name in os.environ: + return os.environ[name] + return default diff --git a/ascender/settings/production.py b/ascender/settings/production.py index 862dabb26..ebba78e2b 100644 --- a/ascender/settings/production.py +++ b/ascender/settings/production.py @@ -15,6 +15,7 @@ # Load default settings. from .defaults import * # NOQA +from ascender.settings.environment import environment_setting DEBUG = False TEMPLATE_DEBUG = DEBUG @@ -56,12 +57,12 @@ # Load settings from any .py files in the global conf.d directory specified in # the environment, defaulting to /etc/tower/conf.d/. -settings_dir = os.environ.get('AWX_SETTINGS_DIR', '/etc/tower/conf.d/') +settings_dir = environment_setting('SETTINGS_DIR', '/etc/tower/conf.d/') settings_files = os.path.join(settings_dir, '*.py') # Load remaining settings from the global settings file specified in the # environment, defaulting to /etc/tower/settings.py. -settings_file = os.environ.get('AWX_SETTINGS_FILE', '/etc/tower/settings.py') +settings_file = environment_setting('SETTINGS_FILE', '/etc/tower/settings.py') # Attempt to load settings from /etc/tower/settings.py first, followed by # /etc/tower/conf.d/*.py. @@ -87,7 +88,7 @@ LOGGING = {} else: msg = 'No AWX configuration found at %s.' % settings_file - msg += '\nDefine the AWX_SETTINGS_FILE environment variable to ' + msg += '\nDefine the ASCENDER_SETTINGS_FILE environment variable to ' msg += 'specify an alternate path.' raise ImproperlyConfigured(msg) else: @@ -135,6 +136,19 @@ 'AWX_RUNNER_KEEPALIVE_SECONDS': 'ASCENDER_RUNNER_KEEPALIVE_SECONDS', 'AWX_SHOW_PLAYBOOK_LINKS': 'ASCENDER_SHOW_PLAYBOOK_LINKS', 'AWX_TASK_ENV': 'ASCENDER_TASK_ENV', + 'AWX_AUTO_DEPROVISION_INSTANCES': 'ASCENDER_AUTO_DEPROVISION_INSTANCES', + 'AWX_CALLBACK_PROFILE': 'ASCENDER_CALLBACK_PROFILE', + 'AWX_CONTAINER_GROUP_DEFAULT_JOB_LABEL': 'ASCENDER_CONTAINER_GROUP_DEFAULT_JOB_LABEL', + 'AWX_CONTAINER_GROUP_DEFAULT_NAMESPACE': 'ASCENDER_CONTAINER_GROUP_DEFAULT_NAMESPACE', + 'AWX_CONTAINER_GROUP_K8S_API_TIMEOUT': 'ASCENDER_CONTAINER_GROUP_K8S_API_TIMEOUT', + 'AWX_CONTAINER_GROUP_K8S_API_USE_PROXY': 'ASCENDER_CONTAINER_GROUP_K8S_API_USE_PROXY', + 'AWX_CONTAINER_GROUP_POD_PENDING_TIMEOUT': 'ASCENDER_CONTAINER_GROUP_POD_PENDING_TIMEOUT', + 'AWX_CONTROL_NODE_TASK_IMPACT': 'ASCENDER_CONTROL_NODE_TASK_IMPACT', + 'AWX_NOTIFICATION_REQUEST_TIMEOUT': 'ASCENDER_NOTIFICATION_REQUEST_TIMEOUT', + 'AWX_REBUILD_SMART_MEMBERSHIP': 'ASCENDER_REBUILD_SMART_MEMBERSHIP', + 'AWX_REQUEST_PROFILE_WITH_DOT': 'ASCENDER_REQUEST_PROFILE_WITH_DOT', + 'AWX_RUNNER_OMIT_ENV_FILES': 'ASCENDER_RUNNER_OMIT_ENV_FILES', + 'AWX_RUNNER_SUPPRESS_OUTPUT_FILE': 'ASCENDER_RUNNER_SUPPRESS_OUTPUT_FILE', } for _former, _current in _FORMER_NAMES.items(): _scope = locals() diff --git a/ascender/settings/statement_timeout.py b/ascender/settings/statement_timeout.py index 5f2070a06..3e8942316 100644 --- a/ascender/settings/statement_timeout.py +++ b/ascender/settings/statement_timeout.py @@ -1,4 +1,4 @@ -import os +from ascender.settings.environment import environment_setting # What the uwsgi path used to work out to: harakiri of 115 seconds less a five # second margin. uvicorn serves the web process now and uwsgi is no longer @@ -39,7 +39,7 @@ def set_statement_timeout(DATABASES, DATABASE_STATEMENT_TIMEOUT=None): except (ImportError, ValueError, TypeError): pass - if timeout_ms is None and os.environ.get('AWX_WEB_PROCESS'): + if timeout_ms is None and environment_setting('WEB_PROCESS'): # a web process that is not uwsgi: same protection, explicit source timeout_ms = DATABASE_STATEMENT_TIMEOUT if DATABASE_STATEMENT_TIMEOUT is not None else DEFAULT_WEB_TIMEOUT_MS diff --git a/ascender/settings/typed.py b/ascender/settings/typed.py index 7d6cffc49..6eabf087c 100644 --- a/ascender/settings/typed.py +++ b/ascender/settings/typed.py @@ -49,10 +49,18 @@ class AscenderSettings(Protocol): API_400_ERROR_LOG_FORMAT: str APPEND_SLASH: bool ASCENDER_ANSIBLE_CALLBACK_PLUGINS: list[Any] + ASCENDER_AUTO_DEPROVISION_INSTANCES: bool ASCENDER_AUTO_STATS_ENABLED: bool ASCENDER_AUTO_STATS_MAX_HOSTS: int + ASCENDER_CALLBACK_PROFILE: bool ASCENDER_CLEANUP_PATHS: bool ASCENDER_COLLECTIONS_ENABLED: bool + ASCENDER_CONTAINER_GROUP_DEFAULT_JOB_LABEL: str + ASCENDER_CONTAINER_GROUP_DEFAULT_NAMESPACE: str + ASCENDER_CONTAINER_GROUP_K8S_API_TIMEOUT: int + ASCENDER_CONTAINER_GROUP_K8S_API_USE_PROXY: bool + ASCENDER_CONTAINER_GROUP_POD_PENDING_TIMEOUT: str + ASCENDER_CONTROL_NODE_TASK_IMPACT: int ASCENDER_ENABLED_VALUE: str ASCENDER_ENABLED_VAR: str ASCENDER_EXCLUDE_EMPTY_GROUPS: bool @@ -60,9 +68,14 @@ class AscenderSettings(Protocol): ASCENDER_ISOLATION_BASE_PATH: str ASCENDER_ISOLATION_SHOW_PATHS: list[Any] ASCENDER_MOUNT_ISOLATED_PATHS_ON_K8S: bool + ASCENDER_NOTIFICATION_REQUEST_TIMEOUT: int + ASCENDER_REBUILD_SMART_MEMBERSHIP: bool ASCENDER_REQUEST_PROFILE: bool + ASCENDER_REQUEST_PROFILE_WITH_DOT: bool ASCENDER_ROLES_ENABLED: bool ASCENDER_RUNNER_KEEPALIVE_SECONDS: int + ASCENDER_RUNNER_OMIT_ENV_FILES: bool + ASCENDER_RUNNER_SUPPRESS_OUTPUT_FILE: bool ASCENDER_SHOW_PLAYBOOK_LINKS: bool ASCENDER_TASK_ENV: dict[Any, Any] ASCENDER_URL_BASE: str @@ -171,20 +184,7 @@ class AscenderSettings(Protocol): AUTOMATION_ANALYTICS_LAST_ENTRIES: str AUTOMATION_ANALYTICS_LAST_GATHER: Any AUTOMATION_ANALYTICS_URL: str - AWX_AUTO_DEPROVISION_INSTANCES: bool - AWX_CALLBACK_PROFILE: bool - AWX_CONTAINER_GROUP_DEFAULT_JOB_LABEL: str - AWX_CONTAINER_GROUP_DEFAULT_NAMESPACE: str - AWX_CONTAINER_GROUP_K8S_API_TIMEOUT: int - AWX_CONTAINER_GROUP_K8S_API_USE_PROXY: bool - AWX_CONTAINER_GROUP_POD_PENDING_TIMEOUT: str - AWX_CONTROL_NODE_TASK_IMPACT: int AWX_DISABLE_TASK_MANAGERS: bool - AWX_NOTIFICATION_REQUEST_TIMEOUT: int - AWX_REBUILD_SMART_MEMBERSHIP: bool - AWX_REQUEST_PROFILE_WITH_DOT: bool - AWX_RUNNER_OMIT_ENV_FILES: bool - AWX_RUNNER_SUPPRESS_OUTPUT_FILE: bool AZURE_RM_ENABLED_VALUE: str AZURE_RM_ENABLED_VAR: str AZURE_RM_EXCLUDE_EMPTY_GROUPS: bool diff --git a/docs/capacity.md b/docs/capacity.md index b50431c3b..4d48c79c5 100644 --- a/docs/capacity.md +++ b/docs/capacity.md @@ -92,15 +92,15 @@ Other job types have a fixed execution impact: * Project Updates: 1 * System Jobs: 5 -For jobs that execute on the same node as they are controlled by, both settings.AWX_CONTROL_NODE_TASK_IMPACT and the job task execution impact apply. +For jobs that execute on the same node as they are controlled by, both settings.ASCENDER_CONTROL_NODE_TASK_IMPACT and the job task execution impact apply. Examples: -Given settings.AWX_CONTROL_NODE_TASK_IMPACT is 1: +Given settings.ASCENDER_CONTROL_NODE_TASK_IMPACT is 1: - Project updates (where the execution_node is always the same as the controller_node), have a total impact of 2. - Container group jobs (where the execution node is not a member of the cluster) only control impact applies, and the controller node has a total task impact of 1. - A job executing on a "hybrid" node where both control and execution will occur on the same node has the task impact of (1 overhead for ansible main process) + (min(forks,hosts)) + (1 control node task impact). Meaning a Job running on a hybrid node with forks set to 1 would have a total task impact of 3. -### Selecting the Right settings.AWX_CONTROL_NODE_TASK_IMPACT +### Selecting the Right settings.ASCENDER_CONTROL_NODE_TASK_IMPACT This setting allows you to determine how much impact controlling jobs has. This can be helpful if you notice symptoms of your control plane exceeding desired diff --git a/docs/deprecated/inventory_refresh.md b/docs/deprecated/inventory_refresh.md index 9c021ab1d..de2e27656 100644 --- a/docs/deprecated/inventory_refresh.md +++ b/docs/deprecated/inventory_refresh.md @@ -52,7 +52,7 @@ are generated by the `update_host_smart_inventory_memberships` task. The task is * Existing Host is changed (update/delete). * New Smart Inventory is added. * Existing Smart Inventory is changed (update/delete). - * **NOTE:** This task is only run if the `AWX_REBUILD_SMART_MEMBERSHIP` is set to `True`. It defaults to `False`. + * **NOTE:** This task is only run if the `ASCENDER_REBUILD_SMART_MEMBERSHIP` is set to `True`. It defaults to `False`. ### Smart Filter (`host_filter`) The `SmartFilter` class handles our translation of the smart search string. We store the diff --git a/docs/docsite/rst/userguide/inventories.rst b/docs/docsite/rst/userguide/inventories.rst index 219030e4d..d367ff2b8 100644 --- a/docs/docsite/rst/userguide/inventories.rst +++ b/docs/docsite/rst/userguide/inventories.rst @@ -72,7 +72,7 @@ The ``host`` model has a related endpoint, ``smart_inventories`` that identifies .. note:: - To update the memberships more frequently, you can change the file-based setting ``AWX_REBUILD_SMART_MEMBERSHIP`` to **True** (default is False). This will update memberships in the following events: + To update the memberships more frequently, you can change the file-based setting ``ASCENDER_REBUILD_SMART_MEMBERSHIP`` to **True** (default is False). This will update memberships in the following events: - a new host is added - an existing host is modified (updated or deleted) diff --git a/docs/tasks.md b/docs/tasks.md index a8c5b055f..7c8432c55 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -245,7 +245,7 @@ Running the Update Inventory Computed Fields task in the background, in response The `smart_inventories` field in Ascender uses a membership lookup table that identifies the set of every Smart Inventory a host is associated with. This particular task generates memberships and is launched whenever certain conditions are met (_e.g._, a new host is added or an existing host is modified). -An important thing to note is that this task is only run if the `AWX_REBUILD_SMART_MEMBERSHIP` is set to `True` (default is `False`). +An important thing to note is that this task is only run if the `ASCENDER_REBUILD_SMART_MEMBERSHIP` is set to `True` (default is `False`). For more information, visit the [Smart Inventories section](https://docs.ansible.com/ansible-tower/latest/html/userguide/inventories.html#smart-inventories) of the Tower User Guide's "Inventory" page or the Ascender documentation page [Inventory Refresh Overview page](github.com/ctrliq/ascender/blob/main/docs/inventory_refresh.md#inventory-changes) in this repo.