mirror of https://github.com/minio/minio.git
Merge pull request #453 from harshavardhana/pr_out_implement_headbuckethandler_and_its_related_tests
This commit is contained in:
commit
34d06101cc
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 <<EOF
|
||||
/*
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
donut-cli
|
58
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-attach-disk.go
generated
vendored
58
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-attach-disk.go
generated
vendored
|
@ -1,58 +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 (
|
||||
"log"
|
||||
|
||||
"github.com/minio-io/cli"
|
||||
)
|
||||
|
||||
func doAttachDiskCmd(c *cli.Context) {
|
||||
if !c.Args().Present() {
|
||||
log.Fatalln("no args?")
|
||||
}
|
||||
disks := c.Args()
|
||||
mcDonutConfigData, err := loadDonutConfig()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
donutName := c.String("name")
|
||||
if donutName == "" {
|
||||
log.Fatalln("Invalid --donut <name> 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)
|
||||
}
|
||||
}
|
110
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-common.go
generated
vendored
110
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-common.go
generated
vendored
|
@ -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
|
||||
}
|
105
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-config.go
generated
vendored
105
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-config.go
generated
vendored
|
@ -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
|
||||
}
|
66
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-detach-disk.go
generated
vendored
66
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-detach-disk.go
generated
vendored
|
@ -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 <name> 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())
|
||||
}
|
||||
}
|
84
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-info.go
generated
vendored
84
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-info.go
generated
vendored
|
@ -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)
|
||||
}
|
36
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-list.go
generated
vendored
36
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-list.go
generated
vendored
|
@ -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)
|
||||
}
|
||||
}
|
80
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-make.go
generated
vendored
80
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-make.go
generated
vendored
|
@ -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)
|
||||
}
|
||||
}
|
95
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-options.go
generated
vendored
95
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-options.go
generated
vendored
|
@ -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) {
|
||||
}
|
32
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-rebalance.go
generated
vendored
32
Godeps/_workspace/src/github.com/minio-io/donut/cmd/donut-cli/donut-cmd-rebalance.go
generated
vendored
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/minio-io/donut",
|
||||
"Rev": "1adb050ccbc6b56caa8b29502adf43592d16adbd"
|
||||
"Rev": "9d0c663a857103c780414e15d7e426c6fca9984e"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/minio-io/erasure",
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue