oras-project / oras-py

ORAS Python SDK
https://oras-project.github.io/oras-py/
Apache License 2.0
38 stars 31 forks source link

Issue retrieving session url #67

Open alishah730 opened 1 year ago

alishah730 commented 1 year ago

using sample code from here https://github.com/oras-project/oras-py/blob/main/examples/simple/push.py with harbor https://demo.goharbor.io/harbor/projects

#!/usr/bin/env python3

# This shows an example client. You might need to modify the underlying client
# or provider for your use case. See the oras/client.py (client here) and
# oras.provider.py for what is used here (and you might want to customize
# these classes for your needs).

import argparse
import os

import oras.client
import oras.utils
from oras.logger import logger, setup_logger

def load_manifest_annotations(annotation_file, annotations):
    """
    Disambiguate annotations.
    """
    annotations = annotations or []
    if annotation_file and not os.path.exists(annotation_file):
        logger.exit(f"Annotation file {annotation_file} does not exist.")
    if annotation_file:
        lookup = oras.utils.read_json(annotation_file)

        # not allowed to define both, mirroring oras-go
        if "$manifest" in lookup and lookup["$manifest"]:
            raise ValueError(
                "`--annotation` and `--annotation-file` with $manifest cannot be both specified."
            )

    # Finally, parse the list of annotations
    parsed = {}
    for annot in annotations:
        if "=" not in annot:
            logger.exit(
                "Annotation {annot} invalid format, needs to be key=value pair."
            )
        key, value = annot.split("=", 1)
        parsed[key.strip()] = value.strip()
    return parsed

def main(args):
    """
    A wrapper around an oras client push.
    """
    manifest_annotations = load_manifest_annotations(
        args.annotation_file, args.annotation
    )
    client = oras.client.OrasClient(insecure=args.insecure)
    try:
        if args.username and args.password:
            client.set_basic_auth(args.username, args.password)
        client.push(
            config_path=args.config,
            disable_path_validation=args.disable_path_validation,
            files=args.filerefs,
            manifest_config=args.manifest_config,
            annotation_file=args.annotation_file,
            manifest_annotations=manifest_annotations,
            quiet=args.quiet,
            target=args.target,
        )
    except Exception as e:
        logger.exit(str(e))

def get_parser():
    parser = argparse.ArgumentParser(
        description="OCI Registry as Storage Python SDK example push client",
        formatter_class=argparse.RawTextHelpFormatter,
    )

    parser.add_argument(
        "--quiet",
        dest="quiet",
        help="suppress additional output.",
        default=False,
        action="store_true",
    )

    parser.add_argument(
        "--version",
        dest="version",
        help="Show the oras version information.",
        default=False,
        action="store_true",
    )

    parser.add_argument("--annotation-file", help="manifest annotation file")
    parser.add_argument(
        "--annotation",
        help="single manifest annotation (e.g., key=value)",
        action="append",
    )
    parser.add_argument("--manifest-config", help="manifest config file")
    parser.add_argument(
        "--disable-path-validation",
        help="skip path validation",
        default=False,
        action="store_true",
    )
    parser.add_argument("target", help="target")
    parser.add_argument("filerefs", help="file references", nargs="+")

    # Debug is added on the level of the command
    parser.add_argument(
        "--debug",
        dest="debug",
        help="debug mode",
        default=False,
        action="store_true",
    )

    parser.add_argument(
        "-c",
        "--config",
        dest="config",
        help="auth config path",
        action="append",
    )

    parser.add_argument("-u", "--username", dest="username", help="registry username")
    parser.add_argument(
        "-p",
        "--password",
        dest="password",
        help="registry password or identity token",
    )
    parser.add_argument(
        "-i",
        "--insecure",
        dest="insecure",
        help="allow connections to SSL registry without certs",
        default=False,
        action="store_true",
    )
    return parser

if __name__ == "__main__":
    parser = get_parser()
    args, _ = parser.parse_known_args()
    setup_logger(quiet=args.quiet, debug=args.debug)
    main(args)

getting below error

Issue retrieving session url: {'errors': [{'code': 'BLOB_UPLOAD_UNKNOWN', 'message': 'blob upload unknown to registry'}]} raise ValueError(f"Issue retrieving session url: {r.json()}")

py test-oras.py 
{'Status': 'Login Succeeded'}
Traceback (most recent call last):
  File "/Users/ali/Documents/code/oras/test-oras.py", line 5, in <module>
    client.push(files=["repo.txt"], target="demo.goharbor.io/oras/test:latest")
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/oras/client.py", line 112, in push
    return self.remote.push(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/oras/provider.py", line 592, in push
    response = self.upload_blob(blob, container, layer)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/oras/provider.py", line 214, in upload_blob
    response = self.put_upload(blob, container, layer)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/oras/provider.py", line 377, in put_upload
    raise ValueError(f"Issue retrieving session url: {r.json()}")
ValueError: Issue retrieving session url: {'errors': [{'code': 'BLOB_UPLOAD_UNKNOWN', 'message': 'blob upload unknown to registry'}]}

able to push same file via oras cli

oras push demo.goharbor.io/oras/test:latest repo.txt
Uploading fe7d9872a34c repo.txt
Uploaded  fe7d9872a34c repo.txt
Pushed demo.goharbor.io/oras/test:latest
Digest: sha256:a1c6906c2ba07....

is that harbor registry is not supported by oras? any working example with harbor pushing tar file?

vsoch commented 1 year ago

I’m busy this weekend but if you can get me a credential to a testing repo I can look into this for you. Generally I would suggest subclassing the provider.Registry directly and very specifically providing the layers/media types but that’s just my preference. There are examples for how to do this in the documentation.

alishah730 commented 1 year ago

indeed I tried with custom layer as well with the example getting same. You can create a demo Harbor account. Or I can invite to the project. Please let me know

vsoch commented 1 year ago

If you invite me would I still need to make the account? :thinking:

alishah730 commented 1 year ago
image

just need to fill out this form for demo https://demo.goharbor.io/ , no email verification is required.

alishah730 commented 1 year ago

alishah730/Asdf@1234 please use for testing

vsoch commented 1 year ago

I tried making an account, the password that I put doesn't work, and it doesn't let me reset or make another one with the same email - I don't think I can help.

alishah730 commented 1 year ago

i can login using the creds

client = oras.client.OrasClient(insecure=True)
logged=client.login(username="alishah730",password="Asdf@1234",hostname="demo.goharbor.io")
print(logged)

output :

{'Status': 'Login Succeeded'}

@vsoch

vsoch commented 1 year ago

The upload URL returns 404, I'm not sure what to say about that.

In [13]: upload_url
Out[13]: 'http://demo.goharbor.io/v2/oras/test/blobs/uploads/'

In [14]: r.json()
Out[14]: 
{'errors': [{'code': 'BLOB_UPLOAD_UNKNOWN',
   'message': 'blob upload unknown to registry'}]}
vsoch commented 1 year ago

Yes you told me that, I'm not sure how it helps me further debug this. I think it's strange you can't use https

In [23]: r.json()
Out[23]: {'errors': [{'code': 'FORBIDDEN', 'message': 'CSRF token invalid'}]}

If the oras cli works then why not just use it?

vsoch commented 1 year ago

If you want to help, perhaps you can use the working client in some debug mode to provide the url endpoints that are hit and we can compare side by side.

alishah730 commented 1 year ago

Yes you told me that, I'm not sure how it helps me further debug this. I think it's strange you can't use https

In [23]: r.json()
Out[23]: {'errors': [{'code': 'FORBIDDEN', 'message': 'CSRF token invalid'}]}

If the oras cli works then why not just use it?

i need to write a script to customize and push 100+ artifacts.

alishah730 commented 1 year ago

Yes you told me that, I'm not sure how it helps me further debug this. I think it's strange you can't use https

In [23]: r.json()
Out[23]: {'errors': [{'code': 'FORBIDDEN', 'message': 'CSRF token invalid'}]}

If the oras cli works then why not just use it?


oras push demo.goharbor.io/oras/test:latest repo.txt
Uploading fe7d9872a34c repo.txt
Uploaded  fe7d9872a34c repo.txt
Pushed demo.goharbor.io/oras/test:latest
Digest: sha256:a1c6906c2ba07.
```...
vsoch commented 1 year ago

Do you know if harbor accepts the single put request? It could be that it does not, hence the 404 response.

alishah730 commented 1 year ago

Do you know if harbor accepts the single put request? It could be that it does not, hence the 404 response.

not sure, if there is any blob upload API

Harbor API

vsoch commented 1 year ago

@alishah730 could you please try a pull?

vsoch commented 1 year ago

@alishah730 I'm testing chunked upload (which is currently disabled) and it's telling me the project does not exist:

Issue retrieving session url: {'errors': [{'code': 'UNAUTHORIZED', 'message': 'project oras not found: project oras not found'}]}

Could you please make it / verity it exists? Some registries I think require the target project to exist before you can push to it.

alishah730 commented 1 year ago

@alishah730 I'm testing chunked upload (which is currently disabled) and it's telling me the project does not exist:

Issue retrieving session url: {'errors': [{'code': 'UNAUTHORIZED', 'message': 'project oras not found: project oras not found'}]}

Could you please make it / verity it exists? Some registries I think require the target project to exist before you can push to it.

you can use demo/Asdf@1234 , I have created oras

vsoch commented 1 year ago

@alishah730 is this the same one as before? demo/Asdf@1234 is the full project name? (sorry not familiar with how Harbor is organized!)

vsoch commented 1 year ago

@alishah730 please provide a name that doesn't have a @ in it - I don't think that is valid for most registries - it typically is put before a digest at the end.

alishah730 commented 1 year ago

@alishah730 please provide a name that doesn't have a @ in it - I don't think that is valid for most registries - it typically is put before a digest at the end.

this is password.

user : demo password : Asdf@1234 repo : oras host : demo.goharbor.io

sample docker push

docker push demo.goharbor.io/oras/test:latest

vsoch commented 1 year ago

oh gotcha I interpreted what you said wrong. I'll try that!

vsoch commented 1 year ago

okay I keep getting a 404. I don't know why - maybe another one of the oras developers can help. It's usually just me on here so you might have better luck pinging the slack and pointing at this issue.