def set_browser(self): """ set the browser settings """ profile = webdriver.FirefoxProfile() try: if not self.tor: logger.info(set_color( "setting the browser..." )) profile.set_preference("general.useragent.override", self.agent) browser = webdriver.Firefox(profile, proxy=self.__set_proxy()) elif self.xforward: profile = self.__set_x_forward(profile) browser = webdriver.Firefox(profile, proxy=self.__set_proxy()) else: logger.info(set_color( "setting the Tor browser emulation..." )) profile = self.__tor_browser_emulation(profile) browser = webdriver.Firefox(profile) except (OSError, WebDriverException): if not self.tor: profile.set_preference("general.useragent.override", self.agent) browser = webdriver.Firefox(profile, proxy=self.__set_proxy(), executable_path=whichcraft.which("geckodriver")) elif self.xforward: profile = self.__set_x_forward(profile) browser = webdriver.Firefox(profile, proxy=self.__set_proxy()) else: profile = self.__tor_browser_emulation(profile) browser = webdriver.Firefox(profile, executable_path=whichcraft.which("geckodriver")) return browser
def autoconf_run(working_dir): """Run autoconf binaries corresponding to the platform. Args: working_dir (Path): Directory to be set as the current working directory """ if platform.system() == "Darwin": # Total hack to support new and old Homebrew configs, we can probably just call autoconf213 if which("brew"): autoconf213_mac_bin = "/usr/local/Cellar/autoconf213/2.13/bin/autoconf213" else: autoconf213_mac_bin = which("autoconf213") if not Path(autoconf213_mac_bin).is_file(): autoconf213_mac_bin = "autoconf213" subprocess.run([autoconf213_mac_bin], check=True, cwd=str(working_dir)) elif platform.system() == "Linux": if which("autoconf2.13"): subprocess.run(["autoconf2.13"], check=True, cwd=str(working_dir)) elif which("autoconf-2.13"): subprocess.run(["autoconf-2.13"], check=True, cwd=str(working_dir)) elif which("autoconf213"): subprocess.run(["autoconf213"], check=True, cwd=str(working_dir)) elif platform.system() == "Windows": # Windows needs to call sh to be able to find autoconf. subprocess.run(["sh", "autoconf-2.13"], check=True, cwd=str(working_dir))
def get_java_path(): global jpath if whichcraft.which('java'): jpath = whichcraft.which('java') else: raise Exception('Java 环境配置异常 请检查电脑Java环境配置') return jpath
def _graphical_sudo(self): from whichcraft import which if which('pkexec'): return ['pkexec'] elif which('gksudo'): return ['gksudo', '--'] return ['sudo', '--']
def forward_ports(remote_host, local_host, local_listen_ports, remote_listen_ports): """Forwards ports such that multiplayer works between machines. Args: remote_host: Where to ssh to. local_host: "127.0.0.1" or "::1". local_listen_ports: Which ports to listen on locally to forward remotely. remote_listen_ports: Which ports to listen on remotely to forward locally. Returns: The ssh process. Raises: ValueError: if it can't find ssh. """ if ":" in local_host and not local_host.startswith("["): local_host = "[%s]" % local_host ssh = whichcraft.which("ssh") or whichcraft.which("plink") if not ssh: raise ValueError("Couldn't find an ssh client.") args = [ssh, remote_host] for local_port in local_listen_ports: args += ["-L", "%s:%s:%s:%s" % (local_host, local_port, local_host, local_port)] for remote_port in remote_listen_ports: args += ["-R", "%s:%s:%s:%s" % (local_host, remote_port, local_host, remote_port)] logging.info("SSH port forwarding: %s", " ".join(args)) return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, close_fds=(os.name == "posix"))
def then_update_repository_with_packages(ctx, repository): """ Examples: Feature: Working with repositories Given I update http repository base with packages | Package | Tag | Value | | foo | | | Given I update http repository "updates" with packages | Package | Tag | Value | | foo | Version | 2.1 | | foo v3 | Version | 3.1 | """ packages = table_utils.parse_skv_table(ctx, HEADINGS_REPO, PKG_TAGS, PKG_TAGS_REPEATING) rpmbuild = which("rpmbuild") ctx.assertion.assertIsNotNone(rpmbuild, "rpmbuild is required") createrepo = which("createrepo_c") ctx.assertion.assertIsNotNone(createrepo, "createrepo_c is required") repodir = repo_utils.get_repo_dir(repository) tmpdir = repodir srpm_tmpdir = '{}-source'.format(tmpdir.rstrip('/')) template = JINJA_ENV.from_string(PKG_TMPL) for name, settings in packages.items(): name = name.split()[0] # cut-off the pkg name _suffix_ to allow defining multiple package versions disttag = "" if '/' in name: # using the module/pkgname notation, module would be placed to a disttag (module, name) = name.split('/', 1) disttag = ".{}".format(module) # before processing the template # lower all characters # replace '%' in Tag name with '_' # replace '(' in Tag name with '_' # delete all ')' in Tag settings = {k.lower().replace('%', '_').replace('(', '_').replace(')', ''): v for k, v in settings.items()} ctx.text = template.render(name=name, disttag=disttag, **settings) fname = "{!s}/{!s}.spec".format(tmpdir, name) step_a_file_filepath_with(ctx, fname) buildname = '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm' if 'arch' not in settings or settings['arch'] == 'noarch': cmd = "{!s} --define '_rpmdir {!s}' --define '_srcrpmdir {!s}' \ --define '_build_name_fmt {!s}' -ba {!s}" \ .format(rpmbuild, tmpdir, srpm_tmpdir, buildname, fname) else: cmd = "setarch {!s} {!s} --define '_rpmdir {!s}' --define '_srcrpmdir {!s}' \ --define '_build_name_fmt {!s}' --target {!s} -ba {!s}" \ .format(settings['arch'], rpmbuild, tmpdir, srpm_tmpdir, buildname, settings['arch'], fname) step_i_successfully_run_command(ctx, cmd) file_utils.set_dir_content_ownership(ctx, repodir, 'root') # change file ownership to root so we can change it cmd = "{!s} --update {!s}".format(createrepo, repodir) step_i_successfully_run_command(ctx, cmd) file_utils.set_dir_content_ownership(ctx, repodir) # restore file ownership
def find_path(): if sys.platform in ['win32', 'win64']: # It doesn't work well passing the .bat file to Popen, so we get the actual .exe bat_path = wch.which('electron') return os.path.join(bat_path, r'..\node_modules\electron\dist\electron.exe') elif sys.platform in ['darwin', 'linux']: # This should work find... return wch.which('electron') else: return None
def find_path(): if sys.platform in ["win32", "win64"]: # It doesn't work well passing the .bat file to Popen, so we get the actual .exe bat_path = wch.which("electron") return os.path.join(bat_path, r"..\node_modules\electron\dist\electron.exe") elif sys.platform in ["darwin", "linux"]: # This should work find... return wch.which("electron") else: return None
def _find_path(self): if sys.platform in ['win32', 'win64']: # It doesn't work well passing the .bat file to Popen, so we get the actual .exe bat_path = whichcraft.which('electron') if bat_path is None: return None return os.path.join(bat_path, r'..\node_modules\electron\dist\electron.exe') elif sys.platform in ['darwin', 'linux']: return whichcraft.which('electron') else: return None
def get_context_data(self, **kwargs): context = super(SetupView, self).get_context_data(**kwargs) if which('python') != '': context['python'] = which('python') else: context['nopython'] = None if which('ansible') != '': context['ansible'] = which('ansible') else: context['noansible'] = None if which('pip') != '': context['pip'] = which('pip') else: context['nopip'] = None if which('sshpass') != '': context['sshpass'] = which('sshpass') else: context['nosshpass'] = None name = "var.yaml" curDir = "{0}/".format(settings.BASE_DIR.rstrip("/")) path = curDir + name if os.path.exists(path): with open(path ,'r') as f: file = yaml.load(f) context['file'] = file return context
def get_binary(name): binaries_dir = os.path.realpath( os.path.join(os.path.dirname(__file__), '..', 'bin')) exe = None installed_exe = which(name) if installed_exe and os.path.isfile(installed_exe): return installed_exe else: if name == 'ffprobe': dir_name = 'ffmpeg' else: dir_name = name if platform.system() == "Windows": # Windows exe = os.path.abspath( os.path.join(binaries_dir, "Windows", "i386", dir_name, "%s.exe" % name)) elif platform.system() == "Darwin": # MacOSX exe = os.path.abspath( os.path.join(binaries_dir, "MacOSX", "i386", dir_name, name)) elif platform.system() == "Linux": # Linux exe = os.path.abspath( os.path.join(binaries_dir, "Linux", platform.machine(), dir_name, name)) if exe and os.path.isfile(exe): return exe else: raise BinaryNotFound
def find_tools(to_search=("sqlmap", "nmap"), directory="{}/bin/paths", filename="path_config.ini"): global stop_animation lib.core.settings.create_dir(directory.format(os.getcwd())) full_path = "{}/{}".format(directory.format(os.getcwd()), filename) cfgfile = open(full_path, "a+") parser = ConfigParser.ConfigParser() path_schema = {} for item in to_search: path_obj = whichcraft.which(item) if path_obj is not None: path_schema[item] = path_obj else: path_schema[item] = None for key, value in path_schema.iteritems(): if value is None: stop_animation = True print("\n") provided_path = lib.core.common.prompt( "what is the full path to {} on your system".format(key)) path_schema[key] = provided_path for program, path in path_schema.iteritems(): parser.add_section(program) parser.set(program, "path", path) parser.write(cfgfile) cfgfile.close()
def is_vcs_installed(repo_type): """ Check if the version control system for a repo type is installed. :param repo_type: """ return bool(which(repo_type))
def __enter__(self): # TODO: Use shutil directly when Python 2.7 is removed from whichcraft import which self.patches.append( patch('whichcraft.which', lambda cmd: dict(git=self.executable).get(cmd, which(cmd)))) return super(Git, self).__enter__()
def step_a_file_with_type_added_into_repository(ctx, filepath, mdtype, repository): """ Example: Given repository "base" with packages | Package | Tag | Value | | TestA | Version | 1 | And a file "metadata.ini" with type "newmd" added into repository "base" \"\"\" [example] TestA = 1 \"\"\" """ # verify that modifyrepo_c is present modifyrepo = which("modifyrepo_c") ctx.assertion.assertIsNotNone(modifyrepo, "modifyrepo_c is required") repodir = repo_utils.get_repo_dir(repository) if not os.path.isfile(filepath): ctx.assertion.assertIsNotNone(ctx.text, "Multiline text is not provided") tmpdir = tempfile.mkdtemp() filepath = os.path.join(tmpdir, os.path.basename(filepath)) with open(filepath, 'w') as fw: fw.write(ctx.text) file_utils.set_dir_content_ownership(ctx, repodir, 'root') # change file ownership to root so we can change it cmd = "{} --mdtype={} {} {}".format(modifyrepo, mdtype, filepath, os.path.join(repodir, "repodata")) step_i_successfully_run_command(ctx, cmd) file_utils.set_dir_content_ownership(ctx, repodir) # restore file ownership
def vlc_check(): vlc_location = which('vlc') if vlc_location == None: raise(Exception("CRITICAL: VLC not found. Please install it and try again.")) else: print("VLC found at {0} - OK!".format(vlc_location)) return
def __init__(self, meka_classifier=None, weka_classifier=None, java_command=None, meka_classpath=None): super(Meka, self).__init__() self.java_command = java_command if self.java_command is None: # TODO: this will not be needed once we're python 3 ready - we will # use it only in python 2.7 cases from whichcraft import which self.java_command = which("java") if self.java_command is None: raise ValueError("Java not found") self.meka_classpath = meka_classpath if self.meka_classpath is None: self.meka_classpath = os.environ.get('MEKA_CLASSPATH') if self.meka_classpath is None: raise ValueError("No meka classpath defined") self.meka_classifier = meka_classifier self.verbosity = 5 self.weka_classifier = weka_classifier self.output = None self.warnings = None self.require_dense = [False, False] self.copyable_attrs = ['meka_classifier', 'weka_classifier', 'java_command', 'meka_classpath'] self.clean()
def executable(cls, program): # TODO: Use shutil directly when Python 2.7 is removed from whichcraft import which path = which(program) if path is None: raise OSError("Cannot find '{}' program".format(program)) return os.path.realpath(path)
def tox_configure(config): for py in config.envlist: interpreter = py[py.index('py'): py.index('py') + 4] if not which('python%s.%s' % tuple(interpreter[2:])): # install interpreter print(interpreter)
def is_tool(name): """! Check whether an executable exists on PATH. @param name Name of the executable @return True if executable exists, False otherwise """ from whichcraft import which return which(name) is not None
def check_for_command(command): """ Check for command. :param command: Command (str) :rtype: True/False """ return which(command) is not None
def find_path(): if sys.platform in ['win32', 'win64']: return r'..\node_modules\electron\dist\electron.exe' elif sys.platform in ['darwin', 'linux']: # This should work find... return wch.which('electron') else: return None
def path(self): """Find the path of the bgpq3 executable.""" self.log.debug(msg="determining bgpq3 executable path") try: return self.opts["bgpq3_path"] except KeyError: self.log.debug(msg="no configured path, using system default") return which("bgpq3")
def __init__(self, executable=None): if not executable: executable = which('komondor_main') self.executable = executable if not (self.executable and os.path.isfile(self.executable)): raise ValueError( "Komondor executable {} not found.".format(executable))
def test_ocaml_version_has_list_targets(self): exe = GUP_EXES[0] if not os.path.isabs(exe): from whichcraft import which exe = which(exe) is_ocaml = os.path.join("ocaml", "bin") in exe if not is_ocaml: assert os.path.join("python", "bin") in exe or os.path.join("test","bin") in exe, ("unknown exe: %s" % exe) self.assertEqual(has_feature("list-targets"), is_ocaml)
def which(executable): """ Find `executable` in ``node_modules/.bin/`` of current Python environment. :return: Absolute ``path.Path`` instance or ``None`` """ path = whichcraft.which(executable, path=NODE_MODULES_DIR / '.bin') if path is not None: return Path(path)
def print_machine_info(): """Log information about the machine.""" print("Platform details: %s" % " ".join(platform.uname())) print("hg info: %s" % subprocess.run( ["hg", "-q", "version"], check=True, stdout=subprocess.PIPE).stdout.decode("utf-8", errors="replace").rstrip()) if which("gdb"): gdb_version = subprocess.run(["gdb", "--version"], stdout=subprocess.PIPE).stdout.decode( "utf-8", errors="replace") print("gdb info: %s" % gdb_version.split("\n")[0]) if which("git"): print("git info: %s" % subprocess.run( ["git", "version"], check=True, stdout=subprocess.PIPE).stdout.decode("utf-8", errors="replace").rstrip()) print("Python version: %s" % sys.version.split()[0]) print("Number of cores visible to OS: %d" % multiprocessing.cpu_count()) if sys.version_info.major == 2: rootdir_free_space = psutil.disk_usage("/").free / (1024**3) else: rootdir_free_space = shutil.disk_usage("/").free / (1024**3) # pylint: disable=no-member print("Free space (GB): %.2f" % rootdir_free_space) hgrc_path = Path("~/.hg/hgrc").expanduser() if hgrc_path.is_file(): print("The hgrc of this repository is:") with io.open(str(hgrc_path), "r", encoding="utf-8", errors="replace") as f: hgrc_contents = f.readlines() for line in hgrc_contents: print(line.rstrip()) try: # resource library is only applicable to Linux or Mac platforms. import resource # pylint: disable=import-error # pylint: disable=no-member print("Corefile size (soft limit, hard limit) is: %r" % (resource.getrlimit(resource.RLIMIT_CORE), )) except ImportError: print("Not checking corefile size as resource module is unavailable")
def get_binary(name): installed_exe = which(name) if installed_exe and os.path.isfile(installed_exe): logging.debug('BAZARR returning this binary: {}'.format(installed_exe)) return installed_exe else: logging.debug('BAZARR binary not found in path, searching for it...') binaries_dir = os.path.realpath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'bin')) system = platform.system() machine = platform.machine() dir_name = name # deals with exceptions if platform.system() == "Windows": # Windows machine = "i386" name = "%s.exe" % name elif platform.system() == "Darwin": # MacOSX system = 'MacOSX' if name in ['ffprobe', 'ffprobe.exe']: dir_name = 'ffmpeg' exe_dir = os.path.abspath(os.path.join(binaries_dir, system, machine, dir_name)) exe = os.path.abspath(os.path.join(exe_dir, name)) binaries_json = get_binaries_from_json() binary = next((item for item in binaries_json if item['system'] == system and item['machine'] == machine and item['directory'] == dir_name and item['name'] == name), None) if not binary: logging.debug('BAZARR binary not found in binaries.json') raise BinaryNotFound else: logging.debug('BAZARR found this in binaries.json: {}'.format(binary)) if os.path.isfile(exe) and md5(exe) == binary['checksum']: logging.debug('BAZARR returning this existing and up-to-date binary: {}'.format(exe)) return exe else: try: logging.debug('BAZARR creating directory tree for {}'.format(exe_dir)) os.makedirs(exe_dir, exist_ok=True) logging.debug('BAZARR downloading {0} from {1}'.format(name, binary['url'])) r = requests.get(binary['url']) logging.debug('BAZARR saving {0} to {1}'.format(name, exe_dir)) with open(exe, 'wb') as f: f.write(r.content) if system != 'Windows': logging.debug('BAZARR adding execute permission on {}'.format(exe)) st = os.stat(exe) os.chmod(exe, st.st_mode | stat.S_IEXEC) except Exception: logging.exception('BAZARR unable to download {0} to {1}'.format(name, exe_dir)) raise BinaryNotFound else: logging.debug('BAZARR returning this new binary: {}'.format(exe)) return exe
def test_ocaml_version_has_list_targets(self): exe = GUP_EXES[0] if not os.path.isabs(exe): from whichcraft import which exe = which(exe) is_ocaml = os.path.join("ocaml", "bin") in exe if not is_ocaml: assert os.path.join("python", "bin") in exe or os.path.join( "test", "bin") in exe, ("unknown exe: %s" % exe) self.assertEqual(has_feature("list-targets"), is_ocaml)
def prereqs(): programs = ["python", "samtools", "STAR"] ready = True for i in range(0, len(programs)): if which(programs[i]) is None: print(programs[i] + " not installed. Please install " + programs[i]) ready = False return ready
def find_application(to_find, default_search_path="/", proc_num=25, given_search_path=None, verbose=False): """ find an application on the users system if it is not in their PATH or not path is given """ retval = set() if whichcraft.which(to_find) is None: logger.error( set_color( "{} not in your PATH, what kind of hacker are you?! " "defaulting to root search, this can take awhile...".format( to_find), level=40)) if verbose: logger.debug( set_color( "starting {} processes to search for '{}' starting at '{}'..." .format( proc_num, to_find, default_search_path if given_search_path is None else given_search_path), level=10)) pool = multiprocessing.Pool(proc_num) walker = os.walk(default_search_path) file_data_gen = itertools.chain.from_iterable( (os.path.join(root, f) for f in files) for root, sub, files in walker) results = pool.map(worker, file_data_gen) for data in results: if data is not None: retval.add(data) if len(retval) == 0: raise lib.errors.ApplicationNotFound( "unable to find '{}' on your system, install it first...". format(to_find)) else: return list(retval) else: return whichcraft.which(to_find)
def build(squirrel_version, delta=True): logging.info('Build MicroDrop launcher executable') cwd = os.getcwd() os.chdir('launcher') try: sp.check_call('msbuild.bat') finally: os.chdir(cwd) logging.info('Download `nuget v3.5.0` (to work around NuGet/Home#7188 and ' 'NuGet/Home#5016).') urlretrieve('https://dist.nuget.org/win-x86-commandline/v3.5.0/nuget.exe', 'nuget.exe') logging.info('Create NuGet package.') # Strip version suffix (e.g., `rc1`, `a1`, etc.) since `nuget` does not # support them. sp.check_call(['./nuget.exe', 'pack', './Package.nuspec', '-Version', squirrel_version]) logging.info('Generate Squirrel release.') squirrel_com = whichcraft.which('Squirrel.com') if squirrel_com is None: # Squirrel.com was not found on system path. Try to find version from # Conda package. squirrel_com = whichcraft.which('Squirrel.com', path=r'%s\Library\usr\bin\squirrel;' % os.environ['CONDA_PREFIX']) if squirrel_com is None: # Conda packaged Squirrel.com was not found. print('`Squirrel.com` was not found.', file=sys.stderr) sys.exit(-1) command = [squirrel_com, '--no-msi', '-i', 'launcher/microdrop.ico', '-g', 'microdrop-installation-splash.gif', '--releasify', 'MicroDrop.%s.nupkg' % squirrel_version] if not delta: command.insert(1, '--no-delta') logging.info('calling: `%s`', sp.list2cmdline(command)) sp.check_call(command) logging.info('Done')
def check_xvfb(exc="Xvfb"): """ test for xvfb on the users system """ if whichcraft.which(exc) is None: lib.settings.logger.info(lib.settings.set_color( "installing Xvfb, required by pyvirutaldisplay..." )) subprocess.call(["sudo", "apt-get", "install", "xvfb"]) else: return True
def find_chrome_linux(): import shutil as shu chrome_names = [ 'chromium-browser', 'chromium', 'google-chrome', 'google-chrome-stable' ] for name in chrome_names: chrome = which(name) if chrome is not None: return chrome return None
def find_chrome_linux(): import whichcraft as wch chrome_names = [ 'chromium-browser', 'chromium', 'google-chrome', 'google-chrome-stable' ] for name in chrome_names: chrome = wch.which(name) if chrome is not None: return chrome return None
def run(self): if which('mongod'): cwd = os.path.join(os.path.dirname(__file__), '..', '..') dbpath = os.path.join('/', 'data', 'db') if not os.path.exists(dbpath): dbpath = os.path.join(cwd, 'db') logpath = os.path.join(dbpath, 'mongodb-mpcontribs.log') call(['mongod', '--dbpath', dbpath, '--logpath', logpath, '--logappend']) print('mongod started.') else: print('install MongoDB to use local DB instance.')
def find_chrome_linux(): import whichcraft as wch chrome_names = ['chromium-browser', 'chromium', 'google-chrome', 'google-chrome-stable'] for name in chrome_names: chrome = wch.which(name) if chrome is not None: return chrome return None
def default_evaluator(): """ Find and instantiate best available evaluator. """ from .barvinok import BarvinokEvaluator from .latte import LatteEvaluator # first try environment variables if 'BARVIKRON_BARVINOK' in os.environ: return BarvinokEvaluator(os.environ['BARVIKRON_BARVINOK']) if 'BARVIKRON_LATTE' in os.environ: return LatteEvaluator(os.environ['BARVIKRON_LATTE']) # then try to find executables path = whichcraft.which('barvinok_count') if path: return BarvinokEvaluator(path) path = whichcraft.which('count') if path: return LatteEvaluator(path) raise NoEvaluatorFound()
def check_r(): if len(sys.argv) == 3: r_path = sys.argv[2] elif sys.platform == 'win32': r_path = r'C:\R\R-2.15.1\bin\x64\Rcmd.exe' elif sys.platform in ('linux', 'darwin'): r_path = which('RScript') # might return None else: raise Exception("platform %r not supported (yet)" % sys.platform) if r_path is None or not os.path.exists(r_path): print print "could not find R interpreter at %r" % r_path print_help() sys.exit(1) return r_path
def step_gpg_key_signed_by(ctx, signed_key, signing_key): """ Signs one GPG with another GPG key producing a detached signature file. Examples: .. code-block:: gherkin Feature: GPG key signing Scenario: Sign one GPG with another Given GPG key "James Bond" And GPG key "M" And GPG key "James Bond" signed by "M" """ signed_key_path = GPGKEY_FILEPATH_TMPL.format(signed_key, "pubkey") gpgbin = which("gpg2") cmd = "{!s} --detach-sig --armor --default-key '{!s}' '{!s}'".format(gpgbin, signing_key, signed_key_path) step_i_successfully_run_command(ctx, cmd)
def step_gpg_key_imported_in_rpm_database(ctx, name_real): """ Imports the public key for the previously generated GPG key into the rpm database. Examples: .. code-block:: gherkin Feature: Package signatures Scenario: Setup repository with signed packages Given GPG key "James Bond" And GPG key "James Bond" imported in rpm database And repository "TestRepo" with packages signed by "James Bond" | Package | Tag | Value | | TestA | | | """ pubkey = GPGKEY_FILEPATH_TMPL.format(name_real, 'pubkey') rpm = which("rpm") cmd = "{!s} --import '{!s}'".format(rpm, pubkey) step_i_successfully_run_command(ctx, cmd)
def given_repository_metadata_signed_by(ctx, repository, gpgkey): """ Signs repodata.xml for a given repository using the given GPG key and updates the repo file with gpgkey URL. Should be used after the repo is created or updated. .. note:: The default dnf settings is *repo_gpgcheck = False*. Examples: .. code-block:: gherkin Feature: Repodata signatures Scenario: Setup repository with signed metadata Given GPG key "JamesBond" And GPG key "JamesBond" imported in rpm database And repository "TestRepo" with packages signed by "JamesBond" | Package | Tag | Value | | TestA | | | And repository "TestRepo" metadata signed by "JamesBond" And a repo file of repository "TestRepo" modified with | Key | Value | | repo_gpgcheck | True | """ # sign the repomd.xml file repodir = repo_utils.get_repo_dir(repository) gpg = which("gpg2") cmd = "{!s} --detach-sig --armor --default-key '{!s}' {!s}/repodata/repomd.xml".format(gpg, gpgkey, repodir) step_i_successfully_run_command(ctx, cmd) # update the repo file with path to the gpg key pubkey = GPGKEY_FILEPATH_TMPL.format(gpgkey, "pubkey") keyurl = "file://{!s}".format(pubkey) repofile = REPO_TMPL.format(repository) conf = file_utils.read_ini_file(repofile) conf.set(repository, "gpgkey", keyurl) file_utils.create_file_with_contents(repofile, conf)
def given_repository_with_packages(ctx, repository): """ Builds dummy noarch packages, creates repo and *.repo* file. .. note:: Requires *rpmbuild* and *createrepo_c*. Requires table with following headers: ========= ===== ======= Package Tag Value ========= ===== ======= *Tag* is tag in RPM. Supported ones are: ============= =============== Tag Default value ============= =============== Summary Empty Version 1 Release 1 License Public Domain BuildRequires [] Requires [] Obsoletes [] Provides [] Conflicts [] ============= =============== All packages are built during step execution. .. note:: *BuildRequires* are ignored for build-time (*rpmbuild* is executed with ``--nodeps`` option). Examples: .. code-block:: gherkin Feature: Working with repositories Background: Repository base with dummy package Given repository base with packages | Package | Tag | Value | | foo | | | Scenario: Installing dummy package from background When I enable repository base Then I successfully run "dnf -y install foo" """ packages = table_utils.parse_skv_table(ctx, HEADINGS_REPO, PKG_TAGS, PKG_TAGS_REPEATING) rpmbuild = which("rpmbuild") ctx.assertion.assertIsNotNone(rpmbuild, "rpmbuild is required") createrepo = which("createrepo_c") ctx.assertion.assertIsNotNone(createrepo, "createrepo_c is required") tmpdir = tempfile.mkdtemp() template = JINJA_ENV.from_string(PKG_TMPL) for name, settings in packages.items(): settings = {k.lower(): v for k, v in settings.items()} ctx.text = template.render(name=name, **settings) fname = "{!s}/{!s}.spec".format(tmpdir, name) step_a_file_filepath_with(ctx, fname) cmd = "{!s} --define '_rpmdir {!s}' -bb {!s}".format( rpmbuild, tmpdir, fname) step_i_successfully_run_command(ctx, cmd) cmd = "{!s} {!s}".format(createrepo, tmpdir) step_i_successfully_run_command(ctx, cmd) repofile = REPO_TMPL.format(repository) ctx.table = Table(HEADINGS_INI) ctx.table.add_row([repository, "name", repository]) ctx.table.add_row(["", "enabled", "False"]) ctx.table.add_row(["", "gpgcheck", "False"]) ctx.table.add_row(["", "baseurl", "file://{!s}".format(tmpdir)]) step_an_ini_file_filepath_with(ctx, repofile)
def given_repository_with_packages(ctx, rtype, repository, gpgkey=None): """ Builds dummy packages, creates repo and *.repo* file. Supported repo types are http, https, ftp or local (default). Supported architectures are x86_64, i686 and noarch (default). .. note:: *https* repositories are configured to use certificates at following locations: /etc/pki/tls/certs/testcerts/ca/cert.pem /etc/pki/tls/certs/testcerts/client/key.pem /etc/pki/tls/certs/testcerts/client/cert.pem .. note:: Requires *rpmbuild* and *createrepo_c*. Requires table with following headers: ========= ===== ======= Package Tag Value ========= ===== ======= *Tag* is tag in RPM. Supported ones are: ============= =============== Tag Default value ============= =============== Summary Empty Version 1 Release 1 Arch x86_64 License Public Domain BuildRequires [] Requires [] Obsoletes [] Provides [] Conflicts [] ============= =============== All packages are built during step execution. .. note:: *BuildRequires* are ignored for build-time (*rpmbuild* is executed with ``--nodeps`` option). Examples: .. code-block:: gherkin Feature: Working with repositories Background: Repository base with dummy package Given http repository base with packages | Package | Tag | Value | | foo | | | Scenario: Installing dummy package from background When I enable repository base Then I successfully run "dnf -y install foo" """ packages = table_utils.parse_skv_table(ctx, HEADINGS_REPO, PKG_TAGS, PKG_TAGS_REPEATING) rpmbuild = which("rpmbuild") ctx.assertion.assertIsNotNone(rpmbuild, "rpmbuild is required") createrepo = which("createrepo_c") ctx.assertion.assertIsNotNone(createrepo, "createrepo_c is required") if rtype == 'http' or rtype == 'https': tmpdir = tempfile.mkdtemp(dir='/var/www/html') repopath = os.path.join('localhost', os.path.basename(tmpdir)) elif rtype == 'ftp': tmpdir = tempfile.mkdtemp(dir='/var/ftp/pub') repopath = os.path.join('localhost/pub', os.path.basename(tmpdir)) else: tmpdir = tempfile.mkdtemp() repopath = tmpdir template = JINJA_ENV.from_string(PKG_TMPL) for name, settings in packages.items(): settings = {k.lower(): v for k, v in settings.items()} ctx.text = template.render(name=name, **settings) fname = "{!s}/{!s}.spec".format(tmpdir, name) step_a_file_filepath_with(ctx, fname) buildname = '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm' if 'arch' not in settings or settings['arch'] == 'noarch': cmd = "{!s} --define '_rpmdir {!s}' --define '_build_name_fmt {!s}' -bb {!s}".format( rpmbuild, tmpdir, buildname, fname) else: cmd = "setarch {!s} {!s} --define '_rpmdir {!s}' --define '_build_name_fmt {!s}' --target {!s} -bb {!s}".format( settings['arch'], rpmbuild, tmpdir, buildname, settings['arch'], fname) step_i_successfully_run_command(ctx, cmd) if gpgkey: # sign all rpms built rpmsign = which("rpmsign") rpms = glob.glob("{!s}/*.rpm".format(tmpdir)) cmd = "{!s} --addsign --key-id '{!s}' {!s}".format(rpmsign, gpgkey, ' '.join(rpms)) step_i_successfully_run_command(ctx, cmd) cmd = "{!s} {!s}".format(createrepo, tmpdir) step_i_successfully_run_command(ctx, cmd) # set proper directory content ownership file_utils.set_dir_content_ownership(ctx, tmpdir) repofile = REPO_TMPL.format(repository) ctx.table = Table(HEADINGS_INI) ctx.table.add_row([repository, "name", repository]) ctx.table.add_row(["", "enabled", "False"]) ctx.table.add_row(["", "baseurl", "{!s}://{!s}".format(rtype, repopath)]) if gpgkey: ctx.table.add_row(["", "gpgcheck", "True"]) else: ctx.table.add_row(["", "gpgcheck", "False"]) if rtype == 'https': ctx.table.add_row(["", "sslcacert", "/etc/pki/tls/certs/testcerts/ca/cert.pem"]) ctx.table.add_row(["", "sslclientkey", "/etc/pki/tls/certs/testcerts/client/key.pem"]) ctx.table.add_row(["", "sslclientcert", "/etc/pki/tls/certs/testcerts/client/cert.pem"]) step_an_ini_file_filepath_with(ctx, repofile)
def check_stow(): if which('stow') is None: raise click.ClickException("GNU Stow is not installed")
def given_repository_with_packages(ctx, enabled, rtype, repository, gpgkey=None): """ Builds dummy packages, creates repo and *.repo* file. Supported repo types are http, https, ftp or local (default). Supported architectures are x86_64, i686 and noarch (default). .. note:: Along with the repository also *-source repository with src.rpm packages is built. The repository is disabled. .. note:: *https* repositories are configured to use certificates at following locations: /etc/pki/tls/certs/testcerts/ca/cert.pem /etc/pki/tls/certs/testcerts/client/key.pem /etc/pki/tls/certs/testcerts/client/cert.pem .. note:: Requires *rpmbuild* and *createrepo_c*. Requires table with following headers: ========= ===== ======= Package Tag Value ========= ===== ======= *Tag* is tag in RPM. Supported ones are: ================== =============== Tag Default value ================== =============== Summary Empty Version 1 Release 1 Arch x86_64 License Public Domain BuildRequires [] Requires [] Recommends [] Suggests [] Supplements [] Enhances [] Requires(pretrans) [] Requires(pre) [] Requires(post) [] Requires(preun) [] Obsoletes [] Provides [] Conflicts [] %pretrans Empty %pre Empty %post Empty %preun Empty %postun Empty %posttrans Empty ================== =============== All packages are built during step execution. .. note:: *BuildRequires* are ignored for build-time (*rpmbuild* is executed with ``--nodeps`` option). If there is a space character in the package name only the preceding part is used. .. note:: Scriptlets such as *%pre* can be listed multiple time so that the entering of a multi-line script is more comfortable. Examples: .. code-block:: gherkin Feature: Working with repositories Background: Repository base with dummy package Given http repository base with packages | Package | Tag | Value | | foo | | | Scenario: Installing dummy package from background When I enable repository base Then I successfully run "dnf -y install foo" Scenario: Creating repository with multiple package versions Given http repository "updates" with packages | Package | Tag | Value | | foo | Version | 2.0 | | foo v3 | Version | 3.0 | Scenario: Creating a package with %pre scriptlet failing Given http repository "more_updates" with packages | Package | Tag | Value | | foo | Version | 4.0 | | | %pre | exit 1 | """ packages = table_utils.parse_skv_table(ctx, HEADINGS_REPO, PKG_TAGS, PKG_TAGS_REPEATING) rpmbuild = which("rpmbuild") ctx.assertion.assertIsNotNone(rpmbuild, "rpmbuild is required") createrepo = which("createrepo_c") ctx.assertion.assertIsNotNone(createrepo, "createrepo_c is required") if rtype == 'http' or rtype == 'https': tmpdir = tempfile.mkdtemp(dir='/var/www/html') repopath = os.path.join('localhost', os.path.basename(tmpdir)) elif rtype == 'ftp': tmpdir = tempfile.mkdtemp(dir='/var/ftp/pub') repopath = os.path.join('localhost/pub', os.path.basename(tmpdir)) else: tmpdir = tempfile.mkdtemp() repopath = tmpdir srpm_tmpdir = '{}-source'.format(tmpdir.rstrip('/')) srpm_repopath = '{}-source'.format(repopath.rstrip('/')) os.mkdir(srpm_tmpdir) # create a directory for src.rpm pkgs template = JINJA_ENV.from_string(PKG_TMPL) for name, settings in packages.items(): name = name.split()[0] # cut-off the pkg name _suffix_ to allow defining multiple package versions disttag = "" if '/' in name: # using the module/pkgname notation, module would be placed to a disttag (module, name) = name.split('/', 1) disttag = ".{}".format(module) # before processing the template # lower all characters # replace '%' in Tag name with '_' # replace '(' in Tag name with '_' # delete all ')' in Tag settings = {k.lower().replace('%', '_').replace('(', '_').replace(')', ''): v for k, v in settings.items()} ctx.text = template.render(name=name, disttag=disttag, **settings) fname = "{!s}/{!s}.spec".format(tmpdir, name) step_a_file_filepath_with(ctx, fname) buildname = '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm' if 'arch' not in settings or settings['arch'] == 'noarch': cmd = "{!s} --define '_rpmdir {!s}' --define '_srcrpmdir {!s}' --define '_build_name_fmt {!s}' -ba {!s}".format( rpmbuild, tmpdir, srpm_tmpdir, buildname, fname) else: cmd = "setarch {!s} {!s} --define '_rpmdir {!s}' --define '_srcrpmdir {!s}' --define '_build_name_fmt {!s}' --target {!s} -ba {!s}".format( settings['arch'], rpmbuild, tmpdir, srpm_tmpdir, buildname, settings['arch'], fname) step_i_successfully_run_command(ctx, cmd) if gpgkey: # sign all rpms built rpmsign = which("rpmsign") rpms = glob.glob("{!s}/*.rpm".format(tmpdir)) srpms = glob.glob("{!s}/*.rpm".format(srpm_tmpdir)) cmd = "{!s} --addsign --key-id '{!s}' {!s} {!s}".format(rpmsign, gpgkey, ' '.join(rpms), ' '.join(srpms)) step_i_successfully_run_command(ctx, cmd) cmd = "{!s} {!s}".format(createrepo, tmpdir) step_i_successfully_run_command(ctx, cmd) cmd = "{!s} {!s}".format(createrepo, srpm_tmpdir) step_i_successfully_run_command(ctx, cmd) # set proper directory content ownership file_utils.set_dir_content_ownership(ctx, tmpdir) file_utils.set_dir_content_ownership(ctx, srpm_tmpdir) repofile = REPO_TMPL.format(repository) ctx.table = Table(HEADINGS_INI) ctx.table.add_row([repository, "name", repository]) ctx.table.add_row(["", "enabled", six.text_type(enabled)]) ctx.table.add_row(["", "baseurl", "{!s}://{!s}".format(rtype, repopath)]) if gpgkey: ctx.table.add_row(["", "gpgcheck", "True"]) else: ctx.table.add_row(["", "gpgcheck", "False"]) if rtype == 'https': ctx.table.add_row(["", "sslcacert", "/etc/pki/tls/certs/testcerts/ca/cert.pem"]) ctx.table.add_row(["", "sslclientkey", "/etc/pki/tls/certs/testcerts/client/key.pem"]) ctx.table.add_row(["", "sslclientcert", "/etc/pki/tls/certs/testcerts/client/cert.pem"]) step_an_ini_file_filepath_with(ctx, repofile) # create -source repository too srpm_repository = '{}-source'.format(repository) repofile = REPO_TMPL.format(srpm_repository) ctx.table = Table(HEADINGS_INI) ctx.table.add_row([srpm_repository, "name", srpm_repository]) ctx.table.add_row(["", "enabled", "False"]) ctx.table.add_row(["", "baseurl", "{!s}://{!s}".format(rtype, srpm_repopath)]) if gpgkey: ctx.table.add_row(["", "gpgcheck", "True"]) else: ctx.table.add_row(["", "gpgcheck", "False"]) if rtype == 'https': ctx.table.add_row(["", "sslcacert", "/etc/pki/tls/certs/testcerts/ca/cert.pem"]) ctx.table.add_row(["", "sslclientkey", "/etc/pki/tls/certs/testcerts/client/key.pem"]) ctx.table.add_row(["", "sslclientcert", "/etc/pki/tls/certs/testcerts/client/cert.pem"]) step_an_ini_file_filepath_with(ctx, repofile)
def step_updateinfo_defined_in_repository(ctx, repository): """ For a given repository creates updateinfo.xml file with described updates and recreates the repo .. note:: Requires *modifyrepo_c* and the repo to be already created. Requires table with following headers: ==== ===== ======= Id Tag Value ==== ===== ======= *Tag* is describing attributes of the respective update. Supported tags are: ============ ========================= Tag Default value ============ ========================= Title Default title of Id Type security Description Default description of Id Summary Default summary of Id Severity Low Solution Default solution of Id Rights nobody Issued 2017-01-01 00:00:01 Updated 2017-01-01 00:00:01 Reference none Package none ============ ========================= Examples: .. code-block:: gherkin Feature: Defining updateinfo in a repository @setup Scenario: Repository base with updateinfo defined Given repository "base" with packages | Package | Tag | Value | | foo | Version | 2 | | bar | Version | 2 | And updateinfo defined in repository "base" | Id | Tag | Value | | RHSA-2017-001 | Title | foo bar security update | | | Type | security | | | Description | Fixes buffer overflow | | | Summary | Critical bug is fixed | | | Severity | Critical | | | Solution | Update to the new version | | | Rights | Copyright 2017 Baz Inc | | | Reference | CVE-2017-0001 | | | Reference | BZ123456 | | | Package | foo-2 | | | Package | bar-2 | .. note:: Specifying Version or Release in Package tag is not necessary, however when multiple RPMs matches the string the last one from the sorted list is used. """ HEADINGS_GROUP = ['Id', 'Tag', 'Value'] UPDATEINFO_TAGS_REPEATING = ['Package', 'Reference'] UPDATEINFO_TAGS = ['Title', 'Type', 'Description', 'Solution', 'Summary', 'Severity', 'Rights', 'Issued', 'Updated'] + \ UPDATEINFO_TAGS_REPEATING updateinfo_table = table_utils.parse_skv_table(ctx, HEADINGS_GROUP, UPDATEINFO_TAGS, UPDATEINFO_TAGS_REPEATING) # verify that modifyrepo_c is present modifyrepo = which("modifyrepo_c") ctx.assertion.assertIsNotNone(modifyrepo, "modifyrepo_c is required") # prepare updateinfo.xml content repodir = repo_utils.get_repo_dir(repository) updateinfo_xml = repo_utils.get_updateinfo_xml(repository, updateinfo_table) # save it to the updateinfo.xml file and recreate the repodata tmpdir = tempfile.mkdtemp() with open(os.path.join(tmpdir, "updateinfo.xml"), 'w') as fw: fw.write(updateinfo_xml) file_utils.set_dir_content_ownership(ctx, repodir, 'root') # change file ownership to root so we can change it cmd = "{!s} {!s} {!s}".format(modifyrepo, os.path.join(tmpdir, 'updateinfo.xml'), os.path.join(repodir, 'repodata')) step_i_successfully_run_command(ctx, cmd) file_utils.set_dir_content_ownership(ctx, repodir) # restore file ownership
import settings from whichcraft import which import subprocess import os command = [] if which('node') is not None: command.append('node') elif which('nodejs') is not None: command.append('nodejs') else: raise Exception('NodeJS is not installed. Please install it.') command.append(os.path.join(settings.BASE_DIR, 'node_server', 'server.js')) print(' '.join(command)) p = subprocess.Popen(command) p.wait()
def test_existing_command(): cmd = which('date') assert cmd assert os.path.exists(cmd) assert os.access(cmd, os.F_OK | os.X_OK) assert not os.path.isdir(cmd)
def test_non_existing_command(): assert which('stringthatisntashellcommand') is None
def expand_exe(exe): if not os.path.isabs(exe): from whichcraft import which exe = which(exe) return exe
def step_gpg_key(ctx, name_real): """ Generates for the root user GPG key with a given identity, a.k.a. the Name-Real attribute. GPG key attributes can be optionally specified using the table with following headers: ======= ========= Tag Value ======= ========= Supported GPG key attrubutes are: ============= =============== Tag Default value ============= =============== Key-Type RSA Key-Length 2048 Subkey-Type <not present> Subkey-Length <not present> Name-Comment No Comment Name-Email dnf@noreply Expire-Date 0 ============================= .. note:: GPG key configuration is saved in a file /root/${Name-Real}.keyconf respective public key is exported to a file /root/${Name-Real}.pubkey Examples: .. code-block:: gherkin Feature: Package signatures Scenario: Setup repository with signed packages Given GPG key "James Bond" And GPG key "James Bond" imported in rpm database And repository "TestRepo" with packages signed by "James Bond" | Package | Tag | Value | | TestA | | | """ if ctx.table: # additional GPG key configuration listed in the table GPGKEY_HEADINGS = ['Tag', 'Value'] GPGKEY_TAGS = ['Key-Type', 'Key-Length', 'Subkey-Type', 'Subkey-Length', 'Name-Comment', 'Name-Email', 'Expire-Date'] gpgkey_conf_table = table_utils.parse_kv_table(ctx, GPGKEY_HEADINGS, GPGKEY_TAGS) else: # no table present gpgkey_conf_table = {} template = JINJA_ENV.from_string(GPGKEY_CONF_TMPL) settings = {k.lower().replace('-', '_'): v for k, v in gpgkey_conf_table.items()} gpgkey_conf = template.render(name_real=name_real, **settings) # write gpgkey configuration to a file fpath = GPGKEY_FILEPATH_TMPL.format(name_real, "keyconf") with open(fpath, 'w') as fw: fw.write(gpgkey_conf) # generate the GPG key gpgbin = which("gpg2") cmd = "{!s} --batch --gen-key '{!s}'".format(gpgbin, fpath) step_i_successfully_run_command(ctx, cmd) # export the public key cmd = "{!s} --export --armor '{!s}'".format(gpgbin, name_real) step_i_successfully_run_command(ctx, cmd) fpath = GPGKEY_FILEPATH_TMPL.format(name_real, "pubkey") with open(fpath, 'w') as fw: fw.write(ctx.cmd_result.stdout)
def given_package_groups_defined_in_repository(ctx, repository): """ For a given repository creates comps.xml file with described package groups and recreates the repo .. note:: Requires *createrepo_c* and the repo to be already created. Requires table with following headers: ========= ===== ======= Group Tag Value ========= ===== ======= *Tag* is describing characteristics of the respective package group.Supported tags are: ============== =============== Tag Default value ============== =============== is_default false is_uservisible true description "" mandatory [] default [] optional [] conditional [] ============== =============== Examples: .. code-block:: gherkin Feature: Installing a package group @setup Scenario: Repository base with package group minimal Given repository "base" with packages | Package | Tag | Value | | foo | | | | bar | | | | baz | | | | qux | | | And package groups defined in repository "base" | Group | Tag | Value | | minimal | mandatory | foo | | | default | bar | | | conditional | baz qux | Scenario: Installing package group from background When I enable repository "base" Then I successfully run "dnf -y group install minimal" .. note:: Conditional packages are described in a form PKG REQUIREDPKG """ HEADINGS_GROUP = ['Group', 'Tag', 'Value'] GROUP_TAGS_REPEATING = ['mandatory', 'default', 'optional', 'conditional'] GROUP_TAGS = ['is_default', 'is_uservisible', 'description'] + GROUP_TAGS_REPEATING pkg_groups = table_utils.parse_skv_table(ctx, HEADINGS_GROUP, GROUP_TAGS, GROUP_TAGS_REPEATING) createrepo = which("createrepo_c") ctx.assertion.assertIsNotNone(createrepo, "createrepo_c is required") # prepare the comps.xml comps_xml = COMPS_PREFIX template = JINJA_ENV.from_string(COMPS_TMPL) for name, settings in pkg_groups.items(): settings = {k.lower(): v for k, v in settings.items()} comps_xml += template.render(name=name, **settings) comps_xml += COMPS_SUFFIX # save comps.xml and recreate the repo repodir = repo_utils.get_repo_dir(repository) with open(os.path.join(repodir, "comps.xml"), "w") as f_comps: f_comps.write(comps_xml) file_utils.set_dir_content_ownership(ctx, repodir, 'root') # change file ownership to root so we can change it cmd = "{!s} -g comps.xml --update {!s}".format(createrepo, repodir) step_i_successfully_run_command(ctx, cmd) file_utils.set_dir_content_ownership(ctx, repodir) # restore file ownership