diff --git a/CREDITS b/CREDITS index efe21db99..fbf5e9a90 100644 --- a/CREDITS +++ b/CREDITS @@ -10317,6 +10317,214 @@ https://github.com/minio/highwayhash ================================================================ +github.com/minio/madmin-go +https://github.com/minio/madmin-go +---------------------------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================ + github.com/minio/md5-simd https://github.com/minio/md5-simd ---------------------------------------------------------------- @@ -15668,6 +15876,249 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================ +github.com/tklauser/go-sysconf +https://github.com/tklauser/go-sysconf +---------------------------------------------------------------- +BSD 3-Clause License + +Copyright (c) 2018, Tobias Klauser +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================ + +github.com/tklauser/numcpus +https://github.com/tklauser/numcpus +---------------------------------------------------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} Authors of Cilium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +================================================================ + github.com/tmc/grpc-websocket-proxy https://github.com/tmc/grpc-websocket-proxy ---------------------------------------------------------------- diff --git a/cmd/admin-bucket-handlers.go b/cmd/admin-bucket-handlers.go index f87f4709e..4313be5b1 100644 --- a/cmd/admin-bucket-handlers.go +++ b/cmd/admin-bucket-handlers.go @@ -24,9 +24,9 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" ) const ( diff --git a/cmd/admin-handlers-config-kv.go b/cmd/admin-handlers-config-kv.go index 0bf5d419e..36af8753a 100644 --- a/cmd/admin-handlers-config-kv.go +++ b/cmd/admin-handlers-config-kv.go @@ -27,6 +27,7 @@ import ( "strings" "github.com/gorilla/mux" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/config/cache" "github.com/minio/minio/cmd/config/etcd" @@ -37,7 +38,6 @@ import ( "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" ) func validateAdminReqConfigKV(ctx context.Context, w http.ResponseWriter, r *http.Request) (auth.Credentials, ObjectLayer) { diff --git a/cmd/admin-handlers-users.go b/cmd/admin-handlers-users.go index c1c9f6d21..0acacc659 100644 --- a/cmd/admin-handlers-users.go +++ b/cmd/admin-handlers-users.go @@ -18,6 +18,7 @@ package cmd import ( + "bytes" "context" "encoding/json" "errors" @@ -27,11 +28,11 @@ import ( "sort" "github.com/gorilla/mux" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config/dns" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" ) func validateAdminUsersReq(ctx context.Context, w http.ResponseWriter, r *http.Request, action iampolicy.AdminAction) (ObjectLayer, auth.Credentials) { @@ -533,7 +534,20 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque targetGroups = cred.Groups } - opts := newServiceAccountOpts{sessionPolicy: createReq.Policy, accessKey: createReq.AccessKey, secretKey: createReq.SecretKey} + var sp *iampolicy.Policy + if len(createReq.Policy) > 0 { + sp, err = iampolicy.ParseConfig(bytes.NewReader(createReq.Policy)) + if err != nil { + writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) + return + } + } + + opts := newServiceAccountOpts{ + accessKey: createReq.AccessKey, + secretKey: createReq.SecretKey, + sessionPolicy: sp, + } newCred, err := globalIAMSys.NewServiceAccount(ctx, targetUser, targetGroups, opts) if err != nil { writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) @@ -549,7 +563,7 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque } var createResp = madmin.AddServiceAccountResp{ - Credentials: auth.Credentials{ + Credentials: madmin.Credentials{ AccessKey: newCred.AccessKey, SecretKey: newCred.SecretKey, }, @@ -632,7 +646,19 @@ func (a adminAPIHandlers) UpdateServiceAccount(w http.ResponseWriter, r *http.Re return } - opts := updateServiceAccountOpts{sessionPolicy: updateReq.NewPolicy, secretKey: updateReq.NewSecretKey, status: updateReq.NewStatus} + var sp *iampolicy.Policy + if len(updateReq.NewPolicy) > 0 { + sp, err = iampolicy.ParseConfig(bytes.NewReader(updateReq.NewPolicy)) + if err != nil { + writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) + return + } + } + opts := updateServiceAccountOpts{ + secretKey: updateReq.NewSecretKey, + status: updateReq.NewStatus, + sessionPolicy: sp, + } err = globalIAMSys.UpdateServiceAccount(ctx, accessKey, opts) if err != nil { writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) @@ -988,9 +1014,16 @@ func (a adminAPIHandlers) AccountInfoHandler(w http.ResponseWriter, r *http.Requ return } + p := globalIAMSys.GetCombinedPolicy(policies...) + buf, err := json.Marshal(p) + if err != nil { + writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) + return + } + acctInfo := madmin.AccountInfo{ AccountName: accountName, - Policy: globalIAMSys.GetCombinedPolicy(policies...), + Policy: buf, } for _, bucket := range buckets { diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 53447e6ba..923bcef04 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -37,6 +37,7 @@ import ( "time" "github.com/gorilla/mux" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/crypto" xhttp "github.com/minio/minio/cmd/http" @@ -47,9 +48,7 @@ import ( "github.com/minio/minio/pkg/handlers" iampolicy "github.com/minio/minio/pkg/iam/policy" "github.com/minio/minio/pkg/kms" - "github.com/minio/minio/pkg/madmin" xnet "github.com/minio/minio/pkg/net" - trace "github.com/minio/minio/pkg/trace" ) const ( @@ -1061,13 +1060,13 @@ func toAdminAPIErr(ctx context.Context, err error) APIError { return apiErr } -// Returns true if the trace.Info should be traced, +// Returns true if the madmin.TraceInfo should be traced, // false if certain conditions are not met. -// - input entry is not of the type *trace.Info* +// - input entry is not of the type *madmin.TraceInfo* // - errOnly entries are to be traced, not status code 2xx, 3xx. -// - trace.Info type is asked by opts +// - madmin.TraceInfo type is asked by opts func mustTrace(entry interface{}, opts madmin.ServiceTraceOpts) (shouldTrace bool) { - trcInfo, ok := entry.(trace.Info) + trcInfo, ok := entry.(madmin.TraceInfo) if !ok { return false } @@ -1082,11 +1081,11 @@ func mustTrace(entry interface{}, opts madmin.ServiceTraceOpts) (shouldTrace boo if opts.Threshold > 0 { var latency time.Duration switch trcInfo.TraceType { - case trace.OS: + case madmin.TraceOS: latency = trcInfo.OSStats.Duration - case trace.Storage: + case madmin.TraceStorage: latency = trcInfo.StorageStats.Duration - case trace.HTTP: + case madmin.TraceHTTP: latency = trcInfo.CallStats.Latency } if latency < opts.Threshold { @@ -1094,19 +1093,19 @@ func mustTrace(entry interface{}, opts madmin.ServiceTraceOpts) (shouldTrace boo } } - if opts.Internal && trcInfo.TraceType == trace.HTTP && HasPrefix(trcInfo.ReqInfo.Path, minioReservedBucketPath+SlashSeparator) { + if opts.Internal && trcInfo.TraceType == madmin.TraceHTTP && HasPrefix(trcInfo.ReqInfo.Path, minioReservedBucketPath+SlashSeparator) { return true } - if opts.S3 && trcInfo.TraceType == trace.HTTP && !HasPrefix(trcInfo.ReqInfo.Path, minioReservedBucketPath+SlashSeparator) { + if opts.S3 && trcInfo.TraceType == madmin.TraceHTTP && !HasPrefix(trcInfo.ReqInfo.Path, minioReservedBucketPath+SlashSeparator) { return true } - if opts.Storage && trcInfo.TraceType == trace.Storage { + if opts.Storage && trcInfo.TraceType == madmin.TraceStorage { return true } - return opts.OS && trcInfo.TraceType == trace.OS + return opts.OS && trcInfo.TraceType == madmin.TraceOS } func extractTraceOptions(r *http.Request) (opts madmin.ServiceTraceOpts, err error) { diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index ec1363aef..6f451a1fe 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -30,8 +30,8 @@ import ( "testing" "github.com/gorilla/mux" + "github.com/minio/madmin-go" "github.com/minio/minio/pkg/auth" - "github.com/minio/minio/pkg/madmin" ) // adminErasureTestBed - encapsulates subsystems that need to be setup for diff --git a/cmd/admin-heal-ops.go b/cmd/admin-heal-ops.go index 99a3900a7..aa7e17651 100644 --- a/cmd/admin-heal-ops.go +++ b/cmd/admin-heal-ops.go @@ -26,8 +26,8 @@ import ( "sync" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" - "github.com/minio/minio/pkg/madmin" ) // healStatusSummary - overall short summary of a healing sequence diff --git a/cmd/admin-router.go b/cmd/admin-router.go index 75ac5e08e..87ab62de0 100644 --- a/cmd/admin-router.go +++ b/cmd/admin-router.go @@ -21,7 +21,7 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) const ( diff --git a/cmd/admin-server-info.go b/cmd/admin-server-info.go index aaefbf7f7..d2f7b164b 100644 --- a/cmd/admin-server-info.go +++ b/cmd/admin-server-info.go @@ -23,8 +23,8 @@ import ( "runtime" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" - "github.com/minio/minio/pkg/madmin" ) // getLocalServerProperty - returns madmin.ServerProperties for only the diff --git a/cmd/background-heal-ops.go b/cmd/background-heal-ops.go index dad97ec62..b1207dcf7 100644 --- a/cmd/background-heal-ops.go +++ b/cmd/background-heal-ops.go @@ -21,8 +21,8 @@ import ( "context" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" - "github.com/minio/minio/pkg/madmin" ) // healTask represents what to heal along with options diff --git a/cmd/background-newdisks-heal-ops.go b/cmd/background-newdisks-heal-ops.go index 6535cfa58..a38a0cf6f 100644 --- a/cmd/background-newdisks-heal-ops.go +++ b/cmd/background-newdisks-heal-ops.go @@ -30,11 +30,11 @@ import ( "time" "github.com/dustin/go-humanize" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/color" "github.com/minio/minio/pkg/console" - "github.com/minio/minio/pkg/madmin" ) const ( diff --git a/cmd/bucket-metadata-sys.go b/cmd/bucket-metadata-sys.go index 0884d35e6..2cae5ecfa 100644 --- a/cmd/bucket-metadata-sys.go +++ b/cmd/bucket-metadata-sys.go @@ -24,6 +24,7 @@ import ( "fmt" "sync" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/logger" @@ -34,7 +35,6 @@ import ( "github.com/minio/minio/pkg/bucket/replication" "github.com/minio/minio/pkg/bucket/versioning" "github.com/minio/minio/pkg/event" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/sync/errgroup" ) diff --git a/cmd/bucket-metadata.go b/cmd/bucket-metadata.go index c1ad6e034..d6b0cf95d 100644 --- a/cmd/bucket-metadata.go +++ b/cmd/bucket-metadata.go @@ -29,6 +29,7 @@ import ( "path" "time" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/logger" @@ -41,7 +42,6 @@ import ( "github.com/minio/minio/pkg/event" "github.com/minio/minio/pkg/fips" "github.com/minio/minio/pkg/kms" - "github.com/minio/minio/pkg/madmin" "github.com/minio/sio" ) diff --git a/cmd/bucket-quota.go b/cmd/bucket-quota.go index d6f19cd22..5a617537d 100644 --- a/cmd/bucket-quota.go +++ b/cmd/bucket-quota.go @@ -23,9 +23,9 @@ import ( "fmt" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/event" - "github.com/minio/minio/pkg/madmin" ) // BucketQuotaSys - map of bucket and quota configuration. diff --git a/cmd/bucket-replication.go b/cmd/bucket-replication.go index 787a6da32..e5ea6463f 100644 --- a/cmd/bucket-replication.go +++ b/cmd/bucket-replication.go @@ -26,6 +26,7 @@ import ( "sync" "time" + "github.com/minio/madmin-go" minio "github.com/minio/minio-go/v7" miniogo "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/encrypt" @@ -38,7 +39,6 @@ import ( "github.com/minio/minio/pkg/bucket/replication" "github.com/minio/minio/pkg/event" iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" ) // gets replication config associated to a given bucket name. diff --git a/cmd/bucket-targets.go b/cmd/bucket-targets.go index f0608eee1..deb37e57a 100644 --- a/cmd/bucket-targets.go +++ b/cmd/bucket-targets.go @@ -26,13 +26,13 @@ import ( "sync" "time" + "github.com/minio/madmin-go" minio "github.com/minio/minio-go/v7" miniogo "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/bucket/versioning" - "github.com/minio/minio/pkg/madmin" ) const ( diff --git a/cmd/config-current.go b/cmd/config-current.go index 6cf7f34b0..f3645da94 100644 --- a/cmd/config-current.go +++ b/cmd/config-current.go @@ -24,6 +24,7 @@ import ( "strings" "sync" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/config/api" "github.com/minio/minio/cmd/config/cache" @@ -43,7 +44,6 @@ import ( "github.com/minio/minio/cmd/logger/target/http" "github.com/minio/minio/pkg/env" "github.com/minio/minio/pkg/kms" - "github.com/minio/minio/pkg/madmin" ) func initHelp() { diff --git a/cmd/config-encrypted.go b/cmd/config-encrypted.go index d62934057..17274fbe1 100644 --- a/cmd/config-encrypted.go +++ b/cmd/config-encrypted.go @@ -25,11 +25,11 @@ import ( "time" "unicode/utf8" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/kms" - "github.com/minio/minio/pkg/madmin" etcd "go.etcd.io/etcd/clientv3" ) diff --git a/cmd/config-encrypted_test.go b/cmd/config-encrypted_test.go index d8155e297..c7a281532 100644 --- a/cmd/config-encrypted_test.go +++ b/cmd/config-encrypted_test.go @@ -21,8 +21,8 @@ import ( "bytes" "testing" + "github.com/minio/madmin-go" "github.com/minio/minio/pkg/auth" - "github.com/minio/minio/pkg/madmin" ) func TestDecryptData(t *testing.T) { diff --git a/cmd/config-migrate.go b/cmd/config-migrate.go index b265fa920..33a66893f 100644 --- a/cmd/config-migrate.go +++ b/cmd/config-migrate.go @@ -27,6 +27,7 @@ import ( "strings" "unicode/utf8" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/config/cache" "github.com/minio/minio/cmd/config/compress" @@ -40,7 +41,6 @@ import ( "github.com/minio/minio/pkg/event" "github.com/minio/minio/pkg/event/target" "github.com/minio/minio/pkg/kms" - "github.com/minio/minio/pkg/madmin" xnet "github.com/minio/minio/pkg/net" "github.com/minio/minio/pkg/quick" ) diff --git a/cmd/config.go b/cmd/config.go index 32caac214..507a883ad 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -26,9 +26,9 @@ import ( "unicode/utf8" jsoniter "github.com/json-iterator/go" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" "github.com/minio/minio/pkg/kms" - "github.com/minio/minio/pkg/madmin" ) const ( diff --git a/cmd/config/config.go b/cmd/config/config.go index 7783ff8a5..33b20c6e3 100644 --- a/cmd/config/config.go +++ b/cmd/config/config.go @@ -24,10 +24,10 @@ import ( "regexp" "strings" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/env" - "github.com/minio/minio/pkg/madmin" ) // Error config error type diff --git a/cmd/config/config_test.go b/cmd/config/config_test.go index 7114d4091..1238cebf9 100644 --- a/cmd/config/config_test.go +++ b/cmd/config/config_test.go @@ -20,7 +20,7 @@ package config import ( "testing" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) func TestKVFields(t *testing.T) { diff --git a/cmd/data-scanner.go b/cmd/data-scanner.go index ef7596905..8b00f1f39 100644 --- a/cmd/data-scanner.go +++ b/cmd/data-scanner.go @@ -31,6 +31,7 @@ import ( "sync" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config/heal" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger/message/audit" @@ -40,7 +41,6 @@ import ( "github.com/minio/minio/pkg/console" "github.com/minio/minio/pkg/event" "github.com/minio/minio/pkg/hash" - "github.com/minio/minio/pkg/madmin" "github.com/willf/bloom" ) diff --git a/cmd/data-usage-cache.go b/cmd/data-usage-cache.go index fd0346269..64e9c4254 100644 --- a/cmd/data-usage-cache.go +++ b/cmd/data-usage-cache.go @@ -30,10 +30,10 @@ import ( "github.com/cespare/xxhash/v2" "github.com/klauspost/compress/zstd" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/bucket/lifecycle" "github.com/minio/minio/pkg/hash" - "github.com/minio/minio/pkg/madmin" "github.com/tinylib/msgp/msgp" ) diff --git a/cmd/data-usage.go b/cmd/data-usage.go index f86133e60..747ea33bd 100644 --- a/cmd/data-usage.go +++ b/cmd/data-usage.go @@ -24,9 +24,9 @@ import ( "net/http" jsoniter "github.com/json-iterator/go" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/hash" - "github.com/minio/minio/pkg/madmin" ) const ( diff --git a/cmd/erasure-healing-common.go b/cmd/erasure-healing-common.go index 15b7b646d..03410d509 100644 --- a/cmd/erasure-healing-common.go +++ b/cmd/erasure-healing-common.go @@ -22,8 +22,8 @@ import ( "context" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/pkg/bucket/lifecycle" - "github.com/minio/minio/pkg/madmin" ) // commonTime returns a maximally occurring time from a list of time. diff --git a/cmd/erasure-healing-common_test.go b/cmd/erasure-healing-common_test.go index 1125976b9..1c8d7f28b 100644 --- a/cmd/erasure-healing-common_test.go +++ b/cmd/erasure-healing-common_test.go @@ -26,7 +26,7 @@ import ( "testing" "time" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) // validates functionality provided to find most common diff --git a/cmd/erasure-healing.go b/cmd/erasure-healing.go index daba4b827..60fa9c1da 100644 --- a/cmd/erasure-healing.go +++ b/cmd/erasure-healing.go @@ -26,9 +26,9 @@ import ( "sync" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/bucket/lifecycle" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/sync/errgroup" ) diff --git a/cmd/erasure-healing_test.go b/cmd/erasure-healing_test.go index 372d94ca3..9c99904d4 100644 --- a/cmd/erasure-healing_test.go +++ b/cmd/erasure-healing_test.go @@ -28,7 +28,7 @@ import ( "time" "github.com/dustin/go-humanize" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) // Tests both object and bucket healing. diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index 58de04a7a..a0932fb0f 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -28,6 +28,7 @@ import ( "strings" "sync" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/tags" xhttp "github.com/minio/minio/cmd/http" "github.com/minio/minio/cmd/logger" @@ -35,7 +36,6 @@ import ( "github.com/minio/minio/pkg/bucket/replication" "github.com/minio/minio/pkg/event" "github.com/minio/minio/pkg/hash" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/mimedb" "github.com/minio/minio/pkg/sync/errgroup" ) diff --git a/cmd/erasure-server-pool.go b/cmd/erasure-server-pool.go index a608ca993..9e900c8c7 100644 --- a/cmd/erasure-server-pool.go +++ b/cmd/erasure-server-pool.go @@ -30,11 +30,11 @@ import ( "sync" "time" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio/cmd/config/storageclass" "github.com/minio/minio/cmd/logger" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/sync/errgroup" "github.com/minio/minio/pkg/wildcard" ) diff --git a/cmd/erasure-sets.go b/cmd/erasure-sets.go index 99862feb1..65619dbc0 100644 --- a/cmd/erasure-sets.go +++ b/cmd/erasure-sets.go @@ -32,6 +32,7 @@ import ( "github.com/dchest/siphash" "github.com/dustin/go-humanize" "github.com/google/uuid" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio/cmd/logger" @@ -39,7 +40,6 @@ import ( "github.com/minio/minio/pkg/console" "github.com/minio/minio/pkg/dsync" "github.com/minio/minio/pkg/env" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/sync/errgroup" ) diff --git a/cmd/erasure.go b/cmd/erasure.go index f061d50eb..297b7ea38 100644 --- a/cmd/erasure.go +++ b/cmd/erasure.go @@ -27,11 +27,11 @@ import ( "sync" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/bpool" "github.com/minio/minio/pkg/color" "github.com/minio/minio/pkg/dsync" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/sync/errgroup" ) diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index 282ce92cf..125edebde 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -34,6 +34,7 @@ import ( "time" jsoniter "github.com/json-iterator/go" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/s3utils" "github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio/cmd/config" @@ -43,7 +44,6 @@ import ( "github.com/minio/minio/pkg/color" xioutil "github.com/minio/minio/pkg/ioutil" "github.com/minio/minio/pkg/lock" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/mimedb" "github.com/minio/minio/pkg/mountinfo" ) diff --git a/cmd/fs-v1_test.go b/cmd/fs-v1_test.go index 1891216e7..4adea4f5b 100644 --- a/cmd/fs-v1_test.go +++ b/cmd/fs-v1_test.go @@ -23,7 +23,7 @@ import ( "path/filepath" "testing" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) // Tests for if parent directory is object diff --git a/cmd/gateway-unsupported.go b/cmd/gateway-unsupported.go index 85099b440..bc2d57b83 100644 --- a/cmd/gateway-unsupported.go +++ b/cmd/gateway-unsupported.go @@ -29,7 +29,7 @@ import ( "github.com/minio/minio/pkg/bucket/policy" "github.com/minio/minio/pkg/bucket/versioning" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) // GatewayUnsupported list of unsupported call stubs for gateway. diff --git a/cmd/gateway/azure/gateway-azure.go b/cmd/gateway/azure/gateway-azure.go index 25e167c20..860cea375 100644 --- a/cmd/gateway/azure/gateway-azure.go +++ b/cmd/gateway/azure/gateway-azure.go @@ -40,6 +40,7 @@ import ( "github.com/Azure/azure-storage-blob-go/azblob" humanize "github.com/dustin/go-humanize" "github.com/minio/cli" + "github.com/minio/madmin-go" miniogopolicy "github.com/minio/minio-go/v7/pkg/policy" minio "github.com/minio/minio/cmd" "github.com/minio/minio/cmd/logger" @@ -47,7 +48,6 @@ import ( "github.com/minio/minio/pkg/bucket/policy" "github.com/minio/minio/pkg/bucket/policy/condition" "github.com/minio/minio/pkg/env" - "github.com/minio/minio/pkg/madmin" ) const ( diff --git a/cmd/gateway/gcs/gateway-gcs.go b/cmd/gateway/gcs/gateway-gcs.go index c18fff05f..1ea9dc135 100644 --- a/cmd/gateway/gcs/gateway-gcs.go +++ b/cmd/gateway/gcs/gateway-gcs.go @@ -37,6 +37,7 @@ import ( "cloud.google.com/go/storage" humanize "github.com/dustin/go-humanize" "github.com/minio/cli" + "github.com/minio/madmin-go" miniogopolicy "github.com/minio/minio-go/v7/pkg/policy" minio "github.com/minio/minio/cmd" "github.com/minio/minio/cmd/logger" @@ -44,7 +45,6 @@ import ( "github.com/minio/minio/pkg/bucket/policy" "github.com/minio/minio/pkg/bucket/policy/condition" "github.com/minio/minio/pkg/env" - "github.com/minio/minio/pkg/madmin" "google.golang.org/api/googleapi" "google.golang.org/api/iterator" "google.golang.org/api/option" diff --git a/cmd/gateway/hdfs/gateway-hdfs.go b/cmd/gateway/hdfs/gateway-hdfs.go index c49c60cbc..4e37b49db 100644 --- a/cmd/gateway/hdfs/gateway-hdfs.go +++ b/cmd/gateway/hdfs/gateway-hdfs.go @@ -38,12 +38,12 @@ import ( "github.com/jcmturner/gokrb5/v8/credentials" "github.com/jcmturner/gokrb5/v8/keytab" "github.com/minio/cli" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/s3utils" minio "github.com/minio/minio/cmd" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/env" - "github.com/minio/minio/pkg/madmin" xnet "github.com/minio/minio/pkg/net" ) diff --git a/cmd/gateway/nas/gateway-nas.go b/cmd/gateway/nas/gateway-nas.go index 3d95ed97a..830fd24ce 100644 --- a/cmd/gateway/nas/gateway-nas.go +++ b/cmd/gateway/nas/gateway-nas.go @@ -20,9 +20,9 @@ import ( "context" "github.com/minio/cli" + "github.com/minio/madmin-go" minio "github.com/minio/minio/cmd" "github.com/minio/minio/pkg/auth" - "github.com/minio/minio/pkg/madmin" ) func init() { diff --git a/cmd/gateway/s3/gateway-s3.go b/cmd/gateway/s3/gateway-s3.go index fbb8585fb..e076e32d4 100644 --- a/cmd/gateway/s3/gateway-s3.go +++ b/cmd/gateway/s3/gateway-s3.go @@ -27,6 +27,7 @@ import ( "time" "github.com/minio/cli" + "github.com/minio/madmin-go" miniogo "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "github.com/minio/minio-go/v7/pkg/encrypt" @@ -37,7 +38,6 @@ import ( "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/bucket/policy" - "github.com/minio/minio/pkg/madmin" ) func init() { diff --git a/cmd/global-heal.go b/cmd/global-heal.go index dcdc909cc..25640facd 100644 --- a/cmd/global-heal.go +++ b/cmd/global-heal.go @@ -24,10 +24,10 @@ import ( "sort" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/color" "github.com/minio/minio/pkg/console" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/wildcard" ) diff --git a/cmd/handler-utils.go b/cmd/handler-utils.go index 9336e7cf6..38588db43 100644 --- a/cmd/handler-utils.go +++ b/cmd/handler-utils.go @@ -32,11 +32,11 @@ import ( "regexp" "strings" + "github.com/minio/madmin-go" xhttp "github.com/minio/minio/cmd/http" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" "github.com/minio/minio/pkg/handlers" - "github.com/minio/minio/pkg/madmin" ) const ( diff --git a/cmd/healthinfo.go b/cmd/healthinfo.go index 50b0fc4eb..a92459b10 100644 --- a/cmd/healthinfo.go +++ b/cmd/healthinfo.go @@ -25,8 +25,8 @@ import ( "sync" "syscall" + "github.com/minio/madmin-go" "github.com/minio/minio/pkg/disk" - "github.com/minio/minio/pkg/madmin" cpuhw "github.com/shirou/gopsutil/v3/cpu" memhw "github.com/shirou/gopsutil/v3/mem" "github.com/shirou/gopsutil/v3/process" diff --git a/cmd/healthinfo_linux.go b/cmd/healthinfo_linux.go index 89aba5ab0..b502500d6 100644 --- a/cmd/healthinfo_linux.go +++ b/cmd/healthinfo_linux.go @@ -25,7 +25,7 @@ import ( "net/http" "strings" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" "github.com/minio/minio/pkg/smart" diskhw "github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/host" diff --git a/cmd/healthinfo_nonlinux.go b/cmd/healthinfo_nonlinux.go index 3f4624700..4d8a67b13 100644 --- a/cmd/healthinfo_nonlinux.go +++ b/cmd/healthinfo_nonlinux.go @@ -24,7 +24,7 @@ import ( "net/http" "runtime" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) func getLocalDiskHwInfo(ctx context.Context, r *http.Request) madmin.ServerDiskHwInfo { diff --git a/cmd/http-tracer.go b/cmd/http-tracer.go index 121d11dda..8b496ab94 100644 --- a/cmd/http-tracer.go +++ b/cmd/http-tracer.go @@ -31,9 +31,9 @@ import ( "time" "github.com/gorilla/mux" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/handlers" - trace "github.com/minio/minio/pkg/trace" jsonrpc "github.com/minio/rpc" ) @@ -111,7 +111,7 @@ func getOpName(name string) (op string) { } // WebTrace gets trace of web request -func WebTrace(ri *jsonrpc.RequestInfo) trace.Info { +func WebTrace(ri *jsonrpc.RequestInfo) madmin.TraceInfo { r := ri.Request w := ri.ResponseWriter @@ -126,7 +126,7 @@ func WebTrace(ri *jsonrpc.RequestInfo) trace.Info { } now := time.Now().UTC() - t := trace.Info{TraceType: trace.HTTP, FuncName: name, Time: now} + t := madmin.TraceInfo{TraceType: madmin.TraceHTTP, FuncName: name, Time: now} t.NodeName = r.Host if globalIsDistErasure { t.NodeName = globalLocalNodeName @@ -143,7 +143,7 @@ func WebTrace(ri *jsonrpc.RequestInfo) trace.Info { } vars := mux.Vars(r) - rq := trace.RequestInfo{ + rq := madmin.TraceRequestInfo{ Time: now, Proto: r.Proto, Method: r.Method, @@ -155,7 +155,7 @@ func WebTrace(ri *jsonrpc.RequestInfo) trace.Info { rw, ok := w.(*logger.ResponseWriter) if ok { - rs := trace.ResponseInfo{ + rs := madmin.TraceResponseInfo{ Time: time.Now().UTC(), Headers: rw.Header().Clone(), StatusCode: rw.StatusCode, @@ -167,7 +167,7 @@ func WebTrace(ri *jsonrpc.RequestInfo) trace.Info { } t.RespInfo = rs - t.CallStats = trace.CallStats{ + t.CallStats = madmin.TraceCallStats{ Latency: rs.Time.Sub(rw.StartTime), InputBytes: int(r.ContentLength), OutputBytes: rw.Size(), @@ -180,7 +180,7 @@ func WebTrace(ri *jsonrpc.RequestInfo) trace.Info { } // Trace gets trace of http request -func Trace(f http.HandlerFunc, logBody bool, w http.ResponseWriter, r *http.Request) trace.Info { +func Trace(f http.HandlerFunc, logBody bool, w http.ResponseWriter, r *http.Request) madmin.TraceInfo { name := getOpName(runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()) // Setup a http request body recorder @@ -196,7 +196,7 @@ func Trace(f http.HandlerFunc, logBody bool, w http.ResponseWriter, r *http.Requ r.Body = ioutil.NopCloser(reqBodyRecorder) now := time.Now().UTC() - t := trace.Info{TraceType: trace.HTTP, FuncName: name, Time: now} + t := madmin.TraceInfo{TraceType: madmin.TraceHTTP, FuncName: name, Time: now} t.NodeName = r.Host if globalIsDistErasure { @@ -214,7 +214,7 @@ func Trace(f http.HandlerFunc, logBody bool, w http.ResponseWriter, r *http.Requ } } - rq := trace.RequestInfo{ + rq := madmin.TraceRequestInfo{ Time: now, Proto: r.Proto, Method: r.Method, @@ -231,7 +231,7 @@ func Trace(f http.HandlerFunc, logBody bool, w http.ResponseWriter, r *http.Requ // Execute call. f(rw, r) - rs := trace.ResponseInfo{ + rs := madmin.TraceResponseInfo{ Time: time.Now().UTC(), Headers: rw.Header().Clone(), StatusCode: rw.StatusCode, @@ -248,7 +248,7 @@ func Trace(f http.HandlerFunc, logBody bool, w http.ResponseWriter, r *http.Requ t.ReqInfo = rq t.RespInfo = rs - t.CallStats = trace.CallStats{ + t.CallStats = madmin.TraceCallStats{ Latency: rs.Time.Sub(rw.StartTime), InputBytes: reqBodyRecorder.Size(), OutputBytes: rw.Size(), diff --git a/cmd/iam-etcd-store.go b/cmd/iam-etcd-store.go index ac9b43f4e..a6a685472 100644 --- a/cmd/iam-etcd-store.go +++ b/cmd/iam-etcd-store.go @@ -29,13 +29,13 @@ import ( "unicode/utf8" jwtgo "github.com/dgrijalva/jwt-go" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" iampolicy "github.com/minio/minio/pkg/iam/policy" "github.com/minio/minio/pkg/kms" - "github.com/minio/minio/pkg/madmin" etcd "go.etcd.io/etcd/clientv3" "go.etcd.io/etcd/mvcc/mvccpb" ) diff --git a/cmd/iam-object-store.go b/cmd/iam-object-store.go index 5dae37992..79f1bb965 100644 --- a/cmd/iam-object-store.go +++ b/cmd/iam-object-store.go @@ -28,12 +28,12 @@ import ( "time" "unicode/utf8" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" iampolicy "github.com/minio/minio/pkg/iam/policy" "github.com/minio/minio/pkg/kms" - "github.com/minio/minio/pkg/madmin" ) // IAMObjectStore implements IAMStorageAPI diff --git a/cmd/iam.go b/cmd/iam.go index 0b2f5567e..ac50d2cfe 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -30,11 +30,11 @@ import ( "time" humanize "github.com/dustin/go-humanize" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/auth" iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" ) // UsersSysType - defines the type of users and groups system that is diff --git a/cmd/metrics.go b/cmd/metrics.go index dcc14fbdd..eb44d0812 100644 --- a/cmd/metrics.go +++ b/cmd/metrics.go @@ -23,9 +23,9 @@ import ( "sync/atomic" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) diff --git a/cmd/notification-summary.go b/cmd/notification-summary.go index de96a267a..ac00d125a 100644 --- a/cmd/notification-summary.go +++ b/cmd/notification-summary.go @@ -18,7 +18,7 @@ package cmd import ( - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) // GetTotalCapacity gets the total capacity in the cluster. diff --git a/cmd/notification.go b/cmd/notification.go index 461c282aa..d62e0e3af 100644 --- a/cmd/notification.go +++ b/cmd/notification.go @@ -33,6 +33,7 @@ import ( "github.com/cespare/xxhash/v2" "github.com/klauspost/compress/zip" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio/cmd/crypto" xhttp "github.com/minio/minio/cmd/http" @@ -40,7 +41,6 @@ import ( bucketBandwidth "github.com/minio/minio/pkg/bucket/bandwidth" "github.com/minio/minio/pkg/bucket/policy" "github.com/minio/minio/pkg/event" - "github.com/minio/minio/pkg/madmin" xnet "github.com/minio/minio/pkg/net" "github.com/minio/minio/pkg/sync/errgroup" "github.com/willf/bloom" diff --git a/cmd/object-api-datatypes.go b/cmd/object-api-datatypes.go index 583d5f56b..afdf11ebf 100644 --- a/cmd/object-api-datatypes.go +++ b/cmd/object-api-datatypes.go @@ -23,9 +23,9 @@ import ( "time" humanize "github.com/dustin/go-humanize" + "github.com/minio/madmin-go" "github.com/minio/minio/pkg/bucket/replication" "github.com/minio/minio/pkg/hash" - "github.com/minio/minio/pkg/madmin" ) // BackendType - represents different backend types. diff --git a/cmd/object-api-interface.go b/cmd/object-api-interface.go index 0f6dfce4b..18cdc622c 100644 --- a/cmd/object-api-interface.go +++ b/cmd/object-api-interface.go @@ -23,10 +23,10 @@ import ( "net/http" "time" + "github.com/minio/madmin-go" "github.com/minio/minio-go/v7/pkg/encrypt" "github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio/pkg/bucket/policy" - "github.com/minio/minio/pkg/madmin" ) // CheckPreconditionFn returns true if precondition check failed. diff --git a/cmd/os-instrumented.go b/cmd/os-instrumented.go index d17349836..184ea1407 100644 --- a/cmd/os-instrumented.go +++ b/cmd/os-instrumented.go @@ -22,8 +22,8 @@ import ( "strings" "time" + "github.com/minio/madmin-go" "github.com/minio/minio/pkg/disk" - trace "github.com/minio/minio/pkg/trace" ) //go:generate stringer -type=osMetric -trimprefix=osMetric $GOFILE @@ -46,13 +46,13 @@ const ( osMetricLast ) -func osTrace(s osMetric, startTime time.Time, duration time.Duration, path string) trace.Info { - return trace.Info{ - TraceType: trace.OS, +func osTrace(s osMetric, startTime time.Time, duration time.Duration, path string) madmin.TraceInfo { + return madmin.TraceInfo{ + TraceType: madmin.TraceOS, Time: startTime, NodeName: globalLocalNodeName, FuncName: "os." + s.String(), - OSStats: trace.OSStats{ + OSStats: madmin.TraceOSStats{ Duration: duration, Path: path, }, diff --git a/cmd/peer-rest-client.go b/cmd/peer-rest-client.go index 970779de0..e8f850c74 100644 --- a/cmd/peer-rest-client.go +++ b/cmd/peer-rest-client.go @@ -33,14 +33,13 @@ import ( "time" "github.com/dustin/go-humanize" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/rest" "github.com/minio/minio/pkg/event" - "github.com/minio/minio/pkg/madmin" xnet "github.com/minio/minio/pkg/net" - "github.com/minio/minio/pkg/trace" "github.com/tinylib/msgp/msgp" ) @@ -740,7 +739,7 @@ func (client *peerRESTClient) doTrace(traceCh chan interface{}, doneCh <-chan st dec := gob.NewDecoder(respBody) for { - var info trace.Info + var info madmin.TraceInfo if err = dec.Decode(&info); err != nil { return } diff --git a/cmd/peer-rest-server.go b/cmd/peer-rest-server.go index 387bf24d6..90814493b 100644 --- a/cmd/peer-rest-server.go +++ b/cmd/peer-rest-server.go @@ -30,11 +30,10 @@ import ( "time" "github.com/gorilla/mux" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" b "github.com/minio/minio/pkg/bucket/bandwidth" "github.com/minio/minio/pkg/event" - "github.com/minio/minio/pkg/madmin" - trace "github.com/minio/minio/pkg/trace" "github.com/tinylib/msgp/msgp" ) @@ -981,7 +980,7 @@ func (s *peerRESTServer) TraceHandler(w http.ResponseWriter, r *http.Request) { } w.(http.Flusher).Flush() case <-keepAliveTicker.C: - if err := enc.Encode(&trace.Info{}); err != nil { + if err := enc.Encode(&madmin.TraceInfo{}); err != nil { return } w.(http.Flusher).Flush() diff --git a/cmd/server-main.go b/cmd/server-main.go index e87929c4f..c044bef05 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -32,6 +32,7 @@ import ( "time" "github.com/minio/cli" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" xhttp "github.com/minio/minio/cmd/http" "github.com/minio/minio/cmd/logger" @@ -42,7 +43,6 @@ import ( "github.com/minio/minio/pkg/color" "github.com/minio/minio/pkg/env" "github.com/minio/minio/pkg/fips" - "github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/sync/errgroup" ) diff --git a/cmd/server-startup-msg.go b/cmd/server-startup-msg.go index c0575ad24..d23fad59e 100644 --- a/cmd/server-startup-msg.go +++ b/cmd/server-startup-msg.go @@ -25,10 +25,10 @@ import ( "strings" humanize "github.com/dustin/go-humanize" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/logger" color "github.com/minio/minio/pkg/color" - "github.com/minio/minio/pkg/madmin" xnet "github.com/minio/minio/pkg/net" ) diff --git a/cmd/server-startup-msg_test.go b/cmd/server-startup-msg_test.go index d6b458505..6128414ce 100644 --- a/cmd/server-startup-msg_test.go +++ b/cmd/server-startup-msg_test.go @@ -23,7 +23,7 @@ import ( "strings" "testing" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) // Tests if we generate storage info. diff --git a/cmd/tier-handlers.go b/cmd/tier-handlers.go index 7e073dddc..87f4a4e6c 100644 --- a/cmd/tier-handlers.go +++ b/cmd/tier-handlers.go @@ -23,9 +23,9 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/minio/madmin-go" "github.com/minio/minio/cmd/logger" iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" ) var ( diff --git a/cmd/tier.go b/cmd/tier.go index b98251c31..9208c0d05 100644 --- a/cmd/tier.go +++ b/cmd/tier.go @@ -28,8 +28,8 @@ import ( "strings" "sync" + "github.com/minio/madmin-go" "github.com/minio/minio/pkg/hash" - "github.com/minio/minio/pkg/madmin" ) //go:generate msgp -file $GOFILE diff --git a/cmd/tier_gen.go b/cmd/tier_gen.go index b38002efa..03464d331 100644 --- a/cmd/tier_gen.go +++ b/cmd/tier_gen.go @@ -3,7 +3,7 @@ package cmd // Code generated by github.com/tinylib/msgp DO NOT EDIT. import ( - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" "github.com/tinylib/msgp/msgp" ) diff --git a/cmd/utils.go b/cmd/utils.go index 55f67dde2..efbe42777 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -43,12 +43,12 @@ import ( humanize "github.com/dustin/go-humanize" "github.com/gorilla/mux" + "github.com/minio/madmin-go" xhttp "github.com/minio/minio/cmd/http" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/rest" "github.com/minio/minio/pkg/certs" "github.com/minio/minio/pkg/handlers" - "github.com/minio/minio/pkg/madmin" "golang.org/x/net/http2" ) diff --git a/cmd/warm-backend-azure.go b/cmd/warm-backend-azure.go index b2e33a52c..9b4e68979 100644 --- a/cmd/warm-backend-azure.go +++ b/cmd/warm-backend-azure.go @@ -28,7 +28,7 @@ import ( "strings" "github.com/Azure/azure-storage-blob-go/azblob" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) type warmBackendAzure struct { diff --git a/cmd/warm-backend-gcs.go b/cmd/warm-backend-gcs.go index 559599220..a24f07997 100644 --- a/cmd/warm-backend-gcs.go +++ b/cmd/warm-backend-gcs.go @@ -23,7 +23,7 @@ import ( "io" "cloud.google.com/go/storage" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" "google.golang.org/api/googleapi" "google.golang.org/api/iterator" "google.golang.org/api/option" diff --git a/cmd/warm-backend-s3.go b/cmd/warm-backend-s3.go index 1edc44840..de11dc469 100644 --- a/cmd/warm-backend-s3.go +++ b/cmd/warm-backend-s3.go @@ -25,10 +25,10 @@ import ( "strings" "time" + "github.com/minio/madmin-go" minio "github.com/minio/minio-go/v7" miniogo "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" - "github.com/minio/minio/pkg/madmin" ) type warmBackendS3 struct { diff --git a/cmd/warm-backend.go b/cmd/warm-backend.go index cd2454a06..c1ccdfecc 100644 --- a/cmd/warm-backend.go +++ b/cmd/warm-backend.go @@ -24,7 +24,7 @@ import ( "fmt" "io" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) // WarmBackendGetOpts is used to express byte ranges within an object. The zero diff --git a/cmd/xl-storage-disk-id-check.go b/cmd/xl-storage-disk-id-check.go index fcfe3212e..d30ffa49b 100644 --- a/cmd/xl-storage-disk-id-check.go +++ b/cmd/xl-storage-disk-id-check.go @@ -26,7 +26,7 @@ import ( "time" ewma "github.com/VividCortex/ewma" - trace "github.com/minio/minio/pkg/trace" + "github.com/minio/madmin-go" ) //go:generate stringer -type=storageMetric -trimprefix=storageMetric $GOFILE @@ -607,13 +607,13 @@ func (p *xlStorageDiskIDCheck) ReadAll(ctx context.Context, volume string, path return p.storage.ReadAll(ctx, volume, path) } -func storageTrace(s storageMetric, startTime time.Time, duration time.Duration, path string) trace.Info { - return trace.Info{ - TraceType: trace.Storage, +func storageTrace(s storageMetric, startTime time.Time, duration time.Duration, path string) madmin.TraceInfo { + return madmin.TraceInfo{ + TraceType: madmin.TraceStorage, Time: startTime, NodeName: globalLocalNodeName, FuncName: "storage." + s.String(), - StorageStats: trace.StorageStats{ + StorageStats: madmin.TraceStorageStats{ Duration: duration, Path: path, }, diff --git a/go.mod b/go.mod index dd57d89b1..92611908d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( cloud.google.com/go/storage v1.8.0 github.com/Azure/azure-pipeline-go v0.2.2 github.com/Azure/azure-storage-blob-go v0.10.0 - github.com/Azure/go-autorest/autorest/adal v0.9.1 // indirect github.com/Shopify/sarama v1.27.2 github.com/VividCortex/ewma v1.1.1 github.com/alecthomas/participle v0.2.1 @@ -44,14 +43,12 @@ require ( github.com/klauspost/reedsolomon v1.9.11 github.com/lib/pq v1.9.0 github.com/mattn/go-colorable v0.1.8 - github.com/mattn/go-ieproxy v0.0.1 // indirect github.com/mattn/go-isatty v0.0.12 github.com/miekg/dns v1.1.35 - github.com/minio/argon2 v1.0.0 github.com/minio/cli v1.22.0 github.com/minio/csvparser v1.0.0 github.com/minio/highwayhash v1.0.2 - github.com/minio/md5-simd v1.1.1 // indirect + github.com/minio/madmin-go v1.0.1 github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78 github.com/minio/parquet-go v1.0.0 github.com/minio/rpc v1.0.0 @@ -62,9 +59,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/montanaflynn/stats v0.5.0 github.com/nats-io/nats-server/v2 v2.1.9 - github.com/nats-io/nats-streaming-server v0.21.1 // indirect github.com/nats-io/nats.go v1.10.0 - github.com/nats-io/nkeys v0.2.0 // indirect github.com/nats-io/stan.go v0.8.3 github.com/ncw/directio v1.0.5 github.com/nsqio/go-nsq v1.0.8 @@ -78,21 +73,19 @@ require ( github.com/rjeczalik/notify v0.9.2 github.com/rs/cors v1.7.0 github.com/secure-io/sio-go v0.3.1 - github.com/shirou/gopsutil/v3 v3.21.1 - github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/shirou/gopsutil/v3 v3.21.3 github.com/spf13/pflag v1.0.5 // indirect github.com/streadway/amqp v1.0.0 github.com/tinylib/msgp v1.1.3 github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a - github.com/willf/bitset v1.1.11 // indirect github.com/willf/bloom v2.0.3+incompatible github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c go.etcd.io/etcd v0.0.0-20201125193152-8a03d2e9614b go.uber.org/zap v1.14.1 - golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc + golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b golang.org/x/mod v0.4.0 // indirect - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 - golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 + golang.org/x/net v0.0.0-20210421230115-4e50805a0758 + golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect golang.org/x/tools v0.1.1-0.20210201201750-4d4ee958a9b7 // indirect google.golang.org/api v0.25.0 diff --git a/go.sum b/go.sum index 3a439e5f0..c05be3918 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -242,6 +243,7 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.8.3/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -378,6 +380,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= @@ -442,9 +445,12 @@ github.com/minio/csvparser v1.0.0 h1:xJEHcYK8ZAjeW4hNV9Zu30u+/2o4UyPnYgyjWp8b7ZU github.com/minio/csvparser v1.0.0/go.mod h1:lKXskSLzPgC5WQyzP7maKH7Sl1cqvANXo9YCto8zbtM= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/minio/madmin-go v1.0.1 h1:6hte9D9Wjv+GvGtk9n4XK2C9YCSQ4L2hOLDn3XZB3r0= +github.com/minio/madmin-go v1.0.1/go.mod h1:6Hox3cho6WUdTzFt3GjA4Y0abFOs11Axn25sZXiyR9M= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= github.com/minio/md5-simd v1.1.1 h1:9ojcLbuZ4gXbB2sX53MKn8JUZ0sB/2wfwsEcRw+I08U= github.com/minio/md5-simd v1.1.1/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= +github.com/minio/minio v0.0.0-20210422165109-3455f786faf0/go.mod h1:nFVEfjWoCj2KxWymJnQuVPolrE3/gvFCYm0wZkCIdXw= github.com/minio/minio-go/v7 v7.0.10/go.mod h1:td4gW1ldOsj1PbSNS+WYK43j+P1XVhX/8W8awaYlBFo= github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78 h1:v7OMbUnWkyRlO2MZ5AuYioELhwXF/BgZEznrQ1drBEM= github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78/go.mod h1:mTh2uJuAbEqdhMVl6CMIIZLUeiMiWtJR4JB8/5g2skw= @@ -595,8 +601,9 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc= github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs= -github.com/shirou/gopsutil/v3 v3.21.1 h1:dA72XXj5WOXIZkAL2iYTKRVcNOOqh4yfLn9Rm7t8BMM= github.com/shirou/gopsutil/v3 v3.21.1/go.mod h1:igHnfak0qnw1biGeI2qKQvu0ZkwvEkUcCLlYhZzdr/4= +github.com/shirou/gopsutil/v3 v3.21.3 h1:wgcdAHZS2H6qy4JFewVTtqfiYxFzCeEJod/mLztdPG8= +github.com/shirou/gopsutil/v3 v3.21.3/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -632,17 +639,24 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/gjson v1.7.5 h1:zmAN/xmX7OtpAkv4Ovfso60r/BiCi5IErCDYGNJu+uc= github.com/tidwall/gjson v1.7.5/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y= github.com/tidwall/sjson v1.1.6 h1:8fDdlahON04OZBlTQCIatW8FstSFJz8oxidj5h0rmSQ= github.com/tidwall/sjson v1.1.6/go.mod h1:KN3FZ7odvXIHPbJdhNorK/M9lWweVUbXsXXhrJ/kGOA= github.com/tinylib/msgp v1.1.3 h1:3giwAkmtaEDLSV0MdO1lDLuPgklgPzmk8H9+So2BVfA= github.com/tinylib/msgp v1.1.3/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tklauser/go-sysconf v0.3.4 h1:HT8SVixZd3IzLdfs/xlpq0jeSfTX57g1v6wB1EuzV7M= +github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= +github.com/tklauser/numcpus v0.2.1 h1:ct88eFm+Q7m2ZfXJdan1xYoXKlmwsfP+k88q05KvlZc= +github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -710,8 +724,9 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc h1:+q90ECDSAQirdykUN6sPEiBXBsp8Csjcca8Oy7bgLTA= golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -780,8 +795,9 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -848,16 +864,19 @@ golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M= +golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe h1:WdX7u8s3yOigWAhHEaDl8r9G+4XwFQEQFtBMYyN+kXQ= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -911,6 +930,7 @@ golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210201201750-4d4ee958a9b7 h1:/wdPW261t381NDQd8TBo63/FyvACfLICwtH8wMRoHJQ= golang.org/x/tools v0.1.1-0.20210201201750-4d4ee958a9b7/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -920,6 +940,7 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -947,6 +968,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= diff --git a/pkg/bucket/bandwidth/monitor.go b/pkg/bucket/bandwidth/monitor.go index b6657b205..e645ac9a8 100644 --- a/pkg/bucket/bandwidth/monitor.go +++ b/pkg/bucket/bandwidth/monitor.go @@ -22,7 +22,7 @@ import ( "sync" "time" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) // throttleBandwidth gets the throttle for bucket with the configured value diff --git a/pkg/bucket/bandwidth/monitor_test.go b/pkg/bucket/bandwidth/monitor_test.go index 2e1ffec89..bd5d58e2d 100644 --- a/pkg/bucket/bandwidth/monitor_test.go +++ b/pkg/bucket/bandwidth/monitor_test.go @@ -23,7 +23,7 @@ import ( "testing" "time" - "github.com/minio/minio/pkg/madmin" + "github.com/minio/madmin-go" ) const ( diff --git a/pkg/disk/health.go b/pkg/disk/health.go index 2cd3dbc40..2519fb417 100644 --- a/pkg/disk/health.go +++ b/pkg/disk/health.go @@ -24,37 +24,18 @@ import ( "time" "github.com/dustin/go-humanize" + "github.com/minio/madmin-go" "github.com/montanaflynn/stats" ) -// Latency holds latency information for write operations to the drive -type Latency struct { - Avg float64 `json:"avg_secs,omitempty"` - Percentile50 float64 `json:"percentile50_secs,omitempty"` - Percentile90 float64 `json:"percentile90_secs,omitempty"` - Percentile99 float64 `json:"percentile99_secs,omitempty"` - Min float64 `json:"min_secs,omitempty"` - Max float64 `json:"max_secs,omitempty"` -} - -// Throughput holds throughput information for write operations to the drive -type Throughput struct { - Avg float64 `json:"avg_bytes_per_sec,omitempty"` - Percentile50 float64 `json:"percentile50_bytes_per_sec,omitempty"` - Percentile90 float64 `json:"percentile90_bytes_per_sec,omitempty"` - Percentile99 float64 `json:"percentile99_bytes_per_sec,omitempty"` - Min float64 `json:"min_bytes_per_sec,omitempty"` - Max float64 `json:"max_bytes_per_sec,omitempty"` -} - // GetHealthInfo about the drive -func GetHealthInfo(ctx context.Context, drive, fsPath string) (Latency, Throughput, error) { +func GetHealthInfo(ctx context.Context, drive, fsPath string) (madmin.DiskLatency, madmin.DiskThroughput, error) { // Create a file with O_DIRECT flag, choose default umask and also make sure // we are exclusively writing to a new file using O_EXCL. w, err := OpenFileDirectIO(fsPath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0666) if err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } defer func() { @@ -72,13 +53,13 @@ func GetHealthInfo(ctx context.Context, drive, fsPath string) (Latency, Throughp for i := 0; i < (fileSize / blockSize); i++ { if ctx.Err() != nil { - return Latency{}, Throughput{}, ctx.Err() + return madmin.DiskLatency{}, madmin.DiskThroughput{}, ctx.Err() } startTime := time.Now() if n, err := w.Write(data); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } else if n != blockSize { - return Latency{}, Throughput{}, fmt.Errorf("Expected to write %d, but only wrote %d", blockSize, n) + return madmin.DiskLatency{}, madmin.DiskThroughput{}, fmt.Errorf("Expected to write %d, but only wrote %d", blockSize, n) } latencyInSecs := time.Since(startTime).Seconds() latencies[i] = latencyInSecs @@ -107,24 +88,24 @@ func GetHealthInfo(ctx context.Context, drive, fsPath string) (Latency, Throughp var maxThroughput float64 if avgLatency, err = stats.Mean(latencies); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if percentile50Latency, err = stats.Percentile(latencies, 50); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if percentile90Latency, err = stats.Percentile(latencies, 90); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if percentile99Latency, err = stats.Percentile(latencies, 99); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if maxLatency, err = stats.Max(latencies); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if minLatency, err = stats.Min(latencies); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } - l := Latency{ + l := madmin.DiskLatency{ Avg: avgLatency, Percentile50: percentile50Latency, Percentile90: percentile90Latency, @@ -134,25 +115,25 @@ func GetHealthInfo(ctx context.Context, drive, fsPath string) (Latency, Throughp } if avgThroughput, err = stats.Mean(throughputs); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if percentile50Throughput, err = stats.Percentile(throughputs, 50); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if percentile90Throughput, err = stats.Percentile(throughputs, 90); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if percentile99Throughput, err = stats.Percentile(throughputs, 99); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if maxThroughput, err = stats.Max(throughputs); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } if minThroughput, err = stats.Min(throughputs); err != nil { - return Latency{}, Throughput{}, err + return madmin.DiskLatency{}, madmin.DiskThroughput{}, err } - t := Throughput{ + t := madmin.DiskThroughput{ Avg: avgThroughput, Percentile50: percentile50Throughput, Percentile90: percentile90Throughput, diff --git a/pkg/madmin/README.md b/pkg/madmin/README.md deleted file mode 100644 index a5d28c1cd..000000000 --- a/pkg/madmin/README.md +++ /dev/null @@ -1,576 +0,0 @@ -# Golang Admin Client API Reference [![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io) -The MinIO Admin Golang Client SDK provides APIs to manage MinIO services. - -This quickstart guide will show you how to install the MinIO Admin client SDK, connect to MinIO admin service, and provide a walkthrough of a simple file uploader. - -This document assumes that you have a working [Golang setup](https://golang.org/doc/install). - -## Initialize MinIO Admin Client object. - -## MinIO - -```go - -package main - -import ( - "fmt" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Use a secure connection. - ssl := true - - // Initialize minio client object. - mdmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETKEY", ssl) - if err != nil { - fmt.Println(err) - return - } - - // Fetch service status. - st, err := mdmClnt.ServerInfo() - if err != nil { - fmt.Println(err) - return - } - for _, peerInfo := range serversInfo { - log.Printf("Node: %s, Info: %v\n", peerInfo.Addr, peerInfo.Data) - } -} - -``` - -| Service operations | Info operations | Healing operations | Config operations | -|:------------------------------------|:-----------------------------------------|:-------------------|:--------------------------| -| [`ServiceTrace`](#ServiceTrace) | [`ServerInfo`](#ServerInfo) | [`Heal`](#Heal) | [`GetConfig`](#GetConfig) | -| [`ServiceStop`](#ServiceStop) | [`StorageInfo`](#StorageInfo) | | [`SetConfig`](#SetConfig) | -| [`ServiceRestart`](#ServiceRestart) | [`AccountInfo`](#AccountInfo) | | | - - - -| Top operations | IAM operations | Misc | KMS | -|:------------------------|:--------------------------------------|:--------------------------------------------------|:--------------------------------| -| [`TopLocks`](#TopLocks) | [`AddUser`](#AddUser) | [`StartProfiling`](#StartProfiling) | [`GetKeyStatus`](#GetKeyStatus) | -| | [`SetUserPolicy`](#SetUserPolicy) | [`DownloadProfilingData`](#DownloadProfilingData) | | -| | [`ListUsers`](#ListUsers) | [`ServerUpdate`](#ServerUpdate) | | -| | [`AddCannedPolicy`](#AddCannedPolicy) | | | - -## 1. Constructor - - -### New(endpoint string, accessKeyID string, secretAccessKey string, ssl bool) (*AdminClient, error) -Initializes a new admin client object. - -__Parameters__ - -| Param | Type | Description | -|:------------------|:---------|:----------------------------------------------------------| -| `endpoint` | _string_ | MinIO endpoint. | -| `accessKeyID` | _string_ | Access key for the object storage endpoint. | -| `secretAccessKey` | _string_ | Secret key for the object storage endpoint. | -| `ssl` | _bool_ | Set this value to 'true' to enable secure (HTTPS) access. | - -## 2. Service operations - - -### ServiceStatus(ctx context.Context) (ServiceStatusMetadata, error) -Fetch service status, replies disk space used, backend type and total disks offline/online (applicable in distributed mode). - -| Param | Type | Description | -|-----------------|-------------------------|------------------------------------------------------------| -| `serviceStatus` | _ServiceStatusMetadata_ | Represents current server status info in following format: | - - -| Param | Type | Description | -|-----------------------------|-----------------|------------------------------------| -| `st.ServerVersion.Version` | _string_ | Server version. | -| `st.ServerVersion.CommitID` | _string_ | Server commit id. | -| `st.Uptime` | _time.Duration_ | Server uptime duration in seconds. | - - __Example__ - - ```go - - st, err := madmClnt.ServiceStatus(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Printf("%#v\n", st) - - ``` - - -### ServiceRestart(ctx context.Context) error -Sends a service action restart command to MinIO server. - - __Example__ - -```go - // To restart the service, restarts all servers in the cluster. - err := madmClnt.ServiceRestart(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Println("Success") -``` - - -### ServiceStop(ctx context.Context) error -Sends a service action stop command to MinIO server. - - __Example__ - -```go - // To stop the service, stops all servers in the cluster. - err := madmClnt.ServiceStop(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Println("Success") -``` - - -### ServiceTrace(ctx context.Context, allTrace bool, doneCh <-chan struct{}) <-chan TraceInfo -Enable HTTP request tracing on all nodes in a MinIO cluster - -__Example__ - -``` go - doneCh := make(chan struct{}) - defer close(doneCh) - // listen to all trace including internal API calls - allTrace := true - // Start listening on all trace activity. - traceCh := madmClnt.ServiceTrace(context.Background(), allTrace, doneCh) - for traceInfo := range traceCh { - fmt.Println(traceInfo.String()) - } -``` - -## 3. Info operations - - -### ServerInfo(ctx context.Context) ([]ServerInfo, error) -Fetches information for all cluster nodes, such as server properties, storage information, network statistics, etc. - -| Param | Type | Description | -|----------------------------------|--------------------|--------------------------------------------------------------------| -| `si.Addr` | _string_ | Address of the server the following information is retrieved from. | -| `si.ConnStats` | _ServerConnStats_ | Connection statistics from the given server. | -| `si.HTTPStats` | _ServerHTTPStats_ | HTTP connection statistics from the given server. | -| `si.Properties` | _ServerProperties_ | Server properties such as region, notification targets. | - -| Param | Type | Description | -|-----------------------------|-----------------|----------------------------------------------------| -| `ServerProperties.Uptime` | _time.Duration_ | Total duration in seconds since server is running. | -| `ServerProperties.Version` | _string_ | Current server version. | -| `ServerProperties.CommitID` | _string_ | Current server commitID. | -| `ServerProperties.Region` | _string_ | Configured server region. | -| `ServerProperties.SQSARN` | _[]string_ | List of notification target ARNs. | - -| Param | Type | Description | -|------------------------------------|----------|-------------------------------------| -| `ServerConnStats.TotalInputBytes` | _uint64_ | Total bytes received by the server. | -| `ServerConnStats.TotalOutputBytes` | _uint64_ | Total bytes sent by the server. | - -| Param | Type | Description | -|--------------------------------------|-------------------------|---------------------------------------------------------| -| `ServerHTTPStats.TotalHEADStats` | _ServerHTTPMethodStats_ | Total statistics regarding HEAD operations | -| `ServerHTTPStats.SuccessHEADStats` | _ServerHTTPMethodStats_ | Total statistics regarding successful HEAD operations | -| `ServerHTTPStats.TotalGETStats` | _ServerHTTPMethodStats_ | Total statistics regarding GET operations | -| `ServerHTTPStats.SuccessGETStats` | _ServerHTTPMethodStats_ | Total statistics regarding successful GET operations | -| `ServerHTTPStats.TotalPUTStats` | _ServerHTTPMethodStats_ | Total statistics regarding PUT operations | -| `ServerHTTPStats.SuccessPUTStats` | _ServerHTTPMethodStats_ | Total statistics regarding successful PUT operations | -| `ServerHTTPStats.TotalPOSTStats` | _ServerHTTPMethodStats_ | Total statistics regarding POST operations | -| `ServerHTTPStats.SuccessPOSTStats` | _ServerHTTPMethodStats_ | Total statistics regarding successful POST operations | -| `ServerHTTPStats.TotalDELETEStats` | _ServerHTTPMethodStats_ | Total statistics regarding DELETE operations | -| `ServerHTTPStats.SuccessDELETEStats` | _ServerHTTPMethodStats_ | Total statistics regarding successful DELETE operations | - -| Param | Type | Description | -|-------------------------------------|----------|-------------------------------------------------| -| `ServerHTTPMethodStats.Count` | _uint64_ | Total number of operations. | -| `ServerHTTPMethodStats.AvgDuration` | _string_ | Average duration of Count number of operations. | - -| Param | Type | Description | -|----------------------|----------|-------------------------------------------------------| -| `DriveInfo.UUID` | _string_ | Unique ID for each disk provisioned by server format. | -| `DriveInfo.Endpoint` | _string_ | Endpoint location of the remote/local disk. | -| `DriveInfo.State` | _string_ | Current state of the disk at endpoint. | - - __Example__ - - ```go - - serversInfo, err := madmClnt.ServerInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - - for _, peerInfo := range serversInfo { - log.Printf("Node: %s, Info: %v\n", peerInfo.Addr, peerInfo.Data) - } - - ``` - - -### StorageInfo(ctx context.Context) (StorageInfo, error) - -Fetches Storage information for all cluster nodes. - -| Param | Type | Description | -|-------------------------|------------|---------------------------------------------| -| `storageInfo.Used` | _[]int64_ | Used disk spaces. | -| `storageInfo.Total` | _[]int64_ | Total disk spaces. | -| `storageInfo.Available` | _[]int64_ | Available disk spaces. | -| `StorageInfo.Backend` | _struct{}_ | Represents backend type embedded structure. | - -| Param | Type | Description | -|----------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------| -| `Backend.Type` | _BackendType_ | Type of backend used by the server currently only FS or Erasure. | -| `Backend.OnlineDisks` | _BackendDisks_ | Total number of disks online per node (only applies to Erasure backend) represented in map[string]int, is empty for FS. | -| `Backend.OfflineDisks` | _BackendDisks_ | Total number of disks offline per node (only applies to Erasure backend) represented in map[string]int, is empty for FS. | -| `Backend.StandardSCParity` | _int_ | Parity disks set for standard storage class, is empty for FS. | -| `Backend.RRSCParity` | _int_ | Parity disks set for reduced redundancy storage class, is empty for FS. | -| `Backend.Sets` | _[][]DriveInfo_ | Represents topology of drives in erasure coded sets. | - -__Example__ - - ```go - - storageInfo, err := madmClnt.StorageInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - - log.Println(storageInfo) - - ``` - - - -### AccountInfo(ctx context.Context) (AccountInfo, error) - -Fetches accounting usage information for the current authenticated user - -| Param | Type | Description | -|--------------------------------|----------------------|-------------------------| -| `AccountInfo.AccountName` | _string_ | Account name. | -| `AccountInfo.Buckets` | _[]BucketAccessInfo_ | Bucket usage info. | - - -| Param | Type | Description | -|----------------------------|-----------------|-----------------------------------------| -| `BucketAccessInfo.Name` | _string_ | The name of the current bucket -| `BucketAccessInfo.Size` | _uint64_ | The total size of the current bucket -| `BucketAccessInfo.Created` | _time.Time_ | Bucket creation time -| `BucketAccessInfo.Access` | _AccountAccess_ | Type of access of the current account - - -| Param | Type | Description | -|------------------------|---------|------------------------------------------------------------------| -| `AccountAccess.Read` | _bool_ | Indicate if the bucket is readable by the current account name. | -| `AccountAccess.Write` | _bool_ | Indocate if the bucket is writable by the current account name. | - - -__Example__ - -```go - - accountInfo, err := madmClnt.AccountInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - - log.Println(accountInfo) - -``` - - - -## 5. Heal operations - - -### Heal(ctx context.Context, bucket, prefix string, healOpts HealOpts, clientToken string, forceStart bool, forceStop bool) (start HealStartSuccess, status HealTaskStatus, err error) - -Start a heal sequence that scans data under given (possible empty) -`bucket` and `prefix`. The `recursive` bool turns on recursive -traversal under the given path. `dryRun` does not mutate on-disk data, -but performs data validation. - -Two heal sequences on overlapping paths may not be initiated. - -The progress of a heal should be followed using the same API `Heal` -by providing the `clientToken` previously obtained from a `Heal` -API. The server accumulates results of the heal traversal and waits -for the client to receive and acknowledge them using the status -request by providing `clientToken`. - -__Example__ - -``` go - - opts := madmin.HealOpts{ - Recursive: true, - DryRun: false, - } - forceStart := false - forceStop := false - healPath, err := madmClnt.Heal(context.Background(), "", "", opts, "", forceStart, forceStop) - if err != nil { - log.Fatalln(err) - } - log.Printf("Heal sequence started at %s", healPath) - -``` - -#### HealStartSuccess structure - -| Param | Type | Description | -|-------------------|-------------|----------------------------------------------------------------------------------------------------------------------------------| -| `s.ClientToken` | _string_ | A unique token for a successfully started heal operation, this token is used to request realtime progress of the heal operation. | -| `s.ClientAddress` | _string_ | Address of the client which initiated the heal operation, the client address has the form "host:port". | -| `s.StartTime` | _time.Time_ | Time when heal was initially started. | - -#### HealTaskStatus structure - -| Param | Type | Description | -|-------------------|--------------------|---------------------------------------------------| -| `s.Summary` | _string_ | Short status of heal sequence | -| `s.FailureDetail` | _string_ | Error message in case of heal sequence failure | -| `s.HealSettings` | _HealOpts_ | Contains the booleans set in the `HealStart` call | -| `s.Items` | _[]HealResultItem_ | Heal records for actions performed by server | - -#### HealResultItem structure - -| Param | Type | Description | -|------------------------|----------------|-----------------------------------------------------------------| -| `ResultIndex` | _int64_ | Index of the heal-result record | -| `Type` | _HealItemType_ | Represents kind of heal operation in the heal record | -| `Bucket` | _string_ | Bucket name | -| `Object` | _string_ | Object name | -| `Detail` | _string_ | Details about heal operation | -| `DiskInfo.AvailableOn` | _[]int_ | List of disks on which the healed entity is present and healthy | -| `DiskInfo.HealedOn` | _[]int_ | List of disks on which the healed entity was restored | - -## 6. Config operations - - -### GetConfig(ctx context.Context) ([]byte, error) -Get current `config.json` of a MinIO server. - -__Example__ - -``` go - configBytes, err := madmClnt.GetConfig(context.Background()) - if err != nil { - log.Fatalf("failed due to: %v", err) - } - - // Pretty-print config received as json. - var buf bytes.Buffer - err = json.Indent(buf, configBytes, "", "\t") - if err != nil { - log.Fatalf("failed due to: %v", err) - } - - log.Println("config received successfully: ", string(buf.Bytes())) -``` - - - -### SetConfig(ctx context.Context, config io.Reader) error -Set a new `config.json` for a MinIO server. - -__Example__ - -``` go - config := bytes.NewReader([]byte(`config.json contents go here`)) - if err := madmClnt.SetConfig(context.Background(), config); err != nil { - log.Fatalf("failed due to: %v", err) - } - log.Println("SetConfig was successful") -``` - -## 7. Top operations - - -### TopLocks(ctx context.Context) (LockEntries, error) -Get the oldest locks from MinIO server. - -__Example__ - -``` go - locks, err := madmClnt.TopLocks(context.Background()) - if err != nil { - log.Fatalf("failed due to: %v", err) - } - - out, err := json.Marshal(locks) - if err != nil { - log.Fatalf("Marshal failed due to: %v", err) - } - - log.Println("TopLocks received successfully: ", string(out)) -``` - -## 8. IAM operations - - -### AddCannedPolicy(ctx context.Context, policyName string, policy *iampolicy.Policy) error -Create a new canned policy on MinIO server. - -__Example__ - -``` - policy, err := iampolicy.ParseConfig(strings.NewReader(`{"Version": "2012-10-17","Statement": [{"Action": ["s3:GetObject"],"Effect": "Allow","Resource": ["arn:aws:s3:::my-bucketname/*"],"Sid": ""}]}`)) - if err != nil { - log.Fatalln(err) - } - - if err = madmClnt.AddCannedPolicy(context.Background(), "get-only", policy); err != nil { - log.Fatalln(err) - } -``` - - -### AddUser(ctx context.Context, user string, secret string) error -Add a new user on a MinIO server. - -__Example__ - -``` go - if err = madmClnt.AddUser(context.Background(), "newuser", "newstrongpassword"); err != nil { - log.Fatalln(err) - } -``` - - -### SetUserPolicy(ctx context.Context, user string, policyName string) error -Enable a canned policy `get-only` for a given user on MinIO server. - -__Example__ - -``` go - if err = madmClnt.SetUserPolicy(context.Background(), "newuser", "get-only"); err != nil { - log.Fatalln(err) - } -``` - - -### ListUsers(ctx context.Context) (map[string]UserInfo, error) -Lists all users on MinIO server. - -__Example__ - -``` go - users, err := madmClnt.ListUsers(context.Background()); - if err != nil { - log.Fatalln(err) - } - for k, v := range users { - fmt.Printf("User %s Status %s\n", k, v.Status) - } -``` - -## 9. Misc operations - - -### ServerUpdate(ctx context.Context, updateURL string) (ServerUpdateStatus, error) -Sends a update command to MinIO server, to update MinIO server to latest release. In distributed setup it updates all servers atomically. - - __Example__ - -```go - // Updates all servers and restarts all the servers in the cluster. - // optionally takes an updateURL, which is used to update the binary. - us, err := madmClnt.ServerUpdate(context.Background(), updateURL) - if err != nil { - log.Fatalln(err) - } - if us.CurrentVersion != us.UpdatedVersion { - log.Printf("Updated server version from %s to %s successfully", us.CurrentVersion, us.UpdatedVersion) - } -``` - - -### StartProfiling(ctx context.Context, profiler string) error -Ask all nodes to start profiling using the specified profiler mode - -__Example__ - -``` go - startProfilingResults, err = madmClnt.StartProfiling(context.Background(), "cpu") - if err != nil { - log.Fatalln(err) - } - for _, result := range startProfilingResults { - if !result.Success { - log.Printf("Unable to start profiling on node `%s`, reason = `%s`\n", result.NodeName, result.Error) - } else { - log.Printf("Profiling successfully started on node `%s`\n", result.NodeName) - } - } - -``` - - -### DownloadProfilingData(ctx context.Context) ([]byte, error) -Download profiling data of all nodes in a zip format. - -__Example__ - -``` go - profilingData, err := madmClnt.DownloadProfilingData(context.Background()) - if err != nil { - log.Fatalln(err) - } - - profilingFile, err := os.Create("/tmp/profiling-data.zip") - if err != nil { - log.Fatal(err) - } - - if _, err := io.Copy(profilingFile, profilingData); err != nil { - log.Fatal(err) - } - - if err := profilingFile.Close(); err != nil { - log.Fatal(err) - } - - if err := profilingData.Close(); err != nil { - log.Fatal(err) - } - - log.Println("Profiling data successfully downloaded.") -``` - -## 11. KMS - - -### GetKeyStatus(ctx context.Context, keyID string) (*KMSKeyStatus, error) -Requests status information about one particular KMS master key -from a MinIO server. The keyID is optional and the server will -use the default master key (configured via `MINIO_KMS_VAULT_KEY_NAME` -or `MINIO_KMS_MASTER_KEY`) if the keyID is empty. - -__Example__ - -``` go - keyInfo, err := madmClnt.GetKeyStatus(context.Background(), "my-minio-key") - if err != nil { - log.Fatalln(err) - } - if keyInfo.EncryptionErr != "" { - log.Fatalf("Failed to perform encryption operation using '%s': %v\n", keyInfo.KeyID, keyInfo.EncryptionErr) - } - if keyInfo.UpdateErr != "" { - log.Fatalf("Failed to perform key re-wrap operation using '%s': %v\n", keyInfo.KeyID, keyInfo.UpdateErr) - } - if keyInfo.DecryptionErr != "" { - log.Fatalf("Failed to perform decryption operation using '%s': %v\n", keyInfo.KeyID, keyInfo.DecryptionErr) - } -``` diff --git a/pkg/madmin/api-error-response.go b/pkg/madmin/api-error-response.go deleted file mode 100644 index e45265341..000000000 --- a/pkg/madmin/api-error-response.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "encoding/xml" - "fmt" - "net/http" -) - -/* **** SAMPLE ERROR RESPONSE **** - - - AccessDenied - Access Denied - bucketName - objectName - F19772218238A85A - GuWkjyviSiGHizehqpmsD1ndz5NClSP19DOT+s2mv7gXGQ8/X1lhbDGiIJEXpGFD - -*/ - -// ErrorResponse - Is the typed error returned by all API operations. -type ErrorResponse struct { - XMLName xml.Name `xml:"Error" json:"-"` - Code string - Message string - BucketName string - Key string - RequestID string `xml:"RequestId"` - HostID string `xml:"HostId"` - - // Region where the bucket is located. This header is returned - // only in HEAD bucket and ListObjects response. - Region string -} - -// Error - Returns HTTP error string -func (e ErrorResponse) Error() string { - return e.Message -} - -const ( - reportIssue = "Please report this issue at https://github.com/minio/minio/issues." -) - -// httpRespToErrorResponse returns a new encoded ErrorResponse -// structure as error. -func httpRespToErrorResponse(resp *http.Response) error { - if resp == nil { - msg := "Response is empty. " + reportIssue - return ErrInvalidArgument(msg) - } - var errResp ErrorResponse - // Decode the json error - err := jsonDecoder(resp.Body, &errResp) - if err != nil { - return ErrorResponse{ - Code: resp.Status, - Message: fmt.Sprintf("Failed to parse server response: %s.", err), - } - } - closeResponse(resp) - return errResp -} - -// ToErrorResponse - Returns parsed ErrorResponse struct from body and -// http headers. -// -// For example: -// -// import admin "github.com/minio/minio/pkg/madmin" -// ... -// ... -// ss, err := adm.ServiceStatus(...) -// if err != nil { -// resp := admin.ToErrorResponse(err) -// } -// ... -func ToErrorResponse(err error) ErrorResponse { - switch err := err.(type) { - case ErrorResponse: - return err - default: - return ErrorResponse{} - } -} - -// ErrInvalidArgument - Invalid argument response. -func ErrInvalidArgument(message string) error { - return ErrorResponse{ - Code: "InvalidArgument", - Message: message, - RequestID: "minio", - } -} diff --git a/pkg/madmin/api-log-entry.go b/pkg/madmin/api-log-entry.go deleted file mode 100644 index 5f9bcab60..000000000 --- a/pkg/madmin/api-log-entry.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -// Args - defines the arguments for the API. -type logArgs struct { - Bucket string `json:"bucket,omitempty"` - Object string `json:"object,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` -} - -// Trace - defines the trace. -type logTrace struct { - Message string `json:"message,omitempty"` - Source []string `json:"source,omitempty"` - Variables map[string]string `json:"variables,omitempty"` -} - -// API - defines the api type and its args. -type logAPI struct { - Name string `json:"name,omitempty"` - Args *logArgs `json:"args,omitempty"` -} - -// Entry - defines fields and values of each log entry. -type logEntry struct { - DeploymentID string `json:"deploymentid,omitempty"` - Level string `json:"level"` - LogKind string `json:"errKind"` - Time string `json:"time"` - API *logAPI `json:"api,omitempty"` - RemoteHost string `json:"remotehost,omitempty"` - Host string `json:"host,omitempty"` - RequestID string `json:"requestID,omitempty"` - UserAgent string `json:"userAgent,omitempty"` - Message string `json:"message,omitempty"` - Trace *logTrace `json:"error,omitempty"` -} diff --git a/pkg/madmin/api-log.go b/pkg/madmin/api-log.go deleted file mode 100644 index 7d0af2065..000000000 --- a/pkg/madmin/api-log.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "net/http" - "net/url" - "strconv" -) - -// LogInfo holds console log messages -type LogInfo struct { - logEntry - ConsoleMsg string - NodeName string `json:"node"` - Err error `json:"-"` -} - -// GetLogs - listen on console log messages. -func (adm AdminClient) GetLogs(ctx context.Context, node string, lineCnt int, logKind string) <-chan LogInfo { - logCh := make(chan LogInfo, 1) - - // Only success, start a routine to start reading line by line. - go func(logCh chan<- LogInfo) { - defer close(logCh) - urlValues := make(url.Values) - urlValues.Set("node", node) - urlValues.Set("limit", strconv.Itoa(lineCnt)) - urlValues.Set("logType", logKind) - for { - reqData := requestData{ - relPath: adminAPIPrefix + "/log", - queryValues: urlValues, - } - // Execute GET to call log handler - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - if err != nil { - closeResponse(resp) - return - } - - if resp.StatusCode != http.StatusOK { - logCh <- LogInfo{Err: httpRespToErrorResponse(resp)} - return - } - dec := json.NewDecoder(resp.Body) - for { - var info LogInfo - if err = dec.Decode(&info); err != nil { - break - } - select { - case <-ctx.Done(): - return - case logCh <- info: - } - } - - } - }(logCh) - - // Returns the log info channel, for caller to start reading from. - return logCh -} diff --git a/pkg/madmin/api.go b/pkg/madmin/api.go deleted file mode 100644 index 423a12ff2..000000000 --- a/pkg/madmin/api.go +++ /dev/null @@ -1,510 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "bytes" - "context" - "crypto/sha256" - "encoding/hex" - "errors" - "fmt" - "io" - "io/ioutil" - "math/rand" - "net/http" - "net/http/cookiejar" - "net/http/httputil" - "net/url" - "os" - "regexp" - "runtime" - "strings" - "syscall" - "time" - - "github.com/minio/minio-go/v7/pkg/credentials" - "github.com/minio/minio-go/v7/pkg/s3utils" - "github.com/minio/minio-go/v7/pkg/signer" - "golang.org/x/net/publicsuffix" -) - -// AdminClient implements Amazon S3 compatible methods. -type AdminClient struct { - /// Standard options. - - // Parsed endpoint url provided by the user. - endpointURL *url.URL - - // Holds various credential providers. - credsProvider *credentials.Credentials - - // User supplied. - appInfo struct { - appName string - appVersion string - } - - // Indicate whether we are using https or not - secure bool - - // Needs allocation. - httpClient *http.Client - - random *rand.Rand - - // Advanced functionality. - isTraceEnabled bool - traceOutput io.Writer -} - -// Global constants. -const ( - libraryName = "madmin-go" - libraryVersion = "0.0.1" - - libraryAdminURLPrefix = "/minio/admin" -) - -// User Agent should always following the below style. -// Please open an issue to discuss any new changes here. -// -// MinIO (OS; ARCH) LIB/VER APP/VER -const ( - libraryUserAgentPrefix = "MinIO (" + runtime.GOOS + "; " + runtime.GOARCH + ") " - libraryUserAgent = libraryUserAgentPrefix + libraryName + "/" + libraryVersion -) - -// Options for New method -type Options struct { - Creds *credentials.Credentials - Secure bool - // Add future fields here -} - -// New - instantiate minio admin client -func New(endpoint string, accessKeyID, secretAccessKey string, secure bool) (*AdminClient, error) { - creds := credentials.NewStaticV4(accessKeyID, secretAccessKey, "") - - clnt, err := privateNew(endpoint, creds, secure) - if err != nil { - return nil, err - } - return clnt, nil -} - -// NewWithOptions - instantiate minio admin client with options. -func NewWithOptions(endpoint string, opts *Options) (*AdminClient, error) { - clnt, err := privateNew(endpoint, opts.Creds, opts.Secure) - if err != nil { - return nil, err - } - return clnt, nil -} - -func privateNew(endpoint string, creds *credentials.Credentials, secure bool) (*AdminClient, error) { - // Initialize cookies to preserve server sent cookies if any and replay - // them upon each request. - jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) - if err != nil { - return nil, err - } - - // construct endpoint. - endpointURL, err := getEndpointURL(endpoint, secure) - if err != nil { - return nil, err - } - - clnt := new(AdminClient) - - // Save the credentials. - clnt.credsProvider = creds - - // Remember whether we are using https or not - clnt.secure = secure - - // Save endpoint URL, user agent for future uses. - clnt.endpointURL = endpointURL - - // Instantiate http client and bucket location cache. - clnt.httpClient = &http.Client{ - Jar: jar, - Transport: DefaultTransport(secure), - } - - // Add locked pseudo-random number generator. - clnt.random = rand.New(&lockedRandSource{src: rand.NewSource(time.Now().UTC().UnixNano())}) - - // Return. - return clnt, nil -} - -// SetAppInfo - add application details to user agent. -func (adm *AdminClient) SetAppInfo(appName string, appVersion string) { - // if app name and version is not set, we do not a new user - // agent. - if appName != "" && appVersion != "" { - adm.appInfo.appName = appName - adm.appInfo.appVersion = appVersion - } -} - -// SetCustomTransport - set new custom transport. -func (adm *AdminClient) SetCustomTransport(customHTTPTransport http.RoundTripper) { - // Set this to override default transport - // ``http.DefaultTransport``. - // - // This transport is usually needed for debugging OR to add your - // own custom TLS certificates on the client transport, for custom - // CA's and certs which are not part of standard certificate - // authority follow this example :- - // - // tr := &http.Transport{ - // TLSClientConfig: &tls.Config{RootCAs: pool}, - // DisableCompression: true, - // } - // api.SetTransport(tr) - // - if adm.httpClient != nil { - adm.httpClient.Transport = customHTTPTransport - } -} - -// TraceOn - enable HTTP tracing. -func (adm *AdminClient) TraceOn(outputStream io.Writer) { - // if outputStream is nil then default to os.Stdout. - if outputStream == nil { - outputStream = os.Stdout - } - // Sets a new output stream. - adm.traceOutput = outputStream - - // Enable tracing. - adm.isTraceEnabled = true -} - -// TraceOff - disable HTTP tracing. -func (adm *AdminClient) TraceOff() { - // Disable tracing. - adm.isTraceEnabled = false -} - -// requestMetadata - is container for all the values to make a -// request. -type requestData struct { - customHeaders http.Header - queryValues url.Values - relPath string // URL path relative to admin API base endpoint - content []byte -} - -// Filter out signature value from Authorization header. -func (adm AdminClient) filterSignature(req *http.Request) { - /// Signature V4 authorization header. - - // Save the original auth. - origAuth := req.Header.Get("Authorization") - // Strip out accessKeyID from: - // Credential=////aws4_request - regCred := regexp.MustCompile("Credential=([A-Z0-9]+)/") - newAuth := regCred.ReplaceAllString(origAuth, "Credential=**REDACTED**/") - - // Strip out 256-bit signature from: Signature=<256-bit signature> - regSign := regexp.MustCompile("Signature=([[0-9a-f]+)") - newAuth = regSign.ReplaceAllString(newAuth, "Signature=**REDACTED**") - - // Set a temporary redacted auth - req.Header.Set("Authorization", newAuth) -} - -// dumpHTTP - dump HTTP request and response. -func (adm AdminClient) dumpHTTP(req *http.Request, resp *http.Response) error { - // Starts http dump. - _, err := fmt.Fprintln(adm.traceOutput, "---------START-HTTP---------") - if err != nil { - return err - } - - // Filter out Signature field from Authorization header. - adm.filterSignature(req) - - // Only display request header. - reqTrace, err := httputil.DumpRequestOut(req, false) - if err != nil { - return err - } - - // Write request to trace output. - _, err = fmt.Fprint(adm.traceOutput, string(reqTrace)) - if err != nil { - return err - } - - // Only display response header. - var respTrace []byte - - // For errors we make sure to dump response body as well. - if resp.StatusCode != http.StatusOK && - resp.StatusCode != http.StatusPartialContent && - resp.StatusCode != http.StatusNoContent { - respTrace, err = httputil.DumpResponse(resp, true) - if err != nil { - return err - } - } else { - // WORKAROUND for https://github.com/golang/go/issues/13942. - // httputil.DumpResponse does not print response headers for - // all successful calls which have response ContentLength set - // to zero. Keep this workaround until the above bug is fixed. - if resp.ContentLength == 0 { - var buffer bytes.Buffer - if err = resp.Header.Write(&buffer); err != nil { - return err - } - respTrace = buffer.Bytes() - respTrace = append(respTrace, []byte("\r\n")...) - } else { - respTrace, err = httputil.DumpResponse(resp, false) - if err != nil { - return err - } - } - } - // Write response to trace output. - _, err = fmt.Fprint(adm.traceOutput, strings.TrimSuffix(string(respTrace), "\r\n")) - if err != nil { - return err - } - - // Ends the http dump. - _, err = fmt.Fprintln(adm.traceOutput, "---------END-HTTP---------") - return err -} - -// do - execute http request. -func (adm AdminClient) do(req *http.Request) (*http.Response, error) { - resp, err := adm.httpClient.Do(req) - if err != nil { - // Handle this specifically for now until future Golang versions fix this issue properly. - if urlErr, ok := err.(*url.Error); ok { - if strings.Contains(urlErr.Err.Error(), "EOF") { - return nil, &url.Error{ - Op: urlErr.Op, - URL: urlErr.URL, - Err: errors.New("Connection closed by foreign host " + urlErr.URL + ". Retry again."), - } - } - } - return nil, err - } - - // Response cannot be non-nil, report if its the case. - if resp == nil { - msg := "Response is empty. " // + reportIssue - return nil, ErrInvalidArgument(msg) - } - - // If trace is enabled, dump http request and response. - if adm.isTraceEnabled { - err = adm.dumpHTTP(req, resp) - if err != nil { - return nil, err - } - } - return resp, nil -} - -// List of success status. -var successStatus = []int{ - http.StatusOK, - http.StatusNoContent, - http.StatusPartialContent, -} - -// executeMethod - instantiates a given method, and retries the -// request upon any error up to maxRetries attempts in a binomially -// delayed manner using a standard back off algorithm. -func (adm AdminClient) executeMethod(ctx context.Context, method string, reqData requestData) (res *http.Response, err error) { - var reqRetry = MaxRetry // Indicates how many times we can retry the request - defer func() { - if err != nil { - // close idle connections before returning, upon error. - adm.httpClient.CloseIdleConnections() - } - }() - - // Create cancel context to control 'newRetryTimer' go routine. - retryCtx, cancel := context.WithCancel(ctx) - - // Indicate to our routine to exit cleanly upon return. - defer cancel() - - for range adm.newRetryTimer(retryCtx, reqRetry, DefaultRetryUnit, DefaultRetryCap, MaxJitter) { - // Instantiate a new request. - var req *http.Request - req, err = adm.newRequest(ctx, method, reqData) - if err != nil { - return nil, err - } - - // Initiate the request. - res, err = adm.do(req) - if err != nil { - // Give up right away if it is a connection refused problem - if errors.Is(err, syscall.ECONNREFUSED) { - return nil, err - } - if err == context.Canceled || err == context.DeadlineExceeded { - return nil, err - } - // retry all network errors. - continue - } - - // For any known successful http status, return quickly. - for _, httpStatus := range successStatus { - if httpStatus == res.StatusCode { - return res, nil - } - } - - // Read the body to be saved later. - errBodyBytes, err := ioutil.ReadAll(res.Body) - // res.Body should be closed - closeResponse(res) - if err != nil { - return nil, err - } - - // Save the body. - errBodySeeker := bytes.NewReader(errBodyBytes) - res.Body = ioutil.NopCloser(errBodySeeker) - - // For errors verify if its retryable otherwise fail quickly. - errResponse := ToErrorResponse(httpRespToErrorResponse(res)) - - // Save the body back again. - errBodySeeker.Seek(0, 0) // Seek back to starting point. - res.Body = ioutil.NopCloser(errBodySeeker) - - // Verify if error response code is retryable. - if isS3CodeRetryable(errResponse.Code) { - continue // Retry. - } - - // Verify if http status code is retryable. - if isHTTPStatusRetryable(res.StatusCode) { - continue // Retry. - } - - break - } - - // Return an error when retry is canceled or deadlined - if e := retryCtx.Err(); e != nil { - return nil, e - } - - return res, err -} - -// set User agent. -func (adm AdminClient) setUserAgent(req *http.Request) { - req.Header.Set("User-Agent", libraryUserAgent) - if adm.appInfo.appName != "" && adm.appInfo.appVersion != "" { - req.Header.Set("User-Agent", libraryUserAgent+" "+adm.appInfo.appName+"/"+adm.appInfo.appVersion) - } -} - -func (adm AdminClient) getSecretKey() string { - value, err := adm.credsProvider.Get() - if err != nil { - // Return empty, call will fail. - return "" - } - - return value.SecretAccessKey -} - -// newRequest - instantiate a new HTTP request for a given method. -func (adm AdminClient) newRequest(ctx context.Context, method string, reqData requestData) (req *http.Request, err error) { - // If no method is supplied default to 'POST'. - if method == "" { - method = "POST" - } - - // Default all requests to "" - location := "" - - // Construct a new target URL. - targetURL, err := adm.makeTargetURL(reqData) - if err != nil { - return nil, err - } - - // Initialize a new HTTP request for the method. - req, err = http.NewRequestWithContext(ctx, method, targetURL.String(), nil) - if err != nil { - return nil, err - } - - value, err := adm.credsProvider.Get() - if err != nil { - return nil, err - } - - var ( - accessKeyID = value.AccessKeyID - secretAccessKey = value.SecretAccessKey - sessionToken = value.SessionToken - ) - - adm.setUserAgent(req) - for k, v := range reqData.customHeaders { - req.Header.Set(k, v[0]) - } - if length := len(reqData.content); length > 0 { - req.ContentLength = int64(length) - } - sum := sha256.Sum256(reqData.content) - req.Header.Set("X-Amz-Content-Sha256", hex.EncodeToString(sum[:])) - req.Body = ioutil.NopCloser(bytes.NewReader(reqData.content)) - - req = signer.SignV4(*req, accessKeyID, secretAccessKey, sessionToken, location) - return req, nil -} - -// makeTargetURL make a new target url. -func (adm AdminClient) makeTargetURL(r requestData) (*url.URL, error) { - - host := adm.endpointURL.Host - scheme := adm.endpointURL.Scheme - - urlStr := scheme + "://" + host + libraryAdminURLPrefix + r.relPath - - // If there are any query values, add them to the end. - if len(r.queryValues) > 0 { - urlStr = urlStr + "?" + s3utils.QueryEncode(r.queryValues) - } - u, err := url.Parse(urlStr) - if err != nil { - return nil, err - } - return u, nil -} diff --git a/pkg/madmin/api_test.go b/pkg/madmin/api_test.go deleted file mode 100644 index c13ebb03c..000000000 --- a/pkg/madmin/api_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Package madmin_test -package madmin_test - -import ( - "testing" - - "github.com/minio/minio/pkg/madmin" -) - -func TestMinioAdminClient(t *testing.T) { - _, err := madmin.New("localhost:9000", "food", "food123", true) - if err != nil { - t.Fatal(err) - } -} diff --git a/pkg/madmin/bandwidth.go b/pkg/madmin/bandwidth.go deleted file mode 100644 index 539661d71..000000000 --- a/pkg/madmin/bandwidth.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "net/http" - "net/url" - "strings" -) - -// BandwidthDetails for the measured bandwidth -type BandwidthDetails struct { - LimitInBytesPerSecond int64 `json:"limitInBits"` - CurrentBandwidthInBytesPerSecond float64 `json:"currentBandwidth"` -} - -// BucketBandwidthReport captures the details for all buckets. -type BucketBandwidthReport struct { - BucketStats map[string]BandwidthDetails `json:"bucketStats,omitempty"` -} - -// Report includes the bandwidth report or the error encountered. -type Report struct { - Report BucketBandwidthReport `json:"report"` - Err error `json:"error,omitempty"` -} - -// GetBucketBandwidth - Gets a channel reporting bandwidth measurements for replication buckets. If no buckets -// generate replication traffic an empty map is returned in the report until traffic is seen. -func (adm *AdminClient) GetBucketBandwidth(ctx context.Context, buckets ...string) <-chan Report { - queryValues := url.Values{} - ch := make(chan Report) - if len(buckets) > 0 { - queryValues.Set("buckets", strings.Join(buckets, ",")) - } - - reqData := requestData{ - relPath: adminAPIPrefix + "/bandwidth", - queryValues: queryValues, - } - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - if err != nil { - defer closeResponse(resp) - ch <- Report{Err: err} - return ch - } - if resp.StatusCode != http.StatusOK { - ch <- Report{Err: httpRespToErrorResponse(resp)} - return ch - } - - dec := json.NewDecoder(resp.Body) - - go func(ctx context.Context, ch chan<- Report, resp *http.Response) { - defer func() { - closeResponse(resp) - close(ch) - }() - for { - var report BucketBandwidthReport - - if err = dec.Decode(&report); err != nil { - ch <- Report{Err: err} - return - } - select { - case <-ctx.Done(): - return - case ch <- Report{Report: report}: - } - } - }(ctx, ch, resp) - return ch -} diff --git a/pkg/madmin/config-commands.go b/pkg/madmin/config-commands.go deleted file mode 100644 index c0a8499b2..000000000 --- a/pkg/madmin/config-commands.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "bytes" - "context" - "io" - "net/http" -) - -// GetConfig - returns the config.json of a minio setup, incoming data is encrypted. -func (adm *AdminClient) GetConfig(ctx context.Context) ([]byte, error) { - // Execute GET on /minio/admin/v3/config to get config of a setup. - resp, err := adm.executeMethod(ctx, - http.MethodGet, - requestData{relPath: adminAPIPrefix + "/config"}) - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - return DecryptData(adm.getSecretKey(), resp.Body) -} - -// SetConfig - set config supplied as config.json for the setup. -func (adm *AdminClient) SetConfig(ctx context.Context, config io.Reader) (err error) { - const maxConfigJSONSize = 256 * 1024 // 256KiB - - // Read configuration bytes - configBuf := make([]byte, maxConfigJSONSize+1) - n, err := io.ReadFull(config, configBuf) - if err == nil { - return bytes.ErrTooLarge - } - if err != io.ErrUnexpectedEOF { - return err - } - configBytes := configBuf[:n] - econfigBytes, err := EncryptData(adm.getSecretKey(), configBytes) - if err != nil { - return err - } - - reqData := requestData{ - relPath: adminAPIPrefix + "/config", - content: econfigBytes, - } - - // Execute PUT on /minio/admin/v3/config to set config. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} diff --git a/pkg/madmin/config-help-commands.go b/pkg/madmin/config-help-commands.go deleted file mode 100644 index 837678406..000000000 --- a/pkg/madmin/config-help-commands.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "net/http" - "net/url" -) - -// Help - return sub-system level help -type Help struct { - SubSys string `json:"subSys"` - Description string `json:"description"` - MultipleTargets bool `json:"multipleTargets"` - KeysHelp HelpKVS `json:"keysHelp"` -} - -// HelpKV - implements help messages for keys -// with value as description of the keys. -type HelpKV struct { - Key string `json:"key"` - Description string `json:"description"` - Optional bool `json:"optional"` - Type string `json:"type"` - MultipleTargets bool `json:"multipleTargets"` -} - -// HelpKVS - implement order of keys help messages. -type HelpKVS []HelpKV - -// Keys returns help keys -func (h Help) Keys() []string { - var keys []string - for _, kh := range h.KeysHelp { - keys = append(keys, kh.Key) - } - return keys -} - -// HelpConfigKV - return help for a given sub-system. -func (adm *AdminClient) HelpConfigKV(ctx context.Context, subSys, key string, envOnly bool) (Help, error) { - v := url.Values{} - v.Set("subSys", subSys) - v.Set("key", key) - if envOnly { - v.Set("env", "") - } - - reqData := requestData{ - relPath: adminAPIPrefix + "/help-config-kv", - queryValues: v, - } - - // Execute GET on /minio/admin/v3/help-config-kv - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - if err != nil { - return Help{}, err - } - defer closeResponse(resp) - - if resp.StatusCode != http.StatusOK { - return Help{}, httpRespToErrorResponse(resp) - } - - var help = Help{} - d := json.NewDecoder(resp.Body) - d.DisallowUnknownFields() - if err = d.Decode(&help); err != nil { - return help, err - } - - return help, nil -} diff --git a/pkg/madmin/config-history-commands.go b/pkg/madmin/config-history-commands.go deleted file mode 100644 index 9cbebecaa..000000000 --- a/pkg/madmin/config-history-commands.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "net/http" - "net/url" - "strconv" - "time" -) - -// ClearConfigHistoryKV - clears the config entry represented by restoreID. -// optionally allows setting `all` as a special keyword to automatically -// erase all config set history entires. -func (adm *AdminClient) ClearConfigHistoryKV(ctx context.Context, restoreID string) (err error) { - v := url.Values{} - v.Set("restoreId", restoreID) - reqData := requestData{ - relPath: adminAPIPrefix + "/clear-config-history-kv", - queryValues: v, - } - - // Execute DELETE on /minio/admin/v3/clear-config-history-kv - resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// RestoreConfigHistoryKV - Restore a previous config set history. -// Input is a unique id which represents the previous setting. -func (adm *AdminClient) RestoreConfigHistoryKV(ctx context.Context, restoreID string) (err error) { - v := url.Values{} - v.Set("restoreId", restoreID) - reqData := requestData{ - relPath: adminAPIPrefix + "/restore-config-history-kv", - queryValues: v, - } - - // Execute PUT on /minio/admin/v3/set-config-kv to set config key/value. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// ConfigHistoryEntry - captures config set history with a unique -// restore ID and createTime -type ConfigHistoryEntry struct { - RestoreID string `json:"restoreId"` - CreateTime time.Time `json:"createTime"` - Data string `json:"data"` -} - -// CreateTimeFormatted is used to print formatted time for CreateTime. -func (ch ConfigHistoryEntry) CreateTimeFormatted() string { - return ch.CreateTime.Format(http.TimeFormat) -} - -// ListConfigHistoryKV - lists a slice of ConfigHistoryEntries sorted by createTime. -func (adm *AdminClient) ListConfigHistoryKV(ctx context.Context, count int) ([]ConfigHistoryEntry, error) { - if count == 0 { - count = 10 - } - v := url.Values{} - v.Set("count", strconv.Itoa(count)) - - // Execute GET on /minio/admin/v3/list-config-history-kv - resp, err := adm.executeMethod(ctx, - http.MethodGet, - requestData{ - relPath: adminAPIPrefix + "/list-config-history-kv", - queryValues: v, - }) - defer closeResponse(resp) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - data, err := DecryptData(adm.getSecretKey(), resp.Body) - if err != nil { - return nil, err - } - - var chEntries []ConfigHistoryEntry - if err = json.Unmarshal(data, &chEntries); err != nil { - return chEntries, err - } - - return chEntries, nil -} diff --git a/pkg/madmin/config-kv-commands.go b/pkg/madmin/config-kv-commands.go deleted file mode 100644 index 150943d02..000000000 --- a/pkg/madmin/config-kv-commands.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "net/http" - "net/url" -) - -// DelConfigKV - delete key from server config. -func (adm *AdminClient) DelConfigKV(ctx context.Context, k string) (err error) { - econfigBytes, err := EncryptData(adm.getSecretKey(), []byte(k)) - if err != nil { - return err - } - - reqData := requestData{ - relPath: adminAPIPrefix + "/del-config-kv", - content: econfigBytes, - } - - // Execute DELETE on /minio/admin/v3/del-config-kv to delete config key. - resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -const ( - // ConfigAppliedHeader is the header indicating whether the config was applied without requiring a restart. - ConfigAppliedHeader = "x-minio-config-applied" - - // ConfigAppliedTrue is the value set in header if the config was applied. - ConfigAppliedTrue = "true" -) - -// SetConfigKV - set key value config to server. -func (adm *AdminClient) SetConfigKV(ctx context.Context, kv string) (restart bool, err error) { - econfigBytes, err := EncryptData(adm.getSecretKey(), []byte(kv)) - if err != nil { - return false, err - } - - reqData := requestData{ - relPath: adminAPIPrefix + "/set-config-kv", - content: econfigBytes, - } - - // Execute PUT on /minio/admin/v3/set-config-kv to set config key/value. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return false, err - } - - if resp.StatusCode != http.StatusOK { - return false, httpRespToErrorResponse(resp) - } - - return resp.Header.Get(ConfigAppliedHeader) != ConfigAppliedTrue, nil -} - -// GetConfigKV - returns the key, value of the requested key, incoming data is encrypted. -func (adm *AdminClient) GetConfigKV(ctx context.Context, key string) ([]byte, error) { - v := url.Values{} - v.Set("key", key) - - // Execute GET on /minio/admin/v3/get-config-kv?key={key} to get value of key. - resp, err := adm.executeMethod(ctx, - http.MethodGet, - requestData{ - relPath: adminAPIPrefix + "/get-config-kv", - queryValues: v, - }) - defer closeResponse(resp) - if err != nil { - return nil, err - } - - defer closeResponse(resp) - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - return DecryptData(adm.getSecretKey(), resp.Body) -} diff --git a/pkg/madmin/encrypt.go b/pkg/madmin/encrypt.go deleted file mode 100644 index ea5f656c0..000000000 --- a/pkg/madmin/encrypt.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "bytes" - "crypto/sha256" - "errors" - "io" - "io/ioutil" - - "github.com/minio/argon2" - "github.com/minio/minio/pkg/fips" - "github.com/secure-io/sio-go" - "github.com/secure-io/sio-go/sioutil" - "golang.org/x/crypto/pbkdf2" -) - -// EncryptData encrypts the data with an unique key -// derived from password using the Argon2id PBKDF. -// -// The returned ciphertext data consists of: -// salt | AEAD ID | nonce | encrypted data -// 32 1 8 ~ len(data) -func EncryptData(password string, data []byte) ([]byte, error) { - salt := sioutil.MustRandom(32) - - var ( - id byte - err error - stream *sio.Stream - ) - if fips.Enabled() { - key := pbkdf2.Key([]byte(password), salt, pbkdf2Cost, 32, sha256.New) - stream, err = sio.AES_256_GCM.Stream(key) - if err != nil { - return nil, err - } - id = pbkdf2AESGCM - } else { - key := argon2.IDKey([]byte(password), salt, argon2idTime, argon2idMemory, argon2idThreads, 32) - if sioutil.NativeAES() { - stream, err = sio.AES_256_GCM.Stream(key) - if err != nil { - return nil, err - } - id = argon2idAESGCM - } else { - stream, err = sio.ChaCha20Poly1305.Stream(key) - if err != nil { - return nil, err - } - id = argon2idChaCHa20Poly1305 - } - } - - nonce := sioutil.MustRandom(stream.NonceSize()) - - // ciphertext = salt || AEAD ID | nonce | encrypted data - cLen := int64(len(salt)+1+len(nonce)+len(data)) + stream.Overhead(int64(len(data))) - ciphertext := bytes.NewBuffer(make([]byte, 0, cLen)) // pre-alloc correct length - - // Prefix the ciphertext with salt, AEAD ID and nonce - ciphertext.Write(salt) - ciphertext.WriteByte(id) - ciphertext.Write(nonce) - - w := stream.EncryptWriter(ciphertext, nonce, nil) - if _, err = w.Write(data); err != nil { - return nil, err - } - if err = w.Close(); err != nil { - return nil, err - } - return ciphertext.Bytes(), nil -} - -// ErrMaliciousData indicates that the stream cannot be -// decrypted by provided credentials. -var ErrMaliciousData = sio.NotAuthentic - -// DecryptData decrypts the data with the key derived -// from the salt (part of data) and the password using -// the PBKDF used in EncryptData. DecryptData returns -// the decrypted plaintext on success. -// -// The data must be a valid ciphertext produced by -// EncryptData. Otherwise, the decryption will fail. -func DecryptData(password string, data io.Reader) ([]byte, error) { - var ( - salt [32]byte - id [1]byte - nonce [8]byte // This depends on the AEAD but both used ciphers have the same nonce length. - ) - - if _, err := io.ReadFull(data, salt[:]); err != nil { - return nil, err - } - if _, err := io.ReadFull(data, id[:]); err != nil { - return nil, err - } - if _, err := io.ReadFull(data, nonce[:]); err != nil { - return nil, err - } - - var ( - err error - stream *sio.Stream - ) - switch { - case id[0] == argon2idAESGCM: - key := argon2.IDKey([]byte(password), salt[:], argon2idTime, argon2idMemory, argon2idThreads, 32) - stream, err = sio.AES_256_GCM.Stream(key) - case id[0] == argon2idChaCHa20Poly1305: - key := argon2.IDKey([]byte(password), salt[:], argon2idTime, argon2idMemory, argon2idThreads, 32) - stream, err = sio.ChaCha20Poly1305.Stream(key) - case id[0] == pbkdf2AESGCM: - key := pbkdf2.Key([]byte(password), salt[:], pbkdf2Cost, 32, sha256.New) - stream, err = sio.AES_256_GCM.Stream(key) - default: - err = errors.New("madmin: invalid encryption algorithm ID") - } - if err != nil { - return nil, err - } - - plaintext, err := ioutil.ReadAll(stream.DecryptReader(data, nonce[:], nil)) - if err != nil { - return nil, err - } - return plaintext, err -} - -const ( - argon2idAESGCM = 0x00 - argon2idChaCHa20Poly1305 = 0x01 - pbkdf2AESGCM = 0x02 -) - -const ( - argon2idTime = 1 - argon2idMemory = 64 * 1024 - argon2idThreads = 4 - pbkdf2Cost = 8192 -) diff --git a/pkg/madmin/encrypt_test.go b/pkg/madmin/encrypt_test.go deleted file mode 100644 index 0073a4133..000000000 --- a/pkg/madmin/encrypt_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "bytes" - "encoding/hex" - "fmt" - "testing" -) - -var encryptDataTests = []struct { - Password string - Data []byte -}{ - {Password: "", Data: nil}, - {Password: "", Data: make([]byte, 256)}, - {Password: `xPl.8/rhR"Q_1xLt`, Data: make([]byte, 32)}, - {Password: "m69?yz4W-!k+7p0", Data: make([]byte, 1024*1024)}, - {Password: `7h5oU4$te{;K}fgqlI^]`, Data: make([]byte, 256)}, -} - -func TestEncryptData(t *testing.T) { - for i, test := range encryptDataTests { - i, test := i, test - t.Run(fmt.Sprintf("Test-%d", i), func(t *testing.T) { - ciphertext, err := EncryptData(test.Password, test.Data) - if err != nil { - t.Fatalf("Failed to encrypt data: %v", err) - } - - plaintext, err := DecryptData(test.Password, bytes.NewReader(ciphertext)) - if err != nil { - t.Fatalf("Failed to decrypt data: %v", err) - } - if !bytes.Equal(plaintext, test.Data) { - t.Fatal("Decrypt plaintext does not match origin data") - } - }) - } -} - -var decryptDataTests = []struct { - Password string - Data string -}{ - {Password: "", Data: "828aa81599df0651c0461adb82283e8b89956baee9f6e719947ef9cddc849028001dc9d3ac0938f66b07bacc9751437e1985f8a9763c240e81"}, - - {Password: "", Data: "1793c71df6647860437134073c15688cbb15961dc0758c7ee1225e66e79c724c00d790dba9c671eae89da2c736d858286ac9bd027abacc6443" + - "0375cd41b63b67c070c7fba475a8dd66ae65ba905176c48cbe6f734fc74df87343d8ccff54bada4aeb0a04bd021633ebe6c4768e23f5dea142" + - "561d4fe3f90ed59d13dc5fb3a585dadec1742325291b9c81692bdd3420b2428127f8195e0ecd9a1c9237712ed67af7339fbbf7ff3ee1c516e1" + - "f81e69d933e057b30997e7274a2c9698e07c39f0e8d6818858f34c8191871b5a52bea9061806bd029024bfc1d9c1f230904968d6c9e10fddcb" + - "c006ba97356ff243570fd96df07dd6894e215a6b24c4ed730369519289ebd877aff6ccbd2265985e4ab1a2b7930bab9cfb767b97348a639ddf" + - "8db81bf5151da7e8f3d9638a1b86eb1dd78cc6a526f10a414c78638f"}, - - {Password: `xPl.8/rhR"Q_1xLt`, Data: "b5c016e93b84b473fc8a37af94936563630c36d6df1841d23a86ee51ca161f9e00ac19116b32f643ff6a56a212b265d8c56" + - "195bb0d12ce199e13dfdc5272f80c1564da2c6fc2fa18da91d8062de02af5cdafea491c6f3cae1f"}, - - {Password: `7h5oU4$te{;K}fgqlI^]`, Data: "c58edf7cfd557b6b655de6f48b1a3049d8d049dadb3a7bfa9ac9ccbb5baf37ec00f83086a26f43b7d6bc9075ad0" + - "38bf5741f118d502ebe94165e4072ba7f98535d6b1e3b6ae67a98115d146d9b4d90e4df4ae82df9cfa17ed7cd42" + - "465181559f7ddf09c98beec521bb4478e0cb73c4e0827af8688ff4e7a07327a10d5a180035e6ddb16d974a85257" + - "981cd9e0360a20f7b4d653190267dfb241148f018ae180568042e864b9e1b5bc05425a3abc2b0324f50c72d5679" + - "8f924405dfc0f8523f4bb564ed65af8e1b1c82a7a0640552ecf81985d95d0993d99172592ddc1393dfa63e8f0b3" + - "d744b2cc4b73384ca4693f0c1aec0e9b00e85f2937e891105d67da8f59c14ca96608e0425c42f9c1e7c2a8b3413" + - "e1381784f9cfe01de7c47cea1f8d7a7d88f5d4aca783cf55332b47f957a6b9a65269d7eb606b877b"}, -} - -func TestDecryptData(t *testing.T) { - for i, test := range decryptDataTests { - i, test := i, test - t.Run(fmt.Sprintf("Test-%d", i), func(t *testing.T) { - ciphertext, err := hex.DecodeString(test.Data) - if err != nil { - t.Fatalf("Failed to decode ciphertext data: %v", err) - } - _, err = DecryptData(test.Password, bytes.NewReader(ciphertext)) - if err != nil { - t.Fatalf("Failed to decrypt data: %v", err) - } - }) - } -} diff --git a/pkg/madmin/examples/accounting-info.go b/pkg/madmin/examples/accounting-info.go deleted file mode 100644 index 9b86b2cd0..000000000 --- a/pkg/madmin/examples/accounting-info.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - accountInfo, err := madmClnt.AccountInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - - log.Println(accountInfo) -} diff --git a/pkg/madmin/examples/add-user-and-policy.go b/pkg/madmin/examples/add-user-and-policy.go deleted file mode 100644 index fd5af3abe..000000000 --- a/pkg/madmin/examples/add-user-and-policy.go +++ /dev/null @@ -1,69 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/bucket/policy" - "github.com/minio/minio/pkg/bucket/policy/condition" - iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - if err = madmClnt.AddUser(context.Background(), "newuser", "newstrongpassword"); err != nil { - log.Fatalln(err) - } - - // Create policy - p := iampolicy.Policy{ - Version: iampolicy.DefaultVersion, - Statements: []iampolicy.Statement{ - iampolicy.NewStatement( - policy.Allow, - iampolicy.NewActionSet(iampolicy.GetObjectAction), - iampolicy.NewResourceSet(iampolicy.NewResource("testbucket/*", "")), - condition.NewFunctions(), - )}, - } - - if err = madmClnt.AddCannedPolicy(context.Background(), "get-only", &p); err != nil { - log.Fatalln(err) - } - - if err = madmClnt.SetUserPolicy(context.Background(), "newuser", "get-only"); err != nil { - log.Fatalln(err) - } -} diff --git a/pkg/madmin/examples/bucket-bandwidth.go b/pkg/madmin/examples/bucket-bandwidth.go deleted file mode 100644 index 4a070b755..000000000 --- a/pkg/madmin/examples/bucket-bandwidth.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "fmt" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madminClient, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - ctx := context.Background() - reportCh := madminClient.GetBucketBandwidth(ctx) - - for i := 0; i < 10; i++ { - report := <-reportCh - fmt.Printf("Report: %+v\n", report) - } - reportCh = madminClient.GetBucketBandwidth(ctx, "sourceBucket", "sourceBucket2") - for i := 0; i < 10; i++ { - report := <-reportCh - fmt.Printf("Report: %+v\n", report) - } -} diff --git a/pkg/madmin/examples/bucket-quota.go b/pkg/madmin/examples/bucket-quota.go deleted file mode 100644 index aec3ef136..000000000 --- a/pkg/madmin/examples/bucket-quota.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "fmt" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - var kiB int64 = 1 << 10 - ctx := context.Background() - // set bucket quota config - if err := madmClnt.SetBucketQuota(ctx, "bucket-name", 64*kiB, HardQuota); err != nil { - log.Fatalln(err) - } - // gets bucket quota config - quotaCfg, err := madmClnt.GetBucketQuota(ctx, "bucket-name") - if err != nil { - log.Fatalln(err) - } - fmt.Println(quotaCfg) - // remove bucket quota config - if err := madmClnt.RemoveBucketQuota(ctx, "bucket-name"); err != nil { - log.Fatalln(err) - } -} diff --git a/pkg/madmin/examples/bucket-target.go b/pkg/madmin/examples/bucket-target.go deleted file mode 100644 index a52a580d7..000000000 --- a/pkg/madmin/examples/bucket-target.go +++ /dev/null @@ -1,80 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "fmt" - "log" - - "github.com/minio/minio/pkg/auth" - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - ctx := context.Background() - creds, err := auth.CreateCredentials("access-key", "secret-key") - if err != nil { - log.Fatalln(err) - } - target := madmin.BucketTarget{Endpoint: "site2:9000", Credentials: creds, TargetBucket: "destbucket", IsSSL: false, Type: madmin.ReplicationArn, BandwidthLimit: 2 * 1024 * 1024} - // Set bucket target - arn, err := madmClnt.SetBucketTarget(ctx, "srcbucket", &target) - if err != nil { - log.Fatalln(err) - } - fmt.Println("replication target ARN is:", arn) - // List all bucket target(s) - target, err = madmClnt.ListBucketTargets(ctx, "srcbucket", "") - if err != nil { - log.Fatalln(err) - } - // Get bucket target for arn type "replica" - target, err = madmClnt.ListBucketTargets(ctx, "srcbucket", "replica") - if err != nil { - log.Fatalln(err) - } - // update credentials for target - creds, err := auth.CreateCredentials("access-key2", "secret-key2") - if err != nil { - log.Fatalln(err) - } - target := madmin.BucketTarget{Endpoint: "site2:9000", Credentials: creds, SourceBucket: "srcbucket", TargetBucket: "destbucket", IsSSL: false, Arn: "arn:minio:ilm:us-east-1:3cbe15b8-82b9-44bc-a737-db9051ab359a:srcbucket"} - // update credentials on bucket target - if _, err := madmClnt.UpdateBucketTarget(ctx, &target); err != nil { - log.Fatalln(err) - } - - // Remove bucket target - arn := "arn:minio:replica::ac66b2cf-dd8f-4e7e-a882-9a64132f0d59:dest" - if err := madmClnt.RemoveBucketTarget(ctx, "srcbucket", arn); err != nil { - log.Fatalln(err) - } - -} diff --git a/pkg/madmin/examples/data-usage-info.go b/pkg/madmin/examples/data-usage-info.go deleted file mode 100644 index 2c8c7f7e5..000000000 --- a/pkg/madmin/examples/data-usage-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - dataUsageInfo, err := madmClnt.DataUsageInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Println(dataUsageInfo) -} diff --git a/pkg/madmin/examples/heal-bucket.go b/pkg/madmin/examples/heal-bucket.go deleted file mode 100644 index b803e2362..000000000 --- a/pkg/madmin/examples/heal-bucket.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - // Heal bucket mybucket - dry run - isDryRun := true - err = madmClnt.HealBucket(context.Background(), "mybucket", isDryRun) - if err != nil { - log.Fatalln(err) - - } - - // Heal bucket mybucket - for real this time. - isDryRun := false - err = madmClnt.HealBucket(context.Background(), "mybucket", isDryRun) - if err != nil { - log.Fatalln(err) - } - - log.Println("successfully healed mybucket") -} diff --git a/pkg/madmin/examples/heal-format.go b/pkg/madmin/examples/heal-format.go deleted file mode 100644 index d40b2c9ba..000000000 --- a/pkg/madmin/examples/heal-format.go +++ /dev/null @@ -1,58 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - // Attempt healing format in dry-run mode. - isDryRun := true - err = madmClnt.HealFormat(context.Background(), isDryRun) - if err != nil { - log.Fatalln(err) - } - - // Perform actual healing of format. - isDryRun = false - err = madmClnt.HealFormat(context.Background(), isDryRun) - if err != nil { - log.Fatalln(err) - } - - log.Println("successfully healed storage format on available disks.") -} diff --git a/pkg/madmin/examples/heal-object.go b/pkg/madmin/examples/heal-object.go deleted file mode 100644 index 013a121fb..000000000 --- a/pkg/madmin/examples/heal-object.go +++ /dev/null @@ -1,58 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - // Heal object mybucket/myobject - dry run. - isDryRun := true - _, err = madmClnt.HealObject(context.Background(), "mybucket", "myobject", isDryRun) - if err != nil { - log.Fatalln(err) - } - - // Heal object mybucket/myobject - this time for real. - isDryRun = false - healResult, err := madmClnt.HealObject(context.Background(), "mybucket", "myobject", isDryRun) - if err != nil { - log.Fatalln(err) - } - - log.Printf("heal result: %#v\n", healResult) -} diff --git a/pkg/madmin/examples/heal-status.go b/pkg/madmin/examples/heal-status.go deleted file mode 100644 index 50e9672d7..000000000 --- a/pkg/madmin/examples/heal-status.go +++ /dev/null @@ -1,48 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "encoding/json" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - healStatusResult, err := madmClnt.BackgroundHealStatus(context.Background()) - if err != nil { - log.Fatalln(err) - } - js, _ := json.MarshalIndent(healStatusResult, "", " ") - - log.Printf("Heal status result: %s\n", string(js)) -} diff --git a/pkg/madmin/examples/kms-status.go b/pkg/madmin/examples/kms-status.go deleted file mode 100644 index f1a246770..000000000 --- a/pkg/madmin/examples/kms-status.go +++ /dev/null @@ -1,61 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - status, err := madmClnt.GetKeyStatus(context.Background(), "") // empty string refers to the default master key - if err != nil { - log.Fatalln(err) - } - - log.Printf("Key: %s\n", status.KeyID) - if status.EncryptionErr == "" { - log.Println("\t • Encryption ✔") - } else { - log.Printf("\t • Encryption failed: %s\n", status.EncryptionErr) - } - if status.UpdateErr == "" { - log.Println("\t • Re-wrap ✔") - } else { - log.Printf("\t • Re-wrap failed: %s\n", status.UpdateErr) - } - if status.DecryptionErr == "" { - log.Println("\t • Decryption ✔") - } else { - log.Printf("\t • Decryption failed: %s\n", status.DecryptionErr) - } -} diff --git a/pkg/madmin/examples/lock-clear.go b/pkg/madmin/examples/lock-clear.go deleted file mode 100644 index 50a70ce02..000000000 --- a/pkg/madmin/examples/lock-clear.go +++ /dev/null @@ -1,48 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - "time" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - // Clear locks held on mybucket/myprefix for longer than 30s. - olderThan := time.Duration(30 * time.Second) - locksCleared, err := madmClnt.ClearLocks(context.Background(), "mybucket", "myprefix", olderThan) - if err != nil { - log.Fatalln(err) - } - log.Println(locksCleared) -} diff --git a/pkg/madmin/examples/profiling.go b/pkg/madmin/examples/profiling.go deleted file mode 100644 index b4909dd7e..000000000 --- a/pkg/madmin/examples/profiling.go +++ /dev/null @@ -1,90 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "io" - "log" - "os" - "time" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - profiler := madmin.ProfilerCPU - log.Println("Starting " + profiler + " profiling..") - - startResults, err := madmClnt.StartProfiling(context.Background(), profiler) - if err != nil { - log.Fatalln(err) - } - - for _, result := range startResults { - if !result.Success { - log.Printf("Unable to start profiling on node `%s`, reason = `%s`\n", result.NodeName, result.Error) - continue - } - log.Printf("Profiling successfully started on node `%s`\n", result.NodeName) - } - - sleep := time.Duration(10) - time.Sleep(time.Second * sleep) - - log.Println("Stopping profiling..") - - profilingData, err := madmClnt.DownloadProfilingData(context.Background()) - if err != nil { - log.Fatalln(err) - } - - profilingFile, err := os.Create("/tmp/profiling-" + string(profiler) + ".zip") - if err != nil { - log.Fatal(err) - } - - if _, err := io.Copy(profilingFile, profilingData); err != nil { - log.Fatal(err) - } - - if err := profilingFile.Close(); err != nil { - log.Fatal(err) - } - - if err := profilingData.Close(); err != nil { - log.Fatal(err) - } - - log.Println("Profiling files " + profilingFile.Name() + " successfully downloaded.") -} diff --git a/pkg/madmin/examples/server-info.go b/pkg/madmin/examples/server-info.go deleted file mode 100644 index b14487efe..000000000 --- a/pkg/madmin/examples/server-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - st, err := madmClnt.ServerInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Printf("%+v\n", st) -} diff --git a/pkg/madmin/examples/service-accounts.go b/pkg/madmin/examples/service-accounts.go deleted file mode 100644 index 5c13e9e25..000000000 --- a/pkg/madmin/examples/service-accounts.go +++ /dev/null @@ -1,77 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "fmt" - "log" - - "github.com/minio/minio/pkg/bucket/policy" - "github.com/minio/minio/pkg/bucket/policy/condition" - iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - p := iampolicy.Policy{ - Version: iampolicy.DefaultVersion, - Statements: []iampolicy.Statement{ - iampolicy.NewStatement( - policy.Allow, - iampolicy.NewActionSet(iampolicy.GetObjectAction), - iampolicy.NewResourceSet(iampolicy.NewResource("testbucket/*", "")), - condition.NewFunctions(), - )}, - } - - // Create a new service account - creds, err := madmClnt.AddServiceAccount(context.Background(), madmin.AddServiceAccountReq{Policy: &p}) - if err != nil { - log.Fatalln(err) - } - fmt.Println(creds) - - // List all services accounts - list, err := madmClnt.ListServiceAccounts(context.Background(), "") - if err != nil { - log.Fatalln(err) - } - fmt.Println(list) - - // Delete a service account - err = madmClnt.DeleteServiceAccount(context.Background(), list.Accounts[0]) - if err != nil { - log.Fatalln(err) - } -} diff --git a/pkg/madmin/examples/service-restart.go b/pkg/madmin/examples/service-restart.go deleted file mode 100644 index daac42a4a..000000000 --- a/pkg/madmin/examples/service-restart.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - err = madmClnt.ServiceRestart(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Println("Success") -} diff --git a/pkg/madmin/examples/service-trace.go b/pkg/madmin/examples/service-trace.go deleted file mode 100644 index bf1b0487d..000000000 --- a/pkg/madmin/examples/service-trace.go +++ /dev/null @@ -1,55 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "fmt" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - // Start listening on all http trace activity from all servers in the minio cluster. - traceCh := madmClnt.ServiceTrace(context.Background(), madmin.ServiceTraceOpts{ - S3: true, - Internal: true, - Storage: true, - OS: true, - Threshold: 0, - }) - for traceInfo := range traceCh { - if traceInfo.Err != nil { - fmt.Println(traceInfo.Err) - } - fmt.Println(traceInfo) - } -} diff --git a/pkg/madmin/examples/storage-info.go b/pkg/madmin/examples/storage-info.go deleted file mode 100644 index 7499a1fdc..000000000 --- a/pkg/madmin/examples/storage-info.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - st, err := madmClnt.StorageInfo(context.Background()) - if err != nil { - log.Fatalln(err) - } - log.Printf("%+v\n", st) -} diff --git a/pkg/madmin/examples/top-locks.go b/pkg/madmin/examples/top-locks.go deleted file mode 100644 index d7065fed6..000000000 --- a/pkg/madmin/examples/top-locks.go +++ /dev/null @@ -1,51 +0,0 @@ -// +build ignore - -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package main - -import ( - "context" - "encoding/json" - "log" - - "github.com/minio/minio/pkg/madmin" -) - -func main() { - // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY are - // dummy values, please replace them with original values. - - // API requests are secure (HTTPS) if secure=true and insecure (HTTP) otherwise. - // New returns an MinIO Admin client object. - madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true) - if err != nil { - log.Fatalln(err) - } - - locks, err := madmClnt.TopLocks(context.Background()) - if err != nil { - log.Fatalf("failed due to: %v", err) - } - - out, err := json.Marshal(locks) - if err != nil { - log.Fatalf("Marshal failed due to: %v", err) - } - log.Println("Top Locks received successfully: ", string(out)) -} diff --git a/pkg/madmin/group-commands.go b/pkg/madmin/group-commands.go deleted file mode 100644 index ec223e66c..000000000 --- a/pkg/madmin/group-commands.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "io/ioutil" - "net/http" - "net/url" -) - -// GroupAddRemove is type for adding/removing members to/from a group. -type GroupAddRemove struct { - Group string `json:"group"` - Members []string `json:"members"` - IsRemove bool `json:"isRemove"` -} - -// UpdateGroupMembers - adds/removes users to/from a group. Server -// creates the group as needed. Group is removed if remove request is -// made on empty group. -func (adm *AdminClient) UpdateGroupMembers(ctx context.Context, g GroupAddRemove) error { - data, err := json.Marshal(g) - if err != nil { - return err - } - - reqData := requestData{ - relPath: adminAPIPrefix + "/update-group-members", - content: data, - } - - // Execute PUT on /minio/admin/v3/update-group-members - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// GroupDesc is a type that holds group info along with the policy -// attached to it. -type GroupDesc struct { - Name string `json:"name"` - Status string `json:"status"` - Members []string `json:"members"` - Policy string `json:"policy"` -} - -// GetGroupDescription - fetches information on a group. -func (adm *AdminClient) GetGroupDescription(ctx context.Context, group string) (*GroupDesc, error) { - v := url.Values{} - v.Set("group", group) - reqData := requestData{ - relPath: adminAPIPrefix + "/group", - queryValues: v, - } - - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - gd := GroupDesc{} - if err = json.Unmarshal(data, &gd); err != nil { - return nil, err - } - - return &gd, nil -} - -// ListGroups - lists all groups names present on the server. -func (adm *AdminClient) ListGroups(ctx context.Context) ([]string, error) { - reqData := requestData{ - relPath: adminAPIPrefix + "/groups", - } - - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - groups := []string{} - if err = json.Unmarshal(data, &groups); err != nil { - return nil, err - } - - return groups, nil -} - -// GroupStatus - group status. -type GroupStatus string - -// GroupStatus values. -const ( - GroupEnabled GroupStatus = "enabled" - GroupDisabled GroupStatus = "disabled" -) - -// SetGroupStatus - sets the status of a group. -func (adm *AdminClient) SetGroupStatus(ctx context.Context, group string, status GroupStatus) error { - v := url.Values{} - v.Set("group", group) - v.Set("status", string(status)) - - reqData := requestData{ - relPath: adminAPIPrefix + "/set-group-status", - queryValues: v, - } - - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} diff --git a/pkg/madmin/heal-commands.go b/pkg/madmin/heal-commands.go deleted file mode 100644 index 5945dbd4e..000000000 --- a/pkg/madmin/heal-commands.go +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "sort" - "time" -) - -// HealScanMode represents the type of healing scan -type HealScanMode int - -const ( - // HealUnknownScan default is unknown - HealUnknownScan HealScanMode = iota - - // HealNormalScan checks if parts are present and not outdated - HealNormalScan - - // HealDeepScan checks for parts bitrot checksums - HealDeepScan -) - -// HealOpts - collection of options for a heal sequence -type HealOpts struct { - Recursive bool `json:"recursive"` - DryRun bool `json:"dryRun"` - Remove bool `json:"remove"` - Recreate bool `json:"recreate"` // only used when bucket needs to be healed - ScanMode HealScanMode `json:"scanMode"` - NoLock bool `json:"nolock"` -} - -// Equal returns true if no is same as o. -func (o HealOpts) Equal(no HealOpts) bool { - if o.Recursive != no.Recursive { - return false - } - if o.DryRun != no.DryRun { - return false - } - if o.Remove != no.Remove { - return false - } - return o.ScanMode == no.ScanMode -} - -// HealStartSuccess - holds information about a successfully started -// heal operation -type HealStartSuccess struct { - ClientToken string `json:"clientToken"` - ClientAddress string `json:"clientAddress"` - StartTime time.Time `json:"startTime"` -} - -// HealStopSuccess - holds information about a successfully stopped -// heal operation. -type HealStopSuccess HealStartSuccess - -// HealTaskStatus - status struct for a heal task -type HealTaskStatus struct { - Summary string `json:"summary"` - FailureDetail string `json:"detail"` - StartTime time.Time `json:"startTime"` - HealSettings HealOpts `json:"settings"` - - Items []HealResultItem `json:"items,omitempty"` -} - -// HealItemType - specify the type of heal operation in a healing -// result -type HealItemType string - -// HealItemType constants -const ( - HealItemMetadata HealItemType = "metadata" - HealItemBucket = "bucket" - HealItemBucketMetadata = "bucket-metadata" - HealItemObject = "object" -) - -// Drive state constants -const ( - DriveStateOk string = "ok" - DriveStateOffline = "offline" - DriveStateCorrupt = "corrupt" - DriveStateMissing = "missing" - DriveStatePermission = "permission-denied" - DriveStateFaulty = "faulty" - DriveStateUnknown = "unknown" - DriveStateUnformatted = "unformatted" // only returned by disk -) - -// HealDriveInfo - struct for an individual drive info item. -type HealDriveInfo struct { - UUID string `json:"uuid"` - Endpoint string `json:"endpoint"` - State string `json:"state"` -} - -// HealResultItem - struct for an individual heal result item -type HealResultItem struct { - ResultIndex int64 `json:"resultId"` - Type HealItemType `json:"type"` - Bucket string `json:"bucket"` - Object string `json:"object"` - VersionID string `json:"versionId"` - Detail string `json:"detail"` - ParityBlocks int `json:"parityBlocks,omitempty"` - DataBlocks int `json:"dataBlocks,omitempty"` - DiskCount int `json:"diskCount"` - SetCount int `json:"setCount"` - // below slices are from drive info. - Before struct { - Drives []HealDriveInfo `json:"drives"` - } `json:"before"` - After struct { - Drives []HealDriveInfo `json:"drives"` - } `json:"after"` - ObjectSize int64 `json:"objectSize"` -} - -// GetMissingCounts - returns the number of missing disks before -// and after heal -func (hri *HealResultItem) GetMissingCounts() (b, a int) { - if hri == nil { - return - } - for _, v := range hri.Before.Drives { - if v.State == DriveStateMissing { - b++ - } - } - for _, v := range hri.After.Drives { - if v.State == DriveStateMissing { - a++ - } - } - return -} - -// GetOfflineCounts - returns the number of offline disks before -// and after heal -func (hri *HealResultItem) GetOfflineCounts() (b, a int) { - if hri == nil { - return - } - for _, v := range hri.Before.Drives { - if v.State == DriveStateOffline { - b++ - } - } - for _, v := range hri.After.Drives { - if v.State == DriveStateOffline { - a++ - } - } - return -} - -// GetCorruptedCounts - returns the number of corrupted disks before -// and after heal -func (hri *HealResultItem) GetCorruptedCounts() (b, a int) { - if hri == nil { - return - } - for _, v := range hri.Before.Drives { - if v.State == DriveStateCorrupt { - b++ - } - } - for _, v := range hri.After.Drives { - if v.State == DriveStateCorrupt { - a++ - } - } - return -} - -// GetOnlineCounts - returns the number of online disks before -// and after heal -func (hri *HealResultItem) GetOnlineCounts() (b, a int) { - if hri == nil { - return - } - for _, v := range hri.Before.Drives { - if v.State == DriveStateOk { - b++ - } - } - for _, v := range hri.After.Drives { - if v.State == DriveStateOk { - a++ - } - } - return -} - -// Heal - API endpoint to start heal and to fetch status -// forceStart and forceStop are mutually exclusive, you can either -// set one of them to 'true'. If both are set 'forceStart' will be -// honored. -func (adm *AdminClient) Heal(ctx context.Context, bucket, prefix string, - healOpts HealOpts, clientToken string, forceStart, forceStop bool) ( - healStart HealStartSuccess, healTaskStatus HealTaskStatus, err error) { - - if forceStart && forceStop { - return healStart, healTaskStatus, ErrInvalidArgument("forceStart and forceStop set to true is not allowed") - } - - body, err := json.Marshal(healOpts) - if err != nil { - return healStart, healTaskStatus, err - } - - path := fmt.Sprintf(adminAPIPrefix+"/heal/%s", bucket) - if bucket != "" && prefix != "" { - path += "/" + prefix - } - - // execute POST request to heal api - queryVals := make(url.Values) - if clientToken != "" { - queryVals.Set("clientToken", clientToken) - body = []byte{} - } - - // Anyone can be set, either force start or forceStop. - if forceStart { - queryVals.Set("forceStart", "true") - } else if forceStop { - queryVals.Set("forceStop", "true") - } - - resp, err := adm.executeMethod(ctx, - http.MethodPost, requestData{ - relPath: path, - content: body, - queryValues: queryVals, - }) - defer closeResponse(resp) - if err != nil { - return healStart, healTaskStatus, err - } - - if resp.StatusCode != http.StatusOK { - return healStart, healTaskStatus, httpRespToErrorResponse(resp) - } - - respBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return healStart, healTaskStatus, err - } - - // Was it a status request? - if clientToken == "" { - // As a special operation forceStop would return a - // similar struct as healStart will have the - // heal sequence information about the heal which - // was stopped. - err = json.Unmarshal(respBytes, &healStart) - } else { - err = json.Unmarshal(respBytes, &healTaskStatus) - } - if err != nil { - // May be the server responded with error after success - // message, handle it separately here. - var errResp ErrorResponse - err = json.Unmarshal(respBytes, &errResp) - if err != nil { - // Unknown structure return error anyways. - return healStart, healTaskStatus, err - } - return healStart, healTaskStatus, errResp - } - return healStart, healTaskStatus, nil -} - -// BgHealState represents the status of the background heal -type BgHealState struct { - ScannedItemsCount int64 - - HealDisks []string - - // SetStatus contains information for each set. - Sets []SetStatus `json:"sets"` -} - -// SetStatus contains information about the heal status of a set. -type SetStatus struct { - ID string `json:"id"` - PoolIndex int `json:"pool_index"` - SetIndex int `json:"set_index"` - HealStatus string `json:"heal_status"` - HealPriority string `json:"heal_priority"` - Disks []Disk `json:"disks"` -} - -// HealingDisk contains information about -type HealingDisk struct { - // Copied from cmd/background-newdisks-heal-ops.go - // When adding new field, update (*healingTracker).toHealingDisk - - ID string `json:"id"` - PoolIndex int `json:"pool_index"` - SetIndex int `json:"set_index"` - DiskIndex int `json:"disk_index"` - Endpoint string `json:"endpoint"` - Path string `json:"path"` - Started time.Time `json:"started"` - LastUpdate time.Time `json:"last_update"` - ObjectsHealed uint64 `json:"objects_healed"` - ObjectsFailed uint64 `json:"objects_failed"` - BytesDone uint64 `json:"bytes_done"` - BytesFailed uint64 `json:"bytes_failed"` - - // Last object scanned. - Bucket string `json:"current_bucket"` - Object string `json:"current_object"` - - // Filled on startup/restarts. - QueuedBuckets []string `json:"queued_buckets"` - - // Filled during heal. - HealedBuckets []string `json:"healed_buckets"` - // future add more tracking capabilities -} - -// Merge others into b. -func (b *BgHealState) Merge(others ...BgHealState) { - for _, other := range others { - b.ScannedItemsCount += other.ScannedItemsCount - if len(b.Sets) == 0 { - b.Sets = make([]SetStatus, len(other.Sets)) - copy(b.Sets, other.Sets) - continue - } - - // Add disk if not present. - // If present select the one with latest lastupdate. - addSet := func(set SetStatus) { - for eSetIdx, existing := range b.Sets { - if existing.ID != set.ID { - continue - } - if len(existing.Disks) < len(set.Disks) { - b.Sets[eSetIdx].Disks = set.Disks - } - if len(existing.Disks) < len(set.Disks) { - return - } - for i, disk := range set.Disks { - // Disks should be the same. - if disk.HealInfo != nil { - existing.Disks[i].HealInfo = disk.HealInfo - } - } - return - } - b.Sets = append(b.Sets, set) - } - for _, disk := range other.Sets { - addSet(disk) - } - } - sort.Slice(b.Sets, func(i, j int) bool { - if b.Sets[i].PoolIndex != b.Sets[j].PoolIndex { - return b.Sets[i].PoolIndex < b.Sets[j].PoolIndex - } - return b.Sets[i].SetIndex < b.Sets[j].SetIndex - }) -} - -// BackgroundHealStatus returns the background heal status of the -// current server or cluster. -func (adm *AdminClient) BackgroundHealStatus(ctx context.Context) (BgHealState, error) { - // Execute POST request to background heal status api - resp, err := adm.executeMethod(ctx, - http.MethodPost, - requestData{relPath: adminAPIPrefix + "/background-heal/status"}) - if err != nil { - return BgHealState{}, err - } - defer closeResponse(resp) - - if resp.StatusCode != http.StatusOK { - return BgHealState{}, httpRespToErrorResponse(resp) - } - - respBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return BgHealState{}, err - } - - var healState BgHealState - - err = json.Unmarshal(respBytes, &healState) - if err != nil { - return BgHealState{}, err - } - return healState, nil -} diff --git a/pkg/madmin/heal-commands_test.go b/pkg/madmin/heal-commands_test.go deleted file mode 100644 index 5b598b26b..000000000 --- a/pkg/madmin/heal-commands_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "testing" -) - -// Tests heal drives missing and offline counts. -func TestHealDriveCounts(t *testing.T) { - rs := HealResultItem{} - rs.Before.Drives = make([]HealDriveInfo, 20) - rs.After.Drives = make([]HealDriveInfo, 20) - for i := range rs.Before.Drives { - if i < 4 { - rs.Before.Drives[i] = HealDriveInfo{State: DriveStateMissing} - rs.After.Drives[i] = HealDriveInfo{State: DriveStateMissing} - } else if i > 4 && i < 15 { - rs.Before.Drives[i] = HealDriveInfo{State: DriveStateOffline} - rs.After.Drives[i] = HealDriveInfo{State: DriveStateOffline} - } else if i > 15 { - rs.Before.Drives[i] = HealDriveInfo{State: DriveStateCorrupt} - rs.After.Drives[i] = HealDriveInfo{State: DriveStateCorrupt} - } else { - rs.Before.Drives[i] = HealDriveInfo{State: DriveStateOk} - rs.After.Drives[i] = HealDriveInfo{State: DriveStateOk} - } - } - - i, j := rs.GetOnlineCounts() - if i > 2 { - t.Errorf("Expected '2', got %d before online disks", i) - } - if j > 2 { - t.Errorf("Expected '2', got %d after online disks", j) - } - i, j = rs.GetOfflineCounts() - if i > 10 { - t.Errorf("Expected '10', got %d before offline disks", i) - } - if j > 10 { - t.Errorf("Expected '10', got %d after offline disks", j) - } - i, j = rs.GetCorruptedCounts() - if i > 4 { - t.Errorf("Expected '4', got %d before corrupted disks", i) - } - if j > 4 { - t.Errorf("Expected '4', got %d after corrupted disks", j) - } - i, j = rs.GetMissingCounts() - if i > 4 { - t.Errorf("Expected '4', got %d before missing disks", i) - } - if j > 4 { - t.Errorf("Expected '4', got %d after missing disks", i) - } -} diff --git a/pkg/madmin/health.go b/pkg/madmin/health.go deleted file mode 100644 index e228028ba..000000000 --- a/pkg/madmin/health.go +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "io" - "net/http" - "net/url" - "time" - - "github.com/minio/minio/pkg/disk" - "github.com/minio/minio/pkg/net" - - smart "github.com/minio/minio/pkg/smart" - "github.com/shirou/gopsutil/v3/cpu" - diskhw "github.com/shirou/gopsutil/v3/disk" - "github.com/shirou/gopsutil/v3/host" - "github.com/shirou/gopsutil/v3/mem" - "github.com/shirou/gopsutil/v3/process" -) - -// HealthInfo - MinIO cluster's health Info -type HealthInfo struct { - TimeStamp time.Time `json:"timestamp,omitempty"` - Error string `json:"error,omitempty"` - Perf PerfInfo `json:"perf,omitempty"` - Minio MinioHealthInfo `json:"minio,omitempty"` - Sys SysHealthInfo `json:"sys,omitempty"` -} - -// SysHealthInfo - Includes hardware and system information of the MinIO cluster -type SysHealthInfo struct { - CPUInfo []ServerCPUInfo `json:"cpus,omitempty"` - DiskHwInfo []ServerDiskHwInfo `json:"drives,omitempty"` - OsInfo []ServerOsInfo `json:"osinfos,omitempty"` - MemInfo []ServerMemInfo `json:"meminfos,omitempty"` - ProcInfo []ServerProcInfo `json:"procinfos,omitempty"` - Error string `json:"error,omitempty"` -} - -// ServerProcInfo - Includes host process lvl information -type ServerProcInfo struct { - Addr string `json:"addr"` - Processes []SysProcess `json:"processes,omitempty"` - Error string `json:"error,omitempty"` -} - -// SysProcess - Includes process lvl information about a single process -type SysProcess struct { - Pid int32 `json:"pid"` - Background bool `json:"background,omitempty"` - CPUPercent float64 `json:"cpupercent,omitempty"` - Children []int32 `json:"children,omitempty"` - CmdLine string `json:"cmd,omitempty"` - ConnectionCount int `json:"connection_count,omitempty"` - CreateTime int64 `json:"createtime,omitempty"` - Cwd string `json:"cwd,omitempty"` - Exe string `json:"exe,omitempty"` - Gids []int32 `json:"gids,omitempty"` - IOCounters *process.IOCountersStat `json:"iocounters,omitempty"` - IsRunning bool `json:"isrunning,omitempty"` - MemInfo *process.MemoryInfoStat `json:"meminfo,omitempty"` - MemMaps *[]process.MemoryMapsStat `json:"memmaps,omitempty"` - MemPercent float32 `json:"mempercent,omitempty"` - Name string `json:"name,omitempty"` - Nice int32 `json:"nice,omitempty"` - NumCtxSwitches *process.NumCtxSwitchesStat `json:"numctxswitches,omitempty"` - NumFds int32 `json:"numfds,omitempty"` - NumThreads int32 `json:"numthreads,omitempty"` - PageFaults *process.PageFaultsStat `json:"pagefaults,omitempty"` - Parent int32 `json:"parent,omitempty"` - Ppid int32 `json:"ppid,omitempty"` - Status string `json:"status,omitempty"` - Tgid int32 `json:"tgid,omitempty"` - Times *cpu.TimesStat `json:"cputimes,omitempty"` - Uids []int32 `json:"uids,omitempty"` - Username string `json:"username,omitempty"` -} - -// ServerMemInfo - Includes host virtual and swap mem information -type ServerMemInfo struct { - Addr string `json:"addr"` - SwapMem *mem.SwapMemoryStat `json:"swap,omitempty"` - VirtualMem *mem.VirtualMemoryStat `json:"virtualmem,omitempty"` - Error string `json:"error,omitempty"` -} - -// ServerOsInfo - Includes host os information -type ServerOsInfo struct { - Addr string `json:"addr"` - Info *host.InfoStat `json:"info,omitempty"` - Sensors []host.TemperatureStat `json:"sensors,omitempty"` - Users []host.UserStat `json:"users,omitempty"` - Error string `json:"error,omitempty"` -} - -// ServerCPUInfo - Includes cpu and timer stats of each node of the MinIO cluster -type ServerCPUInfo struct { - Addr string `json:"addr"` - CPUStat []cpu.InfoStat `json:"cpu,omitempty"` - TimeStat []cpu.TimesStat `json:"time,omitempty"` - Error string `json:"error,omitempty"` -} - -// MinioHealthInfo - Includes MinIO confifuration information -type MinioHealthInfo struct { - Info InfoMessage `json:"info,omitempty"` - Config interface{} `json:"config,omitempty"` - Error string `json:"error,omitempty"` -} - -// ServerDiskHwInfo - Includes usage counters, disk counters and partitions -type ServerDiskHwInfo struct { - Addr string `json:"addr"` - Usage []*diskhw.UsageStat `json:"usages,omitempty"` - Partitions []PartitionStat `json:"partitions,omitempty"` - Counters map[string]diskhw.IOCountersStat `json:"counters,omitempty"` - Error string `json:"error,omitempty"` -} - -// PartitionStat - includes data from both shirou/psutil.diskHw.PartitionStat as well as SMART data -type PartitionStat struct { - Device string `json:"device"` - Mountpoint string `json:"mountpoint,omitempty"` - Fstype string `json:"fstype,omitempty"` - Opts string `json:"opts,omitempty"` - SmartInfo smart.Info `json:"smartInfo,omitempty"` -} - -// PerfInfo - Includes Drive and Net perf info for the entire MinIO cluster -type PerfInfo struct { - DriveInfo []ServerDrivesInfo `json:"drives,omitempty"` - Net []ServerNetHealthInfo `json:"net,omitempty"` - NetParallel ServerNetHealthInfo `json:"net_parallel,omitempty"` - Error string `json:"error,omitempty"` -} - -// ServerDrivesInfo - Drive info about all drives in a single MinIO node -type ServerDrivesInfo struct { - Addr string `json:"addr"` - Serial []DrivePerfInfo `json:"serial,omitempty"` // Drive perf info collected one drive at a time - Parallel []DrivePerfInfo `json:"parallel,omitempty"` // Drive perf info collected in parallel - Error string `json:"error,omitempty"` -} - -// DrivePerfInfo - Stats about a single drive in a MinIO node -type DrivePerfInfo struct { - Path string `json:"endpoint"` - Latency disk.Latency `json:"latency,omitempty"` - Throughput disk.Throughput `json:"throughput,omitempty"` - Error string `json:"error,omitempty"` -} - -// ServerNetHealthInfo - Network health info about a single MinIO node -type ServerNetHealthInfo struct { - Addr string `json:"addr"` - Net []NetPerfInfo `json:"net,omitempty"` - Error string `json:"error,omitempty"` -} - -// NetPerfInfo - one-to-one network connectivity Stats between 2 MinIO nodes -type NetPerfInfo struct { - Addr string `json:"remote"` - Latency net.Latency `json:"latency,omitempty"` - Throughput net.Throughput `json:"throughput,omitempty"` - Error string `json:"error,omitempty"` -} - -// HealthDataType - Typed Health data types -type HealthDataType string - -// HealthDataTypes -const ( - HealthDataTypePerfDrive HealthDataType = "perfdrive" - HealthDataTypePerfNet HealthDataType = "perfnet" - HealthDataTypeMinioInfo HealthDataType = "minioinfo" - HealthDataTypeMinioConfig HealthDataType = "minioconfig" - HealthDataTypeSysCPU HealthDataType = "syscpu" - HealthDataTypeSysDiskHw HealthDataType = "sysdiskhw" - HealthDataTypeSysDocker HealthDataType = "sysdocker" // is this really needed? - HealthDataTypeSysOsInfo HealthDataType = "sysosinfo" - HealthDataTypeSysLoad HealthDataType = "sysload" // provides very little info. Making it TBD - HealthDataTypeSysMem HealthDataType = "sysmem" - HealthDataTypeSysNet HealthDataType = "sysnet" - HealthDataTypeSysProcess HealthDataType = "sysprocess" -) - -// HealthDataTypesMap - Map of Health datatypes -var HealthDataTypesMap = map[string]HealthDataType{ - "perfdrive": HealthDataTypePerfDrive, - "perfnet": HealthDataTypePerfNet, - "minioinfo": HealthDataTypeMinioInfo, - "minioconfig": HealthDataTypeMinioConfig, - "syscpu": HealthDataTypeSysCPU, - "sysdiskhw": HealthDataTypeSysDiskHw, - "sysdocker": HealthDataTypeSysDocker, - "sysosinfo": HealthDataTypeSysOsInfo, - "sysload": HealthDataTypeSysLoad, - "sysmem": HealthDataTypeSysMem, - "sysnet": HealthDataTypeSysNet, - "sysprocess": HealthDataTypeSysProcess, -} - -// HealthDataTypesList - List of Health datatypes -var HealthDataTypesList = []HealthDataType{ - HealthDataTypePerfDrive, - HealthDataTypePerfNet, - HealthDataTypeMinioInfo, - HealthDataTypeMinioConfig, - HealthDataTypeSysCPU, - HealthDataTypeSysDiskHw, - HealthDataTypeSysDocker, - HealthDataTypeSysOsInfo, - HealthDataTypeSysLoad, - HealthDataTypeSysMem, - HealthDataTypeSysNet, - HealthDataTypeSysProcess, -} - -// ServerHealthInfo - Connect to a minio server and call Health Info Management API -// to fetch server's information represented by HealthInfo structure -func (adm *AdminClient) ServerHealthInfo(ctx context.Context, healthDataTypes []HealthDataType, deadline time.Duration) <-chan HealthInfo { - respChan := make(chan HealthInfo) - go func() { - v := url.Values{} - - v.Set("deadline", - deadline.Truncate(1*time.Second).String()) - - // start with all set to false - for _, d := range HealthDataTypesList { - v.Set(string(d), "false") - } - - // only 'trueify' user provided values - for _, d := range healthDataTypes { - v.Set(string(d), "true") - } - var healthInfoMessage HealthInfo - healthInfoMessage.TimeStamp = time.Now() - - resp, err := adm.executeMethod(ctx, "GET", requestData{ - relPath: adminAPIPrefix + "/healthinfo", - queryValues: v, - }) - - defer closeResponse(resp) - if err != nil { - respChan <- HealthInfo{ - Error: err.Error(), - } - close(respChan) - return - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - respChan <- HealthInfo{ - Error: httpRespToErrorResponse(resp).Error(), - } - return - } - - // Unmarshal the server's json response - decoder := json.NewDecoder(resp.Body) - for { - err := decoder.Decode(&healthInfoMessage) - healthInfoMessage.TimeStamp = time.Now() - - if err == io.EOF { - break - } - if err != nil { - respChan <- HealthInfo{ - Error: err.Error(), - } - } - respChan <- healthInfoMessage - } - - respChan <- healthInfoMessage - - if v.Get(string(HealthDataTypeMinioInfo)) == "true" { - info, err := adm.ServerInfo(ctx) - if err != nil { - respChan <- HealthInfo{ - Error: err.Error(), - } - return - } - healthInfoMessage.Minio.Info = info - respChan <- healthInfoMessage - } - - close(respChan) - }() - return respChan -} - -// GetTotalCapacity gets the total capacity a server holds. -func (s *ServerDiskHwInfo) GetTotalCapacity() (capacity uint64) { - for _, u := range s.Usage { - capacity += u.Total - } - return -} - -// GetTotalFreeCapacity gets the total capacity that is free. -func (s *ServerDiskHwInfo) GetTotalFreeCapacity() (capacity uint64) { - for _, u := range s.Usage { - capacity += u.Free - } - return -} - -// GetTotalUsedCapacity gets the total capacity used. -func (s *ServerDiskHwInfo) GetTotalUsedCapacity() (capacity uint64) { - for _, u := range s.Usage { - capacity += u.Used - } - return -} diff --git a/pkg/madmin/info-commands.go b/pkg/madmin/info-commands.go deleted file mode 100644 index a5daa022f..000000000 --- a/pkg/madmin/info-commands.go +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "net/http" - "runtime" - "time" -) - -// BackendType - represents different backend types. -type BackendType int - -// Enum for different backend types. -const ( - Unknown BackendType = iota - // Filesystem backend. - FS - // Multi disk Erasure (single, distributed) backend. - Erasure - // Gateway to other storage - Gateway - - // Add your own backend. -) - -// ItemState - represents the status of any item in offline,init,online state -type ItemState string - -const ( - - // ItemOffline indicates that the item is offline - ItemOffline = ItemState("offline") - // ItemInitializing indicates that the item is still in initialization phase - ItemInitializing = ItemState("initializing") - // ItemOnline indicates that the item is online - ItemOnline = ItemState("online") -) - -// StorageInfo - represents total capacity of underlying storage. -type StorageInfo struct { - Disks []Disk - - // Backend type. - Backend BackendInfo -} - -// BackendInfo - contains info of the underlying backend -type BackendInfo struct { - // Represents various backend types, currently on FS, Erasure and Gateway - Type BackendType - - // Following fields are only meaningful if BackendType is Gateway. - GatewayOnline bool - - // Following fields are only meaningful if BackendType is Erasure. - OnlineDisks BackendDisks // Online disks during server startup. - OfflineDisks BackendDisks // Offline disks during server startup. - - // Following fields are only meaningful if BackendType is Erasure. - StandardSCData []int // Data disks for currently configured Standard storage class. - StandardSCParity int // Parity disks for currently configured Standard storage class. - RRSCData []int // Data disks for currently configured Reduced Redundancy storage class. - RRSCParity int // Parity disks for currently configured Reduced Redundancy storage class. -} - -// BackendDisks - represents the map of endpoint-disks. -type BackendDisks map[string]int - -// Sum - Return the sum of the disks in the endpoint-disk map. -func (d1 BackendDisks) Sum() (sum int) { - for _, count := range d1 { - sum += count - } - return sum -} - -// Merge - Reduces two endpoint-disk maps. -func (d1 BackendDisks) Merge(d2 BackendDisks) BackendDisks { - if len(d2) == 0 { - d2 = make(BackendDisks) - } - var merged = make(BackendDisks) - for i1, v1 := range d1 { - if v2, ok := d2[i1]; ok { - merged[i1] = v2 + v1 - continue - } - merged[i1] = v1 - } - return merged -} - -// StorageInfo - Connect to a minio server and call Storage Info Management API -// to fetch server's information represented by StorageInfo structure -func (adm *AdminClient) StorageInfo(ctx context.Context) (StorageInfo, error) { - resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/storageinfo"}) - defer closeResponse(resp) - if err != nil { - return StorageInfo{}, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return StorageInfo{}, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var storageInfo StorageInfo - if err = json.NewDecoder(resp.Body).Decode(&storageInfo); err != nil { - return StorageInfo{}, err - } - - return storageInfo, nil -} - -// BucketUsageInfo - bucket usage info provides -// - total size of the bucket -// - total objects in a bucket -// - object size histogram per bucket -type BucketUsageInfo struct { - Size uint64 `json:"size"` - ReplicationPendingSize uint64 `json:"objectsPendingReplicationTotalSize"` - ReplicationFailedSize uint64 `json:"objectsFailedReplicationTotalSize"` - ReplicatedSize uint64 `json:"objectsReplicatedTotalSize"` - ReplicaSize uint64 `json:"objectReplicaTotalSize"` - ReplicationPendingCount uint64 `json:"objectsPendingReplicationCount"` - ReplicationFailedCount uint64 `json:"objectsFailedReplicationCount"` - - ObjectsCount uint64 `json:"objectsCount"` - ObjectSizesHistogram map[string]uint64 `json:"objectsSizesHistogram"` -} - -// DataUsageInfo represents data usage stats of the underlying Object API -type DataUsageInfo struct { - // LastUpdate is the timestamp of when the data usage info was last updated. - // This does not indicate a full scan. - LastUpdate time.Time `json:"lastUpdate"` - - // Objects total count across all buckets - ObjectsTotalCount uint64 `json:"objectsCount"` - - // Objects total size across all buckets - ObjectsTotalSize uint64 `json:"objectsTotalSize"` - - // Total Size for objects that have not yet been replicated - ReplicationPendingSize uint64 `json:"objectsPendingReplicationTotalSize"` - - // Total size for objects that have witness one or more failures and will be retried - ReplicationFailedSize uint64 `json:"objectsFailedReplicationTotalSize"` - - // Total size for objects that have been replicated to destination - ReplicatedSize uint64 `json:"objectsReplicatedTotalSize"` - - // Total size for objects that are replicas - ReplicaSize uint64 `json:"objectsReplicaTotalSize"` - - // Total number of objects pending replication - ReplicationPendingCount uint64 `json:"objectsPendingReplicationCount"` - - // Total number of objects that failed replication - ReplicationFailedCount uint64 `json:"objectsFailedReplicationCount"` - - // Total number of buckets in this cluster - BucketsCount uint64 `json:"bucketsCount"` - - // Buckets usage info provides following information across all buckets - // - total size of the bucket - // - total objects in a bucket - // - object size histogram per bucket - BucketsUsage map[string]BucketUsageInfo `json:"bucketsUsageInfo"` - - // Deprecated kept here for backward compatibility reasons. - BucketSizes map[string]uint64 `json:"bucketsSizes"` -} - -// DataUsageInfo - returns data usage of the current object API -func (adm *AdminClient) DataUsageInfo(ctx context.Context) (DataUsageInfo, error) { - resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/datausageinfo"}) - defer closeResponse(resp) - if err != nil { - return DataUsageInfo{}, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return DataUsageInfo{}, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var dataUsageInfo DataUsageInfo - if err = json.NewDecoder(resp.Body).Decode(&dataUsageInfo); err != nil { - return DataUsageInfo{}, err - } - - return dataUsageInfo, nil -} - -// InfoMessage container to hold server admin related information. -type InfoMessage struct { - Mode string `json:"mode,omitempty"` - Domain []string `json:"domain,omitempty"` - Region string `json:"region,omitempty"` - SQSARN []string `json:"sqsARN,omitempty"` - DeploymentID string `json:"deploymentID,omitempty"` - Buckets Buckets `json:"buckets,omitempty"` - Objects Objects `json:"objects,omitempty"` - Usage Usage `json:"usage,omitempty"` - Services Services `json:"services,omitempty"` - Backend interface{} `json:"backend,omitempty"` - Servers []ServerProperties `json:"servers,omitempty"` -} - -// Services contains different services information -type Services struct { - KMS KMS `json:"kms,omitempty"` - LDAP LDAP `json:"ldap,omitempty"` - Logger []Logger `json:"logger,omitempty"` - Audit []Audit `json:"audit,omitempty"` - Notifications []map[string][]TargetIDStatus `json:"notifications,omitempty"` -} - -// Buckets contains the number of buckets -type Buckets struct { - Count uint64 `json:"count"` - Error string `json:"error,omitempty"` -} - -// Objects contains the number of objects -type Objects struct { - Count uint64 `json:"count"` - Error string `json:"error,omitempty"` -} - -// Usage contains the total size used -type Usage struct { - Size uint64 `json:"size"` - Error string `json:"error,omitempty"` -} - -// KMS contains KMS status information -type KMS struct { - Status string `json:"status,omitempty"` - Encrypt string `json:"encrypt,omitempty"` - Decrypt string `json:"decrypt,omitempty"` -} - -// LDAP contains ldap status -type LDAP struct { - Status string `json:"status,omitempty"` -} - -// Status of endpoint -type Status struct { - Status string `json:"status,omitempty"` -} - -// Audit contains audit logger status -type Audit map[string]Status - -// Logger contains logger status -type Logger map[string]Status - -// TargetIDStatus containsid and status -type TargetIDStatus map[string]Status - -// backendType - indicates the type of backend storage -type backendType string - -const ( - // FsType - Backend is FS Type - FsType = backendType("FS") - // ErasureType - Backend is Erasure type - ErasureType = backendType("Erasure") -) - -// FSBackend contains specific FS storage information -type FSBackend struct { - Type backendType `json:"backendType,omitempty"` -} - -// ErasureBackend contains specific erasure storage information -type ErasureBackend struct { - Type backendType `json:"backendType,omitempty"` - OnlineDisks int `json:"onlineDisks,omitempty"` - OfflineDisks int `json:"offlineDisks,omitempty"` - // Parity disks for currently configured Standard storage class. - StandardSCParity int `json:"standardSCParity,omitempty"` - // Parity disks for currently configured Reduced Redundancy storage class. - RRSCParity int `json:"rrSCParity,omitempty"` -} - -// ServerProperties holds server information -type ServerProperties struct { - State string `json:"state,omitempty"` - Endpoint string `json:"endpoint,omitempty"` - Uptime int64 `json:"uptime,omitempty"` - Version string `json:"version,omitempty"` - CommitID string `json:"commitID,omitempty"` - Network map[string]string `json:"network,omitempty"` - Disks []Disk `json:"drives,omitempty"` - PoolNumber int `json:"poolNumber,omitempty"` - MemStats runtime.MemStats `json:"mem_stats"` -} - -// DiskMetrics has the information about XL Storage APIs -// the number of calls of each API and the moving average of -// the duration of each API. -type DiskMetrics struct { - APILatencies map[string]string `json:"apiLatencies,omitempty"` - APICalls map[string]uint64 `json:"apiCalls,omitempty"` -} - -// Disk holds Disk information -type Disk struct { - Endpoint string `json:"endpoint,omitempty"` - RootDisk bool `json:"rootDisk,omitempty"` - DrivePath string `json:"path,omitempty"` - Healing bool `json:"healing,omitempty"` - State string `json:"state,omitempty"` - UUID string `json:"uuid,omitempty"` - Model string `json:"model,omitempty"` - TotalSpace uint64 `json:"totalspace,omitempty"` - UsedSpace uint64 `json:"usedspace,omitempty"` - AvailableSpace uint64 `json:"availspace,omitempty"` - ReadThroughput float64 `json:"readthroughput,omitempty"` - WriteThroughPut float64 `json:"writethroughput,omitempty"` - ReadLatency float64 `json:"readlatency,omitempty"` - WriteLatency float64 `json:"writelatency,omitempty"` - Utilization float64 `json:"utilization,omitempty"` - Metrics *DiskMetrics `json:"metrics,omitempty"` - HealInfo *HealingDisk `json:"heal_info,omitempty"` - - // Indexes, will be -1 until assigned a set. - PoolIndex int `json:"pool_index"` - SetIndex int `json:"set_index"` - DiskIndex int `json:"disk_index"` -} - -// ServerInfo - Connect to a minio server and call Server Admin Info Management API -// to fetch server's information represented by infoMessage structure -func (adm *AdminClient) ServerInfo(ctx context.Context) (InfoMessage, error) { - resp, err := adm.executeMethod(ctx, - http.MethodGet, - requestData{relPath: adminAPIPrefix + "/info"}, - ) - defer closeResponse(resp) - if err != nil { - return InfoMessage{}, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return InfoMessage{}, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var message InfoMessage - if err = json.NewDecoder(resp.Body).Decode(&message); err != nil { - return InfoMessage{}, err - } - - return message, nil -} diff --git a/pkg/madmin/kms-commands.go b/pkg/madmin/kms-commands.go deleted file mode 100644 index 00c7dc368..000000000 --- a/pkg/madmin/kms-commands.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "net/http" - "net/url" -) - -// CreateKey tries to create a new master key with the given keyID -// at the KMS connected to a MinIO server. -func (adm *AdminClient) CreateKey(ctx context.Context, keyID string) error { - // POST /minio/admin/v3/kms/key/create?key-id= - qv := url.Values{} - qv.Set("key-id", keyID) - reqData := requestData{ - relPath: adminAPIPrefix + "/kms/key/create", - queryValues: qv, - } - - resp, err := adm.executeMethod(ctx, http.MethodPost, reqData) - if err != nil { - return err - } - defer closeResponse(resp) - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - return nil -} - -// GetKeyStatus requests status information about the key referenced by keyID -// from the KMS connected to a MinIO by performing a Admin-API request. -// It basically hits the `/minio/admin/v3/kms/key/status` API endpoint. -func (adm *AdminClient) GetKeyStatus(ctx context.Context, keyID string) (*KMSKeyStatus, error) { - // GET /minio/admin/v3/kms/key/status?key-id= - qv := url.Values{} - qv.Set("key-id", keyID) - reqData := requestData{ - relPath: adminAPIPrefix + "/kms/key/status", - queryValues: qv, - } - - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - if err != nil { - return nil, err - } - defer closeResponse(resp) - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - var keyInfo KMSKeyStatus - if err = json.NewDecoder(resp.Body).Decode(&keyInfo); err != nil { - return nil, err - } - return &keyInfo, nil -} - -// KMSKeyStatus contains some status information about a KMS master key. -// The MinIO server tries to access the KMS and perform encryption and -// decryption operations. If the MinIO server can access the KMS and -// all master key operations succeed it returns a status containing only -// the master key ID but no error. -type KMSKeyStatus struct { - KeyID string `json:"key-id"` - EncryptionErr string `json:"encryption-error,omitempty"` // An empty error == success - DecryptionErr string `json:"decryption-error,omitempty"` // An empty error == success -} diff --git a/pkg/madmin/parse-kv.go b/pkg/madmin/parse-kv.go deleted file mode 100644 index 1aea14e45..000000000 --- a/pkg/madmin/parse-kv.go +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "bufio" - "bytes" - "fmt" - "sort" - "strings" - "unicode" -) - -// KV - is a shorthand of each key value. -type KV struct { - Key string `json:"key"` - Value string `json:"value"` -} - -// KVS - is a shorthand for some wrapper functions -// to operate on list of key values. -type KVS []KV - -// Empty - return if kv is empty -func (kvs KVS) Empty() bool { - return len(kvs) == 0 -} - -// Set sets a value, if not sets a default value. -func (kvs *KVS) Set(key, value string) { - for i, kv := range *kvs { - if kv.Key == key { - (*kvs)[i] = KV{ - Key: key, - Value: value, - } - return - } - } - *kvs = append(*kvs, KV{ - Key: key, - Value: value, - }) -} - -// Get - returns the value of a key, if not found returns empty. -func (kvs KVS) Get(key string) string { - v, ok := kvs.Lookup(key) - if ok { - return v - } - return "" -} - -// Lookup - lookup a key in a list of KVS -func (kvs KVS) Lookup(key string) (string, bool) { - for _, kv := range kvs { - if kv.Key == key { - return kv.Value, true - } - } - return "", false -} - -// Target signifies an individual target -type Target struct { - SubSystem string `json:"subSys"` - KVS KVS `json:"kvs"` -} - -// Standard config keys and values. -const ( - EnableKey = "enable" - CommentKey = "comment" - - // Enable values - EnableOn = "on" - EnableOff = "off" -) - -// HasSpace - returns if given string has space. -func HasSpace(s string) bool { - for _, r := range s { - if unicode.IsSpace(r) { - return true - } - } - return false -} - -// Constant separators -const ( - SubSystemSeparator = `:` - KvSeparator = `=` - KvComment = `#` - KvSpaceSeparator = ` ` - KvNewline = "\n" - KvDoubleQuote = `"` - KvSingleQuote = `'` - - Default = `_` -) - -// SanitizeValue - this function is needed, to trim off single or double quotes, creeping into the values. -func SanitizeValue(v string) string { - v = strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(v), KvDoubleQuote), KvDoubleQuote) - return strings.TrimSuffix(strings.TrimPrefix(v, KvSingleQuote), KvSingleQuote) -} - -// KvFields - converts an input string of form "k1=v1 k2=v2" into -// fields of ["k1=v1", "k2=v2"], the tokenization of each `k=v` -// happens with the right number of input keys, if keys -// input is empty returned value is empty slice as well. -func KvFields(input string, keys []string) []string { - var valueIndexes []int - for _, key := range keys { - i := strings.Index(input, key+KvSeparator) - if i == -1 { - continue - } - valueIndexes = append(valueIndexes, i) - } - - sort.Ints(valueIndexes) - var fields = make([]string, len(valueIndexes)) - for i := range valueIndexes { - j := i + 1 - if j < len(valueIndexes) { - fields[i] = strings.TrimSpace(input[valueIndexes[i]:valueIndexes[j]]) - } else { - fields[i] = strings.TrimSpace(input[valueIndexes[i]:]) - } - } - return fields -} - -// ParseTarget - adds new targets, by parsing the input string s. -func ParseTarget(s string, help Help) (*Target, error) { - inputs := strings.SplitN(s, KvSpaceSeparator, 2) - if len(inputs) <= 1 { - return nil, fmt.Errorf("invalid number of arguments '%s'", s) - } - - subSystemValue := strings.SplitN(inputs[0], SubSystemSeparator, 2) - if len(subSystemValue) == 0 { - return nil, fmt.Errorf("invalid number of arguments %s", s) - } - - if help.SubSys != subSystemValue[0] { - return nil, fmt.Errorf("unknown sub-system %s", subSystemValue[0]) - } - - var kvs = KVS{} - var prevK string - for _, v := range KvFields(inputs[1], help.Keys()) { - kv := strings.SplitN(v, KvSeparator, 2) - if len(kv) == 0 { - continue - } - if len(kv) == 1 && prevK != "" { - value := strings.Join([]string{ - kvs.Get(prevK), - SanitizeValue(kv[0]), - }, KvSpaceSeparator) - kvs.Set(prevK, value) - continue - } - if len(kv) == 2 { - prevK = kv[0] - kvs.Set(prevK, SanitizeValue(kv[1])) - continue - } - return nil, fmt.Errorf("value for key '%s' cannot be empty", kv[0]) - } - - return &Target{ - SubSystem: inputs[0], - KVS: kvs, - }, nil -} - -// ParseSubSysTarget - parse a sub-system target -func ParseSubSysTarget(buf []byte, help Help) (target *Target, err error) { - bio := bufio.NewScanner(bytes.NewReader(buf)) - if bio.Scan() { - return ParseTarget(bio.Text(), help) - } - return nil, bio.Err() -} diff --git a/pkg/madmin/policy-commands.go b/pkg/madmin/policy-commands.go deleted file mode 100644 index 82e74bc55..000000000 --- a/pkg/madmin/policy-commands.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "io/ioutil" - "net/http" - "net/url" - - iampolicy "github.com/minio/minio/pkg/iam/policy" -) - -// InfoCannedPolicy - expand canned policy into JSON structure. -func (adm *AdminClient) InfoCannedPolicy(ctx context.Context, policyName string) (*iampolicy.Policy, error) { - queryValues := url.Values{} - queryValues.Set("name", policyName) - - reqData := requestData{ - relPath: adminAPIPrefix + "/info-canned-policy", - queryValues: queryValues, - } - - // Execute GET on /minio/admin/v3/info-canned-policy - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - return iampolicy.ParseConfig(resp.Body) -} - -// ListCannedPolicies - list all configured canned policies. -func (adm *AdminClient) ListCannedPolicies(ctx context.Context) (map[string]*iampolicy.Policy, error) { - reqData := requestData{ - relPath: adminAPIPrefix + "/list-canned-policies", - } - - // Execute GET on /minio/admin/v3/list-canned-policies - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - respBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - var policies = make(map[string]*iampolicy.Policy) - if err = json.Unmarshal(respBytes, &policies); err != nil { - return nil, err - } - - return policies, nil -} - -// RemoveCannedPolicy - remove a policy for a canned. -func (adm *AdminClient) RemoveCannedPolicy(ctx context.Context, policyName string) error { - queryValues := url.Values{} - queryValues.Set("name", policyName) - - reqData := requestData{ - relPath: adminAPIPrefix + "/remove-canned-policy", - queryValues: queryValues, - } - - // Execute DELETE on /minio/admin/v3/remove-canned-policy to remove policy. - resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// AddCannedPolicy - adds a policy for a canned. -func (adm *AdminClient) AddCannedPolicy(ctx context.Context, policyName string, policy *iampolicy.Policy) error { - if policy == nil { - return ErrInvalidArgument("policy input cannot be empty") - } - - if err := policy.Validate(); err != nil { - return err - } - - buf, err := json.Marshal(policy) - if err != nil { - return err - } - - queryValues := url.Values{} - queryValues.Set("name", policyName) - - reqData := requestData{ - relPath: adminAPIPrefix + "/add-canned-policy", - queryValues: queryValues, - content: buf, - } - - // Execute PUT on /minio/admin/v3/add-canned-policy to set policy. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// SetPolicy - sets the policy for a user or a group. -func (adm *AdminClient) SetPolicy(ctx context.Context, policyName, entityName string, isGroup bool) error { - queryValues := url.Values{} - queryValues.Set("policyName", policyName) - queryValues.Set("userOrGroup", entityName) - groupStr := "false" - if isGroup { - groupStr = "true" - } - queryValues.Set("isGroup", groupStr) - - reqData := requestData{ - relPath: adminAPIPrefix + "/set-user-or-group-policy", - queryValues: queryValues, - } - - // Execute PUT on /minio/admin/v3/set-user-or-group-policy to set policy. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - return nil -} diff --git a/pkg/madmin/profiling-commands.go b/pkg/madmin/profiling-commands.go deleted file mode 100644 index a2621b5c9..000000000 --- a/pkg/madmin/profiling-commands.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" -) - -// ProfilerType represents the profiler type -// passed to the profiler subsystem. -type ProfilerType string - -// Different supported profiler types. -const ( - ProfilerCPU ProfilerType = "cpu" // represents CPU profiler type - ProfilerMEM ProfilerType = "mem" // represents MEM profiler type - ProfilerBlock ProfilerType = "block" // represents Block profiler type - ProfilerMutex ProfilerType = "mutex" // represents Mutex profiler type - ProfilerTrace ProfilerType = "trace" // represents Trace profiler type - ProfilerThreads ProfilerType = "threads" // represents ThreadCreate profiler type - ProfilerGoroutines ProfilerType = "goroutines" // represents Goroutine dumps. -) - -// StartProfilingResult holds the result of starting -// profiler result in a given node. -type StartProfilingResult struct { - NodeName string `json:"nodeName"` - Success bool `json:"success"` - Error string `json:"error"` -} - -// StartProfiling makes an admin call to remotely start profiling on a standalone -// server or the whole cluster in case of a distributed setup. -func (adm *AdminClient) StartProfiling(ctx context.Context, profiler ProfilerType) ([]StartProfilingResult, error) { - v := url.Values{} - v.Set("profilerType", string(profiler)) - resp, err := adm.executeMethod(ctx, - http.MethodPost, requestData{ - relPath: adminAPIPrefix + "/profiling/start", - queryValues: v, - }, - ) - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - jsonResult, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - var startResults []StartProfilingResult - err = json.Unmarshal(jsonResult, &startResults) - if err != nil { - return nil, err - } - - return startResults, nil -} - -// DownloadProfilingData makes an admin call to download profiling data of a standalone -// server or of the whole cluster in case of a distributed setup. -func (adm *AdminClient) DownloadProfilingData(ctx context.Context) (io.ReadCloser, error) { - path := fmt.Sprintf(adminAPIPrefix + "/profiling/download") - resp, err := adm.executeMethod(ctx, - http.MethodGet, requestData{ - relPath: path, - }, - ) - - if err != nil { - closeResponse(resp) - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - if resp.Body == nil { - return nil, errors.New("body is nil") - } - - return resp.Body, nil -} diff --git a/pkg/madmin/quota-commands.go b/pkg/madmin/quota-commands.go deleted file mode 100644 index ce0cdba33..000000000 --- a/pkg/madmin/quota-commands.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "io/ioutil" - "net/http" - "net/url" -) - -// QuotaType represents bucket quota type -type QuotaType string - -const ( - // HardQuota specifies a hard quota of usage for bucket - HardQuota QuotaType = "hard" - // FIFOQuota specifies a quota limit beyond which older files are deleted from bucket - FIFOQuota QuotaType = "fifo" -) - -// IsValid returns true if quota type is one of FIFO or Hard -func (t QuotaType) IsValid() bool { - return t == HardQuota || t == FIFOQuota -} - -// BucketQuota holds bucket quota restrictions -type BucketQuota struct { - Quota uint64 `json:"quota"` - Type QuotaType `json:"quotatype,omitempty"` -} - -// IsValid returns false if quota is invalid -// empty quota when Quota == 0 is always true. -func (q BucketQuota) IsValid() bool { - if q.Quota > 0 { - return q.Type.IsValid() - } - // Empty configs are valid. - return true -} - -// GetBucketQuota - get info on a user -func (adm *AdminClient) GetBucketQuota(ctx context.Context, bucket string) (q BucketQuota, err error) { - queryValues := url.Values{} - queryValues.Set("bucket", bucket) - - reqData := requestData{ - relPath: adminAPIPrefix + "/get-bucket-quota", - queryValues: queryValues, - } - - // Execute GET on /minio/admin/v3/get-quota - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - - defer closeResponse(resp) - if err != nil { - return q, err - } - - if resp.StatusCode != http.StatusOK { - return q, httpRespToErrorResponse(resp) - } - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return q, err - } - if err = json.Unmarshal(b, &q); err != nil { - return q, err - } - - return q, nil -} - -// SetBucketQuota - sets a bucket's quota, if quota is set to '0' -// quota is disabled. -func (adm *AdminClient) SetBucketQuota(ctx context.Context, bucket string, quota *BucketQuota) error { - data, err := json.Marshal(quota) - if err != nil { - return err - } - - queryValues := url.Values{} - queryValues.Set("bucket", bucket) - - reqData := requestData{ - relPath: adminAPIPrefix + "/set-bucket-quota", - queryValues: queryValues, - content: data, - } - - // Execute PUT on /minio/admin/v3/set-bucket-quota to set quota for a bucket. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} diff --git a/pkg/madmin/remote-target-commands.go b/pkg/madmin/remote-target-commands.go deleted file mode 100644 index e7306a6fa..000000000 --- a/pkg/madmin/remote-target-commands.go +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "strings" - "time" - - "github.com/minio/minio/pkg/auth" -) - -// ServiceType represents service type -type ServiceType string - -const ( - // ReplicationService specifies replication service - ReplicationService ServiceType = "replication" -) - -// IsValid returns true if ARN type represents replication -func (t ServiceType) IsValid() bool { - return t == ReplicationService -} - -// ARN is a struct to define arn. -type ARN struct { - Type ServiceType - ID string - Region string - Bucket string -} - -// Empty returns true if arn struct is empty -func (a ARN) Empty() bool { - return !a.Type.IsValid() -} -func (a ARN) String() string { - return fmt.Sprintf("arn:minio:%s:%s:%s:%s", a.Type, a.Region, a.ID, a.Bucket) -} - -// ParseARN return ARN struct from string in arn format. -func ParseARN(s string) (*ARN, error) { - // ARN must be in the format of arn:minio:::: - if !strings.HasPrefix(s, "arn:minio:") { - return nil, fmt.Errorf("Invalid ARN %s", s) - } - - tokens := strings.Split(s, ":") - if len(tokens) != 6 { - return nil, fmt.Errorf("Invalid ARN %s", s) - } - - if tokens[4] == "" || tokens[5] == "" { - return nil, fmt.Errorf("Invalid ARN %s", s) - } - - return &ARN{ - Type: ServiceType(tokens[2]), - Region: tokens[3], - ID: tokens[4], - Bucket: tokens[5], - }, nil -} - -// BucketTarget represents the target bucket and site association. -type BucketTarget struct { - SourceBucket string `json:"sourcebucket"` - Endpoint string `json:"endpoint"` - Credentials *auth.Credentials `json:"credentials"` - TargetBucket string `json:"targetbucket"` - Secure bool `json:"secure"` - Path string `json:"path,omitempty"` - API string `json:"api,omitempty"` - Arn string `json:"arn,omitempty"` - Type ServiceType `json:"type"` - Region string `json:"omitempty"` - BandwidthLimit int64 `json:"bandwidthlimit,omitempty"` - ReplicationSync bool `json:"replicationSync"` - StorageClass string `json:"storageclass,omitempty"` - HealthCheckDuration time.Duration `json:"healthCheckDuration,omitempty"` - DisableProxy bool `json:"disableProxy"` -} - -// Clone returns shallow clone of BucketTarget without secret key in credentials -func (t *BucketTarget) Clone() BucketTarget { - return BucketTarget{ - SourceBucket: t.SourceBucket, - Endpoint: t.Endpoint, - TargetBucket: t.TargetBucket, - Credentials: &auth.Credentials{AccessKey: t.Credentials.AccessKey}, - Secure: t.Secure, - Path: t.Path, - API: t.API, - Arn: t.Arn, - Type: t.Type, - Region: t.Region, - BandwidthLimit: t.BandwidthLimit, - ReplicationSync: t.ReplicationSync, - StorageClass: t.StorageClass, // target storage class - HealthCheckDuration: t.HealthCheckDuration, - DisableProxy: t.DisableProxy, - } -} - -// URL returns target url -func (t BucketTarget) URL() *url.URL { - scheme := "http" - if t.Secure { - scheme = "https" - } - return &url.URL{ - Scheme: scheme, - Host: t.Endpoint, - } -} - -// Empty returns true if struct is empty. -func (t BucketTarget) Empty() bool { - return t.String() == "" || t.Credentials == nil -} - -func (t *BucketTarget) String() string { - return fmt.Sprintf("%s %s", t.Endpoint, t.TargetBucket) -} - -// BucketTargets represents a slice of bucket targets by type and endpoint -type BucketTargets struct { - Targets []BucketTarget -} - -// Empty returns true if struct is empty. -func (t BucketTargets) Empty() bool { - if len(t.Targets) == 0 { - return true - } - empty := true - for _, t := range t.Targets { - if !t.Empty() { - return false - } - } - return empty -} - -// ListRemoteTargets - gets target(s) for this bucket -func (adm *AdminClient) ListRemoteTargets(ctx context.Context, bucket, arnType string) (targets []BucketTarget, err error) { - queryValues := url.Values{} - queryValues.Set("bucket", bucket) - queryValues.Set("type", arnType) - - reqData := requestData{ - relPath: adminAPIPrefix + "/list-remote-targets", - queryValues: queryValues, - } - - // Execute GET on /minio/admin/v3/list-remote-targets - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - - defer closeResponse(resp) - if err != nil { - return targets, err - } - - if resp.StatusCode != http.StatusOK { - return targets, httpRespToErrorResponse(resp) - } - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return targets, err - } - if err = json.Unmarshal(b, &targets); err != nil { - return targets, err - } - return targets, nil -} - -// SetRemoteTarget sets up a remote target for this bucket -func (adm *AdminClient) SetRemoteTarget(ctx context.Context, bucket string, target *BucketTarget) (string, error) { - data, err := json.Marshal(target) - if err != nil { - return "", err - } - encData, err := EncryptData(adm.getSecretKey(), data) - if err != nil { - return "", err - } - queryValues := url.Values{} - queryValues.Set("bucket", bucket) - - reqData := requestData{ - relPath: adminAPIPrefix + "/set-remote-target", - queryValues: queryValues, - content: encData, - } - - // Execute PUT on /minio/admin/v3/set-remote-target to set a target for this bucket of specific arn type. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return "", err - } - - if resp.StatusCode != http.StatusOK { - return "", httpRespToErrorResponse(resp) - } - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "", err - } - var arn string - if err = json.Unmarshal(b, &arn); err != nil { - return "", err - } - return arn, nil -} - -// TargetUpdateType - type of update on the remote target -type TargetUpdateType int - -const ( - // CredentialsUpdateType update creds - CredentialsUpdateType TargetUpdateType = 1 + iota - // SyncUpdateType update synchronous replication setting - SyncUpdateType - // ProxyUpdateType update proxy setting - ProxyUpdateType - // BandwidthLimitUpdateType update bandwidth limit - BandwidthLimitUpdateType - // HealthCheckDurationUpdateType update health check duration - HealthCheckDurationUpdateType - // PathUpdateType update Path - PathUpdateType -) - -// GetTargetUpdateOps returns a slice of update operations being -// performed with `mc admin bucket remote edit` -func GetTargetUpdateOps(values url.Values) []TargetUpdateType { - var ops []TargetUpdateType - if values.Get("update") != "true" { - return ops - } - if values.Get("creds") == "true" { - ops = append(ops, CredentialsUpdateType) - } - if values.Get("sync") == "true" { - ops = append(ops, SyncUpdateType) - } - if values.Get("proxy") == "true" { - ops = append(ops, ProxyUpdateType) - } - if values.Get("healthcheck") == "true" { - ops = append(ops, HealthCheckDurationUpdateType) - } - if values.Get("bandwidth") == "true" { - ops = append(ops, BandwidthLimitUpdateType) - } - if values.Get("path") == "true" { - ops = append(ops, PathUpdateType) - } - return ops -} - -// UpdateRemoteTarget updates credentials for a remote bucket target -func (adm *AdminClient) UpdateRemoteTarget(ctx context.Context, target *BucketTarget, ops ...TargetUpdateType) (string, error) { - if target == nil { - return "", fmt.Errorf("target cannot be nil") - } - data, err := json.Marshal(target) - if err != nil { - return "", err - } - encData, err := EncryptData(adm.getSecretKey(), data) - if err != nil { - return "", err - } - queryValues := url.Values{} - queryValues.Set("bucket", target.SourceBucket) - queryValues.Set("update", "true") - - for _, op := range ops { - switch op { - case CredentialsUpdateType: - queryValues.Set("creds", "true") - case SyncUpdateType: - queryValues.Set("sync", "true") - case ProxyUpdateType: - queryValues.Set("proxy", "true") - case BandwidthLimitUpdateType: - queryValues.Set("bandwidth", "true") - case HealthCheckDurationUpdateType: - queryValues.Set("healthcheck", "true") - case PathUpdateType: - queryValues.Set("path", "true") - } - } - - reqData := requestData{ - relPath: adminAPIPrefix + "/set-remote-target", - queryValues: queryValues, - content: encData, - } - - // Execute PUT on /minio/admin/v3/set-remote-target to set a target for this bucket of specific arn type. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return "", err - } - - if resp.StatusCode != http.StatusOK { - return "", httpRespToErrorResponse(resp) - } - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "", err - } - var arn string - if err = json.Unmarshal(b, &arn); err != nil { - return "", err - } - return arn, nil -} - -// RemoveRemoteTarget removes a remote target associated with particular ARN for this bucket -func (adm *AdminClient) RemoveRemoteTarget(ctx context.Context, bucket, arn string) error { - queryValues := url.Values{} - queryValues.Set("bucket", bucket) - queryValues.Set("arn", arn) - - reqData := requestData{ - relPath: adminAPIPrefix + "/remove-remote-target", - queryValues: queryValues, - } - - // Execute PUT on /minio/admin/v3/remove-remote-target to remove a target for this bucket - // with specific ARN - resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusNoContent { - return httpRespToErrorResponse(resp) - } - return nil -} diff --git a/pkg/madmin/remote-target-commands_test.go b/pkg/madmin/remote-target-commands_test.go deleted file mode 100644 index aef235480..000000000 --- a/pkg/madmin/remote-target-commands_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "net/url" - "testing" -) - -func isOpsEqual(op1 []TargetUpdateType, op2 []TargetUpdateType) bool { - if len(op1) != len(op2) { - return false - } - for _, o1 := range op1 { - found := false - for _, o2 := range op2 { - if o2 == o1 { - found = true - break - } - } - if !found { - return false - } - } - return true -} - -// TestGetTargetUpdateOps tests GetTargetUpdateOps -func TestGetTargetUpdateOps(t *testing.T) { - testCases := []struct { - values url.Values - expectedOps []TargetUpdateType - }{ - {values: url.Values{ - "update": []string{"true"}}, - expectedOps: []TargetUpdateType{}, - }, - {values: url.Values{ - "update": []string{"false"}, - "path": []string{"true"}, - }, - expectedOps: []TargetUpdateType{}, - }, - {values: url.Values{ - "update": []string{"true"}, - "path": []string{""}, - }, - expectedOps: []TargetUpdateType{}, - }, - {values: url.Values{ - "update": []string{"true"}, - "path": []string{"true"}, - "bzzzz": []string{"true"}, - }, - expectedOps: []TargetUpdateType{PathUpdateType}, - }, - - {values: url.Values{ - "update": []string{"true"}, - "path": []string{"true"}, - "creds": []string{"true"}, - "sync": []string{"true"}, - "proxy": []string{"true"}, - "bandwidth": []string{"true"}, - "healthcheck": []string{"true"}, - }, - expectedOps: []TargetUpdateType{ - PathUpdateType, CredentialsUpdateType, SyncUpdateType, ProxyUpdateType, BandwidthLimitUpdateType, HealthCheckDurationUpdateType}, - }, - } - for i, test := range testCases { - gotOps := GetTargetUpdateOps(test.values) - if !isOpsEqual(gotOps, test.expectedOps) { - t.Fatalf("test %d: expected %v got %v", i+1, test.expectedOps, gotOps) - } - } -} diff --git a/pkg/madmin/retry.go b/pkg/madmin/retry.go deleted file mode 100644 index 808c908d4..000000000 --- a/pkg/madmin/retry.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "math/rand" - "net/http" - "sync" - "time" -) - -// MaxRetry is the maximum number of retries before stopping. -var MaxRetry = 10 - -// MaxJitter will randomize over the full exponential backoff time -const MaxJitter = 1.0 - -// NoJitter disables the use of jitter for randomizing the exponential backoff time -const NoJitter = 0.0 - -// DefaultRetryUnit - default unit multiplicative per retry. -// defaults to 1 second. -const DefaultRetryUnit = time.Second - -// DefaultRetryCap - Each retry attempt never waits no longer than -// this maximum time duration. -const DefaultRetryCap = time.Second * 30 - -// lockedRandSource provides protected rand source, implements rand.Source interface. -type lockedRandSource struct { - lk sync.Mutex - src rand.Source -} - -// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. -func (r *lockedRandSource) Int63() (n int64) { - r.lk.Lock() - n = r.src.Int63() - r.lk.Unlock() - return -} - -// Seed uses the provided seed value to initialize the generator to a -// deterministic state. -func (r *lockedRandSource) Seed(seed int64) { - r.lk.Lock() - r.src.Seed(seed) - r.lk.Unlock() -} - -// newRetryTimer creates a timer with exponentially increasing -// delays until the maximum retry attempts are reached. -func (adm AdminClient) newRetryTimer(ctx context.Context, maxRetry int, unit time.Duration, cap time.Duration, jitter float64) <-chan int { - attemptCh := make(chan int) - - // computes the exponential backoff duration according to - // https://www.awsarchitectureblog.com/2015/03/backoff.html - exponentialBackoffWait := func(attempt int) time.Duration { - // normalize jitter to the range [0, 1.0] - if jitter < NoJitter { - jitter = NoJitter - } - if jitter > MaxJitter { - jitter = MaxJitter - } - - //sleep = random_between(0, min(cap, base * 2 ** attempt)) - sleep := unit * 1 << uint(attempt) - if sleep > cap { - sleep = cap - } - if jitter > NoJitter { - sleep -= time.Duration(adm.random.Float64() * float64(sleep) * jitter) - } - return sleep - } - - go func() { - defer close(attemptCh) - for i := 0; i < maxRetry; i++ { - // Attempts start from 1. - select { - case attemptCh <- i + 1: - case <-ctx.Done(): - // Stop the routine. - return - } - - select { - case <-time.After(exponentialBackoffWait(i)): - case <-ctx.Done(): - // Stop the routine. - return - } - } - }() - return attemptCh -} - -// List of AWS S3 error codes which are retryable. -var retryableS3Codes = map[string]struct{}{ - "RequestError": {}, - "RequestTimeout": {}, - "Throttling": {}, - "ThrottlingException": {}, - "RequestLimitExceeded": {}, - "RequestThrottled": {}, - "InternalError": {}, - "SlowDown": {}, - // Add more AWS S3 codes here. -} - -// isS3CodeRetryable - is s3 error code retryable. -func isS3CodeRetryable(s3Code string) (ok bool) { - _, ok = retryableS3Codes[s3Code] - return ok -} - -// List of HTTP status codes which are retryable. -var retryableHTTPStatusCodes = map[int]struct{}{ - http.StatusRequestTimeout: {}, - http.StatusTooManyRequests: {}, - http.StatusInternalServerError: {}, - http.StatusBadGateway: {}, - http.StatusServiceUnavailable: {}, - // Add more HTTP status codes here. -} - -// isHTTPStatusRetryable - is HTTP error code retryable. -func isHTTPStatusRetryable(httpStatusCode int) (ok bool) { - _, ok = retryableHTTPStatusCodes[httpStatusCode] - return ok -} diff --git a/pkg/madmin/service-commands.go b/pkg/madmin/service-commands.go deleted file mode 100644 index 378da4e6f..000000000 --- a/pkg/madmin/service-commands.go +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "net/http" - "net/url" - "strconv" - "time" - - trace "github.com/minio/minio/pkg/trace" -) - -// ServiceRestart - restarts the MinIO cluster -func (adm *AdminClient) ServiceRestart(ctx context.Context) error { - return adm.serviceCallAction(ctx, ServiceActionRestart) -} - -// ServiceStop - stops the MinIO cluster -func (adm *AdminClient) ServiceStop(ctx context.Context) error { - return adm.serviceCallAction(ctx, ServiceActionStop) -} - -// ServiceAction - type to restrict service-action values -type ServiceAction string - -const ( - // ServiceActionRestart represents restart action - ServiceActionRestart ServiceAction = "restart" - // ServiceActionStop represents stop action - ServiceActionStop = "stop" -) - -// serviceCallAction - call service restart/update/stop API. -func (adm *AdminClient) serviceCallAction(ctx context.Context, action ServiceAction) error { - queryValues := url.Values{} - queryValues.Set("action", string(action)) - - // Request API to Restart server - resp, err := adm.executeMethod(ctx, - http.MethodPost, requestData{ - relPath: adminAPIPrefix + "/service", - queryValues: queryValues, - }, - ) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// ServiceTraceInfo holds http trace -type ServiceTraceInfo struct { - Trace trace.Info - Err error `json:"-"` -} - -// ServiceTraceOpts holds tracing options -type ServiceTraceOpts struct { - All bool // Deprecated - - S3 bool - Internal bool - Storage bool - OS bool - OnlyErrors bool - Threshold time.Duration -} - -// ServiceTrace - listen on http trace notifications. -func (adm AdminClient) ServiceTrace(ctx context.Context, opts ServiceTraceOpts) <-chan ServiceTraceInfo { - traceInfoCh := make(chan ServiceTraceInfo) - // Only success, start a routine to start reading line by line. - go func(traceInfoCh chan<- ServiceTraceInfo) { - defer close(traceInfoCh) - for { - urlValues := make(url.Values) - urlValues.Set("err", strconv.FormatBool(opts.OnlyErrors)) - urlValues.Set("threshold", opts.Threshold.String()) - - if opts.All { - // Deprecated flag - urlValues.Set("all", "true") - } else { - urlValues.Set("s3", strconv.FormatBool(opts.S3)) - urlValues.Set("internal", strconv.FormatBool(opts.Internal)) - urlValues.Set("storage", strconv.FormatBool(opts.Storage)) - urlValues.Set("os", strconv.FormatBool(opts.OS)) - } - reqData := requestData{ - relPath: adminAPIPrefix + "/trace", - queryValues: urlValues, - } - // Execute GET to call trace handler - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - if err != nil { - closeResponse(resp) - traceInfoCh <- ServiceTraceInfo{Err: err} - return - } - - if resp.StatusCode != http.StatusOK { - traceInfoCh <- ServiceTraceInfo{Err: httpRespToErrorResponse(resp)} - return - } - - dec := json.NewDecoder(resp.Body) - for { - var info trace.Info - if err = dec.Decode(&info); err != nil { - break - } - select { - case <-ctx.Done(): - return - case traceInfoCh <- ServiceTraceInfo{Trace: info}: - } - } - } - }(traceInfoCh) - - // Returns the trace info channel, for caller to start reading from. - return traceInfoCh -} diff --git a/pkg/madmin/tier-azure.go b/pkg/madmin/tier-azure.go deleted file mode 100644 index 1566b9964..000000000 --- a/pkg/madmin/tier-azure.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -//go:generate msgp -file $GOFILE - -// TierAzure represents the remote tier configuration for Azure Blob Storage. -type TierAzure struct { - Endpoint string `json:",omitempty"` - AccountName string `json:",omitempty"` - AccountKey string `json:",omitempty"` - Bucket string `json:",omitempty"` - Prefix string `json:",omitempty"` - Region string `json:",omitempty"` - StorageClass string `json:",omitempty"` -} - -// AzureOptions supports NewTierAzure to take variadic options -type AzureOptions func(*TierAzure) error - -// AzurePrefix helper to supply optional object prefix to NewTierAzure -func AzurePrefix(prefix string) func(az *TierAzure) error { - return func(az *TierAzure) error { - az.Prefix = prefix - return nil - } -} - -// AzureEndpoint helper to supply optional endpoint to NewTierAzure -func AzureEndpoint(endpoint string) func(az *TierAzure) error { - return func(az *TierAzure) error { - az.Endpoint = endpoint - return nil - } -} - -// AzureRegion helper to supply optional region to NewTierAzure -func AzureRegion(region string) func(az *TierAzure) error { - return func(az *TierAzure) error { - az.Region = region - return nil - } -} - -// AzureStorageClass helper to supply optional storage class to NewTierAzure -func AzureStorageClass(sc string) func(az *TierAzure) error { - return func(az *TierAzure) error { - az.StorageClass = sc - return nil - } -} - -// NewTierAzure returns a TierConfig of Azure type. Returns error if the given -// parameters are invalid like name is empty etc. -func NewTierAzure(name, accountName, accountKey, bucket string, options ...AzureOptions) (*TierConfig, error) { - if name == "" { - return nil, ErrTierNameEmpty - } - - az := &TierAzure{ - AccountName: accountName, - AccountKey: accountKey, - Bucket: bucket, - // Defaults - Endpoint: "http://blob.core.windows.net", - Prefix: "", - Region: "", - StorageClass: "", - } - - for _, option := range options { - err := option(az) - if err != nil { - return nil, err - } - } - - return &TierConfig{ - Version: TierConfigV1, - Type: Azure, - Name: name, - Azure: az, - }, nil -} diff --git a/pkg/madmin/tier-azure_gen.go b/pkg/madmin/tier-azure_gen.go deleted file mode 100644 index 95a50f2d6..000000000 --- a/pkg/madmin/tier-azure_gen.go +++ /dev/null @@ -1,260 +0,0 @@ -package madmin - -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - -import ( - "github.com/tinylib/msgp/msgp" -) - -// DecodeMsg implements msgp.Decodable -func (z *TierAzure) DecodeMsg(dc *msgp.Reader) (err error) { - var field []byte - _ = field - var zb0001 uint32 - zb0001, err = dc.ReadMapHeader() - if err != nil { - err = msgp.WrapError(err) - return - } - for zb0001 > 0 { - zb0001-- - field, err = dc.ReadMapKeyPtr() - if err != nil { - err = msgp.WrapError(err) - return - } - switch msgp.UnsafeString(field) { - case "Endpoint": - z.Endpoint, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - case "AccountName": - z.AccountName, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "AccountName") - return - } - case "AccountKey": - z.AccountKey, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "AccountKey") - return - } - case "Bucket": - z.Bucket, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - case "Prefix": - z.Prefix, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - case "Region": - z.Region, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - case "StorageClass": - z.StorageClass, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - default: - err = dc.Skip() - if err != nil { - err = msgp.WrapError(err) - return - } - } - } - return -} - -// EncodeMsg implements msgp.Encodable -func (z *TierAzure) EncodeMsg(en *msgp.Writer) (err error) { - // map header, size 7 - // write "Endpoint" - err = en.Append(0x87, 0xa8, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74) - if err != nil { - return - } - err = en.WriteString(z.Endpoint) - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - // write "AccountName" - err = en.Append(0xab, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65) - if err != nil { - return - } - err = en.WriteString(z.AccountName) - if err != nil { - err = msgp.WrapError(err, "AccountName") - return - } - // write "AccountKey" - err = en.Append(0xaa, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4b, 0x65, 0x79) - if err != nil { - return - } - err = en.WriteString(z.AccountKey) - if err != nil { - err = msgp.WrapError(err, "AccountKey") - return - } - // write "Bucket" - err = en.Append(0xa6, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74) - if err != nil { - return - } - err = en.WriteString(z.Bucket) - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - // write "Prefix" - err = en.Append(0xa6, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78) - if err != nil { - return - } - err = en.WriteString(z.Prefix) - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - // write "Region" - err = en.Append(0xa6, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e) - if err != nil { - return - } - err = en.WriteString(z.Region) - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - // write "StorageClass" - err = en.Append(0xac, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73) - if err != nil { - return - } - err = en.WriteString(z.StorageClass) - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - return -} - -// MarshalMsg implements msgp.Marshaler -func (z *TierAzure) MarshalMsg(b []byte) (o []byte, err error) { - o = msgp.Require(b, z.Msgsize()) - // map header, size 7 - // string "Endpoint" - o = append(o, 0x87, 0xa8, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74) - o = msgp.AppendString(o, z.Endpoint) - // string "AccountName" - o = append(o, 0xab, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65) - o = msgp.AppendString(o, z.AccountName) - // string "AccountKey" - o = append(o, 0xaa, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4b, 0x65, 0x79) - o = msgp.AppendString(o, z.AccountKey) - // string "Bucket" - o = append(o, 0xa6, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74) - o = msgp.AppendString(o, z.Bucket) - // string "Prefix" - o = append(o, 0xa6, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78) - o = msgp.AppendString(o, z.Prefix) - // string "Region" - o = append(o, 0xa6, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e) - o = msgp.AppendString(o, z.Region) - // string "StorageClass" - o = append(o, 0xac, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73) - o = msgp.AppendString(o, z.StorageClass) - return -} - -// UnmarshalMsg implements msgp.Unmarshaler -func (z *TierAzure) UnmarshalMsg(bts []byte) (o []byte, err error) { - var field []byte - _ = field - var zb0001 uint32 - zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - for zb0001 > 0 { - zb0001-- - field, bts, err = msgp.ReadMapKeyZC(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - switch msgp.UnsafeString(field) { - case "Endpoint": - z.Endpoint, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - case "AccountName": - z.AccountName, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "AccountName") - return - } - case "AccountKey": - z.AccountKey, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "AccountKey") - return - } - case "Bucket": - z.Bucket, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - case "Prefix": - z.Prefix, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - case "Region": - z.Region, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - case "StorageClass": - z.StorageClass, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - default: - bts, err = msgp.Skip(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - } - } - o = bts - return -} - -// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *TierAzure) Msgsize() (s int) { - s = 1 + 9 + msgp.StringPrefixSize + len(z.Endpoint) + 12 + msgp.StringPrefixSize + len(z.AccountName) + 11 + msgp.StringPrefixSize + len(z.AccountKey) + 7 + msgp.StringPrefixSize + len(z.Bucket) + 7 + msgp.StringPrefixSize + len(z.Prefix) + 7 + msgp.StringPrefixSize + len(z.Region) + 13 + msgp.StringPrefixSize + len(z.StorageClass) - return -} diff --git a/pkg/madmin/tier-azure_gen_test.go b/pkg/madmin/tier-azure_gen_test.go deleted file mode 100644 index 45ddc67ca..000000000 --- a/pkg/madmin/tier-azure_gen_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package madmin - -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - -import ( - "bytes" - "testing" - - "github.com/tinylib/msgp/msgp" -) - -func TestMarshalUnmarshalTierAzure(t *testing.T) { - v := TierAzure{} - bts, err := v.MarshalMsg(nil) - if err != nil { - t.Fatal(err) - } - left, err := v.UnmarshalMsg(bts) - if err != nil { - t.Fatal(err) - } - if len(left) > 0 { - t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) - } - - left, err = msgp.Skip(bts) - if err != nil { - t.Fatal(err) - } - if len(left) > 0 { - t.Errorf("%d bytes left over after Skip(): %q", len(left), left) - } -} - -func BenchmarkMarshalMsgTierAzure(b *testing.B) { - v := TierAzure{} - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.MarshalMsg(nil) - } -} - -func BenchmarkAppendMsgTierAzure(b *testing.B) { - v := TierAzure{} - bts := make([]byte, 0, v.Msgsize()) - bts, _ = v.MarshalMsg(bts[0:0]) - b.SetBytes(int64(len(bts))) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - bts, _ = v.MarshalMsg(bts[0:0]) - } -} - -func BenchmarkUnmarshalTierAzure(b *testing.B) { - v := TierAzure{} - bts, _ := v.MarshalMsg(nil) - b.ReportAllocs() - b.SetBytes(int64(len(bts))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := v.UnmarshalMsg(bts) - if err != nil { - b.Fatal(err) - } - } -} - -func TestEncodeDecodeTierAzure(t *testing.T) { - v := TierAzure{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - - m := v.Msgsize() - if buf.Len() > m { - t.Log("WARNING: TestEncodeDecodeTierAzure Msgsize() is inaccurate") - } - - vn := TierAzure{} - err := msgp.Decode(&buf, &vn) - if err != nil { - t.Error(err) - } - - buf.Reset() - msgp.Encode(&buf, &v) - err = msgp.NewReader(&buf).Skip() - if err != nil { - t.Error(err) - } -} - -func BenchmarkEncodeTierAzure(b *testing.B) { - v := TierAzure{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - b.SetBytes(int64(buf.Len())) - en := msgp.NewWriter(msgp.Nowhere) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.EncodeMsg(en) - } - en.Flush() -} - -func BenchmarkDecodeTierAzure(b *testing.B) { - v := TierAzure{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - b.SetBytes(int64(buf.Len())) - rd := msgp.NewEndlessReader(buf.Bytes(), b) - dc := msgp.NewReader(rd) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - err := v.DecodeMsg(dc) - if err != nil { - b.Fatal(err) - } - } -} diff --git a/pkg/madmin/tier-config.go b/pkg/madmin/tier-config.go deleted file mode 100644 index ed1b9af6f..000000000 --- a/pkg/madmin/tier-config.go +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "encoding/json" - "errors" - "log" -) - -//go:generate msgp -file $GOFILE - -// TierConfigV1 is the supported tier config version -const TierConfigV1 = "v1" - -// TierType enumerates different remote tier backends. -type TierType int - -const ( - // Unsupported refers to remote tier backend that is not supported in this version - Unsupported TierType = iota - // S3 refers to AWS S3 compatible backend - S3 - // Azure refers to Azure Blob Storage - Azure - // GCS refers to Google Cloud Storage - GCS -) - -// String returns the name of tt's remote tier backend. -func (tt TierType) String() string { - switch tt { - case S3: - return "s3" - case Azure: - return "azure" - case GCS: - return "gcs" - } - return "unsupported" -} - -// MarshalJSON returns the canonical json representation of tt. -func (tt TierType) MarshalJSON() ([]byte, error) { - typ := tt.String() - return json.Marshal(typ) -} - -// UnmarshalJSON parses the provided tier type string, failing unmarshal -// if data contains invalid tier type. -func (tt *TierType) UnmarshalJSON(data []byte) error { - var s string - err := json.Unmarshal(data, &s) - if err != nil { - return err - } - - newtt, err := NewTierType(s) - if err != nil { - return err - } - *tt = newtt - return nil -} - -// NewTierType creates TierType if scType is a valid tier type string, otherwise -// returns an error. -func NewTierType(scType string) (TierType, error) { - switch scType { - case S3.String(): - return S3, nil - case Azure.String(): - return Azure, nil - case GCS.String(): - return GCS, nil - } - - return Unsupported, ErrTierTypeUnsupported -} - -// TierConfig represents the different remote tier backend configurations -// supported. The specific backend is identified by the Type field. It has a -// Version field to allow for backwards-compatible extension in the future. -type TierConfig struct { - Version string - Type TierType `json:",omitempty"` - Name string `json:",omitempty"` - S3 *TierS3 `json:",omitempty"` - Azure *TierAzure `json:",omitempty"` - GCS *TierGCS `json:",omitempty"` -} - -var ( - // ErrTierNameEmpty "remote tier name empty" - ErrTierNameEmpty = errors.New("remote tier name empty") - // ErrTierInvalidConfig "invalid tier config" - ErrTierInvalidConfig = errors.New("invalid tier config") - // ErrTierInvalidConfigVersion "invalid tier config version" - ErrTierInvalidConfigVersion = errors.New("invalid tier config version") - // ErrTierTypeUnsupported "unsupported tier type" - ErrTierTypeUnsupported = errors.New("unsupported tier type") -) - -// Clone returns a copy of TierConfig with secret key/credentials redacted. -func (cfg *TierConfig) Clone() TierConfig { - var ( - s3 TierS3 - az TierAzure - gcs TierGCS - ) - switch cfg.Type { - case S3: - s3 = *cfg.S3 - s3.SecretKey = "REDACTED" - case Azure: - az = *cfg.Azure - az.AccountKey = "REDACTED" - case GCS: - gcs = *cfg.GCS - gcs.Creds = "REDACTED" - } - return TierConfig{ - Version: cfg.Version, - Type: cfg.Type, - Name: cfg.Name, - S3: &s3, - Azure: &az, - GCS: &gcs, - } -} - -// UnmarshalJSON unmarshals json value to ensure that Type field is filled in -// correspondence with the tier config supplied. -// See TestUnmarshalTierConfig for an example json. -func (cfg *TierConfig) UnmarshalJSON(b []byte) error { - type tierConfig TierConfig - var m tierConfig - err := json.Unmarshal(b, &m) - if err != nil { - return err - } - - if m.Version != TierConfigV1 { - return ErrTierInvalidConfigVersion - } - - switch m.Type { - case S3: - if m.S3 == nil { - return ErrTierInvalidConfig - } - case Azure: - if m.Azure == nil { - return ErrTierInvalidConfig - } - case GCS: - if m.GCS == nil { - return ErrTierInvalidConfig - } - } - - if m.Name == "" { - return ErrTierNameEmpty - } - - *cfg = TierConfig(m) - return nil -} - -// Endpoint returns the remote tier backend endpoint. -func (cfg *TierConfig) Endpoint() string { - switch cfg.Type { - case S3: - return cfg.S3.Endpoint - case Azure: - return cfg.Azure.Endpoint - case GCS: - return cfg.GCS.Endpoint - } - log.Printf("unexpected tier type %s", cfg.Type) - return "" -} - -// Bucket returns the remote tier backend bucket. -func (cfg *TierConfig) Bucket() string { - switch cfg.Type { - case S3: - return cfg.S3.Bucket - case Azure: - return cfg.Azure.Bucket - case GCS: - return cfg.GCS.Bucket - } - log.Printf("unexpected tier type %s", cfg.Type) - return "" -} - -// Prefix returns the remote tier backend prefix. -func (cfg *TierConfig) Prefix() string { - switch cfg.Type { - case S3: - return cfg.S3.Prefix - case Azure: - return cfg.Azure.Prefix - case GCS: - return cfg.GCS.Prefix - } - log.Printf("unexpected tier type %s", cfg.Type) - return "" -} - -// Region returns the remote tier backend region. -func (cfg *TierConfig) Region() string { - switch cfg.Type { - case S3: - return cfg.S3.Region - case Azure: - return cfg.Azure.Region - case GCS: - return cfg.GCS.Region - } - log.Printf("unexpected tier type %s", cfg.Type) - return "" -} diff --git a/pkg/madmin/tier-config_gen.go b/pkg/madmin/tier-config_gen.go deleted file mode 100644 index e948ae16f..000000000 --- a/pkg/madmin/tier-config_gen.go +++ /dev/null @@ -1,426 +0,0 @@ -package madmin - -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - -import ( - "github.com/tinylib/msgp/msgp" -) - -// DecodeMsg implements msgp.Decodable -func (z *TierConfig) DecodeMsg(dc *msgp.Reader) (err error) { - var field []byte - _ = field - var zb0001 uint32 - zb0001, err = dc.ReadMapHeader() - if err != nil { - err = msgp.WrapError(err) - return - } - for zb0001 > 0 { - zb0001-- - field, err = dc.ReadMapKeyPtr() - if err != nil { - err = msgp.WrapError(err) - return - } - switch msgp.UnsafeString(field) { - case "Version": - z.Version, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Version") - return - } - case "Type": - { - var zb0002 int - zb0002, err = dc.ReadInt() - if err != nil { - err = msgp.WrapError(err, "Type") - return - } - z.Type = TierType(zb0002) - } - case "Name": - z.Name, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Name") - return - } - case "S3": - if dc.IsNil() { - err = dc.ReadNil() - if err != nil { - err = msgp.WrapError(err, "S3") - return - } - z.S3 = nil - } else { - if z.S3 == nil { - z.S3 = new(TierS3) - } - err = z.S3.DecodeMsg(dc) - if err != nil { - err = msgp.WrapError(err, "S3") - return - } - } - case "Azure": - if dc.IsNil() { - err = dc.ReadNil() - if err != nil { - err = msgp.WrapError(err, "Azure") - return - } - z.Azure = nil - } else { - if z.Azure == nil { - z.Azure = new(TierAzure) - } - err = z.Azure.DecodeMsg(dc) - if err != nil { - err = msgp.WrapError(err, "Azure") - return - } - } - case "GCS": - if dc.IsNil() { - err = dc.ReadNil() - if err != nil { - err = msgp.WrapError(err, "GCS") - return - } - z.GCS = nil - } else { - if z.GCS == nil { - z.GCS = new(TierGCS) - } - err = z.GCS.DecodeMsg(dc) - if err != nil { - err = msgp.WrapError(err, "GCS") - return - } - } - default: - err = dc.Skip() - if err != nil { - err = msgp.WrapError(err) - return - } - } - } - return -} - -// EncodeMsg implements msgp.Encodable -func (z *TierConfig) EncodeMsg(en *msgp.Writer) (err error) { - // map header, size 6 - // write "Version" - err = en.Append(0x86, 0xa7, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e) - if err != nil { - return - } - err = en.WriteString(z.Version) - if err != nil { - err = msgp.WrapError(err, "Version") - return - } - // write "Type" - err = en.Append(0xa4, 0x54, 0x79, 0x70, 0x65) - if err != nil { - return - } - err = en.WriteInt(int(z.Type)) - if err != nil { - err = msgp.WrapError(err, "Type") - return - } - // write "Name" - err = en.Append(0xa4, 0x4e, 0x61, 0x6d, 0x65) - if err != nil { - return - } - err = en.WriteString(z.Name) - if err != nil { - err = msgp.WrapError(err, "Name") - return - } - // write "S3" - err = en.Append(0xa2, 0x53, 0x33) - if err != nil { - return - } - if z.S3 == nil { - err = en.WriteNil() - if err != nil { - return - } - } else { - err = z.S3.EncodeMsg(en) - if err != nil { - err = msgp.WrapError(err, "S3") - return - } - } - // write "Azure" - err = en.Append(0xa5, 0x41, 0x7a, 0x75, 0x72, 0x65) - if err != nil { - return - } - if z.Azure == nil { - err = en.WriteNil() - if err != nil { - return - } - } else { - err = z.Azure.EncodeMsg(en) - if err != nil { - err = msgp.WrapError(err, "Azure") - return - } - } - // write "GCS" - err = en.Append(0xa3, 0x47, 0x43, 0x53) - if err != nil { - return - } - if z.GCS == nil { - err = en.WriteNil() - if err != nil { - return - } - } else { - err = z.GCS.EncodeMsg(en) - if err != nil { - err = msgp.WrapError(err, "GCS") - return - } - } - return -} - -// MarshalMsg implements msgp.Marshaler -func (z *TierConfig) MarshalMsg(b []byte) (o []byte, err error) { - o = msgp.Require(b, z.Msgsize()) - // map header, size 6 - // string "Version" - o = append(o, 0x86, 0xa7, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e) - o = msgp.AppendString(o, z.Version) - // string "Type" - o = append(o, 0xa4, 0x54, 0x79, 0x70, 0x65) - o = msgp.AppendInt(o, int(z.Type)) - // string "Name" - o = append(o, 0xa4, 0x4e, 0x61, 0x6d, 0x65) - o = msgp.AppendString(o, z.Name) - // string "S3" - o = append(o, 0xa2, 0x53, 0x33) - if z.S3 == nil { - o = msgp.AppendNil(o) - } else { - o, err = z.S3.MarshalMsg(o) - if err != nil { - err = msgp.WrapError(err, "S3") - return - } - } - // string "Azure" - o = append(o, 0xa5, 0x41, 0x7a, 0x75, 0x72, 0x65) - if z.Azure == nil { - o = msgp.AppendNil(o) - } else { - o, err = z.Azure.MarshalMsg(o) - if err != nil { - err = msgp.WrapError(err, "Azure") - return - } - } - // string "GCS" - o = append(o, 0xa3, 0x47, 0x43, 0x53) - if z.GCS == nil { - o = msgp.AppendNil(o) - } else { - o, err = z.GCS.MarshalMsg(o) - if err != nil { - err = msgp.WrapError(err, "GCS") - return - } - } - return -} - -// UnmarshalMsg implements msgp.Unmarshaler -func (z *TierConfig) UnmarshalMsg(bts []byte) (o []byte, err error) { - var field []byte - _ = field - var zb0001 uint32 - zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - for zb0001 > 0 { - zb0001-- - field, bts, err = msgp.ReadMapKeyZC(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - switch msgp.UnsafeString(field) { - case "Version": - z.Version, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Version") - return - } - case "Type": - { - var zb0002 int - zb0002, bts, err = msgp.ReadIntBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Type") - return - } - z.Type = TierType(zb0002) - } - case "Name": - z.Name, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Name") - return - } - case "S3": - if msgp.IsNil(bts) { - bts, err = msgp.ReadNilBytes(bts) - if err != nil { - return - } - z.S3 = nil - } else { - if z.S3 == nil { - z.S3 = new(TierS3) - } - bts, err = z.S3.UnmarshalMsg(bts) - if err != nil { - err = msgp.WrapError(err, "S3") - return - } - } - case "Azure": - if msgp.IsNil(bts) { - bts, err = msgp.ReadNilBytes(bts) - if err != nil { - return - } - z.Azure = nil - } else { - if z.Azure == nil { - z.Azure = new(TierAzure) - } - bts, err = z.Azure.UnmarshalMsg(bts) - if err != nil { - err = msgp.WrapError(err, "Azure") - return - } - } - case "GCS": - if msgp.IsNil(bts) { - bts, err = msgp.ReadNilBytes(bts) - if err != nil { - return - } - z.GCS = nil - } else { - if z.GCS == nil { - z.GCS = new(TierGCS) - } - bts, err = z.GCS.UnmarshalMsg(bts) - if err != nil { - err = msgp.WrapError(err, "GCS") - return - } - } - default: - bts, err = msgp.Skip(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - } - } - o = bts - return -} - -// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *TierConfig) Msgsize() (s int) { - s = 1 + 8 + msgp.StringPrefixSize + len(z.Version) + 5 + msgp.IntSize + 5 + msgp.StringPrefixSize + len(z.Name) + 3 - if z.S3 == nil { - s += msgp.NilSize - } else { - s += z.S3.Msgsize() - } - s += 6 - if z.Azure == nil { - s += msgp.NilSize - } else { - s += z.Azure.Msgsize() - } - s += 4 - if z.GCS == nil { - s += msgp.NilSize - } else { - s += z.GCS.Msgsize() - } - return -} - -// DecodeMsg implements msgp.Decodable -func (z *TierType) DecodeMsg(dc *msgp.Reader) (err error) { - { - var zb0001 int - zb0001, err = dc.ReadInt() - if err != nil { - err = msgp.WrapError(err) - return - } - (*z) = TierType(zb0001) - } - return -} - -// EncodeMsg implements msgp.Encodable -func (z TierType) EncodeMsg(en *msgp.Writer) (err error) { - err = en.WriteInt(int(z)) - if err != nil { - err = msgp.WrapError(err) - return - } - return -} - -// MarshalMsg implements msgp.Marshaler -func (z TierType) MarshalMsg(b []byte) (o []byte, err error) { - o = msgp.Require(b, z.Msgsize()) - o = msgp.AppendInt(o, int(z)) - return -} - -// UnmarshalMsg implements msgp.Unmarshaler -func (z *TierType) UnmarshalMsg(bts []byte) (o []byte, err error) { - { - var zb0001 int - zb0001, bts, err = msgp.ReadIntBytes(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - (*z) = TierType(zb0001) - } - o = bts - return -} - -// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z TierType) Msgsize() (s int) { - s = msgp.IntSize - return -} diff --git a/pkg/madmin/tier-config_gen_test.go b/pkg/madmin/tier-config_gen_test.go deleted file mode 100644 index 9d4177828..000000000 --- a/pkg/madmin/tier-config_gen_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package madmin - -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - -import ( - "bytes" - "testing" - - "github.com/tinylib/msgp/msgp" -) - -func TestMarshalUnmarshalTierConfig(t *testing.T) { - v := TierConfig{} - bts, err := v.MarshalMsg(nil) - if err != nil { - t.Fatal(err) - } - left, err := v.UnmarshalMsg(bts) - if err != nil { - t.Fatal(err) - } - if len(left) > 0 { - t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) - } - - left, err = msgp.Skip(bts) - if err != nil { - t.Fatal(err) - } - if len(left) > 0 { - t.Errorf("%d bytes left over after Skip(): %q", len(left), left) - } -} - -func BenchmarkMarshalMsgTierConfig(b *testing.B) { - v := TierConfig{} - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.MarshalMsg(nil) - } -} - -func BenchmarkAppendMsgTierConfig(b *testing.B) { - v := TierConfig{} - bts := make([]byte, 0, v.Msgsize()) - bts, _ = v.MarshalMsg(bts[0:0]) - b.SetBytes(int64(len(bts))) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - bts, _ = v.MarshalMsg(bts[0:0]) - } -} - -func BenchmarkUnmarshalTierConfig(b *testing.B) { - v := TierConfig{} - bts, _ := v.MarshalMsg(nil) - b.ReportAllocs() - b.SetBytes(int64(len(bts))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := v.UnmarshalMsg(bts) - if err != nil { - b.Fatal(err) - } - } -} - -func TestEncodeDecodeTierConfig(t *testing.T) { - v := TierConfig{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - - m := v.Msgsize() - if buf.Len() > m { - t.Log("WARNING: TestEncodeDecodeTierConfig Msgsize() is inaccurate") - } - - vn := TierConfig{} - err := msgp.Decode(&buf, &vn) - if err != nil { - t.Error(err) - } - - buf.Reset() - msgp.Encode(&buf, &v) - err = msgp.NewReader(&buf).Skip() - if err != nil { - t.Error(err) - } -} - -func BenchmarkEncodeTierConfig(b *testing.B) { - v := TierConfig{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - b.SetBytes(int64(buf.Len())) - en := msgp.NewWriter(msgp.Nowhere) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.EncodeMsg(en) - } - en.Flush() -} - -func BenchmarkDecodeTierConfig(b *testing.B) { - v := TierConfig{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - b.SetBytes(int64(buf.Len())) - rd := msgp.NewEndlessReader(buf.Bytes(), b) - dc := msgp.NewReader(rd) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - err := v.DecodeMsg(dc) - if err != nil { - b.Fatal(err) - } - } -} diff --git a/pkg/madmin/tier-config_test.go b/pkg/madmin/tier-config_test.go deleted file mode 100644 index e228c1257..000000000 --- a/pkg/madmin/tier-config_test.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "encoding/json" - "testing" -) - -// TestUnmarshalInvalidTierConfig tests that TierConfig parsing can catch invalid tier configs -func TestUnmarshalInvalidTierConfig(t *testing.T) { - testCases := []struct { - cfg TierConfig - err error - }{ - { - cfg: TierConfig{ - Version: TierConfigV1, - Name: "S3TIER?", - Type: S3, - GCS: &TierGCS{ - Creds: "VWJ1bnR1IDIwLjA0LjEgTFRTIFxuIFxsCgo", - Bucket: "ilmtesting", - Endpoint: "https://storage.googleapis.com/", - Prefix: "testprefix", - Region: "us-west-2", - StorageClass: "", - }, - }, - err: ErrTierInvalidConfig, - }, - { - cfg: TierConfig{ - Version: "invalid-version", - Name: "INVALIDTIER", - Type: GCS, - GCS: &TierGCS{ - Creds: "VWJ1bnR1IDIwLjA0LjEgTFRTIFxuIFxsCgo", - Bucket: "ilmtesting", - Endpoint: "https://storage.googleapis.com/", - Prefix: "testprefix", - Region: "us-west-2", - StorageClass: "", - }, - }, - err: ErrTierInvalidConfigVersion, - }, - { - cfg: TierConfig{ - Version: TierConfigV1, - Type: GCS, - GCS: &TierGCS{ - Creds: "VWJ1bnR1IDIwLjA0LjEgTFRTIFxuIFxsCgo", - Bucket: "ilmtesting", - Endpoint: "https://storage.googleapis.com/", - Prefix: "testprefix", - Region: "us-west-2", - StorageClass: "", - }, - }, - err: ErrTierNameEmpty, - }, - { - cfg: TierConfig{ - Version: TierConfigV1, - Name: "GCSTIER", - Type: GCS, - GCS: &TierGCS{ - Creds: "VWJ1bnR1IDIwLjA0LjEgTFRTIFxuIFxsCgo", - Bucket: "ilmtesting", - Endpoint: "https://storage.googleapis.com/", - Prefix: "testprefix", - Region: "us-west-2", - StorageClass: "", - }, - }, - err: nil, - }, - } - for i, tc := range testCases { - data, err := json.Marshal(tc.cfg) - if err != nil { - t.Fatalf("Test %d: Failed to marshal tier config %v: %v", i+1, tc.cfg, err) - } - var cfg TierConfig - err = json.Unmarshal(data, &cfg) - if err != tc.err { - t.Fatalf("Test %d: Failed in unmarshal tier config %s: expected %v got %v", i+1, data, tc.err, err) - } - } - - // Test invalid tier type - evilJSON := []byte(`{ - "Version": "v1", - "Type" : "not-a-type", - "Name" : "GCSTIER3", - "GCS" : { - "Bucket" : "ilmtesting", - "Prefix" : "testprefix3", - "Endpoint" : "https://storage.googleapis.com/", - "Creds": "VWJ1bnR1IDIwLjA0LjEgTFRTIFxuIFxsCgo", - "Region" : "us-west-2", - "StorageClass" : "" - } - }`) - var cfg TierConfig - err := json.Unmarshal(evilJSON, &cfg) - if err != ErrTierTypeUnsupported { - t.Fatalf("Expected to fail with unsupported type but got %v", err) - } -} diff --git a/pkg/madmin/tier-gcs.go b/pkg/madmin/tier-gcs.go deleted file mode 100644 index b9a59f2ef..000000000 --- a/pkg/madmin/tier-gcs.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "encoding/base64" -) - -//go:generate msgp -file $GOFILE - -// TierGCS represents the remote tier configuration for Google Cloud Storage -type TierGCS struct { - Endpoint string `json:",omitempty"` // custom endpoint is not supported for GCS - Creds string `json:",omitempty"` // base64 encoding of credentials.json - Bucket string `json:",omitempty"` - Prefix string `json:",omitempty"` - Region string `json:",omitempty"` - StorageClass string `json:",omitempty"` -} - -// GCSOptions supports NewTierGCS to take variadic options -type GCSOptions func(*TierGCS) error - -// GCSPrefix helper to supply optional object prefix to NewTierGCS -func GCSPrefix(prefix string) func(*TierGCS) error { - return func(gcs *TierGCS) error { - gcs.Prefix = prefix - return nil - } -} - -// GCSRegion helper to supply optional region to NewTierGCS -func GCSRegion(region string) func(*TierGCS) error { - return func(gcs *TierGCS) error { - gcs.Region = region - return nil - } -} - -// GCSStorageClass helper to supply optional storage class to NewTierGCS -func GCSStorageClass(sc string) func(*TierGCS) error { - return func(gcs *TierGCS) error { - gcs.StorageClass = sc - return nil - } -} - -// GetCredentialJSON method returns the credentials JSON bytes. -func (gcs *TierGCS) GetCredentialJSON() ([]byte, error) { - return base64.URLEncoding.DecodeString(gcs.Creds) -} - -// NewTierGCS returns a TierConfig of GCS type. Returns error if the given -// parameters are invalid like name is empty etc. -func NewTierGCS(name string, credsJSON []byte, bucket string, options ...GCSOptions) (*TierConfig, error) { - if name == "" { - return nil, ErrTierNameEmpty - } - creds := base64.URLEncoding.EncodeToString(credsJSON) - gcs := &TierGCS{ - Creds: creds, - Bucket: bucket, - // Defaults - // endpoint is meant only for client-side display purposes - Endpoint: "https://storage.googleapis.com/", - Prefix: "", - Region: "", - StorageClass: "", - } - - for _, option := range options { - err := option(gcs) - if err != nil { - return nil, err - } - } - - return &TierConfig{ - Version: TierConfigV1, - Type: GCS, - Name: name, - GCS: gcs, - }, nil -} diff --git a/pkg/madmin/tier-gcs_gen.go b/pkg/madmin/tier-gcs_gen.go deleted file mode 100644 index 9a11f4e78..000000000 --- a/pkg/madmin/tier-gcs_gen.go +++ /dev/null @@ -1,235 +0,0 @@ -package madmin - -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - -import ( - "github.com/tinylib/msgp/msgp" -) - -// DecodeMsg implements msgp.Decodable -func (z *TierGCS) DecodeMsg(dc *msgp.Reader) (err error) { - var field []byte - _ = field - var zb0001 uint32 - zb0001, err = dc.ReadMapHeader() - if err != nil { - err = msgp.WrapError(err) - return - } - for zb0001 > 0 { - zb0001-- - field, err = dc.ReadMapKeyPtr() - if err != nil { - err = msgp.WrapError(err) - return - } - switch msgp.UnsafeString(field) { - case "Endpoint": - z.Endpoint, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - case "Creds": - z.Creds, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Creds") - return - } - case "Bucket": - z.Bucket, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - case "Prefix": - z.Prefix, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - case "Region": - z.Region, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - case "StorageClass": - z.StorageClass, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - default: - err = dc.Skip() - if err != nil { - err = msgp.WrapError(err) - return - } - } - } - return -} - -// EncodeMsg implements msgp.Encodable -func (z *TierGCS) EncodeMsg(en *msgp.Writer) (err error) { - // map header, size 6 - // write "Endpoint" - err = en.Append(0x86, 0xa8, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74) - if err != nil { - return - } - err = en.WriteString(z.Endpoint) - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - // write "Creds" - err = en.Append(0xa5, 0x43, 0x72, 0x65, 0x64, 0x73) - if err != nil { - return - } - err = en.WriteString(z.Creds) - if err != nil { - err = msgp.WrapError(err, "Creds") - return - } - // write "Bucket" - err = en.Append(0xa6, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74) - if err != nil { - return - } - err = en.WriteString(z.Bucket) - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - // write "Prefix" - err = en.Append(0xa6, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78) - if err != nil { - return - } - err = en.WriteString(z.Prefix) - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - // write "Region" - err = en.Append(0xa6, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e) - if err != nil { - return - } - err = en.WriteString(z.Region) - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - // write "StorageClass" - err = en.Append(0xac, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73) - if err != nil { - return - } - err = en.WriteString(z.StorageClass) - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - return -} - -// MarshalMsg implements msgp.Marshaler -func (z *TierGCS) MarshalMsg(b []byte) (o []byte, err error) { - o = msgp.Require(b, z.Msgsize()) - // map header, size 6 - // string "Endpoint" - o = append(o, 0x86, 0xa8, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74) - o = msgp.AppendString(o, z.Endpoint) - // string "Creds" - o = append(o, 0xa5, 0x43, 0x72, 0x65, 0x64, 0x73) - o = msgp.AppendString(o, z.Creds) - // string "Bucket" - o = append(o, 0xa6, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74) - o = msgp.AppendString(o, z.Bucket) - // string "Prefix" - o = append(o, 0xa6, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78) - o = msgp.AppendString(o, z.Prefix) - // string "Region" - o = append(o, 0xa6, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e) - o = msgp.AppendString(o, z.Region) - // string "StorageClass" - o = append(o, 0xac, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73) - o = msgp.AppendString(o, z.StorageClass) - return -} - -// UnmarshalMsg implements msgp.Unmarshaler -func (z *TierGCS) UnmarshalMsg(bts []byte) (o []byte, err error) { - var field []byte - _ = field - var zb0001 uint32 - zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - for zb0001 > 0 { - zb0001-- - field, bts, err = msgp.ReadMapKeyZC(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - switch msgp.UnsafeString(field) { - case "Endpoint": - z.Endpoint, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - case "Creds": - z.Creds, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Creds") - return - } - case "Bucket": - z.Bucket, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - case "Prefix": - z.Prefix, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - case "Region": - z.Region, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - case "StorageClass": - z.StorageClass, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - default: - bts, err = msgp.Skip(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - } - } - o = bts - return -} - -// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *TierGCS) Msgsize() (s int) { - s = 1 + 9 + msgp.StringPrefixSize + len(z.Endpoint) + 6 + msgp.StringPrefixSize + len(z.Creds) + 7 + msgp.StringPrefixSize + len(z.Bucket) + 7 + msgp.StringPrefixSize + len(z.Prefix) + 7 + msgp.StringPrefixSize + len(z.Region) + 13 + msgp.StringPrefixSize + len(z.StorageClass) - return -} diff --git a/pkg/madmin/tier-gcs_gen_test.go b/pkg/madmin/tier-gcs_gen_test.go deleted file mode 100644 index ff69ec4e2..000000000 --- a/pkg/madmin/tier-gcs_gen_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package madmin - -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - -import ( - "bytes" - "testing" - - "github.com/tinylib/msgp/msgp" -) - -func TestMarshalUnmarshalTierGCS(t *testing.T) { - v := TierGCS{} - bts, err := v.MarshalMsg(nil) - if err != nil { - t.Fatal(err) - } - left, err := v.UnmarshalMsg(bts) - if err != nil { - t.Fatal(err) - } - if len(left) > 0 { - t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) - } - - left, err = msgp.Skip(bts) - if err != nil { - t.Fatal(err) - } - if len(left) > 0 { - t.Errorf("%d bytes left over after Skip(): %q", len(left), left) - } -} - -func BenchmarkMarshalMsgTierGCS(b *testing.B) { - v := TierGCS{} - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.MarshalMsg(nil) - } -} - -func BenchmarkAppendMsgTierGCS(b *testing.B) { - v := TierGCS{} - bts := make([]byte, 0, v.Msgsize()) - bts, _ = v.MarshalMsg(bts[0:0]) - b.SetBytes(int64(len(bts))) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - bts, _ = v.MarshalMsg(bts[0:0]) - } -} - -func BenchmarkUnmarshalTierGCS(b *testing.B) { - v := TierGCS{} - bts, _ := v.MarshalMsg(nil) - b.ReportAllocs() - b.SetBytes(int64(len(bts))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := v.UnmarshalMsg(bts) - if err != nil { - b.Fatal(err) - } - } -} - -func TestEncodeDecodeTierGCS(t *testing.T) { - v := TierGCS{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - - m := v.Msgsize() - if buf.Len() > m { - t.Log("WARNING: TestEncodeDecodeTierGCS Msgsize() is inaccurate") - } - - vn := TierGCS{} - err := msgp.Decode(&buf, &vn) - if err != nil { - t.Error(err) - } - - buf.Reset() - msgp.Encode(&buf, &v) - err = msgp.NewReader(&buf).Skip() - if err != nil { - t.Error(err) - } -} - -func BenchmarkEncodeTierGCS(b *testing.B) { - v := TierGCS{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - b.SetBytes(int64(buf.Len())) - en := msgp.NewWriter(msgp.Nowhere) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.EncodeMsg(en) - } - en.Flush() -} - -func BenchmarkDecodeTierGCS(b *testing.B) { - v := TierGCS{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - b.SetBytes(int64(buf.Len())) - rd := msgp.NewEndlessReader(buf.Bytes(), b) - dc := msgp.NewReader(rd) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - err := v.DecodeMsg(dc) - if err != nil { - b.Fatal(err) - } - } -} diff --git a/pkg/madmin/tier-s3.go b/pkg/madmin/tier-s3.go deleted file mode 100644 index 5038d4e8c..000000000 --- a/pkg/madmin/tier-s3.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -//go:generate msgp -file $GOFILE - -// TierS3 represents the remote tier configuration for AWS S3 compatible backend. -type TierS3 struct { - Endpoint string `json:",omitempty"` - AccessKey string `json:",omitempty"` - SecretKey string `json:",omitempty"` - Bucket string `json:",omitempty"` - Prefix string `json:",omitempty"` - Region string `json:",omitempty"` - StorageClass string `json:",omitempty"` -} - -// S3Options supports NewTierS3 to take variadic options -type S3Options func(*TierS3) error - -// S3Region helper to supply optional region to NewTierS3 -func S3Region(region string) func(s3 *TierS3) error { - return func(s3 *TierS3) error { - s3.Region = region - return nil - } -} - -// S3Prefix helper to supply optional object prefix to NewTierS3 -func S3Prefix(prefix string) func(s3 *TierS3) error { - return func(s3 *TierS3) error { - s3.Prefix = prefix - return nil - } -} - -// S3Endpoint helper to supply optional endpoint to NewTierS3 -func S3Endpoint(endpoint string) func(s3 *TierS3) error { - return func(s3 *TierS3) error { - s3.Endpoint = endpoint - return nil - } -} - -// S3StorageClass helper to supply optional storage class to NewTierS3 -func S3StorageClass(storageClass string) func(s3 *TierS3) error { - return func(s3 *TierS3) error { - s3.StorageClass = storageClass - return nil - } -} - -// NewTierS3 returns a TierConfig of S3 type. Returns error if the given -// parameters are invalid like name is empty etc. -func NewTierS3(name, accessKey, secretKey, bucket string, options ...S3Options) (*TierConfig, error) { - if name == "" { - return nil, ErrTierNameEmpty - } - sc := &TierS3{ - AccessKey: accessKey, - SecretKey: secretKey, - Bucket: bucket, - // Defaults - Endpoint: "https://s3.amazonaws.com", - Region: "", - StorageClass: "", - } - - for _, option := range options { - err := option(sc) - if err != nil { - return nil, err - } - } - - return &TierConfig{ - Version: TierConfigV1, - Type: S3, - Name: name, - S3: sc, - }, nil -} diff --git a/pkg/madmin/tier-s3_gen.go b/pkg/madmin/tier-s3_gen.go deleted file mode 100644 index 425bf8f34..000000000 --- a/pkg/madmin/tier-s3_gen.go +++ /dev/null @@ -1,260 +0,0 @@ -package madmin - -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - -import ( - "github.com/tinylib/msgp/msgp" -) - -// DecodeMsg implements msgp.Decodable -func (z *TierS3) DecodeMsg(dc *msgp.Reader) (err error) { - var field []byte - _ = field - var zb0001 uint32 - zb0001, err = dc.ReadMapHeader() - if err != nil { - err = msgp.WrapError(err) - return - } - for zb0001 > 0 { - zb0001-- - field, err = dc.ReadMapKeyPtr() - if err != nil { - err = msgp.WrapError(err) - return - } - switch msgp.UnsafeString(field) { - case "Endpoint": - z.Endpoint, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - case "AccessKey": - z.AccessKey, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "AccessKey") - return - } - case "SecretKey": - z.SecretKey, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "SecretKey") - return - } - case "Bucket": - z.Bucket, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - case "Prefix": - z.Prefix, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - case "Region": - z.Region, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - case "StorageClass": - z.StorageClass, err = dc.ReadString() - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - default: - err = dc.Skip() - if err != nil { - err = msgp.WrapError(err) - return - } - } - } - return -} - -// EncodeMsg implements msgp.Encodable -func (z *TierS3) EncodeMsg(en *msgp.Writer) (err error) { - // map header, size 7 - // write "Endpoint" - err = en.Append(0x87, 0xa8, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74) - if err != nil { - return - } - err = en.WriteString(z.Endpoint) - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - // write "AccessKey" - err = en.Append(0xa9, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79) - if err != nil { - return - } - err = en.WriteString(z.AccessKey) - if err != nil { - err = msgp.WrapError(err, "AccessKey") - return - } - // write "SecretKey" - err = en.Append(0xa9, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79) - if err != nil { - return - } - err = en.WriteString(z.SecretKey) - if err != nil { - err = msgp.WrapError(err, "SecretKey") - return - } - // write "Bucket" - err = en.Append(0xa6, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74) - if err != nil { - return - } - err = en.WriteString(z.Bucket) - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - // write "Prefix" - err = en.Append(0xa6, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78) - if err != nil { - return - } - err = en.WriteString(z.Prefix) - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - // write "Region" - err = en.Append(0xa6, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e) - if err != nil { - return - } - err = en.WriteString(z.Region) - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - // write "StorageClass" - err = en.Append(0xac, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73) - if err != nil { - return - } - err = en.WriteString(z.StorageClass) - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - return -} - -// MarshalMsg implements msgp.Marshaler -func (z *TierS3) MarshalMsg(b []byte) (o []byte, err error) { - o = msgp.Require(b, z.Msgsize()) - // map header, size 7 - // string "Endpoint" - o = append(o, 0x87, 0xa8, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74) - o = msgp.AppendString(o, z.Endpoint) - // string "AccessKey" - o = append(o, 0xa9, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79) - o = msgp.AppendString(o, z.AccessKey) - // string "SecretKey" - o = append(o, 0xa9, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79) - o = msgp.AppendString(o, z.SecretKey) - // string "Bucket" - o = append(o, 0xa6, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74) - o = msgp.AppendString(o, z.Bucket) - // string "Prefix" - o = append(o, 0xa6, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78) - o = msgp.AppendString(o, z.Prefix) - // string "Region" - o = append(o, 0xa6, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e) - o = msgp.AppendString(o, z.Region) - // string "StorageClass" - o = append(o, 0xac, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73) - o = msgp.AppendString(o, z.StorageClass) - return -} - -// UnmarshalMsg implements msgp.Unmarshaler -func (z *TierS3) UnmarshalMsg(bts []byte) (o []byte, err error) { - var field []byte - _ = field - var zb0001 uint32 - zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - for zb0001 > 0 { - zb0001-- - field, bts, err = msgp.ReadMapKeyZC(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - switch msgp.UnsafeString(field) { - case "Endpoint": - z.Endpoint, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Endpoint") - return - } - case "AccessKey": - z.AccessKey, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "AccessKey") - return - } - case "SecretKey": - z.SecretKey, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "SecretKey") - return - } - case "Bucket": - z.Bucket, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Bucket") - return - } - case "Prefix": - z.Prefix, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Prefix") - return - } - case "Region": - z.Region, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "Region") - return - } - case "StorageClass": - z.StorageClass, bts, err = msgp.ReadStringBytes(bts) - if err != nil { - err = msgp.WrapError(err, "StorageClass") - return - } - default: - bts, err = msgp.Skip(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - } - } - o = bts - return -} - -// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z *TierS3) Msgsize() (s int) { - s = 1 + 9 + msgp.StringPrefixSize + len(z.Endpoint) + 10 + msgp.StringPrefixSize + len(z.AccessKey) + 10 + msgp.StringPrefixSize + len(z.SecretKey) + 7 + msgp.StringPrefixSize + len(z.Bucket) + 7 + msgp.StringPrefixSize + len(z.Prefix) + 7 + msgp.StringPrefixSize + len(z.Region) + 13 + msgp.StringPrefixSize + len(z.StorageClass) - return -} diff --git a/pkg/madmin/tier-s3_gen_test.go b/pkg/madmin/tier-s3_gen_test.go deleted file mode 100644 index 09457dfe1..000000000 --- a/pkg/madmin/tier-s3_gen_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package madmin - -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - -import ( - "bytes" - "testing" - - "github.com/tinylib/msgp/msgp" -) - -func TestMarshalUnmarshalTierS3(t *testing.T) { - v := TierS3{} - bts, err := v.MarshalMsg(nil) - if err != nil { - t.Fatal(err) - } - left, err := v.UnmarshalMsg(bts) - if err != nil { - t.Fatal(err) - } - if len(left) > 0 { - t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) - } - - left, err = msgp.Skip(bts) - if err != nil { - t.Fatal(err) - } - if len(left) > 0 { - t.Errorf("%d bytes left over after Skip(): %q", len(left), left) - } -} - -func BenchmarkMarshalMsgTierS3(b *testing.B) { - v := TierS3{} - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.MarshalMsg(nil) - } -} - -func BenchmarkAppendMsgTierS3(b *testing.B) { - v := TierS3{} - bts := make([]byte, 0, v.Msgsize()) - bts, _ = v.MarshalMsg(bts[0:0]) - b.SetBytes(int64(len(bts))) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - bts, _ = v.MarshalMsg(bts[0:0]) - } -} - -func BenchmarkUnmarshalTierS3(b *testing.B) { - v := TierS3{} - bts, _ := v.MarshalMsg(nil) - b.ReportAllocs() - b.SetBytes(int64(len(bts))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := v.UnmarshalMsg(bts) - if err != nil { - b.Fatal(err) - } - } -} - -func TestEncodeDecodeTierS3(t *testing.T) { - v := TierS3{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - - m := v.Msgsize() - if buf.Len() > m { - t.Log("WARNING: TestEncodeDecodeTierS3 Msgsize() is inaccurate") - } - - vn := TierS3{} - err := msgp.Decode(&buf, &vn) - if err != nil { - t.Error(err) - } - - buf.Reset() - msgp.Encode(&buf, &v) - err = msgp.NewReader(&buf).Skip() - if err != nil { - t.Error(err) - } -} - -func BenchmarkEncodeTierS3(b *testing.B) { - v := TierS3{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - b.SetBytes(int64(buf.Len())) - en := msgp.NewWriter(msgp.Nowhere) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - v.EncodeMsg(en) - } - en.Flush() -} - -func BenchmarkDecodeTierS3(b *testing.B) { - v := TierS3{} - var buf bytes.Buffer - msgp.Encode(&buf, &v) - b.SetBytes(int64(buf.Len())) - rd := msgp.NewEndlessReader(buf.Bytes(), b) - dc := msgp.NewReader(rd) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - err := v.DecodeMsg(dc) - if err != nil { - b.Fatal(err) - } - } -} diff --git a/pkg/madmin/tier.go b/pkg/madmin/tier.go deleted file mode 100644 index f5deae5d3..000000000 --- a/pkg/madmin/tier.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "io/ioutil" - "net/http" - "path" -) - -// tierAPI is API path prefix for tier related admin APIs -const tierAPI = "tier" - -// AddTier adds a new remote tier. -func (adm *AdminClient) AddTier(ctx context.Context, cfg *TierConfig) error { - data, err := json.Marshal(cfg) - if err != nil { - return err - } - - encData, err := EncryptData(adm.getSecretKey(), data) - if err != nil { - return err - } - - reqData := requestData{ - relPath: path.Join(adminAPIPrefix, tierAPI), - content: encData, - } - - // Execute PUT on /minio/admin/v3/tier to add a remote tier - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusNoContent { - return httpRespToErrorResponse(resp) - } - return nil -} - -// ListTiers returns a list of remote tiers configured. -func (adm *AdminClient) ListTiers(ctx context.Context) ([]*TierConfig, error) { - reqData := requestData{ - relPath: path.Join(adminAPIPrefix, tierAPI), - } - - // Execute GET on /minio/admin/v3/tier to list remote tiers configured. - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - var tiers []*TierConfig - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return tiers, err - } - - err = json.Unmarshal(b, &tiers) - if err != nil { - return tiers, err - } - - return tiers, nil -} - -// TierCreds is used to pass remote tier credentials in a tier-edit operation. -type TierCreds struct { - AccessKey string `json:"access,omitempty"` - SecretKey string `json:"secret,omitempty"` - CredsJSON []byte `json:"creds,omitempty"` -} - -// EditTier supports updating credentials for the remote tier identified by tierName. -func (adm *AdminClient) EditTier(ctx context.Context, tierName string, creds TierCreds) error { - data, err := json.Marshal(creds) - if err != nil { - return err - } - - var encData []byte - encData, err = EncryptData(adm.getSecretKey(), data) - if err != nil { - return err - } - - reqData := requestData{ - relPath: path.Join(adminAPIPrefix, tierAPI, tierName), - content: encData, - } - - // Execute POST on /minio/admin/v3/tier/tierName" to edit a tier - // configured. - resp, err := adm.executeMethod(ctx, http.MethodPost, reqData) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusNoContent { - return httpRespToErrorResponse(resp) - } - - return nil -} diff --git a/pkg/madmin/tier_test.go b/pkg/madmin/tier_test.go deleted file mode 100644 index eb9e8a008..000000000 --- a/pkg/madmin/tier_test.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "encoding/base64" - "fmt" - "log" - - "reflect" - "testing" -) - -func ExampleNewTierS3() { - simpleS3SC, err := NewTierS3("simple-s3", "accessKey", "secretKey", "testbucket") - if err != nil { - log.Fatalln(err, "Failed to create s3 backed tier") - } - fmt.Println(simpleS3SC) - - fullyCustomS3SC, err := NewTierS3("custom-s3", "accessKey", "secretKey", "testbucket", - S3Endpoint("https://s3.amazonaws.com"), S3Prefix("testprefix"), S3Region("us-west-1"), S3StorageClass("S3_IA")) - if err != nil { - log.Fatalln(err, "Failed to create s3 tier") - } - fmt.Println(fullyCustomS3SC) -} - -func ExampleNewTierAzure() { - simpleAzSC, err := NewTierAzure("simple-az", "accessKey", "secretKey", "testbucket") - if err != nil { - log.Fatalln(err, "Failed to create azure backed tier") - } - fmt.Println(simpleAzSC) - - fullyCustomAzSC, err := NewTierAzure("custom-az", "accessKey", "secretKey", "testbucket", AzureEndpoint("http://blob.core.windows.net"), AzurePrefix("testprefix")) - if err != nil { - log.Fatalln(err, "Failed to create azure backed tier") - } - fmt.Println(fullyCustomAzSC) -} - -func ExampleNewTierGCS() { - credsJSON := []byte("credentials json content goes here") - simpleGCSSC, err := NewTierGCS("simple-gcs", credsJSON, "testbucket") - if err != nil { - log.Fatalln(err, "Failed to create GCS backed tier") - } - fmt.Println(simpleGCSSC) - - fullyCustomGCSSC, err := NewTierGCS("custom-gcs", credsJSON, "testbucket", GCSPrefix("testprefix")) - if err != nil { - log.Fatalln(err, "Failed to create GCS backed tier") - } - fmt.Println(fullyCustomGCSSC) -} - -// TestS3Tier tests S3Options helpers -func TestS3Tier(t *testing.T) { - scName := "test-s3" - endpoint := "https://mys3.com" - accessKey, secretKey := "accessKey", "secretKey" - bucket, prefix := "testbucket", "testprefix" - region := "us-west-1" - storageClass := "S3_IA" - - want := &TierConfig{ - Version: TierConfigV1, - Type: S3, - Name: scName, - S3: &TierS3{ - AccessKey: accessKey, - SecretKey: secretKey, - Bucket: bucket, - - // custom values - Endpoint: endpoint, - Prefix: prefix, - Region: region, - StorageClass: storageClass, - }, - } - options := []S3Options{ - S3Endpoint(endpoint), - S3Prefix(prefix), - S3Region(region), - S3StorageClass(storageClass), - } - got, err := NewTierS3(scName, accessKey, secretKey, bucket, options...) - if err != nil { - t.Fatalf("Failed to create a custom s3 tier %s", err) - } - - if !reflect.DeepEqual(got, want) { - t.Fatalf("got != want, got = %v want = %v", *got, *want) - } -} - -// TestAzTier tests AzureOptions helpers -func TestAzTier(t *testing.T) { - scName := "test-az" - endpoint := "https://myazure.com" - - accountName, accountKey := "accountName", "accountKey" - bucket, prefix := "testbucket", "testprefix" - region := "us-east-1" - want := &TierConfig{ - Version: TierConfigV1, - Type: Azure, - Name: scName, - Azure: &TierAzure{ - AccountName: accountName, - AccountKey: accountKey, - Bucket: bucket, - - // custom values - Endpoint: endpoint, - Prefix: prefix, - Region: region, - }, - } - - options := []AzureOptions{ - AzureEndpoint(endpoint), - AzurePrefix(prefix), - AzureRegion(region), - } - - got, err := NewTierAzure(scName, accountName, accountKey, bucket, options...) - if err != nil { - t.Fatalf("Failed to create a custom azure tier %s", err) - } - - if !reflect.DeepEqual(got, want) { - t.Fatalf("got != want, got = %v want = %v", *got, *want) - } -} - -// TestGCSStorageClass tests GCSOptions helpers -func TestGCSStorageClass(t *testing.T) { - scName := "test-gcs" - credsJSON := []byte("test-creds-json") - encodedCreds := base64.URLEncoding.EncodeToString(credsJSON) - bucket, prefix := "testbucket", "testprefix" - region := "us-west-2" - - want := &TierConfig{ - Version: TierConfigV1, - Type: GCS, - Name: scName, - GCS: &TierGCS{ - Bucket: bucket, - Creds: encodedCreds, - - // custom values - Endpoint: "https://storage.googleapis.com/", - Prefix: prefix, - Region: region, - }, - } - options := []GCSOptions{ - GCSRegion(region), - GCSPrefix(prefix), - } - got, err := NewTierGCS(scName, credsJSON, bucket, options...) - if err != nil { - t.Fatalf("Failed to create a custom gcs tier %s", err) - } - - if !reflect.DeepEqual(got, want) { - t.Fatalf("got != want, got = %v want = %v", *got, *want) - } -} diff --git a/pkg/madmin/top-commands.go b/pkg/madmin/top-commands.go deleted file mode 100644 index 180fb939d..000000000 --- a/pkg/madmin/top-commands.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "io/ioutil" - "net/http" - "net/url" - "strconv" - "strings" - "time" -) - -// LockEntry holds information about client requesting the lock, -// servers holding the lock, source on the client machine, -// ID, type(read or write) and time stamp. -type LockEntry struct { - Timestamp time.Time `json:"time"` // When the lock was first granted - Resource string `json:"resource"` // Resource contains info like bucket+object - Type string `json:"type"` // Type indicates if 'Write' or 'Read' lock - Source string `json:"source"` // Source at which lock was granted - ServerList []string `json:"serverlist"` // List of servers participating in the lock. - Owner string `json:"owner"` // Owner UUID indicates server owns the lock. - ID string `json:"id"` // UID to uniquely identify request of client. - // Represents quorum number of servers required to hold this lock, used to look for stale locks. - Quorum int `json:"quorum"` -} - -// LockEntries - To sort the locks -type LockEntries []LockEntry - -func (l LockEntries) Len() int { - return len(l) -} - -func (l LockEntries) Less(i, j int) bool { - return l[i].Timestamp.Before(l[j].Timestamp) -} - -func (l LockEntries) Swap(i, j int) { - l[i], l[j] = l[j], l[i] -} - -// TopLockOpts top lock options -type TopLockOpts struct { - Count int - Stale bool -} - -// ForceUnlock force unlocks input paths... -func (adm *AdminClient) ForceUnlock(ctx context.Context, paths ...string) error { - // Execute POST on /minio/admin/v3/force-unlock - queryVals := make(url.Values) - queryVals.Set("paths", strings.Join(paths, ",")) - resp, err := adm.executeMethod(ctx, - http.MethodPost, - requestData{ - relPath: adminAPIPrefix + "/force-unlock", - queryValues: queryVals, - }, - ) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// TopLocksWithOpts - returns the count number of oldest locks currently active on the server. -// additionally we can also enable `stale` to get stale locks currently present on server. -func (adm *AdminClient) TopLocksWithOpts(ctx context.Context, opts TopLockOpts) (LockEntries, error) { - // Execute GET on /minio/admin/v3/top/locks?count=10 - // to get the 'count' number of oldest locks currently - // active on the server. - queryVals := make(url.Values) - queryVals.Set("count", strconv.Itoa(opts.Count)) - queryVals.Set("stale", strconv.FormatBool(opts.Stale)) - resp, err := adm.executeMethod(ctx, - http.MethodGet, - requestData{ - relPath: adminAPIPrefix + "/top/locks", - queryValues: queryVals, - }, - ) - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - response, err := ioutil.ReadAll(resp.Body) - if err != nil { - return LockEntries{}, err - } - - var lockEntries LockEntries - err = json.Unmarshal(response, &lockEntries) - return lockEntries, err -} - -// TopLocks - returns top '10' oldest locks currently active on the server. -func (adm *AdminClient) TopLocks(ctx context.Context) (LockEntries, error) { - return adm.TopLocksWithOpts(ctx, TopLockOpts{Count: 10}) -} diff --git a/pkg/madmin/transport.go b/pkg/madmin/transport.go deleted file mode 100644 index 7cce4d33f..000000000 --- a/pkg/madmin/transport.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "crypto/tls" - "net" - "net/http" - "time" -) - -// DefaultTransport - this default transport is similar to -// http.DefaultTransport but with additional param DisableCompression -// is set to true to avoid decompressing content with 'gzip' encoding. -var DefaultTransport = func(secure bool) http.RoundTripper { - tr := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 5 * time.Second, - KeepAlive: 15 * time.Second, - FallbackDelay: 100 * time.Millisecond, - }).DialContext, - MaxIdleConns: 1024, - MaxIdleConnsPerHost: 1024, - ResponseHeaderTimeout: 60 * time.Second, - IdleConnTimeout: 60 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - // Set this value so that the underlying transport round-tripper - // doesn't try to auto decode the body of objects with - // content-encoding set to `gzip`. - // - // Refer: - // https://golang.org/src/net/http/transport.go?h=roundTrip#L1843 - DisableCompression: true, - } - - if secure { - tr.TLSClientConfig = &tls.Config{ - // Can't use SSLv3 because of POODLE and BEAST - // Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher - // Can't use TLSv1.1 because of RC4 cipher usage - MinVersion: tls.VersionTLS12, - } - } - return tr -} diff --git a/pkg/madmin/update-commands.go b/pkg/madmin/update-commands.go deleted file mode 100644 index 337ab8bed..000000000 --- a/pkg/madmin/update-commands.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "net/http" - "net/url" -) - -// ServerUpdateStatus - contains the response of service update API -type ServerUpdateStatus struct { - CurrentVersion string `json:"currentVersion"` - UpdatedVersion string `json:"updatedVersion"` -} - -// ServerUpdate - updates and restarts the MinIO cluster to latest version. -// optionally takes an input URL to specify a custom update binary link -func (adm *AdminClient) ServerUpdate(ctx context.Context, updateURL string) (us ServerUpdateStatus, err error) { - queryValues := url.Values{} - queryValues.Set("updateURL", updateURL) - - // Request API to Restart server - resp, err := adm.executeMethod(ctx, - http.MethodPost, requestData{ - relPath: adminAPIPrefix + "/update", - queryValues: queryValues, - }, - ) - defer closeResponse(resp) - if err != nil { - return us, err - } - - if resp.StatusCode != http.StatusOK { - return us, httpRespToErrorResponse(resp) - } - - if err = json.NewDecoder(resp.Body).Decode(&us); err != nil { - return us, err - } - - return us, nil -} diff --git a/pkg/madmin/user-commands.go b/pkg/madmin/user-commands.go deleted file mode 100644 index 05bc85fbb..000000000 --- a/pkg/madmin/user-commands.go +++ /dev/null @@ -1,483 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "context" - "encoding/json" - "io/ioutil" - "net/http" - "net/url" - "time" - - "github.com/minio/minio/pkg/auth" - iampolicy "github.com/minio/minio/pkg/iam/policy" -) - -// AccountAccess contains information about -type AccountAccess struct { - Read bool `json:"read"` - Write bool `json:"write"` -} - -// BucketAccessInfo represents bucket usage of a bucket, and its relevant -// access type for an account -type BucketAccessInfo struct { - Name string `json:"name"` - Size uint64 `json:"size"` - Created time.Time `json:"created"` - Access AccountAccess `json:"access"` -} - -// AccountInfo represents the account usage info of an -// account across buckets. -type AccountInfo struct { - AccountName string - Policy iampolicy.Policy - Buckets []BucketAccessInfo -} - -// AccountInfo returns the usage info for the authenticating account. -func (adm *AdminClient) AccountInfo(ctx context.Context) (AccountInfo, error) { - resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/accountinfo"}) - defer closeResponse(resp) - if err != nil { - return AccountInfo{}, err - } - - // Check response http status code - if resp.StatusCode != http.StatusOK { - return AccountInfo{}, httpRespToErrorResponse(resp) - } - - // Unmarshal the server's json response - var accountInfo AccountInfo - - respBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return AccountInfo{}, err - } - - err = json.Unmarshal(respBytes, &accountInfo) - if err != nil { - return AccountInfo{}, err - } - - return accountInfo, nil -} - -// AccountStatus - account status. -type AccountStatus string - -// Account status per user. -const ( - AccountEnabled AccountStatus = "enabled" - AccountDisabled AccountStatus = "disabled" -) - -// UserInfo carries information about long term users. -type UserInfo struct { - SecretKey string `json:"secretKey,omitempty"` - PolicyName string `json:"policyName,omitempty"` - Status AccountStatus `json:"status"` - MemberOf []string `json:"memberOf,omitempty"` -} - -// RemoveUser - remove a user. -func (adm *AdminClient) RemoveUser(ctx context.Context, accessKey string) error { - queryValues := url.Values{} - queryValues.Set("accessKey", accessKey) - - reqData := requestData{ - relPath: adminAPIPrefix + "/remove-user", - queryValues: queryValues, - } - - // Execute DELETE on /minio/admin/v3/remove-user to remove a user. - resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// ListUsers - list all users. -func (adm *AdminClient) ListUsers(ctx context.Context) (map[string]UserInfo, error) { - reqData := requestData{ - relPath: adminAPIPrefix + "/list-users", - } - - // Execute GET on /minio/admin/v3/list-users - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - - defer closeResponse(resp) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, httpRespToErrorResponse(resp) - } - - data, err := DecryptData(adm.getSecretKey(), resp.Body) - if err != nil { - return nil, err - } - - var users = make(map[string]UserInfo) - if err = json.Unmarshal(data, &users); err != nil { - return nil, err - } - - return users, nil -} - -// GetUserInfo - get info on a user -func (adm *AdminClient) GetUserInfo(ctx context.Context, name string) (u UserInfo, err error) { - queryValues := url.Values{} - queryValues.Set("accessKey", name) - - reqData := requestData{ - relPath: adminAPIPrefix + "/user-info", - queryValues: queryValues, - } - - // Execute GET on /minio/admin/v3/user-info - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - - defer closeResponse(resp) - if err != nil { - return u, err - } - - if resp.StatusCode != http.StatusOK { - return u, httpRespToErrorResponse(resp) - } - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return u, err - } - - if err = json.Unmarshal(b, &u); err != nil { - return u, err - } - - return u, nil -} - -// SetUser - sets a user info. -func (adm *AdminClient) SetUser(ctx context.Context, accessKey, secretKey string, status AccountStatus) error { - - if !auth.IsAccessKeyValid(accessKey) { - return auth.ErrInvalidAccessKeyLength - } - - if !auth.IsSecretKeyValid(secretKey) { - return auth.ErrInvalidSecretKeyLength - } - - data, err := json.Marshal(UserInfo{ - SecretKey: secretKey, - Status: status, - }) - if err != nil { - return err - } - econfigBytes, err := EncryptData(adm.getSecretKey(), data) - if err != nil { - return err - } - - queryValues := url.Values{} - queryValues.Set("accessKey", accessKey) - - reqData := requestData{ - relPath: adminAPIPrefix + "/add-user", - queryValues: queryValues, - content: econfigBytes, - } - - // Execute PUT on /minio/admin/v3/add-user to set a user. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// AddUser - adds a user. -func (adm *AdminClient) AddUser(ctx context.Context, accessKey, secretKey string) error { - return adm.SetUser(ctx, accessKey, secretKey, AccountEnabled) -} - -// SetUserStatus - adds a status for a user. -func (adm *AdminClient) SetUserStatus(ctx context.Context, accessKey string, status AccountStatus) error { - queryValues := url.Values{} - queryValues.Set("accessKey", accessKey) - queryValues.Set("status", string(status)) - - reqData := requestData{ - relPath: adminAPIPrefix + "/set-user-status", - queryValues: queryValues, - } - - // Execute PUT on /minio/admin/v3/set-user-status to set status. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusOK { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// AddServiceAccountReq is the request options of the add service account admin call -type AddServiceAccountReq struct { - Policy *iampolicy.Policy `json:"policy,omitempty"` - TargetUser string `json:"targetUser,omitempty"` - AccessKey string `json:"accessKey,omitempty"` - SecretKey string `json:"secretKey,omitempty"` -} - -// AddServiceAccountResp is the response body of the add service account admin call -type AddServiceAccountResp struct { - Credentials auth.Credentials `json:"credentials"` -} - -// AddServiceAccount - creates a new service account belonging to the user sending -// the request while restricting the service account permission by the given policy document. -func (adm *AdminClient) AddServiceAccount(ctx context.Context, opts AddServiceAccountReq) (auth.Credentials, error) { - if opts.Policy != nil { - if err := opts.Policy.Validate(); err != nil { - return auth.Credentials{}, err - } - } - - data, err := json.Marshal(opts) - if err != nil { - return auth.Credentials{}, err - } - - econfigBytes, err := EncryptData(adm.getSecretKey(), data) - if err != nil { - return auth.Credentials{}, err - } - - reqData := requestData{ - relPath: adminAPIPrefix + "/add-service-account", - content: econfigBytes, - } - - // Execute PUT on /minio/admin/v3/add-service-account to set a user. - resp, err := adm.executeMethod(ctx, http.MethodPut, reqData) - defer closeResponse(resp) - if err != nil { - return auth.Credentials{}, err - } - - if resp.StatusCode != http.StatusOK { - return auth.Credentials{}, httpRespToErrorResponse(resp) - } - - data, err = DecryptData(adm.getSecretKey(), resp.Body) - if err != nil { - return auth.Credentials{}, err - } - - var serviceAccountResp AddServiceAccountResp - if err = json.Unmarshal(data, &serviceAccountResp); err != nil { - return auth.Credentials{}, err - } - return serviceAccountResp.Credentials, nil -} - -// UpdateServiceAccountReq is the request options of the edit service account admin call -type UpdateServiceAccountReq struct { - NewPolicy *iampolicy.Policy `json:"newPolicy,omitempty"` - NewSecretKey string `json:"newSecretKey,omitempty"` - NewStatus string `json:"newStatus,omityempty"` -} - -// UpdateServiceAccount - edit an existing service account -func (adm *AdminClient) UpdateServiceAccount(ctx context.Context, accessKey string, opts UpdateServiceAccountReq) error { - if opts.NewPolicy != nil { - if err := opts.NewPolicy.Validate(); err != nil { - return err - } - } - - data, err := json.Marshal(opts) - if err != nil { - return err - } - - econfigBytes, err := EncryptData(adm.getSecretKey(), data) - if err != nil { - return err - } - - queryValues := url.Values{} - queryValues.Set("accessKey", accessKey) - - reqData := requestData{ - relPath: adminAPIPrefix + "/update-service-account", - content: econfigBytes, - queryValues: queryValues, - } - - // Execute POST on /minio/admin/v3/update-service-account to edit a service account - resp, err := adm.executeMethod(ctx, http.MethodPost, reqData) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusNoContent { - return httpRespToErrorResponse(resp) - } - - return nil -} - -// ListServiceAccountsResp is the response body of the list service accounts call -type ListServiceAccountsResp struct { - Accounts []string `json:"accounts"` -} - -// ListServiceAccounts - list service accounts belonging to the specified user -func (adm *AdminClient) ListServiceAccounts(ctx context.Context, user string) (ListServiceAccountsResp, error) { - queryValues := url.Values{} - queryValues.Set("user", user) - - reqData := requestData{ - relPath: adminAPIPrefix + "/list-service-accounts", - queryValues: queryValues, - } - - // Execute GET on /minio/admin/v3/list-service-accounts - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - defer closeResponse(resp) - if err != nil { - return ListServiceAccountsResp{}, err - } - - if resp.StatusCode != http.StatusOK { - return ListServiceAccountsResp{}, httpRespToErrorResponse(resp) - } - - data, err := DecryptData(adm.getSecretKey(), resp.Body) - if err != nil { - return ListServiceAccountsResp{}, err - } - - var listResp ListServiceAccountsResp - if err = json.Unmarshal(data, &listResp); err != nil { - return ListServiceAccountsResp{}, err - } - return listResp, nil -} - -// InfoServiceAccountResp is the response body of the info service account call -type InfoServiceAccountResp struct { - ParentUser string `json:"parentUser"` - AccountStatus string `json:"accountStatus"` - ImpliedPolicy bool `json:"impliedPolicy"` - Policy string `json:"policy"` -} - -// InfoServiceAccount - returns the info of service account belonging to the specified user -func (adm *AdminClient) InfoServiceAccount(ctx context.Context, accessKey string) (InfoServiceAccountResp, error) { - queryValues := url.Values{} - queryValues.Set("accessKey", accessKey) - - reqData := requestData{ - relPath: adminAPIPrefix + "/info-service-account", - queryValues: queryValues, - } - - // Execute GET on /minio/admin/v3/info-service-account - resp, err := adm.executeMethod(ctx, http.MethodGet, reqData) - defer closeResponse(resp) - if err != nil { - return InfoServiceAccountResp{}, err - } - - if resp.StatusCode != http.StatusOK { - return InfoServiceAccountResp{}, httpRespToErrorResponse(resp) - } - - data, err := DecryptData(adm.getSecretKey(), resp.Body) - if err != nil { - return InfoServiceAccountResp{}, err - } - - var infoResp InfoServiceAccountResp - if err = json.Unmarshal(data, &infoResp); err != nil { - return InfoServiceAccountResp{}, err - } - return infoResp, nil -} - -// DeleteServiceAccount - delete a specified service account. The server will reject -// the request if the service account does not belong to the user initiating the request -func (adm *AdminClient) DeleteServiceAccount(ctx context.Context, serviceAccount string) error { - if !auth.IsAccessKeyValid(serviceAccount) { - return auth.ErrInvalidAccessKeyLength - } - - queryValues := url.Values{} - queryValues.Set("accessKey", serviceAccount) - - reqData := requestData{ - relPath: adminAPIPrefix + "/delete-service-account", - queryValues: queryValues, - } - - // Execute DELETE on /minio/admin/v3/delete-service-account - resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData) - defer closeResponse(resp) - if err != nil { - return err - } - - if resp.StatusCode != http.StatusNoContent { - return httpRespToErrorResponse(resp) - } - - return nil -} diff --git a/pkg/madmin/utils.go b/pkg/madmin/utils.go deleted file mode 100644 index 463490ea4..000000000 --- a/pkg/madmin/utils.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package madmin - -import ( - "encoding/json" - "io" - "io/ioutil" - "net" - "net/http" - "net/url" - "strings" - - "github.com/minio/minio-go/v7/pkg/s3utils" -) - -// AdminAPIVersion - admin api version used in the request. -const ( - AdminAPIVersion = "v3" - AdminAPIVersionV2 = "v2" - adminAPIPrefix = "/" + AdminAPIVersion -) - -// jsonDecoder decode json to go type. -func jsonDecoder(body io.Reader, v interface{}) error { - d := json.NewDecoder(body) - return d.Decode(v) -} - -// getEndpointURL - construct a new endpoint. -func getEndpointURL(endpoint string, secure bool) (*url.URL, error) { - if strings.Contains(endpoint, ":") { - host, _, err := net.SplitHostPort(endpoint) - if err != nil { - return nil, err - } - if !s3utils.IsValidIP(host) && !s3utils.IsValidDomain(host) { - msg := "Endpoint: " + endpoint + " does not follow ip address or domain name standards." - return nil, ErrInvalidArgument(msg) - } - } else { - if !s3utils.IsValidIP(endpoint) && !s3utils.IsValidDomain(endpoint) { - msg := "Endpoint: " + endpoint + " does not follow ip address or domain name standards." - return nil, ErrInvalidArgument(msg) - } - } - - // If secure is false, use 'http' scheme. - scheme := "https" - if !secure { - scheme = "http" - } - - // Strip the obvious :443 and :80 from the endpoint - // to avoid the signature mismatch error. - if secure && strings.HasSuffix(endpoint, ":443") { - endpoint = strings.TrimSuffix(endpoint, ":443") - } - if !secure && strings.HasSuffix(endpoint, ":80") { - endpoint = strings.TrimSuffix(endpoint, ":80") - } - - // Construct a secured endpoint URL. - endpointURLStr := scheme + "://" + endpoint - endpointURL, err := url.Parse(endpointURLStr) - if err != nil { - return nil, err - } - - // Validate incoming endpoint URL. - if err := isValidEndpointURL(endpointURL.String()); err != nil { - return nil, err - } - return endpointURL, nil -} - -// Verify if input endpoint URL is valid. -func isValidEndpointURL(endpointURL string) error { - if endpointURL == "" { - return ErrInvalidArgument("Endpoint url cannot be empty.") - } - url, err := url.Parse(endpointURL) - if err != nil { - return ErrInvalidArgument("Endpoint url cannot be parsed.") - } - if url.Path != "/" && url.Path != "" { - return ErrInvalidArgument("Endpoint url cannot have fully qualified paths.") - } - return nil -} - -// closeResponse close non nil response with any response Body. -// convenient wrapper to drain any remaining data on response body. -// -// Subsequently this allows golang http RoundTripper -// to re-use the same connection for future requests. -func closeResponse(resp *http.Response) { - // Callers should close resp.Body when done reading from it. - // If resp.Body is not closed, the Client's underlying RoundTripper - // (typically Transport) may not be able to re-use a persistent TCP - // connection to the server for a subsequent "keep-alive" request. - if resp != nil && resp.Body != nil { - // Drain any remaining Body and then close the connection. - // Without this closing connection would disallow re-using - // the same connection for future uses. - // - http://stackoverflow.com/a/17961593/4465767 - io.Copy(ioutil.Discard, resp.Body) - resp.Body.Close() - } -} diff --git a/pkg/net/health.go b/pkg/net/health.go index 864377dfe..aa319e9fe 100644 --- a/pkg/net/health.go +++ b/pkg/net/health.go @@ -18,31 +18,12 @@ package net import ( + "github.com/minio/madmin-go" "github.com/montanaflynn/stats" ) -// Latency holds latency information for read/write operations to the drive -type Latency struct { - Avg float64 `json:"avg_secs,omitempty"` - Percentile50 float64 `json:"percentile50_secs,omitempty"` - Percentile90 float64 `json:"percentile90_secs,omitempty"` - Percentile99 float64 `json:"percentile99_secs,omitempty"` - Min float64 `json:"min_secs,omitempty"` - Max float64 `json:"max_secs,omitempty"` -} - -// Throughput holds throughput information for read/write operations to the drive -type Throughput struct { - Avg float64 `json:"avg_bytes_per_sec,omitempty"` - Percentile50 float64 `json:"percentile50_bytes_per_sec,omitempty"` - Percentile90 float64 `json:"percentile90_bytes_per_sec,omitempty"` - Percentile99 float64 `json:"percentile99_bytes_per_sec,omitempty"` - Min float64 `json:"min_bytes_per_sec,omitempty"` - Max float64 `json:"max_bytes_per_sec,omitempty"` -} - // ComputePerfStats takes arrays of Latency & Throughput to compute Statistics -func ComputePerfStats(latencies, throughputs []float64) (Latency, Throughput, error) { +func ComputePerfStats(latencies, throughputs []float64) (madmin.NetLatency, madmin.NetThroughput, error) { var avgLatency float64 var percentile50Latency float64 var percentile90Latency float64 @@ -59,24 +40,24 @@ func ComputePerfStats(latencies, throughputs []float64) (Latency, Throughput, er var err error if avgLatency, err = stats.Mean(latencies); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if percentile50Latency, err = stats.Percentile(latencies, 50); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if percentile90Latency, err = stats.Percentile(latencies, 90); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if percentile99Latency, err = stats.Percentile(latencies, 99); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if maxLatency, err = stats.Max(latencies); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if minLatency, err = stats.Min(latencies); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } - l := Latency{ + l := madmin.NetLatency{ Avg: avgLatency, Percentile50: percentile50Latency, Percentile90: percentile90Latency, @@ -86,24 +67,24 @@ func ComputePerfStats(latencies, throughputs []float64) (Latency, Throughput, er } if avgThroughput, err = stats.Mean(throughputs); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if percentile50Throughput, err = stats.Percentile(throughputs, 50); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if percentile90Throughput, err = stats.Percentile(throughputs, 90); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if percentile99Throughput, err = stats.Percentile(throughputs, 99); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if maxThroughput, err = stats.Max(throughputs); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } if minThroughput, err = stats.Min(throughputs); err != nil { - return Latency{}, Throughput{}, err + return madmin.NetLatency{}, madmin.NetThroughput{}, err } - t := Throughput{ + t := madmin.NetThroughput{ Avg: avgThroughput, Percentile50: percentile50Throughput, Percentile90: percentile90Throughput, diff --git a/pkg/smart/smart.go b/pkg/smart/smart.go index 99c80071f..ac88249a6 100644 --- a/pkg/smart/smart.go +++ b/pkg/smart/smart.go @@ -31,13 +31,14 @@ import ( "github.com/dswarbrick/smart/ioctl" "github.com/dswarbrick/smart/scsi" "github.com/dswarbrick/smart/utils" + "github.com/minio/madmin-go" "gopkg.in/yaml.v2" ) // GetInfo - gets info about device -func GetInfo(device string) (Info, error) { - info := Info{ +func GetInfo(device string) (madmin.SmartInfo, error) { + info := madmin.SmartInfo{ Device: device, } @@ -89,9 +90,9 @@ func GetInfo(device string) (Info, error) { return info, nil } -func getNvmeInfo(d *NVMeDevice) (*NvmeInfo, error) { +func getNvmeInfo(d *NVMeDevice) (*madmin.SmartNvmeInfo, error) { buf := make([]byte, 4096) - nvmeInfo := &NvmeInfo{} + nvmeInfo := &madmin.SmartNvmeInfo{} cmd := nvmePassthruCommand{ opcode: NvmeAdminIdentify, @@ -145,10 +146,10 @@ func getNvmeInfo(d *NVMeDevice) (*NvmeInfo, error) { return nvmeInfo, nil } -func getScsiInfo(d *scsi.SCSIDevice) (*ScsiInfo, error) { - return &ScsiInfo{}, nil +func getScsiInfo(d *scsi.SCSIDevice) (*madmin.SmartScsiInfo, error) { + return &madmin.SmartScsiInfo{}, nil } -func getAtaInfo(d *scsi.SATDevice) (*AtaInfo, error) { - return &AtaInfo{}, nil +func getAtaInfo(d *scsi.SATDevice) (*madmin.SmartAtaInfo, error) { + return &madmin.SmartAtaInfo{}, nil } diff --git a/pkg/smart/types.go b/pkg/smart/types.go index 9e950150a..5311c8b70 100644 --- a/pkg/smart/types.go +++ b/pkg/smart/types.go @@ -17,8 +17,6 @@ package smart -import "math/big" - // Defined in //nolint:structcheck,deadcode type nvmePassthruCommand struct { @@ -182,62 +180,3 @@ type NVMeDevice struct { Name string fd int } - -// Info contains S.M.A.R.T data about the drive -type Info struct { - Device string `json:"device"` - - Scsi *ScsiInfo `json:"scsi,omitempty"` - Nvme *NvmeInfo `json:"nvme,omitempty"` - Ata *AtaInfo `json:"ata,omitempty"` - - Error string `json:"error,omitempty"` -} - -// AtaInfo contains ATA drive info -type AtaInfo struct { - LUWWNDeviceID string `json:"scsiLuWWNDeviceID,omitempty"` - SerialNum string `json:"serialNum,omitempty"` - ModelNum string `json:"modelNum,omitempty"` - FirmwareRevision string `json:"firmwareRevision,omitempty"` - RotationRate string `json:"RotationRate,omitempty"` - ATAMajorVersion string `json:"MajorVersion,omitempty"` - ATAMinorVersion string `json:"MinorVersion,omitempty"` - SmartSupportAvailable bool `json:"smartSupportAvailable,omitempty"` - SmartSupportEnabled bool `json:"smartSupportEnabled,omitempty"` - ErrorLog string `json:"smartErrorLog,omitempty"` - Transport string `json:"transport,omitempty"` -} - -// ScsiInfo contains SCSI drive Info -type ScsiInfo struct { - CapacityBytes int64 `json:"scsiCapacityBytes,omitempty"` - ModeSenseBuf string `json:"scsiModeSenseBuf,omitempty"` - RespLen int64 `json:"scsirespLen,omitempty"` - BdLen int64 `json:"scsiBdLen,omitempty"` - Offset int64 `json:"scsiOffset,omitempty"` - RPM int64 `json:"sciRpm,omitempty"` -} - -// NvmeInfo contains NVMe drive info -type NvmeInfo struct { - SerialNum string `json:"serialNum,omitempty"` - VendorID string `json:"vendorId,omitempty"` - FirmwareVersion string `json:"firmwareVersion,omitempty"` - ModelNum string `json:"modelNum,omitempty"` - SpareAvailable string `json:"spareAvailable,omitempty"` - SpareThreshold string `json:"spareThreshold,omitempty"` - Temperature string `json:"temperature,omitempty"` - CriticalWarning string `json:"criticalWarning,omitempty"` - - MaxDataTransferPages int `json:"maxDataTransferPages,omitempty"` - ControllerBusyTime *big.Int `json:"controllerBusyTime,omitempty"` - PowerOnHours *big.Int `json:"powerOnHours,omitempty"` - PowerCycles *big.Int `json:"powerCycles,omitempty"` - UnsafeShutdowns *big.Int `json:"unsafeShutdowns,omitempty"` - MediaAndDataIntegrityErrors *big.Int `json:"mediaAndDataIntgerityErrors,omitempty"` - DataUnitsReadBytes *big.Int `json:"dataUnitsReadBytes,omitempty"` - DataUnitsWrittenBytes *big.Int `json:"dataUnitsWrittenBytes,omitempty"` - HostReadCommands *big.Int `json:"hostReadCommands,omitempty"` - HostWriteCommands *big.Int `json:"hostWriteCommands,omitempty"` -} diff --git a/pkg/trace/trace.go b/pkg/trace/trace.go deleted file mode 100644 index 97f39c21d..000000000 --- a/pkg/trace/trace.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2015-2021 MinIO, Inc. -// -// This file is part of MinIO Object Storage stack -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package trace - -import ( - "net/http" - "time" -) - -// Type indicates the type of the tracing Info -type Type int - -const ( - // HTTP tracing (MinIO S3 & Internode) - HTTP Type = iota - // OS tracing (Golang os package calls) - OS - // Storage tracing (MinIO Storage Layer) - Storage -) - -// Info - represents a trace record, additionally -// also reports errors if any while listening on trace. -type Info struct { - TraceType Type `json:"type"` - - NodeName string `json:"nodename"` - FuncName string `json:"funcname"` - Time time.Time `json:"time"` - - ReqInfo RequestInfo `json:"request"` - RespInfo ResponseInfo `json:"response"` - CallStats CallStats `json:"stats"` - - StorageStats StorageStats `json:"storageStats"` - OSStats OSStats `json:"osStats"` -} - -// StorageStats statistics on MinIO Storage layer calls -type StorageStats struct { - Path string `json:"path"` - Duration time.Duration `json:"duration"` -} - -// OSStats statistics on operating system specific calls. -type OSStats struct { - Path string `json:"path"` - Duration time.Duration `json:"duration"` -} - -// CallStats records request stats -type CallStats struct { - InputBytes int `json:"inputbytes"` - OutputBytes int `json:"outputbytes"` - Latency time.Duration `json:"latency"` - TimeToFirstByte time.Duration `json:"timetofirstbyte"` -} - -// RequestInfo represents trace of http request -type RequestInfo struct { - Time time.Time `json:"time"` - Proto string `json:"proto"` - Method string `json:"method"` - Path string `json:"path,omitempty"` - RawQuery string `json:"rawquery,omitempty"` - Headers http.Header `json:"headers,omitempty"` - Body []byte `json:"body,omitempty"` - Client string `json:"client"` -} - -// ResponseInfo represents trace of http request -type ResponseInfo struct { - Time time.Time `json:"time"` - Headers http.Header `json:"headers,omitempty"` - Body []byte `json:"body,omitempty"` - StatusCode int `json:"statuscode,omitempty"` -}