def run(self): ''' Run the logic for saltkey ''' self._update_opts() cmd = self.opts['fun'] veri = None ret = None try: if cmd in ('accept', 'reject', 'delete'): ret = self._run_cmd('name_match') if not isinstance(ret, dict): salt.output.display_output(ret, 'key', opts=self.opts) return ret ret = self._filter_ret(cmd, ret) if not ret: self._print_no_match(cmd, self.opts['match']) return print('The following keys are going to be {0}ed:'.format( cmd.rstrip('e'))) salt.output.display_output(ret, 'key', opts=self.opts) if not self.opts.get('yes', False): try: if cmd.startswith('delete'): veri = input('Proceed? [N/y] ') if not veri: veri = 'n' else: veri = input('Proceed? [n/Y] ') if not veri: veri = 'y' except KeyboardInterrupt: raise SystemExit("\nExiting on CTRL-c") # accept/reject/delete the same keys we're printed to the user self.opts['match_dict'] = ret self.opts.pop('match', None) list_ret = ret if veri is None or veri.lower().startswith('y'): ret = self._run_cmd(cmd) if cmd in ('accept', 'reject', 'delete'): if cmd == 'delete': ret = list_ret for minions in ret.values(): for minion in minions: print('Key for minion {0} {1}ed.'.format( minion, cmd.rstrip('e'))) elif isinstance(ret, dict): salt.output.display_output(ret, 'key', opts=self.opts) else: salt.output.display_output({'return': ret}, 'key', opts=self.opts) except salt.exceptions.SaltException as exc: ret = '{0}'.format(exc) if not self.opts.get('quiet', False): salt.output.display_output(ret, 'nested', self.opts) return ret
def run(self): """ Run the logic for saltkey """ self._update_opts() cmd = self.opts["fun"] veri = None ret = None try: if cmd in ("accept", "reject", "delete"): ret = self._run_cmd("name_match") if not isinstance(ret, dict): salt.output.display_output(ret, "key", opts=self.opts) return ret ret = self._filter_ret(cmd, ret) if not ret: self._print_no_match(cmd, self.opts["match"]) return print("The following keys are going to be {0}ed:".format( cmd.rstrip("e"))) salt.output.display_output(ret, "key", opts=self.opts) if not self.opts.get("yes", False): try: if cmd.startswith("delete"): veri = input("Proceed? [N/y] ") if not veri: veri = "n" else: veri = input("Proceed? [n/Y] ") if not veri: veri = "y" except KeyboardInterrupt: raise SystemExit("\nExiting on CTRL-c") # accept/reject/delete the same keys we're printed to the user self.opts["match_dict"] = ret self.opts.pop("match", None) list_ret = ret if veri is None or veri.lower().startswith("y"): ret = self._run_cmd(cmd) if cmd in ("accept", "reject", "delete"): if cmd == "delete": ret = list_ret for minions in ret.values(): for minion in minions: print("Key for minion {0} {1}ed.".format( minion, cmd.rstrip("e"))) elif isinstance(ret, dict): salt.output.display_output(ret, "key", opts=self.opts) else: salt.output.display_output({"return": ret}, "key", opts=self.opts) except salt.exceptions.SaltException as exc: ret = "{0}".format(exc) if not self.opts.get("quiet", False): salt.output.display_output(ret, "nested", self.opts) return ret
def cli(self, eauth): ''' Execute the CLI options to fill in the extra data needed for the defined eauth system ''' ret = {} if not eauth: print('External authentication system has not been specified') return ret fstr = '{0}.auth'.format(eauth) if fstr not in self.auth: print(('The specified external authentication system "{0}" is ' 'not available').format(eauth)) return ret args = salt.utils.arg_lookup(self.auth[fstr]) for arg in args['args']: if arg in self.opts: ret[arg] = self.opts[arg] elif arg.startswith('pass'): ret[arg] = getpass.getpass('{0}: '.format(arg)) else: ret[arg] = input('{0}: '.format(arg)) for kwarg, default in list(args['kwargs'].items()): if kwarg in self.opts: ret['kwarg'] = self.opts[kwarg] else: ret[kwarg] = input('{0} [{1}]: '.format(kwarg, default)) return ret
def cli(self, eauth): ''' Execute the CLI options to fill in the extra data needed for the defined eauth system ''' ret = {} if not eauth: print('External authentication system has not been specified') return ret fstr = '{0}.auth'.format(eauth) if fstr not in self.auth: print(('The specified external authentication system "{0}" is ' 'not available').format(eauth)) return ret args = salt.utils.args.arg_lookup(self.auth[fstr]) for arg in args['args']: if arg in self.opts: ret[arg] = self.opts[arg] elif arg.startswith('pass'): ret[arg] = getpass.getpass('{0}: '.format(arg)) else: ret[arg] = input('{0}: '.format(arg)) for kwarg, default in list(args['kwargs'].items()): if kwarg in self.opts: ret['kwarg'] = self.opts[kwarg] else: ret[kwarg] = input('{0} [{1}]: '.format(kwarg, default)) # Use current user if empty if 'username' in ret and not ret['username']: ret['username'] = salt.utils.user.get_user() return ret
def delete(self, match): ''' Delete the matched keys :param str match: A string to match against. i.e. 'web*' ''' def _print_deleted(matches, after_match): deleted = [] for keydir in (self.key.ACC, self.key.PEND, self.key.REJ): deleted.extend( list( set(matches.get(keydir, [])).difference( set(after_match.get(keydir, []))))) for key in sorted(deleted): print('Key for minion {0} deleted.'.format(key)) matches = self.key.name_match(match) if not matches: print('The key glob {0!r} does not match any accepted, unaccepted ' 'or rejected keys.'.format(match)) return if not self.opts.get('yes', False): print('The following keys are going to be deleted:') salt.output.display_output(matches, 'key', self.opts) try: veri = input('Proceed? [N/y] ') except KeyboardInterrupt: raise SystemExit("\nExiting on CTRL-c") if veri.lower().startswith('y'): _print_deleted(matches, self.key.delete_key(match_dict=matches)) else: print('Deleting the following keys:') salt.output.display_output(matches, 'key', self.opts) _print_deleted(matches, self.key.delete_key(match_dict=matches))
def print_confirm(self, msg): if self.options.assume_yes: return True print(msg) res = input("Proceed? [N/y] ") if not res.lower().startswith("y"): return False print("... proceeding") return True
def print_confirm(self, msg): if self.options.assume_yes: return True print(msg) res = input('Proceed? [N/y] ') if not res.lower().startswith('y'): return False print('... proceeding') return True
def cli(self, eauth): """ Execute the CLI options to fill in the extra data needed for the defined eauth system """ ret = {} if not eauth: print("External authentication system has not been specified") return ret fstr = "{0}.auth".format(eauth) if fstr not in self.auth: print( ( 'The specified external authentication system "{0}" is ' "not available" ).format(eauth) ) print( "Available eauth types: {0}".format( ", ".join([k[:-5] for k in self.auth if k.endswith(".auth")]) ) ) return ret args = salt.utils.args.arg_lookup(self.auth[fstr]) for arg in args["args"]: if arg in self.opts: ret[arg] = self.opts[arg] elif arg.startswith("pass"): ret[arg] = getpass.getpass("{0}: ".format(arg)) else: ret[arg] = input("{0}: ".format(arg)) for kwarg, default in list(args["kwargs"].items()): if kwarg in self.opts: ret["kwarg"] = self.opts[kwarg] else: ret[kwarg] = input("{0} [{1}]: ".format(kwarg, default)) # Use current user if empty if "username" in ret and not ret["username"]: ret["username"] = salt.utils.user.get_user() return ret
def run(self): ''' Run the logic for saltkey ''' self._update_opts() cmd = self.opts['fun'] veri = None if cmd in ('accept', 'reject', 'delete'): ret = self._run_cmd('list_match') if not isinstance(ret, dict): salt.output.display_output(ret, 'key', opts=self.opts) return ret ret = self._filter_ret(cmd, ret) if not ret: self._print_no_match(cmd, self.opts['match']) return print('The following keys are going to be {0}ed:'.format(cmd)) salt.output.display_output(ret, 'key', opts=self.opts) if not self.opts.get('yes', False): try: if cmd.startswith('delete'): veri = input('Proceed? [N/y] ') if not veri: veri = 'n' else: veri = input('Proceed? [n/Y] ') if not veri: veri = 'y' except KeyboardInterrupt: raise SystemExit("\nExiting on CTRL-c") if veri is None or veri.lower().startswith('y'): ret = self._run_cmd(cmd) if isinstance(ret, dict): salt.output.display_output(ret, 'key', opts=self.opts) else: salt.output.display_output({'return': ret}, 'key', opts=self.opts)
def delete(self, match): ''' Delete the matched keys :param str match: A string to match against. i.e. 'web*' ''' def _print_deleted(matches, after_match): deleted = [] for keydir in (self.key.ACC, self.key.PEND, self.key.REJ): deleted.extend(list( set(matches.get(keydir, [])).difference( set(after_match.get(keydir, [])) ) )) for key in sorted(deleted): print('Key for minion {0} deleted.'.format(key)) matches = self.key.name_match(match) if not matches: print( 'The key glob {0!r} does not match any accepted, unaccepted ' 'or rejected keys.'.format(match) ) return if not self.opts.get('yes', False): print('The following keys are going to be deleted:') salt.output.display_output( matches, 'key', self.opts) try: veri = input('Proceed? [N/y] ') except KeyboardInterrupt: raise SystemExit("\nExiting on CTRL-c") if veri.lower().startswith('y'): _print_deleted( matches, self.key.delete_key(match_dict=matches) ) else: print('Deleting the following keys:') salt.output.display_output( matches, 'key', self.opts) _print_deleted( matches, self.key.delete_key(match_dict=matches) )
def reject(self, match, include_accepted=False): ''' Reject the matched keys :param str match: A string to match against. i.e. 'web*' :param bool include_accepted: Whether or not to accept a matched key that was formerly accepted ''' def _print_rejected(matches, after_match): if self.key.REJ in after_match: rejected = sorted( set(after_match[self.key.REJ]).difference( set(matches.get(self.key.REJ, [])) ) ) for key in rejected: print('Key for minion {0} rejected.'.format(key)) matches = self.key.name_match(match) keys = {} if self.key.PEND in matches: keys[self.key.PEND] = matches[self.key.PEND] if include_accepted and bool(matches.get(self.key.ACC)): keys[self.key.ACC] = matches[self.key.ACC] if not keys: msg = 'The key glob \'{0}\' does not match any {1} keys.'.format( match, 'accepted or unaccepted' if include_accepted else 'unaccepted' ) print(msg) return if not self.opts.get('yes', False): print('The following keys are going to be rejected:') salt.output.display_output( keys, 'key', self.opts) veri = input('Proceed? [n/Y] ') if veri.lower().startswith('n'): return _print_rejected( matches, self.key.reject( match_dict=matches, include_accepted=include_accepted ) )
def reject(self, match, include_accepted=False): ''' Reject the matched keys :param str match: A string to match against. i.e. 'web*' :param bool include_accepted: Whether or not to accept a matched key that was formerly accepted ''' def _print_rejected(matches, after_match): if self.key.REJ in after_match: rejected = sorted( set(after_match[self.key.REJ]).difference( set(matches.get(self.key.REJ, [])) ) ) for key in rejected: print('Key for minion {0} rejected.'.format(key)) matches = self.key.name_match(match) keys = {} if self.key.PEND in matches: keys[self.key.PEND] = matches[self.key.PEND] if include_accepted and bool(matches.get(self.key.ACC)): keys[self.key.ACC] = matches[self.key.ACC] if not keys: msg = 'The key glob {0!r} does not match any {1} keys.'.format( match, 'accepted or unaccepted' if include_accepted else 'unaccepted' ) print(msg) return if not self.opts.get('yes', False): print('The following keys are going to be rejected:') salt.output.display_output( keys, 'key', self.opts) veri = input('Proceed? [n/Y] ') if veri.lower().startswith('n'): return _print_rejected( matches, self.key.reject( match_dict=matches, include_accepted=include_accepted ) )
def accept(self, match, include_rejected=False): ''' Accept the keys matched :param str match: A string to match against. i.e. 'web*' :param bool include_rejected: Whether or not to accept a matched key that was formerly rejected ''' def _print_accepted(matches, after_match): if self.key.ACC in after_match: accepted = sorted( set(after_match[self.key.ACC]).difference( set(matches.get(self.key.ACC, [])))) for key in accepted: print('Key for minion {0} accepted.'.format(key)) matches = self.key.name_match(match) keys = {} if self.key.PEND in matches: keys[self.key.PEND] = matches[self.key.PEND] if include_rejected and bool(matches.get(self.key.REJ)): keys[self.key.REJ] = matches[self.key.REJ] if not keys: msg = ('The key glob {0!r} does not match any unaccepted {1}keys.'. format(match, 'or rejected ' if include_rejected else '')) print(msg) return if not self.opts.get('yes', False): print('The following keys are going to be accepted:') salt.output.display_output(keys, 'key', self.opts) try: veri = input('Proceed? [n/Y] ') except KeyboardInterrupt: raise SystemExit("\nExiting on CTRL-c") if not veri or veri.lower().startswith('y'): _print_accepted( matches, self.key.accept(match_dict=keys, include_rejected=include_rejected)) else: print('The following keys are going to be accepted:') salt.output.display_output(keys, 'key', self.opts) _print_accepted( matches, self.key.accept(match_dict=keys, include_rejected=include_rejected))
def key_deploy(self, host, ret): ''' Deploy the SSH key if the minions don't auth ''' if not isinstance(ret[host], dict) or self.opts.get('ssh_key_deploy'): target = self.targets[host] if 'passwd' in target or self.opts['ssh_passwd']: self._key_deploy_run(host, target, False) return ret if ret[host].get('stderr', '').count('Permission denied'): target = self.targets[host] # permission denied, attempt to auto deploy ssh key print(('Permission denied for host {0}, do you want to deploy ' 'the salt-ssh key? (password required):').format(host)) deploy = input('[Y/n] ') if deploy.startswith(('n', 'N')): return ret target['passwd'] = getpass.getpass('Password for {0}@{1}: '.format( target['user'], host)) return self._key_deploy_run(host, target, True) return ret
def key_deploy(self, host, ret): ''' Deploy the SSH key if the minions don't auth ''' if not isinstance(ret[host], dict) or self.opts.get('ssh_key_deploy'): target = self.targets[host] if 'passwd' in target or self.opts['ssh_passwd']: self._key_deploy_run(host, target, False) return ret if ret[host].get('stderr', '').count('Permission denied'): target = self.targets[host] # permission denied, attempt to auto deploy ssh key print(('Permission denied for host {0}, do you want to deploy ' 'the salt-ssh key? (password required):').format(host)) deploy = input('[Y/n] ') if deploy.startswith(('n', 'N')): return ret target['passwd'] = getpass.getpass( 'Password for {0}@{1}: '.format(target['user'], host) ) return self._key_deploy_run(host, target, True) return ret
def confirm(self, action): print(action) res = input('Proceed? [N/y] ') if not res.lower().startswith('y'): raise SPMOperationCanceled('canceled')
__pillar__ = __opts__["pepa_pillar"] if args.pillar: __pillar__.update(salt.utils.yaml.safe_load(args.pillar)) # Validate or not if args.validate: __opts__["pepa_validate"] = True if args.query_api: import requests import getpass username = args.username password = args.password if username is None: username = input("Username: "******"Authenticate REST API") auth = {"username": username, "password": password, "eauth": "pam"} request = requests.post(args.url + "/login", auth) if not request.ok: raise RuntimeError( "Failed to authenticate to SaltStack REST API: {0}".format(request.text) ) response = request.json() token = response["return"][0]["token"]
def confirm(self, action): print(action) res = input("Proceed? [N/y] ") if not res.lower().startswith("y"): raise SPMOperationCanceled("canceled")
def accept(self, match, include_rejected=False): ''' Accept the keys matched :param str match: A string to match against. i.e. 'web*' :param bool include_rejected: Whether or not to accept a matched key that was formerly rejected ''' def _print_accepted(matches, after_match): if self.key.ACC in after_match: accepted = sorted( set(after_match[self.key.ACC]).difference( set(matches.get(self.key.ACC, [])) ) ) for key in accepted: print('Key for minion {0} accepted.'.format(key)) matches = self.key.name_match(match) keys = {} if self.key.PEND in matches: keys[self.key.PEND] = matches[self.key.PEND] if include_rejected and bool(matches.get(self.key.REJ)): keys[self.key.REJ] = matches[self.key.REJ] if not keys: msg = ( 'The key glob {0!r} does not match any unaccepted {1}keys.' .format(match, 'or rejected ' if include_rejected else '') ) print(msg) return if not self.opts.get('yes', False): print('The following keys are going to be accepted:') salt.output.display_output( keys, 'key', self.opts) try: veri = input('Proceed? [n/Y] ') except KeyboardInterrupt: raise SystemExit("\nExiting on CTRL-c") if not veri or veri.lower().startswith('y'): _print_accepted( matches, self.key.accept( match_dict=keys, include_rejected=include_rejected ) ) else: print('The following keys are going to be accepted:') salt.output.display_output( keys, 'key', self.opts) _print_accepted( matches, self.key.accept( match_dict=keys, include_rejected=include_rejected ) )
__pillar__ = __opts__['pepa_pillar'] if args.pillar: __pillar__.update(yaml.load(args.pillar, Loader=SaltYamlSafeLoader)) # Validate or not if args.validate: __opts__['pepa_validate'] = True if args.query_api: import requests import getpass username = args.username password = args.password if username is None: username = input('Username: '******'Authenticate REST API') auth = {'username': username, 'password': password, 'eauth': 'pam'} request = requests.post(args.url + '/login', auth) if not request.ok: raise RuntimeError( 'Failed to authenticate to SaltStack REST API: {0}'.format( request.text)) response = request.json() token = response['return'][0]['token']
def _local_install(self, args, pkg_name=None): ''' Install a package from a file ''' if len(args) < 2: log.error('A package file must be specified') return False pkg_file = args[1] self._init_db() roots_path = self.opts['file_roots']['base'][0] pillar_path = self.opts['pillar_roots']['base'][0] comps = pkg_file.split('-') comps = '-'.join(comps[:-2]).split('/') name = comps[-1] if not os.path.exists(pkg_file): log.error('File {0} not found'.format(pkg_file)) return False if not os.path.exists(roots_path): os.makedirs(roots_path) sqlite3.enable_callback_tracebacks(True) conn = sqlite3.connect(self.opts['spm_db'], isolation_level=None) cur = conn.cursor() formula_tar = tarfile.open(pkg_file, 'r:bz2') formula_ref = formula_tar.extractfile('{0}/FORMULA'.format(name)) formula_def = yaml.safe_load(formula_ref) data = conn.execute('SELECT package FROM packages WHERE package=?', (formula_def['name'], )) if data.fetchone() and not self.opts['force']: print('Package {0} already installed, not installing again'.format( formula_def['name'])) return if 'dependencies' in formula_def: if not isinstance(formula_def['dependencies'], list): formula_def['dependencies'] = [formula_def['dependencies']] needs = [] for dep in formula_def['dependencies']: if not isinstance(dep, string_types): continue data = conn.execute( 'SELECT package FROM packages WHERE package=?', (dep, )) if data.fetchone(): continue needs.append(dep) print('Cannot install {0}, the following dependencies are needed: ' '\n\n{1}'.format(formula_def['name'], '\n'.join(needs))) return if pkg_name is None: print('Installing package from file {0}'.format(pkg_file)) else: print('Installing package {0}'.format(pkg_name)) if not self.opts['assume_yes']: res = input('Proceed? [N/y] ') if not res.lower().startswith('y'): print('... canceled') return False print('... installing') log.debug('Locally installing package file {0} to {1}'.format( pkg_file, roots_path)) for field in ('version', 'release', 'summary', 'description'): if field not in formula_def: log.error( 'Invalid package: the {0} was not found'.format(field)) return False pkg_files = formula_tar.getmembers() # First pass: check for files that already exist existing_files = [] for member in pkg_files: if member.isdir(): continue if member.name.startswith('{0}/_'.format(name)): # Module files are distributed via _modules, _states, etc new_name = member.name.replace('{0}/'.format(name), '') out_file = os.path.join(roots_path, new_name) elif member.name == '{0}/pillar.example'.format(name): # Pillars are automatically put in the pillar_roots new_name = '{0}.sls.orig'.format(name) out_file = os.path.join(pillar_path, new_name) else: out_file = os.path.join(roots_path, member.name) if os.path.exists(out_file): existing_files.append(out_file) if not self.opts['force']: log.error( '{0} already exists, not installing'.format(out_file)) if existing_files and not self.opts['force']: return # We've decided to install conn.execute( 'INSERT INTO packages VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', ( name, formula_def['version'], formula_def['release'], datetime.datetime.utcnow().strftime( '%a, %d %b %Y %H:%M:%S GMT'), formula_def.get('os', None), formula_def.get('os_family', None), formula_def.get('dependencies', None), formula_def.get('os_dependencies', None), formula_def.get('os_family_dependencies', None), formula_def['summary'], formula_def['description'], )) # No defaults for this in config.py; default to the current running # user and group uid = self.opts.get('spm_uid', os.getuid()) gid = self.opts.get('spm_gid', os.getgid()) uname = pwd.getpwuid(uid)[0] gname = grp.getgrgid(gid)[0] # Second pass: install the files for member in pkg_files: out_path = roots_path file_ref = formula_tar.extractfile(member) member.uid = uid member.gid = gid member.uname = uname member.gname = gname if member.isdir(): digest = '' else: file_hash = hashlib.sha1() file_hash.update(file_ref.read()) digest = file_hash.hexdigest() if member.name.startswith('{0}/_'.format(name)): # Module files are distributed via _modules, _states, etc member.name = member.name.replace('{0}/'.format(name), '') elif member.name == '{0}/pillar.example'.format(name): # Pillars are automatically put in the pillar_roots member.name = '{0}.sls.orig'.format(name) out_path = pillar_path formula_tar.extract(member, out_path) conn.execute( 'INSERT INTO files VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', (name, '{0}/{1}'.format( out_path, member.path), member.size, member.mode, digest, member.devmajor, member.devminor, member.linkname, member.linkpath, member.uname, member.gname, member.mtime)) formula_tar.close() conn.close()
def _remove(self, args): ''' Remove a package ''' if len(args) < 2: log.error('A package must be specified') return False package = args[1] print('Removing package {0}'.format(package)) if not self.opts['assume_yes']: res = input('Proceed? [N/y] ') if not res.lower().startswith('y'): print('... canceled') return False print('... removing') if not os.path.exists(self.opts['spm_db']): log.error('No database at {0}, cannot remove {1}'.format( self.opts['spm_db'], package)) return # Look at local repo index sqlite3.enable_callback_tracebacks(True) conn = sqlite3.connect(self.opts['spm_db'], isolation_level=None) cur = conn.cursor() data = conn.execute('SELECT * FROM packages WHERE package=?', (package, )) if not data.fetchone(): log.error('Package {0} not installed'.format(package)) return # Find files that have not changed and remove them data = conn.execute('SELECT path, sum FROM files WHERE package=?', (package, )) dirs = [] for filerow in data.fetchall(): if os.path.isdir(filerow[0]): dirs.append(filerow[0]) continue with salt.utils.fopen(filerow[0], 'r') as fh_: file_hash = hashlib.sha1() file_hash.update(fh_.read()) digest = file_hash.hexdigest() if filerow[1] == digest: log.trace('Removing file {0}'.format(filerow[0])) os.remove(filerow[0]) else: log.trace('Not removing file {0}'.format(filerow[0])) conn.execute('DELETE FROM files WHERE path=?', (filerow[0], )) # Clean up directories for dir_ in sorted(dirs, reverse=True): conn.execute('DELETE FROM files WHERE path=?', (dir_, )) try: log.trace('Removing directory {0}'.format(dir_)) os.rmdir(dir_) except OSError: # Leave directories in place that still have files in them log.trace( 'Cannot remove directory {0}, probably not empty'.format( dir_)) conn.execute('DELETE FROM packages WHERE package=?', (package, ))
def _local_install(self, args, pkg_name=None): ''' Install a package from a file ''' if len(args) < 2: log.error('A package file must be specified') return False pkg_file = args[1] self._init_db() roots_path = self.opts['file_roots']['base'][0] pillar_path = self.opts['pillar_roots']['base'][0] comps = pkg_file.split('-') comps = '-'.join(comps[:-2]).split('/') name = comps[-1] if not os.path.exists(pkg_file): log.error('File {0} not found'.format(pkg_file)) return False if not os.path.exists(roots_path): os.makedirs(roots_path) sqlite3.enable_callback_tracebacks(True) conn = sqlite3.connect(self.opts['spm_db'], isolation_level=None) cur = conn.cursor() formula_tar = tarfile.open(pkg_file, 'r:bz2') formula_ref = formula_tar.extractfile('{0}/FORMULA'.format(name)) formula_def = yaml.safe_load(formula_ref) data = conn.execute('SELECT package FROM packages WHERE package=?', (formula_def['name'], )) if data.fetchone() and not self.opts['force']: print('Package {0} already installed, not installing again'.format(formula_def['name'])) return if 'dependencies' in formula_def: if not isinstance(formula_def['dependencies'], list): formula_def['dependencies'] = [formula_def['dependencies']] needs = [] for dep in formula_def['dependencies']: if not isinstance(dep, string_types): continue data = conn.execute('SELECT package FROM packages WHERE package=?', (dep, )) if data.fetchone(): continue needs.append(dep) print('Cannot install {0}, the following dependencies are needed: ' '\n\n{1}'.format(formula_def['name'], '\n'.join(needs))) return if pkg_name is None: print('Installing package from file {0}'.format(pkg_file)) else: print('Installing package {0}'.format(pkg_name)) if not self.opts['assume_yes']: res = input('Proceed? [N/y] ') if not res.lower().startswith('y'): print('... canceled') return False print('... installing') log.debug('Locally installing package file {0} to {1}'.format(pkg_file, roots_path)) for field in ('version', 'release', 'summary', 'description'): if field not in formula_def: log.error('Invalid package: the {0} was not found'.format(field)) return False pkg_files = formula_tar.getmembers() # First pass: check for files that already exist existing_files = [] for member in pkg_files: if member.isdir(): continue if member.name.startswith('{0}/_'.format(name)): # Module files are distributed via _modules, _states, etc new_name = member.name.replace('{0}/'.format(name), '') out_file = os.path.join(roots_path, new_name) elif member.name == '{0}/pillar.example'.format(name): # Pillars are automatically put in the pillar_roots new_name = '{0}.sls.orig'.format(name) out_file = os.path.join(pillar_path, new_name) else: out_file = os.path.join(roots_path, member.name) if os.path.exists(out_file): existing_files.append(out_file) if not self.opts['force']: log.error('{0} already exists, not installing'.format(out_file)) if existing_files and not self.opts['force']: return # We've decided to install conn.execute('INSERT INTO packages VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', ( name, formula_def['version'], formula_def['release'], datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'), formula_def.get('os', None), formula_def.get('os_family', None), formula_def.get('dependencies', None), formula_def.get('os_dependencies', None), formula_def.get('os_family_dependencies', None), formula_def['summary'], formula_def['description'], )) # No defaults for this in config.py; default to the current running # user and group uid = self.opts.get('spm_uid', os.getuid()) gid = self.opts.get('spm_gid', os.getgid()) uname = pwd.getpwuid(uid)[0] gname = grp.getgrgid(gid)[0] # Second pass: install the files for member in pkg_files: out_path = roots_path file_ref = formula_tar.extractfile(member) member.uid = uid member.gid = gid member.uname = uname member.gname = gname if member.isdir(): digest = '' else: file_hash = hashlib.sha1() file_hash.update(file_ref.read()) digest = file_hash.hexdigest() if member.name.startswith('{0}/_'.format(name)): # Module files are distributed via _modules, _states, etc member.name = member.name.replace('{0}/'.format(name), '') elif member.name == '{0}/pillar.example'.format(name): # Pillars are automatically put in the pillar_roots member.name = '{0}.sls.orig'.format(name) out_path = pillar_path formula_tar.extract(member, out_path) conn.execute('INSERT INTO files VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', ( name, '{0}/{1}'.format(out_path, member.path), member.size, member.mode, digest, member.devmajor, member.devminor, member.linkname, member.linkpath, member.uname, member.gname, member.mtime )) formula_tar.close() conn.close()
def _local_install(self, args, pkg_name=None): ''' Install a package from a file ''' if len(args) < 2: log.error('A package file must be specified') return False pkg_file = args[1] if not os.path.exists(pkg_file): log.error('File {0} not found'.format(pkg_file)) return False comps = pkg_file.split('-') comps = '-'.join(comps[:-2]).split('/') name = comps[-1] formula_tar = tarfile.open(pkg_file, 'r:bz2') formula_ref = formula_tar.extractfile('{0}/FORMULA'.format(name)) formula_def = yaml.safe_load(formula_ref) pkg_info = self.pkgdb['{0}.info'.format(self.db_prov)](name, self.db_conn) if pkg_info is not None and not self.opts['force']: print('Package {0} already installed, not installing again'.format( formula_def['name'])) return if 'dependencies' in formula_def: if not isinstance(formula_def['dependencies'], list): formula_def['dependencies'] = [formula_def['dependencies']] needs = [] for dep in formula_def['dependencies']: if not isinstance(dep, string_types): continue data = self.pkgdb['{0}.info'.format(self.db_prov)]( dep, self.db_conn) if data is not None: continue needs.append(dep) print('Cannot install {0}, the following dependencies are needed: ' '\n\n{1}'.format(formula_def['name'], '\n'.join(needs))) return if pkg_name is None: print('Installing package from file {0}'.format(pkg_file)) else: print('Installing package {0}'.format(pkg_name)) if not self.opts['assume_yes']: res = input('Proceed? [N/y] ') if not res.lower().startswith('y'): print('... canceled') return False print('... installing') for field in ('version', 'release', 'summary', 'description'): if field not in formula_def: log.error( 'Invalid package: the {0} was not found'.format(field)) return False pkg_files = formula_tar.getmembers() # First pass: check for files that already exist existing_files = self.pkgfiles['{0}.check_existing'.format( self.files_prov)](name, pkg_files) if existing_files and not self.opts['force']: return # We've decided to install self.pkgdb['{0}.register_pkg'.format(self.db_prov)](name, formula_def, self.db_conn) # No defaults for this in config.py; default to the current running # user and group uid = self.opts.get('spm_uid', os.getuid()) gid = self.opts.get('spm_gid', os.getgid()) uname = pwd.getpwuid(uid)[0] gname = grp.getgrgid(gid)[0] # Second pass: install the files for member in pkg_files: member.uid = uid member.gid = gid member.uname = uname member.gname = gname file_ref = formula_tar.extractfile(member) if member.isdir(): digest = '' else: file_hash = hashlib.sha1() file_hash.update(file_ref.read()) digest = file_hash.hexdigest() out_path = self.pkgfiles['{0}.install_file'.format( self.files_prov)](name, formula_tar, member, self.files_conn) self.pkgdb['{0}.register_file'.format(self.db_prov)](name, member, out_path, digest, self.db_conn) formula_tar.close()
tempdict = {} tempdict[title] = {'data': {server: [{key: {'tag': tag, 'match_ouput': match, 'value_type': vtype}}]}, 'description': desc} return tempdict # ask for PDF file (figure out good way to use XLS file) filename = [] print("Which PDF file are we checking against (alternatly place in same folder as script and this will happen automatically)") files = os.listdir(os.getcwd()) pdffiles = glob(os.path.join(os.getcwd(), "*.pdf")) if pdffiles: if len(pdffiles) >= 2: print("There is more than 1 pdf in the folder") truefile = False while not truefile: filename = input('Path to PDF: ') if os.path.isfile(filename): truefile = True else: print("that file does not exist") else: filename = pdffiles else: truefile = False while not truefile: filename = input('Path to PDF: ') if os.path.isfile(filename): truefile = True else: print("that file does not exist")
def _remove(self, args): ''' Remove a package ''' if len(args) < 2: log.error('A package must be specified') return False package = args[1] print('Removing package {0}'.format(package)) if not self.opts['assume_yes']: res = input('Proceed? [N/y] ') if not res.lower().startswith('y'): print('... canceled') return False print('... removing') if not os.path.exists(self.opts['spm_db']): log.error('No database at {0}, cannot remove {1}'.format(self.opts['spm_db'], package)) return # Look at local repo index sqlite3.enable_callback_tracebacks(True) conn = sqlite3.connect(self.opts['spm_db'], isolation_level=None) cur = conn.cursor() data = conn.execute('SELECT * FROM packages WHERE package=?', (package, )) if not data.fetchone(): log.error('Package {0} not installed'.format(package)) return # Find files that have not changed and remove them data = conn.execute('SELECT path, sum FROM files WHERE package=?', (package, )) dirs = [] for filerow in data.fetchall(): if os.path.isdir(filerow[0]): dirs.append(filerow[0]) continue with salt.utils.fopen(filerow[0], 'r') as fh_: file_hash = hashlib.sha1() file_hash.update(fh_.read()) digest = file_hash.hexdigest() if filerow[1] == digest: log.trace('Removing file {0}'.format(filerow[0])) os.remove(filerow[0]) else: log.trace('Not removing file {0}'.format(filerow[0])) conn.execute('DELETE FROM files WHERE path=?', (filerow[0], )) # Clean up directories for dir_ in sorted(dirs, reverse=True): conn.execute('DELETE FROM files WHERE path=?', (dir_, )) try: log.trace('Removing directory {0}'.format(dir_)) os.rmdir(dir_) except OSError: # Leave directories in place that still have files in them log.trace('Cannot remove directory {0}, probably not empty'.format(dir_)) conn.execute('DELETE FROM packages WHERE package=?', (package, ))
def _remove(self, args): ''' Remove a package ''' if len(args) < 2: log.error('A package must be specified') return False package = args[1] print('Removing package {0}'.format(package)) if not self.opts['assume_yes']: res = input('Proceed? [N/y] ') if not res.lower().startswith('y'): print('... canceled') return False print('... removing') if not os.path.exists(self.opts['spm_db']): log.error('No database at {0}, cannot remove {1}'.format( self.opts['spm_db'], package)) return # Look at local repo index pkg_info = self.pkgdb['{0}.info'.format(self.db_prov)](package, self.db_conn) if pkg_info is None: print('package {0} not installed'.format(package)) return # Find files that have not changed and remove them files = self.pkgdb['{0}.list_files'.format(self.db_prov)](package, self.db_conn) dirs = [] for filerow in files: if os.path.isdir(filerow[0]): dirs.append(filerow[0]) continue with salt.utils.fopen(filerow[0], 'r') as fh_: file_hash = hashlib.sha1() file_hash.update(fh_.read()) digest = file_hash.hexdigest() if filerow[1] == digest: log.trace('Removing file {0}'.format(filerow[0])) self.pkgfiles['{0}.remove_file'.format(self.files_prov)]( filerow[0], self.files_conn) else: log.trace('Not removing file {0}'.format(filerow[0])) self.pkgdb['{0}.unregister_file'.format(self.db_prov)]( filerow[0], self.db_conn) # Clean up directories for dir_ in sorted(dirs, reverse=True): self.pkgdb['{0}.unregister_file'.format(self.db_prov)]( dir_, self.db_conn) try: log.trace('Removing directory {0}'.format(dir_)) os.rmdir(dir_) except OSError: # Leave directories in place that still have files in them log.trace( 'Cannot remove directory {0}, probably not empty'.format( dir_)) self.pkgdb['{0}.unregister_pkg'.format(self.db_prov)](package, self.db_conn)
__pillar__ = __opts__['pepa_pillar'] if args.pillar: __pillar__.update(yaml.load(args.pillar)) # Validate or not if args.validate: __opts__['pepa_validate'] = True if args.query_api: import requests import getpass username = args.username password = args.password if username is None: username = input('Username: '******'Authenticate REST API') auth = {'username': username, 'password': password, 'eauth': 'pam'} request = requests.post(args.url + '/login', auth) if not request.ok: raise RuntimeError('Failed to authenticate to SaltStack REST API: {0}'.format(request.text)) response = request.json() token = response['return'][0]['token'] log.info('Request Grains from REST API') headers = {'X-Auth-Token': token, 'Accept': 'application/json'}