Skip to content

Commit

Permalink
Refactor flag parsing code.
Browse files Browse the repository at this point in the history
  • Loading branch information
rlmcpherson committed Jul 23, 2014
1 parent d0d47b0 commit 3ed3f51
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 80 deletions.
12 changes: 2 additions & 10 deletions gof3r/cp.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,8 @@ import (
)

type Cp struct {
NoSSL bool `long:"no-ssl" description:"do not use SSL for endpoint connection."`
NoMd5 bool `long:"no-md5" description:"Do not use md5 hash checking to ensure data integrity."`
Concurrency int `long:"concurrency" short:"c" default:"10" description:"concurrency of transfers"`
PartSize int64 `long:"partsize" short:"s" description:"initial size of concurrent parts, in bytes" default:"20971520"`
EndPoint string `long:"endpoint" description:"Amazon S3 endpoint" default:"s3.amazonaws.com"`
Debug bool `long:"debug" description:"enable debug logging."`
Header http.Header `long:"header" short:"m" description:"HTTP headers"`
//Src flags.Arg `long:"source" description:"s3 object or file to be copied" positional-args:"true" required:"true"`
//Src string `long:"source" positional-args:"true" required:"true"`
//Dst flags.Arg `long:"destination" description:"s3 object file to copy to"`
CommonOpts
Header http.Header `long:"header" short:"m" description:"HTTP headers. May be used to set custom metadata, server-side encryption etc."`
}

var cp Cp
Expand Down
23 changes: 13 additions & 10 deletions gof3r/cp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ const (
)

var tb = os.Getenv("TEST_BUCKET")
var defaultCp = &Cp{EndPoint: "s3.amazonaws.com",
PartSize: mb}
var defaultCp = &Cp{
CommonOpts: CommonOpts{EndPoint: "s3.amazonaws.com",
PartSize: mb}}

type cpTest struct {
*Cp
Expand All @@ -40,20 +41,22 @@ var cpTests = []cpTest{
{defaultCp,
[]string{"s3://" + tb + "/noexist", "/dev/null"},
errors.New("404")},
{&Cp{EndPoint: "s3-external-1.amazonaws.com",
PartSize: mb},
{&Cp{
CommonOpts: CommonOpts{EndPoint: "s3-external-1.amazonaws.com",
PartSize: mb}},
[]string{"s3://" + tb + "/&exist", "/dev/null"},
errors.New("404")},
{&Cp{NoSSL: true,
PartSize: mb},
{&Cp{
CommonOpts: CommonOpts{NoSSL: true,
PartSize: mb}},
[]string{"s3://" + tb + "/t1", "s3://" + tb + "/tdir/.tst"},
nil},
{&Cp{EndPoint: "s3.amazonaws.com",
PartSize: mb},
{&Cp{
CommonOpts: CommonOpts{EndPoint: "s3.amazonaws.com",
PartSize: mb}},
[]string{"s3://" + tb + "/t1"},
errors.New("source and destination arguments required")},
{&Cp{EndPoint: "s3.amazonaws.com",
PartSize: mb},
{defaultCp,
[]string{"s://" + tb + "/t1", "s3://" + tb + "/tdir/.tst"},
errors.New("parse error: s://")},
{defaultCp,
Expand Down
5 changes: 3 additions & 2 deletions gof3r/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
)

type Get struct {
Path string `short:"p" long:"path" description:"Path to file. Defaults to standard output for streaming."`
Key string `long:"key" short:"k" description:"S3 object key" required:"true"`
Bucket string `long:"bucket" short:"b" description:"S3 bucket" required:"true"`
Path string `short:"p" long:"path" description:"Path to file. Defaults to standard output for streaming."`
CommonOpts
VersionID string `short:"v" long:"versionId" description:"Version ID of the object. Incompatible with md5 check (use --no-md5)."`
}
Expand Down Expand Up @@ -60,7 +62,6 @@ func (get *Get) Execute(args []string) (err error) {
}
if get.Debug {
log.Println("Headers: ", header)
debug()
}
return
}
Expand Down
57 changes: 4 additions & 53 deletions gof3r/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ package main
import (
"errors"
"fmt"
"log"
"os"
"runtime"
"time"
Expand All @@ -46,52 +45,13 @@ const (
version = "0.4.1"
)

var AppOpts struct {
Version func() `long:"version" short:"v" description:"Print version"`
Man func() `long:"manpage" short:"m" description:"Create gof3r.man man page in current directory"`
}

var parser = flags.NewParser(&AppOpts, (flags.HelpFlag | flags.PassDoubleDash))

func init() {
func main() {
// set the number of processors to use to the number of cpus for parallelization of concurrent transfers
runtime.GOMAXPROCS(runtime.NumCPU())

// set parser fields
parser.ShortDescription = "streaming, concurrent s3 client"

AppOpts.Version = func() {
fmt.Fprintf(os.Stderr, "%s version %s\n", name, version)
os.Exit(0)
}

AppOpts.Man = func() {
f, err := os.Create(name + ".man")
if err != nil {
log.Fatal(err)
}
parser.WriteManPage(f)
fmt.Fprintf(os.Stderr, "man page written to %s\n", f.Name())
os.Exit(0)
}
}

// CommonOpts are Options common to both puts and gets
type CommonOpts struct {
//Url string `short:"u" long:"url" description:"URL of S3 object"` //TODO: bring back url support
Key string `long:"key" short:"k" description:"S3 object key" required:"true"`
Bucket string `long:"bucket" short:"b" description:"S3 bucket" required:"true"`
NoSSL bool `long:"no-ssl" description:"Do not use SSL for endpoint connection."`
NoMd5 bool `long:"no-md5" description:"Do not use md5 hash checking to ensure data integrity. By default, the md5 hash of is calculated concurrently during puts, stored at <bucket>.md5/<key>.md5, and verified on gets."`
Concurrency int `long:"concurrency" short:"c" default:"10" description:"Concurrency of transfers"`
PartSize int64 `long:"partsize" short:"s" description:"Initial size of concurrent parts, in bytes" default:"20971520"`
EndPoint string `long:"endpoint" description:"Amazon S3 endpoint" default:"s3.amazonaws.com"`
Debug bool `long:"debug" description:"Enable debug logging."`
}

func main() {
// parser calls the Execute functions on Get and Put, after parsing the command line options.
start := time.Now()

// parser calls the Execute function for the command after parsing the command line options.
if _, err := parser.Parse(); err != nil {

// handling for flag parse errors
Expand All @@ -114,9 +74,8 @@ func main() {
fmt.Fprintf(os.Stderr, "Duration: %v\n", time.Since(start))
}

// Gets the AWS Keys from environment variables or the instance-based metadata on EC2
// getAWSKeys gets the AWS Keys from environment variables or the instance-based metadata on EC2
// Environment variables are attempted first, followed by the instance-based credentials.
// It returns an error if no keys are found.
func getAWSKeys() (keys s3gof3r.Keys, err error) {

keys, err = s3gof3r.EnvKeys()
Expand All @@ -130,11 +89,3 @@ func getAWSKeys() (keys s3gof3r.Keys, err error) {
err = errors.New("no AWS keys found")
return
}

func debug() {
log.Println("Running debug report...")
var m runtime.MemStats
runtime.ReadMemStats(&m)
log.Println("MEMORY STATS")
log.Printf("%d,%d,%d,%d\n", m.HeapSys, m.HeapAlloc, m.HeapIdle, m.HeapReleased)
}
47 changes: 47 additions & 0 deletions gof3r/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"fmt"
"log"
"os"

"github.com/jessevdk/go-flags"
)

// CommonOpts are Options common to all commands
type CommonOpts struct {
NoSSL bool `long:"no-ssl" description:"Do not use SSL for endpoint connection."`
NoMd5 bool `long:"no-md5" description:"Do not use md5 hash checking to ensure data integrity. By default, the md5 hash of is calculated concurrently during puts, stored at <bucket>.md5/<key>.md5, and verified on gets."`
Concurrency int `long:"concurrency" short:"c" default:"10" description:"Concurrency of transfers"`
PartSize int64 `long:"partsize" short:"s" description:"Initial size of concurrent parts, in bytes" default:"20971520"`
EndPoint string `long:"endpoint" description:"Amazon S3 endpoint" default:"s3.amazonaws.com"`
Debug bool `long:"debug" description:"Enable debug logging."`
}

var AppOpts struct {
Version func() `long:"version" short:"v" description:"Print version"`
Man func() `long:"manpage" short:"m" description:"Create gof3r.man man page in current directory"`
}

var parser = flags.NewParser(&AppOpts, (flags.HelpFlag | flags.PassDoubleDash))

func init() {

// set parser fields
parser.ShortDescription = "streaming, concurrent s3 client"

AppOpts.Version = func() {
fmt.Fprintf(os.Stderr, "%s version %s\n", name, version)
os.Exit(0)
}

AppOpts.Man = func() {
f, err := os.Create(name + ".man")
if err != nil {
log.Fatal(err)
}
parser.WriteManPage(f)
fmt.Fprintf(os.Stderr, "man page written to %s\n", f.Name())
os.Exit(0)
}
}
9 changes: 4 additions & 5 deletions gof3r/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (
)

type Put struct {
Path string `short:"p" long:"path" description:"Path to file. Defaults to standard input for streaming."`
Key string `long:"key" short:"k" description:"S3 object key" required:"true"`
Bucket string `long:"bucket" short:"b" description:"S3 bucket" required:"true"`
Path string `short:"p" long:"path" description:"Path to file. Defaults to standard input for streaming."`
CommonOpts
Header http.Header `long:"header" short:"m" description:"HTTP headers"`
Header http.Header `long:"header" short:"m" description:"HTTP headers. May be used to set custom metadata, server-side encryption etc."`
}

var put Put
Expand Down Expand Up @@ -57,9 +59,6 @@ func (put *Put) Execute(args []string) (err error) {
if err = w.Close(); err != nil {
return
}
if put.Debug {
debug()
}
return
}

Expand Down

0 comments on commit 3ed3f51

Please sign in to comment.