add instance install bundle endpoint

add scaffolding for instance install_bundle endpoint

- add instance_install_bundle view (does not do anything yet)
- add `instance_install_bundle` related field to serializer
- add `/install_bundle` to instance URL
- `/install_bundle` only available for execution and hop node
- `/install_bundle` endpoint response contain a downloadable tgz with moc data

TODO: add actual data to the install bundle response

Signed-off-by: Hao Liu <haoli@redhat.com>
This commit is contained in:
TheRealHaoLiu 2022-07-18 11:10:59 -04:00 committed by Jeff Bradberry
parent 9b034ad574
commit 7956fc3c31
4 changed files with 58 additions and 1 deletions

View File

@ -4917,6 +4917,7 @@ class InstanceSerializer(BaseSerializer):
res = super(InstanceSerializer, self).get_related(obj)
res['jobs'] = self.reverse('api:instance_unified_jobs_list', kwargs={'pk': obj.pk})
res['instance_groups'] = self.reverse('api:instance_instance_groups_list', kwargs={'pk': obj.pk})
res['install_bundle'] = self.reverse('api:instance_install_bundle', kwargs={'pk': obj.pk})
if self.context['request'].user.is_superuser or self.context['request'].user.is_system_auditor:
if obj.node_type != 'hop':
res['health_check'] = self.reverse('api:instance_health_check', kwargs={'pk': obj.pk})

View File

@ -3,7 +3,7 @@
from django.urls import re_path
from awx.api.views import InstanceList, InstanceDetail, InstanceUnifiedJobsList, InstanceInstanceGroupsList, InstanceHealthCheck
from awx.api.views import InstanceList, InstanceDetail, InstanceUnifiedJobsList, InstanceInstanceGroupsList, InstanceHealthCheck, InstanceInstallBundle
urls = [
@ -12,6 +12,7 @@ urls = [
re_path(r'^(?P<pk>[0-9]+)/jobs/$', InstanceUnifiedJobsList.as_view(), name='instance_unified_jobs_list'),
re_path(r'^(?P<pk>[0-9]+)/instance_groups/$', InstanceInstanceGroupsList.as_view(), name='instance_instance_groups_list'),
re_path(r'^(?P<pk>[0-9]+)/health_check/$', InstanceHealthCheck.as_view(), name='instance_health_check'),
re_path(r'^(?P<pk>[0-9]+)/install_bundle/$', InstanceInstallBundle.as_view(), name='instance_install_bundle'),
]
__all__ = ['urls']

View File

@ -174,6 +174,7 @@ from awx.api.views.webhooks import WebhookKeyView, GithubWebhookReceiver, Gitlab
from awx.api.pagination import UnifiedJobEventPagination
from awx.main.utils import set_environ
from awx.api.views.instance_install_bundle import InstanceInstallBundle # noqa
logger = logging.getLogger('awx.api.views')

View File

@ -0,0 +1,54 @@
# Copyright (c) 2018 Red Hat, Inc.
# All Rights Reserved.
import os
import tarfile
import tempfile
from awx.api import serializers
from awx.api.generics import GenericAPIView, Response
from awx.api.permissions import IsSystemAdminOrAuditor
from awx.main import models
from django.utils.translation import gettext_lazy as _
from rest_framework import status
from django.http import HttpResponse
# generate install bundle for the instance
class InstanceInstallBundle(GenericAPIView):
name = _('Install Bundle')
model = models.Instance
serializer_class = serializers.InstanceSerializer
permission_classes = (IsSystemAdminOrAuditor,)
def get(self, request, *args, **kwargs):
instance_obj = self.get_object()
# if the instance is not a hop or execution node than return 400
if instance_obj.node_type not in ('execution', 'hop'):
return Response(
data=dict(msg=_('Install bundle can only be generated for execution or hop nodes.')),
status=status.HTTP_400_BAD_REQUEST,
)
# TODO: add actual data into the bundle
# create a named temporary file directory to store the content of the install bundle
with tempfile.TemporaryDirectory() as tmpdirname:
# create a empty file named "moc_content.txt" in the temporary directory
with open(os.path.join(tmpdirname, 'mock_content.txt'), 'w') as f:
f.write('mock content')
# create empty directory in temporary directory
os.mkdir(os.path.join(tmpdirname, 'mock_dir'))
# tar.gz and create a temporary file from the temporary directory
# the directory will be renamed and prefixed with the hostname of the instance
with tempfile.NamedTemporaryFile(suffix='.tar.gz') as tmpfile:
with tarfile.open(tmpfile.name, 'w:gz') as tar:
tar.add(tmpdirname, arcname=f"{instance_obj.hostname}_install_bundle")
# read the temporary file and send it to the client
with open(tmpfile.name, 'rb') as f:
response = HttpResponse(f.read(), status=status.HTTP_200_OK)
response['Content-Disposition'] = f"attachment; filename={instance_obj.hostname}_install_bundle.tar.gz"
return response