Skip to content

Commit

Permalink
Add Command Line Tools (#3)
Browse files Browse the repository at this point in the history
* Add pull command

* Add push cmd
  • Loading branch information
shizhMSFT committed Dec 26, 2018
1 parent d12f96d commit d3e1395
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 0 deletions.
18 changes: 18 additions & 0 deletions cmd/oras/main.go
@@ -0,0 +1,18 @@
package main

import (
"os"

"github.com/spf13/cobra"
)

func main() {
cmd := &cobra.Command{
Use: "oras [OPTIONS] COMMAND",
SilenceUsage: true,
}
cmd.AddCommand(pullCmd(), pushCmd())
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
}
55 changes: 55 additions & 0 deletions cmd/oras/pull.go
@@ -0,0 +1,55 @@
package main

import (
"context"
"io/ioutil"
"path"

"github.com/shizhMSFT/oras/pkg/oras"

"github.com/spf13/cobra"
)

type pullOptions struct {
targetRef string
output string
username string
password string
}

func pullCmd() *cobra.Command {
var opts pullOptions
cmd := &cobra.Command{
Use: "pull [OPTIONS] NAME[:TAG|@DIGEST]",
Short: "Pull files from remote registry",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.targetRef = args[0]
return runPull(opts)
},
}

cmd.Flags().StringVarP(&opts.output, "output", "o", "", "output directory")
cmd.Flags().StringVarP(&opts.username, "username", "u", "", "registry username")
cmd.Flags().StringVarP(&opts.password, "password", "p", "", "registry password")
return cmd
}

func runPull(opts pullOptions) error {
resolver := newResolver(opts.username, opts.password)
contents, err := oras.Pull(context.Background(), resolver, opts.targetRef)
if err != nil {
return err
}

for name, content := range contents {
if opts.output != "" {
name = path.Join(opts.output, name)
}
if err := ioutil.WriteFile(name, content, 0644); err != nil {
return err
}
}

return nil
}
50 changes: 50 additions & 0 deletions cmd/oras/push.go
@@ -0,0 +1,50 @@
package main

import (
"context"
"io/ioutil"

"github.com/shizhMSFT/oras/pkg/oras"

"github.com/spf13/cobra"
)

type pushOptions struct {
targetRef string
filenames []string
username string
password string
}

func pushCmd() *cobra.Command {
var opts pushOptions
cmd := &cobra.Command{
Use: "push [OPTIONS] NAME[:TAG|@DIGEST] FILE [FILE...]",
Short: "Push files to remote registry",
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
opts.targetRef = args[0]
opts.filenames = args[1:]
return runPush(opts)
},
}

cmd.Flags().StringVarP(&opts.username, "username", "u", "", "registry username")
cmd.Flags().StringVarP(&opts.password, "password", "p", "", "registry password")
return cmd
}

func runPush(opts pushOptions) error {
resolver := newResolver(opts.username, opts.password)

contents := make(map[string][]byte)
for _, filename := range opts.filenames {
content, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
contents[filename] = content
}

return oras.Push(context.Background(), resolver, opts.targetRef, contents)
}
35 changes: 35 additions & 0 deletions cmd/oras/resolver.go
@@ -0,0 +1,35 @@
package main

import (
"os"

"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
"github.com/docker/cli/cli/config"
"github.com/docker/docker/registry"
)

func newResolver(username, password string) remotes.Resolver {
cfg := config.LoadDefaultConfigFile(os.Stderr)
credential := func(hostName string) (string, string, error) {
if hostName == registry.DefaultV2Registry.Host {
hostName = registry.IndexServer
}
auth, err := cfg.GetAuthConfig(hostName)
if err != nil {
return "", "", err
}
if auth.IdentityToken != "" {
return "", auth.IdentityToken, nil
}
return auth.Username, auth.Password, nil
}
if username != "" {
credential = func(hostName string) (string, string, error) {
return username, password, nil
}
}
return docker.NewResolver(docker.ResolverOptions{
Credentials: credential,
})
}

0 comments on commit d3e1395

Please sign in to comment.