Esempio n. 1
0
    def print_version_information(self,
                                  version_check=True,
                                  version_cache=None):
        """Print out version information"""
        if version_check:
            latest_version = self.get_latest_version(version_cache)
        else:
            latest_version = Unknown()

        cprint.magenta_bold('Version:', lpad=2)
        cprint.white('Git:', lpad=4, rpad=8, end='')
        cprint.white(self.url)
        if isinstance(self.version, GitBranch):
            cprint.blue_bold('Branch: ', lpad=16, end='')
            cprint.yellow_bold(self.version.version, end='')
        elif isinstance(self.version, GitCommit):
            cprint.red('Commit: ', lpad=16, end='')
            cprint.red_bold(self.version.version[:7], end='')
        elif isinstance(self.version, GitRef):
            cprint.red('Ref: ', lpad=16, end='')
            cprint.red_bold(self.version.version, end='')
        elif isinstance(self.version, GitTag):
            cprint.blue_bold('Tag: ', lpad=16, end='')
            if latest_version.version == self.version.version:
                cprint.green_bold(self.version.version, end='')
            else:
                cprint.yellow_bold(self.version.version, end='')
        else:
            cprint.red_bold('UNSPECIFIED', lpad=16, end='')

        if version_check:
            cprint.white('[Latest: %s]' % (latest_version.report), lpad=1)
        else:
            cprint.white('')
Esempio n. 2
0
 def write_puppetfile(self,
                      environment,
                      *,
                      commit_message='Update Puppetfile',
                      diff_only=False,
                      non_interactive=False):
     """write a PuppetEnvironment to a Puppetfile"""
     self.git(['checkout', environment.name])
     with open(os.path.join(self._workdir, 'Puppetfile'),
               'w') as puppetfile:
         LOG.debug('write new version of Puppetfile in environment %s',
                   environment.name)
         # write file header
         puppetfile.write("forge 'http://forge.puppetlabs.com'\n\n")
         # write module lines
         puppetfile.writelines(
             ('{}\n'.format(line)
              for line in chain.from_iterable(environment.puppetfile)))
     # ask git for a diff
     diff = self.git(['diff'])
     if diff:
         if not non_interactive:
             cprint.white_bold('Diff for environment %s:' %
                               environment.name)
             cprint.diff(diff)
         if diff_only:
             # revert pending changes
             self.git(['checkout', '--', 'Puppetfile'])
         else:
             if non_interactive or query_yes_no(
                     'Update (commit and push) Puppetfile for '
                     'environment {}'.format(environment.name)):
                 # commit and push pending changes
                 self.git(['commit', '-m', commit_message, 'Puppetfile'])
                 try:
                     self.git(['push', 'origin', environment.name])
                     cprint.green('Updated environment {}'.format(
                         environment.name))
                 except GitError as exc:
                     cprint.red(
                         'Could not update environment {environment}. '
                         'Maybe somebody else pushed changes to '
                         '{environment} during current crmngr run. '
                         'Full git error: {error}'.format(
                             environment=environment.name,
                             error=exc,
                         ))
                     sys.exit(1)
             else:
                 # revert pending changes
                 self.git(['checkout', '--', 'Puppetfile'])
     else:
         LOG.debug('Puppetfile for environment %s unchanged',
                   environment.name)
Esempio n. 3
0
def main():
    """main entrypoint"""
    try:
        configuration = CrmngrConfig()
    except NoSectionError:
        print("No valid profile file found!")
        print("Enter git url of control repositoriy to create one.")
        print("Leave empty to abort")
        print()
        print("Control repository url: ", end="")
        default_profile_url = input().strip()
        if default_profile_url:
            configuration = CrmngrConfig.create_default_configuration(
                default_profile_url)
        else:
            sys.exit()

    cli_args = parse_cli_args(configuration)
    # now that the profile is known, reload the configuration using the
    # correct profile
    try:
        configuration = CrmngrConfig(profile=cli_args.profile)
    except NoSectionError:
        cprint.red('No configuration for profile {profile}'.format(
            profile=cli_args.profile))
        sys.exit(1)

    setup_logging(cli_args.debug)

    version_cache = JsonCache(configuration.cache_dir, ttl=cli_args.cache_ttl)

    commands = {
        'clean': command_clean,
        'create': command_create,
        'delete': command_delete,
        'environments': command_environments,
        'profiles': command_profiles,
        'report': command_report,
        'update': command_update,
    }
    try:
        commands[cli_args.command](configuration=configuration,
                                   cli_args=cli_args,
                                   version_cache=version_cache)
    except NoEnvironmentError:
        cprint.yellow_bold('no environment is affected by your command. typo?')
    except KeyboardInterrupt:
        cprint.red_bold('crmngr has been aborted.')
Esempio n. 4
0
def command_create(*, configuration, cli_args, version_cache, **kwargs):  # pylint: disable=unused-argument
    """run create command"""
    control_repo = ControlRepository(
        clone_url=configuration.control_repo_url, )
    environments = [
        environment.name for environment in control_repo.environments
    ]

    if cli_args.environment in environments:
        cprint.red('Template environment {environment} already exists in '
                   'control repository {profile} ({url})'.format(
                       environment=cli_args.environment,
                       profile=cli_args.profile,
                       url=control_repo.url,
                   ))
        sys.exit(1)
    if cli_args.template:
        if cli_args.template.strip() not in environments:
            cprint.red('Template environment {template} does not exist in '
                       'control repository {profile} ({url})'.format(
                           template=cli_args.template,
                           profile=cli_args.profile,
                           url=control_repo.url,
                       ))
            sys.exit(1)
        control_repo.clone_environment(
            cli_args.template,
            cli_args.environment,
            report=cli_args.report,
        )
        if cli_args.report:
            control_repo.report(
                version_cache=version_cache,
                version_check=cli_args.version_check,
                wrap=cli_args.wrap,
            )
    else:
        control_repo.new_environment(cli_args.environment,
                                     report=cli_args.report)
        cprint.green('Created new empty environment %s' % cli_args.environment)
Esempio n. 5
0
 def _update_forge_module(module_string, version):
     """return new version of a single forge module"""
     module = ForgeModule(*PuppetModule.parse_module_name(module_string))
     forge_api = ForgeApi(name=module.name, author=module.author)
     if version is None:
         module.version = None
     elif version == 'LATEST_FORGE_VERSION':
         try:
             module.version = Forge(forge_api.current_version['version'])
         except ForgeError as exc:
             cprint.red('Could not determine latest version of forge '
                        'module {author}/{module}: {error}'.format(
                            author=module.author,
                            module=module.name,
                            error=exc,
                        ))
             sys.exit(1)
     else:
         try:
             if not forge_api.has_version(version):
                 cprint.red('{version} is not a valid version for module '
                            '{author}/{module}'.format(
                                version=version,
                                author=module.author,
                                module=module.name,
                            ))
                 sys.exit(1)
         except ForgeError as exc:
             cprint.red('Could not verify version {version} of forge '
                        'module {author}/{module}: {error}'.format(
                            version=version,
                            author=module.author,
                            module=module.name,
                            error=exc,
                        ))
             sys.exit(1)
         module.version = Forge(version)
     return module
Esempio n. 6
0
    def update_puppetfiles(self, *, cli_args):
        """update puppetfiles"""
        with TemporaryDirectory(prefix='crmngr_update_cache') as cache_dir:
            reference = None
            module = None

            update_cache = JsonCache(cache_dir)
            if cli_args.reference:
                try:
                    reference = self.get_environment(cli_args.reference)
                except StopIteration:
                    cprint.red(
                        '%s specified as reference environment does not '
                        'exist' % cli_args.reference)
                    sys.exit(1)
            elif cli_args.git_url and not cli_args.remove:
                module = self._update_git_module(  # pylint: disable=R0204
                    module_string=cli_args.modules[0],
                    url=cli_args.git_url,
                    branch=cli_args.git_branch,
                    commit=cli_args.git_commit,
                    tag=cli_args.git_tag,
                )
            elif cli_args.forge and not cli_args.remove:
                module = self._update_forge_module(  # pylint: disable=R0204
                    module_string=cli_args.modules[0],
                    version=cli_args.forge_version,
                )
            for environment in sorted(self._environments):
                # reference update mode
                commit_message = 'Update Environment'
                if reference:
                    if environment == reference:
                        # when having a reference environment, it will be in the
                        # control repository. So we skip it.
                        continue
                    environment = self._reference_update(
                        environment,
                        reference=reference,
                        add=cli_args.add,
                        remove=cli_args.remove,
                    )
                    commit_message = 'Update {} based on {}.'.format(
                        environment.name,
                        reference.name,
                    )
                elif module is not None:
                    if cli_args.add or module.name in environment.modules:
                        environment[module.name] = module
                        commit_message = module.update_commit_message
                elif cli_args.remove:
                    environment = self._bulk_remove(
                        environment,
                        modules=cli_args.modules,
                    )
                    commit_message = 'Bulk update {}.'.format(environment.name)
                # bulk update mode (i.e. no version / update options specified)
                else:
                    environment = self._bulk_update(
                        environment,
                        modules=cli_args.modules,
                        cache=update_cache,
                    )
                    commit_message = 'Bulk update {}.'.format(environment.name)
                self.write_puppetfile(
                    commit_message=commit_message,
                    diff_only=cli_args.diffonly,
                    environment=environment,
                    non_interactive=cli_args.noninteractive,
                )
Esempio n. 7
0
    def _update_git_module(self, module_string, *, url, branch, commit, tag):
        """return new version of a single git module"""
        # pylint: disable=too-many-branches
        module_name = PuppetModule.parse_module_name(module_string).module

        if url == 'USE_EXISTING_URL':
            git_urls = {
                version.url: environments
                for version, environments in self.modules[module_name].items()
                if isinstance(version, GitModule)
            }
            if len(git_urls) > 1:
                cprint.red(
                    'Multiple URLs for {module} found across specified '
                    'environments:\n - {urls}'.format(
                        module=module_name,
                        urls='\n - '.join([
                            "{url} ({environments})".format(
                                url=url,
                                environments=', '.join(sorted(environments)))
                            for url, environments in sorted(git_urls.items())
                        ])))
                cprint.red('Specify an URL using --git option or restrict the '
                           'update to environments using the same URL for '
                           '{}'.format(module_name))
                sys.exit(1)
            elif len(git_urls) < 1:
                cprint.red('Git module {module} not in any of the specified '
                           'environments. To switch from forge to git for '
                           '{module}, pass an URL to --git.'.format(
                               module=module_name))
                sys.exit(1)
            url = list(git_urls)[0]
        try:
            module_repository = Repository(url)
        except GitError as exc:
            cprint.red('{url} is not a valid git repository: {error}'.format(
                url=url,
                error=exc,
            ))
            sys.exit(1)
        module = GitModule(module_name, url=url)
        if branch is not None:
            try:
                module_repository.git(['fetch', '--unshallow'])
                module_repository.validate_branch(branch)
                module.version = GitBranch(branch)  # pylint: disable=R0204
            except GitError as exc:
                cprint.red('Could not verify branch {branch} for {module}: '
                           '{error}'.format(branch=branch,
                                            module=module.name,
                                            error=exc))
                sys.exit(1)
        elif commit is not None:
            try:
                module_repository.git(['fetch', '--unshallow'])
                module_repository.validate_commit(commit)
                module.version = GitCommit(commit)  # pylint: disable=R0204
            except GitError as exc:
                cprint.red('Could not verify commit {commit} for {module}: '
                           '{error}'.format(commit=commit,
                                            module=module.name,
                                            error=exc))
                sys.exit(1)
        elif tag is not None:
            if tag == 'LATEST_GIT_TAG':
                try:
                    module.version = GitTag(  # pylint: disable=R0204
                        module_repository.latest_tag.name)
                except GitError as exc:
                    cprint.red('Could not determine latest tag for git module '
                               '{module}: {error}'.format(
                                   module=module.name,
                                   error=exc,
                               ))
                    sys.exit(1)
            else:
                try:
                    module_repository.git(['fetch', 'origin', '--tags'])
                    module_repository.validate_tag(tag)
                    module.version = GitTag(tag)  # pylint: disable=R0204
                except GitError as exc:
                    cprint.red('Could not verify tag {tag} for {module}: '
                               '{error}'.format(tag=tag,
                                                module=module.name,
                                                error=exc))
                    sys.exit(1)
        return module