def promote(self, from_channel="unpublished", to_channel="edge"): self.echo( f"Promoting :: {self.entity:^35} :: from:{from_channel} to: {to_channel}" ) charm_id = sh.charm.show(self.entity, "--channel", from_channel, "id") charm_id = yaml.safe_load(charm_id.stdout.decode()) resources_args = [] try: resources = sh.charm( "list-resources", charm_id["id"]["Id"], channel=from_channel, format="yaml", ) resources = yaml.safe_load(resources.stdout.decode()) if resources: resources_args = [( "--resource", "{}-{}".format(resource["name"], resource["revision"]), ) for resource in resources] except sh.ErrorReturnCode: self.echo("No resources for {}".format(charm_id)) sh.charm.release(charm_id["id"]["Id"], "--channel", to_channel, *resources_args) self.echo( f"Setting {charm_id['id']['Id']} permissions for read everyone") cmd_ok( ["charm", "grant", charm_id["id"]["Id"], "--acl=read", "everyone"], echo=self.echo, )
def promote_all(self, from_channel="unpublished", to_channel="edge"): for charm_map in self.artifacts: for charm_name, charm_opts in charm_map.items(): if not any(match in self.filter_by_tag for match in charm_opts["tags"]): continue charm_entity = f"cs:~{charm_opts['namespace']}/{charm_name}" click.echo( f"Promoting :: {charm_entity:^35} :: from:{from_channel} to: {to_channel}" ) charm_id = sh.charm.show(charm_entity, "--channel", from_channel, "id") charm_id = yaml.safe_load(charm_id.stdout.decode()) resources_args = [] try: resources = sh.charm( "list-resources", charm_id["id"]["Id"], channel=from_channel, format="yaml", ) resources = yaml.safe_load(resources.stdout.decode()) if resources: resources_args = [( "--resource", "{}-{}".format(resource["name"], resource["revision"]), ) for resource in resources] except sh.ErrorReturnCode_1: click.echo("No resources for {}".format(charm_id)) sh.charm.release(charm_id["id"]["Id"], "--channel", to_channel, *resources_args)
def has_changed(self): """Determine if the charm/layers commits have changed since last publish to charmstore""" if not self.legacy_charm: # Operator framework charms won't have a .build.manifest and it's # sufficient to just compare the charm repo's commit rev. try: extra_info = yaml.safe_load( sh.charm( "show", self.full_entity, "extra-info", format="yaml", ).stdout.decode())["extra-info"] old_commit = extra_info.get("commit") new_commit = self.commit changed = new_commit != old_commit except sh.ErrorReturnCode: changed = True old_commit = None new_commit = None if changed: self.echo( f"Changes found: {new_commit} (new) != {old_commit} (old)") else: self.echo( f"No changes found: {new_commit} (new) == {old_commit} (old)" ) return changed charmstore_build_manifest = None resp = self.download(".build.manifest") if resp.ok: charmstore_build_manifest = resp.json() if not charmstore_build_manifest: self.echo( "No build.manifest located, unable to determine if any changes occurred." ) return True current_build_manifest = [{ "rev": curr["rev"], "url": curr["url"] } for curr in self.build.db["pull_layer_manifest"]] # Check the current git cloned charm repo commit and add that to # current pull-layer-manifest as that would no be known at the # time of pull_layers current_build_manifest.append({"rev": self.commit, "url": self.name}) the_diff = [ i for i in charmstore_build_manifest["layers"] if i not in current_build_manifest ] if the_diff: self.echo("Changes found:") self.echo(the_diff) return True self.echo(f"No changes found, not building a new {self.entity}") return False
def resource(charm_entity, channel, builder, out_path, resource_spec): out_path = Path(out_path) resource_spec = yaml.load(Path(resource_spec).read_text()) resource_spec_fragment = resource_spec.get(charm_entity, None) click.echo(resource_spec_fragment) if not resource_spec_fragment: raise SystemExit('Unable to determine resource spec for entity') os.makedirs(str(out_path), exist_ok=True) charm_id = sh.charm.show(charm_entity, '--channel', channel, 'id') charm_id = yaml.load(charm_id.stdout.decode()) try: resources = sh.charm('list-resources', charm_id['id']['Id'], channel=channel, format='yaml') except sh.ErrorReturnCode_1: click.echo('No resources found for {}'.format(charm_id)) return resources = yaml.load(resources.stdout.decode()) builder_sh = Path(builder).absolute() click.echo(builder_sh) for line in sh.bash(str(builder_sh), _cwd=out_path, _iter=True): click.echo(line.strip()) for line in glob('{}/*'.format(out_path)): resource_path = Path(line) resource_fn = resource_path.parts[-1] resource_key = resource_spec_fragment.get(resource_fn, None) if resource_key: out = sh.charm.attach(charm_entity, '--channel', channel, '{}={}'.format(resource_key, resource_path)) click.echo(out)
def download(): for line in sh.charm("pull-source", "-v", "-i", layer_index, layer_name, _iter=True, _bg_exc=False): click.echo(f" -- {line.strip()}")
def _resource(charm_entity, channel, builder, out_path, resource_spec): out_path = Path(out_path) resource_spec = yaml.safe_load(Path(resource_spec).read_text()) resource_spec_fragment = resource_spec.get(charm_entity, None) click.echo(resource_spec_fragment) if not resource_spec_fragment: raise SystemExit("Unable to determine resource spec for entity") os.makedirs(str(out_path), exist_ok=True) charm_id = sh.charm.show(charm_entity, "--channel", channel, "id") charm_id = yaml.safe_load(charm_id.stdout.decode()) try: resources = sh.charm("list-resources", charm_id["id"]["Id"], channel=channel, format="yaml") except sh.ErrorReturnCode_1: click.echo("No resources found for {}".format(charm_id)) return resources = yaml.safe_load(resources.stdout.decode()) builder_sh = Path(builder).absolute() click.echo(builder_sh) for line in sh.bash(str(builder_sh), _cwd=out_path, _iter=True, _bg_exc=False): click.echo(line.strip()) for line in glob("{}/*".format(out_path)): resource_path = Path(line) resource_fn = resource_path.parts[-1] resource_key = resource_spec_fragment.get(resource_fn, None) if resource_key: is_attached = False is_attached_count = 0 while not is_attached: try: out = sh.charm.attach( charm_entity, "--channel", channel, f"{resource_key}={resource_path}", _err_to_out=True, ) is_attached = True except sh.ErrorReturnCode_1 as e: click.echo(f"Problem attaching resources, retrying: {e}") is_attached_count += 1 if is_attached_count > 10: raise SystemExit( "Could not attach resource and max retry count reached." ) click.echo(out)
def promote(charm_entity, from_channel, to_channel): charm_id = sh.charm.show(charm_entity, '--channel', from_channel, 'id') charm_id = yaml.load(charm_id.stdout.decode()) resources_args = [] try: resources = sh.charm('list-resources', charm_id['id']['Id'], channel=from_channel, format='yaml') resources = yaml.load(resources.stdout.decode()) if resources: resources_args = [('--resource', '{}-{}'.format(resource['name'], resource['revision'])) for resource in resources] except sh.ErrorReturnCode_1: click.echo("No resources for {}".format(charm_id)) sh.charm.release(charm_id['id']['Id'], '--channel', to_channel, *resources_args)
def promote(self, from_channel="unpublished", to_channel="edge"): click.echo( f"Promoting :: {self.entity:^35} :: from:{from_channel} to: {to_channel}" ) charm_id = sh.charm.show(self.entity, "--channel", from_channel, "id") charm_id = yaml.safe_load(charm_id.stdout.decode()) resources_args = [] try: resources = sh.charm( "list-resources", charm_id["id"]["Id"], channel=from_channel, format="yaml", ) resources = yaml.safe_load(resources.stdout.decode()) if resources: resources_args = [( "--resource", "{}-{}".format(resource["name"], resource["revision"]), ) for resource in resources] except sh.ErrorReturnCode: click.echo("No resources for {}".format(charm_id)) sh.charm.release(charm_id["id"]["Id"], "--channel", to_channel, *resources_args)