├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── MAINTAINERS.md ├── Makefile ├── README.md ├── build-tools ├── before-make-script.sh ├── copyright-check.sh └── git-hooks │ └── pre-commit ├── example ├── example.go └── example_test.go └── s3mem ├── client.go ├── client_logger.go ├── client_logger_test.go ├── copy_object_request.go ├── copy_object_request_test.go ├── create_bucket_request.go ├── create_bucket_request_test.go ├── defaults.go ├── delete_bucket_request.go ├── delete_bucket_request_test.go ├── delete_object_request.go ├── delete_object_request_test.go ├── delete_objects_request.go ├── delete_objects_request_test.go ├── get_bucket_versioning_request.go ├── get_bucket_versioning_request_test.go ├── get_object_request.go ├── get_object_request_test.go ├── handlers.go ├── helper.go ├── helper_test.go ├── list_buckets_request.go ├── list_buckets_request_test.go ├── list_objects_request.go ├── list_objects_request_test.go ├── put_bucket_versioning_request.go ├── put_bucket_versioning_request_test.go ├── put_object_request.go ├── put_object_request_test.go ├── request.go ├── request_test.go ├── s3mem.go ├── s3mem_test.go ├── s3memerr └── errors.go └── types.go /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | VERSION 3 | .idea 4 | vendor 5 | _vendor* 6 | debug.test 7 | c.out 8 | .vscode -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: required 3 | dist: xenial 4 | 5 | go: 6 | - "1.12" 7 | 8 | services: 9 | - docker 10 | 11 | before_install: 12 | - make copyright-check 13 | 14 | script: 15 | - make 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing In General 2 | Our project welcomes external contributions. If you have an itch, please feel 3 | free to scratch it. 4 | 5 | To contribute code or documentation, please submit a [pull request](https://github.com/ibm/s3mem-go/pulls). 6 | 7 | A good way to familiarize yourself with the codebase and contribution process is 8 | to look for and tackle low-hanging fruit in the [issue tracker](https://github.com/ibm/s3mem-go/issues). 9 | Before embarking on a more ambitious contribution, please quickly [get in touch](#communication) with us. 10 | 11 | **Note: We appreciate your effort, and want to avoid a situation where a contribution 12 | requires extensive rework (by you or by us), sits in backlog for a long time, or 13 | cannot be accepted at all!** 14 | 15 | ### Proposing new features 16 | 17 | If you would like to implement a new feature, please [raise an issue](https://github.com/ibm/s3mem-go/issues) 18 | before sending a pull request so the feature can be discussed. This is to avoid 19 | you wasting your valuable time working on a feature that the project developers 20 | are not interested in accepting into the code base. 21 | 22 | ### Fixing bugs 23 | 24 | If you would like to fix a bug, please [raise an issue](https://github.com/ibm/s3mem-go/issues) before sending a 25 | pull request so it can be tracked. 26 | 27 | ### Merge approval 28 | 29 | The project maintainers use LGTM (Looks Good To Me) in comments on the code 30 | review to indicate acceptance. A change requires LGTMs from two of the 31 | maintainers of each component affected. 32 | 33 | For a list of the maintainers, see the [MAINTAINERS.md](MAINTAINERS.md) page. 34 | 35 | ## Legal 36 | 37 | Each source file must include a license header for the Apache 38 | Software License 2.0. Using the SPDX format is the simplest approach. 39 | e.g. 40 | 41 | ``` 42 | /* 43 | ################################################################################ 44 | # Copyright 2019 IBM Corp. All Rights Reserved. 45 | # 46 | # Licensed under the Apache License, Version 2.0 (the "License"); 47 | # you may not use this file except in compliance with the License. 48 | # You may obtain a copy of the License at 49 | # 50 | # http://www.apache.org/licenses/LICENSE-2.0 51 | # 52 | # Unless required by applicable law or agreed to in writing, software 53 | # distributed under the License is distributed on an "AS IS" BASIS, 54 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 55 | # See the License for the specific language governing permissions and 56 | # limitations under the License. 57 | ################################################################################ 58 | */ 59 | ``` 60 | 61 | A githook is in place to verify if Copyright is present at commit. 62 | 63 | We have tried to make it as easy as possible to make contributions. This 64 | applies to how we handle the legal aspects of contribution. We use the 65 | same approach - the [Developer's Certificate of Origin 1.1 (DCO)](https://github.com/hyperledger/fabric/blob/master/docs/source/DCO1.1.txt) - that the Linux® Kernel [community](https://elinux.org/Developer_Certificate_Of_Origin) 66 | uses to manage code contributions. 67 | 68 | We simply ask that when submitting a patch for review, the developer 69 | must include a sign-off statement in the commit message. 70 | 71 | Here is an example Signed-off-by line, which indicates that the 72 | submitter accepts the DCO: 73 | 74 | ```Text 75 | Signed-off-by: John Doe 76 | ``` 77 | 78 | You can include this automatically when you commit a change to your 79 | local git repository using the following command: 80 | 81 | ```bash 82 | git commit -s 83 | ``` 84 | 85 | ## Communication 86 | 87 | **FIXME** Please feel free to connect with us on our [Slack channel](link). 88 | 89 | ## Setup 90 | 91 | If you made changes and want to test, just run `make` in the root directory will install `dep` if not yet present and then run `dep ensure -v` to update the vendor directory. Next, it will run the `go test` and calculate the test coverage. It will also check that all files contain the copyright. 92 | 93 | ## Testing 94 | 95 | The project is tested through unit-tests. 96 | 97 | ## Coding style guidelines 98 | 99 | - For each new S3 API implementation a new go file must be created like [get_object_request.go](https://github.com/IBM/s3mem-go/blob/4c1bd8e44612744d7772d52ca1d3070b400c24bc/s3mem/get_object_request.go#L48) along with a test file. The Non-Implemented method must be removed from the [s3mem.go](https://github.com/IBM/s3mem-go/blob/4c1bd8e44612744d7772d52ca1d3070b400c24bc/s3mem/s3mem.go#L55) file. 100 | - The [handler.go](https://github.com/IBM/s3mem-go/blob/5395cbaf07722d69baa21a54e3462c2bc0876aa6/s3mem/handlers.go#L38) must be updated to redirect the `send` to the correct method. 101 | - Errors must be raised using [s3memerr](https://github.com/IBM/s3mem-go/blob/5395cbaf07722d69baa21a54e3462c2bc0876aa6/s3mem/s3memerr/errors.go#L19), it implements awserr.Error. 102 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | digest = "1:99836a9c1dee8a23d87794d213e857ee6b08a0594e27453e52d9683b99f561aa" 6 | name = "github.com/aws/aws-sdk-go-v2" 7 | packages = [ 8 | "aws", 9 | "aws/awserr", 10 | "aws/endpoints", 11 | "aws/signer/v4", 12 | "internal/awsutil", 13 | "internal/sdk", 14 | "private/protocol", 15 | "private/protocol/query", 16 | "private/protocol/query/queryutil", 17 | "private/protocol/rest", 18 | "private/protocol/restxml", 19 | "private/protocol/xml", 20 | "private/protocol/xml/xmlutil", 21 | "service/s3", 22 | "service/s3/s3iface", 23 | ] 24 | pruneopts = "UT" 25 | revision = "098e15df3044cf1b04a222c1c33c3e6135ac89f3" 26 | version = "v0.9.0" 27 | 28 | [[projects]] 29 | digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" 30 | name = "github.com/davecgh/go-spew" 31 | packages = ["spew"] 32 | pruneopts = "UT" 33 | revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" 34 | version = "v1.1.1" 35 | 36 | [[projects]] 37 | digest = "1:bb81097a5b62634f3e9fec1014657855610c82d19b9a40c17612e32651e35dca" 38 | name = "github.com/jmespath/go-jmespath" 39 | packages = ["."] 40 | pruneopts = "UT" 41 | revision = "c2b33e84" 42 | 43 | [[projects]] 44 | digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" 45 | name = "github.com/pmezard/go-difflib" 46 | packages = ["difflib"] 47 | pruneopts = "UT" 48 | revision = "792786c7400a136282c1664665ae0a8db921c6c2" 49 | version = "v1.0.0" 50 | 51 | [[projects]] 52 | digest = "1:972c2427413d41a1e06ca4897e8528e5a1622894050e2f527b38ddf0f343f759" 53 | name = "github.com/stretchr/testify" 54 | packages = ["assert"] 55 | pruneopts = "UT" 56 | revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053" 57 | version = "v1.3.0" 58 | 59 | [solve-meta] 60 | analyzer-name = "dep" 61 | analyzer-version = 1 62 | input-imports = [ 63 | "github.com/aws/aws-sdk-go-v2/aws", 64 | "github.com/aws/aws-sdk-go-v2/aws/awserr", 65 | "github.com/aws/aws-sdk-go-v2/aws/endpoints", 66 | "github.com/aws/aws-sdk-go-v2/private/protocol/restxml", 67 | "github.com/aws/aws-sdk-go-v2/service/s3", 68 | "github.com/aws/aws-sdk-go-v2/service/s3/s3iface", 69 | "github.com/stretchr/testify/assert", 70 | ] 71 | solver-name = "gps-cdcl" 72 | solver-version = 1 73 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [[constraint]] 29 | name = "github.com/aws/aws-sdk-go-v2" 30 | version = "0.9.0" 31 | 32 | [prune] 33 | go-tests = true 34 | unused-packages = true 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # MAINTAINERS 2 | 3 | Dominique Vernier 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | 18 | TAG_VERSION ?= `cat VERSION`+$(GIT_COMMIT) 19 | 20 | .DEFAULT_GOAL := all 21 | 22 | BEFORE_SCRIPT := $(shell ./build-tools/before-make-script.sh) 23 | 24 | .PHONY: all-checks 25 | all-checks: copyright-check 26 | 27 | .PHONY: dep-install 28 | dep-install:: 29 | 30 | mkdir -p $(GOPATH)/bin 31 | dep version; \ 32 | if [ $$? -ne 0 ]; then \ 33 | go get -u github.com/golang/dep/cmd/dep; \ 34 | fi 35 | 36 | .PHONY: pre-req 37 | pre-req:: dep-install 38 | dep ensure -v 39 | 40 | 41 | .PHONY: go-test 42 | go-test: 43 | @echo "Start Integration test"; 44 | #go clean -testcache 45 | go test -p 1 -v -coverprofile=c.out github.com/IBM/s3mem-go/s3mem/... || exit 1 46 | go tool cover -func=c.out 47 | 48 | .PHONY: copyright-check 49 | copyright-check: 50 | ./build-tools/copyright-check.sh 51 | 52 | .PHONY: all 53 | all:: clean pre-req copyright-check go-test 54 | 55 | .PHONY: clean 56 | clean:: 57 | rm -rf api/testFile 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # s3mem 2 | s3mem is an in-memory S3API implementation. 3 | It is a real serverless AWS S3, no need to run an external process or a docker image. It is a Go package that you use, that's it! 4 | It allows you to create different S3 servers for your tests, for example one per unit-test. 5 | It is a work in progess and only some APIs are implemented (Feel free to contribute) 6 | 7 | ## Build 8 | 9 | This project uses [dep](https://github.com/golang/dep), running `dep ensure -v` will update the vendor directory with all dependencies. 10 | If your projectg doesn't use `dep` then you will need to make available all packages of the vendor directory to your project. 11 | 12 | ## Usage 13 | 14 | To get a client call the `s3mem.New()` function. It returns a s3iface.ClientAPI client for the s3mem in-memory implementation and you can use it as client for the AWS S3 methods. 15 | 16 | ### Examples 17 | 18 | As example here a method which retrieves an object from an S3 implementation [Example](example/example.go) and here how to write a test for it [Example Test](example/example_test.go) using s3mem. It shows also how to manage multiple s3 servers. 19 | The s3mem package offers a number of helper methods to manage the buckets and objects without using the S3API. These methods will directly modify the in-memory s3. This is useful to setup your tests. You can find them in the [Helper methods](s3mem/helper.go). To create new S3 server call `NewDefaultS3MemService()` or `NewS3MemService()` and to get the store `GetDefaultS3MemService()` or `GetS3MemService()`. 20 | 21 | ## Implemented mehtods 22 | 23 | ```go 24 | CopyObjectRequest(*s3.CopyObjectInput) s3.CopyObjectRequest 25 | CreateBucketRequest(input *s3.CreateBucketInput) s3.CreateBucketRequest 26 | DeleteBucketRequest(input *s3.DeleteBucketInput) s3.DeleteBucketRequest 27 | DeleteObjectRequest(input *s3.DeleteObjectInput) s3.DeleteObjectRequest 28 | DeleteObjectsRequest(input *s3.DeleteObjectsInput) s3.DeleteObjectsRequest 29 | GetBucketVersioningRequest(input *s3.GetBucketVersioningInput) s3.GetBucketVersioningRequest 30 | GetObjectRequest(input *s3.GetObjectInput) s3.GetObjectRequest 31 | ListBucketsRequest(input *s3.ListBucketsInput) s3.ListBucketsRequest 32 | ListObjectsRequest(input *s3.ListObjectsInput) s3.ListObjectsRequest 33 | PutBucketVersioningRequest(input *s3.PutBucketVersioningInput) s3.PutBucketVersioningRequest 34 | PutObjectRequest(input *s3.PutObjectInput) s3.PutObjectRequest 35 | ``` 36 | 37 | ## Not implemented methods 38 | 39 | A call to Non-implemented methods will return a ErrCodeNotImplemented error. 40 | 41 | ```go 42 | AbortMultipartUploadRequest(*s3.AbortMultipartUploadInput) s3.AbortMultipartUploadRequest 43 | CompleteMultipartUploadRequest(*s3.CompleteMultipartUploadInput) s3.CompleteMultipartUploadRequest 44 | CreateMultipartUploadRequest(*s3.CreateMultipartUploadInput) s3.CreateMultipartUploadRequest 45 | DeleteBucketAnalyticsConfigurationRequest(*s3.DeleteBucketAnalyticsConfigurationInput) s3.DeleteBucketAnalyticsConfigurationRequest 46 | DeleteBucketCorsRequest(*s3.DeleteBucketCorsInput) s3.DeleteBucketCorsRequest 47 | DeleteBucketEncryptionRequest(*s3.DeleteBucketEncryptionInput) s3.DeleteBucketEncryptionRequest 48 | DeleteBucketInventoryConfigurationRequest(*s3.DeleteBucketInventoryConfigurationInput) s3.DeleteBucketInventoryConfigurationRequest 49 | DeleteBucketLifecycleRequest(*s3.DeleteBucketLifecycleInput) s3.DeleteBucketLifecycleRequest 50 | DeleteBucketMetricsConfigurationRequest(*s3.DeleteBucketMetricsConfigurationInput) s3.DeleteBucketMetricsConfigurationRequest 51 | DeleteBucketPolicyRequest(*s3.DeleteBucketPolicyInput) s3.DeleteBucketPolicyRequest 52 | DeleteBucketReplicationRequest(*s3.DeleteBucketReplicationInput) s3.DeleteBucketReplicationRequest 53 | DeleteBucketTaggingRequest(*s3.DeleteBucketTaggingInput) s3.DeleteBucketTaggingRequest 54 | DeleteBucketWebsiteRequest(*s3.DeleteBucketWebsiteInput) s3.DeleteBucketWebsiteRequest 55 | DeleteObjectTaggingRequest(*s3.DeleteObjectTaggingInput) s3.DeleteObjectTaggingRequest 56 | DeletePublicAccessBlockRequest(*s3.DeletePublicAccessBlockInput) s3.DeletePublicAccessBlockRequest 57 | GetBucketAccelerateConfigurationRequest(*s3.GetBucketAccelerateConfigurationInput) s3.GetBucketAccelerateConfigurationRequest 58 | GetBucketAclRequest(*s3.GetBucketAclInput) s3.GetBucketAclRequest 59 | GetBucketAnalyticsConfigurationRequest(*s3.GetBucketAnalyticsConfigurationInput) s3.GetBucketAnalyticsConfigurationRequest 60 | GetBucketCorsRequest(*s3.GetBucketCorsInput) s3.GetBucketCorsRequest 61 | GetBucketEncryptionRequest(*s3.GetBucketEncryptionInput) s3.GetBucketEncryptionRequest 62 | GetBucketInventoryConfigurationRequest(*s3.GetBucketInventoryConfigurationInput) s3.GetBucketInventoryConfigurationRequest 63 | GetBucketLifecycleRequest(*s3.GetBucketLifecycleInput) s3.GetBucketLifecycleRequest 64 | GetBucketLifecycleConfigurationRequest(*s3.GetBucketLifecycleConfigurationInput) s3.GetBucketLifecycleConfigurationRequest 65 | GetBucketLocationRequest(*s3.GetBucketLocationInput) s3.GetBucketLocationRequest 66 | GetBucketLoggingRequest(*s3.GetBucketLoggingInput) s3.GetBucketLoggingRequest 67 | GetBucketMetricsConfigurationRequest(*s3.GetBucketMetricsConfigurationInput) s3.GetBucketMetricsConfigurationRequest 68 | GetBucketNotificationRequest(*s3.GetBucketNotificationConfigurationInput) s3.GetBucketNotificationRequest 69 | GetBucketNotificationConfigurationRequest(*s3.GetBucketNotificationConfigurationInput) s3.GetBucketNotificationConfigurationRequest 70 | GetBucketPolicyRequest(*s3.GetBucketPolicyInput) s3.GetBucketPolicyRequest 71 | GetBucketPolicyStatusRequest(*s3.GetBucketPolicyStatusInput) s3.GetBucketPolicyStatusRequest 72 | GetBucketReplicationRequest(*s3.GetBucketReplicationInput) s3.GetBucketReplicationRequest 73 | GetBucketRequestPaymentRequest(*s3.GetBucketRequestPaymentInput) s3.GetBucketRequestPaymentRequest 74 | GetBucketTaggingRequest(*s3.GetBucketTaggingInput) s3.GetBucketTaggingRequest 75 | GetBucketWebsiteRequest(*s3.GetBucketWebsiteInput) s3.GetBucketWebsiteRequest 76 | GetObjectAclRequest(*s3.GetObjectAclInput) s3.GetObjectAclRequest 77 | GetObjectLegalHoldRequest(*s3.GetObjectLegalHoldInput) s3.GetObjectLegalHoldRequest 78 | GetObjectLockConfigurationRequest(*s3.GetObjectLockConfigurationInput) s3.GetObjectLockConfigurationRequest 79 | GetObjectRetentionRequest(*s3.GetObjectRetentionInput) s3.GetObjectRetentionRequest 80 | GetObjectTaggingRequest(*s3.GetObjectTaggingInput) s3.GetObjectTaggingRequest 81 | GetObjectTorrentRequest(*s3.GetObjectTorrentInput) s3.GetObjectTorrentRequest 82 | GetPublicAccessBlockRequest(*s3.GetPublicAccessBlockInput) s3.GetPublicAccessBlockRequest 83 | HeadBucketRequest(*s3.HeadBucketInput) s3.HeadBucketRequest 84 | HeadObjectRequest(*s3.HeadObjectInput) s3.HeadObjectRequest 85 | ListBucketAnalyticsConfigurationsRequest(*s3.ListBucketAnalyticsConfigurationsInput) s3.ListBucketAnalyticsConfigurationsRequest 86 | ListBucketInventoryConfigurationsRequest(*s3.ListBucketInventoryConfigurationsInput) s3.ListBucketInventoryConfigurationsRequest 87 | ListBucketMetricsConfigurationsRequest(*s3.ListBucketMetricsConfigurationsInput) s3.ListBucketMetricsConfigurationsRequest 88 | ListMultipartUploadsRequest(*s3.ListMultipartUploadsInput) s3.ListMultipartUploadsRequest 89 | ListObjectVersionsRequest(*s3.ListObjectVersionsInput) s3.ListObjectVersionsRequest 90 | ListObjectsV2Request(*s3.ListObjectsV2Input) s3.ListObjectsV2Request 91 | ListPartsRequest(*s3.ListPartsInput) s3.ListPartsRequest 92 | PutBucketAccelerateConfigurationRequest(*s3.PutBucketAccelerateConfigurationInput) s3.PutBucketAccelerateConfigurationRequest 93 | PutBucketAclRequest(*s3.PutBucketAclInput) s3.PutBucketAclRequest 94 | PutBucketAnalyticsConfigurationRequest(*s3.PutBucketAnalyticsConfigurationInput) s3.PutBucketAnalyticsConfigurationRequest 95 | PutBucketCorsRequest(*s3.PutBucketCorsInput) s3.PutBucketCorsRequest 96 | PutBucketEncryptionRequest(*s3.PutBucketEncryptionInput) s3.PutBucketEncryptionRequest 97 | PutBucketInventoryConfigurationRequest(*s3.PutBucketInventoryConfigurationInput) s3.PutBucketInventoryConfigurationRequest 98 | PutBucketLifecycleRequest(*s3.PutBucketLifecycleInput) s3.PutBucketLifecycleRequest 99 | PutBucketLifecycleConfigurationRequest(*s3.PutBucketLifecycleConfigurationInput) s3.PutBucketLifecycleConfigurationRequest 100 | PutBucketLoggingRequest(*s3.PutBucketLoggingInput) s3.PutBucketLoggingRequest 101 | PutBucketMetricsConfigurationRequest(*s3.PutBucketMetricsConfigurationInput) s3.PutBucketMetricsConfigurationRequest 102 | PutBucketNotificationRequest(*s3.PutBucketNotificationInput) s3.PutBucketNotificationRequest 103 | PutBucketNotificationConfigurationRequest(*s3.PutBucketNotificationConfigurationInput) s3.PutBucketNotificationConfigurationRequest 104 | PutBucketPolicyRequest(*s3.PutBucketPolicyInput) s3.PutBucketPolicyRequest 105 | PutBucketReplicationRequest(*s3.PutBucketReplicationInput) s3.PutBucketReplicationRequest 106 | PutBucketRequestPaymentRequest(*s3.PutBucketRequestPaymentInput) s3.PutBucketRequestPaymentRequest 107 | PutBucketTaggingRequest(*s3.PutBucketTaggingInput) s3.PutBucketTaggingRequest 108 | PutBucketWebsiteRequest(*s3.PutBucketWebsiteInput) s3.PutBucketWebsiteRequest 109 | PutObjectAclRequest(*s3.PutObjectAclInput) s3.PutObjectAclRequest 110 | PutObjectLegalHoldRequest(*s3.PutObjectLegalHoldInput) s3.PutObjectLegalHoldRequest 111 | PutObjectLockConfigurationRequest(*s3.PutObjectLockConfigurationInput) s3.PutObjectLockConfigurationRequest 112 | PutObjectRetentionRequest(*s3.PutObjectRetentionInput) s3.PutObjectRetentionRequest 113 | PutObjectTaggingRequest(*s3.PutObjectTaggingInput) s3.PutObjectTaggingRequest 114 | PutPublicAccessBlockRequest(*s3.PutPublicAccessBlockInput) s3.PutPublicAccessBlockRequest 115 | RestoreObjectRequest(*s3.RestoreObjectInput) s3.RestoreObjectRequest 116 | UploadPartRequest(*s3.UploadPartInput) s3.UploadPartRequest 117 | UploadPartCopyRequest(*s3.UploadPartCopyInput) s3.UploadPartCopyRequest 118 | WaitUntilBucketExists(context.Context, *s3.HeadBucketInput, ...aws.WaiterOption) error 119 | WaitUntilBucketNotExists(context.Context, *s3.HeadBucketInput, ...aws.WaiterOption) error 120 | WaitUntilObjectExists(context.Context, *s3.HeadObjectInput, ...aws.WaiterOption) error 121 | WaitUntilObjectNotExists(context.Context, *s3.HeadObjectInput, ...aws.WaiterOption) error 122 | ``` 123 | 124 | ## Limitation 125 | 126 | - Pagination is not implemented, all items are returned. 127 | -------------------------------------------------------------------------------- /build-tools/before-make-script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################################ 4 | # Copyright 2019 IBM Corp. All Rights Reserved. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | ################################################################################ 18 | 19 | ln -sf ../../build-tools/git-hooks/pre-commit .git/hooks/pre-commit 20 | -------------------------------------------------------------------------------- /build-tools/copyright-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | IFS='' read -r -d '' LICENSE <<'EOF' 5 | ################################################################################ 6 | # Copyright 2019 IBM Corp. All Rights Reserved. 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # http://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | ################################################################################ 20 | EOF 21 | 22 | 23 | LICENSE_NB_LINE=`echo "$LICENSE" | wc -l` 24 | 25 | HEADER_TO_READ=$(($LICENSE_NB_LINE +5)) 26 | 27 | ERROR=0 28 | 29 | echo "##### Copyright check #####" 30 | for f in `find . \( -path ./vendor -prune \) -type f ! -iname ".*" -o -print`; do 31 | if [ ! -f "$f" ] || [ "$f" = "./build-tools/copyright-check.sh" ]; then 32 | continue 33 | fi 34 | 35 | FILETYPE=$(basename ${f##*.}) 36 | case "${FILETYPE}" in 37 | js | sh | go | java | rb) 38 | COMMENT_PREFIX="" 39 | ;; 40 | *) 41 | continue 42 | esac 43 | 44 | # Read the first 10 lines 45 | HEADER=`head -$HEADER_TO_READ $f` 46 | printf "Scanning $f\n" 47 | if [[ "$HEADER" != *"$LICENSE"* ]]; then 48 | printf "Missing or incorrect license in file $f\n" 49 | ERROR=1 50 | fi 51 | done 52 | 53 | echo "##### Copyright check ##### ReturnCode: ${ERROR}" 54 | exit $ERROR 55 | -------------------------------------------------------------------------------- /build-tools/git-hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | make all-checks 6 | -------------------------------------------------------------------------------- /example/example.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package example 20 | 21 | import ( 22 | "bytes" 23 | "context" 24 | 25 | "github.com/aws/aws-sdk-go-v2/service/s3" 26 | "github.com/aws/aws-sdk-go-v2/service/s3/s3iface" 27 | ) 28 | 29 | const MyURLEndpoint = "https://my-s3-target.mycompany.com" 30 | 31 | func GetObject(client s3iface.ClientAPI, bucket *string, key *string) ([]byte, error) { 32 | //Create a request 33 | req := client.GetObjectRequest(&s3.GetObjectInput{ 34 | Bucket: bucket, 35 | Key: key, 36 | }) 37 | //Send the request 38 | getObjectOutput, err := req.Send(context.TODO()) 39 | if err != nil { 40 | return nil, err 41 | } 42 | //Read body 43 | buf := new(bytes.Buffer) 44 | buf.ReadFrom(getObjectOutput.Body) 45 | newBytes := buf.Bytes() 46 | return newBytes, nil 47 | } 48 | 49 | func GetBuckets(client s3iface.ClientAPI) ([]string, error) { 50 | //Create the request 51 | req := client.ListBucketsRequest(&s3.ListBucketsInput{}) 52 | //Send the request 53 | listBucketsOutput, err := req.Send(context.Background()) 54 | if err != nil { 55 | return nil, err 56 | } 57 | buckets := make([]string, len(listBucketsOutput.Buckets)) 58 | for i, v := range listBucketsOutput.Buckets { 59 | buckets[i] = *v.Name 60 | } 61 | return buckets, nil 62 | } 63 | -------------------------------------------------------------------------------- /example/example_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package example 19 | 20 | import ( 21 | "strings" 22 | "testing" 23 | 24 | "github.com/aws/aws-sdk-go-v2/aws" 25 | "github.com/aws/aws-sdk-go-v2/aws/endpoints" 26 | 27 | "github.com/stretchr/testify/assert" 28 | 29 | "github.com/IBM/s3mem-go/s3mem" 30 | "github.com/aws/aws-sdk-go-v2/service/s3" 31 | ) 32 | 33 | var MyS3MemService *s3mem.S3MemService 34 | 35 | func init() { 36 | MyS3MemService = s3mem.NewS3MemService(MyURLEndpoint) 37 | } 38 | 39 | func getTestConfig(S3MemService string) aws.Config { 40 | defaultResolver := endpoints.NewDefaultResolver() 41 | myCustomResolver := func(service, region string) (aws.Endpoint, error) { 42 | if service == s3.EndpointsID { 43 | return aws.Endpoint{ 44 | URL: S3MemService, 45 | }, nil 46 | } 47 | return defaultResolver.ResolveEndpoint(service, region) 48 | } 49 | config := aws.Config{ 50 | EndpointResolver: aws.EndpointResolverFunc(myCustomResolver), 51 | } 52 | return config 53 | } 54 | 55 | func TestGetObjectOwnS3Env(t *testing.T) { 56 | //Create the s3 service for this test 57 | myS3MemService := s3mem.NewTestS3MemService(t) 58 | //Adding bucket directly in mem to prepare the test. 59 | bucket := strings.ToLower(t.Name()) 60 | myS3MemService.CreateBucket(&s3.Bucket{Name: &bucket}) 61 | //Adding an Object directly in mem to prepare the test. 62 | key := "my-object" 63 | content := "test content" 64 | myS3MemService.PutObject(&bucket, &key, strings.NewReader(string(content))) 65 | //Request a client 66 | client := s3mem.New(getTestConfig(myS3MemService.URL)) 67 | //Call the method to test 68 | b, err := GetObject(client, &bucket, &key) 69 | //Assert the result 70 | assert.NoError(t, err) 71 | assert.Equal(t, content, string(b)) 72 | //Delete the s3 service 73 | myS3MemService.DeleteS3MemService() 74 | } 75 | 76 | func TestGetObject(t *testing.T) { 77 | //Adding bucket directly in mem to prepare the test. 78 | bucket := strings.ToLower(t.Name()) 79 | MyS3MemService.CreateBucket(&s3.Bucket{Name: &bucket}) 80 | //Adding an Object directly in mem to prepare the test. 81 | key := "my-object" 82 | content := "test content" 83 | MyS3MemService.PutObject(&bucket, &key, strings.NewReader(string(content))) 84 | //Request a client 85 | client := s3mem.New(getTestConfig(MyURLEndpoint)) 86 | //Call the method to test 87 | b, err := GetObject(client, &bucket, &key) 88 | //Assert the result 89 | assert.NoError(t, err) 90 | assert.Equal(t, content, string(b)) 91 | } 92 | 93 | //Here we use the default endpoint 94 | func TestGetObjectWithDefaultEndpoint(t *testing.T) { 95 | //Request a client 96 | config := aws.Config{} 97 | client := s3mem.New(config) 98 | //Create default S3MemService 99 | defaultS3MemService := s3mem.NewDefaultS3MemService() 100 | //Adding bucket directly in mem to prepare the test. 101 | bucket := strings.ToLower(t.Name()) 102 | // endpointResolver := config.EndpointResolver 103 | defaultS3MemService.CreateBucket(&s3.Bucket{Name: &bucket}) 104 | //Adding an Object directly in mem to prepare the test. 105 | key := "my-object" 106 | content := "test content" 107 | defaultS3MemService.PutObject(&bucket, &key, strings.NewReader(string(content))) 108 | //Call the method to test 109 | b, err := GetObject(client, &bucket, &key) 110 | //Assert the result 111 | assert.NoError(t, err) 112 | assert.Equal(t, content, string(b)) 113 | //Free up memory 114 | defaultS3MemService.DeleteS3MemService() 115 | } 116 | 117 | func TestGetObjectWithLog(t *testing.T) { 118 | //Adding bucket directly in mem to prepare the test. 119 | bucket := strings.ToLower(t.Name()) 120 | MyS3MemService.CreateBucket(&s3.Bucket{Name: &bucket}) 121 | //Adding an Object directly in mem to prepare the test. 122 | key := "my-object" 123 | content := "test content" 124 | MyS3MemService.PutObject(&bucket, &key, strings.NewReader(string(content))) 125 | config := getTestConfig(MyURLEndpoint) 126 | config.LogLevel = aws.LogDebugWithHTTPBody 127 | config.Logger = aws.NewDefaultLogger() 128 | //Request a client 129 | client := s3mem.New(config) 130 | //Call the method to test 131 | b, err := GetObject(client, &bucket, &key) 132 | //Assert the result 133 | assert.NoError(t, err) 134 | assert.Equal(t, content, string(b)) 135 | } 136 | 137 | func TestListBucketsRequest(t *testing.T) { 138 | //Creating a new S3MemService because at the end of this test 139 | //we want to test the bucket ordering and so we want a new 140 | //S3MemService to avoid interraction with other tests. 141 | S3MemService := strings.ToLower(t.Name()) 142 | localS3MemService := s3mem.NewS3MemService(S3MemService) 143 | //Need to lock for testing as tests are running concurrently 144 | //and meanwhile another running test could change the stored buckets 145 | localS3MemService.Lock() 146 | defer localS3MemService.Unlock() 147 | //Adding bucket directly in mem to prepare the test. 148 | bucket0 := strings.ToLower(t.Name() + "0") 149 | bucket1 := strings.ToLower(t.Name() + "1") 150 | localS3MemService.CreateBucket(&s3.Bucket{Name: &bucket0}) 151 | localS3MemService.CreateBucket(&s3.Bucket{Name: &bucket1}) 152 | l := len(s3mem.S3Store.S3MemServices[S3MemService].Buckets) 153 | //Request a client 154 | client := s3mem.New(getTestConfig(S3MemService)) 155 | //Call GetBuckets 156 | buckets, err := GetBuckets(client) 157 | //Assert the result 158 | assert.NoError(t, err) 159 | assert.Equal(t, l, len(buckets)) 160 | //We can check each bucket name in that order as the 161 | //AWS S3 ListBucketRequest is supposed to return all bucket in 162 | //alphabetic order. 163 | assert.Equal(t, bucket0, buckets[0]) 164 | assert.Equal(t, bucket1, buckets[1]) 165 | } 166 | 167 | func TestListBucketsRequestWithLock(t *testing.T) { 168 | //Need to lock for testing as tests are running concurrently 169 | //and meanwhile another running test could change the stored buckets 170 | MyS3MemService.Lock() 171 | defer MyS3MemService.Unlock() 172 | //Adding bucket directly in mem to prepare the test. 173 | bucket0 := strings.ToLower(t.Name() + "0") 174 | bucket1 := strings.ToLower(t.Name() + "1") 175 | MyS3MemService.CreateBucket(&s3.Bucket{Name: &bucket0}) 176 | MyS3MemService.CreateBucket(&s3.Bucket{Name: &bucket1}) 177 | l := len(s3mem.S3Store.S3MemServices[MyURLEndpoint].Buckets) 178 | //Request a client 179 | client := s3mem.New(getTestConfig(MyURLEndpoint)) 180 | //Call GetBuckets 181 | buckets, err := GetBuckets(client) 182 | //Assert the result 183 | assert.NoError(t, err) 184 | assert.Equal(t, l, len(buckets)) 185 | //Here we can not test the order as the MyURLEndpoint 186 | //could get some extra buckets from other tests 187 | } 188 | -------------------------------------------------------------------------------- /s3mem/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package s3mem 19 | 20 | import ( 21 | "github.com/aws/aws-sdk-go-v2/aws" 22 | "github.com/aws/aws-sdk-go-v2/private/protocol/restxml" 23 | "github.com/aws/aws-sdk-go-v2/service/s3" 24 | ) 25 | 26 | type Client struct { 27 | s3.Client 28 | } 29 | 30 | func New(config aws.Config) *Client { 31 | if config.EndpointResolver == nil { 32 | config.EndpointResolver = NewDefaultResolver() 33 | } 34 | svc := &Client{ 35 | Client: *s3.New(config), 36 | } 37 | //set handlers 38 | svc.Handlers = Handlers() 39 | svc.Handlers.Build.PushBackNamed(restxml.BuildHandler) 40 | // svc.Handlers.Unmarshal.PushBackNamed(restxml.UnmarshalHandler) 41 | // svc.Handlers.UnmarshalMeta.PushBackNamed(restxml.UnmarshalMetaHandler) 42 | // svc.Handlers.UnmarshalError.PushBackNamed(restxml.UnmarshalErrorHandler) 43 | svc.AddDebugHandlers() 44 | return svc 45 | } 46 | 47 | // AddDebugHandlers injects debug logging handlers into the service to log request 48 | // debug information. 49 | func (c *Client) AddDebugHandlers() { 50 | if !c.Config.LogLevel.AtLeast(aws.LogDebug) { 51 | return 52 | } 53 | 54 | c.Handlers.Send.PushFrontNamed(aws.NamedHandler{Name: "s3mem.client.LogRequest", Fn: logRequest}) 55 | c.Handlers.Send.PushBackNamed(aws.NamedHandler{Name: "s3mem.client.LogResponse", Fn: logResponse}) 56 | } 57 | -------------------------------------------------------------------------------- /s3mem/client_logger.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package s3mem 19 | 20 | import ( 21 | "bytes" 22 | "fmt" 23 | "io" 24 | "io/ioutil" 25 | "net/http/httputil" 26 | 27 | "github.com/aws/aws-sdk-go-v2/aws" 28 | ) 29 | 30 | const logReqMsg = `DEBUG: Request %s/%s Details: 31 | ---[ REQUEST POST-SIGN ]----------------------------- 32 | %s 33 | -----------------------------------------------------` 34 | 35 | const logReqErrMsg = `DEBUG ERROR: Request %s/%s: 36 | ---[ REQUEST DUMP ERROR ]----------------------------- 37 | %s 38 | ------------------------------------------------------` 39 | 40 | type logWriter struct { 41 | // Logger is what we will use to log the payload of a response. 42 | Logger aws.Logger 43 | // buf stores the contents of what has been read 44 | buf *bytes.Buffer 45 | } 46 | 47 | func (logger *logWriter) Write(b []byte) (int, error) { 48 | return logger.buf.Write(b) 49 | } 50 | 51 | type teeReaderCloser struct { 52 | // io.Reader will be a tee reader that is used during logging. 53 | // This structure will read from a body and write the contents to a logger. 54 | io.Reader 55 | // Source is used just to close when we are done reading. 56 | Source io.ReadCloser 57 | } 58 | 59 | func (reader *teeReaderCloser) Close() error { 60 | return reader.Source.Close() 61 | } 62 | 63 | func logRequest(r *aws.Request) { 64 | logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) 65 | dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, false) 66 | if err != nil { 67 | r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.Metadata.ServiceName, r.Operation.Name, err)) 68 | return 69 | } 70 | 71 | b, err := ioutil.ReadAll(r.HTTPRequest.Body) 72 | if err != nil { 73 | r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, r.Metadata.ServiceName, r.Operation.Name, err)) 74 | return 75 | } 76 | r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.Metadata.ServiceName, r.Operation.Name, string(dumpedBody))) 77 | if r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) { 78 | r.Config.Logger.Log(fmt.Sprintf("\n%s", string(b))) 79 | } 80 | 81 | if logBody { 82 | // Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's 83 | // Body as a NoOpCloser and will not be reset after read by the HTTP 84 | // client reader. 85 | r.ResetBody() 86 | } 87 | 88 | } 89 | 90 | const logRespMsg = `DEBUG: Response %s/%s Details: 91 | ---[ RESPONSE ]-------------------------------------- 92 | %s 93 | -----------------------------------------------------` 94 | 95 | const logRespErrMsg = `DEBUG ERROR: Response %s/%s: 96 | ---[ RESPONSE DUMP ERROR ]----------------------------- 97 | %s 98 | -----------------------------------------------------` 99 | 100 | func logResponse(r *aws.Request) { 101 | if r.Data == nil { 102 | r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, 103 | r.Metadata.ServiceName, r.Operation.Name, "request's Data is nil")) 104 | return 105 | } 106 | 107 | handlerFn := func(req *aws.Request) { 108 | body, err := httputil.DumpRequestOut(r.HTTPRequest, false) 109 | if err != nil { 110 | r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, req.Metadata.ServiceName, req.Operation.Name, err)) 111 | return 112 | } 113 | b, err := ioutil.ReadAll(req.HTTPResponse.Body) 114 | if err != nil { 115 | r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, req.Metadata.ServiceName, req.Operation.Name, err)) 116 | return 117 | } 118 | r.Config.Logger.Log(fmt.Sprintf(logRespMsg, req.Metadata.ServiceName, req.Operation.Name, string(body))) 119 | if req.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) { 120 | r.Config.Logger.Log(fmt.Sprintf("\n%s", string(b))) 121 | } 122 | } 123 | 124 | const handlerName = "s3mem.client.LogResponse.ResponseBody" 125 | 126 | r.Handlers.Unmarshal.SetBackNamed(aws.NamedHandler{ 127 | Name: handlerName, Fn: handlerFn, 128 | }) 129 | r.Handlers.UnmarshalError.SetBackNamed(aws.NamedHandler{ 130 | Name: handlerName, Fn: handlerFn, 131 | }) 132 | } 133 | -------------------------------------------------------------------------------- /s3mem/client_logger_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "testing" 24 | 25 | "github.com/aws/aws-sdk-go-v2/aws" 26 | "github.com/stretchr/testify/assert" 27 | ) 28 | 29 | func TestClientLoggerWrite(t *testing.T) { 30 | logger := &logWriter{ 31 | Logger: aws.NewDefaultLogger(), 32 | buf: new(bytes.Buffer), 33 | } 34 | l := logger.buf.Len() 35 | n, err := logger.Write([]byte("b")) 36 | assert.NoError(t, err) 37 | assert.Equal(t, l+1, n) 38 | } 39 | 40 | // func TestClientLoggerClose(t *testing.T) { 41 | // logger := &logWriter{ 42 | // Logger: aws.NewDefaultLogger(), 43 | // buf: new(bytes.Buffer), 44 | // } 45 | // err := logger. 46 | // } 47 | -------------------------------------------------------------------------------- /s3mem/copy_object_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | "strings" 26 | 27 | "github.com/aws/aws-sdk-go-v2/aws" 28 | "github.com/aws/aws-sdk-go-v2/service/s3" 29 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 30 | ) 31 | 32 | const opCopyObject = "CopyObject" 33 | 34 | //CopyObjectRequest ... 35 | func (c *Client) CopyObjectRequest(input *s3.CopyObjectInput) s3.CopyObjectRequest { 36 | if input == nil { 37 | input = &s3.CopyObjectInput{} 38 | } 39 | output := &s3.CopyObjectOutput{} 40 | operation := &aws.Operation{ 41 | Name: opCopyObject, 42 | HTTPMethod: "PUT", 43 | HTTPPath: "/{Bucket}/{Key+}", 44 | } 45 | req := c.NewRequest(operation, input, output) 46 | return s3.CopyObjectRequest{Request: req, Input: input, Copy: nil} 47 | } 48 | 49 | func copyObject(req *aws.Request) { 50 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 51 | if !S3MemService.IsBucketExist(req.Params.(*s3.CopyObjectInput).Bucket) { 52 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.CopyObjectInput).Bucket, nil, nil) 53 | return 54 | } 55 | bucket, key, err := ParseObjectURL(req.Params.(*s3.CopyObjectInput).CopySource) 56 | obj, versionId, err := S3MemService.GetObject(bucket, key, nil) 57 | if err != nil { 58 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchKey, "", nil, bucket, key, nil) 59 | } 60 | objDest, destVersionId, err := S3MemService.PutObject(req.Params.(*s3.CopyObjectInput).Bucket, key, strings.NewReader(string(obj.Content))) 61 | if err != nil { 62 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchUpload, "", nil, req.Params.(*s3.CopyObjectInput).Bucket, key, nil) 63 | } 64 | req.Data.(*s3.CopyObjectOutput).CopyObjectResult = &s3.CopyObjectResult{ 65 | ETag: objDest.Object.ETag, 66 | LastModified: objDest.Object.LastModified, 67 | } 68 | req.Data.(*s3.CopyObjectOutput).CopySourceVersionId = versionId 69 | req.Data.(*s3.CopyObjectOutput).VersionId = destVersionId 70 | //This is needed just to logResponse when requested 71 | body, _ := json.MarshalIndent(req.Data.(*s3.CopyObjectOutput), "", " ") 72 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 73 | 74 | } 75 | -------------------------------------------------------------------------------- /s3mem/copy_object_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestCopyObject(t *testing.T) { 31 | //Adding bucket directly in mem to prepare the test. 32 | bucketName := strings.ToLower(t.Name()) 33 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 34 | //Adding bucket directly in mem to prepare the test. 35 | bucketNameDest := strings.ToLower(t.Name() + "-dest") 36 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketNameDest}) 37 | //Adding an Object directly in mem to prepare the test. 38 | objectKey := "my-object" 39 | content := "test content" 40 | source := bucketName + "/" + objectKey 41 | _, sourceVerionId, err := S3MemTestService.PutObject(&bucketName, &objectKey, strings.NewReader(string(content))) 42 | assert.NoError(t, err) 43 | //Request a client 44 | client := New(S3MemTestConfig) 45 | req := client.CopyObjectRequest(&s3.CopyObjectInput{ 46 | Bucket: &bucketNameDest, 47 | CopySource: &source, 48 | }) 49 | objOut, err := req.Send(context.Background()) 50 | assert.NoError(t, err) 51 | assert.Equal(t, sourceVerionId, objOut.CopySourceVersionId) 52 | obj, _, err := S3MemTestService.GetObject(&bucketNameDest, &objectKey, nil) 53 | assert.NoError(t, err) 54 | assert.Equal(t, objectKey, *obj.Object.Key) 55 | } 56 | -------------------------------------------------------------------------------- /s3mem/create_bucket_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | "time" 26 | 27 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 28 | 29 | "github.com/aws/aws-sdk-go-v2/aws" 30 | "github.com/aws/aws-sdk-go-v2/service/s3" 31 | ) 32 | 33 | const opCreateBucket = "CreateBucket" 34 | 35 | //CreateBucketRequest ... 36 | func (c *Client) CreateBucketRequest(input *s3.CreateBucketInput) s3.CreateBucketRequest { 37 | if input == nil { 38 | input = &s3.CreateBucketInput{} 39 | } 40 | output := &s3.CreateBucketOutput{ 41 | Location: input.Bucket, 42 | } 43 | op := &aws.Operation{ 44 | Name: opCreateBucket, 45 | HTTPMethod: "PUT", 46 | HTTPPath: "/{Bucket}", 47 | } 48 | req := c.NewRequest(op, input, output) 49 | return s3.CreateBucketRequest{Request: req, Input: input} 50 | } 51 | 52 | func createBucket(req *aws.Request) { 53 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 54 | if S3MemService.IsBucketExist(req.Params.(*s3.CreateBucketInput).Bucket) { 55 | req.Error = s3memerr.NewError(s3.ErrCodeBucketAlreadyExists, "", nil, req.Params.(*s3.CreateBucketInput).Bucket, nil, nil) 56 | return 57 | } 58 | tc := time.Now() 59 | bucket := &s3.Bucket{ 60 | CreationDate: &tc, 61 | Name: req.Params.(*s3.CreateBucketInput).Bucket, 62 | } 63 | S3MemService.CreateBucket(bucket) 64 | //This is needed just to logResponse when requested 65 | body, _ := json.MarshalIndent(req.Data.(*s3.CreateBucketOutput), "", " ") 66 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 67 | } 68 | -------------------------------------------------------------------------------- /s3mem/create_bucket_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | func TestCreateBucketRequest(t *testing.T) { 32 | //Request a client 33 | client := New(S3MemTestConfig) 34 | //Create the request 35 | bucketName := strings.ToLower(t.Name()) 36 | req := client.CreateBucketRequest(&s3.CreateBucketInput{ 37 | Bucket: &bucketName, 38 | }) 39 | //Send the request 40 | createBucketsOutput, err := req.Send(context.Background()) 41 | //Assert the result 42 | assert.NoError(t, err) 43 | bucketGet := S3MemTestService.GetBucket(&bucketName) 44 | assert.NotNil(t, bucketGet) 45 | assert.Equal(t, bucketName, *bucketGet.Name) 46 | assert.Equal(t, bucketName, *createBucketsOutput.Location) 47 | assert.NotNil(t, bucketGet.CreationDate) 48 | } 49 | 50 | func TestCreateBucketRequestBucketAlreadyExists(t *testing.T) { 51 | //Request a client 52 | client := New(S3MemTestConfig) 53 | //Create the request 54 | bucketName := strings.ToLower(t.Name()) 55 | req := client.CreateBucketRequest(&s3.CreateBucketInput{ 56 | Bucket: &bucketName, 57 | }) 58 | ctx := context.Background() 59 | //Send the request 60 | _, err := req.Send(ctx) 61 | //Assert the result 62 | assert.NoError(t, err) 63 | //Send the request 64 | _, err = req.Send(ctx) 65 | //Assert the result 66 | assert.Error(t, err) 67 | assert.Implements(t, (*s3memerr.S3MemError)(nil), err) 68 | assert.Equal(t, s3memerr.ErrCodeBucketAlreadyExists, err.(s3memerr.S3MemError).Code()) 69 | } 70 | -------------------------------------------------------------------------------- /s3mem/defaults.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package s3mem 19 | 20 | import ( 21 | "github.com/aws/aws-sdk-go-v2/aws" 22 | ) 23 | 24 | const S3MemEndpointsID = "http://s3mem" 25 | 26 | func Handlers() aws.Handlers { 27 | var handlers aws.Handlers 28 | 29 | // handlers.Validate.PushBackNamed(defaults.ValidateEndpointHandler) 30 | // handlers.Validate.PushBackNamed(defaults.ValidateParametersHandler) 31 | // handlers.Validate.AfterEachFn = aws.HandlerListStopOnError 32 | // handlers.Build.PushBackNamed(defaults.SDKVersionUserAgentHandler) 33 | // handlers.Build.PushBackNamed(defaults.AddHostExecEnvUserAgentHander) 34 | // handlers.Build.AfterEachFn = aws.HandlerListStopOnError 35 | // handlers.Sign.PushBackNamed(defaults.BuildContentLengthHandler) 36 | // handlers.Send.PushBackNamed(defaults.ValidateReqSigHandler) 37 | // handlers.Send.PushBackNamed(SendHandler) 38 | handlers.Send.PushBackNamed(sendHandler) 39 | // handlers.AfterRetry.PushBackNamed(defaults.AfterRetryHandler) 40 | // handlers.ValidateResponse.PushBackNamed(defaults.ValidateResponseHandler) 41 | 42 | return handlers 43 | } 44 | -------------------------------------------------------------------------------- /s3mem/delete_bucket_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/aws/aws-sdk-go-v2/service/s3" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | const opDeleteBucket = "DeleteBucket" 32 | 33 | //DeleteBucketRequest ... 34 | func (c *Client) DeleteBucketRequest(input *s3.DeleteBucketInput) s3.DeleteBucketRequest { 35 | if input == nil { 36 | input = &s3.DeleteBucketInput{} 37 | } 38 | output := &s3.DeleteBucketOutput{} 39 | op := &aws.Operation{ 40 | Name: opDeleteBucket, 41 | HTTPMethod: "DELETE", 42 | HTTPPath: "/{Bucket}", 43 | } 44 | req := c.NewRequest(op, input, output) 45 | return s3.DeleteBucketRequest{Request: req, Input: input} 46 | } 47 | 48 | func deleteBucket(req *aws.Request) { 49 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 50 | if !S3MemService.IsBucketExist(req.Params.(*s3.DeleteBucketInput).Bucket) { 51 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.DeleteBucketInput).Bucket, nil, nil) 52 | return 53 | } 54 | if !S3MemService.IsBucketEmpty(req.Params.(*s3.DeleteBucketInput).Bucket) { 55 | req.Error = s3memerr.NewError(s3memerr.ErrCodeBucketNotEmpty, "", nil, req.Params.(*s3.DeleteBucketInput).Bucket, nil, nil) 56 | return 57 | } 58 | S3MemService.DeleteBucket(req.Params.(*s3.DeleteBucketInput).Bucket) 59 | //This is needed just to logResponse when requested 60 | body, _ := json.MarshalIndent(req.Data.(*s3.DeleteBucketOutput), "", " ") 61 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 62 | } 63 | -------------------------------------------------------------------------------- /s3mem/delete_bucket_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | func TestDeleteBucketRequest(t *testing.T) { 32 | //Adding bucket directly in mem to prepare the test. 33 | bucketName := strings.ToLower(t.Name()) 34 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 35 | //Request a client 36 | client := New(S3MemTestConfig) 37 | //Create the request 38 | req := client.DeleteBucketRequest(&s3.DeleteBucketInput{ 39 | Bucket: &bucketName, 40 | }) 41 | //Send the request 42 | _, err := req.Send(context.Background()) 43 | assert.NoError(t, err) 44 | bucketGet := S3MemTestService.GetBucket(&bucketName) 45 | assert.Nil(t, bucketGet) 46 | } 47 | 48 | func TestDeleteNotEmptyBucket(t *testing.T) { 49 | bucketName := strings.ToLower(t.Name()) 50 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 51 | //Adding an Object directly in mem to prepare the test. 52 | objectKey := "my-object" 53 | S3MemTestService.PutObject(&bucketName, &objectKey, strings.NewReader(string("test content"))) 54 | //Request a client 55 | client := New(S3MemTestConfig) 56 | //Create the request 57 | req := client.DeleteBucketRequest(&s3.DeleteBucketInput{ 58 | Bucket: &bucketName, 59 | }) 60 | //Send the request 61 | _, err := req.Send(context.Background()) 62 | assert.Error(t, err) 63 | assert.Implements(t, (*s3memerr.S3MemError)(nil), err) 64 | assert.Equal(t, s3memerr.ErrCodeBucketNotEmpty, err.(s3memerr.S3MemError).Code()) 65 | } 66 | -------------------------------------------------------------------------------- /s3mem/delete_object_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/aws/aws-sdk-go-v2/service/s3" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | const opDeleteObject = "DeleteObject" 32 | 33 | //DeleteObjectRequest ... 34 | func (c *Client) DeleteObjectRequest(input *s3.DeleteObjectInput) s3.DeleteObjectRequest { 35 | if input == nil { 36 | input = &s3.DeleteObjectInput{} 37 | } 38 | output := &s3.DeleteObjectOutput{} 39 | op := &aws.Operation{ 40 | Name: opDeleteObject, 41 | HTTPMethod: "DELETE", 42 | HTTPPath: "/{Bucket}/{Key+}", 43 | } 44 | req := c.NewRequest(op, input, output) 45 | return s3.DeleteObjectRequest{Request: req, Input: input} 46 | } 47 | 48 | func deleteObject(req *aws.Request) { 49 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 50 | if !S3MemService.IsBucketExist(req.Params.(*s3.DeleteObjectInput).Bucket) { 51 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.DeleteObjectInput).Bucket, nil, nil) 52 | return 53 | } 54 | if !S3MemService.IsObjectExist(req.Params.(*s3.DeleteObjectInput).Bucket, req.Params.(*s3.DeleteObjectInput).Key) { 55 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchKey, "", nil, req.Params.(*s3.DeleteObjectInput).Bucket, req.Params.(*s3.DeleteObjectInput).Key, req.Params.(*s3.DeleteObjectInput).VersionId) 56 | return 57 | } 58 | deleteMarker, versionID, err := S3MemService.DeleteObject(req.Params.(*s3.DeleteObjectInput).Bucket, req.Params.(*s3.DeleteObjectInput).Key, req.Params.(*s3.DeleteObjectInput).VersionId) 59 | if err != nil { 60 | req.Error = err 61 | return 62 | } 63 | req.Data.(*s3.DeleteObjectOutput).DeleteMarker = deleteMarker 64 | req.Data.(*s3.DeleteObjectOutput).VersionId = versionID 65 | //This is needed just to logResponse when requested 66 | body, _ := json.MarshalIndent(req.Data.(*s3.DeleteObjectOutput), "", " ") 67 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 68 | } 69 | -------------------------------------------------------------------------------- /s3mem/delete_object_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestDeleteObjectRequest(t *testing.T) { 31 | //Adding bucket directly in mem to prepare the test. 32 | bucketName := strings.ToLower(t.Name()) 33 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 34 | //Adding an Object directly in mem to prepare the test. 35 | objectKey := "my-object" 36 | S3MemTestService.PutObject(&bucketName, &objectKey, strings.NewReader(string("test content"))) 37 | //Request a client 38 | client := New(S3MemTestConfig) 39 | //Create the request 40 | req := client.DeleteObjectRequest(&s3.DeleteObjectInput{ 41 | Bucket: &bucketName, 42 | Key: &objectKey, 43 | }) 44 | //Send the request 45 | _, err := req.Send(context.Background()) 46 | assert.NoError(t, err) 47 | object, _, err := S3MemTestService.GetObject(&bucketName, &objectKey, nil) 48 | assert.Error(t, err) 49 | assert.Nil(t, object) 50 | } 51 | 52 | func TestDeleteObjectRequestBucketVersionedThenRestore(t *testing.T) { 53 | //Adding bucket directly in mem to prepare the test. 54 | bucketName := strings.ToLower(t.Name()) 55 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 56 | //Make bucket versioning 57 | S3MemTestService.PutBucketVersioning(&bucketName, nil, &s3.VersioningConfiguration{ 58 | Status: s3.BucketVersioningStatusEnabled, 59 | }) 60 | //Adding an Object directly in mem to prepare the test. 61 | objectKey := "my-object" 62 | content := "test content" 63 | S3MemTestService.PutObject(&bucketName, &objectKey, strings.NewReader(content)) 64 | //Request a client 65 | client := New(S3MemTestConfig) 66 | //Create the request 67 | req := client.DeleteObjectRequest(&s3.DeleteObjectInput{ 68 | Bucket: &bucketName, 69 | Key: &objectKey, 70 | }) 71 | //Send the request 72 | deleteObjectOutput, err := req.Send(context.Background()) 73 | assert.NoError(t, err) 74 | object, _, err := S3MemTestService.GetObject(&bucketName, &objectKey, nil) 75 | assert.Error(t, err) 76 | assert.Nil(t, object) 77 | 78 | //Restore object by delete marker 79 | req = client.DeleteObjectRequest(&s3.DeleteObjectInput{ 80 | Bucket: &bucketName, 81 | Key: &objectKey, 82 | VersionId: deleteObjectOutput.VersionId, 83 | }) 84 | //Send the request 85 | _, err = req.Send(context.Background()) 86 | assert.NoError(t, err) 87 | 88 | object, _, err = S3MemTestService.GetObject(&bucketName, &objectKey, nil) 89 | assert.NoError(t, err) 90 | assert.NotNil(t, object) 91 | 92 | assert.Equal(t, content, string(object.Content)) 93 | 94 | } 95 | -------------------------------------------------------------------------------- /s3mem/delete_objects_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | 26 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 27 | 28 | "github.com/aws/aws-sdk-go-v2/aws" 29 | "github.com/aws/aws-sdk-go-v2/service/s3" 30 | ) 31 | 32 | const opDeleteObjects = "DeleteObjects" 33 | 34 | //DeleteObjectsRequest ... 35 | func (c *Client) DeleteObjectsRequest(input *s3.DeleteObjectsInput) s3.DeleteObjectsRequest { 36 | if input == nil { 37 | input = &s3.DeleteObjectsInput{} 38 | } 39 | output := &s3.DeleteObjectsOutput{ 40 | Deleted: make([]s3.DeletedObject, 0), 41 | Errors: make([]s3.Error, 0), 42 | } 43 | op := &aws.Operation{ 44 | Name: opDeleteObjects, 45 | HTTPMethod: "POST", 46 | HTTPPath: "/{Bucket}?delete", 47 | } 48 | req := c.NewRequest(op, input, output) 49 | return s3.DeleteObjectsRequest{Request: req, Input: input} 50 | } 51 | 52 | func deleteObjects(req *aws.Request) { 53 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 54 | if !S3MemService.IsBucketExist(req.Params.(*s3.DeleteObjectsInput).Bucket) { 55 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.DeleteObjectsInput).Bucket, nil, nil) 56 | return 57 | } 58 | for _, obj := range req.Params.(*s3.DeleteObjectsInput).Delete.Objects { 59 | deleteMarker, versionID, err := S3MemService.DeleteObject(req.Params.(*s3.DeleteObjectsInput).Bucket, obj.Key, obj.VersionId) 60 | if err != nil { 61 | req.Data.(*s3.DeleteObjectsOutput).Errors = append(req.Data.(*s3.DeleteObjectsOutput).Errors, err.Convert2S3Error(obj.Key, obj.VersionId)) 62 | } 63 | req.Data.(*s3.DeleteObjectsOutput).Deleted = append(req.Data.(*s3.DeleteObjectsOutput).Deleted, s3.DeletedObject{ 64 | DeleteMarker: deleteMarker, 65 | DeleteMarkerVersionId: versionID, 66 | VersionId: obj.VersionId, 67 | Key: obj.Key, 68 | }) 69 | } 70 | //This is needed just to logResponse when requested 71 | body, _ := json.MarshalIndent(req.Data.(*s3.DeleteObjectsOutput), "", " ") 72 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 73 | } 74 | -------------------------------------------------------------------------------- /s3mem/delete_objects_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | func TestDeleteObjectsRequest(t *testing.T) { 32 | //Adding bucket directly in mem to prepare the test. 33 | bucketName := strings.ToLower(t.Name()) 34 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 35 | //Adding an Object directly in mem to prepare the test. 36 | objectKey1 := "my-object1" 37 | S3MemTestService.PutObject(&bucketName, &objectKey1, strings.NewReader(string("test contents"))) 38 | //Adding an Object directly in mem to prepare the test. 39 | objectKey2 := "my-object2" 40 | S3MemTestService.PutObject(&bucketName, &objectKey2, strings.NewReader(string("test contents"))) 41 | //Request a client 42 | client := New(S3MemTestConfig) 43 | versionId := "1" 44 | //Create the request 45 | req := client.DeleteObjectsRequest(&s3.DeleteObjectsInput{ 46 | Bucket: &bucketName, 47 | Delete: &s3.Delete{ 48 | Objects: []s3.ObjectIdentifier{ 49 | {Key: &objectKey1, VersionId: &versionId}, 50 | {Key: &objectKey2, VersionId: &versionId}, 51 | }, 52 | }, 53 | }) 54 | //Send the request 55 | _, err := req.Send(context.Background()) 56 | assert.NoError(t, err) 57 | object1, _, err := S3MemTestService.GetObject(&bucketName, &objectKey1, nil) 58 | assert.Error(t, err) 59 | assert.Nil(t, object1) 60 | object2, _, err := S3MemTestService.GetObject(&bucketName, &objectKey2, nil) 61 | assert.Error(t, err) 62 | assert.Nil(t, object2) 63 | } 64 | 65 | func TestDeleteObjectsRequestBucketNotExists(t *testing.T) { 66 | //Adding bucket directly in mem to prepare the test. 67 | bucketName := strings.ToLower(t.Name()) 68 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 69 | //Adding an Object directly in mem to prepare the test. 70 | objectKey1 := "my-object1" 71 | S3MemTestService.PutObject(&bucketName, &objectKey1, strings.NewReader(string("test contents"))) 72 | //Request a client 73 | client := New(S3MemTestConfig) 74 | versionId := "1" 75 | nonExistBucketName := strings.ToLower(t.Name()) + "-1" 76 | //Create the request 77 | req := client.DeleteObjectsRequest(&s3.DeleteObjectsInput{ 78 | Bucket: &nonExistBucketName, 79 | Delete: &s3.Delete{ 80 | Objects: []s3.ObjectIdentifier{ 81 | {Key: &objectKey1, VersionId: &versionId}, 82 | }, 83 | }, 84 | }) 85 | //Send the request 86 | _, err := req.Send(context.Background()) 87 | assert.Error(t, err) 88 | assert.Implements(t, (*s3memerr.S3MemError)(nil), err) 89 | assert.Equal(t, s3.ErrCodeNoSuchBucket, err.(s3memerr.S3MemError).Code()) 90 | } 91 | -------------------------------------------------------------------------------- /s3mem/get_bucket_versioning_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/aws/aws-sdk-go-v2/service/s3" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | const opGetBucketVersioning = "GetBucketVersioning" 32 | 33 | //GetBucketVersioningRequest ... 34 | func (c *Client) GetBucketVersioningRequest(input *s3.GetBucketVersioningInput) s3.GetBucketVersioningRequest { 35 | if input == nil { 36 | input = &s3.GetBucketVersioningInput{} 37 | } 38 | output := &s3.GetBucketVersioningOutput{} 39 | op := &aws.Operation{ 40 | Name: opGetBucketVersioning, 41 | HTTPMethod: "GET", 42 | HTTPPath: "/{Bucket}?versioning", 43 | } 44 | req := c.NewRequest(op, input, output) 45 | return s3.GetBucketVersioningRequest{Request: req, Input: input} 46 | } 47 | 48 | func getBucketVersioning(req *aws.Request) { 49 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 50 | if !S3MemService.IsBucketExist(req.Params.(*s3.GetBucketVersioningInput).Bucket) { 51 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.GetBucketVersioningInput).Bucket, nil, nil) 52 | return 53 | } 54 | _, obj := S3MemService.GetBucketVersioning(req.Params.(*s3.GetBucketVersioningInput).Bucket) 55 | if obj == nil { 56 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.GetBucketVersioningInput).Bucket, nil, nil) 57 | return 58 | } 59 | switch obj.MFADelete { 60 | case s3.MFADeleteEnabled: 61 | req.Data.(*s3.GetBucketVersioningOutput).MFADelete = s3.MFADeleteStatusEnabled 62 | case s3.MFADeleteDisabled: 63 | req.Data.(*s3.GetBucketVersioningOutput).MFADelete = s3.MFADeleteStatusDisabled 64 | default: 65 | } 66 | req.Data.(*s3.GetBucketVersioningOutput).Status = obj.Status 67 | //This is needed just to logResponse when requested 68 | body, _ := json.MarshalIndent(req.Data.(*s3.GetBucketVersioningOutput), "", " ") 69 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 70 | } 71 | -------------------------------------------------------------------------------- /s3mem/get_bucket_versioning_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestGetBucketVersioningRequest(t *testing.T) { 31 | //Adding bucket directly in mem to prepare the test. 32 | bucketName := strings.ToLower(t.Name()) 33 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 34 | 35 | mfa := "122334 13445" 36 | 37 | //Add a VersionConfig 38 | S3MemTestService.PutBucketVersioning(&bucketName, &mfa, &s3.VersioningConfiguration{ 39 | MFADelete: s3.MFADeleteEnabled, 40 | Status: s3.BucketVersioningStatusEnabled, 41 | }) 42 | //Request a client 43 | client := New(S3MemTestConfig) 44 | 45 | //Create request 46 | req := client.GetBucketVersioningRequest(&s3.GetBucketVersioningInput{ 47 | Bucket: &bucketName, 48 | }) 49 | 50 | //Send the request 51 | getBucketVersioningOut, err := req.Send(context.Background()) 52 | assert.NoError(t, err) 53 | assert.Equal(t, s3.MFADeleteStatusEnabled, getBucketVersioningOut.MFADelete) 54 | assert.Equal(t, s3.BucketVersioningStatusEnabled, getBucketVersioningOut.Status) 55 | } 56 | -------------------------------------------------------------------------------- /s3mem/get_object_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/aws/aws-sdk-go-v2/service/s3" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | const opGetObject = "GetObject" 32 | 33 | //GetObjectRequest ... 34 | func (c *Client) GetObjectRequest(input *s3.GetObjectInput) s3.GetObjectRequest { 35 | if input == nil { 36 | input = &s3.GetObjectInput{} 37 | } 38 | output := &s3.GetObjectOutput{} 39 | operation := &aws.Operation{ 40 | Name: opGetObject, 41 | HTTPMethod: "GET", 42 | HTTPPath: "/{Bucket}/{Key+}", 43 | } 44 | req := c.NewRequest(operation, input, output) 45 | return s3.GetObjectRequest{Request: req, Input: input} 46 | } 47 | 48 | func getObject(req *aws.Request) { 49 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 50 | if !S3MemService.IsBucketExist(req.Params.(*s3.GetObjectInput).Bucket) { 51 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.GetObjectInput).Bucket, nil, nil) 52 | } 53 | obj, versionId, err := S3MemService.GetObject(req.Params.(*s3.GetObjectInput).Bucket, req.Params.(*s3.GetObjectInput).Key, req.Params.(*s3.GetObjectInput).VersionId) 54 | if err != nil { 55 | req.Error = err 56 | return 57 | } 58 | if obj == nil { 59 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchKey, "", nil, req.Params.(*s3.GetObjectInput).Bucket, req.Params.(*s3.GetObjectInput).Key, req.Params.(*s3.GetObjectInput).VersionId) 60 | return 61 | } 62 | req.Data.(*s3.GetObjectOutput).Body = ioutil.NopCloser(bytes.NewReader(obj.Content)) 63 | req.Data.(*s3.GetObjectOutput).VersionId = versionId 64 | //This is needed just to logResponse when requested 65 | body, _ := json.MarshalIndent(req.Data.(*s3.GetObjectOutput), "", " ") 66 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 67 | } 68 | -------------------------------------------------------------------------------- /s3mem/get_object_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "context" 24 | "strings" 25 | "testing" 26 | 27 | "github.com/aws/aws-sdk-go-v2/service/s3" 28 | "github.com/stretchr/testify/assert" 29 | ) 30 | 31 | func TestGetObjectRequest(t *testing.T) { 32 | //Adding bucket directly in mem to prepare the test. 33 | bucketName := strings.ToLower(t.Name()) 34 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 35 | //Adding an Object directly in mem to prepare the test. 36 | objectKey := "my-object" 37 | content := "test content" 38 | S3MemTestService.PutObject(&bucketName, &objectKey, strings.NewReader(string(content))) 39 | //Request a client 40 | client := New(S3MemTestConfig) 41 | //Create the request 42 | req := client.GetObjectRequest(&s3.GetObjectInput{ 43 | Bucket: &bucketName, 44 | Key: &objectKey, 45 | }) 46 | //Send the request 47 | object, err := req.Send(context.Background()) 48 | assert.NoError(t, err) 49 | 50 | assert.NotNil(t, object.Body) 51 | 52 | buf := new(bytes.Buffer) 53 | buf.ReadFrom(object.Body) 54 | newBytes := buf.Bytes() 55 | assert.Equal(t, content, string(newBytes)) 56 | } 57 | 58 | func TestGetObjectRequestWithVersioningBucket(t *testing.T) { 59 | //Adding bucket directly in mem to prepare the test. 60 | bucketName := strings.ToLower(t.Name()) 61 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 62 | //Make bucket versioning 63 | S3MemTestService.PutBucketVersioning(&bucketName, nil, &s3.VersioningConfiguration{ 64 | Status: s3.BucketVersioningStatusEnabled, 65 | }) 66 | //Adding an Object 67 | objectKey := "1-my-object" 68 | content1 := "test content 1" 69 | S3MemTestService.PutObject(&bucketName, &objectKey, strings.NewReader(string(content1))) 70 | content2 := "test content 2" 71 | S3MemTestService.PutObject(&bucketName, &objectKey, strings.NewReader(string(content2))) 72 | //Request a client 73 | client := New(S3MemTestConfig) 74 | //Create the request to get the last version 75 | req := client.GetObjectRequest(&s3.GetObjectInput{ 76 | Bucket: &bucketName, 77 | Key: &objectKey, 78 | }) 79 | //Send the request 80 | object, err := req.Send(context.Background()) 81 | assert.NoError(t, err) 82 | 83 | assert.NotNil(t, object.Body) 84 | 85 | buf := new(bytes.Buffer) 86 | buf.ReadFrom(object.Body) 87 | newBytes := buf.Bytes() 88 | assert.Equal(t, content2, string(newBytes)) 89 | 90 | assert.Equal(t, "1", *object.VersionId) 91 | 92 | //Create the request a specific version 93 | versionIDS := "0" 94 | req = client.GetObjectRequest(&s3.GetObjectInput{ 95 | Bucket: &bucketName, 96 | Key: &objectKey, 97 | VersionId: &versionIDS, 98 | }) 99 | //Send the request 100 | object, err = req.Send(context.Background()) 101 | assert.NoError(t, err) 102 | 103 | assert.NotNil(t, object.Body) 104 | 105 | buf = new(bytes.Buffer) 106 | buf.ReadFrom(object.Body) 107 | newBytes = buf.Bytes() 108 | assert.Equal(t, content1, string(newBytes)) 109 | 110 | assert.Equal(t, "0", *object.VersionId) 111 | } 112 | -------------------------------------------------------------------------------- /s3mem/handlers.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package s3mem 19 | 20 | import ( 21 | "github.com/aws/aws-sdk-go-v2/aws" 22 | "github.com/aws/aws-sdk-go-v2/service/s3" 23 | ) 24 | 25 | var checkConfigHandler = aws.NamedHandler{Name: "s3mem.checkConfig", Fn: checkConfig} 26 | var checkACLHandler = aws.NamedHandler{Name: "s3mem.checkACL", Fn: checkACL} 27 | var sendHandler = aws.NamedHandler{Name: "s3mem.sendHandler", Fn: send} 28 | 29 | func checkConfig(r *aws.Request) { 30 | } 31 | 32 | func checkACL(r *aws.Request) { 33 | switch r.Operation.Name { 34 | case "CreateBucketRequest": 35 | } 36 | } 37 | 38 | func send(r *aws.Request) { 39 | switch r.Params.(type) { 40 | case *s3.CopyObjectInput: 41 | copyObject(r) 42 | case *s3.CreateBucketInput: 43 | createBucket(r) 44 | case *s3.DeleteBucketInput: 45 | deleteBucket(r) 46 | case *s3.DeleteObjectInput: 47 | deleteObject(r) 48 | case *s3.DeleteObjectsInput: 49 | deleteObjects(r) 50 | case *s3.GetBucketVersioningInput: 51 | getBucketVersioning(r) 52 | case *s3.GetObjectInput: 53 | getObject(r) 54 | case *s3.ListBucketsInput: 55 | listBuckets(r) 56 | case *s3.ListObjectsInput: 57 | listObjects(r) 58 | case *s3.PutBucketVersioningInput: 59 | putBucketVersioning(r) 60 | case *s3.PutObjectInput: 61 | putObject(r) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /s3mem/helper.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "errors" 23 | "fmt" 24 | "io" 25 | "io/ioutil" 26 | "strconv" 27 | "strings" 28 | "testing" 29 | "time" 30 | 31 | "github.com/aws/aws-sdk-go-v2/service/s3" 32 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 33 | ) 34 | 35 | //NewDefaultS3MemService Creates a new service with "http://s3mem" as url 36 | //Panic if the S3MemService already exists 37 | func NewDefaultS3MemService() *S3MemService { 38 | s3service := S3MemEndpointsID 39 | return NewS3MemService(s3service) 40 | } 41 | 42 | //NewTestS3MemService Creates a new service with concanation of "http://s3mem_" and the test name 43 | //Panic if the S3MemService already exists 44 | func NewTestS3MemService(t *testing.T) *S3MemService { 45 | return NewS3MemService(S3MemEndpointsID + "_" + strings.ToLower(t.Name())) 46 | } 47 | 48 | //NewS3MemService Create a new service with a specific url 49 | //Panic if the S3MemService already exists 50 | func NewS3MemService(s3service string) *S3MemService { 51 | if s3service == "" { 52 | s3service = S3MemEndpointsID 53 | } 54 | if _, ok := S3Store.S3MemServices[s3service]; !ok { 55 | S3Store.S3MemServices[s3service] = &S3MemService{ 56 | URL: s3service, 57 | Buckets: make(map[string]*Bucket, 0), 58 | } 59 | return S3Store.S3MemServices[s3service] 60 | } 61 | panic(fmt.Sprintf("The S3MemService %s already exists", s3service)) 62 | } 63 | 64 | //Delete the current service 65 | func (s *S3MemService) DeleteS3MemService() { 66 | s.deleteS3MemService(s.URL) 67 | } 68 | 69 | func (s *S3MemService) deleteS3MemService(s3service string) { 70 | delete(S3Store.S3MemServices, s3service) 71 | } 72 | 73 | //GetDefaultS3MemService Returns the s3mem service. 74 | //Panic if the service does not exist. 75 | func GetDefaultS3MemService() *S3MemService { 76 | if _, ok := S3Store.S3MemServices[S3MemEndpointsID]; !ok { 77 | panic(fmt.Sprintf("The S3MemService %s doesn't not exist, please call NewDefaultS3MemService() before calling this function", S3MemEndpointsID)) 78 | } 79 | return GetS3MemService(S3MemEndpointsID) 80 | } 81 | 82 | //GetTestS3MemService Returns the s3mem service for the current test. 83 | func GetTestS3MemService(t *testing.T) *S3MemService { 84 | return GetS3MemService(S3MemEndpointsID + "_" + strings.ToLower(t.Name())) 85 | } 86 | 87 | //GetS3MemService Returns the s3mem service of a specific name 88 | func GetS3MemService(s3service string) *S3MemService { 89 | if _, ok := S3Store.S3MemServices[s3service]; !ok { 90 | panic(fmt.Sprintf("The S3MemService %s doesn't not exist, please call NewS3MemService(%s) before calling this function", s3service, s3service)) 91 | } 92 | return S3Store.S3MemServices[s3service] 93 | } 94 | 95 | //Lock Lock the access to the S3MemService 96 | func (s *S3MemService) Lock() { 97 | s3memS3service := GetS3MemService(s.URL) 98 | s3memS3service.Mux.Lock() 99 | } 100 | 101 | //Unlock Unlock the access to the S3MemService 102 | func (s *S3MemService) Unlock() { 103 | s3memS3service := GetS3MemService(s.URL) 104 | s3memS3service.Mux.Unlock() 105 | } 106 | 107 | //GetBucket gets a bucket from memory 108 | //The default s3service is S3MemEndpointsID 109 | func (s *S3MemService) GetBucket(bucket *string) *s3.Bucket { 110 | s3memS3service := GetS3MemService(s.URL) 111 | if _, ok := s3memS3service.Buckets[*bucket]; !ok { 112 | return nil 113 | } 114 | return s3memS3service.Buckets[*bucket].Bucket 115 | } 116 | 117 | //IsBucketExist returns true if bucket exists 118 | //The default s3service is S3MemEndpointsID 119 | func (s *S3MemService) IsBucketExist(bucket *string) bool { 120 | s3memS3service := GetS3MemService(s.URL) 121 | _, ok := s3memS3service.Buckets[*bucket] 122 | return ok 123 | } 124 | 125 | //IsBucketEmpty returns true if bucket is empty 126 | //The default s3service is S3MemEndpointsID 127 | func (s *S3MemService) IsBucketEmpty(bucket *string) bool { 128 | s3memS3service := GetS3MemService(s.URL) 129 | return len(s3memS3service.Buckets[*bucket].Objects) == 0 130 | } 131 | 132 | //CreateBucket adds a bucket in memory 133 | //The default s3service is S3MemEndpointsID 134 | func (s *S3MemService) CreateBucket(b *s3.Bucket) { 135 | s3memS3service := GetS3MemService(s.URL) 136 | tc := time.Now() 137 | b.CreationDate = &tc 138 | s3memS3service.Buckets[*b.Name] = &Bucket{ 139 | Bucket: b, 140 | Objects: make(map[string]*VersionedObjects, 0), 141 | } 142 | } 143 | 144 | //DeleteBucket deletes an object from memory 145 | //The default s3service is S3MemEndpointsID 146 | func (s *S3MemService) DeleteBucket(bucket *string) { 147 | s3memS3service := GetS3MemService(s.URL) 148 | delete(s3memS3service.Buckets, *bucket) 149 | } 150 | 151 | //IsObjectExist returns true if object exists 152 | //The default s3service is S3MemEndpointsID 153 | func (s *S3MemService) IsObjectExist(bucket *string, key *string) bool { 154 | s3memS3service := GetS3MemService(s.URL) 155 | _, ok := s3memS3service.Buckets[*bucket].Objects[*key] 156 | return ok 157 | } 158 | 159 | //PutObject adds an object in memory return the object. 160 | //The default s3service is S3MemEndpointsID 161 | //Raise an error if a failure to read the body occurs 162 | func (s *S3MemService) PutObject(bucket *string, key *string, body io.ReadSeeker) (*Object, *string, error) { 163 | s3memS3service := GetS3MemService(s.URL) 164 | if _, ok := s3memS3service.Buckets[*bucket]; !ok { 165 | s3memS3service.Buckets[*bucket].Objects = make(map[string]*VersionedObjects, 0) 166 | } 167 | if _, ok := s3memS3service.Buckets[*bucket].Objects[*key]; !ok { 168 | s3memS3service.Buckets[*bucket].Objects[*key] = &VersionedObjects{ 169 | VersionedObjects: make([]*Object, 0), 170 | } 171 | } 172 | tc := time.Now() 173 | content, err := ioutil.ReadAll(body) 174 | if err != nil { 175 | return nil, nil, err 176 | } 177 | obj := &Object{ 178 | Object: &s3.Object{ 179 | Key: key, 180 | LastModified: &tc, 181 | StorageClass: "memory", 182 | }, 183 | Content: content, 184 | } 185 | versioning := s3memS3service.Buckets[*bucket].VersioningConfiguration 186 | if versioning != nil && versioning.Status == s3.BucketVersioningStatusEnabled { 187 | s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects = append(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects, obj) 188 | } else { 189 | if len(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects) == 0 { 190 | s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects = append(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects, obj) 191 | } else { 192 | s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[0] = obj 193 | } 194 | } 195 | versionId := strconv.Itoa(len(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects) - 1) 196 | return obj, &versionId, nil 197 | } 198 | 199 | //GetObject gets an object from memory return the Object and its versionID 200 | //The default s3service is S3MemEndpointsID 201 | //Raises an error the bucket or object doesn't exists or if the requested object is deleted, 202 | func (s *S3MemService) GetObject(bucket *string, key *string, versionIDS *string) (object *Object, versionIDSOut *string, s3memerror s3memerr.S3MemError) { 203 | s3memS3service := GetS3MemService(s.URL) 204 | if _, ok := s3memS3service.Buckets[*bucket]; !ok { 205 | return nil, nil, s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, bucket, key, versionIDS) 206 | } 207 | if _, ok := s3memS3service.Buckets[*bucket].Objects[*key]; !ok { 208 | return nil, nil, s3memerr.NewError(s3.ErrCodeNoSuchKey, "", nil, bucket, key, versionIDS) 209 | } 210 | l := len(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects) 211 | if l > 0 { 212 | versioning := s3memS3service.Buckets[*bucket].VersioningConfiguration 213 | if versioning != nil && versioning.Status == s3.BucketVersioningStatusEnabled { 214 | if versionIDS != nil { 215 | versionID, err := strconv.Atoi(*versionIDS) 216 | if err != nil { 217 | return nil, nil, s3memerr.NewError(s3memerr.ErrCodeNoSuchVersion, "Version not a number", err, bucket, key, versionIDS) 218 | } 219 | if versionID >= l { 220 | return nil, nil, s3memerr.NewError(s3memerr.ErrCodeNoSuchVersion, "", nil, bucket, key, versionIDS) 221 | } 222 | object = s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[versionID] 223 | versionIDSOut = versionIDS 224 | s3memerror = nil 225 | } else { 226 | object = s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[l-1] 227 | versionID := strconv.Itoa(l - 1) 228 | versionIDSOut = &versionID 229 | s3memerror = nil 230 | } 231 | } else { 232 | object = s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[l-1] 233 | versionID := strconv.Itoa(l - 1) 234 | versionIDSOut = &versionID 235 | s3memerror = nil 236 | } 237 | if object.DeletedObject != nil { 238 | return nil, nil, s3memerr.NewError(s3memerr.ErrCodeNoSuchVersion, "", nil, bucket, key, versionIDS) 239 | } 240 | return 241 | } 242 | return nil, nil, s3memerr.NewError(s3.ErrCodeNoSuchKey, "", nil, bucket, key, nil) 243 | } 244 | 245 | //DeleteObject Deletes an object 246 | //The default s3service is S3MemEndpointsID 247 | func (s *S3MemService) DeleteObject(bucket *string, key *string, versionIDS *string) (deleteMarkerOut *bool, deleteMarkerVersionIDOut *string, err s3memerr.S3MemError) { 248 | s3memS3service := GetS3MemService(s.URL) 249 | if _, ok := s3memS3service.Buckets[*bucket]; !ok { 250 | return nil, nil, s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", err, bucket, key, versionIDS) 251 | } 252 | if _, ok := s3memS3service.Buckets[*bucket].Objects[*key]; !ok { 253 | return nil, nil, s3memerr.NewError(s3.ErrCodeNoSuchKey, "", nil, bucket, key, versionIDS) 254 | } 255 | l := len(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects) 256 | if l > 0 { 257 | versioning := s3memS3service.Buckets[*bucket].VersioningConfiguration 258 | if versioning != nil && versioning.Status == s3.BucketVersioningStatusEnabled { 259 | deleteMarker := true 260 | if versionIDS != nil { 261 | //if version provided then remove specific version 262 | versionID, err := strconv.Atoi(*versionIDS) 263 | if err != nil { 264 | return nil, nil, s3memerr.NewError(s3memerr.ErrCodeNoSuchVersion, "Version not a number", err, bucket, key, versionIDS) 265 | } 266 | if l-1 == versionID { 267 | s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects = s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[:l-1] 268 | } else { 269 | s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects = append(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[:versionID], s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[versionID+1:]...) 270 | } 271 | } else { 272 | //if version not provided then add a marker object for the same version with no data 273 | deleteMarker = false 274 | currentVersionedObject := s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[l-1] 275 | versionID := strconv.Itoa(l - 1) 276 | deletedObject := &Object{ 277 | DeletedObject: &s3.DeletedObject{ 278 | DeleteMarker: &deleteMarker, 279 | Key: currentVersionedObject.Object.Key, 280 | VersionId: &versionID, 281 | }, 282 | } 283 | s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects = append(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects, deletedObject) 284 | deleteMarkerVersionID := strconv.Itoa(len(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects) - 1) 285 | deleteMarkerVersionIDOut = &deleteMarkerVersionID 286 | deletedObject.DeletedObject.DeleteMarkerVersionId = deleteMarkerVersionIDOut 287 | } 288 | deleteMarkerOut = &deleteMarker 289 | } else { 290 | s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects = s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects[:l-1] 291 | } 292 | } 293 | if len(s3memS3service.Buckets[*bucket].Objects[*key].VersionedObjects) == 0 { 294 | delete(s3memS3service.Buckets[*bucket].Objects, *key) 295 | } 296 | return deleteMarkerOut, deleteMarkerVersionIDOut, nil 297 | } 298 | 299 | //PutBucketVersioning Sets the bucket in versionning mode 300 | //The default s3service is S3MemEndpointsID 301 | func (s *S3MemService) PutBucketVersioning(bucket *string, mfa *string, versioningConfiguration *s3.VersioningConfiguration) error { 302 | s3memS3service := GetS3MemService(s.URL) 303 | s3memS3service.Buckets[*bucket].MFA = mfa 304 | s3memS3service.Buckets[*bucket].VersioningConfiguration = versioningConfiguration 305 | return nil 306 | } 307 | 308 | //GetBucketVersioning gets the versioning configuration. 309 | func (s *S3MemService) GetBucketVersioning(bucket *string) (*string, *s3.VersioningConfiguration) { 310 | s3memS3service := GetS3MemService(s.URL) 311 | if _, ok := s3memS3service.Buckets[*bucket]; !ok { 312 | return nil, nil 313 | } 314 | return s3memS3service.Buckets[*bucket].MFA, s3memS3service.Buckets[*bucket].VersioningConfiguration 315 | } 316 | 317 | //For future development 318 | func CreateUser(canonicalID, email *string) error { 319 | if _, ok := S3MemUsers.Users[*canonicalID]; ok { 320 | return fmt.Errorf("User %s already exists", *canonicalID) 321 | } 322 | S3MemUsers.Users[*canonicalID] = &User{ 323 | CanonicalID: *canonicalID, 324 | Email: *email, 325 | } 326 | return nil 327 | } 328 | 329 | //For future development 330 | func GetUser(canonicalID, email *string) (*User, error) { 331 | if canonicalID == nil { 332 | user, err := searchUserByEmail(email) 333 | if err != nil { 334 | return nil, err 335 | } 336 | return user, nil 337 | } 338 | if user, ok := S3MemUsers.Users[*canonicalID]; ok { 339 | return user, nil 340 | } 341 | return nil, fmt.Errorf("User with email %s not found", *email) 342 | } 343 | 344 | //For future development 345 | func searchUserByEmail(email *string) (*User, error) { 346 | var user *User 347 | for _, v := range S3MemUsers.Users { 348 | if v.Email == *email { 349 | user = v 350 | break 351 | } 352 | } 353 | if user == nil { 354 | return nil, fmt.Errorf("User with email %s not found", *email) 355 | } 356 | return user, nil 357 | } 358 | 359 | func ParseObjectURL(url *string) (bucket, key *string, err error) { 360 | segs := strings.SplitN(*url, "/", 2) 361 | if len(segs) < 2 { 362 | return nil, nil, errors.New("Malformed url") 363 | } 364 | return &segs[0], &segs[1], nil 365 | } 366 | -------------------------------------------------------------------------------- /s3mem/helper_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "fmt" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestGetDefaultS3MemServiceNotExists(t *testing.T) { 31 | defer func() { 32 | if r := recover(); r != nil { 33 | fmt.Println("Recovered in f", r) 34 | } 35 | }() 36 | GetS3MemService(strings.ToLower(t.Name())) 37 | assert.Fail(t, "Panic was expected as the S3Store doesn't exist yet") 38 | } 39 | 40 | func TestGetTestS3MemServiceeNotExists(t *testing.T) { 41 | defer func() { 42 | if r := recover(); r != nil { 43 | fmt.Println("Recovered in f", r) 44 | } 45 | }() 46 | GetTestS3MemService(t) 47 | assert.Fail(t, "Panic was expected as the S3Store doesn't exist yet") 48 | } 49 | 50 | func TestNewS3MemServiceAlreadyExists(t *testing.T) { 51 | defer func() { 52 | if r := recover(); r != nil { 53 | fmt.Println("Recovered in f", r) 54 | } 55 | }() 56 | NewS3MemService(strings.ToLower(t.Name())) 57 | NewS3MemService(strings.ToLower(t.Name())) 58 | assert.Fail(t, "Panic was expected as the S3Store already exists") 59 | } 60 | func TestNewTestServiceAlreadyExists(t *testing.T) { 61 | defer func() { 62 | if r := recover(); r != nil { 63 | fmt.Println("Recovered in f", r) 64 | } 65 | }() 66 | NewTestS3MemService(t) 67 | NewTestS3MemService(t) 68 | assert.Fail(t, "Panic was expected as the S3Store already exists") 69 | } 70 | 71 | func TestDeleteSevice(t *testing.T) { 72 | defer func() { 73 | if r := recover(); r != nil { 74 | fmt.Println("Recovered in f", r) 75 | } 76 | }() 77 | s := NewTestS3MemService(t) 78 | bucketName := strings.ToLower(t.Name()) 79 | s.CreateBucket(&s3.Bucket{Name: &bucketName}) 80 | s.DeleteS3MemService() 81 | GetTestS3MemService(t) 82 | assert.Fail(t, "Panic was expected as the S3Store doesn't exist anymore") 83 | } 84 | func TestParseObjectURL(t *testing.T) { 85 | url := "bucket/folder1/folder2/key" 86 | bucket, key, err := ParseObjectURL(&url) 87 | assert.NoError(t, err) 88 | assert.Equal(t, "bucket", *bucket) 89 | assert.Equal(t, "folder1/folder2/key", *key) 90 | } 91 | -------------------------------------------------------------------------------- /s3mem/list_buckets_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | "sort" 26 | 27 | "github.com/aws/aws-sdk-go-v2/aws" 28 | "github.com/aws/aws-sdk-go-v2/service/s3" 29 | ) 30 | 31 | const opListBuckets = "ListBuckets" 32 | 33 | //ListBucketsRequest ... 34 | func (c *Client) ListBucketsRequest(input *s3.ListBucketsInput) s3.ListBucketsRequest { 35 | if input == nil { 36 | input = &s3.ListBucketsInput{} 37 | } 38 | output := &s3.ListBucketsOutput{} 39 | op := &aws.Operation{ 40 | Name: opListBuckets, 41 | HTTPMethod: "GET", 42 | HTTPPath: "/", 43 | } 44 | req := c.NewRequest(op, input, output) 45 | return s3.ListBucketsRequest{Request: req, Input: input, Copy: c.ListBucketsRequest} 46 | } 47 | 48 | func listBuckets(req *aws.Request) { 49 | if req.Error != nil { 50 | return 51 | } 52 | req.Data.(*s3.ListBucketsOutput).Buckets = make([]s3.Bucket, 0) 53 | s3memBuckets := S3Store.S3MemServices[req.Metadata.Endpoint] 54 | var keys []string 55 | for k := range s3memBuckets.Buckets { 56 | keys = append(keys, k) 57 | } 58 | sort.Strings(keys) 59 | for _, k := range keys { 60 | req.Data.(*s3.ListBucketsOutput).Buckets = append(req.Data.(*s3.ListBucketsOutput).Buckets, *s3memBuckets.Buckets[k].Bucket) 61 | } 62 | //This is needed just to logResponse when requested 63 | body, _ := json.MarshalIndent(req.Data.(*s3.ListBucketsOutput), "", " ") 64 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 65 | } 66 | -------------------------------------------------------------------------------- /s3mem/list_buckets_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package s3mem 19 | 20 | import ( 21 | "context" 22 | "strings" 23 | "testing" 24 | 25 | "github.com/aws/aws-sdk-go-v2/service/s3" 26 | "github.com/stretchr/testify/assert" 27 | ) 28 | 29 | func TestListBucketsRequest(t *testing.T) { 30 | //Need to lock for testing as tests are running concurrently 31 | //and meanwhile another running test could change the stored buckets 32 | S3MemTestService.Lock() 33 | defer S3MemTestService.Unlock() 34 | l := len(S3Store.S3MemServices[S3MemEndpointsID].Buckets) 35 | //Adding bucket directly in mem to prepare the test. 36 | bucket0 := strings.ToLower(t.Name() + "0") 37 | bucket1 := strings.ToLower(t.Name() + "1") 38 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucket0}) 39 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucket1}) 40 | //Request a client 41 | client := New(S3MemTestConfig) 42 | //Create the request 43 | req := client.ListBucketsRequest(&s3.ListBucketsInput{}) 44 | //Send the request 45 | listBucketsOutput, err := req.Send(context.Background()) 46 | //Assert the result 47 | assert.NoError(t, err) 48 | assert.Equal(t, l+2, len(listBucketsOutput.Buckets)) 49 | } 50 | -------------------------------------------------------------------------------- /s3mem/list_objects_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | "sort" 26 | "strings" 27 | 28 | "github.com/aws/aws-sdk-go-v2/aws" 29 | "github.com/aws/aws-sdk-go-v2/service/s3" 30 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 31 | ) 32 | 33 | const opListObjects = "ListObjects" 34 | 35 | //ListObjectsRequest ... 36 | func (c *Client) ListObjectsRequest(input *s3.ListObjectsInput) s3.ListObjectsRequest { 37 | if input == nil { 38 | input = &s3.ListObjectsInput{} 39 | } 40 | output := &s3.ListObjectsOutput{} 41 | op := &aws.Operation{ 42 | Name: opListObjects, 43 | HTTPMethod: "GET", 44 | HTTPPath: "/{Bucket}", 45 | Paginator: &aws.Paginator{ 46 | InputTokens: []string{"Marker"}, 47 | OutputTokens: []string{"NextMarker || Contents[-1].Key"}, 48 | LimitToken: "MaxKeys", 49 | TruncationToken: "IsTruncated", 50 | }, 51 | } 52 | req := c.NewRequest(op, input, output) 53 | return s3.ListObjectsRequest{Request: req, Input: input, Copy: c.ListObjectsRequest} 54 | } 55 | 56 | func listObjects(req *aws.Request) { 57 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 58 | if !S3MemService.IsBucketExist(req.Params.(*s3.ListObjectsInput).Bucket) { 59 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.ListObjectsInput).Bucket, nil, nil) 60 | return 61 | } 62 | req.Data.(*s3.ListObjectsOutput).Contents = make([]s3.Object, 0) 63 | bucket := req.Params.(*s3.ListObjectsInput).Bucket 64 | prefix := req.Params.(*s3.ListObjectsInput).Prefix 65 | s3memBuckets := S3Store.S3MemServices[req.Metadata.Endpoint] 66 | var keys []string 67 | for k := range s3memBuckets.Buckets[*bucket].Objects { 68 | keys = append(keys, k) 69 | } 70 | sort.Strings(keys) 71 | for _, k := range keys { 72 | obj := s3memBuckets.Buckets[*bucket].Objects[k] 73 | if prefix != nil { 74 | if strings.HasPrefix(*obj.VersionedObjects[0].Object.Key, *prefix) { 75 | req.Data.(*s3.ListObjectsOutput).Contents = append(req.Data.(*s3.ListObjectsOutput).Contents, *obj.VersionedObjects[0].Object) 76 | } 77 | } else { 78 | req.Data.(*s3.ListObjectsOutput).Contents = append(req.Data.(*s3.ListObjectsOutput).Contents, *obj.VersionedObjects[0].Object) 79 | } 80 | } 81 | //This is needed just to logResponse when requested 82 | body, _ := json.MarshalIndent(req.Data.(*s3.ListObjectsOutput), "", " ") 83 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 84 | } 85 | -------------------------------------------------------------------------------- /s3mem/list_objects_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package s3mem 19 | 20 | import ( 21 | "context" 22 | "strings" 23 | "testing" 24 | 25 | "github.com/aws/aws-sdk-go-v2/service/s3" 26 | "github.com/stretchr/testify/assert" 27 | ) 28 | 29 | func TestListObjectssRequest(t *testing.T) { 30 | //Need to lock for testing as tests are running concurrently 31 | //and meanwhile another running test could change the stored buckets 32 | S3MemTestService.Lock() 33 | defer S3MemTestService.Unlock() 34 | 35 | //Adding bucket directly in mem to prepare the test. 36 | bucketName := strings.ToLower(t.Name()) 37 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 38 | //Adding an Object directly in mem to prepare the test. 39 | objectKey1 := "1-my-object" 40 | content1 := "test content 1" 41 | S3MemTestService.PutObject(&bucketName, &objectKey1, strings.NewReader(string(content1))) 42 | objectKey2 := "2-my-object" 43 | content2 := "test content 2" 44 | S3MemTestService.PutObject(&bucketName, &objectKey2, strings.NewReader(string(content2))) 45 | 46 | //Request a client 47 | client := New(S3MemTestConfig) 48 | //Create the request 49 | req := client.ListObjectsRequest(&s3.ListObjectsInput{ 50 | Bucket: &bucketName, 51 | }) 52 | //Send the request 53 | listObjectsOutput, err := req.Send(context.Background()) 54 | //Assert the result 55 | assert.NoError(t, err) 56 | assert.Equal(t, 2, len(listObjectsOutput.Contents)) 57 | //Create the request 58 | prefix := "1" 59 | req = client.ListObjectsRequest(&s3.ListObjectsInput{ 60 | Bucket: &bucketName, 61 | Prefix: &prefix, 62 | }) 63 | //Send the request 64 | listObjectsOutput, err = req.Send(context.Background()) 65 | //Assert the result 66 | assert.NoError(t, err) 67 | assert.Equal(t, 1, len(listObjectsOutput.Contents)) 68 | } 69 | -------------------------------------------------------------------------------- /s3mem/put_bucket_versioning_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/aws/aws-sdk-go-v2/service/s3" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | const opPutBucketVersioning = "PutBucketVersioning" 32 | 33 | //PutBucketVersioningRequest ... 34 | func (c *Client) PutBucketVersioningRequest(input *s3.PutBucketVersioningInput) s3.PutBucketVersioningRequest { 35 | if input == nil { 36 | input = &s3.PutBucketVersioningInput{} 37 | } 38 | output := &s3.PutBucketVersioningOutput{} 39 | op := &aws.Operation{ 40 | Name: opPutBucketVersioning, 41 | HTTPMethod: "PUT", 42 | HTTPPath: "/{Bucket}?versioning", 43 | } 44 | req := c.NewRequest(op, input, output) 45 | return s3.PutBucketVersioningRequest{Request: req, Input: input} 46 | } 47 | 48 | func putBucketVersioningBucketExists(req *aws.Request) { 49 | } 50 | 51 | func putBucketVersioning(req *aws.Request) { 52 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 53 | if !S3MemService.IsBucketExist(req.Params.(*s3.PutBucketVersioningInput).Bucket) { 54 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.PutBucketVersioningInput).Bucket, nil, nil) 55 | return 56 | } 57 | err := S3MemService.PutBucketVersioning(req.Params.(*s3.PutBucketVersioningInput).Bucket, req.Params.(*s3.PutBucketVersioningInput).MFA, req.Params.(*s3.PutBucketVersioningInput).VersioningConfiguration) 58 | if err != nil { 59 | req.Error = s3memerr.NewError(s3memerr.ErrCodeIllegalVersioningConfigurationException, "", nil, req.Params.(*s3.PutBucketVersioningInput).Bucket, nil, nil) 60 | } 61 | //This is needed just to logResponse when requested 62 | body, _ := json.MarshalIndent(req.Data.(*s3.PutBucketVersioningOutput), "", " ") 63 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 64 | } 65 | -------------------------------------------------------------------------------- /s3mem/put_bucket_versioning_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestPutBucketVersioningRequestMFAString(t *testing.T) { 31 | //Adding bucket directly in mem to prepare the test. 32 | bucketName := strings.ToLower(t.Name()) 33 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 34 | 35 | //Request a client 36 | client := New(S3MemTestConfig) 37 | mfa := "122334 13445" 38 | req := client.PutBucketVersioningRequest(&s3.PutBucketVersioningInput{ 39 | Bucket: &bucketName, 40 | MFA: &mfa, 41 | }) 42 | //Send the request 43 | putBucketVersioningOutput, err := req.Send(context.Background()) 44 | //Assert the result 45 | assert.NoError(t, err) 46 | assert.NotNil(t, putBucketVersioningOutput) 47 | mfaOut, _ := S3MemTestService.GetBucketVersioning(&bucketName) 48 | assert.NotNil(t, mfaOut) 49 | assert.Equal(t, mfa, *mfaOut) 50 | } 51 | 52 | func TestPutBucketVersioningRequestMFAEnable(t *testing.T) { 53 | //Adding bucket directly in mem to prepare the test. 54 | bucketName := strings.ToLower(t.Name()) 55 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 56 | 57 | //Request a client 58 | client := New(S3MemTestConfig) 59 | mfa := "122334 13445" 60 | req := client.PutBucketVersioningRequest(&s3.PutBucketVersioningInput{ 61 | Bucket: &bucketName, 62 | MFA: &mfa, 63 | VersioningConfiguration: &s3.VersioningConfiguration{ 64 | MFADelete: s3.MFADeleteEnabled, 65 | Status: s3.BucketVersioningStatusEnabled, 66 | }, 67 | }) 68 | //Send the request 69 | putBucketVersioningOutput, err := req.Send(context.Background()) 70 | //Assert the result 71 | assert.NoError(t, err) 72 | assert.NotNil(t, putBucketVersioningOutput) 73 | _, versioningConfigurationOut := S3MemTestService.GetBucketVersioning(&bucketName) 74 | assert.NotNil(t, versioningConfigurationOut) 75 | assert.Equal(t, s3.MFADeleteEnabled, versioningConfigurationOut.MFADelete) 76 | } 77 | 78 | func TestPutBucketVersioningRequestMFADisabled(t *testing.T) { 79 | //Adding bucket directly in mem to prepare the test. 80 | bucketName := strings.ToLower(t.Name()) 81 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 82 | 83 | //Request a client 84 | client := New(S3MemTestConfig) 85 | mfa := "122334 13445" 86 | req := client.PutBucketVersioningRequest(&s3.PutBucketVersioningInput{ 87 | Bucket: &bucketName, 88 | MFA: &mfa, 89 | VersioningConfiguration: &s3.VersioningConfiguration{ 90 | MFADelete: s3.MFADeleteDisabled, 91 | }, 92 | }) 93 | //Send the request 94 | putBucketVersioningOutput, err := req.Send(context.Background()) 95 | //Assert the result 96 | assert.NoError(t, err) 97 | assert.NotNil(t, putBucketVersioningOutput) 98 | _, versioningConfigurationOut := S3MemTestService.GetBucketVersioning(&bucketName) 99 | assert.NotNil(t, versioningConfigurationOut) 100 | assert.Equal(t, s3.MFADeleteDisabled, versioningConfigurationOut.MFADelete) 101 | } 102 | 103 | func TestPutBucketVersioningRequestStatusEnabled(t *testing.T) { 104 | //Adding bucket directly in mem to prepare the test. 105 | bucketName := strings.ToLower(t.Name()) 106 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 107 | 108 | //Request a client 109 | client := New(S3MemTestConfig) 110 | mfa := "122334 13445" 111 | req := client.PutBucketVersioningRequest(&s3.PutBucketVersioningInput{ 112 | Bucket: &bucketName, 113 | MFA: &mfa, 114 | VersioningConfiguration: &s3.VersioningConfiguration{ 115 | Status: s3.BucketVersioningStatusEnabled, 116 | }, 117 | }) 118 | //Send the request 119 | putBucketVersioningOutput, err := req.Send(context.Background()) 120 | //Assert the result 121 | assert.NoError(t, err) 122 | assert.NotNil(t, putBucketVersioningOutput) 123 | _, versioningConfigurationOut := S3MemTestService.GetBucketVersioning(&bucketName) 124 | assert.NotNil(t, versioningConfigurationOut) 125 | assert.Equal(t, s3.BucketVersioningStatusEnabled, versioningConfigurationOut.Status) 126 | } 127 | 128 | func TestPutBucketVersioningRequestStatusSuspended(t *testing.T) { 129 | //Adding bucket directly in mem to prepare the test. 130 | bucketName := strings.ToLower(t.Name()) 131 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 132 | 133 | //Request a client 134 | client := New(S3MemTestConfig) 135 | mfa := "122334 13445" 136 | req := client.PutBucketVersioningRequest(&s3.PutBucketVersioningInput{ 137 | Bucket: &bucketName, 138 | MFA: &mfa, 139 | VersioningConfiguration: &s3.VersioningConfiguration{ 140 | Status: s3.BucketVersioningStatusSuspended, 141 | }, 142 | }) 143 | //Send the request 144 | putBucketVersioningOutput, err := req.Send(context.Background()) 145 | //Assert the result 146 | assert.NoError(t, err) 147 | assert.NotNil(t, putBucketVersioningOutput) 148 | _, versioningConfigurationOut := S3MemTestService.GetBucketVersioning(&bucketName) 149 | assert.NotNil(t, versioningConfigurationOut) 150 | assert.Equal(t, s3.BucketVersioningStatusSuspended, versioningConfigurationOut.Status) 151 | } 152 | -------------------------------------------------------------------------------- /s3mem/put_object_request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "bytes" 23 | "encoding/json" 24 | "io/ioutil" 25 | 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/aws/aws-sdk-go-v2/service/s3" 28 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 29 | ) 30 | 31 | const opPutObject = "PutObject" 32 | 33 | //PutObjectRequest ... 34 | func (c *Client) PutObjectRequest(input *s3.PutObjectInput) s3.PutObjectRequest { 35 | if input == nil { 36 | input = &s3.PutObjectInput{} 37 | } 38 | output := &s3.PutObjectOutput{} 39 | op := &aws.Operation{ 40 | Name: opPutObject, 41 | HTTPMethod: "PUT", 42 | HTTPPath: "/{Bucket}/{Key+}", 43 | } 44 | req := c.NewRequest(op, input, output) 45 | return s3.PutObjectRequest{Request: req, Input: input} 46 | } 47 | 48 | func putObject(req *aws.Request) { 49 | S3MemService := GetS3MemService(req.Metadata.Endpoint) 50 | if !S3MemService.IsBucketExist(req.Params.(*s3.PutObjectInput).Bucket) { 51 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchBucket, "", nil, req.Params.(*s3.PutObjectInput).Bucket, nil, nil) 52 | return 53 | } 54 | _, _, err := S3MemService.PutObject(req.Params.(*s3.PutObjectInput).Bucket, req.Params.(*s3.PutObjectInput).Key, req.Params.(*s3.PutObjectInput).Body) 55 | if err != nil { 56 | req.Error = s3memerr.NewError(s3.ErrCodeNoSuchUpload, "", nil, req.Params.(*s3.PutObjectInput).Bucket, req.Params.(*s3.PutObjectInput).Key, nil) 57 | } 58 | //This is needed just to logResponse when requested 59 | body, _ := json.MarshalIndent(req.Data.(*s3.PutObjectOutput), "", " ") 60 | req.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(body)) 61 | } 62 | -------------------------------------------------------------------------------- /s3mem/put_object_request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "strings" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/service/s3" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestPutObjectRequest(t *testing.T) { 31 | //Adding bucket directly in mem to prepare the test. 32 | bucketName := strings.ToLower(t.Name()) 33 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 34 | //Adding an Object 35 | objectKey := "my-object" 36 | content := "test content" 37 | //Request a client 38 | client := New(S3MemTestConfig) 39 | //Create the request 40 | req := client.PutObjectRequest(&s3.PutObjectInput{ 41 | Bucket: &bucketName, 42 | Key: &objectKey, 43 | Body: strings.NewReader(string(content)), 44 | }) 45 | //Send the request 46 | _, err := req.Send(context.Background()) 47 | assert.NoError(t, err) 48 | 49 | object, _, err := S3MemTestService.GetObject(&bucketName, &objectKey, nil) 50 | assert.NoError(t, err) 51 | assert.NotNil(t, object) 52 | 53 | assert.Equal(t, content, string(object.Content)) 54 | } 55 | 56 | func TestPutObjectRequestWithVersioningBucket(t *testing.T) { 57 | //Adding bucket directly in mem to prepare the test. 58 | bucketName := strings.ToLower(t.Name()) 59 | S3MemTestService.CreateBucket(&s3.Bucket{Name: &bucketName}) 60 | //Make bucket versioning 61 | S3MemTestService.PutBucketVersioning(&bucketName, nil, &s3.VersioningConfiguration{ 62 | Status: s3.BucketVersioningStatusEnabled, 63 | }) 64 | //Adding an Object 65 | objectKey := "my-object-1" 66 | content1 := "test content 1" 67 | //Request a client 68 | client := New(S3MemTestConfig) 69 | //Create the request 70 | req := client.PutObjectRequest(&s3.PutObjectInput{ 71 | Bucket: &bucketName, 72 | Key: &objectKey, 73 | Body: strings.NewReader(string(content1)), 74 | }) 75 | //Send the request 76 | _, err := req.Send(context.Background()) 77 | assert.NoError(t, err) 78 | 79 | object1, _, err := S3MemTestService.GetObject(&bucketName, &objectKey, nil) 80 | assert.NoError(t, err) 81 | assert.NotNil(t, object1) 82 | 83 | assert.Equal(t, content1, string(object1.Content)) 84 | 85 | content2 := "test content 2" 86 | 87 | //Create the request 88 | req = client.PutObjectRequest(&s3.PutObjectInput{ 89 | Bucket: &bucketName, 90 | Key: &objectKey, 91 | Body: strings.NewReader(string(content2)), 92 | }) 93 | //Send the request 94 | _, err = req.Send(context.Background()) 95 | assert.NoError(t, err) 96 | 97 | //Get last version 98 | object2, versionID, err := S3MemTestService.GetObject(&bucketName, &objectKey, nil) 99 | assert.NoError(t, err) 100 | assert.NotNil(t, object2) 101 | assert.Equal(t, "1", *versionID) 102 | 103 | assert.Equal(t, content2, string(object2.Content)) 104 | 105 | //Get Specific version 106 | versionIDS := "0" 107 | object3, versionID, err := S3MemTestService.GetObject(&bucketName, &objectKey, &versionIDS) 108 | assert.NoError(t, err) 109 | assert.NotNil(t, object3) 110 | assert.Equal(t, content1, string(object1.Content)) 111 | assert.Equal(t, "0", *versionID) 112 | 113 | } 114 | -------------------------------------------------------------------------------- /s3mem/request.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package s3mem 19 | 20 | import ( 21 | "net/http" 22 | "net/url" 23 | "time" 24 | 25 | "github.com/aws/aws-sdk-go-v2/aws" 26 | "github.com/aws/aws-sdk-go-v2/aws/awserr" 27 | "github.com/aws/aws-sdk-go-v2/aws/endpoints" 28 | "github.com/aws/aws-sdk-go-v2/service/s3" 29 | ) 30 | 31 | func (c *Client) NewRequest(operation *aws.Operation, params interface{}, data interface{}) *aws.Request { 32 | 33 | // TODO improve this experiance for config copy? 34 | cfg := c.Config.Copy() 35 | method := operation.HTTPMethod 36 | if method == "" { 37 | method = "POST" 38 | } 39 | 40 | httpReq, _ := http.NewRequest(method, "", nil) 41 | 42 | metadata := c.Metadata 43 | // if metadata.EndpointsID == "" { 44 | // metadata.EndpointsID = s3.EndpointsID 45 | // } 46 | 47 | // if cfg.Region == nil { 48 | // cfg.Region = endpoints.UsEast1RegionID 49 | // } 50 | 51 | // if cfg.EndpointResolver == nil { 52 | // cfg.EndpointResolver = NewDefaultResolver() 53 | // } 54 | 55 | // TODO need better way of handling this error... NewRequest should return error. 56 | endpoint, err := cfg.EndpointResolver.ResolveEndpoint(metadata.EndpointsID, cfg.Region) 57 | if err == nil { 58 | // TODO so ugly 59 | metadata.Endpoint = endpoint.URL 60 | if len(endpoint.SigningName) > 0 && !endpoint.SigningNameDerived { 61 | metadata.SigningName = endpoint.SigningName 62 | } 63 | if len(endpoint.SigningRegion) > 0 { 64 | metadata.SigningRegion = endpoint.SigningRegion 65 | } 66 | 67 | httpReq.URL, err = url.Parse(endpoint.URL + operation.HTTPPath) 68 | if err != nil { 69 | httpReq.URL = &url.URL{} 70 | err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err) 71 | } 72 | } 73 | 74 | handlers := c.Handlers 75 | 76 | r := &aws.Request{ 77 | Config: aws.Config{ 78 | Region: cfg.Region, 79 | Credentials: cfg.Credentials, 80 | Handlers: cfg.Handlers, 81 | LogLevel: cfg.LogLevel, 82 | Logger: cfg.Logger, 83 | }, 84 | Metadata: metadata, 85 | Handlers: handlers.Copy(), 86 | 87 | Time: time.Now(), 88 | ExpireTime: 0, 89 | Operation: operation, 90 | HTTPRequest: httpReq, 91 | HTTPResponse: &http.Response{}, 92 | Body: nil, 93 | Params: params, 94 | Error: nil, 95 | Data: data, 96 | } 97 | r.SetBufferBody([]byte{}) 98 | 99 | return r 100 | } 101 | 102 | func NewDefaultResolver() aws.EndpointResolver { 103 | defaultResolver := endpoints.NewDefaultResolver() 104 | myCustomResolver := func(service, region string) (aws.Endpoint, error) { 105 | if service == s3.EndpointsID { 106 | return aws.Endpoint{ 107 | URL: S3MemEndpointsID, 108 | }, nil 109 | } 110 | return defaultResolver.ResolveEndpoint(service, region) 111 | } 112 | endpointResolver := aws.EndpointResolverFunc(myCustomResolver) 113 | return endpointResolver 114 | } 115 | -------------------------------------------------------------------------------- /s3mem/request_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | package s3mem 19 | 20 | import ( 21 | "testing" 22 | 23 | "github.com/aws/aws-sdk-go-v2/service/s3" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestNewDefaultResolver(t *testing.T) { 28 | resolver := NewDefaultResolver() 29 | endpoint, err := resolver.ResolveEndpoint(s3.EndpointsID, "region") 30 | assert.NoError(t, err) 31 | assert.Equal(t, S3MemEndpointsID, endpoint.URL) 32 | } 33 | -------------------------------------------------------------------------------- /s3mem/s3mem.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "net/http" 24 | 25 | "github.com/aws/aws-sdk-go-v2/service/s3/s3iface" 26 | 27 | "github.com/aws/aws-sdk-go-v2/aws" 28 | "github.com/aws/aws-sdk-go-v2/service/s3" 29 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 30 | ) 31 | 32 | var S3Store S3MemServices 33 | var S3MemUsers Users 34 | 35 | var _ s3iface.ClientAPI = (s3iface.ClientAPI)(nil) 36 | 37 | func init() { 38 | S3Store.S3MemServices = make(map[string]*S3MemService, 0) 39 | S3MemUsers.Users = make(map[string]*User, 0) 40 | S3MemUsers.Users["admin"] = &User{ 41 | CanonicalID: "admin", 42 | Email: "admin@acme.com", 43 | } 44 | } 45 | 46 | func (c *Client) NotImplemented() *aws.Request { 47 | req := &aws.Request{ 48 | HTTPRequest: &http.Request{}, 49 | } 50 | req.Error = s3memerr.NewError(s3memerr.ErrCodeNotImplemented, "Not implemented", nil, nil, nil, nil) 51 | return req 52 | } 53 | 54 | //AbortMultipartUploadRequest ... 55 | func (c *Client) AbortMultipartUploadRequest(input *s3.AbortMultipartUploadInput) s3.AbortMultipartUploadRequest { 56 | req := c.NotImplemented() 57 | return s3.AbortMultipartUploadRequest{Request: req, Input: input, Copy: nil} 58 | } 59 | 60 | //CompleteMultipartUploadRequest ... 61 | func (c *Client) CompleteMultipartUploadRequest(input *s3.CompleteMultipartUploadInput) s3.CompleteMultipartUploadRequest { 62 | req := c.NotImplemented() 63 | return s3.CompleteMultipartUploadRequest{Request: req, Input: input, Copy: nil} 64 | } 65 | 66 | //CreateMultipartUploadRequest ... 67 | func (c *Client) CreateMultipartUploadRequest(input *s3.CreateMultipartUploadInput) s3.CreateMultipartUploadRequest { 68 | req := c.NotImplemented() 69 | return s3.CreateMultipartUploadRequest{Request: req, Input: input, Copy: nil} 70 | } 71 | 72 | //DeleteBucketAnalyticsConfigurationRequest ... 73 | func (c *Client) DeleteBucketAnalyticsConfigurationRequest(input *s3.DeleteBucketAnalyticsConfigurationInput) s3.DeleteBucketAnalyticsConfigurationRequest { 74 | req := c.NotImplemented() 75 | return s3.DeleteBucketAnalyticsConfigurationRequest{Request: req, Input: input, Copy: nil} 76 | } 77 | 78 | //DeleteBucketCorsRequest ... 79 | func (c *Client) DeleteBucketCorsRequest(input *s3.DeleteBucketCorsInput) s3.DeleteBucketCorsRequest { 80 | req := c.NotImplemented() 81 | return s3.DeleteBucketCorsRequest{Request: req, Input: input, Copy: nil} 82 | } 83 | 84 | //DeleteBucketEncryptionRequest ... 85 | func (c *Client) DeleteBucketEncryptionRequest(input *s3.DeleteBucketEncryptionInput) s3.DeleteBucketEncryptionRequest { 86 | req := c.NotImplemented() 87 | return s3.DeleteBucketEncryptionRequest{Request: req, Input: input, Copy: nil} 88 | } 89 | 90 | //DeleteBucketInventoryConfigurationRequest ... 91 | func (c *Client) DeleteBucketInventoryConfigurationRequest(input *s3.DeleteBucketInventoryConfigurationInput) s3.DeleteBucketInventoryConfigurationRequest { 92 | req := c.NotImplemented() 93 | return s3.DeleteBucketInventoryConfigurationRequest{Request: req, Input: input, Copy: nil} 94 | } 95 | 96 | //DeleteBucketLifecycleRequest ... 97 | func (c *Client) DeleteBucketLifecycleRequest(input *s3.DeleteBucketLifecycleInput) s3.DeleteBucketLifecycleRequest { 98 | req := c.NotImplemented() 99 | return s3.DeleteBucketLifecycleRequest{Request: req, Input: input, Copy: nil} 100 | } 101 | 102 | //DeleteBucketMetricsConfigurationRequest ... 103 | func (c *Client) DeleteBucketMetricsConfigurationRequest(input *s3.DeleteBucketMetricsConfigurationInput) s3.DeleteBucketMetricsConfigurationRequest { 104 | req := c.NotImplemented() 105 | return s3.DeleteBucketMetricsConfigurationRequest{Request: req, Input: input, Copy: nil} 106 | } 107 | 108 | //DeleteBucketPolicyRequest ... 109 | func (c *Client) DeleteBucketPolicyRequest(input *s3.DeleteBucketPolicyInput) s3.DeleteBucketPolicyRequest { 110 | req := c.NotImplemented() 111 | return s3.DeleteBucketPolicyRequest{Request: req, Input: input, Copy: nil} 112 | } 113 | 114 | //DeleteBucketReplicationRequest ... 115 | func (c *Client) DeleteBucketReplicationRequest(input *s3.DeleteBucketReplicationInput) s3.DeleteBucketReplicationRequest { 116 | req := c.NotImplemented() 117 | return s3.DeleteBucketReplicationRequest{Request: req, Input: input, Copy: nil} 118 | } 119 | 120 | //DeleteBucketTaggingRequest ... 121 | func (c *Client) DeleteBucketTaggingRequest(input *s3.DeleteBucketTaggingInput) s3.DeleteBucketTaggingRequest { 122 | req := c.NotImplemented() 123 | return s3.DeleteBucketTaggingRequest{Request: req, Input: input, Copy: nil} 124 | } 125 | 126 | //DeleteBucketWebsiteRequest ... 127 | func (c *Client) DeleteBucketWebsiteRequest(input *s3.DeleteBucketWebsiteInput) s3.DeleteBucketWebsiteRequest { 128 | req := c.NotImplemented() 129 | return s3.DeleteBucketWebsiteRequest{Request: req, Input: input, Copy: nil} 130 | } 131 | 132 | //DeleteObjectTaggingRequest ... 133 | func (c *Client) DeleteObjectTaggingRequest(input *s3.DeleteObjectTaggingInput) s3.DeleteObjectTaggingRequest { 134 | req := c.NotImplemented() 135 | return s3.DeleteObjectTaggingRequest{Request: req, Input: input, Copy: nil} 136 | } 137 | 138 | //DeletePublicAccessBlockRequest ... 139 | func (c *Client) DeletePublicAccessBlockRequest(input *s3.DeletePublicAccessBlockInput) s3.DeletePublicAccessBlockRequest { 140 | req := c.NotImplemented() 141 | return s3.DeletePublicAccessBlockRequest{Request: req, Input: input, Copy: nil} 142 | } 143 | 144 | //GetBucketAccelerateConfigurationRequest ... 145 | func (c *Client) GetBucketAccelerateConfigurationRequest(input *s3.GetBucketAccelerateConfigurationInput) s3.GetBucketAccelerateConfigurationRequest { 146 | req := c.NotImplemented() 147 | return s3.GetBucketAccelerateConfigurationRequest{Request: req, Input: input, Copy: nil} 148 | } 149 | 150 | //GetBucketAclRequest ... 151 | func (c *Client) GetBucketAclRequest(input *s3.GetBucketAclInput) s3.GetBucketAclRequest { 152 | req := c.NotImplemented() 153 | return s3.GetBucketAclRequest{Request: req, Input: input, Copy: nil} 154 | } 155 | 156 | //GetBucketAnalyticsConfigurationRequest ... 157 | func (c *Client) GetBucketAnalyticsConfigurationRequest(input *s3.GetBucketAnalyticsConfigurationInput) s3.GetBucketAnalyticsConfigurationRequest { 158 | req := c.NotImplemented() 159 | return s3.GetBucketAnalyticsConfigurationRequest{Request: req, Input: input, Copy: nil} 160 | } 161 | 162 | //GetBucketCorsRequest ... 163 | func (c *Client) GetBucketCorsRequest(input *s3.GetBucketCorsInput) s3.GetBucketCorsRequest { 164 | req := c.NotImplemented() 165 | return s3.GetBucketCorsRequest{Request: req, Input: input, Copy: nil} 166 | } 167 | 168 | //GetBucketEncryptionRequest ... 169 | func (c *Client) GetBucketEncryptionRequest(input *s3.GetBucketEncryptionInput) s3.GetBucketEncryptionRequest { 170 | req := c.NotImplemented() 171 | return s3.GetBucketEncryptionRequest{Request: req, Input: input, Copy: nil} 172 | } 173 | 174 | //GetBucketInventoryConfigurationRequest ... 175 | func (c *Client) GetBucketInventoryConfigurationRequest(input *s3.GetBucketInventoryConfigurationInput) s3.GetBucketInventoryConfigurationRequest { 176 | req := c.NotImplemented() 177 | return s3.GetBucketInventoryConfigurationRequest{Request: req, Input: input, Copy: nil} 178 | } 179 | 180 | //GetBucketLifecycleRequest ... 181 | func (c *Client) GetBucketLifecycleRequest(input *s3.GetBucketLifecycleInput) s3.GetBucketLifecycleRequest { 182 | req := c.NotImplemented() 183 | return s3.GetBucketLifecycleRequest{Request: req, Input: input, Copy: nil} 184 | } 185 | 186 | //GetBucketLifecycleConfigurationRequest ... 187 | func (c *Client) GetBucketLifecycleConfigurationRequest(input *s3.GetBucketLifecycleConfigurationInput) s3.GetBucketLifecycleConfigurationRequest { 188 | req := c.NotImplemented() 189 | return s3.GetBucketLifecycleConfigurationRequest{Request: req, Input: input, Copy: nil} 190 | } 191 | 192 | //GetBucketLocationRequest ... 193 | func (c *Client) GetBucketLocationRequest(input *s3.GetBucketLocationInput) s3.GetBucketLocationRequest { 194 | req := c.NotImplemented() 195 | return s3.GetBucketLocationRequest{Request: req, Input: input, Copy: nil} 196 | } 197 | 198 | //GetBucketLoggingRequest ... 199 | func (c *Client) GetBucketLoggingRequest(input *s3.GetBucketLoggingInput) s3.GetBucketLoggingRequest { 200 | req := c.NotImplemented() 201 | return s3.GetBucketLoggingRequest{Request: req, Input: input, Copy: nil} 202 | } 203 | 204 | //GetBucketMetricsConfigurationRequest ... 205 | func (c *Client) GetBucketMetricsConfigurationRequest(input *s3.GetBucketMetricsConfigurationInput) s3.GetBucketMetricsConfigurationRequest { 206 | req := c.NotImplemented() 207 | return s3.GetBucketMetricsConfigurationRequest{Request: req, Input: input, Copy: nil} 208 | } 209 | 210 | //GetBucketNotificationRequest ... 211 | func (c *Client) GetBucketNotificationRequest(input *s3.GetBucketNotificationInput) s3.GetBucketNotificationRequest { 212 | req := c.NotImplemented() 213 | return s3.GetBucketNotificationRequest{Request: req, Input: input, Copy: nil} 214 | } 215 | 216 | //GetBucketNotificationConfigurationRequest ... 217 | func (c *Client) GetBucketNotificationConfigurationRequest(input *s3.GetBucketNotificationConfigurationInput) s3.GetBucketNotificationConfigurationRequest { 218 | req := c.NotImplemented() 219 | return s3.GetBucketNotificationConfigurationRequest{Request: req, Input: input, Copy: nil} 220 | } 221 | 222 | //GetBucketPolicyRequest ... 223 | func (c *Client) GetBucketPolicyRequest(input *s3.GetBucketPolicyInput) s3.GetBucketPolicyRequest { 224 | req := c.NotImplemented() 225 | return s3.GetBucketPolicyRequest{Request: req, Input: input, Copy: nil} 226 | } 227 | 228 | //GetBucketPolicyStatusRequest ... 229 | func (c *Client) GetBucketPolicyStatusRequest(input *s3.GetBucketPolicyStatusInput) s3.GetBucketPolicyStatusRequest { 230 | req := c.NotImplemented() 231 | return s3.GetBucketPolicyStatusRequest{Request: req, Input: input, Copy: nil} 232 | } 233 | 234 | //GetBucketReplicationRequest ... 235 | func (c *Client) GetBucketReplicationRequest(input *s3.GetBucketReplicationInput) s3.GetBucketReplicationRequest { 236 | req := c.NotImplemented() 237 | return s3.GetBucketReplicationRequest{Request: req, Input: input, Copy: nil} 238 | } 239 | 240 | //GetBucketRequestPaymentRequest ... 241 | func (c *Client) GetBucketRequestPaymentRequest(input *s3.GetBucketRequestPaymentInput) s3.GetBucketRequestPaymentRequest { 242 | req := c.NotImplemented() 243 | return s3.GetBucketRequestPaymentRequest{Request: req, Input: input, Copy: nil} 244 | } 245 | 246 | //GetBucketTaggingRequest ... 247 | func (c *Client) GetBucketTaggingRequest(input *s3.GetBucketTaggingInput) s3.GetBucketTaggingRequest { 248 | req := c.NotImplemented() 249 | return s3.GetBucketTaggingRequest{Request: req, Input: input, Copy: nil} 250 | } 251 | 252 | //GetBucketWebsiteRequest ... 253 | func (c *Client) GetBucketWebsiteRequest(input *s3.GetBucketWebsiteInput) s3.GetBucketWebsiteRequest { 254 | req := c.NotImplemented() 255 | return s3.GetBucketWebsiteRequest{Request: req, Input: input, Copy: nil} 256 | } 257 | 258 | //GetObjectAclRequest ... 259 | func (c *Client) GetObjectAclRequest(input *s3.GetObjectAclInput) s3.GetObjectAclRequest { 260 | req := c.NotImplemented() 261 | return s3.GetObjectAclRequest{Request: req, Input: input, Copy: nil} 262 | } 263 | 264 | //GetObjectLegalHoldRequest ... 265 | func (c *Client) GetObjectLegalHoldRequest(input *s3.GetObjectLegalHoldInput) s3.GetObjectLegalHoldRequest { 266 | req := c.NotImplemented() 267 | return s3.GetObjectLegalHoldRequest{Request: req, Input: input, Copy: nil} 268 | } 269 | 270 | //GetObjectLockConfigurationRequest ... 271 | func (c *Client) GetObjectLockConfigurationRequest(input *s3.GetObjectLockConfigurationInput) s3.GetObjectLockConfigurationRequest { 272 | req := c.NotImplemented() 273 | return s3.GetObjectLockConfigurationRequest{Request: req, Input: input, Copy: nil} 274 | } 275 | 276 | //GetObjectRetentionRequest ... 277 | func (c *Client) GetObjectRetentionRequest(input *s3.GetObjectRetentionInput) s3.GetObjectRetentionRequest { 278 | req := c.NotImplemented() 279 | return s3.GetObjectRetentionRequest{Request: req, Input: input, Copy: nil} 280 | } 281 | 282 | //GetObjectTaggingRequest ... 283 | func (c *Client) GetObjectTaggingRequest(input *s3.GetObjectTaggingInput) s3.GetObjectTaggingRequest { 284 | req := c.NotImplemented() 285 | return s3.GetObjectTaggingRequest{Request: req, Input: input, Copy: nil} 286 | } 287 | 288 | //GetObjectTorrentRequest ... 289 | func (c *Client) GetObjectTorrentRequest(input *s3.GetObjectTorrentInput) s3.GetObjectTorrentRequest { 290 | req := c.NotImplemented() 291 | return s3.GetObjectTorrentRequest{Request: req, Input: input, Copy: nil} 292 | } 293 | 294 | //GetPublicAccessBlockRequest ... 295 | func (c *Client) GetPublicAccessBlockRequest(input *s3.GetPublicAccessBlockInput) s3.GetPublicAccessBlockRequest { 296 | req := c.NotImplemented() 297 | return s3.GetPublicAccessBlockRequest{Request: req, Input: input, Copy: nil} 298 | } 299 | 300 | //HeadBucketRequest ... 301 | func (c *Client) HeadBucketRequest(input *s3.HeadBucketInput) s3.HeadBucketRequest { 302 | req := c.NotImplemented() 303 | return s3.HeadBucketRequest{Request: req, Input: input, Copy: nil} 304 | } 305 | 306 | //HeadObjectRequest ... 307 | func (c *Client) HeadObjectRequest(input *s3.HeadObjectInput) s3.HeadObjectRequest { 308 | req := c.NotImplemented() 309 | return s3.HeadObjectRequest{Request: req, Input: input, Copy: nil} 310 | } 311 | 312 | //ListBucketAnalyticsConfigurationsRequest ... 313 | func (c *Client) ListBucketAnalyticsConfigurationsRequest(input *s3.ListBucketAnalyticsConfigurationsInput) s3.ListBucketAnalyticsConfigurationsRequest { 314 | req := c.NotImplemented() 315 | return s3.ListBucketAnalyticsConfigurationsRequest{Request: req, Input: input, Copy: nil} 316 | } 317 | 318 | //ListBucketInventoryConfigurationsRequest ... 319 | func (c *Client) ListBucketInventoryConfigurationsRequest(input *s3.ListBucketInventoryConfigurationsInput) s3.ListBucketInventoryConfigurationsRequest { 320 | req := c.NotImplemented() 321 | return s3.ListBucketInventoryConfigurationsRequest{Request: req, Input: input, Copy: nil} 322 | } 323 | 324 | //ListBucketMetricsConfigurationsRequest ... 325 | func (c *Client) ListBucketMetricsConfigurationsRequest(input *s3.ListBucketMetricsConfigurationsInput) s3.ListBucketMetricsConfigurationsRequest { 326 | req := c.NotImplemented() 327 | return s3.ListBucketMetricsConfigurationsRequest{Request: req, Input: input, Copy: nil} 328 | } 329 | 330 | //ListMultipartUploadsRequest ... 331 | func (c *Client) ListMultipartUploadsRequest(input *s3.ListMultipartUploadsInput) s3.ListMultipartUploadsRequest { 332 | req := c.NotImplemented() 333 | return s3.ListMultipartUploadsRequest{Request: req, Input: input, Copy: nil} 334 | } 335 | 336 | //ListObjectVersionsRequest ... 337 | func (c *Client) ListObjectVersionsRequest(input *s3.ListObjectVersionsInput) s3.ListObjectVersionsRequest { 338 | req := c.NotImplemented() 339 | return s3.ListObjectVersionsRequest{Request: req, Input: input, Copy: nil} 340 | } 341 | 342 | //ListObjectsV2Request ... 343 | func (c *Client) ListObjectsV2Request(input *s3.ListObjectsV2Input) s3.ListObjectsV2Request { 344 | req := c.NotImplemented() 345 | return s3.ListObjectsV2Request{Request: req, Input: input, Copy: nil} 346 | } 347 | 348 | //ListPartsRequest ... 349 | func (c *Client) ListPartsRequest(input *s3.ListPartsInput) s3.ListPartsRequest { 350 | req := c.NotImplemented() 351 | return s3.ListPartsRequest{Request: req, Input: input, Copy: nil} 352 | } 353 | 354 | //PutBucketAccelerateConfigurationRequest ... 355 | func (c *Client) PutBucketAccelerateConfigurationRequest(input *s3.PutBucketAccelerateConfigurationInput) s3.PutBucketAccelerateConfigurationRequest { 356 | req := c.NotImplemented() 357 | return s3.PutBucketAccelerateConfigurationRequest{Request: req, Input: input, Copy: nil} 358 | } 359 | 360 | //PutBucketAclRequest ... 361 | func (c *Client) PutBucketAclRequest(input *s3.PutBucketAclInput) s3.PutBucketAclRequest { 362 | req := c.NotImplemented() 363 | return s3.PutBucketAclRequest{Request: req, Input: input, Copy: nil} 364 | } 365 | 366 | //PutBucketAnalyticsConfigurationRequest ... 367 | func (c *Client) PutBucketAnalyticsConfigurationRequest(input *s3.PutBucketAnalyticsConfigurationInput) s3.PutBucketAnalyticsConfigurationRequest { 368 | req := c.NotImplemented() 369 | return s3.PutBucketAnalyticsConfigurationRequest{Request: req, Input: input, Copy: nil} 370 | } 371 | 372 | //PutBucketCorsRequest ... 373 | func (c *Client) PutBucketCorsRequest(input *s3.PutBucketCorsInput) s3.PutBucketCorsRequest { 374 | req := c.NotImplemented() 375 | return s3.PutBucketCorsRequest{Request: req, Input: input, Copy: nil} 376 | } 377 | 378 | //PutBucketEncryptionRequest ... 379 | func (c *Client) PutBucketEncryptionRequest(input *s3.PutBucketEncryptionInput) s3.PutBucketEncryptionRequest { 380 | req := c.NotImplemented() 381 | return s3.PutBucketEncryptionRequest{Request: req, Input: input, Copy: nil} 382 | } 383 | 384 | //PutBucketInventoryConfigurationRequest ... 385 | func (c *Client) PutBucketInventoryConfigurationRequest(input *s3.PutBucketInventoryConfigurationInput) s3.PutBucketInventoryConfigurationRequest { 386 | req := c.NotImplemented() 387 | return s3.PutBucketInventoryConfigurationRequest{Request: req, Input: input, Copy: nil} 388 | } 389 | 390 | //PutBucketLifecycleRequest ... 391 | func (c *Client) PutBucketLifecycleRequest(input *s3.PutBucketLifecycleInput) s3.PutBucketLifecycleRequest { 392 | req := c.NotImplemented() 393 | return s3.PutBucketLifecycleRequest{Request: req, Input: input, Copy: nil} 394 | } 395 | 396 | //PutBucketLifecycleConfigurationRequest ... 397 | func (c *Client) PutBucketLifecycleConfigurationRequest(input *s3.PutBucketLifecycleConfigurationInput) s3.PutBucketLifecycleConfigurationRequest { 398 | req := c.NotImplemented() 399 | return s3.PutBucketLifecycleConfigurationRequest{Request: req, Input: input, Copy: nil} 400 | } 401 | 402 | //PutBucketLoggingRequest ... 403 | func (c *Client) PutBucketLoggingRequest(input *s3.PutBucketLoggingInput) s3.PutBucketLoggingRequest { 404 | req := c.NotImplemented() 405 | return s3.PutBucketLoggingRequest{Request: req, Input: input, Copy: nil} 406 | } 407 | 408 | //PutBucketMetricsConfigurationRequest ... 409 | func (c *Client) PutBucketMetricsConfigurationRequest(input *s3.PutBucketMetricsConfigurationInput) s3.PutBucketMetricsConfigurationRequest { 410 | req := c.NotImplemented() 411 | return s3.PutBucketMetricsConfigurationRequest{Request: req, Input: input, Copy: nil} 412 | } 413 | 414 | //PutBucketNotificationRequest ... 415 | func (c *Client) PutBucketNotificationRequest(input *s3.PutBucketNotificationInput) s3.PutBucketNotificationRequest { 416 | req := c.NotImplemented() 417 | return s3.PutBucketNotificationRequest{Request: req, Input: input, Copy: nil} 418 | } 419 | 420 | //PutBucketNotificationConfigurationRequest ... 421 | func (c *Client) PutBucketNotificationConfigurationRequest(input *s3.PutBucketNotificationConfigurationInput) s3.PutBucketNotificationConfigurationRequest { 422 | req := c.NotImplemented() 423 | return s3.PutBucketNotificationConfigurationRequest{Request: req, Input: input, Copy: nil} 424 | } 425 | 426 | //PutBucketPolicyRequest ... 427 | func (c *Client) PutBucketPolicyRequest(input *s3.PutBucketPolicyInput) s3.PutBucketPolicyRequest { 428 | req := c.NotImplemented() 429 | return s3.PutBucketPolicyRequest{Request: req, Input: input, Copy: nil} 430 | } 431 | 432 | //PutBucketReplicationRequest ... 433 | func (c *Client) PutBucketReplicationRequest(input *s3.PutBucketReplicationInput) s3.PutBucketReplicationRequest { 434 | req := c.NotImplemented() 435 | return s3.PutBucketReplicationRequest{Request: req, Input: input, Copy: nil} 436 | } 437 | 438 | //PutBucketRequestPaymentRequest ... 439 | func (c *Client) PutBucketRequestPaymentRequest(input *s3.PutBucketRequestPaymentInput) s3.PutBucketRequestPaymentRequest { 440 | req := c.NotImplemented() 441 | return s3.PutBucketRequestPaymentRequest{Request: req, Input: input, Copy: nil} 442 | } 443 | 444 | //PutBucketTaggingRequest ... 445 | func (c *Client) PutBucketTaggingRequest(input *s3.PutBucketTaggingInput) s3.PutBucketTaggingRequest { 446 | req := c.NotImplemented() 447 | return s3.PutBucketTaggingRequest{Request: req, Input: input, Copy: nil} 448 | } 449 | 450 | //PutBucketWebsiteRequest ... 451 | func (c *Client) PutBucketWebsiteRequest(input *s3.PutBucketWebsiteInput) s3.PutBucketWebsiteRequest { 452 | req := c.NotImplemented() 453 | return s3.PutBucketWebsiteRequest{Request: req, Input: input, Copy: nil} 454 | } 455 | 456 | //PutObjectAclRequest ... 457 | func (c *Client) PutObjectAclRequest(input *s3.PutObjectAclInput) s3.PutObjectAclRequest { 458 | req := c.NotImplemented() 459 | return s3.PutObjectAclRequest{Request: req, Input: input, Copy: nil} 460 | } 461 | 462 | //PutObjectLegalHoldRequest ... 463 | func (c *Client) PutObjectLegalHoldRequest(input *s3.PutObjectLegalHoldInput) s3.PutObjectLegalHoldRequest { 464 | req := c.NotImplemented() 465 | return s3.PutObjectLegalHoldRequest{Request: req, Input: input, Copy: nil} 466 | } 467 | 468 | //PutObjectLockConfigurationRequest ... 469 | func (c *Client) PutObjectLockConfigurationRequest(input *s3.PutObjectLockConfigurationInput) s3.PutObjectLockConfigurationRequest { 470 | req := c.NotImplemented() 471 | return s3.PutObjectLockConfigurationRequest{Request: req, Input: input, Copy: nil} 472 | } 473 | 474 | //PutObjectRetentionRequest ... 475 | func (c *Client) PutObjectRetentionRequest(input *s3.PutObjectRetentionInput) s3.PutObjectRetentionRequest { 476 | req := c.NotImplemented() 477 | return s3.PutObjectRetentionRequest{Request: req, Input: input, Copy: nil} 478 | } 479 | 480 | //PutObjectTaggingRequest ... 481 | func (c *Client) PutObjectTaggingRequest(input *s3.PutObjectTaggingInput) s3.PutObjectTaggingRequest { 482 | req := c.NotImplemented() 483 | return s3.PutObjectTaggingRequest{Request: req, Input: input, Copy: nil} 484 | } 485 | 486 | //PutPublicAccessBlockRequest ... 487 | func (c *Client) PutPublicAccessBlockRequest(input *s3.PutPublicAccessBlockInput) s3.PutPublicAccessBlockRequest { 488 | req := c.NotImplemented() 489 | return s3.PutPublicAccessBlockRequest{Request: req, Input: input, Copy: nil} 490 | } 491 | 492 | //RestoreObjectRequest ... 493 | func (c *Client) RestoreObjectRequest(input *s3.RestoreObjectInput) s3.RestoreObjectRequest { 494 | req := c.NotImplemented() 495 | return s3.RestoreObjectRequest{Request: req, Input: input, Copy: nil} 496 | } 497 | 498 | //UploadPartRequest ... 499 | func (c *Client) UploadPartRequest(input *s3.UploadPartInput) s3.UploadPartRequest { 500 | req := c.NotImplemented() 501 | return s3.UploadPartRequest{Request: req, Input: input, Copy: nil} 502 | } 503 | 504 | //UploadPartCopyRequest ... 505 | func (c *Client) UploadPartCopyRequest(input *s3.UploadPartCopyInput) s3.UploadPartCopyRequest { 506 | req := c.NotImplemented() 507 | return s3.UploadPartCopyRequest{Request: req, Input: input, Copy: nil} 508 | } 509 | 510 | //WaitUntilBucketExists ... 511 | func (c *Client) WaitUntilBucketExists(context.Context, *s3.HeadBucketInput, ...aws.WaiterOption) error { 512 | return s3memerr.NewError(s3memerr.ErrCodeNotImplemented, "Not implemented", nil, nil, nil, nil) 513 | } 514 | 515 | //WaitUntilBucketNotExists ... 516 | func (c *Client) WaitUntilBucketNotExists(context.Context, *s3.HeadBucketInput, ...aws.WaiterOption) error { 517 | return s3memerr.NewError(s3memerr.ErrCodeNotImplemented, "Not implemented", nil, nil, nil, nil) 518 | } 519 | 520 | //WaitUntilObjectExists ... 521 | func (c *Client) WaitUntilObjectExists(context.Context, *s3.HeadObjectInput, ...aws.WaiterOption) error { 522 | return s3memerr.NewError(s3memerr.ErrCodeNotImplemented, "Not implemented", nil, nil, nil, nil) 523 | } 524 | 525 | //WaitUntilObjectNotExists ... 526 | func (c *Client) WaitUntilObjectNotExists(context.Context, *s3.HeadObjectInput, ...aws.WaiterOption) error { 527 | return s3memerr.NewError(s3memerr.ErrCodeNotImplemented, "Not implemented", nil, nil, nil, nil) 528 | } 529 | -------------------------------------------------------------------------------- /s3mem/s3mem_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "context" 23 | "testing" 24 | 25 | "github.com/IBM/s3mem-go/s3mem/s3memerr" 26 | 27 | "github.com/aws/aws-sdk-go-v2/aws/endpoints" 28 | 29 | "github.com/aws/aws-sdk-go-v2/aws" 30 | 31 | "github.com/aws/aws-sdk-go-v2/service/s3" 32 | "github.com/stretchr/testify/assert" 33 | ) 34 | 35 | var S3MemTestConfig aws.Config 36 | var S3MemTestService *S3MemService 37 | 38 | func init() { 39 | S3MemTestConfig = aws.Config{ 40 | Region: endpoints.EuWest1RegionID, 41 | LogLevel: aws.LogDebugWithHTTPBody, 42 | Logger: aws.NewDefaultLogger(), 43 | Credentials: aws.NewStaticCredentialsProvider("fake", "fake", ""), 44 | } 45 | defaultResolver := endpoints.NewDefaultResolver() 46 | myCustomResolver := func(service, region string) (aws.Endpoint, error) { 47 | if service == s3.EndpointsID { 48 | return aws.Endpoint{ 49 | URL: S3MemEndpointsID, 50 | }, nil 51 | } 52 | return defaultResolver.ResolveEndpoint(service, region) 53 | } 54 | S3MemTestConfig.EndpointResolver = aws.EndpointResolverFunc(myCustomResolver) 55 | 56 | S3MemTestService = NewDefaultS3MemService() 57 | } 58 | 59 | func TestNewClient(t *testing.T) { 60 | S3MemTestService.Lock() 61 | defer S3MemTestService.Unlock() 62 | l := len(S3Store.S3MemServices[S3MemEndpointsID].Buckets) 63 | client := New(S3MemTestConfig) 64 | //Create the request 65 | req := client.ListBucketsRequest(&s3.ListBucketsInput{}) 66 | //Send the request 67 | listBucketsOutput, err := req.Send(context.Background()) 68 | assert.NoError(t, err) 69 | assert.Equal(t, l, len(listBucketsOutput.Buckets)) 70 | } 71 | 72 | func TestNotImplemented(t *testing.T) { 73 | //Request a client 74 | client := New(S3MemTestConfig) 75 | input := &s3.AbortMultipartUploadInput{} 76 | req := client.AbortMultipartUploadRequest(input) 77 | assert.Error(t, req.Error) 78 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 79 | } 80 | 81 | //AbortMultipartUploadRequest ... 82 | func TestAbortMultipartUploadRequest(t *testing.T) { 83 | client := New(S3MemTestConfig) 84 | req := client.AbortMultipartUploadRequest(&s3.AbortMultipartUploadInput{}) 85 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 86 | } 87 | 88 | //CompleteMultipartUploadRequest ... 89 | func TestCompleteMultipartUploadRequest(t *testing.T) { 90 | client := New(S3MemTestConfig) 91 | req := client.CompleteMultipartUploadRequest(&s3.CompleteMultipartUploadInput{}) 92 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 93 | } 94 | 95 | //CreateMultipartUploadRequest ... 96 | func TestCreateMultipartUploadRequest(t *testing.T) { 97 | client := New(S3MemTestConfig) 98 | req := client.CreateMultipartUploadRequest(&s3.CreateMultipartUploadInput{}) 99 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 100 | } 101 | 102 | //DeleteBucketAnalyticsConfigurationRequest ... 103 | func TestDeleteBucketAnalyticsConfigurationRequest(t *testing.T) { 104 | client := New(S3MemTestConfig) 105 | req := client.DeleteBucketAnalyticsConfigurationRequest(&s3.DeleteBucketAnalyticsConfigurationInput{}) 106 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 107 | } 108 | 109 | //DeleteBucketCorsRequest ... 110 | func TestDeleteBucketCorsRequest(t *testing.T) { 111 | client := New(S3MemTestConfig) 112 | req := client.DeleteBucketCorsRequest(&s3.DeleteBucketCorsInput{}) 113 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 114 | } 115 | 116 | //DeleteBucketEncryptionRequest ... 117 | func TestDeleteBucketEncryptionRequest(t *testing.T) { 118 | client := New(S3MemTestConfig) 119 | req := client.DeleteBucketEncryptionRequest(&s3.DeleteBucketEncryptionInput{}) 120 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 121 | } 122 | 123 | //DeleteBucketInventoryConfigurationRequest ... 124 | func TestDeleteBucketInventoryConfigurationRequest(t *testing.T) { 125 | client := New(S3MemTestConfig) 126 | req := client.DeleteBucketInventoryConfigurationRequest(&s3.DeleteBucketInventoryConfigurationInput{}) 127 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 128 | } 129 | 130 | //DeleteBucketLifecycleRequest ... 131 | func TestDeleteBucketLifecycleRequest(t *testing.T) { 132 | client := New(S3MemTestConfig) 133 | req := client.DeleteBucketLifecycleRequest(&s3.DeleteBucketLifecycleInput{}) 134 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 135 | } 136 | 137 | //DeleteBucketMetricsConfigurationRequest ... 138 | func TestDeleteBucketMetricsConfigurationRequest(t *testing.T) { 139 | client := New(S3MemTestConfig) 140 | req := client.DeleteBucketMetricsConfigurationRequest(&s3.DeleteBucketMetricsConfigurationInput{}) 141 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 142 | } 143 | 144 | //DeleteBucketPolicyRequest ... 145 | func TestDeleteBucketPolicyRequest(t *testing.T) { 146 | client := New(S3MemTestConfig) 147 | req := client.DeleteBucketPolicyRequest(&s3.DeleteBucketPolicyInput{}) 148 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 149 | } 150 | 151 | //DeleteBucketReplicationRequest ... 152 | func TestDeleteBucketReplicationRequest(t *testing.T) { 153 | client := New(S3MemTestConfig) 154 | req := client.DeleteBucketReplicationRequest(&s3.DeleteBucketReplicationInput{}) 155 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 156 | } 157 | 158 | //DeleteBucketTaggingRequest ... 159 | func TestDeleteBucketTaggingRequest(t *testing.T) { 160 | client := New(S3MemTestConfig) 161 | req := client.DeleteBucketTaggingRequest(&s3.DeleteBucketTaggingInput{}) 162 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 163 | } 164 | 165 | //DeleteBucketWebsiteRequest ... 166 | func TestDeleteBucketWebsiteRequest(t *testing.T) { 167 | client := New(S3MemTestConfig) 168 | req := client.DeleteBucketWebsiteRequest(&s3.DeleteBucketWebsiteInput{}) 169 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 170 | } 171 | 172 | //DeleteObjectTaggingRequest ... 173 | func TestDeleteObjectTaggingRequest(t *testing.T) { 174 | client := New(S3MemTestConfig) 175 | req := client.DeleteObjectTaggingRequest(&s3.DeleteObjectTaggingInput{}) 176 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 177 | } 178 | 179 | //DeletePublicAccessBlockRequest ... 180 | func TestDeletePublicAccessBlockRequest(t *testing.T) { 181 | client := New(S3MemTestConfig) 182 | req := client.DeletePublicAccessBlockRequest(&s3.DeletePublicAccessBlockInput{}) 183 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 184 | } 185 | 186 | //GetBucketAccelerateConfigurationRequest ... 187 | func TestGetBucketAccelerateConfigurationRequest(t *testing.T) { 188 | client := New(S3MemTestConfig) 189 | req := client.GetBucketAccelerateConfigurationRequest(&s3.GetBucketAccelerateConfigurationInput{}) 190 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 191 | } 192 | 193 | //GetBucketAclRequest ... 194 | func TestGetBucketAclRequest(t *testing.T) { 195 | client := New(S3MemTestConfig) 196 | req := client.GetBucketAclRequest(&s3.GetBucketAclInput{}) 197 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 198 | } 199 | 200 | //GetBucketAnalyticsConfigurationRequest ... 201 | func TestGetBucketAnalyticsConfigurationRequest(t *testing.T) { 202 | client := New(S3MemTestConfig) 203 | req := client.GetBucketAnalyticsConfigurationRequest(&s3.GetBucketAnalyticsConfigurationInput{}) 204 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 205 | } 206 | 207 | //GetBucketCorsRequest ... 208 | func TestGetBucketCorsRequest(t *testing.T) { 209 | client := New(S3MemTestConfig) 210 | req := client.GetBucketCorsRequest(&s3.GetBucketCorsInput{}) 211 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 212 | } 213 | 214 | //GetBucketEncryptionRequest ... 215 | func TestGetBucketEncryptionRequest(t *testing.T) { 216 | client := New(S3MemTestConfig) 217 | req := client.GetBucketEncryptionRequest(&s3.GetBucketEncryptionInput{}) 218 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 219 | } 220 | 221 | //GetBucketInventoryConfigurationRequest ... 222 | func TestGetBucketInventoryConfigurationRequest(t *testing.T) { 223 | client := New(S3MemTestConfig) 224 | req := client.GetBucketInventoryConfigurationRequest(&s3.GetBucketInventoryConfigurationInput{}) 225 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 226 | } 227 | 228 | //GetBucketLifecycleRequest ... 229 | func TestGetBucketLifecycleRequest(t *testing.T) { 230 | client := New(S3MemTestConfig) 231 | req := client.GetBucketLifecycleRequest(&s3.GetBucketLifecycleInput{}) 232 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 233 | } 234 | 235 | //GetBucketLifecycleConfigurationRequest ... 236 | func TestGetBucketLifecycleConfigurationRequest(t *testing.T) { 237 | client := New(S3MemTestConfig) 238 | req := client.GetBucketLifecycleConfigurationRequest(&s3.GetBucketLifecycleConfigurationInput{}) 239 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 240 | } 241 | 242 | //GetBucketLocationRequest ... 243 | func TestGetBucketLocationRequest(t *testing.T) { 244 | client := New(S3MemTestConfig) 245 | req := client.GetBucketLocationRequest(&s3.GetBucketLocationInput{}) 246 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 247 | } 248 | 249 | //GetBucketLoggingRequest ... 250 | func TestGetBucketLoggingRequest(t *testing.T) { 251 | client := New(S3MemTestConfig) 252 | req := client.GetBucketLoggingRequest(&s3.GetBucketLoggingInput{}) 253 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 254 | } 255 | 256 | //GetBucketMetricsConfigurationRequest ... 257 | func TestGetBucketMetricsConfigurationRequest(t *testing.T) { 258 | client := New(S3MemTestConfig) 259 | req := client.GetBucketMetricsConfigurationRequest(&s3.GetBucketMetricsConfigurationInput{}) 260 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 261 | } 262 | 263 | //GetBucketNotificationRequest ... 264 | func TestGetBucketNotificationRequest(t *testing.T) { 265 | client := New(S3MemTestConfig) 266 | req := client.GetBucketNotificationRequest(&s3.GetBucketNotificationInput{}) 267 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 268 | } 269 | 270 | //GetBucketNotificationConfigurationRequest ... 271 | func TestGetBucketNotificationConfigurationRequest(t *testing.T) { 272 | client := New(S3MemTestConfig) 273 | req := client.GetBucketNotificationConfigurationRequest(&s3.GetBucketNotificationConfigurationInput{}) 274 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 275 | } 276 | 277 | //GetBucketPolicyRequest ... 278 | func TestGetBucketPolicyRequest(t *testing.T) { 279 | client := New(S3MemTestConfig) 280 | req := client.GetBucketPolicyRequest(&s3.GetBucketPolicyInput{}) 281 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 282 | } 283 | 284 | //GetBucketPolicyStatusRequest ... 285 | func TestGetBucketPolicyStatusRequest(t *testing.T) { 286 | client := New(S3MemTestConfig) 287 | req := client.GetBucketPolicyStatusRequest(&s3.GetBucketPolicyStatusInput{}) 288 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 289 | } 290 | 291 | //GetBucketReplicationRequest ... 292 | func TestGetBucketReplicationRequest(t *testing.T) { 293 | client := New(S3MemTestConfig) 294 | req := client.GetBucketReplicationRequest(&s3.GetBucketReplicationInput{}) 295 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 296 | } 297 | 298 | //GetBucketRequestPaymentRequest ... 299 | func TestGetBucketRequestPaymentRequest(t *testing.T) { 300 | client := New(S3MemTestConfig) 301 | req := client.GetBucketRequestPaymentRequest(&s3.GetBucketRequestPaymentInput{}) 302 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 303 | } 304 | 305 | //GetBucketTaggingRequest ... 306 | func TestGetBucketTaggingRequest(t *testing.T) { 307 | client := New(S3MemTestConfig) 308 | req := client.GetBucketTaggingRequest(&s3.GetBucketTaggingInput{}) 309 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 310 | } 311 | 312 | //GetBucketWebsiteRequest ... 313 | func TestGetBucketWebsiteRequest(t *testing.T) { 314 | client := New(S3MemTestConfig) 315 | req := client.GetBucketWebsiteRequest(&s3.GetBucketWebsiteInput{}) 316 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 317 | } 318 | 319 | //GetObjectAclRequest ... 320 | func TestGetObjectAclRequest(t *testing.T) { 321 | client := New(S3MemTestConfig) 322 | req := client.GetObjectAclRequest(&s3.GetObjectAclInput{}) 323 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 324 | } 325 | 326 | //GetObjectLegalHoldRequest ... 327 | func TestGetObjectLegalHoldRequest(t *testing.T) { 328 | client := New(S3MemTestConfig) 329 | req := client.GetObjectLegalHoldRequest(&s3.GetObjectLegalHoldInput{}) 330 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 331 | } 332 | 333 | //GetObjectLockConfigurationRequest ... 334 | func TestGetObjectLockConfigurationRequest(t *testing.T) { 335 | client := New(S3MemTestConfig) 336 | req := client.GetObjectLockConfigurationRequest(&s3.GetObjectLockConfigurationInput{}) 337 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 338 | } 339 | 340 | //GetObjectRetentionRequest ... 341 | func TestGetObjectRetentionRequest(t *testing.T) { 342 | client := New(S3MemTestConfig) 343 | req := client.GetObjectRetentionRequest(&s3.GetObjectRetentionInput{}) 344 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 345 | } 346 | 347 | //GetObjectTaggingRequest ... 348 | func TestGetObjectTaggingRequest(t *testing.T) { 349 | client := New(S3MemTestConfig) 350 | req := client.GetObjectTaggingRequest(&s3.GetObjectTaggingInput{}) 351 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 352 | } 353 | 354 | //GetObjectTorrentRequest ... 355 | func TestGetObjectTorrentRequest(t *testing.T) { 356 | client := New(S3MemTestConfig) 357 | req := client.GetObjectTorrentRequest(&s3.GetObjectTorrentInput{}) 358 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 359 | } 360 | 361 | //GetPublicAccessBlockRequest ... 362 | func TestGetPublicAccessBlockRequest(t *testing.T) { 363 | client := New(S3MemTestConfig) 364 | req := client.GetPublicAccessBlockRequest(&s3.GetPublicAccessBlockInput{}) 365 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 366 | } 367 | 368 | //HeadBucketRequest ... 369 | func TestHeadBucketRequest(t *testing.T) { 370 | client := New(S3MemTestConfig) 371 | req := client.HeadBucketRequest(&s3.HeadBucketInput{}) 372 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 373 | } 374 | 375 | //HeadObjectRequest ... 376 | func TestHeadObjectRequest(t *testing.T) { 377 | client := New(S3MemTestConfig) 378 | req := client.HeadObjectRequest(&s3.HeadObjectInput{}) 379 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 380 | } 381 | 382 | //ListBucketAnalyticsConfigurationsRequest ... 383 | func TestListBucketAnalyticsConfigurationsRequest(t *testing.T) { 384 | client := New(S3MemTestConfig) 385 | req := client.ListBucketAnalyticsConfigurationsRequest(&s3.ListBucketAnalyticsConfigurationsInput{}) 386 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 387 | } 388 | 389 | //ListBucketInventoryConfigurationsRequest ... 390 | func TestListBucketInventoryConfigurationsRequest(t *testing.T) { 391 | client := New(S3MemTestConfig) 392 | req := client.ListBucketInventoryConfigurationsRequest(&s3.ListBucketInventoryConfigurationsInput{}) 393 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 394 | } 395 | 396 | //ListBucketMetricsConfigurationsRequest ... 397 | func TestListBucketMetricsConfigurationsRequest(t *testing.T) { 398 | client := New(S3MemTestConfig) 399 | req := client.ListBucketMetricsConfigurationsRequest(&s3.ListBucketMetricsConfigurationsInput{}) 400 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 401 | } 402 | 403 | //ListMultipartUploadsRequest ... 404 | func TestListMultipartUploadsRequest(t *testing.T) { 405 | client := New(S3MemTestConfig) 406 | req := client.ListMultipartUploadsRequest(&s3.ListMultipartUploadsInput{}) 407 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 408 | } 409 | 410 | //ListObjectVersionsRequest ... 411 | func TestListObjectVersionsRequest(t *testing.T) { 412 | client := New(S3MemTestConfig) 413 | req := client.ListObjectVersionsRequest(&s3.ListObjectVersionsInput{}) 414 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 415 | } 416 | 417 | //ListObjectsV2Request ... 418 | func TestListObjectsV2Request(t *testing.T) { 419 | client := New(S3MemTestConfig) 420 | req := client.ListObjectsV2Request(&s3.ListObjectsV2Input{}) 421 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 422 | } 423 | 424 | //ListPartsRequest ... 425 | func TestListPartsRequest(t *testing.T) { 426 | client := New(S3MemTestConfig) 427 | req := client.ListPartsRequest(&s3.ListPartsInput{}) 428 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 429 | } 430 | 431 | //PutBucketAccelerateConfigurationRequest ... 432 | func TestPutBucketAccelerateConfigurationRequest(t *testing.T) { 433 | client := New(S3MemTestConfig) 434 | req := client.PutBucketAccelerateConfigurationRequest(&s3.PutBucketAccelerateConfigurationInput{}) 435 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 436 | } 437 | 438 | //PutBucketAclRequest ... 439 | func TestPutBucketAclRequest(t *testing.T) { 440 | client := New(S3MemTestConfig) 441 | req := client.PutBucketAclRequest(&s3.PutBucketAclInput{}) 442 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 443 | } 444 | 445 | //PutBucketAnalyticsConfigurationRequest ... 446 | func TestPutBucketAnalyticsConfigurationRequest(t *testing.T) { 447 | client := New(S3MemTestConfig) 448 | req := client.PutBucketAnalyticsConfigurationRequest(&s3.PutBucketAnalyticsConfigurationInput{}) 449 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 450 | } 451 | 452 | //PutBucketCorsRequest ... 453 | func TestPutBucketCorsRequest(t *testing.T) { 454 | client := New(S3MemTestConfig) 455 | req := client.PutBucketCorsRequest(&s3.PutBucketCorsInput{}) 456 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 457 | } 458 | 459 | //PutBucketEncryptionRequest ... 460 | func TestPutBucketEncryptionRequest(t *testing.T) { 461 | client := New(S3MemTestConfig) 462 | req := client.PutBucketEncryptionRequest(&s3.PutBucketEncryptionInput{}) 463 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 464 | } 465 | 466 | //PutBucketInventoryConfigurationRequest ... 467 | func TestPutBucketInventoryConfigurationRequest(t *testing.T) { 468 | client := New(S3MemTestConfig) 469 | req := client.PutBucketInventoryConfigurationRequest(&s3.PutBucketInventoryConfigurationInput{}) 470 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 471 | } 472 | 473 | //PutBucketLifecycleRequest ... 474 | func TestPutBucketLifecycleRequest(t *testing.T) { 475 | client := New(S3MemTestConfig) 476 | req := client.PutBucketLifecycleRequest(&s3.PutBucketLifecycleInput{}) 477 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 478 | } 479 | 480 | //PutBucketLifecycleConfigurationRequest ... 481 | func TestPutBucketLifecycleConfigurationRequest(t *testing.T) { 482 | client := New(S3MemTestConfig) 483 | req := client.PutBucketLifecycleConfigurationRequest(&s3.PutBucketLifecycleConfigurationInput{}) 484 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 485 | } 486 | 487 | //PutBucketLoggingRequest ... 488 | func TestPutBucketLoggingRequest(t *testing.T) { 489 | client := New(S3MemTestConfig) 490 | req := client.PutBucketLoggingRequest(&s3.PutBucketLoggingInput{}) 491 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 492 | } 493 | 494 | //PutBucketMetricsConfigurationRequest ... 495 | func TestPutBucketMetricsConfigurationRequest(t *testing.T) { 496 | client := New(S3MemTestConfig) 497 | req := client.PutBucketMetricsConfigurationRequest(&s3.PutBucketMetricsConfigurationInput{}) 498 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 499 | } 500 | 501 | //PutBucketNotificationRequest ... 502 | func TestPutBucketNotificationRequest(t *testing.T) { 503 | client := New(S3MemTestConfig) 504 | req := client.PutBucketNotificationRequest(&s3.PutBucketNotificationInput{}) 505 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 506 | } 507 | 508 | //PutBucketNotificationConfigurationRequest ... 509 | func TestPutBucketNotificationConfigurationRequest(t *testing.T) { 510 | client := New(S3MemTestConfig) 511 | req := client.PutBucketNotificationConfigurationRequest(&s3.PutBucketNotificationConfigurationInput{}) 512 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 513 | } 514 | 515 | //PutBucketPolicyRequest ... 516 | func TestPutBucketPolicyRequest(t *testing.T) { 517 | client := New(S3MemTestConfig) 518 | req := client.PutBucketPolicyRequest(&s3.PutBucketPolicyInput{}) 519 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 520 | } 521 | 522 | //PutBucketReplicationRequest ... 523 | func TestPutBucketReplicationRequest(t *testing.T) { 524 | client := New(S3MemTestConfig) 525 | req := client.PutBucketReplicationRequest(&s3.PutBucketReplicationInput{}) 526 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 527 | } 528 | 529 | //PutBucketRequestPaymentRequest ... 530 | func TestPutBucketRequestPaymentRequest(t *testing.T) { 531 | client := New(S3MemTestConfig) 532 | req := client.PutBucketRequestPaymentRequest(&s3.PutBucketRequestPaymentInput{}) 533 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 534 | } 535 | 536 | //PutBucketTaggingRequest ... 537 | func TestPutBucketTaggingRequest(t *testing.T) { 538 | client := New(S3MemTestConfig) 539 | req := client.PutBucketTaggingRequest(&s3.PutBucketTaggingInput{}) 540 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 541 | } 542 | 543 | //PutBucketWebsiteRequest ... 544 | func TestPutBucketWebsiteRequest(t *testing.T) { 545 | client := New(S3MemTestConfig) 546 | req := client.PutBucketWebsiteRequest(&s3.PutBucketWebsiteInput{}) 547 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 548 | } 549 | 550 | //PutObjectAclRequest ... 551 | func TestPutObjectAclRequest(t *testing.T) { 552 | client := New(S3MemTestConfig) 553 | req := client.PutObjectAclRequest(&s3.PutObjectAclInput{}) 554 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 555 | } 556 | 557 | //PutObjectLegalHoldRequest ... 558 | func TestPutObjectLegalHoldRequest(t *testing.T) { 559 | client := New(S3MemTestConfig) 560 | req := client.PutObjectLegalHoldRequest(&s3.PutObjectLegalHoldInput{}) 561 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 562 | } 563 | 564 | //PutObjectLockConfigurationRequest ... 565 | func TestPutObjectLockConfigurationRequest(t *testing.T) { 566 | client := New(S3MemTestConfig) 567 | req := client.PutObjectLockConfigurationRequest(&s3.PutObjectLockConfigurationInput{}) 568 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 569 | } 570 | 571 | //PutObjectRetentionRequest ... 572 | func TestPutObjectRetentionRequest(t *testing.T) { 573 | client := New(S3MemTestConfig) 574 | req := client.PutObjectRetentionRequest(&s3.PutObjectRetentionInput{}) 575 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 576 | } 577 | 578 | //PutObjectTaggingRequest ... 579 | func TestPutObjectTaggingRequest(t *testing.T) { 580 | client := New(S3MemTestConfig) 581 | req := client.PutObjectTaggingRequest(&s3.PutObjectTaggingInput{}) 582 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 583 | } 584 | 585 | //PutPublicAccessBlockRequest ... 586 | func TestPutPublicAccessBlockRequest(t *testing.T) { 587 | client := New(S3MemTestConfig) 588 | req := client.PutPublicAccessBlockRequest(&s3.PutPublicAccessBlockInput{}) 589 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 590 | } 591 | 592 | //RestoreObjectRequest ... 593 | func TestRestoreObjectRequest(t *testing.T) { 594 | client := New(S3MemTestConfig) 595 | req := client.RestoreObjectRequest(&s3.RestoreObjectInput{}) 596 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 597 | } 598 | 599 | //UploadPartRequest ... 600 | func TestUploadPartRequest(t *testing.T) { 601 | client := New(S3MemTestConfig) 602 | req := client.UploadPartRequest(&s3.UploadPartInput{}) 603 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 604 | } 605 | 606 | //UploadPartCopyRequest ... 607 | func TestUploadPartCopyRequest(t *testing.T) { 608 | client := New(S3MemTestConfig) 609 | req := client.UploadPartCopyRequest(&s3.UploadPartCopyInput{}) 610 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, req.Error.(s3memerr.S3MemError).Code()) 611 | } 612 | 613 | //WaitUntilBucketExists ... 614 | func TestWaitUntilBucketExists(t *testing.T) { 615 | client := New(S3MemTestConfig) 616 | err := client.WaitUntilBucketExists(context.TODO(), &s3.HeadBucketInput{}) 617 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, err.(s3memerr.S3MemError).Code()) 618 | } 619 | 620 | //WaitUntilBucketNotExists ... 621 | func TestWaitUntilBucketNotExists(t *testing.T) { 622 | client := New(S3MemTestConfig) 623 | err := client.WaitUntilBucketNotExists(context.TODO(), &s3.HeadBucketInput{}) 624 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, err.(s3memerr.S3MemError).Code()) 625 | } 626 | 627 | //WaitUntilObjectExists ... 628 | func TestWaitUntilObjectExists(t *testing.T) { 629 | client := New(S3MemTestConfig) 630 | err := client.WaitUntilObjectExists(context.TODO(), &s3.HeadObjectInput{}) 631 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, err.(s3memerr.S3MemError).Code()) 632 | } 633 | 634 | //WaitUntilObjectNotExists ... 635 | func TestWaitUntilObjectNotExists(t *testing.T) { 636 | client := New(S3MemTestConfig) 637 | err := client.WaitUntilObjectNotExists(context.TODO(), &s3.HeadObjectInput{}) 638 | assert.Equal(t, s3memerr.ErrCodeNotImplemented, err.(s3memerr.S3MemError).Code()) 639 | } 640 | -------------------------------------------------------------------------------- /s3mem/s3memerr/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3memerr 20 | 21 | import ( 22 | "fmt" 23 | 24 | "github.com/aws/aws-sdk-go-v2/aws/awserr" 25 | "github.com/aws/aws-sdk-go-v2/service/s3" 26 | ) 27 | 28 | const ( 29 | ErrCodeNotS3MemRequest = "NotS3MemRequest" 30 | ErrCodeBucketNotEmpty = "BucketNotEmpty" 31 | ErrCodeBucketAlreadyExists = "BucketAlreadyExists" 32 | ErrCodeIllegalVersioningConfigurationException = "IllegalVersioningConfigurationException" 33 | ErrCodeNoSuchVersion = "NoSuchVersion" 34 | ErrCodeNotImplemented = "NotImplemented" 35 | ) 36 | 37 | // Factory interface for creating Error instances. 38 | type Factory interface { 39 | NewError(code, message string, origErr error, bucket, key, versionId *string) S3MemError 40 | } 41 | 42 | type errorFactory struct{} 43 | 44 | // NewFactory Create a new default Factory for creating S3 instances 45 | func NewFactory() Factory { 46 | return &errorFactory{} 47 | } 48 | 49 | type S3MemError interface { 50 | // Satisfy the generic error interface. 51 | awserr.Error 52 | 53 | Bucket() *string 54 | 55 | Key() *string 56 | 57 | VersionId() *string 58 | 59 | Convert2S3Error(key, versionId *string) s3.Error 60 | } 61 | 62 | type s3memError struct { 63 | code string 64 | message string 65 | origErr error 66 | bucket *string 67 | key *string 68 | versionId *string 69 | } 70 | 71 | func NewError(code, message string, origErr error, bucket, key, versionId *string) S3MemError { 72 | errf := NewFactory() 73 | return errf.NewError(code, message, origErr, bucket, key, versionId) 74 | } 75 | 76 | func (errf errorFactory) NewError(code, message string, origErr error, bucket, key, versionId *string) S3MemError { 77 | return &s3memError{ 78 | code: code, 79 | message: message, 80 | origErr: origErr, 81 | bucket: bucket, 82 | key: key, 83 | versionId: versionId, 84 | } 85 | } 86 | 87 | func (s3memError s3memError) Code() string { 88 | return s3memError.code 89 | } 90 | 91 | func (s3memError s3memError) Message() string { 92 | return s3memError.message 93 | } 94 | func (s3memError s3memError) OrigErr() error { 95 | return s3memError.origErr 96 | } 97 | 98 | func (s3memError s3memError) Bucket() *string { 99 | return s3memError.bucket 100 | } 101 | 102 | func (s3memError s3memError) Key() *string { 103 | return s3memError.key 104 | } 105 | 106 | func (s3memError s3memError) VersionId() *string { 107 | return s3memError.versionId 108 | } 109 | 110 | func (s3memError s3memError) Error() string { 111 | var errMsg string 112 | if s3memError.origErr != nil { 113 | errMsg = s3memError.origErr.Error() 114 | } 115 | var bucket string 116 | if s3memError.bucket != nil { 117 | bucket = *s3memError.bucket 118 | } 119 | var key string 120 | if s3memError.key != nil { 121 | key = *s3memError.key 122 | } 123 | var versionId string 124 | if s3memError.versionId != nil { 125 | key = *s3memError.versionId 126 | } 127 | 128 | return fmt.Sprintf("Code: %s, Message: %s, error: %s, bucket: %s, key: %s, versionId: %s", s3memError.code, s3memError.message, errMsg, bucket, key, versionId) 129 | } 130 | 131 | func (s3memError s3memError) Convert2S3Error(key, versionId *string) s3.Error { 132 | code := s3memError.Code() 133 | message := s3memError.Message() 134 | return s3.Error{ 135 | Code: &code, 136 | Message: &message, 137 | Key: key, 138 | VersionId: versionId, 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /s3mem/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################ 3 | # Copyright 2019 IBM Corp. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | ################################################################################ 17 | */ 18 | 19 | package s3mem 20 | 21 | import ( 22 | "sync" 23 | 24 | "github.com/aws/aws-sdk-go-v2/service/s3" 25 | ) 26 | 27 | type S3MemServices struct { 28 | S3MemServices map[string]*S3MemService 29 | Mux sync.Mutex 30 | } 31 | 32 | type S3MemService struct { 33 | URL string 34 | Buckets map[string]*Bucket 35 | Mux sync.Mutex 36 | } 37 | 38 | //(bucket/key/version) 39 | type Bucket struct { 40 | Bucket *s3.Bucket 41 | AccessControlPolicy *s3.AccessControlPolicy 42 | MFA *string 43 | VersioningConfiguration *s3.VersioningConfiguration 44 | Objects map[string]*VersionedObjects 45 | Mux sync.Mutex 46 | } 47 | 48 | type VersionedObjects struct { 49 | VersionedObjects []*Object 50 | } 51 | 52 | type Object struct { 53 | Object *s3.Object 54 | AccessControlPolicy *s3.AccessControlPolicy 55 | DeletedObject *s3.DeletedObject 56 | Content []byte 57 | } 58 | 59 | type Users struct { 60 | Users map[string]*User 61 | } 62 | 63 | type User struct { 64 | CanonicalID string 65 | Email string 66 | } 67 | --------------------------------------------------------------------------------