diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/app.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/app.py index 2b4a536283..2a8841dd7c 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/app.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/app.py @@ -40,7 +40,7 @@ class AppManager(base.Manager): def upload(self, data): """Stage the specified application, getting it ready for deployment. - :param data: application name and location of tarfile + :param data: application name and location of tarfile and the binary of the tarfile """ return self._create(self._path(), data) diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/app_shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/app_shell.py index 1f9ad50248..586905d2de 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/app_shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/app_shell.py @@ -4,6 +4,7 @@ # # SPDX-License-Identifier: Apache-2.0 # +import base64 import os import re @@ -105,6 +106,15 @@ def do_application_show(cc, args): def do_application_upload(cc, args): """Upload application Helm chart(s) and manifest""" data = _application_check(args) + + if not _is_url(data["tarfile"]): + try: + with open(data["tarfile"], 'rb') as tarfile: + binary_data = base64.urlsafe_b64encode(tarfile.read()) + data.update({'binary_data': binary_data}) + except Exception: + raise exc.CommandError("Error: Could not open file %s." % data["tarfile"]) + response = cc.app.upload(data) _print_application_show(response) _print_reminder_msg(response.name) diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py index 14e220c1a3..2d0ca2538b 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py @@ -4,10 +4,13 @@ # SPDX-License-Identifier: Apache-2.0 # +import base64 import os import hashlib import pecan +import pwd from pecan import rest +import time import wsme from wsme import types as wtypes import wsmeext.pecan as wsme_pecan @@ -200,10 +203,30 @@ class KubeAppController(rest.RestController): @wsme_pecan.wsexpose(KubeApp, body=types.apidict) def post(self, body): """Uploading an application to be deployed by Armada""" - tarfile = body.get('tarfile') + tarfile_path = body.get('tarfile') + tarfile_binary = body.get('binary_data', '') name = body.get('name', '') version = body.get('app_version', '') - name, version, mname, mfile = self._check_tarfile(tarfile, name, version, + + if not cutils.is_url(tarfile_path) and not os.path.exists(tarfile_path): + path_tarballs = '/tmp/tarball_uploads' + if not os.path.exists(path_tarballs): + os.makedirs(path_tarballs) + uid, gid = pwd.getpwnam('sysinv').pw_uid, pwd.getpwnam('sysinv').pw_uid + os.chown(path_tarballs, uid, gid) + + # Keep unique tarball name to avoid conflicts + tarball_name = '{}-{}'.format(time.time(), os.path.basename(tarfile_path)) + tarfile_path = os.path.join(path_tarballs, tarball_name) + try: + with open(tarfile_path, 'wb') as f: + f.write(base64.urlsafe_b64decode(tarfile_binary)) + except Exception as e: + LOG.exception('Error: writing the tarfile: {}'.format(e)) + raise wsme.exc.ClientSideError(_( + "Could not save the application on path {}".format(tarfile_path))) + + name, version, mname, mfile = self._check_tarfile(tarfile_path, name, version, constants.APP_UPLOAD_OP) try: @@ -231,7 +254,7 @@ class KubeAppController(rest.RestController): lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL pecan.request.rpcapi.perform_app_upload(pecan.request.context, - new_app, tarfile, + new_app, tarfile_path, lifecycle_hook_info=lifecycle_hook_info) return KubeApp.convert_with_links(new_app) diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/types.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/types.py index d7f6cfbe4d..7b67e02100 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/types.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/types.py @@ -126,7 +126,11 @@ class ApiDictType(wtypes.UserType): name = 'apidict' __name__ = name - basetype = {wtypes.text: apiutils.ValidTypes(wtypes.text, six.integer_types)} + basetype = {wtypes.text: apiutils.ValidTypes( + wtypes.text, + six.integer_types, + wsme.types.bytes + )} apidict = ApiDictType()