s3: verify configured bucket exists at start-up.

Change-Id: I43d0795641fe9dbc345a1f0916b828ede76cf4a6
This commit is contained in:
Brad Fitzpatrick 2013-01-20 11:33:41 -08:00
parent 6e35c1c26e
commit 37bf028633
3 changed files with 51 additions and 8 deletions

View File

@ -52,9 +52,17 @@ func newFromConfig(_ blobserver.Loader, config jsonconfig.Obj) (storage blobserv
// TODO: skip this check if a file
// ~/.camli/.configcheck/sha1-("IS GOOD: s3: sha1(access key +
// secret key)") exists and has recent time?
if _, err := client.Buckets(); err != nil {
buckets, err := client.Buckets()
if err != nil {
return nil, fmt.Errorf("Failed to get bucket list from S3: %v", err)
}
haveBucket := make(map[string]bool)
for _, b := range buckets {
haveBucket[b.Name] = true
}
if !haveBucket[sto.bucket] {
return nil, fmt.Errorf("S3 bucket %q doesn't exist. Create it first at https://console.aws.amazon.com/s3/home")
}
}
return sto, nil
}

View File

@ -71,13 +71,20 @@ func (c *Client) Buckets() ([]*Bucket, error) {
if res.StatusCode != 200 {
return nil, fmt.Errorf("s3: Unexpected status code %d fetching bucket list", res.StatusCode)
}
slurp, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf("s3: Error reading Buckets response: %v", err)
return parseListAllMyBuckets(res.Body)
}
func parseListAllMyBuckets(r io.Reader) ([]*Bucket, error) {
type allMyBuckets struct {
Buckets struct {
Bucket []*Bucket
}
}
// TODO: parse this XML
log.Printf("s3: TODO: parse bucket list: %q", slurp)
return nil, nil
var res allMyBuckets
if err := xml.NewDecoder(r).Decode(&res); err != nil {
return nil, err
}
return res.Buckets.Bucket, nil
}
// Returns 0, os.ErrNotExist if not on S3, otherwise reterr is real.

View File

@ -19,6 +19,8 @@ package s3
import (
"net/http"
"os"
"reflect"
"strings"
"testing"
)
@ -56,4 +58,30 @@ func TestMarker(t *testing.T) {
t.Errorf("marker(%q) = %q; want %q", tt.s, got, tt.want)
}
}
}
}
func TestParseBuckets(t *testing.T) {
res := "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>ownerIDField</ID><DisplayName>bobDisplayName</DisplayName></Owner><Buckets><Bucket><Name>bucketOne</Name><CreationDate>2006-06-21T07:04:31.000Z</CreationDate></Bucket><Bucket><Name>bucketTwo</Name><CreationDate>2006-06-21T07:04:32.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>"
buckets, err := parseListAllMyBuckets(strings.NewReader(res))
if err != nil {
t.Fatal(err)
}
if g, w := len(buckets), 2; g != w {
t.Errorf("num parsed buckets = %d; want %d", g, w)
}
want := []*Bucket{
{Name: "bucketOne", CreationDate: "2006-06-21T07:04:31.000Z"},
{Name: "bucketTwo", CreationDate: "2006-06-21T07:04:32.000Z"},
}
dump := func(v []*Bucket) {
for i, b := range v {
t.Logf("Bucket #%d: %#v", i, b)
}
}
if !reflect.DeepEqual(buckets, want) {
t.Error("mismatch; GOT:")
dump(buckets)
t.Error("WANT:")
dump(want)
}
}