1
0
mirror of https://github.com/minio/mc.git synced 2025-11-13 12:22:45 +03:00

mc client interface now provides typed errors

This commit is contained in:
Harshavardhana
2015-04-08 22:21:01 -07:00
parent d21d925bd4
commit 6e9fe6dc56
11 changed files with 110 additions and 75 deletions

View File

@@ -54,9 +54,7 @@ var _config *mcConfig
func getMcConfigDir() string { func getMcConfigDir() string {
u, err := user.Current() u, err := user.Current()
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
msg := fmt.Sprintf("Unable to obtain user's home directory. \nError: %s", err) msg := fmt.Sprintf("Unable to obtain user's home directory. \nError: %s", err)
fatal(msg) fatal(msg)
} }
@@ -179,6 +177,7 @@ func saveConfig(ctx *cli.Context) error {
// Reload and cache new config // Reload and cache new config
_, err = getMcConfig() _, err = getMcConfig()
err = iodine.ToError(err)
if os.IsNotExist(err) { if os.IsNotExist(err) {
return iodine.New(err, nil) return iodine.New(err, nil)
} }
@@ -197,16 +196,12 @@ func getBashCompletion() {
fl, err := os.OpenFile(f, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) fl, err := os.OpenFile(f, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
defer fl.Close() defer fl.Close()
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
_, err = fl.Write(b.Bytes()) _, err = fl.Write(b.Bytes())
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
msg := "\nConfiguration written to " + f msg := "\nConfiguration written to " + f
@@ -314,17 +309,13 @@ func doConfigCmd(ctx *cli.Context) {
default: default:
err := saveConfig(ctx) err := saveConfig(ctx)
if os.IsExist(err) { if os.IsExist(err) {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
msg := fmt.Sprintf("mc: Please rename your current configuration file [%s]\n", getMcConfigFilename()) msg := fmt.Sprintf("mc: Please rename your current configuration file [%s]\n", getMcConfigFilename())
fatal(msg) fatal(msg)
} }
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
msg := fmt.Sprintf("mc: Unable to generate config file [%s]. \nError: %v\n", getMcConfigFilename(), err) msg := fmt.Sprintf("mc: Unable to generate config file [%s]. \nError: %v\n", getMcConfigFilename(), err)
fatal(msg) fatal(msg)
} }

View File

@@ -117,9 +117,7 @@ func multiCopy(targetURLs []string, sourceURL string) (err error) {
for msg := range doPutMultiTarget(targetURLs, md5Hex, sourceSize, targetReaders) { for msg := range doPutMultiTarget(targetURLs, md5Hex, sourceSize, targetReaders) {
if msg.err != nil { if msg.err != nil {
if globalDebugFlag { log.Debug.Println(msg.err)
log.Debug.Println(msg.err)
}
fatal(msg.err) fatal(msg.err)
} }
info("Done") info("Done")
@@ -135,9 +133,7 @@ func doCopyCmd(ctx *cli.Context) {
// Convert arguments to URLs: expand alias, fix format... // Convert arguments to URLs: expand alias, fix format...
urlList, err := parseURLs(ctx) urlList, err := parseURLs(ctx)
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
return return
} }
@@ -146,9 +142,7 @@ func doCopyCmd(ctx *cli.Context) {
err = multiCopy(targetURLs, sourceURL) err = multiCopy(targetURLs, sourceURL)
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
return return
} }

View File

@@ -61,43 +61,33 @@ func doListCmd(ctx *cli.Context) {
urlStr, err := parseURL(ctx.Args().First()) urlStr, err := parseURL(ctx.Args().First())
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
bucketName, objectName, err := url2Object(urlStr) bucketName, objectName, err := url2Object(urlStr)
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
client, err := getNewClient(globalDebugFlag, urlStr) client, err := getNewClient(globalDebugFlag, urlStr)
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
if bucketName == "" { // List all buckets if bucketName == "" { // List all buckets
buckets, err := client.ListBuckets() buckets, err := client.ListBuckets()
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
printBuckets(buckets) printBuckets(buckets)
} else { } else {
items, err = client.ListObjects(bucketName, objectName) items, err = client.ListObjects(bucketName, objectName)
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
printObjects(items) printObjects(items)

View File

@@ -27,40 +27,30 @@ import (
func doMakeBucketCmd(ctx *cli.Context) { func doMakeBucketCmd(ctx *cli.Context) {
urlStr, err := parseURL(ctx.Args().First()) urlStr, err := parseURL(ctx.Args().First())
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
bucket, err := url2Bucket(urlStr) bucket, err := url2Bucket(urlStr)
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
clnt, err := getNewClient(globalDebugFlag, urlStr) clnt, err := getNewClient(globalDebugFlag, urlStr)
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
if !s3.IsValidBucketName(bucket) { if !s3.IsValidBucketName(bucket) {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(errInvalidbucket) fatal(errInvalidbucket)
} }
err = clnt.PutBucket(bucket) err = clnt.PutBucket(bucket)
if err != nil { if err != nil {
if globalDebugFlag { log.Debug.Println(iodine.New(err, nil))
log.Debug.Println(iodine.New(err, nil))
}
fatal(err) fatal(err)
} }
} }

View File

@@ -17,6 +17,7 @@
package client package client
import ( import (
"fmt"
"io" "io"
"time" "time"
) )
@@ -53,3 +54,72 @@ type Item struct {
type Prefix struct { type Prefix struct {
Prefix string Prefix string
} }
/// Collection of standard errors
// InvalidBucketName - bucket name invalid
type InvalidBucketName struct {
Bucket string
}
func (e InvalidBucketName) Error() string {
return fmt.Sprintf("Invalid bucketname %v", e.Bucket)
}
// InvalidArgument - bad arguments provided
type InvalidArgument struct{}
func (e InvalidArgument) Error() string {
return fmt.Sprint("invalid arguments")
}
// InvalidMaxKeys - invalid maxkeys provided
type InvalidMaxKeys struct {
Maxkeys int
}
func (e InvalidMaxKeys) Error() string {
return fmt.Sprintf("invalid maxkeys %v", e.Maxkeys)
}
// InvalidAuthorizationKey - invalid authorization key
type InvalidAuthorizationKey struct{}
func (e InvalidAuthorizationKey) Error() string {
return fmt.Sprint("invalid authorization key")
}
// AuthorizationKeyEmpty - empty auth key provided
type AuthorizationKeyEmpty struct{}
func (e AuthorizationKeyEmpty) Error() string {
return fmt.Sprint("authorization key empty")
}
// InvalidRange - invalid range requested
type InvalidRange struct {
Offset int64
}
func (e InvalidRange) Error() string {
return fmt.Sprintf("invalid range value %v", e.Offset)
}
// BucketNotFound - bucket requested does not exist
type BucketNotFound struct {
Bucket string
}
func (e BucketNotFound) Error() string {
return fmt.Sprintf("bucket: %v not found", e.Bucket)
}
// ObjectNotFound - object requested does not exist
type ObjectNotFound struct {
Bucket string
Object string
}
func (e ObjectNotFound) Error() string {
return fmt.Sprintf("object %v not found at bucket: %v", e.Bucket, e.Object)
}

View File

@@ -39,9 +39,7 @@ limitations under the License.
package s3 package s3
import ( import (
"errors"
"fmt" "fmt"
"os"
"strings" "strings"
"net/http" "net/http"
@@ -81,7 +79,7 @@ func (c *s3Client) ListBuckets() ([]*client.Bucket, error) {
// PutBucket - create new bucket // PutBucket - create new bucket
func (c *s3Client) PutBucket(bucket string) error { func (c *s3Client) PutBucket(bucket string) error {
if !IsValidBucketName(bucket) || strings.Contains(bucket, ".") { if !IsValidBucketName(bucket) || strings.Contains(bucket, ".") {
return errors.New("invalid bucket") return iodine.New(client.InvalidBucketName{Bucket: bucket}, nil)
} }
u := fmt.Sprintf("%s://%s/%s", c.Scheme, c.Host, bucket) u := fmt.Sprintf("%s://%s/%s", c.Scheme, c.Host, bucket)
req := newReq(u) req := newReq(u)
@@ -102,10 +100,10 @@ func (c *s3Client) PutBucket(bucket string) error {
func (c *s3Client) StatBucket(bucket string) error { func (c *s3Client) StatBucket(bucket string) error {
if bucket == "" { if bucket == "" {
return iodine.New(errors.New("invalid argument"), nil) return iodine.New(client.InvalidArgument{}, nil)
} }
if !IsValidBucketName(bucket) || strings.Contains(bucket, ".") { if !IsValidBucketName(bucket) || strings.Contains(bucket, ".") {
return errors.New("invalid bucket") return iodine.New(client.InvalidBucketName{Bucket: bucket}, nil)
} }
u := fmt.Sprintf("%s://%s/%s", c.Scheme, c.Host, bucket) u := fmt.Sprintf("%s://%s/%s", c.Scheme, c.Host, bucket)
req := newReq(u) req := newReq(u)
@@ -119,7 +117,7 @@ func (c *s3Client) StatBucket(bucket string) error {
switch res.StatusCode { switch res.StatusCode {
case http.StatusNotFound: case http.StatusNotFound:
return iodine.New(os.ErrNotExist, nil) return iodine.New(client.BucketNotFound{Bucket: bucket}, nil)
case http.StatusOK: case http.StatusOK:
return nil return nil
default: default:

View File

@@ -79,7 +79,7 @@ func (c *s3Client) queryObjects(bucket string, startAt, prefix, delimiter string
var buffer bytes.Buffer var buffer bytes.Buffer
if maxKeys <= 0 { if maxKeys <= 0 {
return nil, nil, iodine.New(errors.New("negative maxKeys are invalid"), nil) return nil, nil, iodine.New(client.InvalidMaxKeys{Maxkeys: maxKeys}, nil)
} }
marker := startAt marker := startAt

View File

@@ -51,6 +51,7 @@ import (
"encoding/xml" "encoding/xml"
"github.com/minio-io/mc/pkg/client" "github.com/minio-io/mc/pkg/client"
"github.com/minio-io/minio/pkg/iodine"
) )
type listBucketResults struct { type listBucketResults struct {
@@ -164,7 +165,7 @@ func listAllMyBuckets(r io.Reader) ([]*client.Bucket, error) {
} }
var res allMyBuckets var res allMyBuckets
if err := xml.NewDecoder(r).Decode(&res); err != nil { if err := xml.NewDecoder(r).Decode(&res); err != nil {
return nil, err return nil, iodine.New(err, nil)
} }
return res.Buckets.Bucket, nil return res.Buckets.Bucket, nil
} }

View File

@@ -17,8 +17,10 @@
package s3 package s3
import ( import (
"errors"
"net/http" "net/http"
"github.com/minio-io/mc/pkg/client"
"github.com/minio-io/minio/pkg/iodine"
) )
// HTTPTracer provides callback hook mechanism for HTTP transport. // HTTPTracer provides callback hook mechanism for HTTP transport.
@@ -38,24 +40,24 @@ func (t RoundTripTrace) RoundTrip(req *http.Request) (res *http.Response, err er
if t.Trace != nil { if t.Trace != nil {
err = t.Trace.Request(req) err = t.Trace.Request(req)
if err != nil { if err != nil {
return nil, err return nil, iodine.New(err, nil)
} }
} }
if t.Transport == nil { if t.Transport == nil {
return nil, errors.New("TraceRoundTrip.Transport is nil") return nil, iodine.New(client.InvalidArgument{}, nil)
} }
res, err = t.Transport.RoundTrip(req) res, err = t.Transport.RoundTrip(req)
if err != nil { if err != nil {
return res, err return res, iodine.New(err, nil)
} }
if t.Trace != nil { if t.Trace != nil {
t.Trace.Response(res) t.Trace.Response(res)
} }
return res, err return res, iodine.New(err, nil)
} }
// GetNewTraceTransport returns a traceable transport // GetNewTraceTransport returns a traceable transport

View File

@@ -39,10 +39,8 @@ limitations under the License.
package s3 package s3
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"os"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -52,6 +50,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"github.com/minio-io/mc/pkg/client"
"github.com/minio-io/minio/pkg/iodine" "github.com/minio-io/minio/pkg/iodine"
) )
@@ -86,7 +85,7 @@ func (c *s3Client) Put(bucket, key, md5HexString string, size int64, contents io
// Stat - returns 0, "", os.ErrNotExist if not on S3 // Stat - returns 0, "", os.ErrNotExist if not on S3
func (c *s3Client) StatObject(bucket, key string) (size int64, date time.Time, reterr error) { func (c *s3Client) StatObject(bucket, key string) (size int64, date time.Time, reterr error) {
if bucket == "" || key == "" { if bucket == "" || key == "" {
return 0, date, iodine.New(os.ErrNotExist, nil) return 0, date, iodine.New(client.InvalidArgument{}, nil)
} }
req := newReq(c.keyURL(bucket, key)) req := newReq(c.keyURL(bucket, key))
req.Method = "HEAD" req.Method = "HEAD"
@@ -99,7 +98,7 @@ func (c *s3Client) StatObject(bucket, key string) (size int64, date time.Time, r
switch res.StatusCode { switch res.StatusCode {
case http.StatusNotFound: case http.StatusNotFound:
return 0, date, iodine.New(os.ErrNotExist, nil) return 0, date, iodine.New(client.ObjectNotFound{Bucket: bucket, Object: key}, nil)
case http.StatusOK: case http.StatusOK:
size, err = strconv.ParseInt(res.Header.Get("Content-Length"), 10, 64) size, err = strconv.ParseInt(res.Header.Get("Content-Length"), 10, 64)
if err != nil { if err != nil {
@@ -139,7 +138,7 @@ func (c *s3Client) Get(bucket, key string) (body io.ReadCloser, size int64, md5
// If length is negative, the rest of the object is returned. // If length is negative, the rest of the object is returned.
func (c *s3Client) GetPartial(bucket, key string, offset, length int64) (body io.ReadCloser, size int64, md5 string, err error) { func (c *s3Client) GetPartial(bucket, key string, offset, length int64) (body io.ReadCloser, size int64, md5 string, err error) {
if offset < 0 { if offset < 0 {
return nil, 0, "", iodine.New(errors.New("invalid negative offset"), nil) return nil, 0, "", iodine.New(client.InvalidRange{Offset: offset}, nil)
} }
req := newReq(c.keyURL(bucket, key)) req := newReq(c.keyURL(bucket, key))
if length >= 0 { if length >= 0 {

View File

@@ -17,10 +17,10 @@
package s3 package s3
import ( import (
"errors"
"net/http" "net/http"
"strings" "strings"
"github.com/minio-io/mc/pkg/client"
"github.com/minio-io/minio/pkg/iodine" "github.com/minio-io/minio/pkg/iodine"
) )
@@ -56,10 +56,10 @@ Example AWS S3 Request / Response
// HTTP S3 request validator. // HTTP S3 request validator.
func (t s3Verify) Request(req *http.Request) error { func (t s3Verify) Request(req *http.Request) error {
if req.Header.Get("Authorization") == "" { if req.Header.Get("Authorization") == "" {
return iodine.New(errors.New("Client request header has authorization key"), nil) return iodine.New(client.AuthorizationKeyEmpty{}, nil)
} }
if !strings.HasPrefix(req.Header.Get("Authorization"), "AWS") { if !strings.HasPrefix(req.Header.Get("Authorization"), "AWS") {
return iodine.New(errors.New("Client request header has malformed authorization key"), nil) return iodine.New(client.InvalidAuthorizationKey{}, nil)
} }
return nil return nil
} }