Codebase list golang-github-ncw-swift / 8d121fa0-d69f-400e-9ef9-7e42d7a9ec08/upstream
Import upstream version 2.0.1 Debian Janitor 2 years ago
28 changed file(s) with 1343 addition(s) and 747 deletion(s). Raw diff Collapse all Expand all
0 github: [ncw]
1 patreon: njcw
2 liberapay: ncw
0 ---
1 # Github Actions build for swift
2 # -*- compile-command: "yamllint -f parsable build.yml" -*-
3
4 name: build
5
6 # Trigger the workflow on push or pull request
7 on:
8 push:
9 branches:
10 - '*'
11 tags:
12 - '*'
13 pull_request:
14 workflow_dispatch:
15 inputs:
16 manual:
17 required: true
18 default: true
19
20 jobs:
21 build:
22 if: ${{ github.repository == 'ncw/swift' || github.event.inputs.manual }}
23 timeout-minutes: 60
24 strategy:
25 fail-fast: false
26 matrix:
27 job_name: ['go1.17', 'go1.16', 'go1.15']
28
29 include:
30 - job_name: go1.17
31 os: ubuntu-latest
32 go: '1.17.x'
33 gotests: true
34 integrationtest: true
35 check: true
36
37 - job_name: go1.16
38 os: ubuntu-latest
39 go: '1.16.x'
40 gotests: true
41 integrationtest: true
42 check: false
43
44 - job_name: go1.15
45 os: ubuntu-latest
46 go: '1.15.x'
47 gotests: true
48 integrationtest: true
49 check: false
50
51 name: ${{ matrix.job_name }}
52
53 runs-on: ${{ matrix.os }}
54
55 steps:
56 - name: Checkout
57 uses: actions/checkout@v2
58 with:
59 fetch-depth: 0
60
61 - name: Install Go
62 uses: actions/setup-go@v2
63 with:
64 stable: 'false'
65 go-version: ${{ matrix.go }}
66
67 - name: Print Go version and environment
68 shell: bash
69 run: |
70 printf "Using go at: $(which go)\n"
71 printf "Go version: $(go version)\n"
72 printf "\n\nGo environment:\n\n"
73 go env
74 printf "\n\nSystem environment:\n\n"
75 env
76
77 - name: Go module cache
78 uses: actions/cache@v2
79 with:
80 path: ~/go/pkg/mod
81 key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
82 restore-keys: |
83 ${{ runner.os }}-go-
84
85 - name: Build
86 shell: bash
87 run: |
88 go build ./...
89
90 - name: Unit tests
91 shell: bash
92 run: |
93 go test -v
94 if: matrix.gotests
95
96 - name: Integration tests
97 shell: bash
98 run: |
99 ./integration_test.sh
100 if: matrix.integrationtest
101
102 - name: Code quality test
103 uses: golangci/golangci-lint-action@v2
104 with:
105 # Version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
106 version: latest
107 if: matrix.check
0 # golangci-lint configuration options
1
2 linters:
3 enable:
4 - deadcode
5 - errcheck
6 - goimports
7 # - revive
8 - ineffassign
9 - structcheck
10 - varcheck
11 - govet
12 - unconvert
13 disable-all: true
14
15 issues:
16 # Enable some lints excluded by default
17 exclude-use-default: false
18
19 # Maximum issues count per one linter. Set to 0 to disable. Default is 50.
20 max-per-linter: 0
21
22 # Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
23 max-same-issues: 0
+0
-35
.travis.yml less more
0 language: go
1 sudo: false
2
3 go:
4 - 1.2.x
5 - 1.3.x
6 - 1.4.x
7 - 1.5.x
8 - 1.6.x
9 - 1.7.x
10 - 1.8.x
11 - 1.9.x
12 - 1.10.x
13 - 1.11.x
14 - 1.12.x
15 - 1.13.x
16 - 1.14.x
17 - master
18
19 matrix:
20 include:
21 - go: 1.14.x
22 env: TEST_REAL_SERVER=rackspace
23 - go: 1.14.x
24 env: TEST_REAL_SERVER=memset
25 allow_failures:
26 - go: 1.14.x
27 env: TEST_REAL_SERVER=rackspace
28 - go: 1.14.x
29 env: TEST_REAL_SERVER=memset
30 install: go test -i ./...
31 script:
32 - test -z "$(go fmt ./...)"
33 - go test
34 - ./travis_realserver.sh
00 Swift
11 =====
22
3 This package provides an easy to use library for interfacing with
4 Swift / Openstack Object Storage / Rackspace cloud files from the Go
5 Language
3 This package provides an easy to use library for interfacing with Swift / Openstack Object Storage / Rackspace cloud
4 files from the Go Language
65
7 See here for package docs
8
9 http://godoc.org/github.com/ncw/swift
10
11 [![Build Status](https://api.travis-ci.org/ncw/swift.svg?branch=master)](https://travis-ci.org/ncw/swift) [![GoDoc](https://godoc.org/github.com/ncw/swift?status.svg)](https://godoc.org/github.com/ncw/swift)
6 [![Build Status](https://github.com/ncw/swift/workflows/build/badge.svg?branch=master)](https://github.com/ncw/swift/actions)
7 [![Go Reference](https://pkg.go.dev/badge/github.com/ncw/v2/swift.svg)](https://pkg.go.dev/github.com/ncw/swift/v2)
128
139 Install
1410 -------
1511
1612 Use go to install the library
1713
18 go get github.com/ncw/swift
14 go get github.com/ncw/swift/v2
1915
2016 Usage
2117 -----
2218
2319 See here for full package docs
2420
25 - http://godoc.org/github.com/ncw/swift
21 - https://pkg.go.dev/github.com/ncw/swift/v2
2622
2723 Here is a short example from the docs
24
2825 ```go
29 import "github.com/ncw/swift"
26 import "github.com/ncw/swift/v2"
3027
3128 // Create a connection
3229 c := swift.Connection{
33 UserName: "user",
34 ApiKey: "key",
35 AuthUrl: "auth_url",
36 Domain: "domain", // Name of the domain (v3 auth only)
37 Tenant: "tenant", // Name of the tenant (v2 auth only)
30 UserName: "user",
31 ApiKey: "key",
32 AuthUrl: "auth_url",
33 Domain: "domain", // Name of the domain (v3 auth only)
34 Tenant: "tenant", // Name of the tenant (v2 auth only)
3835 }
3936 // Authenticate
4037 err := c.Authenticate()
4138 if err != nil {
42 panic(err)
39 panic(err)
4340 }
4441 // List all the containers
4542 containers, err := c.ContainerNames(nil)
4643 fmt.Println(containers)
4744 // etc...
4845 ```
46
47 Migrating from `v1`
48 -----
49 The library has current major version v2. If you want to migrate from the first version of
50 library `github.com/ncw/swift` you have to explicitly add the `/v2` suffix to the imports.
51
52 Most of the exported functions were added a new `context.Context` parameter in the `v2`, which you will have to provide
53 when migrating.
4954
5055 Additions
5156 ---------
5560 Testing
5661 -------
5762
58 To run the tests you can either use an embedded fake Swift server
59 either use a real Openstack Swift server or a Rackspace Cloud files account.
63 To run the tests you can either use an embedded fake Swift server either use a real Openstack Swift server or a
64 Rackspace Cloud files account.
6065
61 When using a real Swift server, you need to set these environment variables
62 before running the tests
66 When using a real Swift server, you need to set these environment variables before running the tests
6367
6468 export SWIFT_API_USER='user'
6569 export SWIFT_API_KEY='key'
98102 License
99103 -------
100104
101 This is free software under the terms of MIT license (check COPYING file
102 included in this package).
105 This is free software under the terms of MIT license (check COPYING file included in this package).
103106
104107 Contact and support
105108 -------------------
160163 - Brandon WELSCH <dev@brandon-welsch.eu>
161164 - Damien Tournoud <damien@platform.sh>
162165 - Pedro Kiefer <pedro@kiefer.com.br>
166 - Martin Chodur <m.chodur@seznam.cz>
167 - Devendra <devendranath.thadi3@gmail.com>
168 - timss <timsateroy@gmail.com>
169 - Jos Houtman <jos@houtman.it>
170 - Paul Collins <paul.collins@canonical.com>
11
22 import (
33 "bytes"
4 "context"
45 "encoding/json"
56 "net/http"
67 "net/url"
1314 // This encapsulates the different authentication schemes in use
1415 type Authenticator interface {
1516 // Request creates an http.Request for the auth - return nil if not needed
16 Request(*Connection) (*http.Request, error)
17 Request(context.Context, *Connection) (*http.Request, error)
1718 // Response parses the http.Response
18 Response(resp *http.Response) error
19 Response(ctx context.Context, resp *http.Response) error
1920 // The public storage URL - set Internal to true to read
2021 // internal/service net URL
2122 StorageUrl(Internal bool) string
8788 }
8889
8990 // v1 Authentication - make request
90 func (auth *v1Auth) Request(c *Connection) (*http.Request, error) {
91 req, err := http.NewRequest("GET", c.AuthUrl, nil)
91 func (auth *v1Auth) Request(ctx context.Context, c *Connection) (*http.Request, error) {
92 req, err := http.NewRequestWithContext(ctx, "GET", c.AuthUrl, nil)
9293 if err != nil {
9394 return nil, err
9495 }
99100 }
100101
101102 // v1 Authentication - read response
102 func (auth *v1Auth) Response(resp *http.Response) error {
103 func (auth *v1Auth) Response(_ context.Context, resp *http.Response) error {
103104 auth.Headers = resp.Header
104105 return nil
105106 }
140141 }
141142
142143 // v2 Authentication - make request
143 func (auth *v2Auth) Request(c *Connection) (*http.Request, error) {
144 func (auth *v2Auth) Request(ctx context.Context, c *Connection) (*http.Request, error) {
144145 auth.Region = c.Region
145146 // Toggle useApiKey if not first run and not OK yet
146147 if auth.notFirst && !auth.useApiKeyOk {
175176 url += "/"
176177 }
177178 url += "tokens"
178 req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
179 req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(body))
179180 if err != nil {
180181 return nil, err
181182 }
185186 }
186187
187188 // v2 Authentication - read response
188 func (auth *v2Auth) Response(resp *http.Response) error {
189 func (auth *v2Auth) Response(_ context.Context, resp *http.Response) error {
189190 auth.Auth = new(v2AuthResponse)
190191 err := readJson(resp, auth.Auth)
191192 // If successfully read Auth then no need to toggle useApiKey any more
11
22 import (
33 "bytes"
4 "context"
45 "encoding/json"
56 "fmt"
67 "net/http"
1213 v3AuthMethodToken = "token"
1314 v3AuthMethodPassword = "password"
1415 v3AuthMethodApplicationCredential = "application_credential"
15 v3CatalogTypeObjectStore = "object-store"
1616 )
1717
1818 // V3 Authentication request
121121 Headers http.Header
122122 }
123123
124 func (auth *v3Auth) Request(c *Connection) (*http.Request, error) {
124 func (auth *v3Auth) Request(ctx context.Context, c *Connection) (*http.Request, error) {
125125 auth.Region = c.Region
126126
127127 var v3i interface{}
241241 url += "/"
242242 }
243243 url += "auth/tokens"
244 req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
244 req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(body))
245245 if err != nil {
246246 return nil, err
247247 }
250250 return req, nil
251251 }
252252
253 func (auth *v3Auth) Response(resp *http.Response) error {
253 func (auth *v3Auth) Response(_ context.Context, resp *http.Response) error {
254254 auth.Auth = &v3AuthResponse{}
255255 auth.Headers = resp.Header
256256 err := readJson(resp, auth.Auth)
0 #!/usr/bin/env python
0 #!/usr/bin/env python3
11 """
22 Update the README.md file with the authors from the git log
33 """
2222 """
2323 adds the email passed in to the end of authors
2424 """
25 print "Adding %s <%s>" % (name, email)
25 print("Adding %s <%s>" % (name, email))
2626 with open(AUTHORS, "a+") as fd:
27 print >>fd, "- %s <%s>" % (name, email)
27 print("- %s <%s>" % (name, email), file=fd)
2828 subprocess.check_call(["git", "commit", "-m", "Add %s to contributors" % name, AUTHORS])
2929
3030 def main():
3131 out = subprocess.check_output(["git", "log", '--reverse', '--format=%an|%ae', "master"])
3232
3333 previous = load()
34 for line in out.split("\n"):
34 for line in out.split(b"\n"):
35 line = line.decode("utf-8")
3536 line = line.strip()
3637 if line == "":
3738 continue
00 // Go 1.0 compatibility functions
11
2 //go:build !go1.1
23 // +build !go1.1
34
45 package swift
00 // Go 1.1 and later compatibility functions
11 //
2 //go:build go1.1
23 // +build go1.1
34
45 package swift
0 //go:build go1.6
01 // +build go1.6
12
23 package swift
0 //go:build !go1.6
01 // +build !go1.6
12
23 package swift
00 package swift
11
22 import (
3 "context"
34 "os"
45 "strings"
56 )
1314 // returning an object which satisfies io.Writer, io.Seeker, io.Closer
1415 // and io.ReaderFrom. The flags are as passes to the
1516 // largeObjectCreate method.
16 func (c *Connection) DynamicLargeObjectCreateFile(opts *LargeObjectOpts) (LargeObjectFile, error) {
17 lo, err := c.largeObjectCreate(opts)
17 func (c *Connection) DynamicLargeObjectCreateFile(ctx context.Context, opts *LargeObjectOpts) (LargeObjectFile, error) {
18 lo, err := c.largeObjectCreate(ctx, opts)
1819 if err != nil {
1920 return nil, err
2021 }
2728 // DynamicLargeObjectCreate creates or truncates an existing dynamic
2829 // large object returning a writeable object. This sets opts.Flags to
2930 // an appropriate value before calling DynamicLargeObjectCreateFile
30 func (c *Connection) DynamicLargeObjectCreate(opts *LargeObjectOpts) (LargeObjectFile, error) {
31 func (c *Connection) DynamicLargeObjectCreate(ctx context.Context, opts *LargeObjectOpts) (LargeObjectFile, error) {
3132 opts.Flags = os.O_TRUNC | os.O_CREATE
32 return c.DynamicLargeObjectCreateFile(opts)
33 return c.DynamicLargeObjectCreateFile(ctx, opts)
3334 }
3435
3536 // DynamicLargeObjectDelete deletes a dynamic large object and all of its segments.
36 func (c *Connection) DynamicLargeObjectDelete(container string, path string) error {
37 return c.LargeObjectDelete(container, path)
37 func (c *Connection) DynamicLargeObjectDelete(ctx context.Context, container string, path string) error {
38 return c.LargeObjectDelete(ctx, container, path)
3839 }
3940
4041 // DynamicLargeObjectMove moves a dynamic large object from srcContainer, srcObjectName to dstContainer, dstObjectName
41 func (c *Connection) DynamicLargeObjectMove(srcContainer string, srcObjectName string, dstContainer string, dstObjectName string) error {
42 info, headers, err := c.Object(srcContainer, srcObjectName)
42 func (c *Connection) DynamicLargeObjectMove(ctx context.Context, srcContainer string, srcObjectName string, dstContainer string, dstObjectName string) error {
43 info, headers, err := c.Object(ctx, srcContainer, srcObjectName)
4344 if err != nil {
4445 return err
4546 }
4647
47 segmentContainer, segmentPath := parseFullPath(headers["X-Object-Manifest"])
48 if err := c.createDLOManifest(dstContainer, dstObjectName, segmentContainer+"/"+segmentPath, info.ContentType, sanitizeLargeObjectMoveHeaders(headers)); err != nil {
48 segmentContainer, segmentPath, err := parseFullPath(headers["X-Object-Manifest"])
49 if err != nil {
4950 return err
5051 }
5152
52 if err := c.ObjectDelete(srcContainer, srcObjectName); err != nil {
53 if err := c.createDLOManifest(ctx, dstContainer, dstObjectName, segmentContainer+"/"+segmentPath, info.ContentType, sanitizeLargeObjectMoveHeaders(headers)); err != nil {
54 return err
55 }
56
57 if err := c.ObjectDelete(ctx, srcContainer, srcObjectName); err != nil {
5358 return err
5459 }
5560
6772 }
6873
6974 // createDLOManifest creates a dynamic large object manifest
70 func (c *Connection) createDLOManifest(container string, objectName string, prefix string, contentType string, headers Headers) error {
75 func (c *Connection) createDLOManifest(ctx context.Context, container string, objectName string, prefix string, contentType string, headers Headers) error {
7176 if headers == nil {
7277 headers = make(Headers)
7378 }
7479 headers["X-Object-Manifest"] = prefix
75 manifest, err := c.ObjectCreate(container, objectName, false, "", contentType, headers)
80 manifest, err := c.ObjectCreate(ctx, container, objectName, false, "", contentType, headers)
7681 if err != nil {
7782 return err
7883 }
8691
8792 // Close satisfies the io.Closer interface
8893 func (file *DynamicLargeObjectCreateFile) Close() error {
89 return file.Flush()
94 return file.CloseWithContext(context.Background())
9095 }
9196
92 func (file *DynamicLargeObjectCreateFile) Flush() error {
93 err := file.conn.createDLOManifest(file.container, file.objectName, file.segmentContainer+"/"+file.prefix, file.contentType, file.headers)
97 func (file *DynamicLargeObjectCreateFile) CloseWithContext(ctx context.Context) error {
98 return file.Flush(ctx)
99 }
100
101 func (file *DynamicLargeObjectCreateFile) Flush(ctx context.Context) error {
102 err := file.conn.createDLOManifest(ctx, file.container, file.objectName, file.segmentContainer+"/"+file.prefix, file.contentType, file.headers)
94103 if err != nil {
95104 return err
96105 }
97 return file.conn.waitForSegmentsToShowUp(file.container, file.objectName, file.Size())
106 return file.conn.waitForSegmentsToShowUp(ctx, file.container, file.objectName, file.Size())
98107 }
99108
100 func (c *Connection) getAllDLOSegments(segmentContainer, segmentPath string) ([]Object, error) {
109 func (c *Connection) getAllDLOSegments(ctx context.Context, segmentContainer, segmentPath string) ([]Object, error) {
101110 //a simple container listing works 99.9% of the time
102 segments, err := c.ObjectsAll(segmentContainer, &ObjectsOpts{Prefix: segmentPath})
111 segments, err := c.ObjectsAll(ctx, segmentContainer, &ObjectsOpts{Prefix: segmentPath})
103112 if err != nil {
104113 return nil, err
105114 }
125134 //guaranteed to return the correct metadata, except for the pathological
126135 //case of an outage of large parts of the Swift cluster or its network,
127136 //since every segment is only written once.)
128 segment, _, err := c.Object(segmentContainer, segmentName)
137 segment, _, err := c.Object(ctx, segmentContainer, segmentName)
129138 switch err {
130139 case nil:
131140 //found new segment -> add it in the correct position and keep
11
22 import (
33 "bytes"
4 "github.com/ncw/swift/swifttest"
4 "context"
55 "net/http"
66 "testing"
77 "time"
8
9 "github.com/ncw/swift/v2/swifttest"
810 )
911
1012 var srv *swifttest.SwiftServer
4648 Domain: "Default",
4749 AuthVersion: 1,
4850 }
49 err = swiftCon.Authenticate()
51 err = swiftCon.Authenticate(context.Background())
5052 return &swiftCon, err
5153 }
5254 func TestCases(t *testing.T) {
6264 }
6365
6466 func createContainers(containers []string, t *testing.T) {
67 ctx := context.Background()
6568 for i := 0; i < len(containers); i++ {
66 err = con.ContainerCreate(containers[i], nil) // Create container
69 err = con.ContainerCreate(ctx, containers[i], nil) // Create container
6770 if err != nil {
6871 t.Errorf("Fail at create container %s", containers[i])
6972 }
7174 }
7275
7376 func createDynamicObject(container, object string, t *testing.T) {
77 ctx := context.Background()
7478 metadata := map[string]string{}
7579 metadata["Custom-Field"] = "SomeValue"
7680 ops := LargeObjectOpts{
8286 SegmentContainer: segmentContainer, // Name of the container to place segments
8387 SegmentPrefix: "sg", // Prefix to use for the segments
8488 }
85 bigfile, err := con.DynamicLargeObjectCreate(&ops)
89 bigfile, err := con.DynamicLargeObjectCreate(ctx, &ops)
8690 if err != nil {
8791 t.Errorf("Fail at dynamic create Large Object")
8892 }
89 bigfile.Write(filecontent)
90 bigfile.Close()
93 _, err = bigfile.WriteWithContext(ctx, filecontent)
94 if err != nil {
95 t.Errorf("WriteWithContext failed: %v", err)
96 }
97 err = bigfile.CloseWithContext(ctx)
98 if err != nil {
99 t.Errorf("CloseWithContext failed: %v", err)
100 }
91101 checkObject(container, object, t)
92102 }
93103 func checkObject(container, object string, t *testing.T) {
94 info, header, err := con.Object(container, object)
104 ctx := context.Background()
105 info, header, err := con.Object(ctx, container, object)
95106 if err != nil {
96107 t.Errorf("Fail at get Large Object metadata: %s", err.Error())
97108 }
105116 t.Errorf("Fail: lost custom metadata header")
106117 }
107118
108 content, err := con.ObjectGetBytes(container, object)
119 content, err := con.ObjectGetBytes(ctx, container, object)
109120 if err != nil {
110121 t.Errorf("Fail at read Large Object : %s", err.Error())
111122 }
115126
116127 }
117128 func checkNotExistObject(container, object string, t *testing.T) {
118 _, _, err = con.Object(container, object)
129 _, _, err = con.Object(context.Background(), container, object)
119130 if err == nil || err.Error() != "Object Not Found" {
120131 t.Errorf("Fail at checkNotExistObject object: %s", err)
121132 }
122133 }
123134 func moveDynamicObject(sc, so, dc, do string, t *testing.T) {
124 err = con.DynamicLargeObjectMove(sc, so, dc, do)
135 err = con.DynamicLargeObjectMove(context.Background(), sc, so, dc, do)
125136 if err != nil {
126137 t.Errorf("Fail at dynamic move Large Object: %s", err.Error())
127138 }
129140 checkObject(dc, do, t)
130141 }
131142 func deleteDynamicObject(container, object string, t *testing.T) {
132 err = con.DynamicLargeObjectDelete(container, object)
143 ctx := context.Background()
144 err = con.DynamicLargeObjectDelete(ctx, container, object)
133145 if err != nil {
134146 t.Errorf("Fail at delte dynamic Large Object: %s", err.Error())
135147 }
136148 checkNotExistObject(container, object, t)
137 objs, err := con.ObjectsAll(segmentContainer, nil)
149 objs, err := con.ObjectsAll(ctx, segmentContainer, nil)
138150 if err != nil {
139151 t.Errorf("Fail at check delte dynamic Large Object: %s", err.Error())
140152 }
143155 }
144156 }
145157 func createStaticObject(container, object string, t *testing.T) {
158 ctx := context.Background()
146159 metadata := map[string]string{}
147160 metadata["Custom-Field"] = "SomeValue"
148161 ops := LargeObjectOpts{
154167 SegmentContainer: segmentContainer, // Name of the container to place segments
155168 SegmentPrefix: "sg", // Prefix to use for the segments
156169 }
157 bigfile, err := con.StaticLargeObjectCreate(&ops)
170 bigfile, err := con.StaticLargeObjectCreate(ctx, &ops)
158171 if err != nil {
159172 t.Errorf("Fail at static create Large Object")
160173 }
161 bigfile.Write(filecontent)
162 bigfile.Close()
174 _, err = bigfile.WriteWithContext(ctx, filecontent)
175 if err != nil {
176 t.Errorf("WriteWithContext failed: %v", err)
177 }
178 err = bigfile.CloseWithContext(ctx)
179 if err != nil {
180 t.Errorf("CloseWithContext failed: %v", err)
181 }
163182 checkObject(container, object, t)
164183 }
165184 func moveStaticObject(sc, so, dc, do string, t *testing.T) {
166 err = con.StaticLargeObjectMove(sc, so, dc, do)
185 err = con.StaticLargeObjectMove(context.Background(), sc, so, dc, do)
167186 if err != nil {
168187 t.Errorf("Fail at static move Large Object: %s", err.Error())
169188 }
171190 checkObject(dc, do, t)
172191 }
173192 func deleteStaticObject(container, object string, t *testing.T) {
174 err = con.StaticLargeObjectDelete(container, object)
193 ctx := context.Background()
194 err = con.StaticLargeObjectDelete(ctx, container, object)
175195 if err != nil {
176196 t.Errorf("Fail at delte dynamic Large Object: %s", err.Error())
177197 }
178198 checkNotExistObject(container, object, t)
179 objs, err := con.ObjectsAll(segmentContainer, nil)
199 objs, err := con.ObjectsAll(ctx, segmentContainer, nil)
180200 if err != nil {
181201 t.Errorf("Fail at check delte dynamic Large Object: %s", err.Error())
182202 }
33 package swift_test
44
55 import (
6 "context"
67 "fmt"
78
8 "github.com/ncw/swift"
9 "github.com/ncw/swift/v2"
910 )
1011
1112 func ExampleConnection() {
13 ctx := context.Background()
1214 // Create a v1 auth connection
1315 c := &swift.Connection{
1416 // This should be your username
2325 }
2426
2527 // Authenticate
26 err := c.Authenticate()
28 err := c.Authenticate(ctx)
2729 if err != nil {
2830 panic(err)
2931 }
3032 // List all the containers
31 containers, err := c.ContainerNames(nil)
33 containers, err := c.ContainerNames(ctx, nil)
34 if err != nil {
35 panic(err)
36 }
3237 fmt.Println(containers)
3338 // etc...
3439
6065 defer rollback()
6166
6267 objects := make([]string, 0)
63 err := c.ObjectsWalk(container, nil, func(opts *swift.ObjectsOpts) (interface{}, error) {
64 newObjects, err := c.ObjectNames(container, opts)
68 err := c.ObjectsWalk(context.Background(), container, nil, func(ctx context.Context, opts *swift.ObjectsOpts) (interface{}, error) {
69 newObjects, err := c.ObjectNames(ctx, container, opts)
6570 if err == nil {
6671 objects = append(objects, newObjects...)
6772 }
7580 defer rollback()
7681
7782 // Use the helper method to create the current and versions container.
78 if err := c.VersionContainerCreate("cds", "cd-versions"); err != nil {
83 if err := c.VersionContainerCreate(context.Background(), "cds", "cd-versions"); err != nil {
7984 fmt.Print(err.Error())
8085 }
8186 }
8287
8388 func ExampleConnection_VersionEnable() {
89 ctx := context.Background()
8490 c, rollback := makeConnection(nil)
8591 defer rollback()
8692
8793 // Build the containers manually and enable them.
88 if err := c.ContainerCreate("movie-versions", nil); err != nil {
94 if err := c.ContainerCreate(ctx, "movie-versions", nil); err != nil {
8995 fmt.Print(err.Error())
9096 }
91 if err := c.ContainerCreate("movies", nil); err != nil {
97 if err := c.ContainerCreate(ctx, "movies", nil); err != nil {
9298 fmt.Print(err.Error())
9399 }
94 if err := c.VersionEnable("movies", "movie-versions"); err != nil {
100 if err := c.VersionEnable(ctx, "movies", "movie-versions"); err != nil {
95101 fmt.Print(err.Error())
96102 }
97103
104110 defer rollback()
105111
106112 // Disable versioning on a container. Note that this does not delete the versioning container.
107 c.VersionDisable("movies")
113 err := c.VersionDisable(context.Background(), "movies")
114 if err != nil {
115 panic(err)
116 }
108117 }
0 module github.com/ncw/swift
0 module github.com/ncw/swift/v2
1
2 go 1.15
(New empty file)
0 #!/bin/bash
1 # Run the swift tests against an openstack server from a swift all in
2 # one docker image
3
4 set -e
5
6 NAME=swift-aio
7 HOST=127.0.0.1
8 PORT=8294
9 AUTH=v1
10
11 case $AUTH in
12 v1)
13 export SWIFT_AUTH_URL="http://${HOST}:${PORT}/auth/v1.0"
14 export SWIFT_API_USER='test:tester'
15 export SWIFT_API_KEY='testing'
16 ;;
17 v2)
18 # NB v2 auth doesn't work for unknown reasons!
19 export SWIFT_AUTH_URL="http://${HOST}:${PORT}/auth/v2.0"
20 export SWIFT_TENANT='tester'
21 export SWIFT_API_USER='test'
22 export SWIFT_API_KEY='testing'
23 ;;
24 *)
25 echo "Bad AUTH %AUTH"
26 exit 1
27 ;;
28 esac
29
30
31 echo "Starting test server"
32 docker run --rm -d --name ${NAME} -p ${HOST}:${PORT}:8080 bouncestorage/swift-aio
33
34 function cleanup {
35 echo "Killing test server"
36 docker kill ${NAME}
37 }
38
39 trap cleanup EXIT
40
41 echo -n "Waiting for test server to startup"
42 tries=30
43 while [[ $tries -gt 0 ]]; do
44 echo -n "."
45 STATUS_RECEIVED=$(curl -s -o /dev/null -L -w ''%{http_code}'' ${SWIFT_AUTH_URL} || true)
46 if [[ ${STATUS_RECEIVED} -ge 200 ]]; then
47 break
48 fi
49 let tries-=1
50 sleep 1
51 done
52 echo "OK"
53
54 echo "Running tests"
55 go test -v
56
22 import (
33 "bufio"
44 "bytes"
5 "context"
56 "crypto/rand"
67 "crypto/sha1"
78 "encoding/hex"
89 "errors"
910 "fmt"
1011 "io"
12 "net/url"
1113 "os"
1214 gopath "path"
1315 "strconv"
5557 return fmt.Sprintf("%s/%016d", segmentPath, partNumber)
5658 }
5759
58 func parseFullPath(manifest string) (container string, prefix string) {
60 func parseFullPath(manifest string) (container string, prefix string, err error) {
61 manifest, err = url.PathUnescape(manifest)
62 if err != nil {
63 return
64 }
5965 components := strings.SplitN(manifest, "/", 2)
6066 container = components[0]
6167 if len(components) > 1 {
6268 prefix = components[1]
6369 }
64 return container, prefix
70 return container, prefix, nil
6571 }
6672
6773 func (headers Headers) IsLargeObjectDLO() bool {
7884 return headers.IsLargeObjectSLO() || headers.IsLargeObjectDLO()
7985 }
8086
81 func (c *Connection) getAllSegments(container string, path string, headers Headers) (string, []Object, error) {
87 func (c *Connection) getAllSegments(ctx context.Context, container string, path string, headers Headers) (string, []Object, error) {
8288 if manifest, isDLO := headers["X-Object-Manifest"]; isDLO {
83 segmentContainer, segmentPath := parseFullPath(manifest)
84 segments, err := c.getAllDLOSegments(segmentContainer, segmentPath)
89 segmentContainer, segmentPath, err := parseFullPath(manifest)
90 if err != nil {
91 return segmentContainer, nil, err
92 }
93 segments, err := c.getAllDLOSegments(ctx, segmentContainer, segmentPath)
8594 return segmentContainer, segments, err
8695 }
8796 if headers.IsLargeObjectSLO() {
88 return c.getAllSLOSegments(container, path)
97 return c.getAllSLOSegments(ctx, container, path)
8998 }
9099 return "", nil, NotLargeObject
91100 }
107116 }
108117
109118 type LargeObjectFile interface {
119 io.Seeker
110120 io.Writer
111 io.Seeker
112121 io.Closer
122
123 WriteWithContext(ctx context.Context, p []byte) (n int, err error)
124 CloseWithContext(ctx context.Context) error
113125 Size() int64
114 Flush() error
126 Flush(ctx context.Context) error
115127 }
116128
117129 // largeObjectCreate creates a large object at opts.Container, opts.ObjectName.
119131 // opts.Flags can have the following bits set
120132 // os.TRUNC - remove the contents of the large object if it exists
121133 // os.APPEND - write at the end of the large object
122 func (c *Connection) largeObjectCreate(opts *LargeObjectOpts) (*largeObjectCreateFile, error) {
134 func (c *Connection) largeObjectCreate(ctx context.Context, opts *LargeObjectOpts) (*largeObjectCreateFile, error) {
123135 var (
124136 segmentPath string
125137 segmentContainer string
134146 return nil, err
135147 }
136148
137 if info, headers, err := c.Object(opts.Container, opts.ObjectName); err == nil {
149 if info, headers, err := c.Object(ctx, opts.Container, opts.ObjectName); err == nil {
138150 if opts.Flags&os.O_TRUNC != 0 {
139 c.LargeObjectDelete(opts.Container, opts.ObjectName)
151 err := c.LargeObjectDelete(ctx, opts.Container, opts.ObjectName)
152 if err != nil {
153 return nil, err
154 }
140155 } else {
141156 currentLength = info.Bytes
142157 if headers.IsLargeObject() {
143 segmentContainer, segments, err = c.getAllSegments(opts.Container, opts.ObjectName, headers)
158 segmentContainer, segments, err = c.getAllSegments(ctx, opts.Container, opts.ObjectName, headers)
144159 if err != nil {
145160 return nil, err
146161 }
148163 segmentPath = gopath.Dir(segments[0].Name)
149164 }
150165 } else {
151 if err = c.ObjectMove(opts.Container, opts.ObjectName, opts.Container, getSegment(segmentPath, 1)); err != nil {
166 if err = c.ObjectMove(ctx, opts.Container, opts.ObjectName, opts.Container, getSegment(segmentPath, 1)); err != nil {
152167 return nil, err
153168 }
154169 segments = append(segments, info)
197212 }
198213
199214 // LargeObjectDelete deletes the large object named by container, path
200 func (c *Connection) LargeObjectDelete(container string, objectName string) error {
201 _, headers, err := c.Object(container, objectName)
215 func (c *Connection) LargeObjectDelete(ctx context.Context, container string, objectName string) error {
216 _, headers, err := c.Object(ctx, container, objectName)
202217 if err != nil {
203218 return err
204219 }
205220
206221 var objects [][]string
207222 if headers.IsLargeObject() {
208 segmentContainer, segments, err := c.getAllSegments(container, objectName, headers)
223 segmentContainer, segments, err := c.getAllSegments(ctx, container, objectName, headers)
209224 if err != nil {
210225 return err
211226 }
215230 }
216231 objects = append(objects, []string{container, objectName})
217232
218 info, err := c.cachedQueryInfo()
233 info, err := c.cachedQueryInfo(ctx)
219234 if err == nil && info.SupportsBulkDelete() && len(objects) > 0 {
220235 filenames := make([]string, len(objects))
221236 for i, obj := range objects {
222237 filenames[i] = obj[0] + "/" + obj[1]
223238 }
224 _, err = c.doBulkDelete(filenames, nil)
239 _, err = c.doBulkDelete(ctx, filenames, nil)
225240 // Don't fail on ObjectNotFound because eventual consistency
226241 // makes this situation normal.
227242 if err != nil && err != Forbidden && err != ObjectNotFound {
229244 }
230245 } else {
231246 for _, obj := range objects {
232 if err := c.ObjectDelete(obj[0], obj[1]); err != nil {
247 if err := c.ObjectDelete(ctx, obj[0], obj[1]); err != nil {
233248 return err
234249 }
235250 }
243258 // that have the prefix as indicated by the manifest.
244259 // If the object is a Static Large Object (SLO), it retrieves the JSON content
245260 // of the manifest and return all the segments of it.
246 func (c *Connection) LargeObjectGetSegments(container string, path string) (string, []Object, error) {
247 _, headers, err := c.Object(container, path)
261 func (c *Connection) LargeObjectGetSegments(ctx context.Context, container string, path string) (string, []Object, error) {
262 _, headers, err := c.Object(ctx, container, path)
248263 if err != nil {
249264 return "", nil, err
250265 }
251266
252 return c.getAllSegments(container, path, headers)
267 return c.getAllSegments(ctx, container, path, headers)
253268 }
254269
255270 // Seek sets the offset for the next write operation
300315 }
301316 }
302317
303 func (c *Connection) waitForSegmentsToShowUp(container, objectName string, expectedSize int64) (err error) {
318 func (c *Connection) waitForSegmentsToShowUp(ctx context.Context, container, objectName string, expectedSize int64) (err error) {
304319 err = withLORetry(expectedSize, func() (Headers, int64, error) {
305320 var info Object
306321 var headers Headers
307 info, headers, err = c.objectBase(container, objectName)
322 info, headers, err = c.objectBase(ctx, container, objectName)
308323 if err != nil {
309324 return headers, 0, err
310325 }
313328 return
314329 }
315330
316 // Write satisfies the io.Writer interface
317331 func (file *largeObjectCreateFile) Write(buf []byte) (int, error) {
332 return file.WriteWithContext(context.Background(), buf)
333 }
334
335 func (file *largeObjectCreateFile) WriteWithContext(ctx context.Context, buf []byte) (int, error) {
318336 var sz int64
319337 var relativeFilePos int
320338 writeSegmentIdx := 0
328346 }
329347 sizeToWrite := len(buf)
330348 for offset := 0; offset < sizeToWrite; {
331 newSegment, n, err := file.writeSegment(buf[offset:], writeSegmentIdx, relativeFilePos)
349 newSegment, n, err := file.writeSegment(ctx, buf[offset:], writeSegmentIdx, relativeFilePos)
332350 if err != nil {
333351 return 0, err
334352 }
349367 return sizeToWrite, nil
350368 }
351369
352 func (file *largeObjectCreateFile) writeSegment(buf []byte, writeSegmentIdx int, relativeFilePos int) (*Object, int, error) {
370 func (file *largeObjectCreateFile) writeSegment(ctx context.Context, buf []byte, writeSegmentIdx int, relativeFilePos int) (obj *Object, n int, err error) {
353371 var (
354372 readers []io.Reader
355373 existingSegment *Object
365383 if relativeFilePos > 0 {
366384 headers := make(Headers)
367385 headers["Range"] = "bytes=0-" + strconv.FormatInt(int64(relativeFilePos-1), 10)
368 existingSegmentReader, _, err := file.conn.ObjectOpen(file.segmentContainer, segmentName, true, headers)
386 existingSegmentReader, _, err := file.conn.ObjectOpen(ctx, file.segmentContainer, segmentName, true, headers)
369387 if err != nil {
370388 return nil, 0, err
371389 }
372 defer existingSegmentReader.Close()
390 defer func() {
391 closeErr := existingSegmentReader.Close()
392 if closeErr != nil {
393 err = closeErr
394 }
395 }()
373396 sizeToRead -= relativeFilePos
374397 segmentSize += relativeFilePos
375398 readers = []io.Reader{existingSegmentReader}
383406 if existingSegment != nil && segmentSize < int(existingSegment.Bytes) {
384407 headers := make(Headers)
385408 headers["Range"] = "bytes=" + strconv.FormatInt(int64(segmentSize), 10) + "-"
386 tailSegmentReader, _, err := file.conn.ObjectOpen(file.segmentContainer, segmentName, true, headers)
409 tailSegmentReader, _, err := file.conn.ObjectOpen(ctx, file.segmentContainer, segmentName, true, headers)
387410 if err != nil {
388411 return nil, 0, err
389412 }
390 defer tailSegmentReader.Close()
413 defer func() {
414 closeErr := tailSegmentReader.Close()
415 if closeErr != nil {
416 err = closeErr
417 }
418 }()
391419 segmentSize = int(existingSegment.Bytes)
392420 readers = append(readers, tailSegmentReader)
393421 }
394422 segmentReader := io.MultiReader(readers...)
395 headers, err := file.conn.ObjectPut(file.segmentContainer, segmentName, segmentReader, true, "", file.contentType, nil)
423 headers, err := file.conn.ObjectPut(ctx, file.segmentContainer, segmentName, segmentReader, true, "", file.contentType, nil)
396424 if err != nil {
397425 return nil, 0, err
398426 }
415443 }
416444
417445 func (blo *bufferedLargeObjectFile) Close() error {
446 return blo.CloseWithContext(context.Background())
447 }
448
449 func (blo *bufferedLargeObjectFile) CloseWithContext(ctx context.Context) error {
418450 err := blo.bw.Flush()
419451 if err != nil {
420452 return err
421453 }
422 return blo.LargeObjectFile.Close()
454 return blo.LargeObjectFile.CloseWithContext(ctx)
455 }
456
457 func (blo *bufferedLargeObjectFile) WriteWithContext(_ context.Context, p []byte) (n int, err error) {
458 return blo.Write(p)
423459 }
424460
425461 func (blo *bufferedLargeObjectFile) Write(p []byte) (n int, err error) {
438474 return blo.LargeObjectFile.Size() + int64(blo.bw.Buffered())
439475 }
440476
441 func (blo *bufferedLargeObjectFile) Flush() error {
477 func (blo *bufferedLargeObjectFile) Flush(ctx context.Context) error {
442478 err := blo.bw.Flush()
443479 if err != nil {
444480 return err
445481 }
446 return blo.LargeObjectFile.Flush()
447 }
482 return blo.LargeObjectFile.Flush(ctx)
483 }
00 package rs
11
22 import (
3 "context"
34 "errors"
45 "net/http"
56 "strconv"
67
7 "github.com/ncw/swift"
8 "github.com/ncw/swift/v2"
89 )
910
1011 // RsConnection is a RackSpace specific wrapper to the core swift library which
1516 }
1617
1718 // manage is similar to the swift storage method, but uses the CDN Management URL for CDN specific calls.
18 func (c *RsConnection) manage(p swift.RequestOpts) (resp *http.Response, headers swift.Headers, err error) {
19 func (c *RsConnection) manage(ctx context.Context, p swift.RequestOpts) (resp *http.Response, headers swift.Headers, err error) {
1920 p.OnReAuth = func() (string, error) {
2021 if c.cdnUrl == "" {
2122 c.cdnUrl = c.Auth.CdnUrl()
3132 return nil, nil, err
3233 }
3334 }
34 return c.Connection.Call(c.cdnUrl, p)
35 return c.Connection.Call(ctx, c.cdnUrl, p)
3536 }
3637
3738 // ContainerCDNEnable enables a container for public CDN usage.
3940 // Change the default TTL of 259200 seconds (72 hours) by passing in an integer value.
4041 //
4142 // This method can be called again to change the TTL.
42 func (c *RsConnection) ContainerCDNEnable(container string, ttl int) (swift.Headers, error) {
43 func (c *RsConnection) ContainerCDNEnable(ctx context.Context, container string, ttl int) (swift.Headers, error) {
4344 h := swift.Headers{"X-CDN-Enabled": "true"}
4445 if ttl > 0 {
4546 h["X-TTL"] = strconv.Itoa(ttl)
4647 }
4748
48 _, headers, err := c.manage(swift.RequestOpts{
49 _, headers, err := c.manage(ctx, swift.RequestOpts{
4950 Container: container,
5051 Operation: "PUT",
5152 ErrorMap: swift.ContainerErrorMap,
5657 }
5758
5859 // ContainerCDNDisable disables CDN access to a container.
59 func (c *RsConnection) ContainerCDNDisable(container string) error {
60 func (c *RsConnection) ContainerCDNDisable(ctx context.Context, container string) error {
6061 h := swift.Headers{"X-CDN-Enabled": "false"}
6162
62 _, _, err := c.manage(swift.RequestOpts{
63 _, _, err := c.manage(ctx, swift.RequestOpts{
6364 Container: container,
6465 Operation: "PUT",
6566 ErrorMap: swift.ContainerErrorMap,
7071 }
7172
7273 // ContainerCDNMeta returns the CDN metadata for a container.
73 func (c *RsConnection) ContainerCDNMeta(container string) (swift.Headers, error) {
74 _, headers, err := c.manage(swift.RequestOpts{
74 func (c *RsConnection) ContainerCDNMeta(ctx context.Context, container string) (swift.Headers, error) {
75 _, headers, err := c.manage(ctx, swift.RequestOpts{
7576 Container: container,
7677 Operation: "HEAD",
7778 ErrorMap: swift.ContainerErrorMap,
11 package rs_test
22
33 import (
4 "context"
45 "os"
56 "testing"
67
7 "github.com/ncw/swift/rs"
8 "github.com/ncw/swift/v2/rs"
89 )
910
1011 var (
3132 c.UserName = UserName
3233 c.ApiKey = ApiKey
3334 c.AuthUrl = AuthUrl
34 err := c.Authenticate()
35 err := c.Authenticate(context.Background())
3536 if err != nil {
3637 t.Fatal("Auth failed", err)
3738 }
4243
4344 // Setup
4445 func TestContainerCreate(t *testing.T) {
45 err := c.ContainerCreate(CONTAINER, nil)
46 err := c.ContainerCreate(context.Background(), CONTAINER, nil)
4647 if err != nil {
4748 t.Fatal(err)
4849 }
4950 }
5051
5152 func TestCDNEnable(t *testing.T) {
52 headers, err := c.ContainerCDNEnable(CONTAINER, 0)
53 headers, err := c.ContainerCDNEnable(context.Background(), CONTAINER, 0)
5354 if err != nil {
5455 t.Error(err)
5556 }
6364 c2.UserName = c.UserName
6465 c2.ApiKey = c.ApiKey
6566 c2.AuthUrl = c.AuthUrl
66 _, err := c2.ContainerCDNEnable(CONTAINER, 0)
67 _, err := c2.ContainerCDNEnable(context.Background(), CONTAINER, 0)
6768 if err != nil {
6869 t.Fatalf("Failed to reauthenticate: %v", err)
6970 }
7071 }
7172
7273 func TestCDNMeta(t *testing.T) {
73 headers, err := c.ContainerCDNMeta(CONTAINER)
74 headers, err := c.ContainerCDNMeta(context.Background(), CONTAINER)
7475 if err != nil {
7576 t.Error(err)
7677 }
8081 }
8182
8283 func TestCDNDisable(t *testing.T) {
83 err := c.ContainerCDNDisable(CONTAINER) // files stick in CDN until TTL expires
84 err := c.ContainerCDNDisable(context.Background(), CONTAINER) // files stick in CDN until TTL expires
8485 if err != nil {
8586 t.Error(err)
8687 }
8889
8990 // Teardown
9091 func TestContainerDelete(t *testing.T) {
91 err := c.ContainerDelete(CONTAINER)
92 err := c.ContainerDelete(context.Background(), CONTAINER)
9293 if err != nil {
9394 t.Fatal(err)
9495 }
11
22 import (
33 "bytes"
4 "context"
45 "encoding/json"
56 "errors"
67 "fmt"
3637 // an object which satisfies io.Writer, io.Seeker, io.Closer and
3738 // io.ReaderFrom. The flags are as passed to the largeObjectCreate
3839 // method.
39 func (c *Connection) StaticLargeObjectCreateFile(opts *LargeObjectOpts) (LargeObjectFile, error) {
40 info, err := c.cachedQueryInfo()
40 func (c *Connection) StaticLargeObjectCreateFile(ctx context.Context, opts *LargeObjectOpts) (LargeObjectFile, error) {
41 info, err := c.cachedQueryInfo(ctx)
4142 if err != nil || !info.SupportsSLO() {
4243 return nil, SLONotSupported
4344 }
4546 if realMinChunkSize > opts.MinChunkSize {
4647 opts.MinChunkSize = realMinChunkSize
4748 }
48 lo, err := c.largeObjectCreate(opts)
49 lo, err := c.largeObjectCreate(ctx, opts)
4950 if err != nil {
5051 return nil, err
5152 }
5758 // StaticLargeObjectCreate creates or truncates an existing static
5859 // large object returning a writeable object. This sets opts.Flags to
5960 // an appropriate value before calling StaticLargeObjectCreateFile
60 func (c *Connection) StaticLargeObjectCreate(opts *LargeObjectOpts) (LargeObjectFile, error) {
61 func (c *Connection) StaticLargeObjectCreate(ctx context.Context, opts *LargeObjectOpts) (LargeObjectFile, error) {
6162 opts.Flags = os.O_TRUNC | os.O_CREATE
62 return c.StaticLargeObjectCreateFile(opts)
63 return c.StaticLargeObjectCreateFile(ctx, opts)
6364 }
6465
6566 // StaticLargeObjectDelete deletes a static large object and all of its segments.
66 func (c *Connection) StaticLargeObjectDelete(container string, path string) error {
67 info, err := c.cachedQueryInfo()
67 func (c *Connection) StaticLargeObjectDelete(ctx context.Context, container string, path string) error {
68 info, err := c.cachedQueryInfo(ctx)
6869 if err != nil || !info.SupportsSLO() {
6970 return SLONotSupported
7071 }
71 return c.LargeObjectDelete(container, path)
72 return c.LargeObjectDelete(ctx, container, path)
7273 }
7374
7475 // StaticLargeObjectMove moves a static large object from srcContainer, srcObjectName to dstContainer, dstObjectName
75 func (c *Connection) StaticLargeObjectMove(srcContainer string, srcObjectName string, dstContainer string, dstObjectName string) error {
76 swiftInfo, err := c.cachedQueryInfo()
76 func (c *Connection) StaticLargeObjectMove(ctx context.Context, srcContainer string, srcObjectName string, dstContainer string, dstObjectName string) error {
77 swiftInfo, err := c.cachedQueryInfo(ctx)
7778 if err != nil || !swiftInfo.SupportsSLO() {
7879 return SLONotSupported
7980 }
80 info, headers, err := c.Object(srcContainer, srcObjectName)
81 info, headers, err := c.Object(ctx, srcContainer, srcObjectName)
8182 if err != nil {
8283 return err
8384 }
8485
85 container, segments, err := c.getAllSegments(srcContainer, srcObjectName, headers)
86 container, segments, err := c.getAllSegments(ctx, srcContainer, srcObjectName, headers)
8687 if err != nil {
8788 return err
8889 }
9091 //copy only metadata during move (other headers might not be safe for copying)
9192 headers = headers.ObjectMetadata().ObjectHeaders()
9293
93 if err := c.createSLOManifest(dstContainer, dstObjectName, info.ContentType, container, segments, headers); err != nil {
94 if err := c.createSLOManifest(ctx, dstContainer, dstObjectName, info.ContentType, container, segments, headers); err != nil {
9495 return err
9596 }
9697
97 if err := c.ObjectDelete(srcContainer, srcObjectName); err != nil {
98 if err := c.ObjectDelete(ctx, srcContainer, srcObjectName); err != nil {
9899 return err
99100 }
100101
102103 }
103104
104105 // createSLOManifest creates a static large object manifest
105 func (c *Connection) createSLOManifest(container string, path string, contentType string, segmentContainer string, segments []Object, h Headers) error {
106 func (c *Connection) createSLOManifest(ctx context.Context, container string, path string, contentType string, segmentContainer string, segments []Object, h Headers) error {
106107 sloSegments := make([]swiftSegment, len(segments))
107108 for i, segment := range segments {
108109 sloSegments[i].Path = fmt.Sprintf("%s/%s", segmentContainer, segment.Name)
117118
118119 values := url.Values{}
119120 values.Set("multipart-manifest", "put")
120 if _, err := c.objectPut(container, path, bytes.NewBuffer(content), false, "", contentType, h, values); err != nil {
121 if _, err := c.objectPut(ctx, container, path, bytes.NewBuffer(content), false, "", contentType, h, values); err != nil {
121122 return err
122123 }
123124
125126 }
126127
127128 func (file *StaticLargeObjectCreateFile) Close() error {
128 return file.Flush()
129 return file.CloseWithContext(context.Background())
129130 }
130131
131 func (file *StaticLargeObjectCreateFile) Flush() error {
132 if err := file.conn.createSLOManifest(file.container, file.objectName, file.contentType, file.segmentContainer, file.segments, file.headers); err != nil {
132 func (file *StaticLargeObjectCreateFile) CloseWithContext(ctx context.Context) error {
133 return file.Flush(ctx)
134 }
135
136 func (file *StaticLargeObjectCreateFile) Flush(ctx context.Context) error {
137 if err := file.conn.createSLOManifest(ctx, file.container, file.objectName, file.contentType, file.segmentContainer, file.segments, file.headers); err != nil {
133138 return err
134139 }
135 return file.conn.waitForSegmentsToShowUp(file.container, file.objectName, file.Size())
140 return file.conn.waitForSegmentsToShowUp(ctx, file.container, file.objectName, file.Size())
136141 }
137142
138 func (c *Connection) getAllSLOSegments(container, path string) (string, []Object, error) {
143 func (c *Connection) getAllSLOSegments(ctx context.Context, container, path string) (string, []Object, error) {
139144 var (
140145 segmentList []swiftSegment
141146 segments []Object
146151 values := url.Values{}
147152 values.Set("multipart-manifest", "get")
148153
149 file, _, err := c.objectOpen(container, path, true, nil, values)
154 file, _, err := c.objectOpen(ctx, container, path, true, nil, values)
150155 if err != nil {
151156 return "", nil, err
152157 }
156161 return "", nil, err
157162 }
158163
159 json.Unmarshal(content, &segmentList)
164 err = json.Unmarshal(content, &segmentList)
165 if err != nil {
166 return "", nil, err
167 }
160168 for _, segment := range segmentList {
161 segmentContainer, segPath = parseFullPath(segment.Name[1:])
169 segmentContainer, segPath, err = parseFullPath(segment.Name[1:])
170 if err != nil {
171 return "", nil, err
172 }
162173 segments = append(segments, Object{
163174 Name: segPath,
164175 Bytes: segment.Bytes,
+191
-140
swift.go less more
22 import (
33 "bufio"
44 "bytes"
5 "context"
56 "crypto/hmac"
67 "crypto/md5"
78 "crypto/sha1"
3031 UploadTarGzip = "tar.gz" // Data format specifier for Connection.BulkUpload().
3132 UploadTarBzip2 = "tar.bz2" // Data format specifier for Connection.BulkUpload().
3233 allContainersLimit = 10000 // Number of containers to fetch at once
33 allObjectsLimit = 10000 // Number objects to fetch at once
34 allObjectsChanLimit = 1000 // ...when fetching to a channel
34 allObjectsChanLimit = 1000 // Number objects to fetch when fetching to a channel
3535 )
3636
3737 // ObjectType is the type of the swift object, regular, static large,
7171 // import (
7272 // "appengine/urlfetch"
7373 // "fmt"
74 // "github.com/ncw/swift"
74 // "github.com/ncw/swift/v2"
7575 // )
7676 //
7777 // func handler(w http.ResponseWriter, r *http.Request) {
124124 Expires time.Time // time the token expires, may be Zero if unknown
125125 client *http.Client
126126 Auth Authenticator `json:"-" xml:"-"` // the current authenticator
127 authLock *sync.Mutex // lock when R/W StorageUrl, AuthToken, Auth
127 authLock sync.Mutex // lock when R/W StorageUrl, AuthToken, Auth
128128 // swiftInfo is filled after QueryInfo is called
129129 swiftInfo SwiftInfo
130 // Workarounds for non-compliant servers that don't always return opts.Limit items per page
131 FetchUntilEmptyPage bool // Always fetch unless we received an empty page
132 PartialPageFetchThreshold int // Fetch if the current page is this percentage of opts.Limit
130133 }
131134
132135 // setFromEnv reads the value that param points to (it must be a
385388 func readHeaders(resp *http.Response) Headers {
386389 headers := Headers{}
387390 for key, values := range resp.Header {
388 headers[key] = values[0]
391 // ETag header may be double quoted if following RFC 7232
392 // https://github.com/openstack/swift/blob/2.24.0/CHANGELOG#L9
393 if key == "Etag" {
394 headers[key] = strings.Trim(values[0], "\"")
395 } else {
396 headers[key] = values[0]
397 }
389398 }
390399 return headers
391400 }
414423 cancelRequest(c.Transport, req)
415424 return nil, TimeoutError
416425 }
417 panic("unreachable") // For Go 1.0
418426 }
419427
420428 // Set defaults for any unset values
456464 //
457465 // If you don't call it before calling one of the connection methods
458466 // then it will be called for you on the first access.
459 func (c *Connection) Authenticate() (err error) {
460 if c.authLock == nil {
461 c.authLock = &sync.Mutex{}
462 }
467 func (c *Connection) Authenticate(ctx context.Context) (err error) {
463468 c.authLock.Lock()
464469 defer c.authLock.Unlock()
465 return c.authenticate()
470 return c.authenticate(ctx)
466471 }
467472
468473 // Internal implementation of Authenticate
469474 //
470475 // Call with authLock held
471 func (c *Connection) authenticate() (err error) {
476 func (c *Connection) authenticate(ctx context.Context) (err error) {
472477 c.setDefaults()
473478
474479 // Flush the keepalives connection - if we are
485490 retries := 1
486491 again:
487492 var req *http.Request
488 req, err = c.Auth.Request(c)
493 req, err = c.Auth.Request(ctx, c)
489494 if err != nil {
490495 return
491496 }
513518 }
514519 return
515520 }
516 err = c.Auth.Response(resp)
521 err = c.Auth.Response(ctx, resp)
517522 if err != nil {
518523 return
519524 }
540545 // Get an authToken and url
541546 //
542547 // The Url may be updated if it needed to authenticate using the OnReAuth function
543 func (c *Connection) getUrlAndAuthToken(targetUrlIn string, OnReAuth func() (string, error)) (targetUrlOut, authToken string, err error) {
548 func (c *Connection) getUrlAndAuthToken(ctx context.Context, targetUrlIn string, OnReAuth func() (string, error)) (targetUrlOut, authToken string, err error) {
544549 c.authLock.Lock()
545550 defer c.authLock.Unlock()
546551 targetUrlOut = targetUrlIn
547552 if !c.authenticated() {
548 err = c.authenticate()
553 err = c.authenticate(ctx)
549554 if err != nil {
550555 return
551556 }
582587 //
583588 // Doesn't actually check the credentials against the server.
584589 func (c *Connection) Authenticated() bool {
585 if c.authLock == nil {
586 c.authLock = &sync.Mutex{}
587 }
588590 c.authLock.Lock()
589591 defer c.authLock.Unlock()
590592 return c.authenticated()
628630 }
629631
630632 // Discover Swift configuration by doing a request against /info
631 func (c *Connection) QueryInfo() (infos SwiftInfo, err error) {
632 infoUrl, err := url.Parse(c.StorageUrl)
633 func (c *Connection) QueryInfo(ctx context.Context) (infos SwiftInfo, err error) {
634 storageUrl, err := c.GetStorageUrl(ctx)
633635 if err != nil {
634636 return nil, err
635637 }
638 infoUrl, err := url.Parse(storageUrl)
639 if err != nil {
640 return nil, err
641 }
636642 infoUrl.Path = path.Join(infoUrl.Path, "..", "..", "info")
637 resp, err := c.client.Get(infoUrl.String())
643 req, err := http.NewRequestWithContext(ctx, http.MethodGet, infoUrl.String(), nil)
644 if err != nil {
645 return nil, err
646 }
647 resp, err := c.client.Do(req)
638648 if err == nil {
639649 if resp.StatusCode != http.StatusOK {
640650 drainAndClose(resp.Body, nil)
651661 return nil, err
652662 }
653663
654 func (c *Connection) cachedQueryInfo() (infos SwiftInfo, err error) {
664 func (c *Connection) cachedQueryInfo(ctx context.Context) (infos SwiftInfo, err error) {
655665 c.authLock.Lock()
656666 infos = c.swiftInfo
657667 c.authLock.Unlock()
658668 if infos == nil {
659 infos, err = c.QueryInfo()
669 infos, err = c.QueryInfo(ctx)
660670 if err != nil {
661671 return
662672 }
699709 // receives a 401 error which means the token has expired
700710 //
701711 // This method is exported so extensions can call it.
702 func (c *Connection) Call(targetUrl string, p RequestOpts) (resp *http.Response, headers Headers, err error) {
712 func (c *Connection) Call(ctx context.Context, targetUrl string, p RequestOpts) (resp *http.Response, headers Headers, err error) {
703713 c.authLock.Lock()
704714 c.setDefaults()
705715 c.authLock.Unlock()
710720 var req *http.Request
711721 for {
712722 var authToken string
713 if targetUrl, authToken, err = c.getUrlAndAuthToken(targetUrl, p.OnReAuth); err != nil {
723 if targetUrl, authToken, err = c.getUrlAndAuthToken(ctx, targetUrl, p.OnReAuth); err != nil {
714724 return //authentication failure
715725 }
716726 var URL *url.URL
733743 if reader != nil {
734744 reader = newWatchdogReader(reader, c.Timeout, timer)
735745 }
736 req, err = http.NewRequest(p.Operation, URL.String(), reader)
746 req, err = http.NewRequestWithContext(ctx, p.Operation, URL.String(), reader)
737747 if err != nil {
738748 return
739749 }
808818 //
809819 // This will Authenticate if necessary, and re-authenticate if it
810820 // receives a 401 error which means the token has expired
811 func (c *Connection) storage(p RequestOpts) (resp *http.Response, headers Headers, err error) {
821 func (c *Connection) storage(ctx context.Context, p RequestOpts) (resp *http.Response, headers Headers, err error) {
812822 p.OnReAuth = func() (string, error) {
813823 return c.StorageUrl, nil
814824 }
815825 c.authLock.Lock()
816826 url := c.StorageUrl
817827 c.authLock.Unlock()
818 return c.Call(url, p)
828 return c.Call(ctx, url, p)
819829 }
820830
821831 // readLines reads the response into an array of strings.
886896 }
887897
888898 // ContainerNames returns a slice of names of containers in this account.
889 func (c *Connection) ContainerNames(opts *ContainersOpts) ([]string, error) {
899 func (c *Connection) ContainerNames(ctx context.Context, opts *ContainersOpts) ([]string, error) {
890900 v, h := opts.parse()
891 resp, _, err := c.storage(RequestOpts{
901 resp, _, err := c.storage(ctx, RequestOpts{
892902 Operation: "GET",
893903 Parameters: v,
894904 ErrorMap: ContainerErrorMap,
910920
911921 // Containers returns a slice of structures with full information as
912922 // described in Container.
913 func (c *Connection) Containers(opts *ContainersOpts) ([]Container, error) {
923 func (c *Connection) Containers(ctx context.Context, opts *ContainersOpts) ([]Container, error) {
914924 v, h := opts.parse()
915925 v.Set("format", "json")
916 resp, _, err := c.storage(RequestOpts{
926 resp, _, err := c.storage(ctx, RequestOpts{
917927 Operation: "GET",
918928 Parameters: v,
919929 ErrorMap: ContainerErrorMap,
941951 return &newOpts
942952 }
943953
954 func (c *Connection) isLastPage(length int, limit int) bool {
955 if c.FetchUntilEmptyPage && length > 0 {
956 return false
957 }
958 if c.PartialPageFetchThreshold > 0 && limit > 0 {
959 if length*100/limit >= c.PartialPageFetchThreshold {
960 return false
961 }
962 }
963 if length < limit {
964 return true
965 }
966 return false
967 }
968
944969 // ContainersAll is like Containers but it returns all the Containers
945970 //
946971 // It calls Containers multiple times using the Marker parameter
947972 //
948973 // It has a default Limit parameter but you may pass in your own
949 func (c *Connection) ContainersAll(opts *ContainersOpts) ([]Container, error) {
974 func (c *Connection) ContainersAll(ctx context.Context, opts *ContainersOpts) ([]Container, error) {
950975 opts = containersAllOpts(opts)
951976 containers := make([]Container, 0)
952977 for {
953 newContainers, err := c.Containers(opts)
978 newContainers, err := c.Containers(ctx, opts)
954979 if err != nil {
955980 return nil, err
956981 }
957982 containers = append(containers, newContainers...)
958 if len(newContainers) < opts.Limit {
983 if c.isLastPage(len(newContainers), opts.Limit) {
959984 break
960985 }
961986 opts.Marker = newContainers[len(newContainers)-1].Name
968993 // It calls ContainerNames multiple times using the Marker parameter
969994 //
970995 // It has a default Limit parameter but you may pass in your own
971 func (c *Connection) ContainerNamesAll(opts *ContainersOpts) ([]string, error) {
996 func (c *Connection) ContainerNamesAll(ctx context.Context, opts *ContainersOpts) ([]string, error) {
972997 opts = containersAllOpts(opts)
973998 containers := make([]string, 0)
974999 for {
975 newContainers, err := c.ContainerNames(opts)
1000 newContainers, err := c.ContainerNames(ctx, opts)
9761001 if err != nil {
9771002 return nil, err
9781003 }
9791004 containers = append(containers, newContainers...)
980 if len(newContainers) < opts.Limit {
1005 if c.isLastPage(len(newContainers), opts.Limit) {
9811006 break
9821007 }
9831008 opts.Marker = newContainers[len(newContainers)-1]
10281053 }
10291054
10301055 // ObjectNames returns a slice of names of objects in a given container.
1031 func (c *Connection) ObjectNames(container string, opts *ObjectsOpts) ([]string, error) {
1056 func (c *Connection) ObjectNames(ctx context.Context, container string, opts *ObjectsOpts) ([]string, error) {
10321057 v, h := opts.parse()
1033 resp, _, err := c.storage(RequestOpts{
1058 resp, _, err := c.storage(ctx, RequestOpts{
10341059 Container: container,
10351060 Operation: "GET",
10361061 Parameters: v,
10641089 // with ContentType 'application/directory'. These are not real
10651090 // objects but represent directories of objects which haven't had an
10661091 // object created for them.
1067 func (c *Connection) Objects(container string, opts *ObjectsOpts) ([]Object, error) {
1092 func (c *Connection) Objects(ctx context.Context, container string, opts *ObjectsOpts) ([]Object, error) {
10681093 v, h := opts.parse()
10691094 v.Set("format", "json")
1070 resp, _, err := c.storage(RequestOpts{
1095 resp, _, err := c.storage(ctx, RequestOpts{
10711096 Container: container,
10721097 Operation: "GET",
10731098 Parameters: v,
11291154
11301155 // A closure defined by the caller to iterate through all objects
11311156 //
1132 // Call Objects or ObjectNames from here with the *ObjectOpts passed in
1157 // Call Objects or ObjectNames from here with the context.Context and *ObjectOpts passed in
11331158 //
11341159 // Do whatever is required with the results then return them
1135 type ObjectsWalkFn func(*ObjectsOpts) (interface{}, error)
1160 type ObjectsWalkFn func(context.Context, *ObjectsOpts) (interface{}, error)
11361161
11371162 // ObjectsWalk is uses to iterate through all the objects in chunks as
11381163 // returned by Objects or ObjectNames using the Marker and Limit
11441169 // Errors will be returned from this function
11451170 //
11461171 // It has a default Limit parameter but you may pass in your own
1147 func (c *Connection) ObjectsWalk(container string, opts *ObjectsOpts, walkFn ObjectsWalkFn) error {
1172 func (c *Connection) ObjectsWalk(ctx context.Context, container string, opts *ObjectsOpts, walkFn ObjectsWalkFn) error {
11481173 opts = objectsAllOpts(opts, allObjectsChanLimit)
11491174 for {
1150 objects, err := walkFn(opts)
1175 objects, err := walkFn(ctx, opts)
11511176 if err != nil {
11521177 return err
11531178 }
11671192 default:
11681193 panic("Unknown type returned to ObjectsWalk")
11691194 }
1170 if n < opts.Limit {
1195 if c.isLastPage(n, opts.Limit) {
11711196 break
11721197 }
11731198 opts.Marker = last
11781203 // ObjectsAll is like Objects but it returns an unlimited number of Objects in a slice
11791204 //
11801205 // It calls Objects multiple times using the Marker parameter
1181 func (c *Connection) ObjectsAll(container string, opts *ObjectsOpts) ([]Object, error) {
1206 func (c *Connection) ObjectsAll(ctx context.Context, container string, opts *ObjectsOpts) ([]Object, error) {
11821207 objects := make([]Object, 0)
1183 err := c.ObjectsWalk(container, opts, func(opts *ObjectsOpts) (interface{}, error) {
1184 newObjects, err := c.Objects(container, opts)
1208 err := c.ObjectsWalk(ctx, container, opts, func(ctx context.Context, opts *ObjectsOpts) (interface{}, error) {
1209 newObjects, err := c.Objects(ctx, container, opts)
11851210 if err == nil {
11861211 objects = append(objects, newObjects...)
11871212 }
11961221 // reset unless KeepMarker is set
11971222 //
11981223 // It has a default Limit parameter but you may pass in your own
1199 func (c *Connection) ObjectNamesAll(container string, opts *ObjectsOpts) ([]string, error) {
1224 func (c *Connection) ObjectNamesAll(ctx context.Context, container string, opts *ObjectsOpts) ([]string, error) {
12001225 objects := make([]string, 0)
1201 err := c.ObjectsWalk(container, opts, func(opts *ObjectsOpts) (interface{}, error) {
1202 newObjects, err := c.ObjectNames(container, opts)
1226 err := c.ObjectsWalk(ctx, container, opts, func(ctx context.Context, opts *ObjectsOpts) (interface{}, error) {
1227 newObjects, err := c.ObjectNames(ctx, container, opts)
12031228 if err == nil {
12041229 objects = append(objects, newObjects...)
12051230 }
12261251 }
12271252
12281253 // Account returns info about the account in an Account struct.
1229 func (c *Connection) Account() (info Account, headers Headers, err error) {
1254 func (c *Connection) Account(ctx context.Context) (info Account, headers Headers, err error) {
12301255 var resp *http.Response
1231 resp, headers, err = c.storage(RequestOpts{
1256 resp, headers, err = c.storage(ctx, RequestOpts{
12321257 Operation: "HEAD",
12331258 ErrorMap: ContainerErrorMap,
12341259 NoResponse: true,
12611286 // Add or update keys by mentioning them in the Headers.
12621287 //
12631288 // Remove keys by setting them to an empty string.
1264 func (c *Connection) AccountUpdate(h Headers) error {
1265 _, _, err := c.storage(RequestOpts{
1289 func (c *Connection) AccountUpdate(ctx context.Context, h Headers) error {
1290 _, _, err := c.storage(ctx, RequestOpts{
12661291 Operation: "POST",
12671292 ErrorMap: ContainerErrorMap,
12681293 NoResponse: true,
12761301 // If you don't want to add Headers just pass in nil
12771302 //
12781303 // No error is returned if it already exists but the metadata if any will be updated.
1279 func (c *Connection) ContainerCreate(container string, h Headers) error {
1280 _, _, err := c.storage(RequestOpts{
1304 func (c *Connection) ContainerCreate(ctx context.Context, container string, h Headers) error {
1305 _, _, err := c.storage(ctx, RequestOpts{
12811306 Container: container,
12821307 Operation: "PUT",
12831308 ErrorMap: ContainerErrorMap,
12901315 // ContainerDelete deletes a container.
12911316 //
12921317 // May return ContainerDoesNotExist or ContainerNotEmpty
1293 func (c *Connection) ContainerDelete(container string) error {
1294 _, _, err := c.storage(RequestOpts{
1318 func (c *Connection) ContainerDelete(ctx context.Context, container string) error {
1319 _, _, err := c.storage(ctx, RequestOpts{
12951320 Container: container,
12961321 Operation: "DELETE",
12971322 ErrorMap: ContainerErrorMap,
13021327
13031328 // Container returns info about a single container including any
13041329 // metadata in the headers.
1305 func (c *Connection) Container(container string) (info Container, headers Headers, err error) {
1330 func (c *Connection) Container(ctx context.Context, container string) (info Container, headers Headers, err error) {
13061331 var resp *http.Response
1307 resp, headers, err = c.storage(RequestOpts{
1332 resp, headers, err = c.storage(ctx, RequestOpts{
13081333 Container: container,
13091334 Operation: "HEAD",
13101335 ErrorMap: ContainerErrorMap,
13311356 // Remove keys by setting them to an empty string.
13321357 //
13331358 // Container metadata can only be read with Container() not with Containers().
1334 func (c *Connection) ContainerUpdate(container string, h Headers) error {
1335 _, _, err := c.storage(RequestOpts{
1359 func (c *Connection) ContainerUpdate(ctx context.Context, container string, h Headers) error {
1360 _, _, err := c.storage(ctx, RequestOpts{
13361361 Container: container,
13371362 Operation: "POST",
13381363 ErrorMap: ContainerErrorMap,
14681493 //
14691494 // If contentType is set it will be used, otherwise one will be
14701495 // guessed from objectName using mime.TypeByExtension
1471 func (c *Connection) ObjectCreate(container string, objectName string, checkHash bool, Hash string, contentType string, h Headers) (file *ObjectCreateFile, err error) {
1496 func (c *Connection) ObjectCreate(ctx context.Context, container string, objectName string, checkHash bool, Hash string, contentType string, h Headers) (file *ObjectCreateFile, err error) {
14721497 extraHeaders := objectPutHeaders(objectName, &checkHash, Hash, contentType, h)
14731498 pipeReader, pipeWriter := io.Pipe()
14741499 file = &ObjectCreateFile{
14891514 NoResponse: true,
14901515 ErrorMap: objectErrorMap,
14911516 }
1492 file.resp, file.headers, file.err = c.storage(opts)
1517 file.resp, file.headers, file.err = c.storage(ctx, opts)
14931518 // Signal finished
1494 pipeReader.Close()
1519 _ = pipeReader.Close()
14951520 close(file.done)
14961521 }()
14971522 return
14981523 }
14991524
1500 func (c *Connection) ObjectSymlinkCreate(container string, symlink string, targetAccount string, targetContainer string, targetObject string, targetEtag string) (headers Headers, err error) {
1525 func (c *Connection) ObjectSymlinkCreate(ctx context.Context, container string, symlink string, targetAccount string, targetContainer string, targetObject string, targetEtag string) (headers Headers, err error) {
15011526
15021527 EMPTY_MD5 := "d41d8cd98f00b204e9800998ecf8427e"
15031528 symHeaders := Headers{}
15091534 symHeaders["X-Symlink-Target-Etag"] = targetEtag
15101535 }
15111536 symHeaders["X-Symlink-Target"] = fmt.Sprintf("%s/%s", targetContainer, targetObject)
1512 _, err = c.ObjectPut(container, symlink, contents, true, EMPTY_MD5, "application/symlink", symHeaders)
1513 return
1514 }
1515
1516 func (c *Connection) objectPut(container string, objectName string, contents io.Reader, checkHash bool, Hash string, contentType string, h Headers, parameters url.Values) (headers Headers, err error) {
1537 _, err = c.ObjectPut(ctx, container, symlink, contents, true, EMPTY_MD5, "application/symlink", symHeaders)
1538 return
1539 }
1540
1541 func (c *Connection) objectPut(ctx context.Context, container string, objectName string, contents io.Reader, checkHash bool, Hash string, contentType string, h Headers, parameters url.Values) (headers Headers, err error) {
15171542 extraHeaders := objectPutHeaders(objectName, &checkHash, Hash, contentType, h)
15181543 hash := md5.New()
15191544 var body io.Reader = contents
15201545 if checkHash {
15211546 body = io.TeeReader(contents, hash)
15221547 }
1523 _, headers, err = c.storage(RequestOpts{
1548 _, headers, err = c.storage(ctx, RequestOpts{
15241549 Container: container,
15251550 ObjectName: objectName,
15261551 Operation: "PUT",
15651590 //
15661591 // If contentType is set it will be used, otherwise one will be
15671592 // guessed from objectName using mime.TypeByExtension
1568 func (c *Connection) ObjectPut(container string, objectName string, contents io.Reader, checkHash bool, Hash string, contentType string, h Headers) (headers Headers, err error) {
1569 return c.objectPut(container, objectName, contents, checkHash, Hash, contentType, h, nil)
1593 func (c *Connection) ObjectPut(ctx context.Context, container string, objectName string, contents io.Reader, checkHash bool, Hash string, contentType string, h Headers) (headers Headers, err error) {
1594 return c.objectPut(ctx, container, objectName, contents, checkHash, Hash, contentType, h, nil)
15701595 }
15711596
15721597 // ObjectPutBytes creates an object from a []byte in a container.
15731598 //
15741599 // This is a simplified interface which checks the MD5.
1575 func (c *Connection) ObjectPutBytes(container string, objectName string, contents []byte, contentType string) (err error) {
1600 func (c *Connection) ObjectPutBytes(ctx context.Context, container string, objectName string, contents []byte, contentType string) (err error) {
15761601 buf := bytes.NewBuffer(contents)
15771602 h := Headers{"Content-Length": strconv.Itoa(len(contents))}
1578 _, err = c.ObjectPut(container, objectName, buf, true, "", contentType, h)
1603 hash := md5.Sum(contents)
1604 hashStr := hex.EncodeToString(hash[:])
1605 _, err = c.ObjectPut(ctx, container, objectName, buf, true, hashStr, contentType, h)
15791606 return
15801607 }
15811608
15821609 // ObjectPutString creates an object from a string in a container.
15831610 //
15841611 // This is a simplified interface which checks the MD5
1585 func (c *Connection) ObjectPutString(container string, objectName string, contents string, contentType string) (err error) {
1612 func (c *Connection) ObjectPutString(ctx context.Context, container string, objectName string, contents string, contentType string) (err error) {
15861613 buf := strings.NewReader(contents)
15871614 h := Headers{"Content-Length": strconv.Itoa(len(contents))}
1588 _, err = c.ObjectPut(container, objectName, buf, true, "", contentType, h)
1615 hash := md5.Sum([]byte(contents))
1616 hashStr := hex.EncodeToString(hash[:])
1617 _, err = c.ObjectPut(ctx, container, objectName, buf, true, hashStr, contentType, h)
15891618 return
15901619 }
15911620
16351664 // unlike os.File
16361665 //
16371666 // Seek(0, 1) will return the current file pointer.
1638 func (file *ObjectOpenFile) Seek(offset int64, whence int) (newPos int64, err error) {
1667 func (file *ObjectOpenFile) Seek(ctx context.Context, offset int64, whence int) (newPos int64, err error) {
16391668 file.overSeeked = false
16401669 switch whence {
16411670 case 0: // relative to start
16731702 } else {
16741703 delete(file.headers, "Range")
16751704 }
1676 newFile, _, err := file.connection.ObjectOpen(file.container, file.objectName, false, file.headers)
1705 newFile, _, err := file.connection.ObjectOpen(ctx, file.container, file.objectName, false, file.headers)
16771706 if err != nil {
16781707 return
16791708 }
16871716
16881717 // Length gets the objects content length either from a cached copy or
16891718 // from the server.
1690 func (file *ObjectOpenFile) Length() (int64, error) {
1719 func (file *ObjectOpenFile) Length(ctx context.Context) (int64, error) {
16911720 if !file.lengthOk {
1692 info, _, err := file.connection.Object(file.container, file.objectName)
1721 info, _, err := file.connection.Object(ctx, file.container, file.objectName)
16931722 file.length = info.Bytes
16941723 file.lengthOk = (err == nil)
16951724 return file.length, err
17101739
17111740 // Check the MD5 sum if requested
17121741 if file.checkHash {
1713 receivedMd5 := strings.ToLower(file.resp.Header.Get("Etag"))
1742 // ETag header may be double quoted if following RFC 7232
1743 // https://github.com/openstack/swift/blob/2.24.0/CHANGELOG#L9
1744 receivedMd5 := strings.ToLower(strings.Trim(file.resp.Header.Get("Etag"), "\""))
17141745 calculatedMd5 := fmt.Sprintf("%x", file.hash.Sum(nil))
17151746 if receivedMd5 != calculatedMd5 {
17161747 err = ObjectCorrupted
17261757 return
17271758 }
17281759
1729 // Check it satisfies the interfaces
1730 var _ io.ReadCloser = &ObjectOpenFile{}
1731 var _ io.Seeker = &ObjectOpenFile{}
1732
1733 func (c *Connection) objectOpenBase(container string, objectName string, checkHash bool, h Headers, parameters url.Values) (file *ObjectOpenFile, headers Headers, err error) {
1760 func (c *Connection) objectOpenBase(ctx context.Context, container string, objectName string, checkHash bool, h Headers, parameters url.Values) (file *ObjectOpenFile, headers Headers, err error) {
17341761 var resp *http.Response
17351762 opts := RequestOpts{
17361763 Container: container,
17401767 Headers: h,
17411768 Parameters: parameters,
17421769 }
1743 resp, headers, err = c.storage(opts)
1770 resp, headers, err = c.storage(ctx, opts)
17441771 if err != nil {
17451772 return
17461773 }
17701797 return
17711798 }
17721799
1773 func (c *Connection) objectOpen(container string, objectName string, checkHash bool, h Headers, parameters url.Values) (file *ObjectOpenFile, headers Headers, err error) {
1800 func (c *Connection) objectOpen(ctx context.Context, container string, objectName string, checkHash bool, h Headers, parameters url.Values) (file *ObjectOpenFile, headers Headers, err error) {
17741801 err = withLORetry(0, func() (Headers, int64, error) {
1775 file, headers, err = c.objectOpenBase(container, objectName, checkHash, h, parameters)
1802 file, headers, err = c.objectOpenBase(ctx, container, objectName, checkHash, h, parameters)
17761803 if err != nil {
17771804 return headers, 0, err
17781805 }
18041831 // you will need to download everything in the manifest separately.
18051832 //
18061833 // headers["Content-Type"] will give the content type if desired.
1807 func (c *Connection) ObjectOpen(container string, objectName string, checkHash bool, h Headers) (file *ObjectOpenFile, headers Headers, err error) {
1808 return c.objectOpen(container, objectName, checkHash, h, nil)
1834 func (c *Connection) ObjectOpen(ctx context.Context, container string, objectName string, checkHash bool, h Headers) (file *ObjectOpenFile, headers Headers, err error) {
1835 return c.objectOpen(ctx, container, objectName, checkHash, h, nil)
18091836 }
18101837
18111838 // ObjectGet gets the object into the io.Writer contents.
18171844 // server. If it is wrong then it will return ObjectCorrupted.
18181845 //
18191846 // headers["Content-Type"] will give the content type if desired.
1820 func (c *Connection) ObjectGet(container string, objectName string, contents io.Writer, checkHash bool, h Headers) (headers Headers, err error) {
1821 file, headers, err := c.ObjectOpen(container, objectName, checkHash, h)
1847 func (c *Connection) ObjectGet(ctx context.Context, container string, objectName string, contents io.Writer, checkHash bool, h Headers) (headers Headers, err error) {
1848 file, headers, err := c.ObjectOpen(ctx, container, objectName, checkHash, h)
18221849 if err != nil {
18231850 return
18241851 }
18301857 // ObjectGetBytes returns an object as a []byte.
18311858 //
18321859 // This is a simplified interface which checks the MD5
1833 func (c *Connection) ObjectGetBytes(container string, objectName string) (contents []byte, err error) {
1860 func (c *Connection) ObjectGetBytes(ctx context.Context, container string, objectName string) (contents []byte, err error) {
18341861 var buf bytes.Buffer
1835 _, err = c.ObjectGet(container, objectName, &buf, true, nil)
1862 _, err = c.ObjectGet(ctx, container, objectName, &buf, true, nil)
18361863 contents = buf.Bytes()
18371864 return
18381865 }
18401867 // ObjectGetString returns an object as a string.
18411868 //
18421869 // This is a simplified interface which checks the MD5
1843 func (c *Connection) ObjectGetString(container string, objectName string) (contents string, err error) {
1870 func (c *Connection) ObjectGetString(ctx context.Context, container string, objectName string) (contents string, err error) {
18441871 var buf bytes.Buffer
1845 _, err = c.ObjectGet(container, objectName, &buf, true, nil)
1872 _, err = c.ObjectGet(ctx, container, objectName, &buf, true, nil)
18461873 contents = buf.String()
18471874 return
18481875 }
18501877 // ObjectDelete deletes the object.
18511878 //
18521879 // May return ObjectNotFound if the object isn't found
1853 func (c *Connection) ObjectDelete(container string, objectName string) error {
1854 _, _, err := c.storage(RequestOpts{
1880 func (c *Connection) ObjectDelete(ctx context.Context, container string, objectName string) error {
1881 _, _, err := c.storage(ctx, RequestOpts{
18551882 Container: container,
18561883 ObjectName: objectName,
18571884 Operation: "DELETE",
18621889
18631890 // ObjectTempUrl returns a temporary URL for an object
18641891 func (c *Connection) ObjectTempUrl(container string, objectName string, secretKey string, method string, expires time.Time) string {
1892 c.authLock.Lock()
1893 storageUrl := c.StorageUrl
1894 c.authLock.Unlock()
1895 if storageUrl == "" {
1896 return "" // Cannot do better without changing the interface
1897 }
1898
18651899 mac := hmac.New(sha1.New, []byte(secretKey))
1866 prefix, _ := url.Parse(c.StorageUrl)
1900 prefix, _ := url.Parse(storageUrl)
18671901 body := fmt.Sprintf("%s\n%d\n%s/%s/%s", method, expires.Unix(), prefix.Path, container, objectName)
18681902 mac.Write([]byte(body))
18691903 sig := hex.EncodeToString(mac.Sum(nil))
19081942 Headers Headers // Response HTTP headers.
19091943 }
19101944
1911 func (c *Connection) doBulkDelete(objects []string, h Headers) (result BulkDeleteResult, err error) {
1945 func (c *Connection) doBulkDelete(ctx context.Context, objects []string, h Headers) (result BulkDeleteResult, err error) {
19121946 var buffer bytes.Buffer
19131947 for _, s := range objects {
19141948 u := url.URL{Path: s}
19221956 for key, value := range h {
19231957 extraHeaders[key] = value
19241958 }
1925 resp, headers, err := c.storage(RequestOpts{
1959 resp, headers, err := c.storage(ctx, RequestOpts{
19261960 Operation: "DELETE",
19271961 Parameters: url.Values{"bulk-delete": []string{"1"}},
19281962 Headers: extraHeaders,
19662000 // See also:
19672001 // * http://docs.openstack.org/trunk/openstack-object-storage/admin/content/object-storage-bulk-delete.html
19682002 // * http://docs.rackspace.com/files/api/v1/cf-devguide/content/Bulk_Delete-d1e2338.html
1969 func (c *Connection) BulkDelete(container string, objectNames []string) (result BulkDeleteResult, err error) {
1970 return c.BulkDeleteHeaders(container, objectNames, nil)
2003 func (c *Connection) BulkDelete(ctx context.Context, container string, objectNames []string) (result BulkDeleteResult, err error) {
2004 return c.BulkDeleteHeaders(ctx, container, objectNames, nil)
19712005 }
19722006
19732007 // BulkDeleteHeaders deletes multiple objectNames from container in one operation.
19782012 // See also:
19792013 // * http://docs.openstack.org/trunk/openstack-object-storage/admin/content/object-storage-bulk-delete.html
19802014 // * http://docs.rackspace.com/files/api/v1/cf-devguide/content/Bulk_Delete-d1e2338.html
1981 func (c *Connection) BulkDeleteHeaders(container string, objectNames []string, h Headers) (result BulkDeleteResult, err error) {
2015 func (c *Connection) BulkDeleteHeaders(ctx context.Context, container string, objectNames []string, h Headers) (result BulkDeleteResult, err error) {
19822016 if len(objectNames) == 0 {
19832017 result.Errors = make(map[string]error)
19842018 return
19872021 for i, name := range objectNames {
19882022 fullPaths[i] = fmt.Sprintf("/%s/%s", container, name)
19892023 }
1990 return c.doBulkDelete(fullPaths, h)
2024 return c.doBulkDelete(ctx, fullPaths, h)
19912025 }
19922026
19932027 // BulkUploadResult stores results of BulkUpload().
20202054 // See also:
20212055 // * http://docs.openstack.org/trunk/openstack-object-storage/admin/content/object-storage-extract-archive.html
20222056 // * http://docs.rackspace.com/files/api/v1/cf-devguide/content/Extract_Archive-d1e2338.html
2023 func (c *Connection) BulkUpload(uploadPath string, dataStream io.Reader, format string, h Headers) (result BulkUploadResult, err error) {
2057 func (c *Connection) BulkUpload(ctx context.Context, uploadPath string, dataStream io.Reader, format string, h Headers) (result BulkUploadResult, err error) {
20242058 extraHeaders := Headers{"Accept": "application/json"}
20252059 for key, value := range h {
20262060 extraHeaders[key] = value
20272061 }
20282062 // The following code abuses Container parameter intentionally.
20292063 // The best fix might be to rename Container to UploadPath.
2030 resp, headers, err := c.storage(RequestOpts{
2064 resp, headers, err := c.storage(ctx, RequestOpts{
20312065 Container: uploadPath,
20322066 Operation: "PUT",
20332067 Parameters: url.Values{"extract-archive": []string{format}},
20722106 // May return ObjectNotFound.
20732107 //
20742108 // Use headers.ObjectMetadata() to read the metadata in the Headers.
2075 func (c *Connection) Object(container string, objectName string) (info Object, headers Headers, err error) {
2109 func (c *Connection) Object(ctx context.Context, container string, objectName string) (info Object, headers Headers, err error) {
20762110 err = withLORetry(0, func() (Headers, int64, error) {
2077 info, headers, err = c.objectBase(container, objectName)
2111 info, headers, err = c.objectBase(ctx, container, objectName)
20782112 if err != nil {
20792113 return headers, 0, err
20802114 }
20832117 return
20842118 }
20852119
2086 func (c *Connection) objectBase(container string, objectName string) (info Object, headers Headers, err error) {
2120 func (c *Connection) objectBase(ctx context.Context, container string, objectName string) (info Object, headers Headers, err error) {
20872121 var resp *http.Response
2088 resp, headers, err = c.storage(RequestOpts{
2122 resp, headers, err = c.storage(ctx, RequestOpts{
20892123 Container: container,
20902124 ObjectName: objectName,
20912125 Operation: "HEAD",
21232157 }
21242158 }
21252159
2126 info.Hash = resp.Header.Get("Etag")
2160 // ETag header may be double quoted if following RFC 7232
2161 // https://github.com/openstack/swift/blob/2.24.0/CHANGELOG#L9
2162 info.Hash = strings.Trim(resp.Header.Get("Etag"), "\"")
21272163 if resp.Header.Get("X-Object-Manifest") != "" {
21282164 info.ObjectType = DynamicLargeObjectType
21292165 } else if resp.Header.Get("X-Static-Large-Object") != "" {
21552191 // other headers such as Content-Type or CORS headers.
21562192 //
21572193 // May return ObjectNotFound.
2158 func (c *Connection) ObjectUpdate(container string, objectName string, h Headers) error {
2159 _, _, err := c.storage(RequestOpts{
2194 func (c *Connection) ObjectUpdate(ctx context.Context, container string, objectName string, h Headers) error {
2195 _, _, err := c.storage(ctx, RequestOpts{
21602196 Container: container,
21612197 ObjectName: objectName,
21622198 Operation: "POST",
21852221 //
21862222 // You can use this to copy an object to itself - this is the only way
21872223 // to update the content type of an object.
2188 func (c *Connection) ObjectCopy(srcContainer string, srcObjectName string, dstContainer string, dstObjectName string, h Headers) (headers Headers, err error) {
2224 func (c *Connection) ObjectCopy(ctx context.Context, srcContainer string, srcObjectName string, dstContainer string, dstObjectName string, h Headers) (headers Headers, err error) {
21892225 // Meta stuff
21902226 extraHeaders := map[string]string{
21912227 "Destination": urlPathEscape(dstContainer + "/" + dstObjectName),
21932229 for key, value := range h {
21942230 extraHeaders[key] = value
21952231 }
2196 _, headers, err = c.storage(RequestOpts{
2232 _, headers, err = c.storage(ctx, RequestOpts{
21972233 Container: srcContainer,
21982234 ObjectName: srcObjectName,
21992235 Operation: "COPY",
22112247 // All metadata is preserved.
22122248 //
22132249 // The destination container must exist before the copy.
2214 func (c *Connection) ObjectMove(srcContainer string, srcObjectName string, dstContainer string, dstObjectName string) (err error) {
2215 _, err = c.ObjectCopy(srcContainer, srcObjectName, dstContainer, dstObjectName, nil)
2250 func (c *Connection) ObjectMove(ctx context.Context, srcContainer string, srcObjectName string, dstContainer string, dstObjectName string) (err error) {
2251 _, err = c.ObjectCopy(ctx, srcContainer, srcObjectName, dstContainer, dstObjectName, nil)
22162252 if err != nil {
22172253 return
22182254 }
2219 return c.ObjectDelete(srcContainer, srcObjectName)
2255 return c.ObjectDelete(ctx, srcContainer, srcObjectName)
22202256 }
22212257
22222258 // ObjectUpdateContentType updates the content type of an object
22242260 // This is a convenience method which calls ObjectCopy
22252261 //
22262262 // All other metadata is preserved.
2227 func (c *Connection) ObjectUpdateContentType(container string, objectName string, contentType string) (err error) {
2263 func (c *Connection) ObjectUpdateContentType(ctx context.Context, container string, objectName string, contentType string) (err error) {
22282264 h := Headers{"Content-Type": contentType}
2229 _, err = c.ObjectCopy(container, objectName, container, objectName, h)
2265 _, err = c.ObjectCopy(ctx, container, objectName, container, objectName, h)
22302266 return
22312267 }
22322268
22382274 //
22392275 // If the server doesn't support versioning then it will return
22402276 // Forbidden however it will have created both the containers at that point.
2241 func (c *Connection) VersionContainerCreate(current, version string) error {
2242 if err := c.ContainerCreate(version, nil); err != nil {
2277 func (c *Connection) VersionContainerCreate(ctx context.Context, current, version string) error {
2278 if err := c.ContainerCreate(ctx, version, nil); err != nil {
22432279 return err
22442280 }
2245 if err := c.ContainerCreate(current, nil); err != nil {
2281 if err := c.ContainerCreate(ctx, current, nil); err != nil {
22462282 return err
22472283 }
2248 if err := c.VersionEnable(current, version); err != nil {
2284 if err := c.VersionEnable(ctx, current, version); err != nil {
22492285 return err
22502286 }
22512287 return nil
22542290 // VersionEnable enables versioning on the current container with version as the tracking container.
22552291 //
22562292 // May return Forbidden if this isn't supported by the server
2257 func (c *Connection) VersionEnable(current, version string) error {
2293 func (c *Connection) VersionEnable(ctx context.Context, current, version string) error {
22582294 h := Headers{"X-Versions-Location": version}
2259 if err := c.ContainerUpdate(current, h); err != nil {
2295 if err := c.ContainerUpdate(ctx, current, h); err != nil {
22602296 return err
22612297 }
22622298 // Check to see if the header was set properly
2263 _, headers, err := c.Container(current)
2299 _, headers, err := c.Container(ctx, current)
22642300 if err != nil {
22652301 return err
22662302 }
22722308 }
22732309
22742310 // VersionDisable disables versioning on the current container.
2275 func (c *Connection) VersionDisable(current string) error {
2311 func (c *Connection) VersionDisable(ctx context.Context, current string) error {
22762312 h := Headers{"X-Versions-Location": ""}
2277 if err := c.ContainerUpdate(current, h); err != nil {
2313 if err := c.ContainerUpdate(ctx, current, h); err != nil {
22782314 return err
22792315 }
22802316 return nil
22832319 // VersionObjectList returns a list of older versions of the object.
22842320 //
22852321 // Objects are returned in the format <length><object_name>/<timestamp>
2286 func (c *Connection) VersionObjectList(version, object string) ([]string, error) {
2322 func (c *Connection) VersionObjectList(ctx context.Context, version, object string) ([]string, error) {
22872323 opts := &ObjectsOpts{
22882324 // <3-character zero-padded hexadecimal character length><object name>/
22892325 Prefix: fmt.Sprintf("%03x", len(object)) + object + "/",
22902326 }
2291 return c.ObjectNames(version, opts)
2292 }
2327 return c.ObjectNames(ctx, version, opts)
2328 }
2329
2330 // GetStorageUrl returns Swift storage URL.
2331 func (c *Connection) GetStorageUrl(ctx context.Context) (string, error) {
2332 c.authLock.Lock()
2333 defer c.authLock.Unlock()
2334
2335 // Return cached URL even if authentication has expired
2336 if c.StorageUrl == "" {
2337 err := c.authenticate(ctx)
2338 if err != nil {
2339 return "", err
2340 }
2341 }
2342 return c.StorageUrl, nil
2343 }
55 package swift
66
77 import (
8 "context"
89 "fmt"
910 "io"
1011 "net"
148149 func NewSwiftServer() *SwiftServer {
149150 server := &SwiftServer{}
150151 http.HandleFunc("/", handle)
151 go http.ListenAndServe(TEST_ADDRESS, nil)
152 go func() {
153 _ = http.ListenAndServe(TEST_ADDRESS, nil)
154 }()
152155 fmt.Print("Waiting for server to start ")
153156 for {
154157 fmt.Print(".")
155158 conn, err := net.Dial("tcp", TEST_ADDRESS)
156159 if err == nil {
157 conn.Close()
160 _ = conn.Close()
158161 fmt.Println(" Started")
159162 break
160163 }
315318 }).Url("/v1.0")
316319 defer server.Finished()
317320
318 err := c.Authenticate()
321 ctx := context.Background()
322 err := c.Authenticate(ctx)
319323 if err != nil {
320324 t.Fatal(err)
321325 }
335339 server.AddCheck(t).Error(401, "DENIED")
336340 defer server.Finished()
337341 c.UnAuthenticate()
338 err := c.Authenticate()
342 err := c.Authenticate(context.Background())
339343 if err != AuthorizationFailed {
340344 t.Fatal("Expecting AuthorizationFailed", err)
341345 }
350354 "X-Storage-Url": PROXY_URL,
351355 })
352356 defer server.Finished()
353 err := c.Authenticate()
357 ctx := context.Background()
358 err := c.Authenticate(ctx)
354359 checkError(t, err, 0, "Response didn't have storage url and auth token")
355360 if c.Authenticated() {
356361 t.Fatal("Expecting not authenticated")
359364 server.AddCheck(t).Out(Headers{
360365 "X-Auth-Token": AUTH_TOKEN,
361366 })
362 err = c.Authenticate()
367 err = c.Authenticate(ctx)
363368 checkError(t, err, 0, "Response didn't have storage url and auth token")
364369 if c.Authenticated() {
365370 t.Fatal("Expecting not authenticated")
366371 }
367372
368373 server.AddCheck(t)
369 err = c.Authenticate()
374 err = c.Authenticate(ctx)
370375 checkError(t, err, 0, "Response didn't have storage url and auth token")
371376 if c.Authenticated() {
372377 t.Fatal("Expecting not authenticated")
376381 "X-Storage-Url": PROXY_URL,
377382 "X-Auth-Token": AUTH_TOKEN,
378383 })
379 err = c.Authenticate()
384 err = c.Authenticate(ctx)
380385 if err != nil {
381386 t.Fatal(err)
382387 }
390395 "User-Agent": DefaultUserAgent,
391396 "X-Auth-Token": AUTH_TOKEN,
392397 }).Tx(rx).Url("/proxy")
393 containers, err := c.ContainerNames(nil)
398 containers, err := c.ContainerNames(context.Background(), nil)
394399 if err != nil {
395400 t.Fatal(err)
396401 }
419424 "Content-Type": "text/plain",
420425 }).Rx("12345")
421426 defer server.Finished()
422 c.ObjectPutBytes("container", "object", []byte{'1', '2', '3', '4', '5'}, "text/plain")
427 err := c.ObjectPutBytes(context.Background(), "container", "object", []byte{'1', '2', '3', '4', '5'}, "text/plain")
428 if err != nil {
429 t.Fatal("ObjectPutBytes", err)
430 }
423431 }
424432
425433 func TestInternalObjectPutString(t *testing.T) {
430438 "Content-Type": "text/plain",
431439 }).Rx("12345")
432440 defer server.Finished()
433 c.ObjectPutString("container", "object", "12345", "text/plain")
441 err := c.ObjectPutString(context.Background(), "container", "object", "12345", "text/plain")
442 if err != nil {
443 t.Fatal(err)
444 }
434445 }
435446
436447 func TestSetFromEnv(t *testing.T) {
437448 // String
438449 s := ""
439450
440 os.Setenv("POTATO", "")
451 _ = os.Setenv("POTATO", "")
441452 err := setFromEnv(&s, "POTATO")
442453 if err != nil {
443454 t.Fatal(err)
444455 }
445456
446 os.Setenv("POTATO", "this is a test")
457 _ = os.Setenv("POTATO", "this is a test")
447458 err = setFromEnv(&s, "POTATO")
448459 if err != nil {
449460 t.Fatal(err)
452463 t.Fatal("incorrect", s)
453464 }
454465
455 os.Setenv("POTATO", "new")
466 _ = os.Setenv("POTATO", "new")
456467 err = setFromEnv(&s, "POTATO")
457468 if err != nil {
458469 t.Fatal(err)
464475 // Integer
465476 i := 0
466477
467 os.Setenv("POTATO", "42")
478 _ = os.Setenv("POTATO", "42")
468479 err = setFromEnv(&i, "POTATO")
469480 if err != nil {
470481 t.Fatal(err)
473484 t.Fatal("incorrect", i)
474485 }
475486
476 os.Setenv("POTATO", "43")
487 _ = os.Setenv("POTATO", "43")
477488 err = setFromEnv(&i, "POTATO")
478489 if err != nil {
479490 t.Fatal(err)
483494 }
484495
485496 i = 0
486 os.Setenv("POTATO", "not a number")
497 _ = os.Setenv("POTATO", "not a number")
487498 err = setFromEnv(&i, "POTATO")
488499 if err == nil {
489500 t.Fatal("expecting error but didn't get one")
491502
492503 // bool
493504 var b bool
494 os.Setenv("POTATO", "1")
505 _ = os.Setenv("POTATO", "1")
495506 err = setFromEnv(&b, "POTATO")
496507 if err != nil {
497508 t.Fatal(err)
502513
503514 // time.Duration
504515 var dt time.Duration
505 os.Setenv("POTATO", "5s")
516 _ = os.Setenv("POTATO", "5s")
506517 err = setFromEnv(&dt, "POTATO")
507518 if err != nil {
508519 t.Fatal(err)
513524
514525 // EndpointType
515526 var e EndpointType
516 os.Setenv("POTATO", "internal")
527 _ = os.Setenv("POTATO", "internal")
517528 err = setFromEnv(&e, "POTATO")
518529 if err != nil {
519530 t.Fatal(err)
529540 t.Fatal("expecting error")
530541 }
531542
532 os.Setenv("POTATO", "")
543 _ = os.Setenv("POTATO", "")
533544 }
534545
535546 func TestApplyEnvironment(t *testing.T) {
536547 // We've tested all the setting logic above, so just do a quick test here
537548 c := new(Connection)
538 os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "100s")
549 _ = os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "100s")
539550 err := c.ApplyEnvironment()
540551 if err != nil {
541552 t.Fatal(err)
545556 }
546557
547558 c.ConnectTimeout = 0
548 os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "parse error")
559 _ = os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "parse error")
549560 err = c.ApplyEnvironment()
550561 if err == nil {
551562 t.Fatal("expecting error")
554565 t.Fatal("timeout incorrect", c.ConnectTimeout)
555566 }
556567
557 os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "")
568 _ = os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "")
558569 }
559570
560571 func TestApplyEnvironmentAll(t *testing.T) {
604615 item := &items[i]
605616 if item.phase == phase {
606617 item.oldValue = os.Getenv(item.name) // save old value
607 os.Setenv(item.name, item.value) // set new value
618 _ = os.Setenv(item.name, item.value) // set new value
608619 }
609620 }
610621
620631 if !reflect.DeepEqual(item.want, got) {
621632 t.Errorf("%s: %v != %v", item.name, item.want, got)
622633 }
623 os.Setenv(item.name, item.oldValue) // restore old value
634 _ = os.Setenv(item.name, item.oldValue) // restore old value
624635 }
625636 }
626637 }
627638
628639 }
640
641 func TestIsLastPage(t *testing.T) {
642 conn := &Connection{}
643 testPaging(t, conn, []pagingTest{
644 {
645 length: 0,
646 limit: 1000,
647 expected: true,
648 },
649 {
650 length: 850,
651 limit: 1000,
652 expected: true,
653 },
654 {
655 length: 950,
656 limit: 1000,
657 expected: true,
658 },
659 {
660 length: 1000,
661 limit: 1000,
662 expected: false,
663 },
664 // For completeness
665 {
666 length: 0,
667 limit: 0,
668 expected: false,
669 },
670 {
671 length: 2000,
672 limit: 1000,
673 expected: false,
674 },
675 })
676
677 }
678
679 func TestFetchUntilEmptyPageWorkaround(t *testing.T) {
680 conn := &Connection{
681 FetchUntilEmptyPage: true,
682 }
683 testPaging(t, conn, []pagingTest{
684 {
685 length: 0,
686 limit: 1000,
687 expected: true,
688 },
689 {
690 length: 850,
691 limit: 1000,
692 expected: false,
693 },
694 {
695 length: 950,
696 limit: 1000,
697 expected: false,
698 },
699 {
700 length: 1000,
701 limit: 1000,
702 expected: false,
703 },
704 // For completeness
705 {
706 length: 0,
707 limit: 0,
708 expected: false,
709 },
710 {
711 length: 2000,
712 limit: 1000,
713 expected: false,
714 },
715 })
716 }
717
718 func TestPartialPageFetchThreshold(t *testing.T) {
719 conn := &Connection{
720 PartialPageFetchThreshold: 90,
721 }
722 testPaging(t, conn, []pagingTest{
723 {
724 length: 0,
725 limit: 1000,
726 expected: true,
727 },
728 {
729 length: 850,
730 limit: 1000,
731 expected: true,
732 },
733 {
734 length: 950,
735 limit: 1000,
736 expected: false,
737 },
738 {
739 length: 1000,
740 limit: 1000,
741 expected: false,
742 },
743 // For completeness
744 {
745 length: 0,
746 limit: 0,
747 expected: false,
748 },
749 {
750 length: 2000,
751 limit: 1000,
752 expected: false,
753 },
754 })
755
756 }
757
758 type pagingTest struct {
759 length int
760 limit int
761 expected bool
762 }
763
764 func testPaging(t *testing.T, conn *Connection, testCases []pagingTest) {
765 for _, tCase := range testCases {
766 if actual := conn.isLastPage(tCase.length, tCase.limit); actual != tCase.expected {
767 t.Fatalf("isLastPage(%d, %d) returned %t, expected %t", tCase.length, tCase.limit, actual, tCase.expected)
768 }
769 }
770 }
1414 import (
1515 "archive/tar"
1616 "bytes"
17 "context"
1718 "crypto/md5"
1819 "crypto/rand"
1920 "crypto/tls"
3233 "testing"
3334 "time"
3435
35 "github.com/ncw/swift"
36 "github.com/ncw/swift/swifttest"
36 "github.com/ncw/swift/v2"
37 "github.com/ncw/swift/v2/swifttest"
3738 )
3839
3940 var (
143144 }
144145
145146 func makeConnectionAuth(t *testing.T) (*swift.Connection, func()) {
147 ctx := context.Background()
146148 c, rollback := makeConnection(t)
147 err := c.Authenticate()
149 err := c.Authenticate(ctx)
148150 if err != nil {
149151 t.Fatal("Auth failed", err)
150152 }
152154 }
153155
154156 func makeConnectionWithContainer(t *testing.T) (*swift.Connection, func()) {
157 ctx := context.Background()
155158 c, rollback := makeConnectionAuth(t)
156 err := c.ContainerCreate(CONTAINER, m1.ContainerHeaders())
159 err := c.ContainerCreate(ctx, CONTAINER, m1.ContainerHeaders())
157160 if err != nil {
158161 t.Fatal(err)
159162 }
160163 return c, func() {
161 c.ContainerDelete(CONTAINER)
164 _ = c.ContainerDelete(ctx, CONTAINER)
162165 rollback()
163166 }
164167 }
165168
166169 func makeConnectionWithObject(t *testing.T) (*swift.Connection, func()) {
170 ctx := context.Background()
167171 c, rollback := makeConnectionWithContainer(t)
168 err := c.ObjectPutString(CONTAINER, OBJECT, CONTENTS, "")
172 err := c.ObjectPutString(ctx, CONTAINER, OBJECT, CONTENTS, "")
169173 if err != nil {
170174 t.Fatal(err)
171175 }
172176 return c, func() {
173 c.ObjectDelete(CONTAINER, OBJECT)
177 _ = c.ObjectDelete(ctx, CONTAINER, OBJECT)
174178 rollback()
175179 }
176180 }
177181
178182 func makeConnectionWithObjectHeaders(t *testing.T) (*swift.Connection, func()) {
183 ctx := context.Background()
179184 c, rollback := makeConnectionWithObject(t)
180 err := c.ObjectUpdate(CONTAINER, OBJECT, m1.ObjectHeaders())
185 err := c.ObjectUpdate(ctx, CONTAINER, OBJECT, m1.ObjectHeaders())
181186 if err != nil {
182187 t.Fatal(err)
183188 }
185190 }
186191
187192 func makeConnectionWithVersionsContainer(t *testing.T) (*swift.Connection, func()) {
193 ctx := context.Background()
188194 c, rollback := makeConnectionAuth(t)
189 err := c.VersionContainerCreate(CURRENT_CONTAINER, VERSIONS_CONTAINER)
195 err := c.VersionContainerCreate(ctx, CURRENT_CONTAINER, VERSIONS_CONTAINER)
190196 newRollback := func() {
191 c.ContainerDelete(CURRENT_CONTAINER)
192 c.ContainerDelete(VERSIONS_CONTAINER)
197 _ = c.ContainerDelete(ctx, CURRENT_CONTAINER)
198 _ = c.ContainerDelete(ctx, VERSIONS_CONTAINER)
193199 rollback()
194200 }
195201 if err != nil {
203209 }
204210
205211 func makeConnectionWithVersionsObject(t *testing.T) (*swift.Connection, func()) {
212 ctx := context.Background()
206213 c, rollback := makeConnectionWithVersionsContainer(t)
207 if err := c.ObjectPutString(CURRENT_CONTAINER, OBJECT, CONTENTS, ""); err != nil {
214 if err := c.ObjectPutString(ctx, CURRENT_CONTAINER, OBJECT, CONTENTS, ""); err != nil {
208215 t.Fatal(err)
209216 }
210217 // Version 2
211 if err := c.ObjectPutString(CURRENT_CONTAINER, OBJECT, CONTENTS2, ""); err != nil {
218 if err := c.ObjectPutString(ctx, CURRENT_CONTAINER, OBJECT, CONTENTS2, ""); err != nil {
212219 t.Fatal(err)
213220 }
214221 // Version 3
215 if err := c.ObjectPutString(CURRENT_CONTAINER, OBJECT, CONTENTS2, ""); err != nil {
222 if err := c.ObjectPutString(ctx, CURRENT_CONTAINER, OBJECT, CONTENTS2, ""); err != nil {
216223 t.Fatal(err)
217224 }
218225 return c, func() {
219226 for i := 0; i < 3; i++ {
220 c.ObjectDelete(CURRENT_CONTAINER, OBJECT)
227 _ = c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT)
221228 }
222229 rollback()
223230 }
224231 }
225232
226233 func makeConnectionWithSegmentsContainer(t *testing.T) (*swift.Connection, func()) {
234 ctx := context.Background()
227235 c, rollback := makeConnectionWithContainer(t)
228 err := c.ContainerCreate(SEGMENTS_CONTAINER, swift.Headers{})
236 err := c.ContainerCreate(ctx, SEGMENTS_CONTAINER, swift.Headers{})
229237 if err != nil {
230238 t.Fatal(err)
231239 }
232240 return c, func() {
233 err = c.ContainerDelete(SEGMENTS_CONTAINER)
241 err = c.ContainerDelete(ctx, SEGMENTS_CONTAINER)
234242 if err != nil {
235243 t.Fatal(err)
236244 }
239247 }
240248
241249 func makeConnectionWithDLO(t *testing.T) (*swift.Connection, func()) {
250 ctx := context.Background()
242251 c, rollback := makeConnectionWithSegmentsContainer(t)
243252 opts := swift.LargeObjectOpts{
244253 Container: CONTAINER,
245254 ObjectName: OBJECT,
246255 ContentType: "image/jpeg",
247256 }
248 out, err := c.DynamicLargeObjectCreate(&opts)
257 out, err := c.DynamicLargeObjectCreate(ctx, &opts)
249258 if err != nil {
250259 t.Fatal(err)
251260 }
255264 t.Fatal(err)
256265 }
257266 }
258 err = out.Close()
267 err = out.CloseWithContext(ctx)
259268 if err != nil {
260269 t.Error(err)
261270 }
262271 return c, func() {
263 c.DynamicLargeObjectDelete(CONTAINER, OBJECT)
272 _ = c.DynamicLargeObjectDelete(ctx, CONTAINER, OBJECT)
264273 rollback()
265274 }
266275 }
267276
268277 func makeConnectionWithSLO(t *testing.T) (*swift.Connection, func()) {
278 ctx := context.Background()
269279 c, rollback := makeConnectionWithSegmentsContainer(t)
270280 opts := swift.LargeObjectOpts{
271281 Container: CONTAINER,
272282 ObjectName: OBJECT,
273283 ContentType: "image/jpeg",
274284 }
275 out, err := c.StaticLargeObjectCreate(&opts)
285 out, err := c.StaticLargeObjectCreate(ctx, &opts)
276286 if err != nil {
277287 if err == swift.SLONotSupported {
278288 t.Skip("SLO not supported")
286296 t.Fatal(err)
287297 }
288298 }
289 err = out.Close()
299 err = out.CloseWithContext(ctx)
290300 if err != nil {
291301 t.Error(err)
292302 }
293303 return c, func() {
294 c.StaticLargeObjectDelete(CONTAINER, OBJECT)
304 _ = c.StaticLargeObjectDelete(ctx, CONTAINER, OBJECT)
295305 rollback()
296306 }
297307 }
302312 }
303313
304314 func getSwinftInfo(t *testing.T) (info swift.SwiftInfo, err error) {
315 ctx := context.Background()
305316 c, rollback := makeConnectionAuth(t)
306317 defer rollback()
307 return c.QueryInfo()
318 return c.QueryInfo(ctx)
308319 }
309320
310321 func TestTransport(t *testing.T) {
322 ctx := context.Background()
311323 c, rollback := makeConnection(t)
312324 defer rollback()
313325
325337
326338 c.Transport = tr
327339
328 err := c.Authenticate()
340 err := c.Authenticate(ctx)
329341 if err != nil {
330342 t.Fatal("Auth failed", err)
331343 }
336348
337349 // The following Test functions are run in order - this one must come before the others!
338350 func TestV1V2Authenticate(t *testing.T) {
351 ctx := context.Background()
339352 if isV3Api() {
340353 return
341354 }
342355 c, rollback := makeConnection(t)
343356 defer rollback()
344357
345 err := c.Authenticate()
358 err := c.Authenticate(ctx)
346359 if err != nil {
347360 t.Fatal("Auth failed", err)
348361 }
352365 }
353366
354367 func TestV3AuthenticateWithDomainNameAndTenantId(t *testing.T) {
368 ctx := context.Background()
355369 if !isV3Api() {
356370 return
357371 }
364378 c.TenantId = os.Getenv("SWIFT_TENANT_ID")
365379 c.DomainId = ""
366380
367 err := c.Authenticate()
381 err := c.Authenticate(ctx)
368382 if err != nil {
369383 t.Fatal("Auth failed", err)
370384 }
374388 }
375389
376390 func TestV3TrustWithTrustId(t *testing.T) {
391 ctx := context.Background()
377392 if !isV3Api() {
378393 return
379394 }
383398
384399 c.TrustId = os.Getenv("SWIFT_TRUST_ID")
385400
386 err := c.Authenticate()
401 err := c.Authenticate(ctx)
387402 if err != nil {
388403 t.Fatal("Auth failed", err)
389404 }
393408 }
394409
395410 func TestV3AuthenticateWithDomainIdAndTenantId(t *testing.T) {
411 ctx := context.Background()
396412 if !isV3Api() {
397413 return
398414 }
405421 c.TenantId = os.Getenv("SWIFT_TENANT_ID")
406422 c.DomainId = os.Getenv("SWIFT_API_DOMAIN_ID")
407423
408 err := c.Authenticate()
424 err := c.Authenticate(ctx)
409425 if err != nil {
410426 t.Fatal("Auth failed", err)
411427 }
415431 }
416432
417433 func TestV3AuthenticateWithDomainNameAndTenantName(t *testing.T) {
434 ctx := context.Background()
418435 if !isV3Api() {
419436 return
420437 }
427444 c.TenantId = ""
428445 c.DomainId = ""
429446
430 err := c.Authenticate()
447 err := c.Authenticate(ctx)
431448 if err != nil {
432449 t.Fatal("Auth failed", err)
433450 }
437454 }
438455
439456 func TestV3AuthenticateWithDomainIdAndTenantName(t *testing.T) {
457 ctx := context.Background()
440458 if !isV3Api() {
441459 return
442460 }
449467 c.TenantId = ""
450468 c.DomainId = os.Getenv("SWIFT_API_DOMAIN_ID")
451469
452 err := c.Authenticate()
470 err := c.Authenticate(ctx)
453471 if err != nil {
454472 t.Fatal("Auth failed", err)
455473 }
462480 //
463481 // Run with -race to test
464482 func TestAuthenticateRace(t *testing.T) {
483 ctx := context.Background()
465484 c, rollback := makeConnection(t)
466485 defer rollback()
467486 var wg sync.WaitGroup
469488 wg.Add(1)
470489 go func() {
471490 defer wg.Done()
472 err := c.Authenticate()
491 err := c.Authenticate(ctx)
473492 if err != nil {
474 t.Fatal("Auth failed", err)
493 t.Error("Auth failed", err)
475494 }
476495 if !c.Authenticated() {
477 t.Fatal("Not authenticated")
496 t.Error("Not authenticated")
478497 }
479498 }()
480499 }
483502
484503 // Test a connection can be serialized and unserialized with JSON
485504 func TestSerializeConnectionJson(t *testing.T) {
505 ctx := context.Background()
486506 c, rollback := makeConnectionAuth(t)
487507 defer rollback()
488508 serializedConnection, err := json.Marshal(c)
497517 if !c2.Authenticated() {
498518 t.Fatal("Should be authenticated")
499519 }
500 _, _, err = c2.Account()
520 _, _, err = c2.Account(ctx)
501521 if err != nil {
502522 t.Fatalf("Failed to use unserialized connection: %v", err)
503523 }
505525
506526 // Test a connection can be serialized and unserialized with XML
507527 func TestSerializeConnectionXml(t *testing.T) {
528 ctx := context.Background()
508529 c, rollback := makeConnectionAuth(t)
509530 defer rollback()
510531 serializedConnection, err := xml.Marshal(c)
519540 if !c2.Authenticated() {
520541 t.Fatal("Should be authenticated")
521542 }
522 _, _, err = c2.Account()
543 _, _, err = c2.Account(ctx)
523544 if err != nil {
524545 t.Fatalf("Failed to use unserialized connection: %v", err)
525546 }
527548
528549 // Test the reauthentication logic
529550 func TestOnReAuth(t *testing.T) {
551 ctx := context.Background()
530552 c, rollback := makeConnectionAuth(t)
531553 defer rollback()
532554 c.UnAuthenticate()
533 _, _, err := c.Account()
555 _, _, err := c.Account(ctx)
534556 if err != nil {
535557 t.Fatalf("Failed to reauthenticate: %v", err)
536558 }
537559 }
538560
539561 func TestAccount(t *testing.T) {
562 ctx := context.Background()
540563 c, rollback := makeConnectionAuth(t)
541564 defer rollback()
542 info, headers, err := c.Account()
565 info, headers, err := c.Account(ctx)
543566 if err != nil {
544567 t.Fatal(err)
545568 }
571594 }
572595
573596 func TestAccountUpdate(t *testing.T) {
597 ctx := context.Background()
574598 c, rollback := makeConnectionAuth(t)
575599 defer rollback()
576 err := c.AccountUpdate(m1.AccountHeaders())
577 if err != nil {
578 t.Fatal(err)
579 }
580
581 _, headers, err := c.Account()
600 err := c.AccountUpdate(ctx, m1.AccountHeaders())
601 if err != nil {
602 t.Fatal(err)
603 }
604
605 _, headers, err := c.Account(ctx)
582606 if err != nil {
583607 t.Fatal(err)
584608 }
586610 delete(m, "temp-url-key") // remove X-Account-Meta-Temp-URL-Key if set
587611 compareMaps(t, m, map[string]string{"hello": "1", "potato-salad": "2"})
588612
589 err = c.AccountUpdate(m2.AccountHeaders())
590 if err != nil {
591 t.Fatal(err)
592 }
593
594 _, headers, err = c.Account()
613 err = c.AccountUpdate(ctx, m2.AccountHeaders())
614 if err != nil {
615 t.Fatal(err)
616 }
617
618 _, headers, err = c.Account(ctx)
595619 if err != nil {
596620 t.Fatal(err)
597621 }
601625 }
602626
603627 func TestContainerCreate(t *testing.T) {
628 ctx := context.Background()
604629 c, rollback := makeConnectionAuth(t)
605630 defer rollback()
606 err := c.ContainerCreate(CONTAINER, m1.ContainerHeaders())
607 if err != nil {
608 t.Fatal(err)
609 }
610 err = c.ContainerDelete(CONTAINER)
631 err := c.ContainerCreate(ctx, CONTAINER, m1.ContainerHeaders())
632 if err != nil {
633 t.Fatal(err)
634 }
635 err = c.ContainerDelete(ctx, CONTAINER)
611636 if err != nil {
612637 t.Fatal(err)
613638 }
614639 }
615640
616641 func TestContainer(t *testing.T) {
642 ctx := context.Background()
617643 c, rollback := makeConnectionWithContainer(t)
618644 defer rollback()
619 info, headers, err := c.Container(CONTAINER)
645 info, headers, err := c.Container(ctx, CONTAINER)
620646 if err != nil {
621647 t.Fatal(err)
622648 }
633659 }
634660
635661 func TestContainersAll(t *testing.T) {
662 ctx := context.Background()
636663 c, rollback := makeConnectionWithContainer(t)
637664 defer rollback()
638 containers1, err := c.ContainersAll(nil)
639 if err != nil {
640 t.Fatal(err)
641 }
642 containers2, err := c.Containers(nil)
665 containers1, err := c.ContainersAll(ctx, nil)
666 if err != nil {
667 t.Fatal(err)
668 }
669 containers2, err := c.Containers(ctx, nil)
643670 if err != nil {
644671 t.Fatal(err)
645672 }
654681 }
655682
656683 func TestContainersAllWithLimit(t *testing.T) {
684 ctx := context.Background()
657685 c, rollback := makeConnectionWithContainer(t)
658686 defer rollback()
659 containers1, err := c.ContainersAll(&swift.ContainersOpts{Limit: 1})
660 if err != nil {
661 t.Fatal(err)
662 }
663 containers2, err := c.Containers(nil)
687 containers1, err := c.ContainersAll(ctx, &swift.ContainersOpts{Limit: 1})
688 if err != nil {
689 t.Fatal(err)
690 }
691 containers2, err := c.Containers(ctx, nil)
664692 if err != nil {
665693 t.Fatal(err)
666694 }
675703 }
676704
677705 func TestContainerUpdate(t *testing.T) {
706 ctx := context.Background()
678707 c, rollback := makeConnectionWithContainer(t)
679708 defer rollback()
680 err := c.ContainerUpdate(CONTAINER, m2.ContainerHeaders())
681 if err != nil {
682 t.Fatal(err)
683 }
684 _, headers, err := c.Container(CONTAINER)
709 err := c.ContainerUpdate(ctx, CONTAINER, m2.ContainerHeaders())
710 if err != nil {
711 t.Fatal(err)
712 }
713 _, headers, err := c.Container(ctx, CONTAINER)
685714 if err != nil {
686715 t.Fatal(err)
687716 }
689718 }
690719
691720 func TestContainerNames(t *testing.T) {
721 ctx := context.Background()
692722 c, rollback := makeConnectionWithContainer(t)
693723 defer rollback()
694 containers, err := c.ContainerNames(nil)
724 containers, err := c.ContainerNames(ctx, nil)
695725 if err != nil {
696726 t.Fatal(err)
697727 }
708738 }
709739
710740 func TestContainerNamesAll(t *testing.T) {
741 ctx := context.Background()
711742 c, rollback := makeConnectionWithContainer(t)
712743 defer rollback()
713 containers1, err := c.ContainerNamesAll(nil)
714 if err != nil {
715 t.Fatal(err)
716 }
717 containers2, err := c.ContainerNames(nil)
744 containers1, err := c.ContainerNamesAll(ctx, nil)
745 if err != nil {
746 t.Fatal(err)
747 }
748 containers2, err := c.ContainerNames(ctx, nil)
718749 if err != nil {
719750 t.Fatal(err)
720751 }
729760 }
730761
731762 func TestContainerNamesAllWithLimit(t *testing.T) {
763 ctx := context.Background()
732764 c, rollback := makeConnectionWithContainer(t)
733765 defer rollback()
734 containers1, err := c.ContainerNamesAll(&swift.ContainersOpts{Limit: 1})
735 if err != nil {
736 t.Fatal(err)
737 }
738 containers2, err := c.ContainerNames(nil)
766 containers1, err := c.ContainerNamesAll(ctx, &swift.ContainersOpts{Limit: 1})
767 if err != nil {
768 t.Fatal(err)
769 }
770 containers2, err := c.ContainerNames(ctx, nil)
739771 if err != nil {
740772 t.Fatal(err)
741773 }
750782 }
751783
752784 func TestObjectPutString(t *testing.T) {
785 ctx := context.Background()
753786 c, rollback := makeConnectionWithContainer(t)
754787 defer rollback()
755 err := c.ObjectPutString(CONTAINER, OBJECT, CONTENTS, "")
788 err := c.ObjectPutString(ctx, CONTAINER, OBJECT, CONTENTS, "")
756789 if err != nil {
757790 t.Fatal(err)
758791 }
759792 defer func() {
760 err = c.ObjectDelete(CONTAINER, OBJECT)
793 err = c.ObjectDelete(ctx, CONTAINER, OBJECT)
761794 if err != nil {
762795 t.Fatal(err)
763796 }
764797 }()
765798
766 info, _, err := c.Object(CONTAINER, OBJECT)
799 info, _, err := c.Object(ctx, CONTAINER, OBJECT)
767800 if err != nil {
768801 t.Error(err)
769802 }
779812 }
780813
781814 func TestObjectPut(t *testing.T) {
815 ctx := context.Background()
782816 c, rollback := makeConnectionWithContainer(t)
783817 defer rollback()
784818
787821 // Set content size incorrectly - should produce an error
788822 headers["Content-Length"] = strconv.FormatInt(CONTENT_SIZE-1, 10)
789823 contents := bytes.NewBufferString(CONTENTS)
790 h, err := c.ObjectPut(CONTAINER, OBJECT, contents, true, CONTENT_MD5, "text/plain", headers)
824 _, err := c.ObjectPut(ctx, CONTAINER, OBJECT, contents, true, CONTENT_MD5, "text/plain", headers)
791825 if err == nil {
792826 t.Fatal("Expecting error but didn't get one")
793827 }
795829 // Now set content size correctly
796830 contents = bytes.NewBufferString(CONTENTS)
797831 headers["Content-Length"] = strconv.FormatInt(CONTENT_SIZE, 10)
798 h, err = c.ObjectPut(CONTAINER, OBJECT, contents, true, CONTENT_MD5, "text/plain", headers)
832 h, err := c.ObjectPut(ctx, CONTAINER, OBJECT, contents, true, CONTENT_MD5, "text/plain", headers)
799833 if err != nil {
800834 t.Fatal(err)
801835 }
802836 defer func() {
803 err = c.ObjectDelete(CONTAINER, OBJECT)
837 err = c.ObjectDelete(ctx, CONTAINER, OBJECT)
804838 if err != nil {
805839 t.Fatal(err)
806840 }
811845 }
812846
813847 // Fetch object info and compare
814 info, _, err := c.Object(CONTAINER, OBJECT)
848 info, _, err := c.Object(ctx, CONTAINER, OBJECT)
815849 if err != nil {
816850 t.Error(err)
817851 }
827861 }
828862
829863 func TestObjectPutWithReauth(t *testing.T) {
864 ctx := context.Background()
830865 if !swift.IS_AT_LEAST_GO_16 {
831866 return
832867 }
837872 c.AuthToken = "expiredtoken"
838873
839874 r := strings.NewReader(CONTENTS)
840 _, err := c.ObjectPut(CONTAINER, OBJECT, r, true, "", "text/plain", nil)
841 if err != nil {
842 t.Fatal(err)
843 }
844
845 info, _, err := c.Object(CONTAINER, OBJECT)
875 _, err := c.ObjectPut(ctx, CONTAINER, OBJECT, r, true, "", "text/plain", nil)
876 if err != nil {
877 t.Fatal(err)
878 }
879
880 info, _, err := c.Object(ctx, CONTAINER, OBJECT)
846881 if err != nil {
847882 t.Error(err)
848883 }
858893 }
859894
860895 func TestObjectPutStringWithReauth(t *testing.T) {
896 ctx := context.Background()
861897 if !swift.IS_AT_LEAST_GO_16 {
862898 return
863899 }
867903 // Simulate that our auth token expired
868904 c.AuthToken = "expiredtoken"
869905
870 err := c.ObjectPutString(CONTAINER, OBJECT, CONTENTS, "")
871 if err != nil {
872 t.Fatal(err)
873 }
874
875 info, _, err := c.Object(CONTAINER, OBJECT)
906 err := c.ObjectPutString(ctx, CONTAINER, OBJECT, CONTENTS, "")
907 if err != nil {
908 t.Fatal(err)
909 }
910
911 info, _, err := c.Object(ctx, CONTAINER, OBJECT)
876912 if err != nil {
877913 t.Error(err)
878914 }
888924 }
889925
890926 func TestObjectEmpty(t *testing.T) {
927 ctx := context.Background()
891928 c, rollback := makeConnectionWithContainer(t)
892929 defer rollback()
893 err := c.ObjectPutString(CONTAINER, EMPTYOBJECT, "", "")
930 err := c.ObjectPutString(ctx, CONTAINER, EMPTYOBJECT, "", "")
894931 if err != nil {
895932 t.Fatal(err)
896933 }
897934 defer func() {
898 err = c.ObjectDelete(CONTAINER, EMPTYOBJECT)
935 err = c.ObjectDelete(ctx, CONTAINER, EMPTYOBJECT)
899936 if err != nil {
900937 t.Error(err)
901938 }
902939 }()
903940
904 info, _, err := c.Object(CONTAINER, EMPTYOBJECT)
941 info, _, err := c.Object(ctx, CONTAINER, EMPTYOBJECT)
905942 if err != nil {
906943 t.Error(err)
907944 }
917954 }
918955
919956 func TestSymlinkObject(t *testing.T) {
957 ctx := context.Background()
920958 info, err := getSwinftInfo(t)
921959 if err != nil {
922960 t.Fatal(err)
930968 defer rollback()
931969
932970 // write target objects
933 err = c.ObjectPutBytes(CONTAINER, OBJECT, []byte(CONTENTS), "text/potato")
971 err = c.ObjectPutBytes(ctx, CONTAINER, OBJECT, []byte(CONTENTS), "text/potato")
934972 if err != nil {
935973 t.Fatal(err)
936974 }
937975 defer func() {
938 err = c.ObjectDelete(CONTAINER, OBJECT)
976 err = c.ObjectDelete(ctx, CONTAINER, OBJECT)
939977 if err != nil {
940978 t.Error(err)
941979 }
942980 }()
943981
944982 // test dynamic link
945 _, err = c.ObjectSymlinkCreate(CONTAINER, SYMLINK_OBJECT, "", CONTAINER, OBJECT, "")
983 _, err = c.ObjectSymlinkCreate(ctx, CONTAINER, SYMLINK_OBJECT, "", CONTAINER, OBJECT, "")
946984 if err != nil {
947985 t.Fatal(err)
948986 }
949987 defer func() {
950 err = c.ObjectDelete(CONTAINER, SYMLINK_OBJECT)
988 err = c.ObjectDelete(ctx, CONTAINER, SYMLINK_OBJECT)
951989 if err != nil {
952990 t.Error(err)
953991 }
954992 }()
955993
956 md, _, err := c.Object(CONTAINER, SYMLINK_OBJECT)
994 md, _, err := c.Object(ctx, CONTAINER, SYMLINK_OBJECT)
957995 if err != nil {
958996 t.Error(err)
959997 }
9701008 }
9711009
9721010 func TestStaticSymlinkObject(t *testing.T) {
1011 ctx := context.Background()
9731012 info, err := getSwinftInfo(t)
9741013 if err != nil {
9751014 t.Fatal(err)
9881027 defer rollback()
9891028
9901029 // write target objects
991 err = c.ObjectPutBytes(CONTAINER, OBJECT2, []byte(CONTENTS2), "text/tomato")
1030 err = c.ObjectPutBytes(ctx, CONTAINER, OBJECT2, []byte(CONTENTS2), "text/tomato")
9921031 if err != nil {
9931032 t.Fatal(err)
9941033 }
9951034 defer func() {
996 err = c.ObjectDelete(CONTAINER, OBJECT2)
1035 err = c.ObjectDelete(ctx, CONTAINER, OBJECT2)
9971036 if err != nil {
9981037 t.Error(err)
9991038 }
10011040
10021041 // test static link
10031042 // first with the wrong target etag
1004 _, err = c.ObjectSymlinkCreate(CONTAINER, SYMLINK_OBJECT2, "", CONTAINER, OBJECT2, CONTENT_MD5)
1043 _, err = c.ObjectSymlinkCreate(ctx, CONTAINER, SYMLINK_OBJECT2, "", CONTAINER, OBJECT2, CONTENT_MD5)
10051044 if err == nil {
10061045 t.Error("Symlink with wrong target etag should have failed")
10071046 }
10081047
1009 _, err = c.ObjectSymlinkCreate(CONTAINER, SYMLINK_OBJECT2, "", CONTAINER, OBJECT2, CONTENT2_MD5)
1048 _, err = c.ObjectSymlinkCreate(ctx, CONTAINER, SYMLINK_OBJECT2, "", CONTAINER, OBJECT2, CONTENT2_MD5)
10101049 if err != nil {
10111050 t.Fatal(err)
10121051 }
10131052 defer func() {
1014 err = c.ObjectDelete(CONTAINER, SYMLINK_OBJECT2)
1053 err = c.ObjectDelete(ctx, CONTAINER, SYMLINK_OBJECT2)
10151054 if err != nil {
10161055 t.Error(err)
10171056 }
10181057 }()
10191058
1020 md, _, err := c.Object(CONTAINER, SYMLINK_OBJECT2)
1059 md, _, err := c.Object(ctx, CONTAINER, SYMLINK_OBJECT2)
10211060 if err != nil {
10221061 t.Error(err)
10231062 }
10331072 }
10341073
10351074 func TestObjectPutBytes(t *testing.T) {
1075 ctx := context.Background()
10361076 c, rollback := makeConnectionWithContainer(t)
10371077 defer rollback()
1038 err := c.ObjectPutBytes(CONTAINER, OBJECT, []byte(CONTENTS), "")
1078 err := c.ObjectPutBytes(ctx, CONTAINER, OBJECT, []byte(CONTENTS), "")
10391079 if err != nil {
10401080 t.Fatal(err)
10411081 }
10421082 defer func() {
1043 err = c.ObjectDelete(CONTAINER, OBJECT)
1083 err = c.ObjectDelete(ctx, CONTAINER, OBJECT)
10441084 if err != nil {
10451085 t.Error(err)
10461086 }
10471087 }()
10481088
1049 info, _, err := c.Object(CONTAINER, OBJECT)
1089 info, _, err := c.Object(ctx, CONTAINER, OBJECT)
10501090 if err != nil {
10511091 t.Error(err)
10521092 }
10621102 }
10631103
10641104 func TestObjectPutMimeType(t *testing.T) {
1105 ctx := context.Background()
10651106 c, rollback := makeConnectionWithContainer(t)
10661107 defer rollback()
1067 err := c.ObjectPutString(CONTAINER, "test.jpg", CONTENTS, "")
1108 err := c.ObjectPutString(ctx, CONTAINER, "test.jpg", CONTENTS, "")
10681109 if err != nil {
10691110 t.Fatal(err)
10701111 }
10711112 defer func() {
1072 err = c.ObjectDelete(CONTAINER, "test.jpg")
1113 err = c.ObjectDelete(ctx, CONTAINER, "test.jpg")
10731114 if err != nil {
10741115 t.Error(err)
10751116 }
10761117 }()
10771118
1078 info, _, err := c.Object(CONTAINER, "test.jpg")
1119 info, _, err := c.Object(ctx, CONTAINER, "test.jpg")
10791120 if err != nil {
10801121 t.Error(err)
10811122 }
10851126 }
10861127
10871128 func TestObjectCreate(t *testing.T) {
1129 ctx := context.Background()
10881130 c, rollback := makeConnectionWithContainer(t)
10891131 defer rollback()
1090 out, err := c.ObjectCreate(CONTAINER, OBJECT2, true, "", "", nil)
1132 out, err := c.ObjectCreate(ctx, CONTAINER, OBJECT2, true, "", "", nil)
10911133 if err != nil {
10921134 t.Fatal(err)
10931135 }
10941136 defer func() {
1095 err = c.ObjectDelete(CONTAINER, OBJECT2)
1137 err = c.ObjectDelete(ctx, CONTAINER, OBJECT2)
10961138 if err != nil {
10971139 t.Error(err)
10981140 }
11011143 hash := md5.New()
11021144 out2 := io.MultiWriter(out, buf, hash)
11031145 for i := 0; i < 100; i++ {
1104 fmt.Fprintf(out2, "%d %s\n", i, CONTENTS)
1146 _, _ = fmt.Fprintf(out2, "%d %s\n", i, CONTENTS)
11051147 }
11061148 // Ensure Headers fails if called prematurely
11071149 _, err = out.Headers()
11131155 t.Error(err)
11141156 }
11151157 expected := buf.String()
1116 contents, err := c.ObjectGetString(CONTAINER, OBJECT2)
1158 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT2)
11171159 if err != nil {
11181160 t.Error(err)
11191161 }
11371179 }
11381180
11391181 // Now with hash instead
1140 out, err = c.ObjectCreate(CONTAINER, OBJECT2, false, fmt.Sprintf("%x", hash.Sum(nil)), "", nil)
1182 out, err = c.ObjectCreate(ctx, CONTAINER, OBJECT2, false, fmt.Sprintf("%x", hash.Sum(nil)), "", nil)
11411183 if err != nil {
11421184 t.Fatal(err)
11431185 }
11491191 if err != nil {
11501192 t.Error(err)
11511193 }
1152 contents, err = c.ObjectGetString(CONTAINER, OBJECT2)
1194 contents, err = c.ObjectGetString(ctx, CONTAINER, OBJECT2)
11531195 if err != nil {
11541196 t.Error(err)
11551197 }
11581200 }
11591201
11601202 // Now with bad hash
1161 out, err = c.ObjectCreate(CONTAINER, OBJECT2, false, CONTENT_MD5, "", nil)
1203 out, err = c.ObjectCreate(ctx, CONTAINER, OBJECT2, false, CONTENT_MD5, "", nil)
11621204 if err != nil {
11631205 t.Fatal(err)
11641206 }
11651207 // FIXME: work around bug which produces 503 not 422 for empty corrupted files
1166 fmt.Fprintf(out, "Sausage")
1208 _, _ = fmt.Fprintf(out, "Sausage")
11671209 err = out.Close()
11681210 if err != swift.ObjectCorrupted {
11691211 t.Error("Expecting object corrupted not", err)
11711213 }
11721214
11731215 func TestObjectCreateAbort(t *testing.T) {
1216 ctx := context.Background()
11741217 c, rollback := makeConnectionWithContainer(t)
11751218 defer rollback()
11761219
1177 out, err := c.ObjectCreate(CONTAINER, OBJECT2, true, "", "", nil)
1220 out, err := c.ObjectCreate(ctx, CONTAINER, OBJECT2, true, "", "", nil)
11781221 if err != nil {
11791222 t.Fatal(err)
11801223 }
11811224 defer func() {
1182 _ = c.ObjectDelete(CONTAINER, OBJECT2) // Ignore error
1225 _ = c.ObjectDelete(ctx, CONTAINER, OBJECT2) // Ignore error
11831226 }()
11841227
11851228 expectedContents := "foo"
11941237 t.Errorf("Unexpected error %#v", err)
11951238 }
11961239
1197 _, err = c.ObjectGetString(CONTAINER, OBJECT2)
1240 _, err = c.ObjectGetString(ctx, CONTAINER, OBJECT2)
11981241 if err != swift.ObjectNotFound {
11991242 t.Errorf("Unexpected error: %#v", err)
12001243 }
12011244 }
12021245
12031246 func TestObjectGetString(t *testing.T) {
1247 ctx := context.Background()
12041248 c, rollback := makeConnectionWithObject(t)
12051249 defer rollback()
1206 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
1250 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
12071251 if err != nil {
12081252 t.Fatal(err)
12091253 }
12131257 }
12141258
12151259 func TestObjectGetBytes(t *testing.T) {
1260 ctx := context.Background()
12161261 c, rollback := makeConnectionWithObject(t)
12171262 defer rollback()
1218 contents, err := c.ObjectGetBytes(CONTAINER, OBJECT)
1263 contents, err := c.ObjectGetBytes(ctx, CONTAINER, OBJECT)
12191264 if err != nil {
12201265 t.Fatal(err)
12211266 }
12251270 }
12261271
12271272 func TestObjectOpen(t *testing.T) {
1273 ctx := context.Background()
12281274 c, rollback := makeConnectionWithObject(t)
12291275 defer rollback()
1230 file, _, err := c.ObjectOpen(CONTAINER, OBJECT, true, nil)
1276 file, _, err := c.ObjectOpen(ctx, CONTAINER, OBJECT, true, nil)
12311277 if err != nil {
12321278 t.Fatal(err)
12331279 }
12491295 }
12501296
12511297 func TestObjectOpenPartial(t *testing.T) {
1298 ctx := context.Background()
12521299 c, rollback := makeConnectionWithObject(t)
12531300 defer rollback()
1254 file, _, err := c.ObjectOpen(CONTAINER, OBJECT, true, nil)
1301 file, _, err := c.ObjectOpen(ctx, CONTAINER, OBJECT, true, nil)
12551302 if err != nil {
12561303 t.Fatal(err)
12571304 }
12731320 }
12741321
12751322 func TestObjectOpenLength(t *testing.T) {
1323 ctx := context.Background()
12761324 c, rollback := makeConnectionWithObject(t)
12771325 defer rollback()
1278 file, _, err := c.ObjectOpen(CONTAINER, OBJECT, true, nil)
1326 file, _, err := c.ObjectOpen(ctx, CONTAINER, OBJECT, true, nil)
12791327 if err != nil {
12801328 t.Fatal(err)
12811329 }
12821330 // FIXME ideally this would check both branches of the Length() code
1283 n, err := file.Length()
1331 n, err := file.Length(ctx)
12841332 if err != nil {
12851333 t.Fatal(err)
12861334 }
12941342 }
12951343
12961344 func TestObjectOpenNotModified(t *testing.T) {
1345 ctx := context.Background()
12971346 c, rollback := makeConnectionWithObject(t)
12981347 defer rollback()
1299 _, _, err := c.ObjectOpen(CONTAINER, OBJECT, true, swift.Headers{
1348 _, _, err := c.ObjectOpen(ctx, CONTAINER, OBJECT, true, swift.Headers{
13001349 "If-None-Match": CONTENT_MD5,
13011350 })
13021351 if err != swift.NotModified {
13051354 }
13061355
13071356 func TestObjectOpenSeek(t *testing.T) {
1357 ctx := context.Background()
13081358 c, rollback := makeConnectionWithObject(t)
13091359 defer rollback()
13101360
13301380 {2, -4, 1},
13311381 }
13321382
1333 file, _, err := c.ObjectOpen(CONTAINER, OBJECT, true, nil)
1383 file, _, err := c.ObjectOpen(ctx, CONTAINER, OBJECT, true, nil)
13341384 if err != nil {
13351385 t.Fatal(err)
13361386 }
13381388 for _, p := range plan {
13391389 if p.whence >= 0 {
13401390 var result int64
1341 result, err = file.Seek(p.offset, p.whence)
1391 result, err = file.Seek(ctx, p.offset, p.whence)
13421392 if err != nil {
13431393 t.Fatal(err, p)
13441394 }
13711421
13721422 // Test seeking to the end to find the file size
13731423 func TestObjectOpenSeekEnd(t *testing.T) {
1424 ctx := context.Background()
13741425 c, rollback := makeConnectionWithObject(t)
13751426 defer rollback()
1376 file, _, err := c.ObjectOpen(CONTAINER, OBJECT, true, nil)
1377 if err != nil {
1378 t.Fatal(err)
1379 }
1380 n, err := file.Seek(0, 2) // seek to end
1427 file, _, err := c.ObjectOpen(ctx, CONTAINER, OBJECT, true, nil)
1428 if err != nil {
1429 t.Fatal(err)
1430 }
1431 n, err := file.Seek(ctx, 0, 2) // seek to end
13811432 if err != nil {
13821433 t.Fatal(err)
13831434 }
13961447 }
13971448
13981449 // Now seek back to start and check we can read the file
1399 n, err = file.Seek(0, 0) // seek to start
1450 n, err = file.Seek(ctx, 0, 0) // seek to start
14001451 if err != nil {
14011452 t.Fatal(err)
14021453 }
14151466 }
14161467
14171468 func TestObjectUpdate(t *testing.T) {
1469 ctx := context.Background()
14181470 c, rollback := makeConnectionWithObject(t)
14191471 defer rollback()
1420 err := c.ObjectUpdate(CONTAINER, OBJECT, m1.ObjectHeaders())
1472 err := c.ObjectUpdate(ctx, CONTAINER, OBJECT, m1.ObjectHeaders())
14211473 if err != nil {
14221474 t.Fatal(err)
14231475 }
14311483 }
14321484
14331485 func TestObject(t *testing.T) {
1486 ctx := context.Background()
14341487 c, rollback := makeConnectionWithObjectHeaders(t)
14351488 defer rollback()
1436 object, headers, err := c.Object(CONTAINER, OBJECT)
1489 object, headers, err := c.Object(ctx, CONTAINER, OBJECT)
14371490 if err != nil {
14381491 t.Fatal(err)
14391492 }
14451498 }
14461499
14471500 func TestObjectUpdate2(t *testing.T) {
1501 ctx := context.Background()
14481502 c, rollback := makeConnectionWithObjectHeaders(t)
14491503 defer rollback()
1450 err := c.ObjectUpdate(CONTAINER, OBJECT, m2.ObjectHeaders())
1451 if err != nil {
1452 t.Fatal(err)
1453 }
1454 _, headers, err := c.Object(CONTAINER, OBJECT)
1504 err := c.ObjectUpdate(ctx, CONTAINER, OBJECT, m2.ObjectHeaders())
1505 if err != nil {
1506 t.Fatal(err)
1507 }
1508 _, headers, err := c.Object(ctx, CONTAINER, OBJECT)
14551509 if err != nil {
14561510 t.Fatal(err)
14571511 }
14591513 }
14601514
14611515 func TestContainers(t *testing.T) {
1516 ctx := context.Background()
14621517 c, rollback := makeConnectionWithObjectHeaders(t)
14631518 defer rollback()
1464 containers, err := c.Containers(nil)
1519 containers, err := c.Containers(ctx, nil)
14651520 if err != nil {
14661521 t.Fatal(err)
14671522 }
14871542 }
14881543
14891544 func TestObjectNames(t *testing.T) {
1545 ctx := context.Background()
14901546 c, rollback := makeConnectionWithObjectHeaders(t)
14911547 defer rollback()
1492 objects, err := c.ObjectNames(CONTAINER, nil)
1548 objects, err := c.ObjectNames(ctx, CONTAINER, nil)
14931549 if err != nil {
14941550 t.Fatal(err)
14951551 }
14991555 }
15001556
15011557 func TestObjectNamesAll(t *testing.T) {
1558 ctx := context.Background()
15021559 c, rollback := makeConnectionWithObjectHeaders(t)
15031560 defer rollback()
1504 objects, err := c.ObjectNamesAll(CONTAINER, nil)
1561 objects, err := c.ObjectNamesAll(ctx, CONTAINER, nil)
15051562 if err != nil {
15061563 t.Fatal(err)
15071564 }
15111568 }
15121569
15131570 func TestObjectNamesAllWithLimit(t *testing.T) {
1571 ctx := context.Background()
15141572 c, rollback := makeConnectionWithObjectHeaders(t)
15151573 defer rollback()
1516 objects, err := c.ObjectNamesAll(CONTAINER, &swift.ObjectsOpts{Limit: 1})
1574 objects, err := c.ObjectNamesAll(ctx, CONTAINER, &swift.ObjectsOpts{Limit: 1})
15171575 if err != nil {
15181576 t.Fatal(err)
15191577 }
15231581 }
15241582
15251583 func TestObjectsWalk(t *testing.T) {
1584 ctx := context.Background()
15261585 c, rollback := makeConnectionWithObjectHeaders(t)
15271586 defer rollback()
15281587 objects := make([]string, 0)
1529 err := c.ObjectsWalk(container, nil, func(opts *swift.ObjectsOpts) (interface{}, error) {
1530 newObjects, err := c.ObjectNames(CONTAINER, opts)
1588 err := c.ObjectsWalk(ctx, container, nil, func(ctx context.Context, opts *swift.ObjectsOpts) (interface{}, error) {
1589 newObjects, err := c.ObjectNames(ctx, CONTAINER, opts)
15311590 if err == nil {
15321591 objects = append(objects, newObjects...)
15331592 }
15421601 }
15431602
15441603 func TestObjects(t *testing.T) {
1604 ctx := context.Background()
15451605 c, rollback := makeConnectionWithObjectHeaders(t)
15461606 defer rollback()
1547 objects, err := c.Objects(CONTAINER, &swift.ObjectsOpts{Delimiter: '/'})
1607 objects, err := c.Objects(ctx, CONTAINER, &swift.ObjectsOpts{Delimiter: '/'})
15481608 if err != nil {
15491609 t.Fatal(err)
15501610 }
15591619 }
15601620
15611621 func TestObjectsDirectory(t *testing.T) {
1622 ctx := context.Background()
15621623 c, rollback := makeConnectionWithObjectHeaders(t)
15631624 defer rollback()
1564 err := c.ObjectPutString(CONTAINER, "directory", "", "application/directory")
1565 if err != nil {
1566 t.Fatal(err)
1567 }
1568 defer c.ObjectDelete(CONTAINER, "directory")
1625 err := c.ObjectPutString(ctx, CONTAINER, "directory", "", "application/directory")
1626 if err != nil {
1627 t.Fatal(err)
1628 }
1629 defer func() {
1630 _ = c.ObjectDelete(ctx, CONTAINER, "directory")
1631 }()
15691632
15701633 // Look for the directory object and check we aren't confusing
15711634 // it with a pseudo directory object
1572 objects, err := c.Objects(CONTAINER, &swift.ObjectsOpts{Delimiter: '/'})
1635 objects, err := c.Objects(ctx, CONTAINER, &swift.ObjectsOpts{Delimiter: '/'})
15731636 if err != nil {
15741637 t.Fatal(err)
15751638 }
15931656 }
15941657
15951658 func TestObjectsPseudoDirectory(t *testing.T) {
1659 ctx := context.Background()
15961660 c, rollback := makeConnectionWithObjectHeaders(t)
15971661 defer rollback()
1598 err := c.ObjectPutString(CONTAINER, "directory/puppy.jpg", "cute puppy", "")
1599 if err != nil {
1600 t.Fatal(err)
1601 }
1602 defer c.ObjectDelete(CONTAINER, "directory/puppy.jpg")
1662 err := c.ObjectPutString(ctx, CONTAINER, "directory/puppy.jpg", "cute puppy", "")
1663 if err != nil {
1664 t.Fatal(err)
1665 }
1666 defer func() {
1667 _ = c.ObjectDelete(ctx, CONTAINER, "directory/puppy.jpg")
1668 }()
16031669
16041670 // Look for the pseudo directory
1605 objects, err := c.Objects(CONTAINER, &swift.ObjectsOpts{Delimiter: '/'})
1671 objects, err := c.Objects(ctx, CONTAINER, &swift.ObjectsOpts{Delimiter: '/'})
16061672 if err != nil {
16071673 t.Fatal(err)
16081674 }
16241690 }
16251691
16261692 // Look in the pseudo directory now
1627 objects, err = c.Objects(CONTAINER, &swift.ObjectsOpts{Delimiter: '/', Path: "directory/"})
1693 objects, err = c.Objects(ctx, CONTAINER, &swift.ObjectsOpts{Delimiter: '/', Path: "directory/"})
16281694 if err != nil {
16291695 t.Fatal(err)
16301696 }
16391705 }
16401706
16411707 func TestObjectsAll(t *testing.T) {
1708 ctx := context.Background()
16421709 c, rollback := makeConnectionWithObjectHeaders(t)
16431710 defer rollback()
1644 objects, err := c.ObjectsAll(CONTAINER, nil)
1711 objects, err := c.ObjectsAll(ctx, CONTAINER, nil)
16451712 if err != nil {
16461713 t.Fatal(err)
16471714 }
16511718 }
16521719
16531720 func TestObjectsAllWithLimit(t *testing.T) {
1721 ctx := context.Background()
16541722 c, rollback := makeConnectionWithObjectHeaders(t)
16551723 defer rollback()
1656 objects, err := c.ObjectsAll(CONTAINER, &swift.ObjectsOpts{Limit: 1})
1724 objects, err := c.ObjectsAll(ctx, CONTAINER, &swift.ObjectsOpts{Limit: 1})
16571725 if err != nil {
16581726 t.Fatal(err)
16591727 }
16631731 }
16641732
16651733 func TestObjectNamesWithPath(t *testing.T) {
1734 ctx := context.Background()
16661735 c, rollback := makeConnectionWithObjectHeaders(t)
16671736 defer rollback()
1668 objects, err := c.ObjectNames(CONTAINER, &swift.ObjectsOpts{Delimiter: '/', Path: ""})
1737 objects, err := c.ObjectNames(ctx, CONTAINER, &swift.ObjectsOpts{Delimiter: '/', Path: ""})
16691738 if err != nil {
16701739 t.Fatal(err)
16711740 }
16731742 t.Error("Bad listing with path", objects)
16741743 }
16751744 // fmt.Println(objects)
1676 objects, err = c.ObjectNames(CONTAINER, &swift.ObjectsOpts{Delimiter: '/', Path: "Downloads/"})
1745 objects, err = c.ObjectNames(ctx, CONTAINER, &swift.ObjectsOpts{Delimiter: '/', Path: "Downloads/"})
16771746 if err != nil {
16781747 t.Fatal(err)
16791748 }
16831752 }
16841753
16851754 func TestObjectCopy(t *testing.T) {
1755 ctx := context.Background()
16861756 c, rollback := makeConnectionWithObjectHeaders(t)
16871757 defer rollback()
1688 _, err := c.ObjectCopy(CONTAINER, OBJECT, CONTAINER, OBJECT2, nil)
1689 if err != nil {
1690 t.Fatal(err)
1691 }
1692 err = c.ObjectDelete(CONTAINER, OBJECT2)
1758 _, err := c.ObjectCopy(ctx, CONTAINER, OBJECT, CONTAINER, OBJECT2, nil)
1759 if err != nil {
1760 t.Fatal(err)
1761 }
1762 err = c.ObjectDelete(ctx, CONTAINER, OBJECT2)
16931763 if err != nil {
16941764 t.Fatal(err)
16951765 }
16961766 }
16971767
16981768 func TestObjectCopyDifficultName(t *testing.T) {
1769 ctx := context.Background()
16991770 c, rollback := makeConnectionWithObjectHeaders(t)
17001771 defer rollback()
17011772 const dest = OBJECT + "?param %30%31%32 £100"
1702 _, err := c.ObjectCopy(CONTAINER, OBJECT, CONTAINER, dest, nil)
1703 if err != nil {
1704 t.Fatal(err)
1705 }
1706 err = c.ObjectDelete(CONTAINER, dest)
1773 _, err := c.ObjectCopy(ctx, CONTAINER, OBJECT, CONTAINER, dest, nil)
1774 if err != nil {
1775 t.Fatal(err)
1776 }
1777 err = c.ObjectDelete(ctx, CONTAINER, dest)
17071778 if err != nil {
17081779 t.Fatal(err)
17091780 }
17101781 }
17111782
17121783 func TestObjectCopyWithMetadata(t *testing.T) {
1784 ctx := context.Background()
17131785 c, rollback := makeConnectionWithObjectHeaders(t)
17141786 defer rollback()
17151787 m := swift.Metadata{}
17171789 m["hello"] = "9"
17181790 h := m.ObjectHeaders()
17191791 h["Content-Type"] = "image/jpeg"
1720 _, err := c.ObjectCopy(CONTAINER, OBJECT, CONTAINER, OBJECT2, h)
1792 _, err := c.ObjectCopy(ctx, CONTAINER, OBJECT, CONTAINER, OBJECT2, h)
17211793 if err != nil {
17221794 t.Fatal(err)
17231795 }
17241796 defer func() {
1725 err = c.ObjectDelete(CONTAINER, OBJECT2)
1797 err = c.ObjectDelete(ctx, CONTAINER, OBJECT2)
17261798 if err != nil {
17271799 t.Fatal(err)
17281800 }
17291801 }()
17301802 // Re-read the metadata to see if it is correct
1731 _, headers, err := c.Object(CONTAINER, OBJECT2)
1803 _, headers, err := c.Object(ctx, CONTAINER, OBJECT2)
17321804 if err != nil {
17331805 t.Fatal(err)
17341806 }
17391811 }
17401812
17411813 func TestObjectMove(t *testing.T) {
1814 ctx := context.Background()
17421815 c, rollback := makeConnectionWithObjectHeaders(t)
17431816 defer rollback()
1744 err := c.ObjectMove(CONTAINER, OBJECT, CONTAINER, OBJECT2)
1817 err := c.ObjectMove(ctx, CONTAINER, OBJECT, CONTAINER, OBJECT2)
17451818 if err != nil {
17461819 t.Fatal(err)
17471820 }
17481821 testExistenceAfterDelete(t, c, CONTAINER, OBJECT)
1749 _, _, err = c.Object(CONTAINER, OBJECT2)
1750 if err != nil {
1751 t.Fatal(err)
1752 }
1753
1754 err = c.ObjectMove(CONTAINER, OBJECT2, CONTAINER, OBJECT)
1822 _, _, err = c.Object(ctx, CONTAINER, OBJECT2)
1823 if err != nil {
1824 t.Fatal(err)
1825 }
1826
1827 err = c.ObjectMove(ctx, CONTAINER, OBJECT2, CONTAINER, OBJECT)
17551828 if err != nil {
17561829 t.Fatal(err)
17571830 }
17581831 testExistenceAfterDelete(t, c, CONTAINER, OBJECT2)
1759 _, headers, err := c.Object(CONTAINER, OBJECT)
1832 _, headers, err := c.Object(ctx, CONTAINER, OBJECT)
17601833 if err != nil {
17611834 t.Fatal(err)
17621835 }
17641837 }
17651838
17661839 func TestObjectUpdateContentType(t *testing.T) {
1840 ctx := context.Background()
17671841 c, rollback := makeConnectionWithObjectHeaders(t)
17681842 defer rollback()
1769 err := c.ObjectUpdateContentType(CONTAINER, OBJECT, "text/potato")
1843 err := c.ObjectUpdateContentType(ctx, CONTAINER, OBJECT, "text/potato")
17701844 if err != nil {
17711845 t.Fatal(err)
17721846 }
17731847 // Re-read the metadata to see if it is correct
1774 _, headers, err := c.Object(CONTAINER, OBJECT)
1848 _, headers, err := c.Object(ctx, CONTAINER, OBJECT)
17751849 if err != nil {
17761850 t.Fatal(err)
17771851 }
17821856 }
17831857
17841858 func TestVersionContainerCreate(t *testing.T) {
1859 ctx := context.Background()
17851860 c, rollback := makeConnectionAuth(t)
17861861 defer rollback()
1787 err := c.VersionContainerCreate(CURRENT_CONTAINER, VERSIONS_CONTAINER)
1862 err := c.VersionContainerCreate(ctx, CURRENT_CONTAINER, VERSIONS_CONTAINER)
17881863 defer func() {
1789 c.ContainerDelete(CURRENT_CONTAINER)
1790 c.ContainerDelete(VERSIONS_CONTAINER)
1864 _ = c.ContainerDelete(ctx, CURRENT_CONTAINER)
1865 _ = c.ContainerDelete(ctx, VERSIONS_CONTAINER)
17911866 }()
17921867 if err != nil {
17931868 if err == swift.Forbidden {
17991874 }
18001875
18011876 func TestVersionObjectAdd(t *testing.T) {
1877 ctx := context.Background()
18021878 c, rollback := makeConnectionWithVersionsContainer(t)
18031879 defer rollback()
18041880 if skipVersionTests {
18061882 return
18071883 }
18081884 // Version 1
1809 if err := c.ObjectPutString(CURRENT_CONTAINER, OBJECT, CONTENTS, ""); err != nil {
1885 if err := c.ObjectPutString(ctx, CURRENT_CONTAINER, OBJECT, CONTENTS, ""); err != nil {
18101886 t.Fatal(err)
18111887 }
18121888 defer func() {
1813 err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT)
1889 err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT)
18141890 if err != nil {
18151891 t.Fatal(err)
18161892 }
18171893 }()
1818 if contents, err := c.ObjectGetString(CURRENT_CONTAINER, OBJECT); err != nil {
1894 if contents, err := c.ObjectGetString(ctx, CURRENT_CONTAINER, OBJECT); err != nil {
18191895 t.Fatal(err)
18201896 } else if contents != CONTENTS {
18211897 t.Error("Contents wrong")
18221898 }
18231899
18241900 // Version 2
1825 if err := c.ObjectPutString(CURRENT_CONTAINER, OBJECT, CONTENTS2, ""); err != nil {
1901 if err := c.ObjectPutString(ctx, CURRENT_CONTAINER, OBJECT, CONTENTS2, ""); err != nil {
18261902 t.Fatal(err)
18271903 }
18281904 defer func() {
1829 err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT)
1905 err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT)
18301906 if err != nil {
18311907 t.Fatal(err)
18321908 }
18331909 }()
1834 if contents, err := c.ObjectGetString(CURRENT_CONTAINER, OBJECT); err != nil {
1910 if contents, err := c.ObjectGetString(ctx, CURRENT_CONTAINER, OBJECT); err != nil {
18351911 t.Fatal(err)
18361912 } else if contents != CONTENTS2 {
18371913 t.Error("Contents wrong")
18381914 }
18391915
18401916 // Version 3
1841 if err := c.ObjectPutString(CURRENT_CONTAINER, OBJECT, CONTENTS2, ""); err != nil {
1917 if err := c.ObjectPutString(ctx, CURRENT_CONTAINER, OBJECT, CONTENTS2, ""); err != nil {
18421918 t.Fatal(err)
18431919 }
18441920 defer func() {
1845 err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT)
1921 err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT)
18461922 if err != nil {
18471923 t.Fatal(err)
18481924 }
18501926 }
18511927
18521928 func TestVersionObjectList(t *testing.T) {
1929 ctx := context.Background()
18531930 c, rollback := makeConnectionWithVersionsObject(t)
18541931 defer rollback()
18551932 if skipVersionTests {
18561933 t.Log("Server doesn't support Versions - skipping test")
18571934 return
18581935 }
1859 list, err := c.VersionObjectList(VERSIONS_CONTAINER, OBJECT)
1936 list, err := c.VersionObjectList(ctx, VERSIONS_CONTAINER, OBJECT)
18601937 if err != nil {
18611938 t.Fatal(err)
18621939 }
18671944 }
18681945
18691946 func TestVersionObjectDelete(t *testing.T) {
1947 ctx := context.Background()
18701948 c, rollback := makeConnectionWithVersionsObject(t)
18711949 defer rollback()
18721950 if skipVersionTests {
18741952 return
18751953 }
18761954 // Delete Version 3
1877 if err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT); err != nil {
1955 if err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT); err != nil {
18781956 t.Fatal(err)
18791957 }
18801958
18811959 // Delete Version 2
1882 if err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT); err != nil {
1960 if err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT); err != nil {
18831961 t.Fatal(err)
18841962 }
18851963
18861964 // Contents should be reverted to Version 1
1887 if contents, err := c.ObjectGetString(CURRENT_CONTAINER, OBJECT); err != nil {
1965 if contents, err := c.ObjectGetString(ctx, CURRENT_CONTAINER, OBJECT); err != nil {
18881966 t.Fatal(err)
18891967 } else if contents != CONTENTS {
18901968 t.Error("Contents wrong")
18921970 }
18931971
18941972 func TestVersionDeleteContent(t *testing.T) {
1973 ctx := context.Background()
18951974 c, rollback := makeConnectionWithVersionsObject(t)
18961975 defer rollback()
18971976 if skipVersionTests {
18991978 return
19001979 }
19011980 // Delete Version 3
1902 if err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT); err != nil {
1981 if err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT); err != nil {
19031982 t.Fatal(err)
19041983 }
19051984 // Delete Version 2
1906 if err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT); err != nil {
1985 if err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT); err != nil {
19071986 t.Fatal(err)
19081987 }
19091988 // Delete Version 1
1910 if err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT); err != nil {
1911 t.Fatal(err)
1912 }
1913 if err := c.ObjectDelete(CURRENT_CONTAINER, OBJECT); err != swift.ObjectNotFound {
1989 if err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT); err != nil {
1990 t.Fatal(err)
1991 }
1992 if err := c.ObjectDelete(ctx, CURRENT_CONTAINER, OBJECT); err != swift.ObjectNotFound {
19141993 t.Fatalf("Expecting Object not found error, got: %v", err)
19151994 }
19161995 }
19181997 // Check for non existence after delete
19191998 // May have to do it a few times to wait for swift to be consistent.
19201999 func testExistenceAfterDelete(t *testing.T, c *swift.Connection, container, object string) {
2000 ctx := context.Background()
19212001 for i := 10; i <= 0; i-- {
1922 _, _, err := c.Object(container, object)
2002 _, _, err := c.Object(ctx, container, object)
19232003 if err == swift.ObjectNotFound {
19242004 break
19252005 }
19312011 }
19322012
19332013 func TestObjectDelete(t *testing.T) {
2014 ctx := context.Background()
19342015 c, rollback := makeConnectionWithObject(t)
19352016 defer rollback()
1936 err := c.ObjectDelete(CONTAINER, OBJECT)
2017 err := c.ObjectDelete(ctx, CONTAINER, OBJECT)
19372018 if err != nil {
19382019 t.Fatal(err)
19392020 }
19402021 testExistenceAfterDelete(t, c, CONTAINER, OBJECT)
1941 err = c.ObjectDelete(CONTAINER, OBJECT)
2022 err = c.ObjectDelete(ctx, CONTAINER, OBJECT)
19422023 if err != swift.ObjectNotFound {
19432024 t.Fatal("Expecting Object not found", err)
19442025 }
19452026 }
19462027
19472028 func TestBulkDelete(t *testing.T) {
2029 ctx := context.Background()
19482030 c, rollback := makeConnectionWithContainer(t)
19492031 defer rollback()
1950 result, err := c.BulkDelete(CONTAINER, []string{OBJECT})
2032 result, err := c.BulkDelete(ctx, CONTAINER, []string{OBJECT})
19512033 if err == swift.Forbidden {
19522034 t.Log("Server doesn't support BulkDelete - skipping test")
19532035 return
19612043 if result.NumberDeleted != 0 {
19622044 t.Error("Expected 0, actual:", result.NumberDeleted)
19632045 }
1964 err = c.ObjectPutString(CONTAINER, OBJECT, CONTENTS, "")
1965 if err != nil {
1966 t.Fatal(err)
1967 }
1968 result, err = c.BulkDelete(CONTAINER, []string{OBJECT2, OBJECT})
2046 err = c.ObjectPutString(ctx, CONTAINER, OBJECT, CONTENTS, "")
2047 if err != nil {
2048 t.Fatal(err)
2049 }
2050 result, err = c.BulkDelete(ctx, CONTAINER, []string{OBJECT2, OBJECT})
19692051 if err != nil {
19702052 t.Fatal(err)
19712053 }
19792061 }
19802062
19812063 func TestBulkUpload(t *testing.T) {
2064 ctx := context.Background()
19822065 c, rollback := makeConnectionWithContainer(t)
19832066 defer rollback()
19842067 buffer := new(bytes.Buffer)
20032086 t.Fatal(err)
20042087 }
20052088
2006 result, err := c.BulkUpload(CONTAINER, buffer, swift.UploadTar, nil)
2089 result, err := c.BulkUpload(ctx, CONTAINER, buffer, swift.UploadTar, nil)
20072090 if err == swift.Forbidden {
20082091 t.Log("Server doesn't support BulkUpload - skipping test")
20092092 return
20122095 t.Fatal(err)
20132096 }
20142097 defer func() {
2015 err = c.ObjectDelete(CONTAINER, OBJECT)
2016 if err != nil {
2017 t.Fatal(err)
2018 }
2019 err = c.ObjectDelete(CONTAINER, OBJECT2)
2098 err = c.ObjectDelete(ctx, CONTAINER, OBJECT)
2099 if err != nil {
2100 t.Fatal(err)
2101 }
2102 err = c.ObjectDelete(ctx, CONTAINER, OBJECT2)
20202103 if err != nil {
20212104 t.Fatal(err)
20222105 }
20262109 }
20272110 t.Log("Errors:", result.Errors)
20282111
2029 _, _, err = c.Object(CONTAINER, OBJECT)
2112 _, _, err = c.Object(ctx, CONTAINER, OBJECT)
20302113 if err != nil {
20312114 t.Error("Expecting object to be found")
20322115 }
2033 _, _, err = c.Object(CONTAINER, OBJECT2)
2116 _, _, err = c.Object(ctx, CONTAINER, OBJECT2)
20342117 if err != nil {
20352118 t.Error("Expecting object to be found")
20362119 }
20372120 }
20382121
20392122 func TestObjectDifficultName(t *testing.T) {
2123 ctx := context.Background()
20402124 c, rollback := makeConnectionWithContainer(t)
20412125 defer rollback()
20422126 const name = `hello? sausage/êé/Hello, 世界/ " ' @ < > & ?/`
2043 err := c.ObjectPutString(CONTAINER, name, CONTENTS, "")
2127 err := c.ObjectPutString(ctx, CONTAINER, name, CONTENTS, "")
20442128 if err != nil {
20452129 t.Fatal(err)
20462130 }
20472131 defer func() {
2048 err = c.ObjectDelete(CONTAINER, name)
2132 err = c.ObjectDelete(ctx, CONTAINER, name)
20492133 if err != nil {
20502134 t.Fatal(err)
20512135 }
20522136 }()
2053 objects, err := c.ObjectNamesAll(CONTAINER, nil)
2137 objects, err := c.ObjectNamesAll(ctx, CONTAINER, nil)
20542138 if err != nil {
20552139 t.Error(err)
20562140 }
20672151 }
20682152
20692153 func TestTempUrl(t *testing.T) {
2154 ctx := context.Background()
20702155 c, rollback := makeConnectionWithContainer(t)
20712156 defer rollback()
2072 err := c.ObjectPutBytes(CONTAINER, OBJECT, []byte(CONTENTS), "")
2157 err := c.ObjectPutBytes(ctx, CONTAINER, OBJECT, []byte(CONTENTS), "")
20732158 if err != nil {
20742159 t.Fatal(err)
20752160 }
20762161 defer func() {
2077 err = c.ObjectDelete(CONTAINER, OBJECT)
2162 err = c.ObjectDelete(ctx, CONTAINER, OBJECT)
20782163 if err != nil {
20792164 t.Fatal(err)
20802165 }
20822167
20832168 m := swift.Metadata{}
20842169 m["temp-url-key"] = SECRET_KEY
2085 err = c.AccountUpdate(m.AccountHeaders())
2170 err = c.AccountUpdate(ctx, m.AccountHeaders())
20862171 if err != nil {
20872172 t.Fatal(err)
20882173 }
20932178 if err != nil {
20942179 t.Fatal("Failed to retrieve file from temporary url")
20952180 }
2096 defer resp.Body.Close()
2181 defer func() {
2182 err := resp.Body.Close()
2183 if err != nil {
2184 t.Error("Close failed", err)
2185 }
2186 }()
20972187 if resp.StatusCode == 401 {
20982188 t.Log("Server doesn't support tempurl")
20992189 } else if resp.StatusCode != 200 {
21082198 if err != nil {
21092199 t.Fatal("Failed to retrieve file from temporary url")
21102200 }
2111 defer resp.Body.Close()
2201 defer func() {
2202 err := resp.Body.Close()
2203 if err != nil {
2204 t.Error("Close failed", err)
2205 }
2206 }()
21122207 if resp.StatusCode != 401 {
21132208 t.Fatal("Expecting server to forbid access to object")
21142209 }
21162211 }
21172212
21182213 func TestQueryInfo(t *testing.T) {
2214 ctx := context.Background()
21192215 c, rollback := makeConnectionAuth(t)
21202216 defer rollback()
2121 infos, err := c.QueryInfo()
2217 infos, err := c.QueryInfo(ctx)
21222218 if err != nil {
21232219 t.Log("Server doesn't support querying info")
21242220 return
21292225 }
21302226
21312227 func TestDLOCreate(t *testing.T) {
2228 ctx := context.Background()
21322229 c, rollback := makeConnectionWithSegmentsContainer(t)
21332230 defer rollback()
21342231
21372234 ObjectName: OBJECT,
21382235 ContentType: "image/jpeg",
21392236 }
2140 out, err := c.DynamicLargeObjectCreate(&opts)
2237 out, err := c.DynamicLargeObjectCreate(ctx, &opts)
21412238 if err != nil {
21422239 t.Fatal(err)
21432240 }
21442241 defer func() {
2145 err = c.DynamicLargeObjectDelete(CONTAINER, OBJECT)
2242 err = c.DynamicLargeObjectDelete(ctx, CONTAINER, OBJECT)
21462243 if err != nil {
21472244 t.Fatal(err)
21482245 }
21562253 t.Fatal(err)
21572254 }
21582255 }
2159 err = out.Close()
2256 err = out.CloseWithContext(ctx)
21602257 if err != nil {
21612258 t.Error(err)
21622259 }
21632260 expected := buf.String()
2164 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2261 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
21652262 if err != nil {
21662263 t.Error(err)
21672264 }
21682265 if contents != expected {
21692266 t.Errorf("Contents wrong, expected %q, got: %q", expected, contents)
21702267 }
2171 info, _, err := c.Object(CONTAINER, OBJECT)
2268 info, _, err := c.Object(ctx, CONTAINER, OBJECT)
21722269 if err != nil {
21732270 t.Fatal(err)
21742271 }
21812278 }
21822279
21832280 func TestDLOInsert(t *testing.T) {
2281 ctx := context.Background()
21842282 c, rollback := makeConnectionWithDLO(t)
21852283 defer rollback()
21862284 opts := swift.LargeObjectOpts{
21892287 CheckHash: true,
21902288 ContentType: "image/jpeg",
21912289 }
2192 out, err := c.DynamicLargeObjectCreateFile(&opts)
2290 out, err := c.DynamicLargeObjectCreateFile(ctx, &opts)
21932291 if err != nil {
21942292 t.Fatal(err)
21952293 }
22002298 if err != nil {
22012299 t.Fatal(err)
22022300 }
2203 fmt.Fprintf(buf, "\n%d %s\n", 1, CONTENTS)
2204 err = out.Close()
2301 _, _ = fmt.Fprintf(buf, "\n%d %s\n", 1, CONTENTS)
2302 err = out.CloseWithContext(ctx)
22052303 if err != nil {
22062304 t.Error(err)
22072305 }
22082306 expected := buf.String()
2209 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2307 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
22102308 if err != nil {
22112309 t.Error(err)
22122310 }
22162314 }
22172315
22182316 func TestDLOAppend(t *testing.T) {
2317 ctx := context.Background()
22192318 c, rollback := makeConnectionWithDLO(t)
22202319 defer rollback()
22212320 opts := swift.LargeObjectOpts{
22252324 CheckHash: true,
22262325 ContentType: "image/jpeg",
22272326 }
2228 out, err := c.DynamicLargeObjectCreateFile(&opts)
2229 if err != nil {
2230 t.Fatal(err)
2231 }
2232
2233 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2327 out, err := c.DynamicLargeObjectCreateFile(ctx, &opts)
2328 if err != nil {
2329 t.Fatal(err)
2330 }
2331
2332 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
2333 if err != nil {
2334 t.Fatal(err)
2335 }
22342336 buf := bytes.NewBuffer([]byte(contents))
22352337 multi := io.MultiWriter(buf, out)
22362338 for i := 0; i < 2; i++ {
22392341 t.Fatal(err)
22402342 }
22412343 }
2242 err = out.Close()
2344 err = out.CloseWithContext(ctx)
22432345 if err != nil {
22442346 t.Error(err)
22452347 }
22462348 expected := buf.String()
2247 contents, err = c.ObjectGetString(CONTAINER, OBJECT)
2349 contents, err = c.ObjectGetString(ctx, CONTAINER, OBJECT)
22482350 if err != nil {
22492351 t.Error(err)
22502352 }
22542356 }
22552357
22562358 func TestDLOTruncate(t *testing.T) {
2359 ctx := context.Background()
22572360 c, rollback := makeConnectionWithDLO(t)
22582361 defer rollback()
22592362 opts := swift.LargeObjectOpts{
22632366 CheckHash: true,
22642367 ContentType: "image/jpeg",
22652368 }
2266 out, err := c.DynamicLargeObjectCreateFile(&opts)
2369 out, err := c.DynamicLargeObjectCreateFile(ctx, &opts)
22672370 if err != nil {
22682371 t.Fatal(err)
22692372 }
22742377 if err != nil {
22752378 t.Fatal(err)
22762379 }
2277 err = out.Close()
2380 err = out.CloseWithContext(ctx)
22782381 if err != nil {
22792382 t.Error(err)
22802383 }
22812384 expected := buf.String()
2282 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2385 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
22832386 if err != nil {
22842387 t.Error(err)
22852388 }
22892392 }
22902393
22912394 func TestDLOMove(t *testing.T) {
2395 ctx := context.Background()
22922396 c, rollback := makeConnectionWithDLO(t)
22932397 defer rollback()
2294 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2295 if err != nil {
2296 t.Fatal(err)
2297 }
2298
2299 err = c.DynamicLargeObjectMove(CONTAINER, OBJECT, CONTAINER, OBJECT2)
2398 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
2399 if err != nil {
2400 t.Fatal(err)
2401 }
2402
2403 err = c.DynamicLargeObjectMove(ctx, CONTAINER, OBJECT, CONTAINER, OBJECT2)
23002404 if err != nil {
23012405 t.Fatal(err)
23022406 }
23032407 defer func() {
2304 err = c.DynamicLargeObjectDelete(CONTAINER, OBJECT2)
2408 err = c.DynamicLargeObjectDelete(ctx, CONTAINER, OBJECT2)
23052409 if err != nil {
23062410 t.Fatal(err)
23072411 }
23082412 }()
23092413
2310 contents2, err := c.ObjectGetString(CONTAINER, OBJECT2)
2414 contents2, err := c.ObjectGetString(ctx, CONTAINER, OBJECT2)
23112415 if err != nil {
23122416 t.Fatal(err)
23132417 }
23182422 }
23192423
23202424 func TestDLONoSegmentContainer(t *testing.T) {
2425 ctx := context.Background()
23212426 c, rollback := makeConnectionWithDLO(t)
23222427 defer rollback()
23232428 opts := swift.LargeObjectOpts{
23262431 ContentType: "image/jpeg",
23272432 SegmentContainer: CONTAINER,
23282433 }
2329 out, err := c.DynamicLargeObjectCreate(&opts)
2434 out, err := c.DynamicLargeObjectCreate(ctx, &opts)
23302435 if err != nil {
23312436 t.Fatal(err)
23322437 }
23392444 t.Fatal(err)
23402445 }
23412446 }
2342 err = out.Close()
2447 err = out.CloseWithContext(ctx)
23432448 if err != nil {
23442449 t.Error(err)
23452450 }
23462451 expected := buf.String()
2347 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2452 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
23482453 if err != nil {
23492454 t.Error(err)
23502455 }
23542459 }
23552460
23562461 func TestDLOCreateMissingSegmentsInList(t *testing.T) {
2462 ctx := context.Background()
23572463 c, rollback := makeConnectionWithContainer(t)
23582464 defer rollback()
23592465
23682474 w.Header().Set(k, v[0])
23692475 }
23702476 w.WriteHeader(recorder.Code)
2371 w.Write([]byte("null\n"))
2477 _, _ = w.Write([]byte("null\n"))
23722478 })
23732479 defer srv.UnsetOverride(listURL)
23742480
23752481 headers := swift.Headers{}
2376 err := c.ContainerCreate(SEGMENTS_CONTAINER, headers)
2482 err := c.ContainerCreate(ctx, SEGMENTS_CONTAINER, headers)
23772483 if err != nil {
23782484 t.Fatal(err)
23792485 }
23802486 defer func() {
2381 err = c.ContainerDelete(SEGMENTS_CONTAINER)
2487 err = c.ContainerDelete(ctx, SEGMENTS_CONTAINER)
23822488 if err != nil {
23832489 t.Fatal(err)
23842490 }
23892495 ObjectName: OBJECT,
23902496 ContentType: "image/jpeg",
23912497 }
2392 out, err := c.DynamicLargeObjectCreate(&opts)
2498 out, err := c.DynamicLargeObjectCreate(ctx, &opts)
23932499 if err != nil {
23942500 t.Fatal(err)
23952501 }
23962502 defer func() {
2397 err = c.DynamicLargeObjectDelete(CONTAINER, OBJECT)
2503 err = c.DynamicLargeObjectDelete(ctx, CONTAINER, OBJECT)
23982504 if err != nil {
23992505 t.Fatal(err)
24002506 }
24082514 t.Fatal(err)
24092515 }
24102516 }
2411 err = out.Close()
2517 err = out.CloseWithContext(ctx)
24122518 if err != nil {
24132519 t.Error(err)
24142520 }
24152521 expected := buf.String()
2416 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2522 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
24172523 if err != nil {
24182524 t.Error(err)
24192525 }
24232529 }
24242530
24252531 func TestDLOCreateIncorrectSize(t *testing.T) {
2532 ctx := context.Background()
24262533 c, rollback := makeConnectionWithContainer(t)
24272534 defer rollback()
24282535
24452552 }
24462553 }
24472554 w.WriteHeader(recorder.Code)
2448 w.Write(recorder.Body.Bytes())
2555 _, _ = w.Write(recorder.Body.Bytes())
24492556 })
24502557 defer srv.UnsetOverride(listURL)
24512558
24522559 headers := swift.Headers{}
2453 err := c.ContainerCreate(SEGMENTS_CONTAINER, headers)
2560 err := c.ContainerCreate(ctx, SEGMENTS_CONTAINER, headers)
24542561 if err != nil {
24552562 t.Fatal(err)
24562563 }
24572564 defer func() {
2458 err = c.ContainerDelete(SEGMENTS_CONTAINER)
2565 err = c.ContainerDelete(ctx, SEGMENTS_CONTAINER)
24592566 if err != nil {
24602567 t.Fatal(err)
24612568 }
24662573 ObjectName: OBJECT,
24672574 ContentType: "image/jpeg",
24682575 }
2469 out, err := c.DynamicLargeObjectCreate(&opts)
2576 out, err := c.DynamicLargeObjectCreate(ctx, &opts)
24702577 if err != nil {
24712578 t.Fatal(err)
24722579 }
24732580 defer func() {
2474 err = c.DynamicLargeObjectDelete(CONTAINER, OBJECT)
2581 err = c.DynamicLargeObjectDelete(ctx, CONTAINER, OBJECT)
24752582 if err != nil {
24762583 t.Fatal(err)
24772584 }
24842591 t.Fatal(err)
24852592 }
24862593 }
2487 err = out.Close()
2594 err = out.CloseWithContext(ctx)
24882595 if err != nil {
24892596 t.Error(err)
24902597 }
24922599 t.Errorf("Unexpected HEAD requests count, expected %d, got: %d", expectedHeadCount, headCount)
24932600 }
24942601 expected := buf.String()
2495 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2602 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
24962603 if err != nil {
24972604 t.Error(err)
24982605 }
25022609 }
25032610
25042611 func TestDLOConcurrentWrite(t *testing.T) {
2612 ctx := context.Background()
25052613 c, rollback := makeConnectionWithSegmentsContainer(t)
25062614 defer rollback()
25072615
25162624 ObjectName: objName,
25172625 ContentType: "image/jpeg",
25182626 }
2519 out, err := c.DynamicLargeObjectCreate(&opts)
2627 out, err := c.DynamicLargeObjectCreate(ctx, &opts)
25202628 if err != nil {
25212629 t.Fatal(err)
25222630 }
25232631 defer func() {
2524 err = c.DynamicLargeObjectDelete(CONTAINER, objName)
2632 err = c.DynamicLargeObjectDelete(ctx, CONTAINER, objName)
25252633 if err != nil {
25262634 t.Fatal(err)
25272635 }
25432651 t.Fatalf("expected to write %d, got: %d", chunkSize, n)
25442652 }
25452653 }
2546 err = out.Close()
2654 err = out.CloseWithContext(ctx)
25472655 if err != nil {
25482656 t.Error(err)
25492657 }
25502658 expected := buf.String()
2551 contents, err := c.ObjectGetString(CONTAINER, objName)
2659 contents, err := c.ObjectGetString(ctx, CONTAINER, objName)
25522660 if err != nil {
25532661 t.Error(err)
25542662 }
25692677 }
25702678
25712679 func TestDLOSegmentation(t *testing.T) {
2680 ctx := context.Background()
25722681 c, rollback := makeConnectionWithSegmentsContainer(t)
25732682 defer rollback()
25742683
25812690 }
25822691
25832692 testSegmentation(t, c, func() swift.LargeObjectFile {
2584 out, err := c.DynamicLargeObjectCreate(&opts)
2693 out, err := c.DynamicLargeObjectCreate(ctx, &opts)
25852694 if err != nil {
25862695 t.Fatal(err)
25872696 }
26242733 }
26252734
26262735 func TestDLOSegmentationBuffered(t *testing.T) {
2736 ctx := context.Background()
26272737 c, rollback := makeConnectionWithSegmentsContainer(t)
26282738 defer rollback()
26292739
26352745 }
26362746
26372747 testSegmentation(t, c, func() swift.LargeObjectFile {
2638 out, err := c.DynamicLargeObjectCreate(&opts)
2748 out, err := c.DynamicLargeObjectCreate(ctx, &opts)
26392749 if err != nil {
26402750 t.Fatal(err)
26412751 }
26782788 }
26792789
26802790 func TestSLOCreate(t *testing.T) {
2791 ctx := context.Background()
26812792 c, rollback := makeConnectionWithSegmentsContainer(t)
26822793 defer rollback()
26832794
26862797 ObjectName: OBJECT,
26872798 ContentType: "image/jpeg",
26882799 }
2689 out, err := c.StaticLargeObjectCreate(&opts)
2800 out, err := c.StaticLargeObjectCreate(ctx, &opts)
26902801 if err != nil {
26912802 if err == swift.SLONotSupported {
26922803 t.Skip("SLO not supported")
26952806 t.Fatal(err)
26962807 }
26972808 defer func() {
2698 err = c.StaticLargeObjectDelete(CONTAINER, OBJECT)
2809 err = c.StaticLargeObjectDelete(ctx, CONTAINER, OBJECT)
26992810 if err != nil {
27002811 t.Fatal(err)
27012812 }
27092820 t.Fatal(err)
27102821 }
27112822 }
2712 err = out.Close()
2823 err = out.CloseWithContext(ctx)
27132824 if err != nil {
27142825 t.Error(err)
27152826 }
27162827 expected := buf.String()
2717 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2828 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
27182829 if err != nil {
27192830 t.Error(err)
27202831 }
27212832 if contents != expected {
27222833 t.Errorf("Contents wrong, expected %q, got: %q", expected, contents)
27232834 }
2724 info, _, err := c.Object(CONTAINER, OBJECT)
2835 info, _, err := c.Object(ctx, CONTAINER, OBJECT)
27252836 if err != nil {
27262837 t.Fatal(err)
27272838 }
27342845 }
27352846
27362847 func TestSLOInsert(t *testing.T) {
2848 ctx := context.Background()
27372849 c, rollback := makeConnectionWithSLO(t)
27382850 defer rollback()
27392851 opts := swift.LargeObjectOpts{
27412853 ObjectName: OBJECT,
27422854 ContentType: "image/jpeg",
27432855 }
2744 out, err := c.StaticLargeObjectCreateFile(&opts)
2856 out, err := c.StaticLargeObjectCreateFile(ctx, &opts)
27452857 if err != nil {
27462858 t.Fatal(err)
27472859 }
27522864 if err != nil {
27532865 t.Fatal(err)
27542866 }
2755 fmt.Fprintf(buf, "\n%d %s\n", 1, CONTENTS)
2756 err = out.Close()
2867 _, _ = fmt.Fprintf(buf, "\n%d %s\n", 1, CONTENTS)
2868 err = out.CloseWithContext(ctx)
27572869 if err != nil {
27582870 t.Error(err)
27592871 }
27602872 expected := buf.String()
2761 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2873 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
27622874 if err != nil {
27632875 t.Error(err)
27642876 }
27682880 }
27692881
27702882 func TestSLOAppend(t *testing.T) {
2883 ctx := context.Background()
27712884 c, rollback := makeConnectionWithSLO(t)
27722885 defer rollback()
27732886 opts := swift.LargeObjectOpts{
27772890 CheckHash: true,
27782891 ContentType: "image/jpeg",
27792892 }
2780 out, err := c.StaticLargeObjectCreateFile(&opts)
2781 if err != nil {
2782 t.Fatal(err)
2783 }
2784
2785 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2893 out, err := c.StaticLargeObjectCreateFile(ctx, &opts)
2894 if err != nil {
2895 t.Fatal(err)
2896 }
2897
2898 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
2899 if err != nil {
2900 t.Fatal(err)
2901 }
27862902 buf := bytes.NewBuffer([]byte(contents))
27872903 multi := io.MultiWriter(buf, out)
27882904 for i := 0; i < 2; i++ {
27912907 t.Fatal(err)
27922908 }
27932909 }
2794 err = out.Close()
2910 err = out.CloseWithContext(ctx)
27952911 if err != nil {
27962912 t.Error(err)
27972913 }
27982914 expected := buf.String()
2799 contents, err = c.ObjectGetString(CONTAINER, OBJECT)
2915 contents, err = c.ObjectGetString(ctx, CONTAINER, OBJECT)
28002916 if err != nil {
28012917 t.Error(err)
28022918 }
28062922 }
28072923
28082924 func TestSLOMove(t *testing.T) {
2925 ctx := context.Background()
28092926 c, rollback := makeConnectionWithSLO(t)
28102927 defer rollback()
2811 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2812 if err != nil {
2813 t.Fatal(err)
2814 }
2815
2816 err = c.StaticLargeObjectMove(CONTAINER, OBJECT, CONTAINER, OBJECT2)
2928 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
2929 if err != nil {
2930 t.Fatal(err)
2931 }
2932
2933 err = c.StaticLargeObjectMove(ctx, CONTAINER, OBJECT, CONTAINER, OBJECT2)
28172934 if err != nil {
28182935 t.Fatal(err)
28192936 }
28202937 defer func() {
2821 err = c.StaticLargeObjectDelete(CONTAINER, OBJECT2)
2938 err = c.StaticLargeObjectDelete(ctx, CONTAINER, OBJECT2)
28222939 if err != nil {
28232940 t.Fatal(err)
28242941 }
28252942 }()
28262943
2827 contents2, err := c.ObjectGetString(CONTAINER, OBJECT2)
2944 contents2, err := c.ObjectGetString(ctx, CONTAINER, OBJECT2)
28282945 if err != nil {
28292946 t.Fatal(err)
28302947 }
28352952 }
28362953
28372954 func TestSLONoSegmentContainer(t *testing.T) {
2955 ctx := context.Background()
28382956 c, rollback := makeConnectionWithSLO(t)
28392957 defer rollback()
28402958
28442962 ContentType: "image/jpeg",
28452963 SegmentContainer: CONTAINER,
28462964 }
2847 out, err := c.StaticLargeObjectCreate(&opts)
2965 out, err := c.StaticLargeObjectCreate(ctx, &opts)
28482966 if err != nil {
28492967 t.Fatal(err)
28502968 }
28572975 t.Fatal(err)
28582976 }
28592977 }
2860 err = out.Close()
2978 err = out.CloseWithContext(ctx)
28612979 if err != nil {
28622980 t.Error(err)
28632981 }
28642982 expected := buf.String()
2865 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
2983 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
28662984 if err != nil {
28672985 t.Error(err)
28682986 }
28702988 t.Errorf("Contents wrong, expected %q, got: %q", expected, contents)
28712989 }
28722990
2873 err = c.StaticLargeObjectDelete(CONTAINER, OBJECT)
2991 err = c.StaticLargeObjectDelete(ctx, CONTAINER, OBJECT)
28742992 if err != nil {
28752993 t.Fatal(err)
28762994 }
28772995 }
28782996
28792997 func TestSLOMinChunkSize(t *testing.T) {
2998 ctx := context.Background()
28802999 c, rollback := makeConnectionWithSegmentsContainer(t)
28813000 defer rollback()
28823001 if srv == nil {
28853004 }
28863005
28873006 srv.SetOverride("/info", func(w http.ResponseWriter, r *http.Request, recorder *httptest.ResponseRecorder) {
2888 w.Write([]byte(`{"slo": {"min_segment_size": 4}}`))
3007 _, _ = w.Write([]byte(`{"slo": {"min_segment_size": 4}}`))
28893008 })
28903009 defer srv.UnsetOverride("/info")
2891 c.QueryInfo()
3010 _, _ = c.QueryInfo(ctx)
28923011
28933012 opts := swift.LargeObjectOpts{
28943013 Container: CONTAINER,
29003019 }
29013020
29023021 testSLOSegmentation(t, c, func() swift.LargeObjectFile {
2903 out, err := c.StaticLargeObjectCreate(&opts)
3022 out, err := c.StaticLargeObjectCreate(ctx, &opts)
29043023 if err != nil {
29053024 t.Fatal(err)
29063025 }
29093028 }
29103029
29113030 func TestSLOSegmentation(t *testing.T) {
3031 ctx := context.Background()
29123032 c, rollback := makeConnectionWithSegmentsContainer(t)
29133033 defer rollback()
29143034 opts := swift.LargeObjectOpts{
29203040 NoBuffer: true,
29213041 }
29223042 testSLOSegmentation(t, c, func() swift.LargeObjectFile {
2923 out, err := c.StaticLargeObjectCreate(&opts)
3043 out, err := c.StaticLargeObjectCreate(ctx, &opts)
29243044 if err != nil {
29253045 if err == swift.SLONotSupported {
29263046 t.Skip("SLO not supported")
29323052 }
29333053
29343054 func TestSLOSegmentationBuffered(t *testing.T) {
3055 ctx := context.Background()
29353056 c, rollback := makeConnectionWithSegmentsContainer(t)
29363057 defer rollback()
29373058 opts := swift.LargeObjectOpts{
29423063 MinChunkSize: 4,
29433064 }
29443065 testSegmentation(t, c, func() swift.LargeObjectFile {
2945 out, err := c.StaticLargeObjectCreate(&opts)
3066 out, err := c.StaticLargeObjectCreate(ctx, &opts)
29463067 if err != nil {
29473068 if err == swift.SLONotSupported {
29483069 t.Skip("SLO not supported")
30343155 }
30353156
30363157 func testSegmentation(t *testing.T, c *swift.Connection, createObj func() swift.LargeObjectFile, testCases []segmentTest) {
3158 ctx := context.Background()
30373159 var err error
30383160 runTestCase := func(tCase segmentTest) {
30393161 out := createObj()
30403162 defer func() {
3041 err = c.LargeObjectDelete(CONTAINER, OBJECT)
3163 err = c.LargeObjectDelete(ctx, CONTAINER, OBJECT)
30423164 if err != nil {
30433165 t.Fatal(err)
30443166 }
30553177 }
30563178 }
30573179 }
3058 err = out.Close()
3180 err = out.CloseWithContext(ctx)
30593181 if err != nil {
30603182 t.Error(err)
30613183 }
3062 contents, err := c.ObjectGetString(CONTAINER, OBJECT)
3184 contents, err := c.ObjectGetString(ctx, CONTAINER, OBJECT)
30633185 if err != nil {
30643186 t.Error(err)
30653187 }
30663188 if contents != tCase.expectedValue {
30673189 t.Errorf("Contents wrong, expected %q, got: %q", tCase.expectedValue, contents)
30683190 }
3069 container, objects, err := c.LargeObjectGetSegments(CONTAINER, OBJECT)
3191 container, objects, err := c.LargeObjectGetSegments(ctx, CONTAINER, OBJECT)
30703192 if err != nil {
30713193 t.Error(err)
30723194 }
30733195 if container != SEGMENTS_CONTAINER {
30743196 t.Errorf("Segments container wrong, expected %q, got: %q", SEGMENTS_CONTAINER, container)
30753197 }
3076 _, headers, err := c.Object(CONTAINER, OBJECT)
3198 _, headers, err := c.Object(ctx, CONTAINER, OBJECT)
30773199 if err != nil {
30783200 t.Fatal(err)
30793201 }
30803202 if headers.IsLargeObjectSLO() {
30813203 var info swift.SwiftInfo
3082 info, err = c.QueryInfo()
3204 info, err = c.QueryInfo(ctx)
30833205 if err != nil {
30843206 t.Fatal(err)
30853207 }
30913213 var segContents []string
30923214 for _, obj := range objects {
30933215 var value string
3094 value, err = c.ObjectGetString(SEGMENTS_CONTAINER, obj.Name)
3216 value, err = c.ObjectGetString(ctx, SEGMENTS_CONTAINER, obj.Name)
30953217 if err != nil {
30963218 t.Error(err)
30973219 }
31073229 }
31083230
31093231 func TestContainerDelete(t *testing.T) {
3232 ctx := context.Background()
31103233 c, rollback := makeConnectionWithContainer(t)
31113234 defer rollback()
3112 err := c.ContainerDelete(CONTAINER)
3113 if err != nil {
3114 t.Fatal(err)
3115 }
3116 err = c.ContainerDelete(CONTAINER)
3235 err := c.ContainerDelete(ctx, CONTAINER)
3236 if err != nil {
3237 t.Fatal(err)
3238 }
3239 err = c.ContainerDelete(ctx, CONTAINER)
31173240 if err != swift.ContainerNotFound {
31183241 t.Fatal("Expecting container not found", err)
31193242 }
3120 _, _, err = c.Container(CONTAINER)
3243 _, _, err = c.Container(ctx, CONTAINER)
31213244 if err != swift.ContainerNotFound {
31223245 t.Fatal("Expecting container not found", err)
31233246 }
31243247 }
31253248
31263249 func TestUnAuthenticate(t *testing.T) {
3250 ctx := context.Background()
31273251 c, rollback := makeConnectionAuth(t)
31283252 defer rollback()
31293253 c.UnAuthenticate()
31313255 t.Fatal("Shouldn't be authenticated")
31323256 }
31333257 // Test re-authenticate
3134 err := c.Authenticate()
3258 err := c.Authenticate(ctx)
31353259 if err != nil {
31363260 t.Fatal("ReAuth failed", err)
31373261 }
3333 "strings"
3434 "sync"
3535 "sync/atomic"
36 "testing"
3736 "time"
3837 )
3938
5049 // See https://golang.org/pkg/sync/atomic/#pkg-note-BUG for more details.
5150 reqId int64
5251 sync.RWMutex
53 t *testing.T
54 mu sync.Mutex
5552 Listener net.Listener
5653 AuthURL string
5754 URL string
144141 sync.RWMutex
145142 metadata
146143 name string
147 ctime time.Time
148144 objects map[string]*object
149145 }
150146
187183 container *container // non-nil if the container already exists.
188184 }
189185
190 var responseParams = map[string]bool{
191 "content-type": true,
192 "content-language": true,
193 "expires": true,
194 "cache-control": true,
195 "content-disposition": true,
196 "content-encoding": true,
197 }
198
199186 func fatalf(code int, codeStr string, errf string, a ...interface{}) {
200187 panic(&swiftError{
201188 statusCode: code,
318305 } else {
319306 for _, item := range objects {
320307 if obj, ok := item.(*object); ok {
321 a.w.Write([]byte(obj.name + "\n"))
308 _, err := a.w.Write([]byte(obj.name + "\n"))
309 if err != nil {
310 fatalf(500, "WriteFailed", "Write failed")
311 }
322312 } else if subdir, ok := item.(Subdir); ok {
323 a.w.Write([]byte(subdir.Subdir + "\n"))
313 _, err := a.w.Write([]byte(subdir.Subdir + "\n"))
314 if err != nil {
315 fatalf(500, "WriteFailed", "Write failed")
316 }
324317 }
325318 }
326319 return nil
397390 if err != nil {
398391 fatalf(400, "TODO", "Invalid tar.gz")
399392 }
400 defer gzr.Close()
393 defer func() {
394 err := gzr.Close()
395 if err != nil {
396 fatalf(400, "CloseFailed", "Close failed")
397 }
398 }()
401399 reader = tar.NewReader(gzr)
402400 case "tar.bz2":
403401 bzr := bzip2.NewReader(dataReader)
659657 } else if value, ok := obj.meta["X-Static-Large-Object"]; ok && value[0] == "True" && a.req.URL.Query().Get("multipart-manifest") != "get" {
660658 var segments []io.Reader
661659 var segmentList []segment
662 json.Unmarshal(obj.data, &segmentList)
660 err := json.Unmarshal(obj.data, &segmentList)
661 if err != nil {
662 fatalf(400, "BadParameters", "Unmarshal failed.")
663 }
663664 cursor := 0
664665 size := 0
665666 sum := md5.New()
768769 a.req.Header.Set("X-Static-Large-Object", "True")
769770
770771 var segments []segment
771 json.Unmarshal(data, &segments)
772 err := json.Unmarshal(data, &segments)
773 if err != nil {
774 fatalf(400, "BadParameters", "Unmarshal failed.")
775 }
772776 for i := range segments {
773777 segments[i].Name = "/" + segments[i].Path
774778 segments[i].Path = ""
900904
901905 func (s *SwiftServer) serveHTTP(w http.ResponseWriter, req *http.Request) {
902906 // ignore error from ParseForm as it's usually spurious.
903 req.ParseForm()
907 err := req.ParseForm()
908 if err != nil {
909 fatalf(400, "BadParameters", "Parse form failed.")
910 }
904911
905912 if fn := s.override[req.URL.Path]; fn != nil {
906913 originalRW := w
953960 _, _ = rand.Read(r)
954961 id := fmt.Sprintf("%X", r)
955962 w.Header().Set("X-Storage-Url", s.URL+"/AUTH_"+username)
956 w.Header().Set("X-Auth-Token", "AUTH_tk"+string(id))
957 w.Header().Set("X-Storage-Token", "AUTH_tk"+string(id))
963 w.Header().Set("X-Auth-Token", "AUTH_tk"+id)
964 w.Header().Set("X-Storage-Token", "AUTH_tk"+id)
958965 s.Sessions[id] = &session{
959966 username: username,
960967 }
10151022 if !ok {
10161023 s.RUnlock()
10171024 panic(notAuthorized())
1018 return
10191025 }
10201026
10211027 a.user = s.Accounts[session.username]
10451051 } else {
10461052 switch r := resp.(type) {
10471053 case string:
1048 w.Write([]byte(r))
1054 _, err := w.Write([]byte(r))
1055 if err != nil {
1056 fatalf(500, "WriteFailed", "Write failed.")
1057 }
10491058 default:
1050 w.Write(resp.([]byte))
1059 _, err := w.Write(resp.([]byte))
1060 if err != nil {
1061 fatalf(500, "WriteFailed", "Write failed.")
1062 }
10511063 }
10521064 }
10531065 }
11941206 Name: container.name,
11951207 })
11961208 } else {
1197 a.w.Write([]byte(container.name + "\n"))
1209 _, err := a.w.Write([]byte(container.name + "\n"))
1210 if err != nil {
1211 fatalf(500, "WriteFailed", "Write failed.")
1212 }
11981213 }
11991214 }
12001215
12741289 }
12751290
12761291 resp := fmt.Sprintf("Number Deleted: %d\nNumber Not Found: %d\nErrors: \nResponse Status: 200 OK\n", nb, notFound)
1277 a.w.Write([]byte(resp))
1292 _, err = a.w.Write([]byte(resp))
1293 if err != nil {
1294 fatalf(500, "WriteFailed", "Write failed.")
1295 }
12781296 return nil
12791297 }
12801298
13091327 Containers: make(map[string]*container),
13101328 }
13111329
1312 go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
1313 server.serveHTTP(w, req)
1314 }))
1330 go func() {
1331 _ = http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
1332 server.serveHTTP(w, req)
1333 }))
1334 }()
13151335
13161336 return server, nil
13171337 }
13181338
13191339 func (srv *SwiftServer) Close() {
1320 srv.Listener.Close()
1321 }
1340 _ = srv.Listener.Close()
1341 }
4646 t.cancel()
4747 return 0, TimeoutError
4848 }
49 panic("unreachable") // for Go 1.0
5049 }
5150
5251 // Close the channel
6666 if test.closed {
6767 t.Fatal("Shouldn't be closed")
6868 }
69 tr.Close()
69 _ = tr.Close()
7070 if !test.closed {
7171 t.Fatal("Should be closed")
7272 }
9999 if test.closed {
100100 t.Fatal("Shouldn't be closed")
101101 }
102 tr.Close()
102 _ = tr.Close()
103103 if !test.closed {
104104 t.Fatal("Should be closed")
105105 }