def setUp(self): """ Creates a fresh test workspace in a temp dir to ensure we do not have conflicts with other CLI tests. """ self.tmp_ws_dir = os.path.join(tempfile.mkdtemp(), "son-workspace") ws = Workspace(self.tmp_ws_dir, ws_name="son-profile test workspace") ws.create_dirs() ws.create_files()
def test__create_from_descriptor__(self, m_path, m_open, m_yaml, m_log): """ Perform several tests to the static function "__create_from_descriptor__" to ensure that workspaces are correctly created from a configuration descriptor" """ # Make sure the workspace root dir and # config file do not exist by patching os.path m_path.join.return_value = None m_path.isdir.return_value = False m_path.isfile.return_value = False # Assure that None is returned using # non-existent root dir and config file self.assertEqual( Workspace.__create_from_descriptor__("/some/root/dir"), None) # Assure that an error message was logged self.assertTrue(m_log.error.called) # Make the root dir and config file exist m_path.isdir.return_value = True m_path.isfile.return_value = True # Create an invalid config descriptor for workspace conf_d = { 'version': '0.01', 'catalogue_servers': "['http://10.10.1.101:4011'," "'http://10.10.1.102:4011']", 'descriptor_extension': 'yml', 'schemas_local_master': '~/.son-schema', 'schemas_remote_master': 'https://raw.githubusercontent.com/' 'sonata-nfv/son-schema/master/', 'platforms_dir': 'platforms', 'catalogues_dir': 'catalogues', 'configuration_dir': 'configuration' } # Feed this descriptor as a config file # by patching os.open and yaml.load methods m_open.return_value = None m_yaml.load.return_value = conf_d # Ensure it raises error when loading incomplete config descriptor self.assertRaises(KeyError, Workspace.__create_from_descriptor__, None) # Complete config descriptor conf_d['name'] = 'test workspace config' conf_d['log_level'] = 'info' # Ensure that a valid Workspace object is returned self.assertIsInstance(Workspace.__create_from_descriptor__(None), Workspace)
def test_create_dirs(self, m_makedirs): """ Verify if the workspace directory structure is being well created. """ # Create a new workspace ws = Workspace("workspace/root/dir", ws_name="workspace_name", log_level='log_level') # Assure directory structure is well created m_makedirs.return_value = None ws.create_dirs() for call in m_makedirs.call_args_list: assert '\'workspace/root/dir' in str(call)
def pack(self, output_path): """ Use son-package to pack the given packet. :param output_path: resulting packages are placed in output_path :return: package path """ start_time = time.time() pkg_destination_path = os.path.join(output_path, self.pkg_name()) # obtain workspace # TODO have workspace dir as command line argument workspace = Workspace.__create_from_descriptor__(Workspace.DEFAULT_WORKSPACE_DIR) if workspace is None: LOG.error("Couldn't initialize workspace: %r. Abort." % Workspace.DEFAULT_WORKSPACE_DIR) exit(1) # obtain project project = Project.__create_from_descriptor__(workspace, self.pkg_service_path) if project is None: LOG.error("Packager couldn't load service project: %r. Abort." % self.pkg_service_path) exit(1) # initialize and run packager pck = Packager(workspace, project, dst_path=pkg_destination_path) pck.generate_package(os.path.join(output_path, self.pkg_name())) self.pkg_package_path = os.path.join(output_path, self.pkg_name()) + ".son" self.pkg_file_size = os.path.getsize(self.pkg_package_path) self.pack_time = time.time() - start_time return self.pkg_package_path
def pack(self, output_path): """ Use son-package to pack the given packet. :param output_path: resulting packages are placed in output_path :return: package path """ start_time = time.time() pkg_destination_path = os.path.join(output_path, self.pkg_name()) # obtain workspace # TODO have workspace dir as command line argument workspace = Workspace.__create_from_descriptor__( Workspace.DEFAULT_WORKSPACE_DIR) if workspace is None: LOG.error("Couldn't initialize workspace: %r. Abort." % Workspace.DEFAULT_WORKSPACE_DIR) exit(1) # obtain project project = Project.__create_from_descriptor__(workspace, self.pkg_service_path) if project is None: LOG.error("Packager couldn't load service project: %r. Abort." % self.pkg_service_path) exit(1) # initialize and run packager pck = Packager(workspace, project, dst_path=pkg_destination_path) pck.generate_package(os.path.join(output_path, self.pkg_name())) self.pkg_package_path = os.path.join(output_path, self.pkg_name()) + ".son" self.pkg_file_size = os.path.getsize(self.pkg_package_path) self.pack_time = time.time() - start_time return self.pkg_package_path
def __init__(self, workspace=None): """ Initialize the Validator. A workspace may be provided for an easy parameter configuration, such as location and extension of descriptors, verbosity level, etc. :param workspace: SONATA workspace object """ self._workspace = workspace self._syntax = True self._integrity = True self._topology = True # create "virtual" workspace if not provided (don't actually create # file structure) if not self._workspace: self._workspace = Workspace('.', log_level='info') # load configurations from workspace self._dext = self._workspace.default_descriptor_extension self._dpath = '.' self._log_level = self._workspace.log_level # configure logs coloredlogs.install(level=self._log_level) # descriptors storage self._storage = DescriptorStorage() # syntax validation self._schema_validator = SchemaValidator(self._workspace) # reset event logger evtlog.reset()
def test_generate_package(self, m_zipfile, m_join): """ Ensures that a package file is created with correct name and location """ # First, create a workspace to give to Packager workspace = Workspace("ws/root", ws_name="ws_test", log_level='debug') # Create project project = Project(workspace, 'prj/path') # Instantiate a Packager instance packager = Packager(workspace=workspace, project=project, generate_pd=False, dst_path="dst/path") packager._package_descriptor = True # Prepare mocks context_manager_mock = Mock() m_zipfile.ZipFile.return_value = context_manager_mock enter_mock = Mock() exit_mock = Mock() setattr(context_manager_mock, '__enter__', enter_mock) setattr(context_manager_mock, '__exit__', exit_mock) # execute packager.generate_package("package_name") # make assertions self.assertEqual(m_join.call_args_list[-1], mock.call('dst/path', 'package_name.son'))
def __init__(self, *args, **kwargs): super(UnitValidateTests, self).__init__(*args, **kwargs) # tap log functions to count for errors and warnings self._workspace = Workspace('.', log_level='debug') val.log.error = CountCalls(val.log.error) val.log.warning = CountCalls(val.log.warning)
def pack(self, output_path, verbose=False, workspace_dir=Workspace.DEFAULT_WORKSPACE_DIR): """ Creates a *.son file of this service object. First writes the normal project structure to disk (to be used with packaging tool) """ start_time = time.time() tmp_path = self._write(output_path) pkg_path = os.path.join(output_path, self.pkg_name) + ".son" LOG.warning(pkg_path) self.metadata["package_disk_path"] = pkg_path # be sure the target directory exists ensure_dir(output_path) # obtain workspace # TODO have workspace dir as command line argument workspace = Workspace.__create_from_descriptor__(workspace_dir) if workspace is None: LOG.error("Couldn't initialize workspace: %r. Abort." % workspace_dir) exit(1) # force verbosity of external tools if required workspace.log_level = "DEBUG" if verbose else "INFO" # obtain project project = Project.__create_from_descriptor__(workspace, tmp_path) if project is None: LOG.error("Packager couldn't load service project: %r. Abort." % tmp_path) exit(1) # initialize and run packager pck = Packager(workspace, project, dst_path=output_path) pck.generate_package(self.pkg_name) self.metadata["package_disk_size"] = os.path.getsize(pkg_path) self.metadata["package_generation_time"] = time.time() - start_time LOG.debug("Packed: {} to {}".format(self, pkg_path)) return pkg_path
def main(): import argparse parser = argparse.ArgumentParser( description="Generate new sonata package") parser.add_argument( "--workspace", help="Specify workspace to generate the package. If not specified " "will assume '{}'".format(Workspace.DEFAULT_WORKSPACE_DIR), required=False) parser.add_argument( "--project", help="create a new package based on the project at the specified " "location. If not specified will assume current directory '{}'" .format(os.getcwd()), required=False) parser.add_argument( "-d", "--destination", help="create the package on the specified location", required=False) parser.add_argument( "-n", "--name", help="create the package with the specific name", required=False) args = parser.parse_args() if args.workspace: ws_root = args.workspace else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR prj_root = args.project if args.project else os.getcwd() # Validate given arguments path_ids = dict() path_ids[ws_root] = Workspace.__descriptor_name__ path_ids[prj_root] = Project.__descriptor_name__ if not __validate_directory__(paths=path_ids): return # Obtain Workspace object workspace = Workspace.__create_from_descriptor__(ws_root) project = Project.__create_from_descriptor__(workspace, prj_root) pck = Packager(workspace, project, dst_path=args.destination) pck.generate_package(args.name)
def test___init__(self): """ Verify variable assignments in init function :return: """ # Create a new workspace ws = Workspace("workspace/root/dir", ws_name="workspace_name", log_level='log_level') # Verify its properties self.assertEqual(ws.ws_root, "workspace/root/dir") self.assertEqual(ws.ws_name, "workspace_name") self.assertEqual(ws.log_level, "log_level")
def main(): import argparse parser = argparse.ArgumentParser(description="Generate new sonata package") parser.add_argument( "--workspace", help="Specify workspace to generate the package. If not specified " "will assume '{}'".format(Workspace.DEFAULT_WORKSPACE_DIR), required=False) parser.add_argument( "--project", help="create a new package based on the project at the specified " "location. If not specified will assume current directory '{}'".format( os.getcwd()), required=False) parser.add_argument("-d", "--destination", help="create the package on the specified location", required=False) parser.add_argument("-n", "--name", help="create the package with the specific name", required=False) args = parser.parse_args() if args.workspace: ws_root = args.workspace else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR prj_root = args.project if args.project else os.getcwd() # Validate given arguments path_ids = dict() path_ids[ws_root] = Workspace.__descriptor_name__ path_ids[prj_root] = Project.__descriptor_name__ if not __validate_directory__(paths=path_ids): return # Obtain Workspace object workspace = Workspace.__create_from_descriptor__(ws_root) project = Project.__create_from_descriptor__(workspace, prj_root) pck = Packager(workspace, project, dst_path=args.destination) pck.generate_package(args.name)
def test_create_ws_descriptor(self, m_open, m_yaml, m_path): """ Tests the function that generates the workspace configuration file. Verify that a workspace can be created using the file generated by this function. """ # Create a new workspace ws = Workspace("workspace/root/dir", ws_name="workspace_name", log_level='log_level') # Patch file handling functions m_open.return_value = None m_open.write.return_value = None m_yaml.dump.return_value = None # Call function cfg_d = ws.write_ws_descriptor() # Assure that config file would be writen with the correct location configfile = os.path.join(ws.workspace_root, Workspace.__descriptor_name__) self.assertEqual(m_open.call_args, mock.call(configfile, 'w')) # Make sure the workspace root dir and # config file exist by patching os.path m_path.isdir.return_value = True m_path.isfile.return_value = True # Patch yaml.load to return the previously obtained configuration m_yaml.load.return_value = cfg_d # Call function new_ws = Workspace.__create_from_descriptor__(ws.workspace_root) # Assert returned workspace configuration is equal to the previous self.assertEqual(ws, new_ws)
def test_create_ws_descriptor(self, m_open, m_yaml, m_path): """ Tests the function that generates the workspace configuration file. Verify that a workspace can be created using the file generated by this function. """ # Create a new workspace ws = Workspace("workspace/root/dir", ws_name="workspace_name", log_level='log_level') # Patch file handling functions m_open.return_value = None m_open.write.return_value = None m_yaml.dump.return_value = None # Call function cfg_d = ws.create_ws_descriptor() # Assure that config file would be writen with the correct location configfile = os.path.join(ws.ws_root, Workspace.__descriptor_name__) self.assertEqual(m_open.call_args, mock.call(configfile, 'w')) # Make sure the workspace root dir and # config file exist by patching os.path m_path.isdir.return_value = True m_path.isfile.return_value = True # Patch yaml.load to return the previously obtained configuration m_yaml.load.return_value = cfg_d # Call function new_ws = Workspace.__create_from_descriptor__(ws.ws_root) # Assert returned workspace configuration is equal to the previous self.assertEqual(ws, new_ws)
def signature(): from son.access.access import AccessClient from son.workspace.workspace import Workspace from Crypto.PublicKey import RSA from Crypto.Hash import SHA256 ws = Workspace('~/workspace/ws1') ac = AccessClient(ws) key = RSA.generate(2048) # package_path = 'son/access/samples/sonata-demo.son' package_path = '../samples/sonata-demo.son' with open(package_path, 'rb') as fhandle: package_content = fhandle.read() package_hash = SHA256.new(package_content).digest() signature = ac.sign_package(package_path, private_key=key.exportKey().decode('utf-8')) public_key = key.publickey() print(public_key.verify(package_hash, (int(signature), )))
def test_package_gds(self): """ Test the validation of the project general description section """ # First, create a workspace to give to Packager workspace = Workspace("ws/root", ws_name="ws_test", log_level='debug') # Create project project = Project(workspace, 'prj/path') # Instantiate a Packager instance packager = Packager(workspace=workspace, project=project, generate_pd=False, dst_path="dst/path") packager._package_descriptor = True # Create fake project configuration prj_config = { 'version': '0.5', 'package': { 'version': '0.1', 'name': 'sonata-project-sample', 'vendor': 'com.sonata.project', 'maintainer': 'Name, Company, Contact', 'description': 'Project description', }, 'descriptor_extension': 'yml' } # Remove package keys, one by one... for key in prj_config['package']: value = prj_config['package'].pop(key) self.assertIsNone(packager.package_gds(prj_config)) prj_config['package'][key] = value # Make prj_config complete... prj_config['name'] = 'sonata - project - sample' self.assertTrue(packager.package_gds(prj_config))
def main(): import argparse parser = argparse.ArgumentParser( description="Publish a project or component to the catalogue server") parser.add_argument( "--workspace", help="Specify workspace. Default is located at '{}'" .format(Workspace.DEFAULT_WORKSPACE_DIR), required=False) parser.add_argument( "--project", help="Specify project to be published", required=False) parser.add_argument( "-d", "--component", help="Project component to be published.", required=False) parser.add_argument("-c", "--catalogue", help="Catalogue ID where to publish. " "Overrides defaults in workspace config.") args = parser.parse_args() # Ensure that either --component or --project # argument is given, but not the two simultaneously (XOR) if bool(args.component) == bool(args.project): parser.print_help() return # If workspace arg is not given, specify workspace as the default location if not args.workspace: ws_root = Workspace.DEFAULT_WORKSPACE_DIR else: ws_root = expanduser(args.workspace) # Create the Workspace object ws = Workspace.__create_from_descriptor__(ws_root) if not ws: print("Could not find a SONATA SDK workspace at '{}'" .format(ws_root), file=sys.stderr) exit(1) if args.project: prj_root = os.path.expanduser(args.project) proj = Project(ws, prj_root) if not proj: print("Could not find a SONATA SDK project at '{}'" .format(prj_root), file=sys.stderr) exit(1) pub = Publisher(ws, project=proj, catalogue=args.catalogue) pub.publish_project() if args.component: comp_file = os.path.expanduser(args.component) if not os.path.isfile(comp_file): print("'{}' is not a valid file" .format(comp_file), file=sys.stderr) exit(1) pub = Publisher(ws, component=comp_file, catalogue=args.catalogue) pub.publish_component()
def main(): import argparse parser = argparse.ArgumentParser(description="Generate new sonata package") parser.add_argument( "--workspace", help="Specify workspace to generate the package. If not specified " "will assume '{}'".format(Workspace.DEFAULT_WORKSPACE_DIR), required=False) exclusive_parser = parser.add_mutually_exclusive_group(required=True) exclusive_parser.add_argument( "--project", dest="project", help="create a new package based on the project at the specified " "location. If not specified will assume current directory '{}'".format( os.getcwd()), required=False) exclusive_parser.add_argument( "--custom", dest="custom", help="Create a custom package. Contents and descriptors can be added " "using the '--service' and '--function' arguments.", action="store_true", required=False) parser.add_argument( "--service", dest="service", nargs='*', help="Only applicable to custom packages. Add a service descriptor " "to the package. Multiple services may be specified separated " "with a space", required=False) parser.add_argument( "--function", dest="function", nargs='*', help="Only applicable to custom packages. Add a function descriptor " "to the package. Multiple functions may be specified separated " "with a space", required=False) parser.add_argument("-d", "--destination", help="create the package on the specified location", required=False) parser.add_argument("-n", "--name", help="create the package with the specific name", required=False) args = parser.parse_args() if args.workspace: ws_root = args.workspace else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR # Obtain Workspace object workspace = Workspace.__create_from_descriptor__(ws_root) prj_root = args.project if args.project else os.getcwd() if args.project: # Validate given arguments path_ids = dict() path_ids[ws_root] = Workspace.__descriptor_name__ path_ids[prj_root] = Project.__descriptor_name__ if not __validate_directory__(paths=path_ids): return project = Project.__create_from_descriptor__(workspace, prj_root) pck = Packager(workspace, project=project, dst_path=args.destination) pck.generate_package(args.name) elif args.custom: if not (args.service or args.function): log.error("To create a custom package, the arguments '--service' " "and/or '--function' must be used.") exit(1) pck = Packager(workspace, services=args.service, functions=args.function, dst_path=args.destination) pck.generate_package(args.name)
def main(): import argparse parser = argparse.ArgumentParser( description="Publish a project or component to the catalogue server") parser.add_argument( "--workspace", help="Specify workspace. Default is located at '{}'".format( Workspace.DEFAULT_WORKSPACE_DIR), required=False) parser.add_argument("--project", help="Specify project to be published", required=False) parser.add_argument("-d", "--component", help="Project component to be published.", required=False) parser.add_argument("-c", "--catalogue", help="Catalogue ID where to publish. " "Overrides defaults in workspace config.") args = parser.parse_args() # Ensure that either --component or --project # argument is given, but not the two simultaneously (XOR) if bool(args.component) == bool(args.project): parser.print_help() return # If workspace arg is not given, specify workspace as the default location if not args.workspace: ws_root = Workspace.DEFAULT_WORKSPACE_DIR else: ws_root = expanduser(args.workspace) # Create the Workspace object ws = Workspace.__create_from_descriptor__(ws_root) if not ws: print("Could not find a SONATA SDK workspace at '{}'".format(ws_root), file=sys.stderr) exit(1) if args.project: prj_root = os.path.expanduser(args.project) proj = Project(ws, prj_root) if not proj: print( "Could not find a SONATA SDK project at '{}'".format(prj_root), file=sys.stderr) exit(1) pub = Publisher(ws, project=proj, catalogue=args.catalogue) pub.publish_project() if args.component: comp_file = os.path.expanduser(args.component) if not os.path.isfile(comp_file): print("'{}' is not a valid file".format(comp_file), file=sys.stderr) exit(1) pub = Publisher(ws, component=comp_file, catalogue=args.catalogue) pub.publish_component()
def test__create_from_descriptor__(self, m_path, m_open, m_yaml, m_log): """ Perform several tests to the static function "__create_from_descriptor__" to ensure that workspaces are correctly created from a configuration descriptor" """ # Make sure the workspace root dir and # config file do not exist by patching os.path m_path.join.return_value = None m_path.isdir.return_value = False m_path.isfile.return_value = False # Assure that None is returned using # non-existent root dir and config file self.assertEqual( Workspace.__create_from_descriptor__("/some/root/dir"), None ) # Assure that an error message was logged self.assertTrue(m_log.error.called) # Make the root dir and config file exist m_path.isdir.return_value = True m_path.isfile.return_value = True # Create an invalid config descriptor for workspace conf_d = { 'version': '0.01', 'catalogue_servers': "['http://10.10.1.101:4011'," "'http://10.10.1.102:4011']", 'descriptor_extension': 'yml', 'schemas_local_master': '~/.son-schema', 'schemas_remote_master': 'https://raw.githubusercontent.com/' 'sonata-nfv/son-schema/master/', 'platforms_dir': 'platforms', 'catalogues_dir': 'catalogues', 'configuration_dir': 'configuration' } # Feed this descriptor as a config file # by patching os.open and yaml.load methods m_open.return_value = None m_yaml.load.return_value = conf_d # Ensure it raises error when loading incomplete config descriptor self.assertRaises( KeyError, Workspace.__create_from_descriptor__, None ) # Complete config descriptor conf_d['name'] = 'test workspace config' conf_d['log_level'] = 'info' # Ensure that a valid Workspace object is returned self.assertIsInstance( Workspace.__create_from_descriptor__(None), Workspace )
def main(): from argparse import ArgumentParser, RawDescriptionHelpFormatter print(mcolors.OKGREEN + "Running PULL\n", mcolors.ENDC) description = """ Pull resources (packages/descriptors) from the SONATA service platform/emulator or list packages/descriptors/instances available on the SONATA platform/emulator. """ examples = """Example usage: son-pull --list_packages son-pull --url http://127.0.0.1:5000 -A """ parser = ArgumentParser(description=description, formatter_class=RawDescriptionHelpFormatter, epilog=examples) parser.add_argument( "--workspace", type=str, metavar="WORKSPACE_PATH", help="specifies workspace to work on. If not specified will " "assume '{}'".format(Workspace.DEFAULT_WORKSPACE_DIR), required=False) parser.add_argument("--url", type=str, metavar="URL", help="url of the gatekeeper/platform/emulator") parser.add_argument("-A", "--alive", help="Checks connectivity with the GK", action="store_true") parser.add_argument("-P", "--list_packages", help="List packages uploaded to the platform", action="store_true") parser.add_argument("-F", "--list_functions", help="List functions uploaded to the platform", action="store_true") parser.add_argument("-S", "--list_services", help="List services uploaded to the platform", action="store_true") parser.add_argument("--get_package", type=str, metavar="ID", help="Pull package from the platform") parser.add_argument("--get_function", type=str, metavar="ID", help="Pull function from the platform") parser.add_argument("--get_service", type=str, metavar="ID", help="Pull service from the platform") parser.add_argument("--get_package_uuid", type=str, metavar="UUID", help="Pull son_package from the platform") parser.add_argument("--get_function_uuid", type=str, metavar="UUID", help="Pull function from the platform") parser.add_argument("--get_service_uuid", type=str, metavar="UUID", help="Pull service from the platform") parser.add_argument("--get_son_package", type=str, metavar="UUID", help="Pull son_package from the platform") parser.add_argument("-I", "--list_instances", help="List deployed packages on the platform", action="store_true") args = parser.parse_args() # Obtain Workspace object if args.workspace: ws_root = args.workspace else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR workspace = Workspace.__create_from_descriptor__(ws_root) if args.url: platform_url = str(args.url) else: platform_url = 'http://' + str(GK_ADDRESS) + ':' + str(GK_PORT) if not platform_url: print("Platform url is required in config file") access_token = None try: with open('config/token.txt', 'rb') as token_file: access_token = token_file.read() access_token = access_token[1:-1] except: pass pull_client = Pull(platform_url, auth_token=access_token) if args.alive: print(mcolors.OKGREEN + "PULL - Checking Platform connectivity...\n", mcolors.ENDC) print(pull_client.alive()) if args.list_packages: print(mcolors.OKGREEN + "PULL - Getting Packages list...\n", mcolors.ENDC) print(pull_client.get_all_packages()) if args.list_functions: print(mcolors.OKGREEN + "PULL - Getting Functions list...\n", mcolors.ENDC) print(pull_client.get_all_vnfs()) if args.list_services: print(mcolors.OKGREEN + "PULL - Getting Services list...\n", mcolors.ENDC) print(pull_client.get_all_nss()) if args.get_package_uuid: print(mcolors.OKGREEN + "PULL - Getting Package...\n", mcolors.ENDC) pull_client.get_package_by_uuid(args.get_package_uuid) if args.get_function_uuid: print(mcolors.OKGREEN + "PULL - Getting Function...\n", mcolors.ENDC) print(pull_client.get_vnf_by_uuid(args.get_function_uuid)) if args.get_service_uuid: print(mcolors.OKGREEN + "PULL - Getting Service...\n", mcolors.ENDC) print(pull_client.get_ns_by_uuid(args.get_service_uuid)) if args.get_package: print(mcolors.OKGREEN + "PULL - Getting Package...\n", mcolors.ENDC) pull_client.get_package_by_id(args.get_package) if args.get_function: print(mcolors.OKGREEN + "PULL - Getting Function...\n", mcolors.ENDC) print(pull_client.get_vnf_by_id(args.get_function)) if args.get_service: print(mcolors.OKGREEN + "PULL - Getting Service...\n", mcolors.ENDC) print(pull_client.get_ns_by_id(args.get_service)) if args.get_son_package: print(mcolors.OKGREEN + "PULL - Getting SON-Package...\n", mcolors.ENDC) binary_data = pull_client.get_son_package_by_uuid(args.get_son_package)
def main(): import argparse parser = argparse.ArgumentParser( description="SONATA Validator API. By default service runs on" " 127.0.0.1:5001\n") parser.add_argument( "--mode", choices=['stateless', 'local'], default='stateless', help="Specify the mode of operation. 'stateless' mode will run as " "a stateless service only. 'local' mode will run as a " "service and will also provide automatic monitoring and " "validation of local SDK projects, services, etc. that are " "configured in the developer workspace", required=False) parser.add_argument("--host", default=app.config['HOST'], help="Bind address for this service", required=False) parser.add_argument("--port", default=app.config['PORT'], type=int, help="Bind port number", required=False) parser.add_argument( "-w", "--workspace", help="Only valid in 'local' mode. " "Specify the directory of the SDK workspace. " "Validation objects defined in the workspace configuration will " "be monitored and automatically validated. " "If not specified will assume '{}'".format( Workspace.DEFAULT_WORKSPACE_DIR), default=Workspace.DEFAULT_WORKSPACE_DIR, required=False) parser.add_argument("--debug", default=app.config['DEBUG'], help="Sets verbosity level to debug", required=False, action="store_true") args = parser.parse_args() coloredlogs.install(level='debug' if args.debug else 'info') app.config['DEBUG'] = True if args.debug else False initialize(debug=args.debug) if args.mode == 'local' and args.workspace: ws_root = os.path.expanduser(args.workspace) ws = Workspace.__create_from_descriptor__(ws_root) if not ws: log.error("Could not find a SONATA workspace " "at the specified location") exit(1) load_watch_dirs(ws) app.run( host=args.host, port=args.port, debug=args.debug, use_reloader=False, ) # enforce debug (if is the case) after app init if args.debug: coloredlogs.install(level='debug')
def test__create_from_descriptor__(self, m_path, m_open, m_yaml, m_log): """ Perform several tests to the static function "__create_from_descriptor__" to ensure that workspaces are correctly created from a configuration descriptor" """ # Make sure the workspace root dir and # config file do not exist by patching os.path m_path.join.return_value = None m_path.isdir.return_value = False m_path.isfile.return_value = False # Assure that None is returned using # non-existent root dir and config file self.assertEqual( Workspace.__create_from_descriptor__("/some/root/dir"), None ) # Assure that an error message was logged self.assertTrue(m_log.error.called) # Make the root dir and config file exist m_path.isdir.return_value = True m_path.isfile.return_value = True # Create an invalid config descriptor for workspace conf_d = { 'version': Workspace.CONFIG_VERSION, 'service_platforms': {'sp1': {'url': 'http://sp.int3.sonata-nfv.eu:32001', 'credentials:': {'username': '******', 'password': '******', 'token_file': 'token.txt'}}}, 'default_service_platform': 'sp1', 'default_descriptor_extension': 'yml', 'schemas_local_master': '~/.son-schema', 'schemas_remote_master': 'https://raw.githubusercontent.com/' 'sonata-nfv/son-schema/master/', 'platforms_dir': 'platforms', 'catalogues_dir': 'catalogues', 'configuration_dir': 'configuration', 'projects_dir': 'projects', 'validate_watch': '~/.son-workspace/projects' } # Feed this descriptor as a config file # by patching os.open and yaml.load methods m_open.return_value = None m_yaml.load.return_value = conf_d # Ensure it raises error when loading incomplete config descriptor self.assertRaises( KeyError, Workspace.__create_from_descriptor__, None ) # Complete config descriptor conf_d['name'] = 'test workspace config' conf_d['log_level'] = 'info' # Ensure that a valid Workspace object is returned self.assertIsInstance( Workspace.__create_from_descriptor__(None), Workspace )
def __init__(self): usage = """son-access [optional] command [<args>] The supported commands are: auth Authenticate a user list List available resources (service, functions, packages,...) push Submit a son-package or request a service instantiation pull Request resources (services, functions, packages, ...) config Configure access parameters """ examples = """Example usage: access auth -u tester -p 1234 access --platform sp1 auth -u tester -p 1234 access auth --logout access push --upload samples/sonata-demo.son access push --upload samples/sonata-demo.son --sign access list services access pull packages --uuid 65b416a6-46c0-4596-a9e9-0a9b04ed34ea access pull files --uuid 65b416a6-46c0-4596-a9e9-0a9b04ed34ea access pull services --id sonata.eu firewall-vnf 1.0 access --platform sp1 push --deploy 65b416a6-46c0-4596-a9e9-0a9b04ed34ea """ parser = ArgumentParser( description="Authenticates users to submit and request resources " "from SONATA Service Platform", usage=usage, ) parser.add_argument( "-w", "--workspace", type=str, metavar="WORKSPACE_PATH", help="Specify workspace to work on. If not specified will " "assume '{}'".format(Workspace.DEFAULT_WORKSPACE_DIR), required=False) parser.add_argument( "--platform", type=str, metavar="PLATFORM_ID", help="Specify the ID of the Service Platform to use from " "workspace configuration. If not specified will assume the ID" " in 'default_service_platform'", required=False) parser.add_argument("--debug", help="Set logging level to debug", required=False, action="store_true") parser.add_argument("command", help="Command to run") # align command index command_idx = 1 for idx in range(1, len(sys.argv)): v = sys.argv[idx] if (v == "-w" or v == "--workspace" or v == "--platform"): command_idx += 2 elif v == '--debug': command_idx += 1 self.subarg_idx = command_idx + 1 args = parser.parse_args(sys.argv[1:self.subarg_idx]) # handle workspace if args.workspace: workspace_root = args.workspace else: workspace_root = Workspace.DEFAULT_WORKSPACE_DIR self.workspace = Workspace.__create_from_descriptor__(workspace_root) if not self.workspace: print("Invalid workspace: ", workspace_root) return # handle debug log_level = 'info' if args.debug: log_level = 'debug' coloredlogs.install(level=log_level) if not hasattr(self, args.command): print("Invalid command: ", args.command) exit(1) self.ac = AccessClient(self.workspace, platform_id=args.platform, log_level=log_level) # call sub-command getattr(self, args.command)()
def main(): coloredlogs.install(level='info') import argparse # specify arguments parser = argparse.ArgumentParser( description="Validate a SONATA Service. By default it performs a " "validation to the syntax, integrity and network " "topology.\n", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="""Example usage: son-validate --project /home/sonata/projects/project_X --workspace /home/sonata/.son-workspace son-validate --service ./nsd_file.yml --path ./vnfds/ --dext yml son-validate --function ./vnfd_file.yml son-validate --function ./vnfds/ --dext yml """ ) exclusive_parser = parser.add_mutually_exclusive_group( required=True ) parser.add_argument( "-w", "--workspace", dest="workspace_path", help="Specify the directory of the SDK workspace for validating the " "SDK project. If not specified will assume the directory: '{}'" .format(Workspace.DEFAULT_WORKSPACE_DIR), required=False ) exclusive_parser.add_argument( "--project", dest="project_path", help="Validate the service of the specified SDK project. If " "not specified will assume the current directory: '{}'\n" .format(os.getcwd()), required=False ) exclusive_parser.add_argument( "--package", dest="package_file", help="Validate the specified package descriptor. " ) exclusive_parser.add_argument( "--service", dest="nsd", help="Validate the specified service descriptor. " "The directory of descriptors referenced in the service " "descriptor should be specified using the argument '--path'.", required=False ) exclusive_parser.add_argument( "--function", dest="vnfd", help="Validate the specified function descriptor. If a directory is " "specified, it will search for descriptor files with extension " "defined in '--dext'", required=False ) parser.add_argument( "--dpath", help="Specify a directory to search for descriptors. Particularly " "useful when using the '--service' argument.", required=False ) parser.add_argument( "--dext", help="Specify the extension of descriptor files. Particularly " "useful when using the '--function' argument", required=False ) parser.add_argument( "--syntax", "-s", help="Perform a syntax validation.", required=False, action="store_true", default=False ) parser.add_argument( "--integrity", "-i", help="Perform an integrity validation.", required=False, action="store_true", default=False ) parser.add_argument( "--topology", "-t", help="Perform a network topology validation.", required=False, action="store_true", default=False ) parser.add_argument( "--debug", help="sets verbosity level to debug", required=False, action="store_true") # parse arguments args = parser.parse_args() # by default, perform all validations if not args.syntax and not args.integrity and not args.topology: args.syntax = args.integrity = args.topology = True if args.package_file: if not os.path.isfile(args.package_file): log.error("Provided package is not a valid file") exit(1) if args.workspace_path: ws_root = args.workspace_path else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR # Obtain Workspace object workspace = Workspace.__create_from_descriptor__(ws_root) if not workspace: log.error("Invalid workspace path: '%s'\n" % ws_root) exit(1) validator = Validator(workspace=workspace) validator.configure(syntax=args.syntax, integrity=args.integrity, topology=args.topology, debug=args.debug) if not validator.validate_package(args.package_file): log.critical("Package validation has failed.") exit(1) if validator.warning_count == 0: log.info("Validation of package '{0}' has succeeded." .format(args.package_file)) else: log.warning("Validation of package '{0}' returned {1} warning(s)" .format(args.package_file, validator.warning_count)) print(validator.error_count) elif args.project_path: if args.workspace_path: ws_root = args.workspace_path else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR prj_root = args.project_path if args.project_path else os.getcwd() # Obtain Workspace object workspace = Workspace.__create_from_descriptor__(ws_root) if not workspace: log.error("Invalid workspace path: '%s'\n" % ws_root) exit(1) project = Project.__create_from_descriptor__(workspace, prj_root) if not project: log.error("Invalid project path: '%s'\n " % prj_root) exit(1) validator = Validator(workspace=workspace) validator.configure(syntax=args.syntax, integrity=args.integrity, topology=args.topology, debug=args.debug) if not validator.validate_project(project): log.critical("Project validation has failed.") exit(1) if validator.warning_count == 0: log.info("Validation of project '{0}' has succeeded." .format(project.project_root)) else: log.warning("Validation of project '{0}' returned {1} warning(s)" .format(project.project_root, validator.warning_count)) elif args.nsd: validator = Validator() validator.configure(dpath=args.dpath, dext=args.dext, syntax=args.syntax, integrity=args.integrity, topology=args.topology, debug=args.debug) if not validator.validate_service(args.nsd): log.critical("Project validation has failed.") exit(1) if validator.warning_count == 0: log.info("Validation of service '{0}' has succeeded." .format(args.nsd)) else: log.warning("Validation of service '{0}' returned {1} warning(s)" .format(args.nsd, validator.warning_count)) elif args.vnfd: validator = Validator() validator.configure(dext=args.dext, syntax=args.syntax, integrity=args.integrity, topology=args.topology, debug=args.debug) if not validator.validate_function(args.vnfd): log.critical("Function validation has failed.") exit(1) if validator.warning_count == 0: log.info("Validation of function '{0}' has succeeded." .format(args.vnfd)) else: log.warning("Validation of function '{0}' returned {1} warning(s)" .format(args.vnfd, validator.warning_count)) else: log.error("Provided arguments are invalid.") exit(1) log.info("Done.") exit(0)
def main(): coloredlogs.install(level='info') import argparse # specify arguments parser = argparse.ArgumentParser( description="Validate a SONATA Service. By default it performs a " "validation to the syntax, integrity and network " "topology.\n", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="""Example usage: son-validate --project /home/sonata/projects/project_X --workspace /home/sonata/.son-workspace son-validate --service ./nsd_file.yml --path ./vnfds/ --dext yml son-validate --function ./vnfd_file.yml son-validate --function ./vnfds/ --dext yml """) exclusive_parser = parser.add_mutually_exclusive_group(required=True) parser.add_argument( "-w", "--workspace", dest="workspace_path", help="Specify the directory of the SDK workspace for validating the " "SDK project. If not specified will assume the directory: '{}'".format( Workspace.DEFAULT_WORKSPACE_DIR), required=False) exclusive_parser.add_argument( "--project", dest="project_path", help="Validate the service of the specified SDK project. If " "not specified will assume the current directory: '{}'\n".format( os.getcwd()), required=False) exclusive_parser.add_argument( "--package", dest="package_file", help="Validate the specified package descriptor. ") exclusive_parser.add_argument( "--service", dest="nsd", help="Validate the specified service descriptor. " "The directory of descriptors referenced in the service " "descriptor should be specified using the argument '--path'.", required=False) exclusive_parser.add_argument( "--function", dest="vnfd", help="Validate the specified function descriptor. If a directory is " "specified, it will search for descriptor files with extension " "defined in '--dext'", required=False) parser.add_argument( "--dpath", help="Specify a directory to search for descriptors. Particularly " "useful when using the '--service' argument.", required=False) parser.add_argument( "--dext", help="Specify the extension of descriptor files. Particularly " "useful when using the '--function' argument", required=False) parser.add_argument("--syntax", "-s", help="Perform a syntax validation.", required=False, action="store_true", default=False) parser.add_argument("--integrity", "-i", help="Perform an integrity validation.", required=False, action="store_true", default=False) parser.add_argument("--topology", "-t", help="Perform a network topology validation.", required=False, action="store_true", default=False) parser.add_argument("--debug", help="sets verbosity level to debug", required=False, action="store_true") # parse arguments args = parser.parse_args() # by default, perform all validations if not args.syntax and not args.integrity and not args.topology: args.syntax = args.integrity = args.topology = True if args.package_file: if not os.path.isfile(args.package_file): log.error("Provided package is not a valid file") exit(1) if args.workspace_path: ws_root = args.workspace_path else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR # Obtain Workspace object workspace = Workspace.__create_from_descriptor__(ws_root) if not workspace: log.error("Invalid workspace path: '%s'\n" % ws_root) exit(1) validator = Validator(workspace=workspace) validator.configure(syntax=args.syntax, integrity=args.integrity, topology=args.topology, debug=args.debug) result = validator.validate_package(args.package_file) print_result(validator, result) elif args.project_path: if args.workspace_path: ws_root = args.workspace_path else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR prj_root = args.project_path if args.project_path else os.getcwd() # Obtain Workspace object workspace = Workspace.__create_from_descriptor__(ws_root) if not workspace: log.error("Invalid workspace path: '%s'\n" % ws_root) exit(1) project = Project.__create_from_descriptor__(workspace, prj_root) if not project: log.error("Invalid project path: '%s'\n " % prj_root) exit(1) validator = Validator(workspace=workspace) validator.configure(syntax=args.syntax, integrity=args.integrity, topology=args.topology, debug=args.debug) result = validator.validate_project(project) print_result(validator, result) elif args.nsd: validator = Validator() validator.configure(dpath=args.dpath, dext=args.dext, syntax=args.syntax, integrity=args.integrity, topology=args.topology, debug=args.debug) result = validator.validate_service(args.nsd) print_result(validator, result) elif args.vnfd: validator = Validator() validator.configure(dext=args.dext, syntax=args.syntax, integrity=args.integrity, topology=args.topology, debug=args.debug) result = validator.validate_function(args.vnfd) print_result(validator, result) else: log.error("Invalid arguments.") exit(1) exit(0)
from son.access.access import AccessClient from son.workspace.workspace import Workspace from Crypto.PublicKey import RSA from Crypto.Hash import SHA256 ws = Workspace('~/workspace/ws1') ac = AccessClient(ws) key = RSA.generate(2048) package_path = 'son/access/samples/sonata-demo.son' with open(package_path, 'rb') as fhandle: package_content = fhandle.read() package_hash = SHA256.new(package_content).digest() signature = ac.sign_package(package_path, private_key=key.exportKey().decode('utf-8')) public_key = key.publickey() print(public_key.verify(package_hash, (int(signature), )))
def main(): import argparse parser = argparse.ArgumentParser( description="SONATA Validator API. By default service runs on" " 127.0.0.1:5001\n" ) parser.add_argument( "--mode", choices=['stateless', 'local'], default='stateless', help="Specify the mode of operation. 'stateless' mode will run as " "a stateless service only. 'local' mode will run as a " "service and will also provide automatic monitoring and " "validation of local SDK projects, services, etc. that are " "configured in the developer workspace", required=False ) parser.add_argument( "--host", default=app.config['HOST'], help="Bind address for this service", required=False ) parser.add_argument( "--port", default=app.config['PORT'], type=int, help="Bind port number", required=False ) parser.add_argument( "-w", "--workspace", help="Only valid in 'local' mode. " "Specify the directory of the SDK workspace. " "Validation objects defined in the workspace configuration will " "be monitored and automatically validated. " "If not specified will assume '{}'" .format(Workspace.DEFAULT_WORKSPACE_DIR), default=Workspace.DEFAULT_WORKSPACE_DIR, required=False ) parser.add_argument( "--debug", default=app.config['DEBUG'], help="Sets verbosity level to debug", required=False, action="store_true" ) args = parser.parse_args() coloredlogs.install(level='debug' if args.debug else 'info') app.config['DEBUG'] = True if args.debug else False initialize(debug=args.debug) if args.mode == 'local' and args.workspace: ws_root = os.path.expanduser(args.workspace) ws = Workspace.__create_from_descriptor__(ws_root) if not ws: log.error("Could not find a SONATA workspace " "at the specified location") exit(1) load_watch_dirs(ws) app.run( host=args.host, port=args.port, debug=args.debug, use_reloader=False, ) # enforce debug (if is the case) after app init if args.debug: coloredlogs.install(level='debug')
def main(): from argparse import ArgumentParser, RawDescriptionHelpFormatter print(mcolors.OKGREEN + "Running PULL\n", mcolors.ENDC) description = """ Pull resources (packages/descriptors) from the SONATA service platform/emulator or list packages/descriptors/instances available on the SONATA platform/emulator. """ examples = """Example usage: son-pull --list_packages son-pull --url http://127.0.0.1:5000 -A """ parser = ArgumentParser( description=description, formatter_class=RawDescriptionHelpFormatter, epilog=examples) parser.add_argument( "--workspace", type=str, metavar="WORKSPACE_PATH", help="specifies workspace to work on. If not specified will " "assume '{}'".format(Workspace.DEFAULT_WORKSPACE_DIR), required=False ) parser.add_argument( "--url", type=str, metavar="URL", help="url of the gatekeeper/platform/emulator") parser.add_argument( "-A", "--alive", help="Checks connectivity with the GK", action="store_true") parser.add_argument( "-P", "--list_packages", help="List packages uploaded to the platform", action="store_true") parser.add_argument( "-F", "--list_functions", help="List functions uploaded to the platform", action="store_true") parser.add_argument( "-S", "--list_services", help="List services uploaded to the platform", action="store_true") parser.add_argument( "--get_package", type=str, metavar="ID", help="Pull package from the platform") parser.add_argument( "--get_function", type=str, metavar="ID", help="Pull function from the platform") parser.add_argument( "--get_service", type=str, metavar="ID", help="Pull service from the platform") parser.add_argument( "--get_package_uuid", type=str, metavar="UUID", help="Pull son_package from the platform") parser.add_argument( "--get_function_uuid", type=str, metavar="UUID", help="Pull function from the platform") parser.add_argument( "--get_service_uuid", type=str, metavar="UUID", help="Pull service from the platform") parser.add_argument( "--get_son_package", type=str, metavar="UUID", help="Pull son_package from the platform") parser.add_argument( "-I", "--list_instances", help="List deployed packages on the platform", action="store_true") args = parser.parse_args() # Obtain Workspace object if args.workspace: ws_root = args.workspace else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR workspace = Workspace.__create_from_descriptor__(ws_root) if args.url: platform_url = str(args.url) else: platform_url = 'http://' + str(GK_ADDRESS) + ':' + str(GK_PORT) if not platform_url: print("Platform url is required in config file") access_token = None try: with open('config/token.txt', 'rb') as token_file: access_token = token_file.read() access_token = access_token[1:-1] except: pass pull_client = Pull(platform_url, auth_token=access_token) if args.alive: print(mcolors.OKGREEN + "PULL - Checking Platform connectivity...\n", mcolors.ENDC) print(pull_client.alive()) if args.list_packages: print(mcolors.OKGREEN + "PULL - Getting Packages list...\n", mcolors.ENDC) print(pull_client.get_all_packages()) if args.list_functions: print(mcolors.OKGREEN + "PULL - Getting Functions list...\n", mcolors.ENDC) print(pull_client.get_all_vnfs()) if args.list_services: print(mcolors.OKGREEN + "PULL - Getting Services list...\n", mcolors.ENDC) print(pull_client.get_all_nss()) if args.get_package_uuid: print(mcolors.OKGREEN + "PULL - Getting Package...\n", mcolors.ENDC) pull_client.get_package_by_uuid(args.get_package_uuid) if args.get_function_uuid: print(mcolors.OKGREEN + "PULL - Getting Function...\n", mcolors.ENDC) print(pull_client.get_vnf_by_uuid(args.get_function_uuid)) if args.get_service_uuid: print(mcolors.OKGREEN + "PULL - Getting Service...\n", mcolors.ENDC) print(pull_client.get_ns_by_uuid(args.get_service_uuid)) if args.get_package: print(mcolors.OKGREEN + "PULL - Getting Package...\n", mcolors.ENDC) pull_client.get_package_by_id(args.get_package) if args.get_function: print(mcolors.OKGREEN + "PULL - Getting Function...\n", mcolors.ENDC) print(pull_client.get_vnf_by_id(args.get_function)) if args.get_service: print(mcolors.OKGREEN + "PULL - Getting Service...\n", mcolors.ENDC) print(pull_client.get_ns_by_id(args.get_service)) if args.get_son_package: print(mcolors.OKGREEN + "PULL - Getting SON-Package...\n", mcolors.ENDC) binary_data = pull_client.get_son_package_by_uuid(args.get_son_package)
def __init__(self): usage = """son-access [optional] command [<args>] The supported commands are: auth Authenticate a user list List available resources (service, functions, packages, ...) push Submit a son-package pull Request resources (services, functions, packages, ...) config Configure access parameters """ examples = """Example usage: access auth -u tester -p 1234 access push samples/sonata-demo.son access list services access pull packages --uuid 65b416a6-46c0-4596-a9e9-0a9b04ed34ea access pull services --id sonata.eu firewall-vnf 1.0 """ parser = ArgumentParser( description="Authenticates users to submit and request resources " "from SONATA Service Platform", usage=usage, ) parser.add_argument( "-w", "--workspace", type=str, metavar="WORKSPACE_PATH", help="Specify workspace to work on. If not specified will " "assume '{}'".format(Workspace.DEFAULT_WORKSPACE_DIR), required=False ) parser.add_argument( "-p", "--platform", type=str, metavar="PLATFORM_ID", help="Specify the ID of the Service Platform to use from " "workspace configuration. If not specified will assume the ID" "in '{}'".format(Workspace.CONFIG_STR_DEF_SERVICE_PLATFORM), required=False ) parser.add_argument( "--debug", help="Set logging level to debug", required=False, action="store_true" ) parser.add_argument( "command", help="Command to run" ) # align command index command_idx = 1 for idx in range(1, len(sys.argv)): v = sys.argv[idx] if (v == "-w" or v == "--workspace" or v == '-p' or v == "--platform"): command_idx += 2 elif v == '--debug': command_idx += 1 self.subarg_idx = command_idx+1 args = parser.parse_args(sys.argv[1: self.subarg_idx]) # handle workspace if args.workspace: ws_root = args.workspace else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR self.workspace = Workspace.__create_from_descriptor__(ws_root) if not self.workspace: print("Invalid workspace: ", ws_root) return # handle debug log_level = 'info' if args.debug: log_level = 'debug' coloredlogs.install(level=log_level) if not hasattr(self, args.command): print("Invalid command: ", args.command) exit(1) self.ac = AccessClient(self.workspace, platform_id=args.platform, log_level=log_level) # call sub-command getattr(self, args.command)()
def __init__(self, *args, **kwargs): super(IntPDTester, self).__init__(*args, **kwargs) ws = Workspace("") prj = Project(ws, '/') self.pck = Packager(workspace=ws, project=prj, generate_pd=False)
def main(): import argparse parser = argparse.ArgumentParser( description="Generate new sonata package") parser.add_argument( "--workspace", help="Specify workspace to generate the package. If not specified " "will assume '{}'".format(Workspace.DEFAULT_WORKSPACE_DIR), required=False) exclusive_parser = parser.add_mutually_exclusive_group( required=True ) exclusive_parser.add_argument( "--project", dest="project", help="create a new package based on the project at the specified " "location. If not specified will assume current directory '{}'" .format(os.getcwd()), required=False) exclusive_parser.add_argument( "--custom", dest="custom", help="Create a custom package. Contents and descriptors can be added " "using the '--service' and '--function' arguments.", action="store_true", required=False ) parser.add_argument( "--service", dest="service", nargs='*', help="Only applicable to custom packages. Add a service descriptor " "to the package. Multiple services may be specified separated " "with a space", required=False ) parser.add_argument( "--function", dest="function", nargs='*', help="Only applicable to custom packages. Add a function descriptor " "to the package. Multiple functions may be specified separated " "with a space", required=False ) parser.add_argument( "-d", "--destination", help="create the package on the specified location", required=False) parser.add_argument( "-n", "--name", help="create the package with the specific name", required=False) args = parser.parse_args() if args.workspace: ws_root = args.workspace else: ws_root = Workspace.DEFAULT_WORKSPACE_DIR # Obtain Workspace object workspace = Workspace.__create_from_descriptor__(ws_root) prj_root = args.project if args.project else os.getcwd() if args.project: # Validate given arguments path_ids = dict() path_ids[ws_root] = Workspace.__descriptor_name__ path_ids[prj_root] = Project.__descriptor_name__ if not __validate_directory__(paths=path_ids): return project = Project.__create_from_descriptor__(workspace, prj_root) pck = Packager(workspace, project=project, dst_path=args.destination) pck.generate_package(args.name) elif args.custom: if not (args.service or args.function): log.error("To create a custom package, the arguments '--service' " "and/or '--function' must be used.") exit(1) pck = Packager(workspace, services=args.service, functions=args.function, dst_path=args.destination) pck.generate_package(args.name)