def _register_pack_db(self, pack_name, pack_dir): content = get_pack_metadata(pack_dir=pack_dir) # The rules for the pack ref are as follows: # 1. If ref attribute is available, we used that # 2. If pack_name is available we use that (this only applies to packs # 2hich are in sub-directories) # 2. If attribute is not available, but pack name is and pack name meets the valid name # criteria, we use that content['ref'] = get_pack_ref_from_metadata( metadata=content, pack_directory_name=pack_name) # Include a list of pack files pack_file_list = get_file_list(directory=pack_dir, exclude_patterns=EXCLUDE_FILE_PATTERNS) content['files'] = pack_file_list pack_api = PackAPI(**content) pack_api.validate() pack_db = PackAPI.to_model(pack_api) try: pack_db.id = Pack.get_by_ref(content['ref']).id except StackStormDBObjectNotFoundError: LOG.debug('Pack %s not found. Creating new one.', pack_name) pack_db = Pack.add_or_update(pack_db) LOG.debug('Pack %s registered.' % (pack_name)) return pack_db
def verify_pack_version(pack_dir): """ Verify that the pack works with the currently running StackStorm version. """ pack_metadata = get_pack_metadata(pack_dir=pack_dir) pack_name = pack_metadata.get('name', None) required_stackstorm_version = pack_metadata.get('stackstorm_version', None) supported_python_versions = pack_metadata.get('python_versions', None) # If stackstorm_version attribute is specified, verify that the pack works with currently # running version of StackStorm if required_stackstorm_version: if not complex_semver_match(CURRENT_STACKSTORM_VERSION, required_stackstorm_version): msg = ('Pack "%s" requires StackStorm "%s", but current version is "%s". ' 'You can override this restriction by providing the "force" flag, but ' 'the pack is not guaranteed to work.' % (pack_name, required_stackstorm_version, CURRENT_STACKSTORM_VERSION)) raise ValueError(msg) if supported_python_versions: if set(supported_python_versions) == set(['2']) and not six.PY2: msg = ('Pack "%s" requires Python 2.x, but current Python version is "%s". ' 'You can override this restriction by providing the "force" flag, but ' 'the pack is not guaranteed to work.' % (pack_name, CURRENT_PYTHON_VERSION)) raise ValueError(msg) elif set(supported_python_versions) == set(['3']) and not six.PY3: msg = ('Pack "%s" requires Python 3.x, but current Python version is "%s". ' 'You can override this restriction by providing the "force" flag, but ' 'the pack is not guaranteed to work.' % (pack_name, CURRENT_PYTHON_VERSION)) raise ValueError(msg) else: # Pack support Python 2.x and 3.x so no check is needed pass return True
def _register_pack_db(self, pack_name, pack_dir): content = get_pack_metadata(pack_dir=pack_dir) # The rules for the pack ref are as follows: # 1. If ref attribute is available, we used that # 2. If pack_name is available we use that (this only applies to packs # 2hich are in sub-directories) # 2. If attribute is not available, but pack name is and pack name meets the valid name # criteria, we use that content['ref'] = get_pack_ref_from_metadata(metadata=content, pack_directory_name=pack_name) # Include a list of pack files pack_file_list = get_file_list(directory=pack_dir, exclude_patterns=EXCLUDE_FILE_PATTERNS) content['files'] = pack_file_list pack_api = PackAPI(**content) pack_api.validate() pack_db = PackAPI.to_model(pack_api) try: pack_db.id = Pack.get_by_ref(content['ref']).id except StackStormDBObjectNotFoundError: LOG.debug('Pack %s not found. Creating new one.', pack_name) pack_db = Pack.add_or_update(pack_db) LOG.debug('Pack %s registered.' % (pack_name)) return pack_db
def run(self, installed_pack, **kwargs): """ :param installed_pack: Installed pack name with version :type: installed_pack: ``string`` """ if not installed_pack: return False, False pack_and_version = installed_pack.split(PACK_VERSION_SEPARATOR) pack_name = pack_and_version[0] pack_version = pack_and_version[1] if len(pack_and_version) > 1 else None # Pack version is not specified. Get pack version from index.json file. if not pack_version: try: _, pack_version = get_repo_url(pack_name, proxy_config=None) except Exception: print ('No record of the "%s" pack in the index.' % (pack_name)) return False, False # Get installed pack version from local pack metadata file. try: pack_dir = '/opt/stackstorm/packs/%s/' % (pack_name) pack_metadata = get_pack_metadata(pack_dir=pack_dir) local_pack_version = pack_metadata.get('version', None) except Exception: print ('Could not open pack.yaml file at location %s' % (pack_dir)) return False, False if pack_version == local_pack_version: return True, True else: return False, False
def get_pack_ref(pack_dir): """ Read pack reference from the metadata file and sanitize it. """ metadata = get_pack_metadata(pack_dir=pack_dir) pack_ref = get_pack_ref_from_metadata(metadata=metadata, pack_directory_name=None) return pack_ref
def get_pack_version(pack=None): pack_path = get_pack_base_path(pack) try: pack_metadata = get_pack_metadata(pack_dir=pack_path) result = pack_metadata.get("version", None) except Exception: result = None finally: return result
def get_warnings(pack=None): result = None pack_path = get_pack_base_path(pack) try: pack_metadata = get_pack_metadata(pack_dir=pack_path) result = get_pack_warnings(pack_metadata) except Exception: print("Could not open pack.yaml at location %s" % pack_path) finally: return result
def get_dependency_list(pack=None): pack_path = get_pack_base_path(pack) try: pack_metadata = get_pack_metadata(pack_dir=pack_path) result = pack_metadata.get("dependencies", None) except Exception: print("Could not open pack.yaml at location %s" % pack_path) result = None finally: return result
def verify_pack_version(pack_dir): """ Verify that the pack works with the currently running StackStorm version. """ pack_metadata = get_pack_metadata(pack_dir=pack_dir) pack_name = pack_metadata.get('name', None) required_stackstorm_version = pack_metadata.get('stackstorm_version', None) # If stackstorm_version attribute is speficied, verify that the pack works with currently # running version of StackStorm if required_stackstorm_version: if not complex_semver_match(CURRENT_STACKSTROM_VERSION, required_stackstorm_version): msg = ( 'Pack "%s" requires StackStorm "%s", but current version is "%s". ' % (pack_name, required_stackstorm_version, CURRENT_STACKSTROM_VERSION), 'You can override this restriction by providing the "force" flag, but ', 'the pack is not guaranteed to work.') raise ValueError(msg) return True
def _get_pack_metadata(pack_dir): metadata = get_pack_metadata(pack_dir=pack_dir) return metadata
def download_pack(pack, abs_repo_base='/opt/stackstorm/packs', verify_ssl=True, force=False, proxy_config=None, force_owner_group=True, force_permissions=True, use_python3=False, logger=LOG): """ Download the pack and move it to /opt/stackstorm/packs. :param abs_repo_base: Path where the pack should be installed to. :type abs_repo_base: ``str`` :param pack: Pack name. :rtype pack: ``str`` :param force_owner_group: Set owner group of the pack directory to the value defined in the config. :type force_owner_group: ``bool`` :param force_permissions: True to force 770 permission on all the pack content. :type force_permissions: ``bool`` :param force: Force the installation and ignore / delete the lock file if it already exists. :type force: ``bool`` :param use_python3: True if a python3 binary should be used for this pack. :type use_python3: ``bool`` :return: (pack_url, pack_ref, result) :rtype: tuple """ proxy_config = proxy_config or {} # Python3 binary check python3_binary = cfg.CONF.actionrunner.python3_binary if use_python3 and not python3_binary: msg = ('Requested to use Python 3, but python3 binary not found on the system or ' 'actionrunner.python3 config option is not configured correctly.') raise ValueError(msg) try: pack_url, pack_version = get_repo_url(pack, proxy_config=proxy_config) except Exception as e: # Pack not found or similar result = [None, pack, (False, six.text_type(e))] return result result = [pack_url, None, None] temp_dir_name = hashlib.md5(pack_url.encode()).hexdigest() lock_file = LockFile('/tmp/%s' % (temp_dir_name)) lock_file_path = lock_file.lock_file if force: logger.debug('Force mode is enabled, deleting lock file...') try: os.unlink(lock_file_path) except OSError: # Lock file doesn't exist or similar pass with lock_file: try: user_home = os.path.expanduser('~') abs_local_path = os.path.join(user_home, temp_dir_name) if pack_url.startswith('file://'): # Local pack local_pack_directory = os.path.abspath(os.path.join(pack_url.split('file://')[1])) else: local_pack_directory = None # If it's a local pack which is not a git repository, just copy the directory content # over if local_pack_directory and not os.path.isdir( os.path.join(local_pack_directory, '.git')): if not os.path.isdir(local_pack_directory): raise ValueError('Local pack directory "%s" doesn\'t exist' % (local_pack_directory)) logger.debug('Detected local pack directory which is not a git repository, just ' 'copying files over...') shutil.copytree(local_pack_directory, abs_local_path) else: # 1. Clone / download the repo clone_repo(temp_dir=abs_local_path, repo_url=pack_url, verify_ssl=verify_ssl, ref=pack_version) pack_metadata = get_pack_metadata(pack_dir=abs_local_path) pack_ref = get_pack_ref(pack_dir=abs_local_path) result[1] = pack_ref # 2. Verify that the pack version if compatible with current StackStorm version if not force: verify_pack_version(pack_metadata=pack_metadata, use_python3=use_python3) # 3. Move pack to the final location move_result = move_pack(abs_repo_base=abs_repo_base, pack_name=pack_ref, abs_local_path=abs_local_path, pack_metadata=pack_metadata, force_owner_group=force_owner_group, force_permissions=force_permissions, logger=logger) result[2] = move_result finally: cleanup_repo(abs_local_path=abs_local_path) return tuple(result)