def update(self, *, prefix: str, distribution: str, snapshots: Optional[Sequence[Dict[str, str]]] = None, force_overwrite: bool = False, sign_skip: bool = False, sign_batch: bool = True, sign_gpgkey: Optional[str] = None, sign_keyring: Optional[str] = None, sign_secret_keyring: Optional[str] = None, sign_passphrase: Optional[str] = None, sign_passphrase_file: Optional[str] = None, skip_cleanup: Optional[bool] = False) -> PublishEndpoint: """ Example: .. code-block:: python p.update( prefix="s3:maurusnet:nightly/stretch", distribution="mn-nightly", sign_batch=True, sign_gpgkey='A16BE921', sign_passphrase='***********' ) """ if sign_passphrase is not None and sign_passphrase_file is not None: raise AptlyAPIException("Can't use sign_passphrase and sign_passphrase_file at the same time") body = {} # type: T_BodyDict if snapshots is not None: for source in snapshots: if "name" not in source and "Name" not in source: raise AptlyAPIException("Each source in update() must contain the 'name' attribute") body["Snapshots"] = snapshots if force_overwrite: body["ForceOverwrite"] = True if skip_cleanup: body["SkipCleanup"] = True sign_dict = {} # type: Dict[str, Union[bool,str]] if sign_skip: sign_dict["Skip"] = True else: sign_dict["Batch"] = sign_batch if sign_gpgkey is not None: sign_dict["GpgKey"] = sign_gpgkey if sign_keyring is not None: sign_dict["Keyring"] = sign_keyring if sign_secret_keyring is not None: sign_dict["SecretKeyring"] = sign_secret_keyring if sign_passphrase is not None: sign_dict["Passphrase"] = sign_passphrase if sign_passphrase_file is not None: sign_dict["PassphraseFile"] = sign_passphrase_file body["Signing"] = sign_dict resp = self.do_put("api/publish/%s/%s" % (quote(self.escape_prefix(prefix)), quote(distribution),), json=body) return self.endpoint_from_response(resp.json())
def search_packages(self, reponame: str, query: str = None, with_deps: bool = False, detailed: bool = False) -> Sequence[Package]: if query is None and with_deps: raise AptlyAPIException( "search_packages can't include dependencies (with_deps==True) without" "a query") params = {} if query: params["q"] = query if with_deps: params["withDeps"] = "1" if detailed: params["format"] = "details" resp = self.do_get("api/repos/%s/packages" % quote(reponame), params=params) ret = [] for rpkg in resp.json(): ret.append(PackageAPISection.package_from_response(rpkg)) return ret
def version(self) -> str: resp = self.do_get("api/version") if "Version" in resp.json(): return cast(str, resp.json()["Version"]) else: raise AptlyAPIException( "Aptly server didn't return a valid response object:\n%s" % resp.text)
def list(self, sort: str='name') -> Sequence[Snapshot]: if sort not in ['name', 'time']: raise AptlyAPIException("Snapshot LIST only supports two sort modes: 'name' and 'time'. %s is not " "supported." % sort) resp = self.do_get("/api/snapshots") ret = [] for rsnap in resp.json(): ret.append(self.snapshot_from_response(rsnap)) return ret
def update(self, snapshotname: str, newname: str=None, newdescription: str=None) -> Snapshot: if newname is None and newdescription is None: raise AptlyAPIException("When updating a Snapshot you must at lease provide either a new name or a " "new description.") body = {} # type: Dict[str, Union[str, Sequence[str]]] if newname is not None: body["Name"] = newname if newdescription is not None: body["Description"] = newdescription resp = self.do_put("/api/snapshots/%s" % quote(snapshotname), json=body) return self.snapshot_from_response(resp.json())
def upload(self, destination: str, *files: str) -> Sequence[str]: to_upload = [] # type: List[Tuple[str, BinaryIO]] for f in files: if not os.path.exists(f) or not os.access(f, os.R_OK): raise AptlyAPIException("File to upload %s can't be opened or read" % f) fh = open(f, mode="rb") to_upload.append((f, fh),) try: resp = self.do_post("api/files/%s" % destination, files=to_upload) except AptlyAPIException: raise finally: for fn, to_close in to_upload: if not to_close.closed: to_close.close() return cast(List[str], resp.json())
def edit(self, reponame: str, comment: str = None, default_distribution: str = None, default_component: str = None) -> Repo: if comment is None and default_component is None and default_distribution is None: raise AptlyAPIException( "edit requires at least one of 'comment', 'default_distribution' or " "'default_component'.") body = {} if comment is not None: body["Comment"] = comment if default_distribution is not None: body["DefaultDistribution"] = default_distribution if default_component is not None: body["DefaultComponent"] = default_component resp = self.do_put("api/repos/%s" % quote(reponame), json=body) return self.repo_from_response(resp.json())
def publish(self, *, source_kind: str = "local", sources: Sequence[Dict[str, str]], architectures: Sequence[str], prefix: str = None, distribution: str = None, label: str = None, origin: str = None, force_overwrite: bool = False, sign_skip: bool = False, sign_batch: bool = True, sign_gpgkey: str = None, sign_keyring: str = None, sign_secret_keyring: str = None, sign_passphrase: str = None, sign_passphrase_file: str = None) -> PublishEndpoint: """ Example: .. code-block:: python p.publish( sources=[{'Name': 'aptly-repo'}], architectures=['amd64'], prefix='s3:myendpoint:test/a_1', distribution='test', sign_batch=True, sign_gpgkey='A16BE921', sign_passphrase='*********' ) """ if not sign_skip and not sign_gpgkey: raise AptlyAPIException( "Publish needs a gpgkey to sign with if sign_skip is False") if sign_passphrase is not None and sign_passphrase_file is not None: raise AptlyAPIException( "Can't use sign_passphrase and sign_passphrase_file at the same time" ) for source in sources: if "name" not in source and "Name" not in source: raise AptlyAPIException( "Each source in publish() must contain the 'name' attribute" ) url = "/api/publish" if prefix is not None and prefix != "": url = "/api/publish/%s" % quote(self.escape_prefix(prefix)) body = { "SourceKind": source_kind, "Sources": sources, } # type: T_BodyDict if architectures is not None: body["Architectures"] = architectures if distribution is not None: body["Distribution"] = distribution if label is not None: body["Label"] = label if origin is not None: body["Origin"] = origin if force_overwrite: body["ForceOverwrite"] = True sign_dict = {} # type: Dict[str, Union[bool,str]] if sign_skip: sign_dict["Skip"] = True else: sign_dict["Batch"] = sign_batch if sign_gpgkey is not None: sign_dict["GpgKey"] = sign_gpgkey if sign_keyring is not None: sign_dict["Keyring"] = sign_keyring if sign_secret_keyring is not None: sign_dict["SecretKeyring"] = sign_secret_keyring if sign_passphrase is not None: sign_dict["Passphrase"] = sign_passphrase if sign_passphrase_file is not None: sign_dict["PassphraseFile"] = sign_passphrase_file body["Signing"] = sign_dict resp = self.do_post(url, json=body) return self.endpoint_from_response(resp.json())