# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Application-catalog v1 package action implementation""" import itertools import os import shutil import tempfile import zipfile from osc_lib.command import command from osc_lib import exceptions as exc from osc_lib import utils from oslo_log import log as logging from muranoclient.apiclient import exceptions from muranoclient.v1.package_creator import hot_package from muranoclient.v1.package_creator import mpl_package LOG = logging.getLogger(__name__) class CreatePackage(command.Command): """Create an application package.""" def get_parser(self, prog_name): parser = super(CreatePackage, self).get_parser(prog_name) parser.add_argument( '-t', '--template', metavar='', help=("Path to the Heat template to import as " "an Application Definition."), ) parser.add_argument( '-c', '--classes-dir', metavar='', help=("Path to the directory containing application classes."), ) parser.add_argument( '-r', '--resources-dir', metavar='', help=("Path to the directory containing application resources."), ) parser.add_argument( '-n', '--name', metavar='', help=("Display name of the Application in Catalog."), ) parser.add_argument( '-f', '--full-name', metavar='', help=("Fully-qualified name of the Application in Catalog."), ) parser.add_argument( '-a', '--author', metavar='', help=("Name of the publisher."), ) parser.add_argument( '--tags', metavar='', nargs='*', help=("A list of keywords connected to the application."), ) parser.add_argument( '-d', '--description', metavar='', help=("Detailed description for the Application in Catalog."), ) parser.add_argument( '-o', '--output', metavar='', help=("The name of the output file archive to save locally."), ) parser.add_argument( '-u', '--ui', metavar='', help=("Dynamic UI form definition."), ) parser.add_argument( '--type', metavar='', help=("Package type. Possible values: Application or Library."), ) parser.add_argument( '-l', '--logo', metavar='', help=("Path to the package logo."), ) return parser def take_action(self, parsed_args): LOG.debug("take_action({0})".format(parsed_args)) parsed_args.os_username = os.getenv('OS_USERNAME') def _make_archive(archive_name, path): zip_file = zipfile.ZipFile(archive_name, 'w') for root, dirs, files in os.walk(path): for f in files: zip_file.write(os.path.join(root, f), arcname=os.path.join( os.path.relpath(root, path), f)) if parsed_args.template and parsed_args.classes_dir: raise exc.CommandError( "Provide --template for a HOT-based package, OR" " --classes-dir for a MuranoPL-based package") if not parsed_args.template and not parsed_args.classes_dir: raise exc.CommandError( "Provide --template for a HOT-based package, OR at least" " --classes-dir for a MuranoPL-based package") directory_path = None try: archive_name = parsed_args.output if parsed_args.output else None if parsed_args.template: directory_path = hot_package.prepare_package(parsed_args) if not archive_name: archive_name = os.path.basename(parsed_args.template) archive_name = os.path.splitext(archive_name)[0] + ".zip" else: directory_path = mpl_package.prepare_package(parsed_args) if not archive_name: archive_name = tempfile.mkstemp( prefix="murano_", dir=os.getcwd())[1] + ".zip" _make_archive(archive_name, directory_path) print("Application package is available at " + os.path.abspath(archive_name)) finally: if directory_path: shutil.rmtree(directory_path) class ListPackages(command.Lister): """List available packages.""" def get_parser(self, prog_name): parser = super(ListPackages, self).get_parser(prog_name) parser.add_argument( "--limit", type=int, default=0, help='Show limited number of packages' ) parser.add_argument( "--marker", default='', help='Show packages starting from package with id excluding it' ) parser.add_argument( "--include-disabled", default=False, action="store_true" ) parser.add_argument( "--owned", default=False, action="store_true" ) parser.add_argument( '--search', metavar='', dest='search', required=False, help='Show packages, that match search keys fuzzily' ) parser.add_argument( '--name', metavar='', dest='name', required=False, help='Show packages, whose name match parameter exactly' ) parser.add_argument( '--fqn', metavar="", dest='fqn', required=False, help='Show packages, ' 'whose fully qualified name match parameter exactly' ) parser.add_argument( '--type', metavar='', dest='type', required=False, help='Show packages, whose type match parameter exactly' ) parser.add_argument( '--category', metavar='', dest='category', required=False, help='Show packages, whose categories include parameter' ) parser.add_argument( '--class_name', metavar='', dest='class_name', required=False, help='Show packages, whose class name match parameter exactly' ) parser.add_argument( '--tag', metavar='', dest='tag', required=False, help='Show packages, whose tags include parameter' ) return parser def take_action(self, parsed_args): LOG.debug("take_action({0})".format(parsed_args)) client = self.app.client_manager.application_catalog filter_args = { "include_disabled": getattr(parsed_args, 'include_disabled', False), "owned": getattr(parsed_args, 'owned', False), } if parsed_args: if parsed_args.limit < 0: raise exceptions.CommandError( '--limit parameter must be non-negative') if parsed_args.limit != 0: filter_args['limit'] = parsed_args.limit if parsed_args.marker: filter_args['marker'] = parsed_args.marker if parsed_args.search: filter_args['search'] = parsed_args.search if parsed_args.name: filter_args['name'] = parsed_args.name if parsed_args.fqn: filter_args['fqn'] = parsed_args.fqn if parsed_args.type: filter_args['type'] = parsed_args.type if parsed_args.category: filter_args['category'] = parsed_args.category if parsed_args.class_name: filter_args['class_name'] = parsed_args.class_name if parsed_args.tag: filter_args['tag'] = parsed_args.tag data = client.packages.filter(**filter_args) columns = ('id', 'name', 'fully_qualified_name', 'author', 'active', 'is public', 'type', 'version') column_headers = [c.capitalize() for c in columns] if not parsed_args or parsed_args.limit == 0: return ( column_headers, list(utils.get_item_properties( s, columns, ) for s in data) ) else: return ( column_headers, list(utils.get_item_properties( s, columns, ) for s in itertools.islice(data, parsed_args.limit)) )