def _render_one_template(cls, env, template, result_filename, data, overwrite): # Get a template instance tpl = None try: logger.debug('Using template file: {0}'.format(template)) tpl = env.get_template(template) except jinja2.TemplateNotFound as e: raise exceptions.CommandException('Template {t} not found in path {p}.'.\ format(t=template, p=env.loader.searchpath)) except jinja2.TemplateError as e: raise exceptions.CommandException('Template file failure: {0}'.format(e.message)) # Check if destination file exists, overwrite if needed if os.path.exists(result_filename): if overwrite: logger.info('Overwriting the destination file {0}'.format(result_filename)) os.remove(result_filename) else: raise exceptions.CommandException('The destination file already exists: {0}'.\ format(result_filename)) # Generate an output file finally... with open(result_filename, 'w') as out: result = tpl.render(**data) out.write(result) return (True, 'success')
def resolve(cls, *deps): """ Return all dependencies which will be installed. Like a portage based implementation it just tries to get the best package available according a given spec. """ import paludis logger.info('[paludis] Resolving dependencies ...') env = paludis.EnvironmentFactory.instance.create('') fltr = paludis.Filter.And(paludis.Filter.SupportsInstallAction(), paludis.Filter.NotMasked()) to_install = set() for dep in deps: ds = paludis.parse_user_package_dep_spec(dep, env, paludis.UserPackageDepSpecOptions()) gen = paludis.Generator.Matches(ds, paludis.MatchPackageOptions()) fg = paludis.FilteredGenerator(gen, fltr) s = paludis.Selection.BestVersionOnly(fg) _to_install = set() for pkg in env[s]: _to_install.add(str(pkg)) if _to_install: to_install += _to_install else: msg = 'Package not found: {pkg}'.format(pkg=dep) raise exceptions.DependencyException(msg) cls.throw_package_list(list(to_install))
def docker_service_enable_and_run(cls): # TODO: add some conditionals for various platforms logger.info('Enabling and running docker service ...') try: cmd_str = 'bash -c "systemctl enable docker && systemctl start docker"' ClHelper.run_command(cmd_str, as_user='******') except exceptions.ClException: raise exceptions.CommandException( 'Failed to enable and run docker service.') # we need to wait until /var/run/docker.sock is created # let's wait for 30 seconds logger.info( 'Waiting for /var/run/docker.sock to be created (max 15 seconds) ...' ) success = False for i in range(0, 30): time.sleep(i * 0.5) try: ClHelper.run_command('ls /var/run/docker.sock') success = True break except exceptions.ClException: pass if not success: logger.warning( '/var/run/docker.sock doesn\'t exist, docker will likely not work!' )
def run_command(cls, cmd_str, fg=False, log_as_info=False): """Runs a command from string, e.g. "cp foo bar" """ result = None split_string = cmd_str.split() for i, s in enumerate(split_string): if '~' in s: split_string[i] = os.path.expanduser(s) # hack for cd to behave like shell cd and stay in the directory if split_string[0] == 'cd': plumbum.local.cwd.chdir(split_string[1]) else: cmd = plumbum.local[split_string[0]] fixed_args = cls._connect_quoted(split_string[1:]) fixed_args = cls._strip_trailing_quotes(fixed_args) for i in fixed_args: cmd = cmd[i] # log the invocation log_string = settings.COMMAND_LOG_STRING.format(cmd=cmd) if log_as_info: logger.info(log_string) else: logger.debug(log_string) # actually invoke the command if fg: result = cmd & plumbum.FG else: result = cmd() return result
def resolve(cls, *deps): """ Return all dependencies which will be installed. NOTE Simplified (naive) implementation will show the list of correctly spelled packages to be installed. For example 'firefox' will be resolved to 'www-client/firefox-25.0.1'... TODO ... or maybe version part must be stripped? """ import portage logger.info('[portage] Resolving dependencies ...') porttree = portage.db[portage.root]['porttree'] to_install = set() for dep in deps: res = porttree.dep_bestmatch(dep) logger.debug('{0} resolved to {1}'.format(repr(dep), repr(res))) if res: to_install.add(res) else: msg = 'Package not found or spec is invalid: {pkg}'.format(pkg=dep) raise exceptions.DependencyException(msg) cls.throw_package_list(list(to_install))
def run_command(cls, cmd_str, fg=False, log_as_info=False): """Runs a command from string, e.g. "cp foo bar" """ result = None split_string = cmd_str.split() for i, s in enumerate(split_string): if '~' in s: split_string[i] = os.path.expanduser(s) # hack for cd to behave like shell cd and stay in the directory if split_string[0] == 'cd': plumbum.local.cwd.chdir(split_string[1]) else: cmd = plumbum.local[split_string[0]] fixed_args = cls._connect_quoted(split_string[1:]) fixed_args = cls._strip_trailing_quotes(fixed_args) for i in fixed_args: cmd = cmd[i] # log the invocation log_string = settings.COMMAND_LOG_STRING.format(cmd=cmd) if log_as_info: logger.info(log_string) else: logger.debug(log_string) # actually invoke the command if fg: result = cmd & plumbum.FG else: result = cmd() return result
def resolve(cls, *args): logger.info('Resolving RPM dependencies with DNF...') import dnf import hawkey base = dnf.Base() base.conf.cachedir = tempfile.mkdtemp() base.conf.substitutions['releasever'] = platform.linux_distribution( )[1] base.read_all_repos() base.fill_sack(load_system_repo=True, load_available_repos=True) for pkg in (str(arg) for arg in args): if pkg.startswith('@'): base.group_install(pkg[1:]) else: try: res = base.sack.query().available().filter( provides=pkg).run() base.install(str(res[0])) except (hawkey.QueryException, IndexError): msg = 'Package not found: {pkg}'.format(pkg=pkg) raise exceptions.DependencyException(msg) try: base.resolve() except dnf.exceptions.Error as e: raise exceptions.DependencyException( 'Error resolving RPM dependencies with DNF: {0}'.format( utils.exc_as_decoded_string(e))) logger.debug('Installing/Updating:') to_install = [] for pkg in base.transaction.install_set: to_install.append(str(pkg)) logger.debug(str(pkg)) return to_install
def resolve(cls, *args): # TODO: we may need to rewrite this for e.g. suse, which # is rpm based, but doesn't use yum; same for install()/is_available()/can_operate() logger.info('Resolving RPM dependencies ...') import yum y = yum.YumBase() y.setCacheDir(tempfile.mkdtemp()) for pkg in args: if pkg.startswith('@'): y.selectGroup(pkg[1:]) else: try: y.install(y.returnPackageByDep(pkg)) except yum.Errors.YumBaseError: msg = 'Package not found: {pkg}'.format(pkg=pkg) logger.error(msg) raise exceptions.DependencyException(msg) y.resolveDeps() logger.debug('Installing/Updating:') to_install = [] for pkg in y.tsInfo.getMembers(): to_install.append(pkg.po.ui_envra) logger.debug(pkg.po.ui_envra) return to_install
def resolve(cls, *args): logger.info('Resolving RPM dependencies with DNF...') import dnf import hawkey base = dnf.Base() base.conf.cachedir = tempfile.mkdtemp() base.conf.substitutions['releasever'] = platform.linux_distribution()[1] base.read_all_repos() base.fill_sack(load_system_repo=True, load_available_repos=True) for pkg in (str(arg) for arg in args): if pkg.startswith('@'): base.group_install(pkg[1:]) else: try: res = base.sack.query().available().filter(provides=pkg).run() base.install(str(res[0])) except (hawkey.QueryException, IndexError): msg = 'Package not found: {pkg}'.format(pkg=pkg) raise exceptions.DependencyException(msg) try: base.resolve() except dnf.exceptions.Error as e: raise exceptions.DependencyException('Error resolving RPM dependencies with DNF: {0}'. format(utils.exc_as_decoded_string(e))) logger.debug('Installing/Updating:') to_install = [] for pkg in base.transaction.install_set: to_install.append(str(pkg)) logger.debug(str(pkg)) return to_install
def _github_create_repo(cls, **kwargs): """Create repo on GitHub. Note: the kwargs are not the global context here, but what cls.format_args returns. If repository already exists then CommandException will be raised. Raises: devassistant.exceptions.CommandException on error """ reponame = kwargs['reponame'] if reponame in map(lambda x: x.name, cls._user.get_repos()): msg = 'Repository already exists on GitHub' raise exceptions.CommandException(msg) else: try: new_repo = cls._user.create_repo(reponame) except cls._gh_module.GithubException: msg = 'Failed to create GitHub repo. This sometime happens when you delete ' msg += 'a repo and then you want to create the same one immediately. Wait ' msg += 'for few minutes and then try again.' raise exceptions.CommandException(msg) logger.info('Your new repository: {0}'.format(new_repo.html_url)) return new_repo.clone_url
def run(self): pkgs = exs = [] try: pkgs = self.kwargs['package'] except KeyError: pkgs = dapicli.get_installed_daps() if pkgs: logger.info('Updating all DAP packages ...') else: logger.info( 'No installed DAP packages found, nothing to update.') for pkg in pkgs: logger.info('Updating DAP {pkg} ...'.format(pkg=pkg)) try: updated = dapicli.install_dap( pkg, update=True, update_allpaths=self.kwargs['allpaths'], force=self.kwargs['force']) if updated: logger.info( 'DAP {pkg} successfully updated.'.format(pkg=pkg)) else: logger.info( 'DAP {pkg} is already up to date.'.format(pkg=pkg)) except exceptions.DapiError as e: exs.append(utils.exc_as_decoded_string(e)) logger.error(utils.exc_as_decoded_string(e)) if exs: raise exceptions.ExecutionException('; '.join(exs))
def _render_one_template(cls, env, template, result_filename, data, overwrite): # Get a template instance tpl = None try: logger.debug('Using template file: {0}'.format(template)) tpl = env.get_template(template) except jinja2.TemplateNotFound as e: raise exceptions.CommandException('Template {t} not found in path {p}.'.\ format(t=template, p=env.loader.searchpath)) except jinja2.TemplateError as e: raise exceptions.CommandException('Template file failure: {0}'.format(e.message)) # Check if destination file exists, overwrite if needed if os.path.exists(result_filename): if overwrite: logger.info('Overwriting the destination file {0}'.format(result_filename)) os.remove(result_filename) else: raise exceptions.CommandException('The destination file already exists: {0}'.\ format(result_filename)) # Generate an output file finally... with open(result_filename, 'w') as out: result = tpl.render(**data) out.write(result) return (True, 'success')
def resolve(cls, *args): # TODO: we may need to rewrite this for e.g. suse, which # is rpm based, but doesn't use yum; same for install()/is_available()/can_operate() logger.info('Resolving RPM dependencies ...') import yum y = yum.YumBase() y.setCacheDir(tempfile.mkdtemp()) for pkg in args: if pkg.startswith('@'): y.selectGroup(pkg[1:]) else: try: y.install(y.returnPackageByDep(pkg)) except yum.Errors.YumBaseError: msg = 'Package not found: {pkg}'.format(pkg=pkg) logger.error(msg) raise exceptions.DependencyException(msg) y.resolveDeps() logger.debug('Installing/Updating:') to_install = [] for pkg in y.tsInfo.getMembers(): to_install.append(pkg.po.ui_envra) logger.debug(pkg.po.ui_envra) return to_install
def resolve(cls, *args): logger.info('Resolving RPM dependencies ...') import yum y = yum.YumBase() y.setCacheDir(tempfile.mkdtemp()) for pkg in args: if pkg.startswith('@'): y.selectGroup(pkg[1:]) else: try: y.install(y.returnPackageByDep(pkg)) except yum.Errors.YumBaseError: msg = 'Package not found: {pkg}'.format(pkg=pkg) raise exceptions.DependencyException(msg) try: y.resolveDeps() except yum.Errors.PackageSackError as e: # Resolution of Issue 154 raise exceptions.DependencyException('Error resolving RPM dependencies: {0}'.\ format(str(e))) logger.debug('Installing/Updating:') to_install = [] for pkg in y.tsInfo.getMembers(): to_install.append(pkg.po.ui_envra) logger.debug(pkg.po.ui_envra) return to_install
def resolve(cls, *deps): """ Return all dependencies which will be installed. Like a portage based implementation it just tries to get the best package available according a given spec. """ import paludis logger.info('[paludis] Resolving dependencies ...') env = paludis.EnvironmentFactory.instance.create('') fltr = paludis.Filter.And(paludis.Filter.SupportsInstallAction(), paludis.Filter.NotMasked()) to_install = set() for dep in deps: ds = paludis.parse_user_package_dep_spec(dep, env, paludis.UserPackageDepSpecOptions()) gen = paludis.Generator.Matches(ds, paludis.MatchPackageOptions()) fg = paludis.FilteredGenerator(gen, fltr) s = paludis.Selection.BestVersionOnly(fg) _to_install = set() for pkg in env[s]: _to_install.add(str(pkg)) if _to_install: to_install += _to_install else: msg = 'Package not found: {pkg}'.format(pkg=dep) raise exceptions.DependencyException(msg) cls.throw_package_list(list(to_install))
def _github_fork(cls, **kwargs): """Create a fork of repo from kwargs['fork_repo']. Note: the kwargs are not the global context here, but what cls.format_args returns. Raises: devassistant.exceptions.CommandException on error """ fork_login, fork_reponame = kwargs['repo_url'].split('/') logger.info('Forking {repo} for user {login} on Github ...'.\ format(login=kwargs['login'], repo=kwargs['repo_url'])) success = False msg = '' try: repo = cls._gh_module.Github().get_user(fork_login).get_repo(fork_reponame) fork = cls._user.create_fork(repo) success = True msg = fork.ssh_url except cls._gh_module.GithubException as e: msg = 'Failed to create Github fork with error: {err}'.format(err=e) except BaseException as e: msg = 'Exception while forking GH repo: {0}'.\ format(getattr(e, 'message', 'Unknown error')) if success: logger.info('Fork is ready at {url}.'.format(url=fork.html_url)) else: logger.warning(msg) return (success, msg)
def _github_create_repo(cls, **kwargs): """Create repo on GitHub. If repository already exists then RunException will be raised. Raises: devassistant.exceptions.RunException on error """ username = cls._github_username(**kwargs) reponame = cls._github_reponame(**kwargs) password = getpass.getpass(prompt='GitHub password:'******'Repository already exists on GitHub' logger.error(msg) raise exceptions.RunException(msg) else: new_repo = user.create_repo(reponame) logger.info('Your new repository: {0}'.format( new_repo.html_url)) except github.GithubException as e: msg = 'GitHub error: {0}'.format(e) logger.log(msg) raise exceptions.RunException(msg)
def run(self): pkgs = exs = [] try: pkgs = self.kwargs['package'] except KeyError: pkgs = dapicli.get_installed_daps() if pkgs: logger.info('Updating all DAP packages ...') else: logger.info('No installed DAP packages found, nothing to update.') for pkg in pkgs: logger.info('Updating DAP {pkg} ...'.format(pkg=pkg)) try: updated = dapicli.install_dap(pkg, update=True, update_allpaths=self.kwargs['allpaths'], force=self.kwargs['force']) if updated: logger.info('DAP {pkg} successfully updated.'.format(pkg=pkg)) else: logger.info('DAP {pkg} is already up to date.'.format(pkg=pkg)) except exceptions.DapiError as e: exs.append(utils.exc_as_decoded_string(e)) logger.error(utils.exc_as_decoded_string(e)) if exs: raise exceptions.ExecutionException('; '.join(exs))
def signal_handler(signal, frame): if package_managers.DependencyInstaller.install_lock: logger.warning('Can\'t interrupt dependency installation!') else: logger.info('DevAssistant received SIGINT, exiting ...') utils.run_exitfuncs() sys.exit(0)
def resolve(cls, *args): logger.info('Resolving RPM dependencies ...') import yum y = yum.YumBase() y.setCacheDir(tempfile.mkdtemp()) for pkg in args: if pkg.startswith('@'): y.selectGroup(pkg[1:]) else: try: y.install(y.returnPackageByDep(pkg)) except yum.Errors.YumBaseError: msg = 'Package not found: {pkg}'.format(pkg=pkg) raise exceptions.DependencyException(msg) try: y.resolveDeps() except yum.Errors.PackageSackError as e: # Resolution of Issue 154 raise exceptions.DependencyException('Error resolving RPM dependencies: {0}'.\ format(str(e))) logger.debug('Installing/Updating:') to_install = [] for pkg in y.tsInfo.getMembers(): to_install.append(pkg.po.ui_envra) logger.debug(pkg.po.ui_envra) return to_install
def _install_dependencies(self): """Install missing dependencies""" for dep_t, dep_l in self.dependencies.items(): if not dep_l: continue pkg_mgr = self.get_package_manager(dep_t) pkg_mgr.works() to_resolve = [] for dep in dep_l: if not pkg_mgr.is_pkg_installed(dep): to_resolve.append(dep) if not to_resolve: # nothing to install, let's move on continue to_install = pkg_mgr.resolve(*to_resolve) confirm = self._ask_to_confirm(pkg_mgr, *to_install) if not confirm: msg = 'List of packages denied by user, exiting.' logger.error(msg) raise exceptions.DependencyException(msg) type(self).install_lock = True logger.info('Installing dependencies, sit back and relax ...') installed = pkg_mgr.install(*to_install) type(self).install_lock = False if not installed: msg = 'Failed to install dependencies, exiting.' logger.error(msg) raise exceptions.DependencyException(msg) else: logger.info('Successfully installed dependencies!')
def _install_dependencies(self): """Install missing dependencies""" for dep_t, dep_l in self.dependencies.items(): if not dep_l: continue pkg_mgr = self.get_package_manager(dep_t) pkg_mgr.works() to_resolve = [] for dep in dep_l: if not pkg_mgr.is_pkg_installed(dep): to_resolve.append(dep) if not to_resolve: # nothing to install, let's move on continue to_install = pkg_mgr.resolve(*to_resolve) confirm = self._ask_to_confirm(pkg_mgr, *to_install) if not confirm: msg = 'List of packages denied by user, exiting.' logger.error(msg) raise exceptions.DependencyException(msg) type(self).install_lock = True logger.info('Installing dependencies, sit back and relax ...') installed = pkg_mgr.install(*to_install) type(self).install_lock = False if not installed: msg = 'Failed to install dependencies, exiting.' logger.error(msg) raise exceptions.DependencyException(msg) else: logger.info('Successfully installed dependencies!')
def resolve(cls, *deps): """ Return all dependencies which will be installed. NOTE Simplified (naive) implementation will show the list of correctly spelled packages to be installed. For example 'firefox' will be resolved to 'www-client/firefox-25.0.1'... TODO ... or maybe version part must be stripped? """ import portage logger.info('[portage] Resolving dependencies ...') porttree = portage.db[portage.root]['porttree'] to_install = set() for dep in deps: res = porttree.dep_bestmatch(dep) logger.debug('{0} resolved to {1}'.format(repr(dep), repr(res))) if res: to_install.add(res) else: msg = 'Package not found or spec is invalid: {pkg}'.format(pkg=dep) raise exceptions.DependencyException(msg) cls.throw_package_list(list(to_install))
def _github_create_repo(cls, **kwargs): """Create repo on GitHub. If repository already exists then RunException will be raised. Raises: devassistant.exceptions.RunException on error """ username = cls._github_username(**kwargs) reponame = cls._github_reponame(**kwargs) password = getpass.getpass(prompt='GitHub password:'******'Repository already exists on GitHub' logger.error(msg) raise exceptions.RunException(msg) else: new_repo = user.create_repo(reponame) logger.info('Your new repository: {0}'.format(new_repo.html_url)) except github.GithubException as e: msg = 'GitHub error: {0}'.format(e) logger.log(msg) raise exceptions.RunException(msg)
def _docker_group_add(cls): username = getpass.getuser() try: logger.info("Adding {0} to group docker ...".format(username)) ClHelper.run_command('bash -c "usermod -a -G docker {0}"'.format(username), as_user="******") except exceptions.ClException as e: msg = 'Failed to add user to "docker" group: {0}'.format(e.output) raise exceptions.CommandException(msg)
def _github_push(cls): try: ret = ClHelper.run_command("git push -u origin master") logger.info('Source code was successfully pushed.') return (True, ret) except exceptions.ClException as e: logger.warning('Problem pushing source code: {0}'.format(e.output)) return (False, e.output)
def add_user_to_docker_group(cls, username): try: logger.info('Adding {0} to group docker ...'.format(username)) ClHelper.run_command('bash -c "usermod -a -G docker {0}"'.format(username), as_user='******') except exceptions.ClException as e: msg = 'Failed to add user to "docker" group: {0}'.format(e.output) raise exceptions.CommandException(msg)
def _github_push(cls): try: ret = ClHelper.run_command("git push -u origin master") logger.info('Source code was successfully pushed.') return (True, ret) except exceptions.ClException as e: logger.warning('Problem pushing source code: {0}'.format(e.output)) return (False, e.output)
def is_group_installed(cls, group): logger.info('Checking for presence of group {0}...'.format(group)) try: ClHelper.run_command('{pacman} -Qg "{group}"'.format( pacman=cls.c_pacman, group=group)) return group except exceptions.ClException: return False
def add_user_to_docker_group(cls, username): try: logger.info('Adding {0} to group docker ...'.format(username)) ClHelper.run_command( 'bash -c "usermod -a -G docker {0}"'.format(username), as_user='******') except exceptions.ClException as e: msg = 'Failed to add user to "docker" group: {0}'.format(e.output) raise exceptions.CommandException(msg)
def install(cls, *args): cmd = plumbum.local[cls.c_yum]['install'] logger.info('Installing: {0}'.format(', '.join(args))) for arg in args: cmd = cmd[arg] try: (sudo[cmd]) & plumbum.FG return args except plumbum.ProcessExecutionError: return False
def is_group_installed(cls, group): logger.info('Checking for presence of group {0}...'.format(group)) try: ClHelper.run_command('{pacman} -Qg "{group}"'.\ format(pacman=cls.c_pacman, group=group)) return group except exceptions.ClException: return False
def test_logger_basic(self, capsys): console_handler = DevassistantClHandler(sys.stdout) console_handler.setFormatter(DevassistantClFormatter()) console_handler.setLevel(logging.INFO) logger.addHandler(console_handler) # just test that logging works... logger.info('info ...') assert capsys.readouterr() == ('INFO: info ...\n', '')
def install(cls, *args): cmd = plumbum.local[cls.c_yum]['install'] logger.info('Installing: {0}'.format(', '.join(args))) for arg in args: cmd = cmd[arg] try: (sudo[cmd]) & plumbum.FG return args except plumbum.ProcessExecutionError: return False
def _github_create_and_push(cls, **kwargs): """Note: the kwargs are not the global context here, but what cls.format_args returns.""" # we assume we're in the project directory logger.info('Registering your {priv}project on GitHub as {login}/{repo}...'.\ format(priv='private ' if kwargs['private'] else '', login=kwargs['login'], repo=kwargs['reponame'])) ret = cls._github_create_repo(**kwargs) if ret[0]: # on success push the sources ret = cls._github_add_remote_and_push(**kwargs) return ret
def _github_create_and_push(cls, **kwargs): """Note: the kwargs are not the global context here, but what cls.format_args returns.""" # we assume we're in the project directory logger.info('Registering your {priv}project on GitHub as {login}/{repo}...'.\ format(priv='private ' if kwargs['private'] else '', login=kwargs['login'], repo=kwargs['reponame'])) ret = cls._github_create_repo(**kwargs) if ret[0]: # on success push the sources ret = cls._github_add_remote_and_push(**kwargs) return ret
def resolve(cls, *args): logger.info('Resolving Homebrew dependencies ...') for pkg in args: logger.debug('Looking at {0}'.format(pkg)) logger.debug('Installing/Updating:') to_install = set() for pkg in args: query = ClHelper.run_command(' '.join([cls.c_homebrew, 'deps -n', pkg])) to_install.update(query.split('\n')) return list(to_install)
def _show_doc(cls, fullpath): have_less = True try: subprocess.check_call(['which', 'less'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) except (subprocess.CalledProcessError, OSError): have_less = False if have_less: subprocess.Popen(['less', '-F', '-R', '-S', '-X', '-K', fullpath], stdin=subprocess.PIPE, stdout=sys.stdout).communicate() else: logger.info(open(fullpath).read())
def ask_for_package_list_confirm(cls, prompt, package_list, **options): prompt += ' [y(es)/n(o)/s(how)]: ' while True: choice = cls.ask_for_input_with_prompt(prompt, **options) choice = choice.lower() if choice not in cls.yesno_list + ['s', 'show']: cls.comm.send_error('You have to choose one of y/n/s.') else: if choice in cls.yesno_list: return choice in cls.yes_list else: logger.info('\n'.join(sorted(package_list)))
def resolve(cls, *args): logger.info('Resolving Homebrew dependencies ...') for pkg in args: logger.debug('Looking at {0}'.format(pkg)) logger.debug('Installing/Updating:') to_install = set() for pkg in args: query = ClHelper.run_command(' '.join([cls.c_homebrew, 'deps -n', pkg])) to_install.update(query.split('\n')) return list(to_install)
def run(cls, **kwargs): exs = [] for pkg in kwargs['package']: logger.info('Uninstalling {pkg}...'.format(pkg=pkg)) try: done = dapicli.uninstall_dap(pkg, confirm=kwargs['force']) if done: logger.info('{pkg} successfully uninstalled'.format(pkg=pkg)) except Exception as e: exs.append(str(e)) logger.error(str(e)) if exs: raise exceptions.ExecutionException('; '.join(exs))
def _show_doc(cls, fullpath): have_less = True try: subprocess.check_call(['which', 'less'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) except (subprocess.CalledProcessError, OSError): have_less = False if have_less: subprocess.Popen(['less', '-F', '-R', '-S', '-X', '-K', fullpath], stdin=subprocess.PIPE, stdout=sys.stdout).communicate() else: logger.info(open(fullpath).read())
def run(cls, **kwargs): exs = [] for pkg in kwargs['package']: logger.info('Installing DAP {pkg} ...'.format(pkg=pkg)) if os.path.isfile(pkg): method = dapicli.install_dap_from_path else: method = dapicli.install_dap try: pkgs = method(pkg, force=kwargs['force']) logger.info('Successfully installed DAPs {pkgs}'.format(pkgs=' '.join(pkgs))) except Exception as e: exs.append(str(e)) logger.error(str(e)) if exs: raise exceptions.ExecutionException('; '.join(exs))
def format_daps(simple=False, skip_installed=False): '''Formats a list of metadaps available on Dapi''' lines = [] m = metadaps() if not m['count']: logger.info('Could not find any daps') return for mdap in sorted(m['results'], key=lambda mdap: mdap['package_name']): if skip_installed and mdap['package_name'] in get_installed_daps(): continue if simple: logger.info(mdap['package_name']) else: for line in _format_dap_with_description(mdap): lines.append(line) return lines
def format_daps(simple=False, skip_installed=False): '''Formats a list of metadaps available on Dapi''' lines= [] m = metadaps() if not m['count']: logger.info('Could not find any daps') return for mdap in sorted(m['results'], key=lambda mdap: mdap['package_name']): if skip_installed and mdap['package_name'] in get_installed_daps(): continue if simple: logger.info(mdap['package_name']) else: for line in _format_dap_with_description(mdap): lines.append(line) return lines
def run(self): exs = [] for pkg in self.kwargs['package']: logger.info('Installing DAP {pkg} ...'.format(pkg=pkg)) if os.path.isfile(pkg): method = dapicli.install_dap_from_path else: method = dapicli.install_dap try: pkgs = method(pkg, force=self.kwargs['force'], nodeps=self.kwargs['nodeps'], reinstall=self.kwargs['reinstall']) logger.info('Successfully installed DAPs {pkgs}'.format(pkgs=' '.join(pkgs))) except exceptions.DapiError as e: exs.append(utils.exc_as_decoded_string(e)) logger.error(utils.exc_as_decoded_string(e)) if exs: raise exceptions.ExecutionException('; '.join(exs))
def run(cls, **kwargs): import os exs = [] for pkg in kwargs['package']: logger.info('Installing {pkg}...'.format(pkg=pkg)) if os.path.isfile(pkg): method = dapicli.install_dap_from_path else: method = dapicli.install_dap try: method(pkg) logger.info('{pkg} successfully installed'.format(pkg=pkg)) except Exception as e: exs.append(str(e)) logger.error(str(e)) if exs: raise exceptions.ExecutionException('; '.join(exs))
def _github_create_repo(cls, **kwargs): """Create repo on GitHub. If repository already exists then RunException will be raised. Raises: devassistant.exceptions.RunException on error """ reponame = cls._github_reponame(**kwargs) if reponame in map(lambda x: x.name, cls._user.get_repos()): msg = 'Repository already exists on GitHub' logger.error(msg) raise exceptions.RunException(msg) else: new_repo = cls._user.create_repo(reponame) logger.info('Your new repository: {0}'.format(new_repo.html_url))
def _install_dependencies(self, ui, debug): """Install missing dependencies""" for dep_t, dep_l in self.dependencies: if not dep_l: continue pkg_mgr = self.get_package_manager(dep_t) pkg_mgr.works() to_resolve = [] for dep in dep_l: if not pkg_mgr.is_pkg_installed(dep): to_resolve.append(dep) if not to_resolve: # nothing to install, let's move on continue to_install = pkg_mgr.resolve(*to_resolve) confirm = self._ask_to_confirm(ui, pkg_mgr, *to_install) if not confirm: msg = 'List of packages denied by user, exiting.' raise exceptions.DependencyException(msg) type(self).install_lock = True # TODO: we should do this more systematically (send signal to cl/gui?) logger.info('Installing dependencies, sit back and relax ...', extra={'event_type': 'dep_installation_start'}) if ui == 'cli' and not debug: # TODO: maybe let every manager to decide when to start event = threading.Event() t = EndlessProgressThread(event) t.start() installed = pkg_mgr.install(*to_install) if ui == 'cli' and not debug: event.set() t.join() if installed: print(' Done.') else: print(' Failed.') type(self).install_lock = False log_extra = {'event_type': 'dep_installation_end'} if not installed: msg = 'Failed to install dependencies, exiting.' logger.error(msg, extra=log_extra) raise exceptions.DependencyException(msg) else: logger.info('Successfully installed dependencies!', extra=log_extra)
def _docker_build(cls, directory): logger.info('Building Docker image, this may take a while ...') logres = False final_image = '' cmd_str = cls._cmd_for_newgrp('docker build --rm {0}'.format(directory)) try: result = ClHelper.run_command(cmd_str, log_level=logging.INFO) success_re = re.compile(r'Successfully built ([0-9a-f]+)') success_found = success_re.search(result) if success_found: logres = True final_image = success_found.group(1) except exceptions.ClException: pass # no-op return (logres, final_image)
def _github_add_remote_origin(cls, **kwargs): """Note: the kwargs are not the global context here, but what cls.format_args returns.""" reponame = kwargs['reponame'] login = kwargs['login'] # if system username != GH login, we need to use [email protected]{login}:... # else just [email protected]:... dash_login = '' if getpass.getuser() != login: dash_login = '******' + login try: logger.info('Adding Github repo as git remote ...') ret = ClHelper.run_command("git remote add origin [email protected]{dl}:{l}/{r}.git".\ format(dl=dash_login, l=login, r=reponame)) logger.info('Successfully added Github repo as git remote.') return (True, ret) except exceptions.ClException as e: logger.warning('Problem adding Github repo as git remote: {0}.'.format(e.output)) return (False, e.output)
def _install_dependencies(self): """Install missing dependencies""" for dep_t, dep_l in self.dependencies.items(): if not dep_l: continue pkg_mgr = self.get_package_manager(dep_t) pkg_mgr.works() to_resolve = [] for dep in dep_l: if not pkg_mgr.is_pkg_installed(dep): to_resolve.append(dep) if not to_resolve: # nothing to install, let's move on continue to_install = pkg_mgr.resolve(*to_resolve) confirm = self._ask_to_confirm(pkg_mgr, *to_install) if not confirm: msg = 'List of packages denied by user, exiting.' raise exceptions.DependencyException(msg) type(self).install_lock = True # TODO: we should do this more systematically (send signal to cl/gui?) logger.info('Installing dependencies, sit back and relax ...', extra={'event_type': 'dep_installation_start'}) if current_run.UI == 'cli': # TODO: maybe let every manager to decide when to start event = threading.Event() t = EndlessProgressThread(event) t.start() installed = pkg_mgr.install(*to_install) if current_run.UI == 'cli': event.set() t.join() type(self).install_lock = False log_extra = {'event_type': 'dep_installation_end'} if not installed: msg = 'Failed to install dependencies, exiting.' logger.error(msg, extra=log_extra) ex = exceptions.DependencyException(msg) ex.already_logged = True raise ex else: logger.info('Successfully installed dependencies!', extra=log_extra)
def run(self): exs = [] for pkg in self.kwargs['package']: logger.info('Installing DAP {pkg} ...'.format(pkg=pkg)) if os.path.isfile(pkg): method = dapicli.install_dap_from_path else: method = dapicli.install_dap try: pkgs = method(pkg, force=self.kwargs['force'], nodeps=self.kwargs['nodeps'], reinstall=self.kwargs['reinstall'], __ui__=self.kwargs['__ui__']) logger.info('Successfully installed DAPs {pkgs}'.format( pkgs=' '.join(pkgs))) except exceptions.DapiError as e: exs.append(utils.exc_as_decoded_string(e)) logger.error(utils.exc_as_decoded_string(e)) if exs: raise exceptions.ExecutionException('; '.join(exs))
def _github_create_repo(cls, **kwargs): """Create repo on GitHub. Note: the kwargs are not the global context here, but what cls.format_args returns. If repository already exists then CommandException will be raised. Raises: devassistant.exceptions.CommandException on error """ reponame = kwargs['reponame'] if reponame in map(lambda x: x.name, cls._user.get_repos()): msg = 'Failed to create Github repo: {0}/{1} alread exists.'.\ format(cls._user.login, reponame) logger.warning(msg) return (False, msg) else: msg = '' success = False try: new_repo = cls._user.create_repo(reponame, private=kwargs['private']) msg = new_repo.clone_url success = True except cls._gh_module.GithubException as e: gh_errs = e.data.get('errors', []) gh_errs = '; '.join(map(lambda err: err.get('message', ''), gh_errs)) msg = 'Failed to create GitHub repo. This sometime happens when you delete ' msg += 'a repo and then you want to create the same one immediately. If that\'s ' msg += 'the case, wait for few minutes and then try again.\n' msg += 'Github errors: ' + gh_errs except BaseException as e: msg = 'Failed to create Github repo: {0}'.\ format(getattr(e, 'message', 'Unknown error')) if success: logger.info('Your new repository: {0}'.format(new_repo.html_url)) else: logger.warning(msg) return (success, msg)
def _github_fork(cls, **kwargs): """Create a fork of repo from kwargs['fork_repo']. Note: the kwargs are not the global context here, but what cls.format_args returns. Raises: devassistant.exceptions.CommandException on error """ timeout = 300 # 5 minutes fork_login, fork_reponame = kwargs['repo_url'].split('/') logger.info('Forking {repo} for user {login} on Github ...'.\ format(login=kwargs['login'], repo=kwargs['repo_url'])) success = False msg = '' try: repo = cls._gh_module.Github().get_user(fork_login).get_repo(fork_reponame) fork = cls._user.create_fork(repo) while timeout > 0: time.sleep(5) timeout -= 5 try: fork.get_contents('/') # This function doesn't throw an exception when clonable success = True break except cls._gh_module.GithubException as e: if 'is empty' not in str(e): raise e msg = fork.ssh_url except cls._gh_module.GithubException as e: msg = 'Failed to create Github fork with error: {err}'.format(err=e) except BaseException as e: msg = 'Exception while forking GH repo: {0}'.\ format(getattr(e, 'message', 'Unknown error')) if success: logger.info('Fork is ready at {url}.'.format(url=fork.html_url)) else: logger.warning(msg) return (success, msg)
def _github_create_and_push(cls, **kwargs): # we assume we're in the project directory logger.info('Registering your project on GitHub as {0}/{1}...'.format( cls._user.login, cls._github_reponame(**kwargs))) cls._github_create_repo(**kwargs) logger.info('Pushing your project to the new GitHub repository...') cls._github_push(**kwargs) logger.info('GitHub repository was created and source code pushed.')
def _github_create_and_push(cls, **kwargs): ClHelper.run_command('cd {0}'.format( os.path.abspath(os.path.expanduser(kwargs['name'])))) logger.info('Registering your project on GitHub as {0}/{1}...'.format( cls._github_username(**kwargs), cls._github_reponame(**kwargs))) cls._github_create_repo(**kwargs) logger.info('Pushing your project to the new GitHub repository...') cls._github_push(**kwargs) logger.info('GitHub repository was created and source code pushed.')