diff options
author | Nikolay Zamotaev <nzamotaev@luxoft.com> | 2018-07-02 16:46:35 +0300 |
---|---|---|
committer | Nikolay Zamotaev <nzamotaev@luxoft.com> | 2018-07-06 12:26:21 +0000 |
commit | 73ac5e6e804ad6cda42834eff85d4c60f4791892 (patch) | |
tree | 4861fcd23ab85cb56b0df3ee3538b645ed90cfd9 | |
parent | 91e213c05f314e9267ca0fe0b6d283badca450f7 (diff) |
[deployment-server] Added command for manual package upload
Change-Id: Ia81820d32947b4644909a556d29199a5f6112d46
Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
-rw-r--r-- | store/admin.py | 26 | ||||
-rw-r--r-- | store/management/commands/store-upload-package.py | 127 | ||||
-rw-r--r-- | store/utilities.py | 22 |
3 files changed, 154 insertions, 21 deletions
diff --git a/store/admin.py b/store/admin.py index d7712fd..1dbac7f 100644 --- a/store/admin.py +++ b/store/admin.py @@ -41,8 +41,7 @@ from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy from store.models import * -from utilities import parseAndValidatePackageMetadata -from utilities import iconPath +from utilities import parseAndValidatePackageMetadata, writeTempIcon, makeTagList class CategoryAdminForm(forms.ModelForm): class Meta: @@ -160,16 +159,9 @@ class AppAdminForm(forms.ModelForm): pass # write icon into file to serve statically - try: - if not os.path.exists(iconPath()): - os.makedirs(iconPath()) - tempicon = open(iconPath(self.appId), 'w') - tempicon.write(pkgdata['icon']) - tempicon.flush() - tempicon.close() - - except IOError as error: - raise forms.ValidationError(_('Validation error: could not write icon file to media directory: %s' % str(error))) + success, error = writeTempIcon(self.appId, pkgdata['icon']) + if not success: + raise forms.ValidationError(_(error)) return cleaned_data @@ -181,15 +173,7 @@ class AppAdminForm(forms.ModelForm): m.file.seek(0) pkgdata = parseAndValidatePackageMetadata(m.file) - taglist = set() - if 'binfmt' in pkgdata: - taglist.add(pkgdata['binfmt']) - for fields in ('extra','extraSigned'): - if fields in pkgdata['header']: - if 'tags' in pkgdata['header'][fields]: - tags = set(pkgdata['header'][fields]['tags']) #Fill tags list then add them - taglist = taglist.union(tags) - m.tags = ",".join(taglist) + m.tags = makeTagList(pkgdata) return m diff --git a/store/management/commands/store-upload-package.py b/store/management/commands/store-upload-package.py new file mode 100644 index 0000000..8a174ce --- /dev/null +++ b/store/management/commands/store-upload-package.py @@ -0,0 +1,127 @@ +############################################################################# +## +## Copyright (C) 2018 Luxoft +## +## This file is part of the Neptune Deployment Server +## +## $QT_BEGIN_LICENSE:GPL-QTAS$ +## Commercial License Usage +## Licensees holding valid commercial Qt Automotive Suite licenses may use +## this file in accordance with the commercial license agreement provided +## with the Software or, alternatively, in accordance with the terms +## contained in a written agreement between you and The Qt Company. For +## licensing terms and conditions see https://www.qt.io/terms-conditions. +## For further information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 or (at your option) any later version +## approved by the KDE Free Qt Foundation. The licenses are as published by +## the Free Software Foundation and appearing in the file LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +## SPDX-License-Identifier: GPL-3.0 +## +############################################################################# + +import os + +from django.core.management.base import BaseCommand, CommandError +from django.core.files.base import ContentFile +from store.models import App, Category, Vendor +from store.utilities import parseAndValidatePackageMetadata, packagePath, makeTagList, writeTempIcon +from optparse import make_option + + +class Command(BaseCommand): + help = 'Uploads a package to the deployment server. This can be used for batch uploading.' + option_list = BaseCommand.option_list + ( + make_option('--vendor', + action='store', + type="string", + dest='vendor', + help='Vendor name'), + make_option('--category', + action='store', + type="string", + dest='category', + help='Category name'), + make_option('--description', + action='store', + type="string", + dest='description', + default="Empty description", + help='Short package description'), + ) + + def handle(self, *args, **options): + if len(args) != 1: + raise CommandError( + 'Usage: manage.py store-upload-package --vendor <vendor> --category <category> [--description <short description>] <package>') + if (not options['vendor']) or (not options['category']): + raise CommandError( + 'Usage: manage.py store-upload-package --vendor <vendor> --category <category> [--description <short description>] <package>') + category = Category.objects.all().filter(name__exact=options['category']) + vendor = Vendor.objects.all().filter(name__exact=options['vendor']) + if len(category) == 0: + raise CommandError('Non-existing category specified') + if len(vendor) == 0: + raise CommandError('Non-existing vendor specified') + + try: + self.stdout.write('Parsing package %s' % args[0]) + packagefile = open(args[0], 'rb') + pkgdata = parseAndValidatePackageMetadata(packagefile) + self.stdout.write(' -> passed validation (internal name: %s)\n' % pkgdata['storeName']) + except Exception as error: + self.stdout.write(' -> failed: %s\n' % str(error)) + return 0 + + packagefile.seek(0) + appId = pkgdata['info']['id'] + name = pkgdata['storeName'] + architecture = pkgdata['architecture'] + description = options['description'] + tags = makeTagList(pkgdata) + + try: + a = App.objects.get(name__exact=name) + if a.id != pkgdata['info']['id']: + raise CommandError( + 'Validation error: the same package name (%s) is already used for application %s' % ( + name, a.id)) + except App.DoesNotExist: + pass + + success, error = writeTempIcon(appId,pkgdata['icon']) + if not success: + raise CommandError(error) + + exists = False + app = None + try: + app = App.objects.get(id__exact=appId) + exists = True + except App.DoesNotExist: + pass + + if exists: + app.category = category[0] + app.vendor = vendor[0] + app.name = name + app.tags = tags + app.description = app.briefDescription = description + app.architecture = architecture + app.file.save(packagePath(appId), ContentFile(packagefile.read())) + app.save() + else: + app, created = App.objects.get_or_create(name=name, tags=tags, vendor=vendor[0], + category=category[0], id=appId, + briefDescription=description, description=description, + architecture=architecture) + app.file.save(packagePath(appId), ContentFile(packagefile.read())) + app.save() diff --git a/store/utilities.py b/store/utilities.py index b9fa3a4..b571d79 100644 --- a/store/utilities.py +++ b/store/utilities.py @@ -53,6 +53,16 @@ def validateTag(tag): return False return True +def makeTagList(pkgdata): + taglist = set() + for fields in ('extra', 'extraSigned'): + if fields in pkgdata['header']: + if 'tags' in pkgdata['header'][fields]: + tags = set(pkgdata['header'][fields]['tags']) # Fill tags list then add them + taglist = taglist.union(tags) + tags = ','.join(taglist) + return tags + def packagePath(appId = None): path = settings.MEDIA_ROOT + 'packages/' if appId is not None: @@ -65,6 +75,18 @@ def iconPath(appId = None): return path + appId + '.png' return path +def writeTempIcon(appId, icon): + try: + if not os.path.exists(iconPath()): + os.makedirs(iconPath()) + tempicon = open(iconPath(appId), 'w') + tempicon.write(icon) + tempicon.flush() + tempicon.close() + return True, None + except IOError as error: + return False, 'Validation error: could not write icon file to media directory: %s' % str(error) + def downloadPath(): return settings.MEDIA_ROOT + 'downloads/' |