Update swift lib for adding the support of Openstack Identity v3 API
Signed-off-by: Li Wenquan <wenquan.li@hp.com>master
							parent
							
								
									3fb42a1502
								
							
						
					
					
						commit
						3ff9f9b9cc
					
				|  | @ -87,7 +87,7 @@ | |||
| 		}, | ||||
| 		{ | ||||
| 			"ImportPath": "github.com/ncw/swift", | ||||
| 			"Rev": "021f1ecdb0940ce5c64ce0e27928d9680f85f291" | ||||
| 			"Rev": "22c8fa9fb5ba145b4d4e2cebb027e84b1a7b1296" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"ImportPath": "github.com/yvasiyarov/go-metrics", | ||||
|  |  | |||
|  | @ -34,6 +34,7 @@ Here is a short example from the docs | |||
|         UserName: "user", | ||||
|         ApiKey:   "key", | ||||
|         AuthUrl:  "auth_url", | ||||
|         Domain:   "domain",  // Name of the domain (v3 auth only) | ||||
|         Tenant:   "tenant",  // Name of the tenant (v2 auth only) | ||||
|     } | ||||
|     // Authenticate | ||||
|  | @ -45,7 +46,7 @@ Here is a short example from the docs | |||
|     containers, err := c.ContainerNames(nil) | ||||
|     fmt.Println(containers) | ||||
|     // etc... | ||||
|      | ||||
| 
 | ||||
| Additions | ||||
| --------- | ||||
| 
 | ||||
|  | @ -69,6 +70,25 @@ And optionally these if using v2 authentication | |||
|     export SWIFT_TENANT='TenantName' | ||||
|     export SWIFT_TENANT_ID='TenantId' | ||||
| 
 | ||||
| And optionally these if using v3 authentication | ||||
| 
 | ||||
|     export SWIFT_TENANT='TenantName' | ||||
|     export SWIFT_TENANT_ID='TenantId' | ||||
|     export SWIFT_API_DOMAIN_ID='domain id' | ||||
|     export SWIFT_API_DOMAIN='domain name' | ||||
| 
 | ||||
| And optionally this if you want to skip server certificate validation | ||||
| 
 | ||||
|     export SWIFT_AUTH_INSECURE=1 | ||||
| 
 | ||||
| And optionally this to configure the connect channel timeout, in seconds | ||||
| 
 | ||||
|     export SWIFT_CONNECTION_CHANNEL_TIMEOUT=60 | ||||
| 
 | ||||
| And optionally this to configure the data channel timeout, in seconds | ||||
| 
 | ||||
|     export SWIFT_DATA_CHANNEL_TIMEOUT=60 | ||||
| 
 | ||||
| Then run the tests with `go test` | ||||
| 
 | ||||
| License | ||||
|  | @ -105,3 +125,4 @@ Contributors | |||
| - lsowen <lsowen@s1network.com> | ||||
| - Sylvain Baubeau <sbaubeau@redhat.com> | ||||
| - Chris Kastorff <encryptio@gmail.com> | ||||
| - Dai HaoJun <haojun.dai@hp.com> | ||||
|  |  | |||
|  | @ -29,7 +29,9 @@ type Authenticator interface { | |||
| func newAuth(c *Connection) (Authenticator, error) { | ||||
| 	AuthVersion := c.AuthVersion | ||||
| 	if AuthVersion == 0 { | ||||
| 		if strings.Contains(c.AuthUrl, "v2") { | ||||
| 		if strings.Contains(c.AuthUrl, "v3") { | ||||
| 			AuthVersion = 3 | ||||
| 		} else if strings.Contains(c.AuthUrl, "v2") { | ||||
| 			AuthVersion = 2 | ||||
| 		} else if strings.Contains(c.AuthUrl, "v1") { | ||||
| 			AuthVersion = 1 | ||||
|  | @ -47,6 +49,8 @@ func newAuth(c *Connection) (Authenticator, error) { | |||
| 			// this is just an optimization.
 | ||||
| 			useApiKey: len(c.ApiKey) >= 32, | ||||
| 		}, nil | ||||
| 	case 3: | ||||
| 		return &v3Auth{}, nil | ||||
| 	} | ||||
| 	return nil, newErrorf(500, "Auth Version %d not supported", AuthVersion) | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,207 @@ | |||
| package swift | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	v3AuthMethodToken        = "token" | ||||
| 	v3AuthMethodPassword     = "password" | ||||
| 	v3InterfacePublic        = "public" | ||||
| 	v3InterfaceInternal      = "internal" | ||||
| 	v3InterfaceAdmin         = "admin" | ||||
| 	v3CatalogTypeObjectStore = "object-store" | ||||
| ) | ||||
| 
 | ||||
| // V3 Authentication request
 | ||||
| // http://docs.openstack.org/developer/keystone/api_curl_examples.html
 | ||||
| // http://developer.openstack.org/api-ref-identity-v3.html
 | ||||
| type v3AuthRequest struct { | ||||
| 	Auth struct { | ||||
| 		Identity struct { | ||||
| 			Methods  []string        `json:"methods"` | ||||
| 			Password *v3AuthPassword `json:"password,omitempty"` | ||||
| 			Token    *v3AuthToken    `json:"token,omitempty"` | ||||
| 		} `json:"identity"` | ||||
| 		Scope *v3Scope `json:"scope,omitempty"` | ||||
| 	} `json:"auth"` | ||||
| } | ||||
| 
 | ||||
| type v3Scope struct { | ||||
| 	Project *v3Project `json:"project,omitempty"` | ||||
| 	Domain  *v3Domain  `json:"domain,omitempty"` | ||||
| } | ||||
| 
 | ||||
| type v3Domain struct { | ||||
| 	Id   string `json:"id,omitempty"` | ||||
| 	Name string `json:"name,omitempty"` | ||||
| } | ||||
| 
 | ||||
| type v3Project struct { | ||||
| 	Name   string    `json:"name,omitempty"` | ||||
| 	Id     string    `json:"id,omitempty"` | ||||
| 	Domain *v3Domain `json:"domain,omitempty"` | ||||
| } | ||||
| 
 | ||||
| type v3User struct { | ||||
| 	Domain   *v3Domain `json:"domain,omitempty"` | ||||
| 	Id       string    `json:"id,omitempty"` | ||||
| 	Name     string    `json:"name,omitempty"` | ||||
| 	Password string    `json:"password,omitempty"` | ||||
| } | ||||
| 
 | ||||
| type v3AuthToken struct { | ||||
| 	Id string `json:"id"` | ||||
| } | ||||
| 
 | ||||
| type v3AuthPassword struct { | ||||
| 	User v3User `json:"user"` | ||||
| } | ||||
| 
 | ||||
| // V3 Authentication response
 | ||||
| type v3AuthResponse struct { | ||||
| 	Token struct { | ||||
| 		Expires_At, Issued_At string | ||||
| 		Methods               []string | ||||
| 		Roles                 []map[string]string | ||||
| 
 | ||||
| 		Project struct { | ||||
| 			Domain struct { | ||||
| 				Id, Name string | ||||
| 			} | ||||
| 			Id, Name string | ||||
| 		} | ||||
| 
 | ||||
| 		Catalog []struct { | ||||
| 			Id, Namem, Type string | ||||
| 			Endpoints       []struct { | ||||
| 				Id, Region_Id, Url, Region, Interface string | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		User struct { | ||||
| 			Id, Name string | ||||
| 			Domain   struct { | ||||
| 				Id, Name string | ||||
| 				Links    struct { | ||||
| 					Self string | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		Audit_Ids []string | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type v3Auth struct { | ||||
| 	Auth    *v3AuthResponse | ||||
| 	Headers http.Header | ||||
| } | ||||
| 
 | ||||
| func (auth *v3Auth) Request(c *Connection) (*http.Request, error) { | ||||
| 
 | ||||
| 	var v3i interface{} | ||||
| 
 | ||||
| 	v3 := v3AuthRequest{} | ||||
| 
 | ||||
| 	if c.UserName == "" { | ||||
| 		v3.Auth.Identity.Methods = []string{v3AuthMethodToken} | ||||
| 		v3.Auth.Identity.Token = &v3AuthToken{Id: c.ApiKey} | ||||
| 	} else { | ||||
| 		v3.Auth.Identity.Methods = []string{v3AuthMethodPassword} | ||||
| 		v3.Auth.Identity.Password = &v3AuthPassword{ | ||||
| 			User: v3User{ | ||||
| 				Name:     c.UserName, | ||||
| 				Password: c.ApiKey, | ||||
| 			}, | ||||
| 		} | ||||
| 
 | ||||
| 		var domain *v3Domain | ||||
| 
 | ||||
| 		if c.Domain != "" { | ||||
| 			domain = &v3Domain{Name: c.Domain} | ||||
| 		} else if c.DomainId != "" { | ||||
| 			domain = &v3Domain{Id: c.DomainId} | ||||
| 		} | ||||
| 		v3.Auth.Identity.Password.User.Domain = domain | ||||
| 	} | ||||
| 
 | ||||
| 	if c.TenantId != "" || c.Tenant != "" { | ||||
| 
 | ||||
| 		v3.Auth.Scope = &v3Scope{Project: &v3Project{}} | ||||
| 
 | ||||
| 		if c.TenantId != "" { | ||||
| 			v3.Auth.Scope.Project.Id = c.TenantId | ||||
| 		} else if c.Tenant != "" { | ||||
| 			v3.Auth.Scope.Project.Name = c.Tenant | ||||
| 			var defaultDomain v3Domain | ||||
| 			if c.Domain != "" { | ||||
| 				defaultDomain = v3Domain{Name: "Default"} | ||||
| 			} else if c.DomainId != "" { | ||||
| 				defaultDomain = v3Domain{Id: "Default"} | ||||
| 			} | ||||
| 			v3.Auth.Scope.Project.Domain = &defaultDomain | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	v3i = v3 | ||||
| 
 | ||||
| 	body, err := json.Marshal(v3i) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	url := c.AuthUrl | ||||
| 	if !strings.HasSuffix(url, "/") { | ||||
| 		url += "/" | ||||
| 	} | ||||
| 	url += "tokens" | ||||
| 	req, err := http.NewRequest("POST", url, bytes.NewBuffer(body)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	req.Header.Set("Content-Type", "application/json") | ||||
| 	return req, nil | ||||
| } | ||||
| 
 | ||||
| func (auth *v3Auth) Response(resp *http.Response) error { | ||||
| 	auth.Auth = &v3AuthResponse{} | ||||
| 	auth.Headers = resp.Header | ||||
| 	err := readJson(resp, auth.Auth) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func (auth *v3Auth) endpointUrl(Type string, Internal bool) string { | ||||
| 	for _, catalog := range auth.Auth.Token.Catalog { | ||||
| 		if catalog.Type == Type { | ||||
| 			for _, endpoint := range catalog.Endpoints { | ||||
| 				if Internal { | ||||
| 					if endpoint.Interface == v3InterfaceInternal { | ||||
| 						return endpoint.Url | ||||
| 					} | ||||
| 				} else { | ||||
| 					if endpoint.Interface == v3InterfacePublic { | ||||
| 						return endpoint.Url | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
| 
 | ||||
| func (auth *v3Auth) StorageUrl(Internal bool) string { | ||||
| 	return auth.endpointUrl(v3CatalogTypeObjectStore, Internal) | ||||
| } | ||||
| 
 | ||||
| func (auth *v3Auth) Token() string { | ||||
| 	return auth.Headers.Get("X-Subject-Token") | ||||
| } | ||||
| 
 | ||||
| func (auth *v3Auth) CdnUrl() string { | ||||
| 	return "" | ||||
| } | ||||
|  | @ -80,6 +80,8 @@ const ( | |||
| type Connection struct { | ||||
| 	// Parameters - fill these in before calling Authenticate
 | ||||
| 	// They are all optional except UserName, ApiKey and AuthUrl
 | ||||
| 	Domain         string            // User's domain name
 | ||||
| 	DomainId       string            // User's domain Id
 | ||||
| 	UserName       string            // UserName for api
 | ||||
| 	ApiKey         string            // Key for api access
 | ||||
| 	AuthUrl        string            // Auth URL
 | ||||
|  |  | |||
|  | @ -16,22 +16,24 @@ import ( | |||
| 	"archive/tar" | ||||
| 	"bytes" | ||||
| 	"crypto/md5" | ||||
| 	"crypto/tls" | ||||
| 	"encoding/json" | ||||
| 	"encoding/xml" | ||||
| 	"fmt" | ||||
| 	"github.com/ncw/swift" | ||||
| 	"github.com/ncw/swift/swifttest" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ncw/swift" | ||||
| 	"github.com/ncw/swift/swifttest" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	c                swift.Connection | ||||
| 	c                *swift.Connection | ||||
| 	srv              *swifttest.SwiftServer | ||||
| 	m1               = swift.Metadata{"Hello": "1", "potato-Salad": "2"} | ||||
| 	m2               = swift.Metadata{"hello": "", "potato-salad": ""} | ||||
|  | @ -54,36 +56,106 @@ const ( | |||
| 
 | ||||
| type someTransport struct{ http.Transport } | ||||
| 
 | ||||
| func TestTransport(t *testing.T) { | ||||
| func makeConnection() (*swift.Connection, error) { | ||||
| 	var err error | ||||
| 
 | ||||
| 	UserName := os.Getenv("SWIFT_API_USER") | ||||
| 	ApiKey := os.Getenv("SWIFT_API_KEY") | ||||
| 	AuthUrl := os.Getenv("SWIFT_AUTH_URL") | ||||
| 
 | ||||
| 	Insecure := os.Getenv("SWIFT_AUTH_INSECURE") | ||||
| 	ConnectionChannelTimeout := os.Getenv("SWIFT_CONNECTION_CHANNEL_TIMEOUT") | ||||
| 	DataChannelTimeout := os.Getenv("SWIFT_DATA_CHANNEL_TIMEOUT") | ||||
| 
 | ||||
| 	if UserName == "" || ApiKey == "" || AuthUrl == "" { | ||||
| 		if srv != nil { | ||||
| 			srv.Close() | ||||
| 		} | ||||
| 		srv, err = swifttest.NewSwiftServer("localhost") | ||||
| 		if err != nil { | ||||
| 			t.Fatal("Failed to create server", err) | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		UserName = "swifttest" | ||||
| 		ApiKey = "swifttest" | ||||
| 		AuthUrl = srv.AuthURL | ||||
| 	} | ||||
| 	tr := &someTransport{Transport: http.Transport{MaxIdleConnsPerHost: 2048}} | ||||
| 	ct := swift.Connection{ | ||||
| 
 | ||||
| 	transport := &http.Transport{ | ||||
| 		Proxy:               http.ProxyFromEnvironment, | ||||
| 		MaxIdleConnsPerHost: 2048, | ||||
| 	} | ||||
| 	if Insecure == "1" { | ||||
| 		transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} | ||||
| 	} | ||||
| 
 | ||||
| 	c := swift.Connection{ | ||||
| 		UserName:       UserName, | ||||
| 		ApiKey:         ApiKey, | ||||
| 		AuthUrl:        AuthUrl, | ||||
| 		Tenant:         os.Getenv("SWIFT_TENANT"), | ||||
| 		TenantId:       os.Getenv("SWIFT_TENANT_ID"), | ||||
| 		Transport:      tr, | ||||
| 		Transport:      transport, | ||||
| 		ConnectTimeout: 60 * time.Second, | ||||
| 		Timeout:        60 * time.Second, | ||||
| 	} | ||||
| 	err = ct.Authenticate() | ||||
| 
 | ||||
| 	var timeout int64 | ||||
| 	if ConnectionChannelTimeout != "" { | ||||
| 		timeout, err = strconv.ParseInt(ConnectionChannelTimeout, 10, 32) | ||||
| 		if err == nil { | ||||
| 			c.ConnectTimeout = time.Duration(timeout) * time.Second | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if DataChannelTimeout != "" { | ||||
| 		timeout, err = strconv.ParseInt(DataChannelTimeout, 10, 32) | ||||
| 		if err == nil { | ||||
| 			c.Timeout = time.Duration(timeout) * time.Second | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return &c, nil | ||||
| } | ||||
| 
 | ||||
| func isV3Api() bool { | ||||
| 	AuthUrl := os.Getenv("SWIFT_AUTH_URL") | ||||
| 	return strings.Contains(AuthUrl, "v3") | ||||
| } | ||||
| 
 | ||||
| func TestTransport(t *testing.T) { | ||||
| 	var err error | ||||
| 
 | ||||
| 	c, err = makeConnection() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Failed to create server", err) | ||||
| 	} | ||||
| 
 | ||||
| 	tr := &someTransport{ | ||||
| 		Transport: http.Transport{ | ||||
| 			MaxIdleConnsPerHost: 2048, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	Insecure := os.Getenv("SWIFT_AUTH_INSECURE") | ||||
| 
 | ||||
| 	if Insecure == "1" { | ||||
| 		tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} | ||||
| 	} | ||||
| 
 | ||||
| 	c.Transport = tr | ||||
| 
 | ||||
| 	if isV3Api() { | ||||
| 		c.Tenant = os.Getenv("SWIFT_TENANT") | ||||
| 		c.Domain = os.Getenv("SWIFT_API_DOMAIN") | ||||
| 	} else { | ||||
| 		c.Tenant = os.Getenv("SWIFT_TENANT") | ||||
| 		c.TenantId = os.Getenv("SWIFT_TENANT_ID") | ||||
| 	} | ||||
| 
 | ||||
| 	err = c.Authenticate() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Auth failed", err) | ||||
| 	} | ||||
| 	if !ct.Authenticated() { | ||||
| 	if !c.Authenticated() { | ||||
| 		t.Fatal("Not authenticated") | ||||
| 	} | ||||
| 	if srv != nil { | ||||
|  | @ -92,27 +164,116 @@ func TestTransport(t *testing.T) { | |||
| } | ||||
| 
 | ||||
| // The following Test functions are run in order - this one must come before the others!
 | ||||
| func TestAuthenticate(t *testing.T) { | ||||
| func TestV1V2Authenticate(t *testing.T) { | ||||
| 	var err error | ||||
| 	UserName := os.Getenv("SWIFT_API_USER") | ||||
| 	ApiKey := os.Getenv("SWIFT_API_KEY") | ||||
| 	AuthUrl := os.Getenv("SWIFT_AUTH_URL") | ||||
| 	if UserName == "" || ApiKey == "" || AuthUrl == "" { | ||||
| 		srv, err = swifttest.NewSwiftServer("localhost") | ||||
| 		if err != nil { | ||||
| 			t.Fatal("Failed to create server", err) | ||||
| 		} | ||||
| 		UserName = "swifttest" | ||||
| 		ApiKey = "swifttest" | ||||
| 		AuthUrl = srv.AuthURL | ||||
| 
 | ||||
| 	if isV3Api() { | ||||
| 		return | ||||
| 	} | ||||
| 	c = swift.Connection{ | ||||
| 		UserName: UserName, | ||||
| 		ApiKey:   ApiKey, | ||||
| 		AuthUrl:  AuthUrl, | ||||
| 		Tenant:   os.Getenv("SWIFT_TENANT"), | ||||
| 		TenantId: os.Getenv("SWIFT_TENANT_ID"), | ||||
| 
 | ||||
| 	c, err = makeConnection() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Failed to create server", err) | ||||
| 	} | ||||
| 
 | ||||
| 	c.Tenant = os.Getenv("SWIFT_TENANT") | ||||
| 	c.TenantId = os.Getenv("SWIFT_TENANT_ID") | ||||
| 
 | ||||
| 	err = c.Authenticate() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Auth failed", err) | ||||
| 	} | ||||
| 	if !c.Authenticated() { | ||||
| 		t.Fatal("Not authenticated") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestV3AuthenticateWithDomainNameAndTenantId(t *testing.T) { | ||||
| 	var err error | ||||
| 	if !isV3Api() { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c, err = makeConnection() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Failed to create server", err) | ||||
| 	} | ||||
| 
 | ||||
| 	c.TenantId = os.Getenv("SWIFT_TENANT_ID") | ||||
| 	c.Domain = os.Getenv("SWIFT_API_DOMAIN") | ||||
| 
 | ||||
| 	err = c.Authenticate() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Auth failed", err) | ||||
| 	} | ||||
| 	if !c.Authenticated() { | ||||
| 		t.Fatal("Not authenticated") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestV3AuthenticateWithDomainIdAndTenantId(t *testing.T) { | ||||
| 	var err error | ||||
| 
 | ||||
| 	if !isV3Api() { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c, err = makeConnection() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Failed to create server", err) | ||||
| 	} | ||||
| 
 | ||||
| 	c.TenantId = os.Getenv("SWIFT_TENANT_ID") | ||||
| 	c.DomainId = os.Getenv("SWIFT_API_DOMAIN_ID") | ||||
| 
 | ||||
| 	err = c.Authenticate() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Auth failed", err) | ||||
| 	} | ||||
| 	if !c.Authenticated() { | ||||
| 		t.Fatal("Not authenticated") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestV3AuthenticateWithDomainNameAndTenantName(t *testing.T) { | ||||
| 	var err error | ||||
| 
 | ||||
| 	if !isV3Api() { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c, err = makeConnection() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Failed to create server", err) | ||||
| 	} | ||||
| 
 | ||||
| 	c.Tenant = os.Getenv("SWIFT_TENANT") | ||||
| 	c.Domain = os.Getenv("SWIFT_API_DOMAIN") | ||||
| 
 | ||||
| 	err = c.Authenticate() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Auth failed", err) | ||||
| 	} | ||||
| 	if !c.Authenticated() { | ||||
| 		t.Fatal("Not authenticated") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestV3AuthenticateWithDomainIdAndTenantName(t *testing.T) { | ||||
| 	var err error | ||||
| 
 | ||||
| 	if !isV3Api() { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c, err = makeConnection() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Failed to create server", err) | ||||
| 	} | ||||
| 
 | ||||
| 	c.Tenant = os.Getenv("SWIFT_TENANT") | ||||
| 	c.DomainId = os.Getenv("SWIFT_API_DOMAIN_ID") | ||||
| 
 | ||||
| 	err = c.Authenticate() | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Auth failed", err) | ||||
|  |  | |||
|  | @ -444,7 +444,7 @@ func (objr objectResource) get(a *action) interface{} { | |||
| 				if start >= cursor+length { | ||||
| 					continue | ||||
| 				} | ||||
| 				segments = append(segments, bytes.NewReader(obj.data[max(0, start - cursor):])) | ||||
| 				segments = append(segments, bytes.NewReader(obj.data[max(0, start-cursor):])) | ||||
| 				cursor += length | ||||
| 			} | ||||
| 		} | ||||
|  | @ -452,7 +452,7 @@ func (objr objectResource) get(a *action) interface{} { | |||
| 		if end == -1 { | ||||
| 			end = size | ||||
| 		} | ||||
| 		reader = io.LimitReader(io.MultiReader(segments...), int64(end - start)) | ||||
| 		reader = io.LimitReader(io.MultiReader(segments...), int64(end-start)) | ||||
| 	} else { | ||||
| 		if end == -1 { | ||||
| 			end = len(obj.data) | ||||
|  | @ -461,7 +461,7 @@ func (objr objectResource) get(a *action) interface{} { | |||
| 		reader = bytes.NewReader(obj.data[start:end]) | ||||
| 	} | ||||
| 
 | ||||
| 	h.Set("Content-Length", fmt.Sprint(end - start)) | ||||
| 	h.Set("Content-Length", fmt.Sprint(end-start)) | ||||
| 	h.Set("ETag", hex.EncodeToString(etag)) | ||||
| 	h.Set("Last-Modified", obj.mtime.Format(http.TimeFormat)) | ||||
| 
 | ||||
|  | @ -519,7 +519,7 @@ func (objr objectResource) put(a *action) interface{} { | |||
| 
 | ||||
| 	var content_type string | ||||
| 	if content_type = a.req.Header.Get("Content-Type"); content_type == "" { | ||||
| 		content_type := mime.TypeByExtension(obj.name) | ||||
| 		content_type = mime.TypeByExtension(obj.name) | ||||
| 		if content_type == "" { | ||||
| 			content_type = "application/octet-stream" | ||||
| 		} | ||||
|  | @ -880,6 +880,6 @@ func NewSwiftServer(address string) (*SwiftServer, error) { | |||
| 	return server, nil | ||||
| } | ||||
| 
 | ||||
| func (srv SwiftServer) Close() { | ||||
| func (srv *SwiftServer) Close() { | ||||
| 	srv.Listener.Close() | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue