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('')
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)
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.')
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)
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
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, )
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