forked from TrueCloudLab/distribution
Add TrustId parameter to swift driver
github/ncw/swift has added support for trust, so let's add it. Signed-off-by: Hua Wang <wanghua.humble@gmail.com>
This commit is contained in:
parent
dbbafe92e9
commit
ddb689ef8b
10 changed files with 201 additions and 50 deletions
2
Godeps/Godeps.json
generated
2
Godeps/Godeps.json
generated
|
@ -96,7 +96,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ncw/swift",
|
"ImportPath": "github.com/ncw/swift",
|
||||||
"Rev": "22c8fa9fb5ba145b4d4e2cebb027e84b1a7b1296"
|
"Rev": "ca8cbbde50d4e12dd8ad70b1bd66589ae98efc5c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/yvasiyarov/go-metrics",
|
"ImportPath": "github.com/yvasiyarov/go-metrics",
|
||||||
|
|
1
Godeps/_workspace/src/github.com/ncw/swift/.travis.yml
generated
vendored
1
Godeps/_workspace/src/github.com/ncw/swift/.travis.yml
generated
vendored
|
@ -1,4 +1,5 @@
|
||||||
language: go
|
language: go
|
||||||
|
sudo: false
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.1.2
|
- 1.1.2
|
||||||
|
|
6
Godeps/_workspace/src/github.com/ncw/swift/README.md
generated
vendored
6
Godeps/_workspace/src/github.com/ncw/swift/README.md
generated
vendored
|
@ -77,6 +77,10 @@ And optionally these if using v3 authentication
|
||||||
export SWIFT_API_DOMAIN_ID='domain id'
|
export SWIFT_API_DOMAIN_ID='domain id'
|
||||||
export SWIFT_API_DOMAIN='domain name'
|
export SWIFT_API_DOMAIN='domain name'
|
||||||
|
|
||||||
|
And optionally these if using v3 trust
|
||||||
|
|
||||||
|
export SWIFT_TRUST_ID='TrustId'
|
||||||
|
|
||||||
And optionally this if you want to skip server certificate validation
|
And optionally this if you want to skip server certificate validation
|
||||||
|
|
||||||
export SWIFT_AUTH_INSECURE=1
|
export SWIFT_AUTH_INSECURE=1
|
||||||
|
@ -126,3 +130,5 @@ Contributors
|
||||||
- Sylvain Baubeau <sbaubeau@redhat.com>
|
- Sylvain Baubeau <sbaubeau@redhat.com>
|
||||||
- Chris Kastorff <encryptio@gmail.com>
|
- Chris Kastorff <encryptio@gmail.com>
|
||||||
- Dai HaoJun <haojun.dai@hp.com>
|
- Dai HaoJun <haojun.dai@hp.com>
|
||||||
|
- Hua Wang <wanghua.humble@gmail.com>
|
||||||
|
- Fabian Ruff <fabian@progra.de>
|
||||||
|
|
18
Godeps/_workspace/src/github.com/ncw/swift/auth_v3.go
generated
vendored
18
Godeps/_workspace/src/github.com/ncw/swift/auth_v3.go
generated
vendored
|
@ -33,6 +33,7 @@ type v3AuthRequest struct {
|
||||||
type v3Scope struct {
|
type v3Scope struct {
|
||||||
Project *v3Project `json:"project,omitempty"`
|
Project *v3Project `json:"project,omitempty"`
|
||||||
Domain *v3Domain `json:"domain,omitempty"`
|
Domain *v3Domain `json:"domain,omitempty"`
|
||||||
|
Trust *v3Trust `json:"OS-TRUST:trust,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type v3Domain struct {
|
type v3Domain struct {
|
||||||
|
@ -46,6 +47,10 @@ type v3Project struct {
|
||||||
Domain *v3Domain `json:"domain,omitempty"`
|
Domain *v3Domain `json:"domain,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type v3Trust struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
type v3User struct {
|
type v3User struct {
|
||||||
Domain *v3Domain `json:"domain,omitempty"`
|
Domain *v3Domain `json:"domain,omitempty"`
|
||||||
Id string `json:"id,omitempty"`
|
Id string `json:"id,omitempty"`
|
||||||
|
@ -66,7 +71,12 @@ type v3AuthResponse struct {
|
||||||
Token struct {
|
Token struct {
|
||||||
Expires_At, Issued_At string
|
Expires_At, Issued_At string
|
||||||
Methods []string
|
Methods []string
|
||||||
Roles []map[string]string
|
Roles []struct {
|
||||||
|
Id, Name string
|
||||||
|
Links struct {
|
||||||
|
Self string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Project struct {
|
Project struct {
|
||||||
Domain struct {
|
Domain struct {
|
||||||
|
@ -129,7 +139,9 @@ func (auth *v3Auth) Request(c *Connection) (*http.Request, error) {
|
||||||
v3.Auth.Identity.Password.User.Domain = domain
|
v3.Auth.Identity.Password.User.Domain = domain
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.TenantId != "" || c.Tenant != "" {
|
if c.TrustId != "" {
|
||||||
|
v3.Auth.Scope = &v3Scope{Trust: &v3Trust{Id: c.TrustId}}
|
||||||
|
} else if c.TenantId != "" || c.Tenant != "" {
|
||||||
|
|
||||||
v3.Auth.Scope = &v3Scope{Project: &v3Project{}}
|
v3.Auth.Scope = &v3Scope{Project: &v3Project{}}
|
||||||
|
|
||||||
|
@ -159,7 +171,7 @@ func (auth *v3Auth) Request(c *Connection) (*http.Request, error) {
|
||||||
if !strings.HasSuffix(url, "/") {
|
if !strings.HasSuffix(url, "/") {
|
||||||
url += "/"
|
url += "/"
|
||||||
}
|
}
|
||||||
url += "tokens"
|
url += "auth/tokens"
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
20
Godeps/_workspace/src/github.com/ncw/swift/swift.go
generated
vendored
20
Godeps/_workspace/src/github.com/ncw/swift/swift.go
generated
vendored
|
@ -3,7 +3,10 @@ package swift
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/hmac"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
|
@ -94,6 +97,7 @@ type Connection struct {
|
||||||
Internal bool // Set this to true to use the the internal / service network
|
Internal bool // Set this to true to use the the internal / service network
|
||||||
Tenant string // Name of the tenant (v2 auth only)
|
Tenant string // Name of the tenant (v2 auth only)
|
||||||
TenantId string // Id of the tenant (v2 auth only)
|
TenantId string // Id of the tenant (v2 auth only)
|
||||||
|
TrustId string // Id of the trust (v3 auth only)
|
||||||
Transport http.RoundTripper `json:"-" xml:"-"` // Optional specialised http.Transport (eg. for Google Appengine)
|
Transport http.RoundTripper `json:"-" xml:"-"` // Optional specialised http.Transport (eg. for Google Appengine)
|
||||||
// These are filled in after Authenticate is called as are the defaults for above
|
// These are filled in after Authenticate is called as are the defaults for above
|
||||||
StorageUrl string
|
StorageUrl string
|
||||||
|
@ -1422,8 +1426,10 @@ func (c *Connection) ObjectOpen(container string, objectName string, checkHash b
|
||||||
file.body = io.TeeReader(resp.Body, file.hash)
|
file.body = io.TeeReader(resp.Body, file.hash)
|
||||||
}
|
}
|
||||||
// Read Content-Length
|
// Read Content-Length
|
||||||
file.length, err = getInt64FromHeader(resp, "Content-Length")
|
if resp.Header.Get("Content-Length") != "" {
|
||||||
file.lengthOk = (err == nil)
|
file.length, err = getInt64FromHeader(resp, "Content-Length")
|
||||||
|
file.lengthOk = (err == nil)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1479,6 +1485,16 @@ func (c *Connection) ObjectDelete(container string, objectName string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ObjectTempUrl returns a temporary URL for an object
|
||||||
|
func (c *Connection) ObjectTempUrl(container string, objectName string, secretKey string, method string, expires time.Time) string {
|
||||||
|
mac := hmac.New(sha1.New, []byte(secretKey))
|
||||||
|
prefix, _ := url.Parse(c.StorageUrl)
|
||||||
|
body := fmt.Sprintf("%s\n%d\n%s/%s/%s", method, expires.Unix(), prefix.Path, container, objectName)
|
||||||
|
mac.Write([]byte(body))
|
||||||
|
sig := hex.EncodeToString(mac.Sum(nil))
|
||||||
|
return fmt.Sprintf("%s/%s/%s?temp_url_sig=%s&temp_url_expires=%d", c.StorageUrl, container, objectName, sig, expires.Unix())
|
||||||
|
}
|
||||||
|
|
||||||
// parseResponseStatus parses string like "200 OK" and returns Error.
|
// parseResponseStatus parses string like "200 OK" and returns Error.
|
||||||
//
|
//
|
||||||
// For status codes beween 200 and 299, this returns nil.
|
// For status codes beween 200 and 299, this returns nil.
|
||||||
|
|
66
Godeps/_workspace/src/github.com/ncw/swift/swift_test.go
generated
vendored
66
Godeps/_workspace/src/github.com/ncw/swift/swift_test.go
generated
vendored
|
@ -20,9 +20,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ncw/swift"
|
|
||||||
"github.com/ncw/swift/swifttest"
|
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -30,6 +29,9 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ncw/swift"
|
||||||
|
"github.com/ncw/swift/swifttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -52,6 +54,7 @@ const (
|
||||||
CONTENT_SIZE = int64(len(CONTENTS))
|
CONTENT_SIZE = int64(len(CONTENTS))
|
||||||
CONTENT_MD5 = "827ccb0eea8a706c4c34a16891f84e7b"
|
CONTENT_MD5 = "827ccb0eea8a706c4c34a16891f84e7b"
|
||||||
EMPTY_MD5 = "d41d8cd98f00b204e9800998ecf8427e"
|
EMPTY_MD5 = "d41d8cd98f00b204e9800998ecf8427e"
|
||||||
|
SECRET_KEY = "b3968d0207b54ece87cccc06515a89d4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type someTransport struct{ http.Transport }
|
type someTransport struct{ http.Transport }
|
||||||
|
@ -211,6 +214,28 @@ func TestV3AuthenticateWithDomainNameAndTenantId(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestV3TrustWithTrustId(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
if !isV3Api() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err = makeConnection()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Failed to create server", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.TrustId = os.Getenv("SWIFT_TRUST_ID")
|
||||||
|
|
||||||
|
err = c.Authenticate()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Auth failed", err)
|
||||||
|
}
|
||||||
|
if !c.Authenticated() {
|
||||||
|
t.Fatal("Not authenticated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestV3AuthenticateWithDomainIdAndTenantId(t *testing.T) {
|
func TestV3AuthenticateWithDomainIdAndTenantId(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -1441,6 +1466,43 @@ func TestObjectDifficultName(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTempUrl(t *testing.T) {
|
||||||
|
err := c.ObjectPutBytes(CONTAINER, OBJECT, []byte(CONTENTS), "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := swift.Metadata{}
|
||||||
|
m["temp-url-key"] = SECRET_KEY
|
||||||
|
err = c.AccountUpdate(m.AccountHeaders())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expiresTime := time.Now().Add(20 * time.Minute)
|
||||||
|
tempUrl := c.ObjectTempUrl(CONTAINER, OBJECT, SECRET_KEY, "GET", expiresTime)
|
||||||
|
resp, err := http.Get(tempUrl)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Failed to retrieve file from temporary url")
|
||||||
|
}
|
||||||
|
if resp.StatusCode == 401 {
|
||||||
|
t.Log("Server doesn't support tempurl")
|
||||||
|
} else if resp.StatusCode != 200 {
|
||||||
|
t.Fatal("HTTP Error retrieving file from temporary url", resp.StatusCode)
|
||||||
|
} else {
|
||||||
|
if content, err := ioutil.ReadAll(resp.Body); err != nil || string(content) != CONTENTS {
|
||||||
|
t.Error("Bad content", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.Body.Close()
|
||||||
|
err = c.ObjectDelete(CONTAINER, OBJECT)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestContainerDelete(t *testing.T) {
|
func TestContainerDelete(t *testing.T) {
|
||||||
err := c.ContainerDelete(CONTAINER)
|
err := c.ContainerDelete(CONTAINER)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
122
Godeps/_workspace/src/github.com/ncw/swift/swifttest/server.go
generated
vendored
122
Godeps/_workspace/src/github.com/ncw/swift/swifttest/server.go
generated
vendored
|
@ -8,8 +8,10 @@ package swifttest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/hmac"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -33,19 +35,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DEBUG = false
|
DEBUG = false
|
||||||
|
TEST_ACCOUNT = "swifttest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SwiftServer struct {
|
type SwiftServer struct {
|
||||||
t *testing.T
|
t *testing.T
|
||||||
reqId int
|
reqId int
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
Listener net.Listener
|
Listener net.Listener
|
||||||
AuthURL string
|
AuthURL string
|
||||||
URL string
|
URL string
|
||||||
Containers map[string]*container
|
Accounts map[string]*account
|
||||||
Accounts map[string]*account
|
Sessions map[string]*session
|
||||||
Sessions map[string]*session
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Folder type represents a container stored in an account
|
// The Folder type represents a container stored in an account
|
||||||
|
@ -96,7 +98,8 @@ type metadata struct {
|
||||||
type account struct {
|
type account struct {
|
||||||
swift.Account
|
swift.Account
|
||||||
metadata
|
metadata
|
||||||
password string
|
password string
|
||||||
|
Containers map[string]*container
|
||||||
}
|
}
|
||||||
|
|
||||||
type object struct {
|
type object struct {
|
||||||
|
@ -294,8 +297,8 @@ func (r containerResource) delete(a *action) interface{} {
|
||||||
if len(b.objects) > 0 {
|
if len(b.objects) > 0 {
|
||||||
fatalf(409, "Conflict", "The container you tried to delete is not empty")
|
fatalf(409, "Conflict", "The container you tried to delete is not empty")
|
||||||
}
|
}
|
||||||
delete(a.srv.Containers, b.name)
|
delete(a.user.Containers, b.name)
|
||||||
a.user.Containers--
|
a.user.Account.Containers--
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,8 +319,8 @@ func (r containerResource) put(a *action) interface{} {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r.container.setMetadata(a, "container")
|
r.container.setMetadata(a, "container")
|
||||||
a.srv.Containers[r.name] = r.container
|
a.user.Containers[r.name] = r.container
|
||||||
a.user.Containers++
|
a.user.Account.Containers++
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -430,7 +433,7 @@ func (objr objectResource) get(a *action) interface{} {
|
||||||
if manifest, ok := obj.meta["X-Object-Manifest"]; ok {
|
if manifest, ok := obj.meta["X-Object-Manifest"]; ok {
|
||||||
var segments []io.Reader
|
var segments []io.Reader
|
||||||
components := strings.SplitN(manifest[0], "/", 2)
|
components := strings.SplitN(manifest[0], "/", 2)
|
||||||
segContainer := a.srv.Containers[components[0]]
|
segContainer := a.user.Containers[components[0]]
|
||||||
prefix := components[1]
|
prefix := components[1]
|
||||||
resp := segContainer.list("", "", prefix, "")
|
resp := segContainer.list("", "", prefix, "")
|
||||||
sum := md5.New()
|
sum := md5.New()
|
||||||
|
@ -575,7 +578,7 @@ func (objr objectResource) copy(a *action) interface{} {
|
||||||
objr2 objectResource
|
objr2 objectResource
|
||||||
)
|
)
|
||||||
|
|
||||||
destURL, _ := url.Parse("/v1/AUTH_tk/" + destination)
|
destURL, _ := url.Parse("/v1/AUTH_" + TEST_ACCOUNT + "/" + destination)
|
||||||
r := a.srv.resourceForURL(destURL)
|
r := a.srv.resourceForURL(destURL)
|
||||||
switch t := r.(type) {
|
switch t := r.(type) {
|
||||||
case objectResource:
|
case objectResource:
|
||||||
|
@ -665,16 +668,35 @@ func (s *SwiftServer) serveHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
panic(notAuthorized())
|
panic(notAuthorized())
|
||||||
}
|
}
|
||||||
|
|
||||||
key := req.Header.Get("x-auth-token")
|
|
||||||
session, ok := s.Sessions[key[7:]]
|
|
||||||
if !ok {
|
|
||||||
panic(notAuthorized())
|
|
||||||
}
|
|
||||||
|
|
||||||
a.user = s.Accounts[session.username]
|
|
||||||
|
|
||||||
r = s.resourceForURL(req.URL)
|
r = s.resourceForURL(req.URL)
|
||||||
|
|
||||||
|
key := req.Header.Get("x-auth-token")
|
||||||
|
if key == "" {
|
||||||
|
secretKey := ""
|
||||||
|
signature := req.URL.Query().Get("temp_url_sig")
|
||||||
|
expires := req.URL.Query().Get("temp_url_expires")
|
||||||
|
accountName, _, _, _ := s.parseURL(req.URL)
|
||||||
|
if account, ok := s.Accounts[accountName]; ok {
|
||||||
|
secretKey = account.meta.Get("X-Account-Meta-Temp-Url-Key")
|
||||||
|
}
|
||||||
|
|
||||||
|
mac := hmac.New(sha1.New, []byte(secretKey))
|
||||||
|
body := fmt.Sprintf("%s\n%s\n%s", req.Method, expires, req.URL.Path)
|
||||||
|
mac.Write([]byte(body))
|
||||||
|
expectedSignature := hex.EncodeToString(mac.Sum(nil))
|
||||||
|
|
||||||
|
if signature != expectedSignature {
|
||||||
|
panic(notAuthorized())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
session, ok := s.Sessions[key[7:]]
|
||||||
|
if !ok {
|
||||||
|
panic(notAuthorized())
|
||||||
|
}
|
||||||
|
|
||||||
|
a.user = s.Accounts[session.username]
|
||||||
|
}
|
||||||
|
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case "PUT":
|
case "PUT":
|
||||||
resp = r.put(a)
|
resp = r.put(a)
|
||||||
|
@ -712,22 +734,38 @@ func jsonMarshal(w io.Writer, x interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathRegexp = regexp.MustCompile("/v1/AUTH_[a-zA-Z0-9]+(/([^/]+)(/(.*))?)?")
|
var pathRegexp = regexp.MustCompile("/v1/AUTH_([a-zA-Z0-9]+)(/([^/]+)(/(.*))?)?")
|
||||||
|
|
||||||
|
func (srv *SwiftServer) parseURL(u *url.URL) (account string, container string, object string, err error) {
|
||||||
|
m := pathRegexp.FindStringSubmatch(u.Path)
|
||||||
|
if m == nil {
|
||||||
|
return "", "", "", fmt.Errorf("Couldn't parse the specified URI")
|
||||||
|
}
|
||||||
|
account = m[1]
|
||||||
|
container = m[3]
|
||||||
|
object = m[5]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// resourceForURL returns a resource object for the given URL.
|
// resourceForURL returns a resource object for the given URL.
|
||||||
func (srv *SwiftServer) resourceForURL(u *url.URL) (r resource) {
|
func (srv *SwiftServer) resourceForURL(u *url.URL) (r resource) {
|
||||||
m := pathRegexp.FindStringSubmatch(u.Path)
|
accountName, containerName, objectName, err := srv.parseURL(u)
|
||||||
if m == nil {
|
|
||||||
fatalf(404, "InvalidURI", "Couldn't parse the specified URI")
|
if err != nil {
|
||||||
|
fatalf(404, "InvalidURI", err.Error())
|
||||||
}
|
}
|
||||||
containerName := m[2]
|
|
||||||
objectName := m[4]
|
account, ok := srv.Accounts[accountName]
|
||||||
|
if !ok {
|
||||||
|
fatalf(404, "NoSuchAccount", "The specified account does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
if containerName == "" {
|
if containerName == "" {
|
||||||
return rootResource{}
|
return rootResource{}
|
||||||
}
|
}
|
||||||
b := containerResource{
|
b := containerResource{
|
||||||
name: containerName,
|
name: containerName,
|
||||||
container: srv.Containers[containerName],
|
container: account.Containers[containerName],
|
||||||
}
|
}
|
||||||
|
|
||||||
if objectName == "" {
|
if objectName == "" {
|
||||||
|
@ -780,7 +818,7 @@ func (rootResource) get(a *action) interface{} {
|
||||||
h := a.w.Header()
|
h := a.w.Header()
|
||||||
|
|
||||||
h.Set("X-Account-Bytes-Used", strconv.Itoa(int(a.user.BytesUsed)))
|
h.Set("X-Account-Bytes-Used", strconv.Itoa(int(a.user.BytesUsed)))
|
||||||
h.Set("X-Account-Container-Count", strconv.Itoa(int(a.user.Containers)))
|
h.Set("X-Account-Container-Count", strconv.Itoa(int(a.user.Account.Containers)))
|
||||||
h.Set("X-Account-Object-Count", strconv.Itoa(int(a.user.Objects)))
|
h.Set("X-Account-Object-Count", strconv.Itoa(int(a.user.Objects)))
|
||||||
|
|
||||||
// add metadata
|
// add metadata
|
||||||
|
@ -792,7 +830,7 @@ func (rootResource) get(a *action) interface{} {
|
||||||
|
|
||||||
var tmp orderedContainers
|
var tmp orderedContainers
|
||||||
// first get all matching objects and arrange them in alphabetical order.
|
// first get all matching objects and arrange them in alphabetical order.
|
||||||
for _, container := range a.srv.Containers {
|
for _, container := range a.user.Containers {
|
||||||
if strings.HasPrefix(container.name, prefix) {
|
if strings.HasPrefix(container.name, prefix) {
|
||||||
tmp = append(tmp, container)
|
tmp = append(tmp, container)
|
||||||
}
|
}
|
||||||
|
@ -858,19 +896,19 @@ func NewSwiftServer(address string) (*SwiftServer, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
server := &SwiftServer{
|
server := &SwiftServer{
|
||||||
Listener: l,
|
Listener: l,
|
||||||
AuthURL: "http://" + l.Addr().String() + "/v1.0",
|
AuthURL: "http://" + l.Addr().String() + "/v1.0",
|
||||||
URL: "http://" + l.Addr().String() + "/v1",
|
URL: "http://" + l.Addr().String() + "/v1",
|
||||||
Containers: make(map[string]*container),
|
Accounts: make(map[string]*account),
|
||||||
Accounts: make(map[string]*account),
|
Sessions: make(map[string]*session),
|
||||||
Sessions: make(map[string]*session),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server.Accounts["swifttest"] = &account{
|
server.Accounts[TEST_ACCOUNT] = &account{
|
||||||
password: "swifttest",
|
password: TEST_ACCOUNT,
|
||||||
metadata: metadata{
|
metadata: metadata{
|
||||||
meta: make(http.Header),
|
meta: make(http.Header),
|
||||||
},
|
},
|
||||||
|
Containers: make(map[string]*container),
|
||||||
}
|
}
|
||||||
|
|
||||||
go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
|
|
@ -778,6 +778,17 @@ This storage backend uses Openstack Swift object storage.
|
||||||
Your Openstack domain id for Identity v3 API.
|
Your Openstack domain id for Identity v3 API.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>trustid</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
no
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Your Openstack trust id for Identity v3 API.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<code>insecureskipverify</code>
|
<code>insecureskipverify</code>
|
||||||
|
|
|
@ -61,6 +61,7 @@ type Parameters struct {
|
||||||
TenantID string
|
TenantID string
|
||||||
Domain string
|
Domain string
|
||||||
DomainID string
|
DomainID string
|
||||||
|
TrustID string
|
||||||
Region string
|
Region string
|
||||||
Container string
|
Container string
|
||||||
Prefix string
|
Prefix string
|
||||||
|
@ -156,6 +157,7 @@ func New(params Parameters) (*Driver, error) {
|
||||||
TenantId: params.TenantID,
|
TenantId: params.TenantID,
|
||||||
Domain: params.Domain,
|
Domain: params.Domain,
|
||||||
DomainId: params.DomainID,
|
DomainId: params.DomainID,
|
||||||
|
TrustId: params.TrustID,
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
ConnectTimeout: 60 * time.Second,
|
ConnectTimeout: 60 * time.Second,
|
||||||
Timeout: 15 * 60 * time.Second,
|
Timeout: 15 * 60 * time.Second,
|
||||||
|
|
|
@ -29,6 +29,7 @@ func init() {
|
||||||
tenantID string
|
tenantID string
|
||||||
domain string
|
domain string
|
||||||
domainID string
|
domainID string
|
||||||
|
trustID string
|
||||||
container string
|
container string
|
||||||
region string
|
region string
|
||||||
insecureSkipVerify bool
|
insecureSkipVerify bool
|
||||||
|
@ -42,6 +43,7 @@ func init() {
|
||||||
tenantID = os.Getenv("SWIFT_TENANT_ID")
|
tenantID = os.Getenv("SWIFT_TENANT_ID")
|
||||||
domain = os.Getenv("SWIFT_DOMAIN_NAME")
|
domain = os.Getenv("SWIFT_DOMAIN_NAME")
|
||||||
domainID = os.Getenv("SWIFT_DOMAIN_ID")
|
domainID = os.Getenv("SWIFT_DOMAIN_ID")
|
||||||
|
trustID = os.Getenv("SWIFT_TRUST_ID")
|
||||||
container = os.Getenv("SWIFT_CONTAINER_NAME")
|
container = os.Getenv("SWIFT_CONTAINER_NAME")
|
||||||
region = os.Getenv("SWIFT_REGION_NAME")
|
region = os.Getenv("SWIFT_REGION_NAME")
|
||||||
insecureSkipVerify, _ = strconv.ParseBool(os.Getenv("SWIFT_INSECURESKIPVERIFY"))
|
insecureSkipVerify, _ = strconv.ParseBool(os.Getenv("SWIFT_INSECURESKIPVERIFY"))
|
||||||
|
@ -71,6 +73,7 @@ func init() {
|
||||||
tenantID,
|
tenantID,
|
||||||
domain,
|
domain,
|
||||||
domainID,
|
domainID,
|
||||||
|
trustID,
|
||||||
region,
|
region,
|
||||||
container,
|
container,
|
||||||
root,
|
root,
|
||||||
|
|
Loading…
Reference in a new issue