Skip to content

Commit

Permalink
Merge branch 'devel' into feature_hop-node
Browse files Browse the repository at this point in the history
  • Loading branch information
fosterseth authored Jul 13, 2023
2 parents 817789a + 8cfb704 commit dbeacf9
Show file tree
Hide file tree
Showing 73 changed files with 1,657 additions and 175 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/label_issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

steps:
- name: Label Issue
uses: github/issue-labeler@v2.4.1
uses: github/issue-labeler@v3.1
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
not-before: 2021-12-07T07:00:00Z
Expand Down
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ COLLECTION_TEMPLATE_VERSION ?= false
# NOTE: This defaults the container image version to the branch that's active
COMPOSE_TAG ?= $(GIT_BRANCH)
MAIN_NODE_TYPE ?= hybrid
# If set to true docker-compose will also start a pgbouncer instance and use it
PGBOUNCER ?= false
# If set to true docker-compose will also start a keycloak instance
KEYCLOAK ?= false
# If set to true docker-compose will also start an ldap instance
Expand All @@ -37,6 +39,8 @@ SPLUNK ?= false
PROMETHEUS ?= false
# If set to true docker-compose will also start a grafana instance
GRAFANA ?= false
# If set to true docker-compose will also start a hashicorp vault instance
VAULT ?= false
# If set to true docker-compose will also start a tacacs+ instance
TACACS ?= false

Expand Down Expand Up @@ -520,15 +524,20 @@ docker-compose-sources: .git/hooks/pre-commit
-e control_plane_node_count=$(CONTROL_PLANE_NODE_COUNT) \
-e execution_node_count=$(EXECUTION_NODE_COUNT) \
-e minikube_container_group=$(MINIKUBE_CONTAINER_GROUP) \
-e enable_pgbouncer=$(PGBOUNCER) \
-e enable_keycloak=$(KEYCLOAK) \
-e enable_ldap=$(LDAP) \
-e enable_splunk=$(SPLUNK) \
-e enable_prometheus=$(PROMETHEUS) \
-e enable_grafana=$(GRAFANA) \
-e enable_vault=$(VAULT) \
-e enable_tacacs=$(TACACS) \
$(EXTRA_SOURCES_ANSIBLE_OPTS)

docker-compose: awx/projects docker-compose-sources
ansible-galaxy install --ignore-certs -r tools/docker-compose/ansible/requirements.yml;
ansible-playbook -i tools/docker-compose/inventory tools/docker-compose/ansible/initialize_containers.yml \
-e enable_vault=$(VAULT);
$(DOCKER_COMPOSE) -f tools/docker-compose/_sources/docker-compose.yml $(COMPOSE_OPTS) up $(COMPOSE_UP_OPTS) --remove-orphans

docker-compose-credential-plugins: awx/projects docker-compose-sources
Expand Down Expand Up @@ -580,7 +589,7 @@ docker-clean:
-$(foreach image_id,$(shell docker images --filter=reference='*/*/*awx_devel*' --filter=reference='*/*awx_devel*' --filter=reference='*awx_devel*' -aq),docker rmi --force $(image_id);)

docker-clean-volumes: docker-compose-clean docker-compose-container-group-clean
docker volume rm -f tools_awx_db tools_grafana_storage tools_prometheus_storage $(docker volume ls --filter name=tools_redis_socket_ -q)
docker volume rm -f tools_awx_db tools_vault_1 tools_grafana_storage tools_prometheus_storage $(docker volume ls --filter name=tools_redis_socket_ -q)

docker-refresh: docker-clean docker-compose

Expand Down
4 changes: 2 additions & 2 deletions awx/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1629,8 +1629,8 @@ class Meta:
fields = ('*', 'host_status_counts', 'playbook_counts')

def get_playbook_counts(self, obj):
task_count = obj.project_update_events.filter(event='playbook_on_task_start').count()
play_count = obj.project_update_events.filter(event='playbook_on_play_start').count()
task_count = obj.get_event_queryset().filter(event='playbook_on_task_start').count()
play_count = obj.get_event_queryset().filter(event='playbook_on_play_start').count()

data = {'play_count': play_count, 'task_count': task_count}

Expand Down
5 changes: 2 additions & 3 deletions awx/api/urls/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
OAuth2TokenList,
ApplicationOAuth2TokenList,
OAuth2ApplicationDetail,
# HostMetricSummaryMonthlyList, # It will be enabled in future version of the AWX
HostMetricSummaryMonthlyList,
)

from awx.api.views.bulk import (
Expand Down Expand Up @@ -124,8 +124,7 @@
re_path(r'^constructed_inventories/', include(constructed_inventory_urls)),
re_path(r'^hosts/', include(host_urls)),
re_path(r'^host_metrics/', include(host_metric_urls)),
# It will be enabled in future version of the AWX
# re_path(r'^host_metric_summary_monthly/$', HostMetricSummaryMonthlyList.as_view(), name='host_metric_summary_monthly_list'),
re_path(r'^host_metric_summary_monthly/$', HostMetricSummaryMonthlyList.as_view(), name='host_metric_summary_monthly_list'),
re_path(r'^groups/', include(group_urls)),
re_path(r'^inventory_sources/', include(inventory_source_urls)),
re_path(r'^inventory_updates/', include(inventory_update_urls)),
Expand Down
19 changes: 9 additions & 10 deletions awx/api/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1565,16 +1565,15 @@ def delete(self, request, *args, **kwargs):
return Response(status=status.HTTP_204_NO_CONTENT)


# It will be enabled in future version of the AWX
# class HostMetricSummaryMonthlyList(ListAPIView):
# name = _("Host Metrics Summary Monthly")
# model = models.HostMetricSummaryMonthly
# serializer_class = serializers.HostMetricSummaryMonthlySerializer
# permission_classes = (IsSystemAdminOrAuditor,)
# search_fields = ('date',)
#
# def get_queryset(self):
# return self.model.objects.all()
class HostMetricSummaryMonthlyList(ListAPIView):
name = _("Host Metrics Summary Monthly")
model = models.HostMetricSummaryMonthly
serializer_class = serializers.HostMetricSummaryMonthlySerializer
permission_classes = (IsSystemAdminOrAuditor,)
search_fields = ('date',)

def get_queryset(self):
return self.model.objects.all()


class HostList(HostRelatedSearchMixin, ListCreateAPIView):
Expand Down
5 changes: 5 additions & 0 deletions awx/api/views/bulk.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from collections import OrderedDict

from django.utils.translation import gettext_lazy as _

from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer
from rest_framework.reverse import reverse
Expand All @@ -18,6 +20,9 @@


class BulkView(APIView):
name = _('Bulk')
swagger_topic = 'Bulk'

permission_classes = [IsAuthenticated]
renderer_classes = [
renderers.BrowsableAPIRenderer,
Expand Down
3 changes: 1 addition & 2 deletions awx/api/views/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ def get(self, request, format=None):
data['groups'] = reverse('api:group_list', request=request)
data['hosts'] = reverse('api:host_list', request=request)
data['host_metrics'] = reverse('api:host_metric_list', request=request)
# It will be enabled in future version of the AWX
# data['host_metric_summary_monthly'] = reverse('api:host_metric_summary_monthly_list', request=request)
data['host_metric_summary_monthly'] = reverse('api:host_metric_summary_monthly_list', request=request)
data['job_templates'] = reverse('api:job_template_list', request=request)
data['jobs'] = reverse('api:job_list', request=request)
data['ad_hoc_commands'] = reverse('api:ad_hoc_command_list', request=request)
Expand Down
2 changes: 1 addition & 1 deletion awx/conf/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ConfConfig(AppConfig):
def ready(self):
self.module.autodiscover()

if not set(sys.argv) & {'migrate', 'check_migrations'}:
if not set(sys.argv) & {'migrate', 'check_migrations', 'showmigrations'}:
from .settings import SettingsWrapper

SettingsWrapper.initialize()
23 changes: 23 additions & 0 deletions awx/main/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@
category_slug='system',
)

register(
'CSRF_TRUSTED_ORIGINS',
default=[],
field_class=fields.StringListField,
label=_('CSRF Trusted Origins List'),
help_text=_(
"If the service is behind a reverse proxy/load balancer, use this setting "
"to configure the schema://addresses from which the service should trust "
"Origin header values. "
),
category=_('System'),
category_slug='system',
)

register(
'LICENSE',
field_class=fields.DictField,
Expand Down Expand Up @@ -848,6 +862,15 @@
category_slug='system',
)

register(
'HOST_METRIC_SUMMARY_TASK_LAST_TS',
field_class=fields.DateTimeField,
label=_('Last computing date of HostMetricSummaryMonthly'),
allow_null=True,
category=_('System'),
category_slug='system',
)

register(
'AWX_CLEANUP_PATHS',
field_class=fields.BooleanField,
Expand Down
2 changes: 2 additions & 0 deletions awx/main/credential_plugins/hashivault.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ def kv_backend(**kwargs):

if secret_key:
try:
if (secret_key != 'data') and (secret_key not in json['data']) and ('data' in json['data']):
return json['data']['data'][secret_key]
return json['data'][secret_key]
except KeyError:
raise RuntimeError('{} is not present at {}'.format(secret_key, secret_path))
Expand Down
19 changes: 18 additions & 1 deletion awx/main/dispatch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@ def notify(self, channel, payload):
with self.conn.cursor() as cur:
cur.execute('SELECT pg_notify(%s, %s);', (channel, payload))

@staticmethod
def current_notifies(conn):
"""
Altered version of .notifies method from psycopg library
This removes the outer while True loop so that we only process
queued notifications
"""
with conn.lock:
try:
ns = conn.wait(psycopg.generators.notifies(conn.pgconn))
except psycopg.errors._NO_TRACEBACK as ex:
raise ex.with_traceback(None)
enc = psycopg._encodings.pgconn_encoding(conn.pgconn)
for pgn in ns:
n = psycopg.connection.Notify(pgn.relname.decode(enc), pgn.extra.decode(enc), pgn.be_pid)
yield n

def events(self, select_timeout=5, yield_timeouts=False):
if not self.conn.autocommit:
raise RuntimeError('Listening for events can only be done in autocommit mode')
Expand All @@ -64,7 +81,7 @@ def events(self, select_timeout=5, yield_timeouts=False):
if yield_timeouts:
yield None
else:
notification_generator = self.conn.notifies()
notification_generator = self.current_notifies(self.conn)
for notification in notification_generator:
yield notification

Expand Down
2 changes: 1 addition & 1 deletion awx/main/management/commands/cleanup_host_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ def handle(self, *args, **options):
months_ago = options.get('months-ago') or None

if not months_ago:
months_ago = getattr(settings, 'CLEANUP_HOST_METRICS_THRESHOLD', 12)
months_ago = getattr(settings, 'CLEANUP_HOST_METRICS_SOFT_THRESHOLD', 12)

HostMetric.cleanup_task(months_ago)
9 changes: 9 additions & 0 deletions awx/main/management/commands/host_metric_summary_monthly.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.core.management.base import BaseCommand
from awx.main.tasks.host_metrics import HostMetricSummaryMonthlyTask


class Command(BaseCommand):
help = 'Computing of HostMetricSummaryMonthly'

def handle(self, *args, **options):
HostMetricSummaryMonthlyTask().execute()
6 changes: 3 additions & 3 deletions awx/main/models/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -899,18 +899,18 @@ def cleanup_task(cls, months_ago):

last_automation_before = now() - dateutil.relativedelta.relativedelta(months=months_ago)

logger.info(f'Cleanup [HostMetric]: soft-deleting records last automated before {last_automation_before}')
logger.info(f'cleanup_host_metrics: soft-deleting records last automated before {last_automation_before}')
HostMetric.active_objects.filter(last_automation__lt=last_automation_before).update(
deleted=True, deleted_counter=models.F('deleted_counter') + 1, last_deleted=now()
)
settings.CLEANUP_HOST_METRICS_LAST_TS = now()
except (TypeError, ValueError):
logger.error(f"Cleanup [HostMetric]: months_ago({months_ago}) has to be a positive integer value")
logger.error(f"cleanup_host_metrics: months_ago({months_ago}) has to be a positive integer value")


class HostMetricSummaryMonthly(models.Model):
"""
HostMetric summaries computed by scheduled task <TODO> monthly
HostMetric summaries computed by scheduled task 'awx.main.tasks.system.host_metric_summary_monthly' monthly
"""

date = models.DateField(unique=True)
Expand Down
12 changes: 10 additions & 2 deletions awx/main/models/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,11 @@ def workflow_nodes(self):

@property
def event_processing_finished(self):
return True
return True # workflow jobs do not have events

@property
def has_unpartitioned_events(self):
return False # workflow jobs do not have events

def _get_parent_field_name(self):
if self.job_template_id:
Expand Down Expand Up @@ -914,7 +918,11 @@ def signal_start(self, **kwargs):

@property
def event_processing_finished(self):
return True
return True # approval jobs do not have events

@property
def has_unpartitioned_events(self):
return False # approval jobs do not have events

def send_approval_notification(self, approval_status):
from awx.main.tasks.system import send_notifications # avoid circular import
Expand Down
2 changes: 1 addition & 1 deletion awx/main/tasks/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from . import jobs, receptor, system # noqa
from . import host_metrics, jobs, receptor, system # noqa
Loading

0 comments on commit dbeacf9

Please sign in to comment.