Skip to content

Commit

Permalink
adding start of work on copy
Browse files Browse the repository at this point in the history
Signed-off-by: vsoch <vsoch@users.noreply.github.com>
  • Loading branch information
vsoch committed Sep 22, 2021
1 parent d87b15b commit 45374c6
Show file tree
Hide file tree
Showing 17 changed files with 1,794 additions and 36 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ $ docker run -it --rm -p 5000:5000 registry
```

And follow [the instructions here](https://oras.land/implementors/#using-docker-registry-with-authentication)
to add authentication (recommended).
to add authentication (recommended). There is a [start-dev-server.sh](start-dev-server.sh) script
in the root of this repository that will start your registry for you after you generate
a credential.

### Login

Expand Down
88 changes: 58 additions & 30 deletions oras/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,37 +52,22 @@ def get_parser():
description=help.login_help,
formatter_class=argparse.RawTextHelpFormatter,
)
login.add_argument(
"-c",
"--config",
dest="debug",
help="auth config path",
default=False,
action="store_true",
)
login.add_argument("hostname", help="hostname", nargs=1)
login.add_argument("-u", "--username", dest="username", help="registry username")
login.add_argument(
"-p", "--password", dest="password", help="registry password or identity token"
)
logout = subparsers.add_parser("logout", description="logout from a registry")

login.add_argument(
"--password-stdin",
dest="password_stdin",
help="read password or identity token from stdin",
default=False,
action="store_true",
)
login.add_argument(
"-k",
"--insecure",
dest="insecure",
help="allow connections to SSL registry without certs",
default=False,
action="store_true",
)

# Login and logout share config and hostname arguments
for command in [login, logout]:
command.add_argument("hostname", help="hostname")

# Debug is added on the level of the command
for command in [login]:
for command in [login, logout, push]:
command.add_argument(
"--debug",
dest="debug",
Expand All @@ -91,9 +76,50 @@ def get_parser():
action="store_true",
)

logout = subparsers.add_parser("logout", description="logout from a registry")
# Copy command
copy = subparsers.add_parser("copy", description=help.copy_help)
copy.add_argument("--manifest-config", help="manifest config file")

copy_required = copy.add_argument_group('required arguments for copy')
copy_required.add_argument("--from", dest="from_str", help="source type and possible options", required=True)
copy_required.add_argument("--to", dest="to_str", help="destination type and possible options", required=True)

pull = subparsers.add_parser("pull", description="pull a container")
push = subparsers.add_parser("push", description="push a container")

push = subparsers.add_parser("push", description=help.push_help)
push.add_argument("target", help="target")
push.add_argument("filerefs", help="file references", nargs="*")
push.add_argument("--manifest-config", help="manifest config file")
push.add_argument("--manifest-path-validation", help="manifest annotation file")
push.add_argument("--disable-path-validation", help="skip path validation", default=False, action="store_true")
push.add_argument("-v", "--verbose", help="verbose output", default=False, action="store_true")

for command in [push, copy]:
command.add_argument("--manifest-config", help="manifest config file")
command.add_argument("--plain-http", help="use plain http and not https", default=False, action="store_true")

for command in [login, logout, push, copy]
command.add_argument(
"-c",
"--config",
dest="config",
help="auth config path",
)

# login and push share username/password, and insecure
for command in [login, push, copy]:
command.add_argument("-u", "--username", dest="username", help="registry username")
command.add_argument(
"-p", "--password", dest="password", help="registry password or identity token")
command.add_argument(
"-k",
"--insecure",
dest="insecure",
help="allow connections to SSL registry without certs",
default=False,
action="store_true",
)

shell = subparsers.add_parser("shell", description="create an interactive shell")
return parser

Expand Down Expand Up @@ -129,11 +155,13 @@ def help(return_code=0):
if args.debug:
os.environ["MESSAGELEVEL"] = "DEBUG"

setup_logger(quiet=args.quiet, debug=args.debug)
setup_logger(quiet=args.quiet, debug=args.debug, verbose=getattr(args, "verbose", False))

# Direct to the right parser
if args.command == "version" or args.version:
from .version import main
elif args.command == "copy":
from .copy import main
elif args.command == "login":
from .login import main
elif args.command == "logout":
Expand All @@ -147,11 +175,11 @@ def help(return_code=0):

# Pass on to the correct parser
return_code = 0
try:
main(args=args, parser=parser, extra=extra, subparser=helper)
sys.exit(return_code)
except UnboundLocalError:
return_code = 1
#try:
main(args=args, parser=parser, extra=extra, subparser=helper)
sys.exit(return_code)
#except UnboundLocalError:
# return_code = 1

help(return_code)

Expand Down
41 changes: 41 additions & 0 deletions oras/client/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

login_help = """
Log in to a remote registry
Example - Login with username and password from command line:
oras-py login -u username -p password localhost:5000
Example - Login with username and password from stdin:
Expand All @@ -19,3 +20,43 @@
Example - Login with insecure registry from command line:
oras-py login --insecure localhost:5000
"""

copy_help = """Copy artifacts from one location to another",
Example - Copy artifacts from local files to local files:
oras copy foo/bar:v1 --from files --to files:path/to/save file1 file2 ... filen
Example - Copy artifacts from registry to local files:
oras copy foo/bar:v1 --from registry --to files:path/to/save
Example - Copy artifacts from registry to oci:
oras copy foo/bar:v1 --from registry --to oci:path/to/oci
Example - Copy artifacts from local files to registry:
oras copy foo/bar:v1 --from files --to registry file1 file2 ... filen
When the source (--from) is "files", the config by default will be "{}" and of media type
application/vnd.unknown.config.v1+json. You can override it by setting the path, for example:
oras copy foo/bar:v1 --from files --manifest-config path/to/config:application/vnd.oci.image.config.v1+json --to files:path/to/save file1 file2 ... fileN"""


logout_help = """
Log out from a remote registry
Example - Logout:
oras-py logout localhost:5000
"""

push_help = """
Push files to remote registry
Example - Push file "hi.txt" with the "application/vnd.oci.image.layer.v1.tar" media type (default):
oras-py push localhost:5000/hello:latest hi.txt
Example - Push file "hi.txt" with the custom "application/vnd.me.hi" media type:
oras-py push localhost:5000/hello:latest hi.txt:application/vnd.me.hi
Example - Push multiple files with different media types:
oras-py push localhost:5000/hello:latest hi.txt:application/vnd.me.hi bye.txt:application/vnd.me.bye
Example - Push file "hi.txt" with the custom manifest config "config.json" of the custom "application/vnd.me.config" media type:
oras-py push --manifest-config config.json:application/vnd.me.config localhost:5000/hello:latest hi.txt
Example - Push file to the insecure registry:
oras-py push localhost:5000/hello:latest hi.txt --insecure
Example - Push file to the HTTP registry:
oras-py push localhost:5000/hello:latest hi.txt --plain-http
"""
6 changes: 3 additions & 3 deletions oras/client/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def main(args, parser, extra, subparser):
password = readline()

# No password provided
elif not args.password:
elif not password:

# No username, try to get from stdin
if not username:
Expand All @@ -40,7 +40,7 @@ def main(args, parser, extra, subparser):

# If we do have a username, we just need a passowrd
else:
password = input("Token: ")
password = input("Password: ")
if not password:
logger.exit("password required")

Expand All @@ -52,6 +52,6 @@ def main(args, parser, extra, subparser):
# Login
# https://docker-py.readthedocs.io/en/stable/client.html?highlight=login#docker.client.DockerClient.login
result = client.login(
username=username, password=password, registry=args.hostname[0]
username=username, password=password, registry=args.hostname, dockercfg_path=args.config
)
logger.info(result["Status"])
2 changes: 2 additions & 0 deletions oras/content/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .content import File, FilePusher
from .file import FileStore
32 changes: 32 additions & 0 deletions oras/content/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
__author__ = "Vanessa Sochat"
__copyright__ = "Copyright 2021, Vanessa Sochat"
__license__ = "MIT"

import opencontainers.image.v1 as ocispec
import opencontainers.digest as digest

# DefaultBlobMediaType specifies the default blob media type
DefaultBlobMediaType = ocispec.MediaTypeImageLayer

# DefaultBlobDirMediaType specifies the default blob directory media type
DefaultBlobDirMediaType = ocispec.MediaTypeImageLayerGzip

# TempFilePattern specifies the pattern to create temporary files
TempFilePattern = "oras"

# AnnotationDigest is the annotation key for the digest of the uncompressed content
AnnotationDigest = "io.deis.oras.content.digest"

# AnnotationUnpack is the annotation key for indication of unpacking
AnnotationUnpack = "io.deis.oras.content.unpack"

# OCIImageIndexFile is the file name of the index from the OCI Image Layout Specification
# Reference: https://github.com/opencontainers/image-spec/blob/master/image-layout.md#indexjson-file
OCIImageIndexFile = "index.json"

# DefaultBlocksize default size of each slice of bytes read in each write through in gunzipand untar.
# Simply uses the same size as io.Copy()
DefaultBlocksize = 32768

# what you get for a blank digest
BlankHash = digest.Digest("sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")

0 comments on commit 45374c6

Please sign in to comment.