From 2a21b7d63910e8e26e6468fdcb3ad5ee857492cc Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 7 Apr 2015 00:44:01 -0700 Subject: [PATCH] Implement headBucketHandler() and its related tests Remove internal testify/mock and use upstream - update all godeps --- Godeps/Godeps.json | 14 +-- .../minio-io/donut/Godeps/Godeps.json | 8 ++ .../src/github.com/minio-io/donut/Makefile | 4 +- .../donut/buildscripts/git-commit-id.sh | 2 +- .../minio-io/donut/cmd/donut-cli/.gitignore | 1 - .../cmd/donut-cli/donut-cmd-attach-disk.go | 58 --------- .../donut/cmd/donut-cli/donut-cmd-common.go | 110 ------------------ .../donut/cmd/donut-cli/donut-cmd-config.go | 105 ----------------- .../cmd/donut-cli/donut-cmd-detach-disk.go | 66 ----------- .../donut/cmd/donut-cli/donut-cmd-info.go | 84 ------------- .../donut/cmd/donut-cli/donut-cmd-list.go | 36 ------ .../donut/cmd/donut-cli/donut-cmd-make.go | 80 ------------- .../donut/cmd/donut-cli/donut-cmd-options.go | 95 --------------- .../cmd/donut-cli/donut-cmd-rebalance.go | 32 ----- .../minio-io/donut/cmd/donut-cli/donut.go | 33 ------ .../minio-io/donut/objectstorage.go | 15 ++- .../minio-io/objectdriver/Godeps/Godeps.json | 2 +- .../minio-io/objectdriver/api_testsuite.go | 12 +- .../minio-io/objectdriver/donut/donut.go | 25 +++- .../minio-io/objectdriver/driver.go | 1 + .../minio-io/objectdriver/file/file_bucket.go | 13 +++ .../minio-io/objectdriver/memory/memory.go | 8 ++ .../minio-io/objectdriver/mocks/Driver.go | 10 +- .../{fkautz => stretchr}/testify/mock/doc.go | 0 .../{fkautz => stretchr}/testify/mock/mock.go | 0 .../testify/mock/mock_test.go | 0 pkg/api/api_bucket_handlers.go | 36 ++++++ pkg/api/api_router.go | 2 + pkg/api/api_test.go | 29 ++++- 29 files changed, 160 insertions(+), 721 deletions(-) delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/.gitignore delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-attach-disk.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-common.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-config.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-detach-disk.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-info.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-list.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-make.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-options.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-rebalance.go delete mode 100644 Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut.go rename Godeps/_workspace/src/github.com/{fkautz => stretchr}/testify/mock/doc.go (100%) rename Godeps/_workspace/src/github.com/{fkautz => stretchr}/testify/mock/mock.go (100%) rename Godeps/_workspace/src/github.com/{fkautz => stretchr}/testify/mock/mock_test.go (100%) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index eccbf9b98..e1e418e23 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,14 +1,10 @@ { "ImportPath": "github.com/minio-io/minio", - "GoVersion": "go1.4.2", + "GoVersion": "go1.4", "Packages": [ "./..." ], "Deps": [ - { - "ImportPath": "github.com/fkautz/testify/mock", - "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" - }, { "ImportPath": "github.com/gorilla/context", "Rev": "50c25fb3b2b3b3cc724e9b6ac75fb44b3bccd0da" @@ -28,7 +24,7 @@ }, { "ImportPath": "github.com/minio-io/donut", - "Rev": "1adb050ccbc6b56caa8b29502adf43592d16adbd" + "Rev": "9d0c663a857103c780414e15d7e426c6fca9984e" }, { "ImportPath": "github.com/minio-io/erasure", @@ -40,7 +36,7 @@ }, { "ImportPath": "github.com/minio-io/objectdriver", - "Rev": "144846812e29de66814a67b38c949f9875e0ee46" + "Rev": "3efb266b6a644b161d8a4d9a1f55bea95a2e391b" }, { "ImportPath": "github.com/stretchr/objx", @@ -49,6 +45,10 @@ { "ImportPath": "github.com/stretchr/testify/assert", "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" + }, + { + "ImportPath": "github.com/stretchr/testify/mock", + "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" } ] } diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/Godeps/Godeps.json b/Godeps/_workspace/src/github.com/minio-io/donut/Godeps/Godeps.json index 19b4cc246..4df40bb72 100644 --- a/Godeps/_workspace/src/github.com/minio-io/donut/Godeps/Godeps.json +++ b/Godeps/_workspace/src/github.com/minio-io/donut/Godeps/Godeps.json @@ -5,6 +5,10 @@ "./..." ], "Deps": [ + { + "ImportPath": "github.com/minio-io/check", + "Rev": "bc4e66da8cd7ff58a4b9b84301f906352b8f2c94" + }, { "ImportPath": "github.com/minio-io/cli", "Comment": "1.2.0-102-gecb385c", @@ -14,6 +18,10 @@ "ImportPath": "github.com/minio-io/erasure", "Rev": "8a72b14991a6835b4d30403e7cb201f373b7cb3a" }, + { + "ImportPath": "github.com/minio-io/iodine", + "Rev": "55cc4d4256c68fbd6f0775f1a25e37e6a2f6457e" + }, { "ImportPath": "github.com/minio-io/minio/pkg/utils/split", "Rev": "936520e6e0fc5dd4ce8d04504ee991084555e57a" diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/Makefile b/Godeps/_workspace/src/github.com/minio-io/donut/Makefile index b81792b5a..13c10ad12 100644 --- a/Godeps/_workspace/src/github.com/minio-io/donut/Makefile +++ b/Godeps/_workspace/src/github.com/minio-io/donut/Makefile @@ -60,8 +60,8 @@ docs-deploy: @mkdocs gh-deploy --clean install: test-all - @echo "Installing donut-cli:" - @godep go install -a github.com/minio-io/donut/cmd/donut-cli + @echo "Installing donut tool:" + @godep go install -a github.com/minio-io/donut/cmd/donut @mkdir -p $(HOME)/.minio/donut clean: diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/buildscripts/git-commit-id.sh b/Godeps/_workspace/src/github.com/minio-io/donut/buildscripts/git-commit-id.sh index bdcc76391..f0e597483 100644 --- a/Godeps/_workspace/src/github.com/minio-io/donut/buildscripts/git-commit-id.sh +++ b/Godeps/_workspace/src/github.com/minio-io/donut/buildscripts/git-commit-id.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -CONST_FILE=${PWD}/cmd/donut-cli/build-constants.go +CONST_FILE=${PWD}/cmd/donut/build-constants.go cat > $CONST_FILE < is needed for attach") - } - if _, ok := mcDonutConfigData.Donuts[donutName]; !ok { - log.Fatalf("Requested donut name %s does not exist, please use ``mc donut make`` first\n", donutName) - } - if _, ok := mcDonutConfigData.Donuts[donutName].Node["localhost"]; !ok { - log.Fatalln("Corrupted donut config, please consult donut experts") - } - activeDisks := mcDonutConfigData.Donuts[donutName].Node["localhost"].ActiveDisks - inactiveDisks := mcDonutConfigData.Donuts[donutName].Node["localhost"].InactiveDisks - for _, disk := range disks { - activeDisks = appendUniq(activeDisks, disk) - inactiveDisks = deleteFromSlice(inactiveDisks, disk) - } - - mcDonutConfigData.Donuts[donutName].Node["localhost"] = nodeConfig{ - ActiveDisks: activeDisks, - InactiveDisks: inactiveDisks, - } - if err := saveDonutConfig(mcDonutConfigData); err != nil { - log.Fatalln(err) - } -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-common.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-common.go deleted file mode 100644 index d79243dfe..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-common.go +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "strings" - - "net/url" -) - -// url2Object converts URL to bucket and objectname -func url2Object(urlStr string) (bucketName, objectName string, err error) { - u, err := url.Parse(urlStr) - if u.Path == "" { - // No bucket name passed. It is a valid case - return "", "", nil - } - splits := strings.SplitN(u.Path, "/", 3) - switch len(splits) { - case 0, 1: - bucketName = "" - objectName = "" - case 2: - bucketName = splits[1] - objectName = "" - case 3: - bucketName = splits[1] - objectName = splits[2] - } - return bucketName, objectName, nil -} - -func isStringInSlice(items []string, item string) bool { - for _, s := range items { - if s == item { - return true - } - } - return false -} - -func deleteFromSlice(items []string, item string) []string { - var newitems []string - for _, s := range items { - if s == item { - continue - } - newitems = append(newitems, s) - } - return newitems -} - -func appendUniq(slice []string, i string) []string { - for _, ele := range slice { - if ele == i { - return slice - } - } - return append(slice, i) -} - -// Is alphanumeric? -func isalnum(c rune) bool { - return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' -} - -// isValidDonutName - verify donutName to be valid -func isValidDonutName(donutName string) bool { - if len(donutName) > 1024 || len(donutName) == 0 { - return false - } - for _, char := range donutName { - if isalnum(char) { - continue - } - switch char { - case '-': - case '.': - case '_': - case '~': - continue - default: - return false - } - } - return true -} - -// getNodeMap - get a node and disk map through nodeConfig struct -func getNodeMap(node map[string]nodeConfig) map[string][]string { - nodes := make(map[string][]string) - for k, v := range node { - nodes[k] = v.ActiveDisks - } - return nodes -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-config.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-config.go deleted file mode 100644 index f5aada16a..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-config.go +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "fmt" - "log" - "os" - "os/user" - "path" - - "encoding/json" - "io/ioutil" -) - -const ( - donutConfigDir = ".minio/donut" - donutConfigFilename = "donuts.json" -) - -type nodeConfig struct { - ActiveDisks []string - InactiveDisks []string -} - -type donutConfig struct { - Node map[string]nodeConfig -} - -type mcDonutConfig struct { - Donuts map[string]donutConfig -} - -func getDonutConfigDir() string { - u, err := user.Current() - if err != nil { - msg := fmt.Sprintf("Unable to obtain user's home directory. \nError: %s", err) - log.Fatalln(msg) - } - - return path.Join(u.HomeDir, donutConfigDir) -} - -func getDonutConfigFilename() string { - return path.Join(getDonutConfigDir(), "donuts.json") -} - -// saveDonutConfig writes configuration data in json format to donut config file. -func saveDonutConfig(donutConfigData *mcDonutConfig) error { - jsonConfig, err := json.MarshalIndent(donutConfigData, "", "\t") - if err != nil { - return err - } - - err = os.MkdirAll(getDonutConfigDir(), 0755) - if !os.IsExist(err) && err != nil { - return err - } - - configFile, err := os.OpenFile(getDonutConfigFilename(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - return err - } - defer configFile.Close() - - _, err = configFile.Write(jsonConfig) - if err != nil { - return err - } - return nil -} - -func loadDonutConfig() (donutConfigData *mcDonutConfig, err error) { - configFile := getDonutConfigFilename() - _, err = os.Stat(configFile) - if err != nil { - return nil, err - } - - configBytes, err := ioutil.ReadFile(configFile) - if err != nil { - return nil, err - } - - err = json.Unmarshal(configBytes, &donutConfigData) - if err != nil { - return nil, err - } - - return donutConfigData, nil -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-detach-disk.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-detach-disk.go deleted file mode 100644 index 1f6ab79cf..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-detach-disk.go +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "fmt" - "log" - - "github.com/minio-io/cli" -) - -func doDetachDiskCmd(c *cli.Context) { - if !c.Args().Present() { - log.Fatalln("no args?") - } - disks := c.Args() - mcDonutConfigData, err := loadDonutConfig() - if err != nil { - log.Fatalln(err.Error()) - } - donutName := c.String("name") - if donutName == "" { - log.Fatalln("Invalid --donut is needed for attach") - } - if _, ok := mcDonutConfigData.Donuts[donutName]; !ok { - msg := fmt.Sprintf("Requested donut name <%s> does not exist, please use ``mc donut make`` first", donutName) - log.Fatalln(msg) - } - if _, ok := mcDonutConfigData.Donuts[donutName].Node["localhost"]; !ok { - msg := fmt.Sprintf("Corrupted donut config, please consult donut experts") - log.Fatalln(msg) - } - - inactiveDisks := mcDonutConfigData.Donuts[donutName].Node["localhost"].InactiveDisks - activeDisks := mcDonutConfigData.Donuts[donutName].Node["localhost"].ActiveDisks - for _, disk := range disks { - if isStringInSlice(activeDisks, disk) { - activeDisks = deleteFromSlice(activeDisks, disk) - inactiveDisks = appendUniq(inactiveDisks, disk) - } else { - msg := fmt.Sprintf("Cannot detach disk: <%s>, not part of donut <%s>", disk, donutName) - log.Println(msg) - } - } - mcDonutConfigData.Donuts[donutName].Node["localhost"] = nodeConfig{ - ActiveDisks: activeDisks, - InactiveDisks: inactiveDisks, - } - if err := saveDonutConfig(mcDonutConfigData); err != nil { - log.Fatalln(err.Error()) - } -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-info.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-info.go deleted file mode 100644 index 2db70f5c9..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-info.go +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2014,2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "log" - "os" - "strings" - - "text/tabwriter" - "text/template" - - "github.com/minio-io/cli" - "github.com/minio-io/donut" -) - -var infoTemplate = ` -{{range $donutName, $nodes := .}} -DONUTNAME: {{$donutName}} -{{range $nodeName, $disks := $nodes}} -NODE: {{$nodeName}} - DISKS: {{$disks}} -{{end}} -{{end}} -` - -var infoPrinter = func(templ string, data interface{}) { - funcMap := template.FuncMap{ - "join": strings.Join, - } - - w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) - t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) - err := t.Execute(w, data) - if err != nil { - panic(err) - } - w.Flush() -} - -// doInfoDonutCmd -func doInfoDonutCmd(c *cli.Context) { - if !c.Args().Present() { - log.Fatalln("no args?") - } - if len(c.Args()) != 1 { - log.Fatalln("invalid number of args") - } - donutName := c.Args().First() - if !isValidDonutName(donutName) { - log.Fatalln("Invalid donutName") - } - mcDonutConfigData, err := loadDonutConfig() - if err != nil { - log.Fatalln(err) - } - if _, ok := mcDonutConfigData.Donuts[donutName]; !ok { - log.Fatalln("donut does not exist") - } - d, err := donut.NewDonut(donutName, getNodeMap(mcDonutConfigData.Donuts[donutName].Node)) - if err != nil { - log.Fatalln(err) - } - donutNodes := make(map[string]map[string][]string) - donutNodes[donutName], err = d.Info() - if err != nil { - log.Fatalln(err) - } - infoPrinter(infoTemplate, donutNodes) -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-list.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-list.go deleted file mode 100644 index a692bf77e..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-list.go +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2014,2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "fmt" - "log" - - "github.com/minio-io/cli" -) - -// doListDonutCmd creates a new bucket -func doListDonutCmd(c *cli.Context) { - mcDonutConfigData, err := loadDonutConfig() - if err != nil { - log.Fatalln(err) - } - - for k := range mcDonutConfigData.Donuts { - fmt.Println(k) - } -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-make.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-make.go deleted file mode 100644 index 8e0d06a5a..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-make.go +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "fmt" - "log" - "os" - - "github.com/minio-io/cli" -) - -func newDonutConfig(donutName string) (*mcDonutConfig, error) { - mcDonutConfigData := new(mcDonutConfig) - mcDonutConfigData.Donuts = make(map[string]donutConfig) - mcDonutConfigData.Donuts[donutName] = donutConfig{ - Node: make(map[string]nodeConfig), - } - mcDonutConfigData.Donuts[donutName].Node["localhost"] = nodeConfig{ - ActiveDisks: make([]string, 0), - InactiveDisks: make([]string, 0), - } - return mcDonutConfigData, nil -} - -// doMakeDonutCmd creates a new donut -func doMakeDonutCmd(c *cli.Context) { - if !c.Args().Present() { - log.Fatalln("no args?") - } - if len(c.Args()) != 1 { - log.Fatalln("invalid number of args") - } - donutName := c.Args().First() - if !isValidDonutName(donutName) { - log.Fatalln("Invalid donutName") - } - mcDonutConfigData, err := loadDonutConfig() - if os.IsNotExist(err) { - mcDonutConfigData, err = newDonutConfig(donutName) - if err != nil { - log.Fatalln(err) - } - if err := saveDonutConfig(mcDonutConfigData); err != nil { - log.Fatalln(err) - } - return - } else if err != nil { - log.Fatalln(err) - } - if _, ok := mcDonutConfigData.Donuts[donutName]; !ok { - mcDonutConfigData.Donuts[donutName] = donutConfig{ - Node: make(map[string]nodeConfig), - } - mcDonutConfigData.Donuts[donutName].Node["localhost"] = nodeConfig{ - ActiveDisks: make([]string, 0), - InactiveDisks: make([]string, 0), - } - if err := saveDonutConfig(mcDonutConfigData); err != nil { - log.Fatalln(err) - } - } else { - msg := fmt.Sprintf("donut: %s already exists", donutName) - log.Println(msg) - } -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-options.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-options.go deleted file mode 100644 index 5fa40d48e..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-options.go +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "github.com/minio-io/cli" -) - -var makeDonutCmd = cli.Command{ - Name: "make", - Usage: "make donut", - Description: "Make a new donut", - Action: doMakeDonutCmd, -} - -var listDonutCmd = cli.Command{ - Name: "list", - Usage: "list donuts", - Description: "list all donuts locally or remote", - Action: doListDonutCmd, -} - -var attachDiskCmd = cli.Command{ - Name: "attach", - Usage: "attach disk", - Description: "Attach disk to an existing donut", - Action: doAttachDiskCmd, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "name", - Usage: "Donut name", - }, - }, -} - -var detachDiskCmd = cli.Command{ - Name: "detach", - Usage: "detach disk", - Description: "Detach disk from an existing donut", - Action: doDetachDiskCmd, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "name", - Usage: "Donut name", - }, - }, -} - -var healDonutCmd = cli.Command{ - Name: "heal", - Usage: "heal donut", - Description: "Heal donut with any errors", - Action: doHealDonutCmd, -} - -var rebalanceDonutCmd = cli.Command{ - Name: "rebalance", - Usage: "rebalance donut", - Description: "Rebalance data on donut after adding disks", - Action: doRebalanceDonutCmd, -} - -var infoDonutCmd = cli.Command{ - Name: "info", - Usage: "information about donut", - Description: "Pretty print donut information", - Action: doInfoDonutCmd, -} - -var donutOptions = []cli.Command{ - makeDonutCmd, - listDonutCmd, - attachDiskCmd, - detachDiskCmd, - healDonutCmd, - rebalanceDonutCmd, - infoDonutCmd, -} - -func doHealDonutCmd(c *cli.Context) { -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-rebalance.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-rebalance.go deleted file mode 100644 index fcfa5779f..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-rebalance.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "log" - - "github.com/minio-io/cli" - "github.com/minio-io/donut" -) - -func doRebalanceDonutCmd(c *cli.Context) { - if !c.Args().Present() { - log.Fatalln("no args?") - } - donutName := c.Args().First() - if !isValidDonutName(donutName) { - log.Fatalln("Invalid donutName") - } - mcDonutConfigData, err := loadDonutConfig() - if err != nil { - log.Fatalln(err) - } - if _, ok := mcDonutConfigData.Donuts[donutName]; !ok { - log.Fatalln("donut does not exist") - } - d, err := donut.NewDonut(donutName, getNodeMap(mcDonutConfigData.Donuts[donutName].Node)) - if err != nil { - log.Fatalln(err) - } - if err := d.Rebalance(); err != nil { - log.Fatalln(err) - } -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut.go b/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut.go deleted file mode 100644 index 21cb1d53c..000000000 --- a/Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut.go +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2014,2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "os" - - "github.com/minio-io/cli" -) - -func main() { - app := cli.NewApp() - app.Usage = "" - app.Version = gitCommitHash - app.Commands = donutOptions - app.Author = "Minio.io" - app.EnableBashCompletion = true - app.Run(os.Args) -} diff --git a/Godeps/_workspace/src/github.com/minio-io/donut/objectstorage.go b/Godeps/_workspace/src/github.com/minio-io/donut/objectstorage.go index 2143b2cc7..11eedf305 100644 --- a/Godeps/_workspace/src/github.com/minio-io/donut/objectstorage.go +++ b/Godeps/_workspace/src/github.com/minio-io/donut/objectstorage.go @@ -6,19 +6,30 @@ import ( "sort" "strconv" "strings" + "time" "github.com/minio-io/iodine" ) func (d donut) MakeBucket(bucket string) error { if bucket == "" || strings.TrimSpace(bucket) == "" { - return errors.New("invalid argument") + return iodine.New(errors.New("invalid argument"), nil) } return d.makeBucket(bucket) } func (d donut) GetBucketMetadata(bucket string) (map[string]string, error) { - return nil, errors.New("Not implemented") + err := d.getAllBuckets() + if err != nil { + return nil, iodine.New(err, nil) + } + if _, ok := d.buckets[bucket]; !ok { + return nil, iodine.New(errors.New("bucket does not exist"), nil) + } + metadata := make(map[string]string) + metadata["name"] = bucket + metadata["created"] = time.Now().Format(time.RFC3339Nano) // TODO get this, from whatever is written from SetBucketMetadata + return metadata, nil } func (d donut) SetBucketMetadata(bucket string, metadata map[string]string) error { diff --git a/Godeps/_workspace/src/github.com/minio-io/objectdriver/Godeps/Godeps.json b/Godeps/_workspace/src/github.com/minio-io/objectdriver/Godeps/Godeps.json index 2be797549..b2afc89db 100644 --- a/Godeps/_workspace/src/github.com/minio-io/objectdriver/Godeps/Godeps.json +++ b/Godeps/_workspace/src/github.com/minio-io/objectdriver/Godeps/Godeps.json @@ -11,7 +11,7 @@ }, { "ImportPath": "github.com/minio-io/donut", - "Rev": "1adb050ccbc6b56caa8b29502adf43592d16adbd" + "Rev": "9d0c663a857103c780414e15d7e426c6fca9984e" }, { "ImportPath": "github.com/minio-io/erasure", diff --git a/Godeps/_workspace/src/github.com/minio-io/objectdriver/api_testsuite.go b/Godeps/_workspace/src/github.com/minio-io/objectdriver/api_testsuite.go index 7ac6db098..aa561a76b 100644 --- a/Godeps/_workspace/src/github.com/minio-io/objectdriver/api_testsuite.go +++ b/Godeps/_workspace/src/github.com/minio-io/objectdriver/api_testsuite.go @@ -35,6 +35,7 @@ func APITestSuite(c *check.C, create func() Driver) { testPaging(c, create) testObjectOverwriteFails(c, create) testNonExistantBucketOperations(c, create) + testBucketMetadata(c, create) testBucketRecreateFails(c, create) testPutObjectInSubdir(c, create) testListBuckets(c, create) @@ -43,7 +44,6 @@ func APITestSuite(c *check.C, create func() Driver) { testNonExistantObjectInBucket(c, create) testGetDirectoryReturnsObjectNotFound(c, create) testDefaultContentType(c, create) - //testContentMd5Set(c, create) TODO } func testCreateBucket(c *check.C, create func() Driver) { @@ -225,6 +225,16 @@ func testNonExistantBucketOperations(c *check.C, create func() Driver) { c.Assert(err, check.Not(check.IsNil)) } +func testBucketMetadata(c *check.C, create func() Driver) { + drivers := create() + err := drivers.CreateBucket("string") + c.Assert(err, check.IsNil) + + metadata, err := drivers.GetBucketMetadata("string") + c.Assert(err, check.IsNil) + c.Assert(metadata.Name, check.Equals, "string") +} + func testBucketRecreateFails(c *check.C, create func() Driver) { drivers := create() err := drivers.CreateBucket("string") diff --git a/Godeps/_workspace/src/github.com/minio-io/objectdriver/donut/donut.go b/Godeps/_workspace/src/github.com/minio-io/objectdriver/donut/donut.go index 0c0315978..f2f60ef83 100644 --- a/Godeps/_workspace/src/github.com/minio-io/objectdriver/donut/donut.go +++ b/Godeps/_workspace/src/github.com/minio-io/objectdriver/donut/donut.go @@ -119,22 +119,37 @@ func (d donutDriver) CreateBucket(bucketName string) error { if drivers.IsValidBucket(bucketName) && !strings.Contains(bucketName, ".") { return d.donut.MakeBucket(bucketName) } - return errors.New("Invalid bucket") + return iodine.New(errors.New("Invalid bucket"), map[string]string{"bucket": bucketName}) } // GetBucketMetadata retrieves an bucket's metadata -func (d donutDriver) GetBucketMetadata(bucket string) (drivers.BucketMetadata, error) { - return drivers.BucketMetadata{}, errors.New("Not Implemented") +func (d donutDriver) GetBucketMetadata(bucketName string) (drivers.BucketMetadata, error) { + if !drivers.IsValidBucket(bucketName) || strings.Contains(bucketName, ".") { + return drivers.BucketMetadata{}, drivers.BucketNameInvalid{Bucket: bucketName} + } + metadata, err := d.donut.GetBucketMetadata(bucketName) + if err != nil { + return drivers.BucketMetadata{}, drivers.BucketNotFound{Bucket: bucketName} + } + created, err := time.Parse(time.RFC3339Nano, metadata["created"]) + if err != nil { + return drivers.BucketMetadata{}, iodine.New(err, nil) + } + bucketMetadata := drivers.BucketMetadata{ + Name: metadata["name"], + Created: created, + } + return bucketMetadata, nil } // CreateBucketPolicy sets a bucket's access policy func (d donutDriver) CreateBucketPolicy(bucket string, p drivers.BucketPolicy) error { - return errors.New("Not Implemented") + return iodine.New(errors.New("Not Implemented"), nil) } // GetBucketPolicy returns a bucket's access policy func (d donutDriver) GetBucketPolicy(bucket string) (drivers.BucketPolicy, error) { - return drivers.BucketPolicy{}, errors.New("Not Implemented") + return drivers.BucketPolicy{}, iodine.New(errors.New("Not Implemented"), nil) } // GetObject retrieves an object and writes it to a writer diff --git a/Godeps/_workspace/src/github.com/minio-io/objectdriver/driver.go b/Godeps/_workspace/src/github.com/minio-io/objectdriver/driver.go index d13c9c94e..baecf4707 100644 --- a/Godeps/_workspace/src/github.com/minio-io/objectdriver/driver.go +++ b/Godeps/_workspace/src/github.com/minio-io/objectdriver/driver.go @@ -28,6 +28,7 @@ type Driver interface { // Bucket Operations ListBuckets() ([]BucketMetadata, error) CreateBucket(bucket string) error + GetBucketMetadata(bucket string) (BucketMetadata, error) CreateBucketPolicy(bucket string, p BucketPolicy) error GetBucketPolicy(bucket string) (BucketPolicy, error) diff --git a/Godeps/_workspace/src/github.com/minio-io/objectdriver/file/file_bucket.go b/Godeps/_workspace/src/github.com/minio-io/objectdriver/file/file_bucket.go index 1d9f4934f..86a0546cf 100644 --- a/Godeps/_workspace/src/github.com/minio-io/objectdriver/file/file_bucket.go +++ b/Godeps/_workspace/src/github.com/minio-io/objectdriver/file/file_bucket.go @@ -30,6 +30,19 @@ import ( /// Bucket Operations +// GetBucketMetadata - head +func (file *fileDriver) GetBucketMetadata(bucket string) (drivers.BucketMetadata, error) { + st, err := os.Stat(path.Join(file.root, bucket)) + if err != nil { + return drivers.BucketMetadata{}, drivers.BucketNotFound{Bucket: bucket} + } + bucketMetadata := drivers.BucketMetadata{ + Name: st.Name(), + Created: st.ModTime(), + } + return bucketMetadata, nil +} + // ListBuckets - Get service func (file *fileDriver) ListBuckets() ([]drivers.BucketMetadata, error) { files, err := ioutil.ReadDir(file.root) diff --git a/Godeps/_workspace/src/github.com/minio-io/objectdriver/memory/memory.go b/Godeps/_workspace/src/github.com/minio-io/objectdriver/memory/memory.go index ce77f6111..24f1bd0c9 100644 --- a/Godeps/_workspace/src/github.com/minio-io/objectdriver/memory/memory.go +++ b/Godeps/_workspace/src/github.com/minio-io/objectdriver/memory/memory.go @@ -96,6 +96,14 @@ func (memory memoryDriver) GetPartialObject(w io.Writer, bucket, object string, return io.CopyN(w, &sourceBuffer, length) } +// GetBucketMetadata - +func (memory memoryDriver) GetBucketMetadata(bucket string) (drivers.BucketMetadata, error) { + if _, ok := memory.bucketdata[bucket]; ok == false { + return drivers.BucketMetadata{}, drivers.BucketNotFound{Bucket: bucket} + } + return memory.bucketdata[bucket].metadata, nil +} + // CreateBucketPolicy - Not implemented func (memory memoryDriver) CreateBucketPolicy(bucket string, policy drivers.BucketPolicy) error { return drivers.APINotImplemented{API: "PutBucketPolicy"} diff --git a/Godeps/_workspace/src/github.com/minio-io/objectdriver/mocks/Driver.go b/Godeps/_workspace/src/github.com/minio-io/objectdriver/mocks/Driver.go index 290d83574..fea618bc8 100644 --- a/Godeps/_workspace/src/github.com/minio-io/objectdriver/mocks/Driver.go +++ b/Godeps/_workspace/src/github.com/minio-io/objectdriver/mocks/Driver.go @@ -35,6 +35,15 @@ func (m *Driver) CreateBucket(bucket string) error { return r0 } +// GetBucketMetadata is a mock +func (m *Driver) GetBucketMetadata(bucket string) (drivers.BucketMetadata, error) { + ret := m.Called(bucket) + r0 := ret.Get(0).(drivers.BucketMetadata) + r1 := ret.Error(1) + + return r0, r1 +} + // CreateBucketPolicy is a mock func (m *Driver) CreateBucketPolicy(bucket string, p drivers.BucketPolicy) error { ret := m.Called(bucket, p) @@ -71,7 +80,6 @@ func (m *Driver) GetObject(w io.Writer, bucket string, object string) (int64, er r0 = n } } - return r0, r1 } diff --git a/Godeps/_workspace/src/github.com/fkautz/testify/mock/doc.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go similarity index 100% rename from Godeps/_workspace/src/github.com/fkautz/testify/mock/doc.go rename to Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go diff --git a/Godeps/_workspace/src/github.com/fkautz/testify/mock/mock.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go similarity index 100% rename from Godeps/_workspace/src/github.com/fkautz/testify/mock/mock.go rename to Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go diff --git a/Godeps/_workspace/src/github.com/fkautz/testify/mock/mock_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go similarity index 100% rename from Godeps/_workspace/src/github.com/fkautz/testify/mock/mock_test.go rename to Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go diff --git a/pkg/api/api_bucket_handlers.go b/pkg/api/api_bucket_handlers.go index 507699e6c..61b84486b 100644 --- a/pkg/api/api_bucket_handlers.go +++ b/pkg/api/api_bucket_handlers.go @@ -150,3 +150,39 @@ func (server *minioAPI) putBucketHandler(w http.ResponseWriter, req *http.Reques } } } + +// HEAD Bucket +// ---------- +// This operation is useful to determine if a bucket exists. +// The operation returns a 200 OK if the bucket exists and you +// have permission to access it. Otherwise, the operation might +// return responses such as 404 Not Found and 403 Forbidden. +func (server *minioAPI) headBucketHandler(w http.ResponseWriter, req *http.Request) { + // TODO need to peek into bucketPolicy return appropriate checks here + vars := mux.Vars(req) + bucket := vars["bucket"] + acceptsContentType := getContentType(req) + + _, err := server.driver.GetBucketMetadata(bucket) + switch err.(type) { + case nil: + { + w.Header().Set("Server", "Minio") + w.Header().Set("Connection", "close") + w.WriteHeader(http.StatusOK) + } + case drivers.BucketNameInvalid: + { + writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) + } + case drivers.BucketNotFound: + { + writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path) + } + default: + { + log.Error.Println(iodine.New(err, nil)) + writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) + } + } +} diff --git a/pkg/api/api_router.go b/pkg/api/api_router.go index 92d502eea..b65b84fdb 100644 --- a/pkg/api/api_router.go +++ b/pkg/api/api_router.go @@ -37,6 +37,7 @@ func pathMux(api minioAPI, mux *router.Router) *router.Router { mux.HandleFunc("/", api.listBucketsHandler).Methods("GET") mux.HandleFunc("/{bucket}", api.listObjectsHandler).Methods("GET") mux.HandleFunc("/{bucket}", api.putBucketHandler).Methods("PUT") + mux.HandleFunc("/{bucket}", api.headBucketHandler).Methods("HEAD") mux.HandleFunc("/{bucket}/{object:.*}", api.getObjectHandler).Methods("GET") mux.HandleFunc("/{bucket}/{object:.*}", api.headObjectHandler).Methods("HEAD") mux.HandleFunc("/{bucket}/{object:.*}", api.putObjectHandler).Methods("PUT") @@ -56,6 +57,7 @@ func domainMux(api minioAPI, mux *router.Router) *router.Router { api.putObjectHandler).Host("{bucket}" + "." + api.domain).Methods("PUT") mux.HandleFunc("/", api.listBucketsHandler).Methods("GET") mux.HandleFunc("/{bucket}", api.putBucketHandler).Methods("PUT") + mux.HandleFunc("/{bucket}", api.headBucketHandler).Methods("HEAD") return mux } diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index aec2fae0d..80f7bab57 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -32,13 +32,13 @@ import ( "net/http" "net/http/httptest" - "github.com/fkautz/testify/mock" "github.com/minio-io/minio/pkg/api" "github.com/minio-io/objectdriver" "github.com/minio-io/objectdriver/donut" "github.com/minio-io/objectdriver/file" "github.com/minio-io/objectdriver/memory" "github.com/minio-io/objectdriver/mocks" + "github.com/stretchr/testify/mock" . "github.com/minio-io/check" ) @@ -177,6 +177,33 @@ func (s *MySuite) TestEmptyObject(c *C) { verifyHeaders(c, response.Header, resMetadata.Created, 0, "application/octet-stream", resMetadata.Md5) } +func (s *MySuite) TestBucket(c *C) { + switch driver := s.Driver.(type) { + case *mocks.Driver: + { + driver.AssertExpectations(c) + } + } + driver := s.Driver + typedDriver := s.MockDriver + metadata := drivers.BucketMetadata{ + Name: "bucket", + Created: time.Now(), + } + typedDriver.On("CreateBucket", "bucket").Return(nil).Once() + typedDriver.On("GetBucketMetadata", "bucket").Return(metadata, nil).Twice() + + httpHandler := api.HTTPHandler("", driver) + testServer := httptest.NewServer(httpHandler) + defer testServer.Close() + + driver.CreateBucket("bucket") + + response, err := http.Head(testServer.URL + "/bucket") + c.Assert(err, IsNil) + c.Assert(response.StatusCode, Equals, http.StatusOK) +} + func (s *MySuite) TestObject(c *C) { switch driver := s.Driver.(type) { case *mocks.Driver: