mirror of
https://github.com/pgsty/minio.git
synced 2026-11-08 08:41:50 +03:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af564b8ba0 | |||
| adb8be069e | |||
| 7c8746732b | |||
| f506117edb | |||
| 1c5af7c31a | |||
| 3a0125fa1f | |||
| 328cb0a076 | |||
| c3c8441a1d | |||
| fa2a8d7209 | |||
| e3ea97c964 | |||
| 7219ae530e | |||
| 8f8f8854f0 | |||
| 4c6869cd9a | |||
| bc7c0d8624 | |||
| 11dfc817f3 | |||
| dde1a12819 | |||
| 065fd094d1 |
@@ -2386,10 +2386,13 @@ SOFTWARE.
|
||||
|
||||
================================================================
|
||||
|
||||
github.com/Shopify/sarama
|
||||
https://github.com/Shopify/sarama
|
||||
github.com/IBM/sarama
|
||||
https://github.com/IBM/sarama
|
||||
----------------------------------------------------------------
|
||||
# MIT License
|
||||
|
||||
Copyright (c) 2013 Shopify
|
||||
Copyright (c) 2023 IBM Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -2410,34 +2413,6 @@ 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/Shopify/toxiproxy/v2
|
||||
https://github.com/Shopify/toxiproxy/v2
|
||||
----------------------------------------------------------------
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Shopify
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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/alecthomas/participle
|
||||
@@ -30459,209 +30434,3 @@ limitations under the License.
|
||||
|
||||
================================================================
|
||||
|
||||
All community contributions are licensed under the terms of the Apache 2 license.
|
||||
----------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
================================================================
|
||||
|
||||
@@ -1147,6 +1147,7 @@ func (a adminAPIHandlers) SitePerfHandler(w http.ResponseWriter, r *http.Request
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(toAPIErrorCode(ctx, err)), r.URL)
|
||||
return
|
||||
}
|
||||
ctx = lkctx.Context()
|
||||
defer nsLock.Unlock(lkctx)
|
||||
|
||||
durationStr := r.Form.Get(peerRESTDuration)
|
||||
@@ -1253,6 +1254,7 @@ func (a adminAPIHandlers) NetperfHandler(w http.ResponseWriter, r *http.Request)
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(toAPIErrorCode(ctx, err)), r.URL)
|
||||
return
|
||||
}
|
||||
ctx = lkctx.Context()
|
||||
defer nsLock.Unlock(lkctx)
|
||||
|
||||
durationStr := r.Form.Get(peerRESTDuration)
|
||||
|
||||
+18
-65
@@ -19,98 +19,51 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/minio/madmin-go/v3"
|
||||
"github.com/minio/minio/internal/pubsub"
|
||||
)
|
||||
|
||||
const bootstrapMsgsLimit = 4 << 10
|
||||
const bootstrapTraceLimit = 4 << 10
|
||||
|
||||
type bootstrapInfo struct {
|
||||
msg string
|
||||
ts time.Time
|
||||
source string
|
||||
}
|
||||
type bootstrapTracer struct {
|
||||
mu sync.RWMutex
|
||||
idx int
|
||||
info [bootstrapMsgsLimit]bootstrapInfo
|
||||
lastUpdate time.Time
|
||||
mu sync.RWMutex
|
||||
info []madmin.TraceInfo
|
||||
}
|
||||
|
||||
var globalBootstrapTracer = &bootstrapTracer{}
|
||||
|
||||
func (bs *bootstrapTracer) DropEvents() {
|
||||
func (bs *bootstrapTracer) Record(info madmin.TraceInfo) {
|
||||
bs.mu.Lock()
|
||||
defer bs.mu.Unlock()
|
||||
|
||||
if time.Now().UTC().Sub(bs.lastUpdate) > 24*time.Hour {
|
||||
bs.info = [4096]bootstrapInfo{}
|
||||
bs.idx = 0
|
||||
if len(bs.info) > bootstrapTraceLimit {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *bootstrapTracer) Empty() bool {
|
||||
var empty bool
|
||||
bs.mu.RLock()
|
||||
empty = bs.info[0].msg == ""
|
||||
bs.mu.RUnlock()
|
||||
|
||||
return empty
|
||||
}
|
||||
|
||||
func (bs *bootstrapTracer) Record(msg string, skip int) {
|
||||
source := getSource(skip + 1)
|
||||
bs.mu.Lock()
|
||||
now := time.Now().UTC()
|
||||
bs.info[bs.idx] = bootstrapInfo{
|
||||
msg: msg,
|
||||
ts: now,
|
||||
source: source,
|
||||
}
|
||||
bs.lastUpdate = now
|
||||
bs.idx = (bs.idx + 1) % bootstrapMsgsLimit
|
||||
bs.mu.Unlock()
|
||||
bs.info = append(bs.info, info)
|
||||
}
|
||||
|
||||
func (bs *bootstrapTracer) Events() []madmin.TraceInfo {
|
||||
traceInfo := make([]madmin.TraceInfo, 0, bootstrapMsgsLimit)
|
||||
|
||||
// Add all messages in order
|
||||
addAll := func(info []bootstrapInfo) {
|
||||
for _, msg := range info {
|
||||
if msg.ts.IsZero() {
|
||||
continue // skip empty events
|
||||
}
|
||||
traceInfo = append(traceInfo, madmin.TraceInfo{
|
||||
TraceType: madmin.TraceBootstrap,
|
||||
Time: msg.ts,
|
||||
NodeName: globalLocalNodeName,
|
||||
FuncName: "BOOTSTRAP",
|
||||
Message: fmt.Sprintf("%s %s", msg.source, msg.msg),
|
||||
})
|
||||
}
|
||||
}
|
||||
traceInfo := make([]madmin.TraceInfo, 0, bootstrapTraceLimit)
|
||||
|
||||
bs.mu.RLock()
|
||||
addAll(bs.info[bs.idx:])
|
||||
addAll(bs.info[:bs.idx])
|
||||
for _, i := range bs.info {
|
||||
traceInfo = append(traceInfo, i)
|
||||
}
|
||||
bs.mu.RUnlock()
|
||||
|
||||
return traceInfo
|
||||
}
|
||||
|
||||
func (bs *bootstrapTracer) Publish(ctx context.Context, trace *pubsub.PubSub[madmin.TraceInfo, madmin.TraceType]) {
|
||||
if bs.Empty() {
|
||||
return
|
||||
}
|
||||
for _, bsEvent := range bs.Events() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
default:
|
||||
trace.Publish(bsEvent)
|
||||
if bsEvent.Message != "" {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
default:
|
||||
trace.Publish(bsEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2015-2023 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBootstrap(t *testing.T) {
|
||||
// Bootstrap events exceed bootstrap messages limit
|
||||
bsTracer := &bootstrapTracer{}
|
||||
for i := 0; i < bootstrapMsgsLimit+10; i++ {
|
||||
bsTracer.Record(fmt.Sprintf("msg-%d", i), 1)
|
||||
}
|
||||
|
||||
traceInfos := bsTracer.Events()
|
||||
if len(traceInfos) != bootstrapMsgsLimit {
|
||||
t.Fatalf("Expected length of events %d but got %d", bootstrapMsgsLimit, len(traceInfos))
|
||||
}
|
||||
|
||||
// Simulate the case where bootstrap events were updated a day ago
|
||||
bsTracer.lastUpdate = time.Now().UTC().Add(-25 * time.Hour)
|
||||
bsTracer.DropEvents()
|
||||
if !bsTracer.Empty() {
|
||||
t.Fatalf("Expected all bootstrap events to have been dropped, but found %d events", len(bsTracer.Events()))
|
||||
}
|
||||
|
||||
// Fewer than 4K bootstrap events
|
||||
for i := 0; i < 10; i++ {
|
||||
bsTracer.Record(fmt.Sprintf("msg-%d", i), 1)
|
||||
}
|
||||
events := bsTracer.Events()
|
||||
if len(events) != 10 {
|
||||
t.Fatalf("Expected length of events %d but got %d", 10, len(events))
|
||||
}
|
||||
for i, traceInfo := range bsTracer.Events() {
|
||||
msg := fmt.Sprintf("msg-%d", i)
|
||||
if !strings.HasSuffix(traceInfo.Message, msg) {
|
||||
t.Fatalf("Expected %s but got %s", msg, traceInfo.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,7 +221,7 @@ func verifyServerSystemConfig(ctx context.Context, endpointServerPools EndpointS
|
||||
for onlineServers < len(clnts)/2 {
|
||||
for _, clnt := range clnts {
|
||||
if err := clnt.Verify(ctx, srcCfg); err != nil {
|
||||
bootstrapTrace(fmt.Sprintf("clnt.Verify: %v, endpoint: %v", err, clnt.endpoint))
|
||||
bootstrapTraceMsg(fmt.Sprintf("clnt.Verify: %v, endpoint: %v", err, clnt.endpoint))
|
||||
if !isNetworkError(err) {
|
||||
logger.LogOnceIf(ctx, fmt.Errorf("%s has incorrect configuration: %w", clnt.String(), err), clnt.String())
|
||||
incorrectConfigs = append(incorrectConfigs, fmt.Errorf("%s has incorrect configuration: %w", clnt.String(), err))
|
||||
|
||||
+39
-54
@@ -27,9 +27,7 @@ import (
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -1631,6 +1629,7 @@ type ReplicationPool struct {
|
||||
ctx context.Context
|
||||
priority string
|
||||
mu sync.RWMutex
|
||||
mrfMU sync.Mutex
|
||||
resyncer *replicationResyncer
|
||||
|
||||
// workers:
|
||||
@@ -1644,7 +1643,6 @@ type ReplicationPool struct {
|
||||
mrfSaveCh chan MRFReplicateEntry
|
||||
mrfStopCh chan struct{}
|
||||
mrfWorkerSize int
|
||||
saveStateCh chan struct{}
|
||||
}
|
||||
|
||||
// ReplicationWorkerOperation is a shared interface of replication operations.
|
||||
@@ -1704,7 +1702,6 @@ func NewReplicationPool(ctx context.Context, o ObjectLayer, opts replicationPool
|
||||
resyncer: newresyncer(),
|
||||
mrfSaveCh: make(chan MRFReplicateEntry, 100000),
|
||||
mrfStopCh: make(chan struct{}, 1),
|
||||
saveStateCh: make(chan struct{}, 1),
|
||||
ctx: ctx,
|
||||
objLayer: o,
|
||||
priority: priority,
|
||||
@@ -3035,13 +3032,11 @@ func (p *ReplicationPool) persistMRF() {
|
||||
return
|
||||
}
|
||||
|
||||
var mu sync.Mutex
|
||||
entries := make(map[string]MRFReplicateEntry)
|
||||
mTimer := time.NewTimer(mrfSaveInterval)
|
||||
defer mTimer.Stop()
|
||||
|
||||
saveMRFToDisk := func(drain bool) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if len(entries) == 0 {
|
||||
return
|
||||
}
|
||||
@@ -3053,12 +3048,16 @@ func (p *ReplicationPool) persistMRF() {
|
||||
entries[e.versionID] = e
|
||||
}
|
||||
}
|
||||
|
||||
// queue all entries for healing before overwriting the node mrf file
|
||||
p.queueMRFHeal()
|
||||
if !contextCanceled(p.ctx) {
|
||||
p.queueMRFHeal()
|
||||
}
|
||||
|
||||
if err := p.saveMRFEntries(cctx, entries); err != nil {
|
||||
logger.LogOnceIf(p.ctx, fmt.Errorf("unable to persist replication failures to disk:%w", err), string(replicationSubsystem))
|
||||
}
|
||||
|
||||
entries = make(map[string]MRFReplicateEntry)
|
||||
}
|
||||
for {
|
||||
@@ -3071,21 +3070,14 @@ func (p *ReplicationPool) persistMRF() {
|
||||
close(p.mrfSaveCh)
|
||||
saveMRFToDisk(true)
|
||||
return
|
||||
case <-p.saveStateCh:
|
||||
saveMRFToDisk(true)
|
||||
return
|
||||
case e, ok := <-p.mrfSaveCh:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var cnt int
|
||||
mu.Lock()
|
||||
entries[e.versionID] = e
|
||||
cnt = len(entries)
|
||||
mu.Unlock()
|
||||
if cnt >= mrfMaxEntries {
|
||||
if len(entries) >= mrfMaxEntries {
|
||||
saveMRFToDisk(true)
|
||||
}
|
||||
entries[e.versionID] = e
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3119,6 +3111,7 @@ func (p *ReplicationPool) saveMRFEntries(ctx context.Context, entries map[string
|
||||
if len(entries) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := MRFReplicateEntries{
|
||||
Entries: entries,
|
||||
Version: mrfMetaVersionV1,
|
||||
@@ -3134,41 +3127,19 @@ func (p *ReplicationPool) saveMRFEntries(ctx context.Context, entries map[string
|
||||
return err
|
||||
}
|
||||
|
||||
for _, diskPath := range globalEndpoints.LocalDisksPaths() {
|
||||
// write to first drive
|
||||
mrfDir := filepath.Join(diskPath, minioMetaBucket, replicationMRFDir)
|
||||
mrfFileName := filepath.Join(mrfDir, globalLocalNodeNameHex+".bin")
|
||||
if err := os.MkdirAll(mrfDir, 0o777); err != nil {
|
||||
return err
|
||||
for _, localDrive := range globalLocalDrives {
|
||||
if err := localDrive.WriteAll(ctx, minioMetaBucket, pathJoin(replicationMRFDir, globalLocalNodeNameHex+".bin"), buf); err == nil {
|
||||
break
|
||||
}
|
||||
file, err := OpenFile(mrfFileName, os.O_CREATE|os.O_WRONLY|writeMode, 0o666)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
defer file.Close()
|
||||
if _, err = file.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// load mrf entries from disk
|
||||
func (p *ReplicationPool) loadMRF(fileName string) (re MRFReplicateEntries, e error) {
|
||||
func (p *ReplicationPool) loadMRF(data []byte) (re MRFReplicateEntries, e error) {
|
||||
if !p.initialized() {
|
||||
return re, nil
|
||||
}
|
||||
file, err := Open(fileName)
|
||||
if err != nil {
|
||||
return re, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return re, err
|
||||
}
|
||||
if len(data) == 0 {
|
||||
// Seems to be empty.
|
||||
return re, nil
|
||||
@@ -3188,7 +3159,7 @@ func (p *ReplicationPool) loadMRF(fileName string) (re MRFReplicateEntries, e er
|
||||
return re, fmt.Errorf("replication mrf: unknown version: %d", binary.LittleEndian.Uint16(data[2:4]))
|
||||
}
|
||||
// OK, parse data.
|
||||
if _, err = re.UnmarshalMsg(data[4:]); err != nil {
|
||||
if _, err := re.UnmarshalMsg(data[4:]); err != nil {
|
||||
return re, err
|
||||
}
|
||||
|
||||
@@ -3233,29 +3204,40 @@ func (p *ReplicationPool) processMRF() {
|
||||
|
||||
// process sends error logs to the heal channel for an attempt to heal replication.
|
||||
func (p *ReplicationPool) queueMRFHeal() error {
|
||||
p.mrfMU.Lock()
|
||||
defer p.mrfMU.Unlock()
|
||||
|
||||
if !p.initialized() {
|
||||
return errServerNotInitialized
|
||||
}
|
||||
|
||||
for _, diskPath := range globalEndpoints.LocalDisksPaths() {
|
||||
fileName := filepath.Join(diskPath, minioMetaBucket, replicationMRFDir, globalLocalNodeNameHex+".bin")
|
||||
mrfRec, err := p.loadMRF(fileName)
|
||||
for _, localDrive := range globalLocalDrives {
|
||||
buf, err := localDrive.ReadAll(p.ctx, minioMetaBucket, pathJoin(replicationMRFDir, globalLocalNodeNameHex+".bin"))
|
||||
if err != nil {
|
||||
return err
|
||||
continue
|
||||
}
|
||||
|
||||
mrfRec, err := p.loadMRF(buf)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// finally delete the file after processing mrf entries
|
||||
os.Remove(fileName)
|
||||
localDrive.Delete(p.ctx, minioMetaBucket, pathJoin(replicationMRFDir, globalLocalNodeNameHex+".bin"), DeleteOptions{})
|
||||
|
||||
// queue replication heal in a goroutine to avoid holding up mrf save routine
|
||||
go func(mrfRec MRFReplicateEntries) {
|
||||
for vID, e := range mrfRec.Entries {
|
||||
ctx, cancel := context.WithTimeout(p.ctx, time.Second) // Do not waste more than a second on this.
|
||||
|
||||
oi, err := p.objLayer.GetObjectInfo(p.ctx, e.Bucket, e.Object, ObjectOptions{
|
||||
oi, err := p.objLayer.GetObjectInfo(ctx, e.Bucket, e.Object, ObjectOptions{
|
||||
VersionID: vID,
|
||||
})
|
||||
cancel()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
QueueReplicationHeal(p.ctx, e.Bucket, oi, e.RetryCount)
|
||||
}
|
||||
}(mrfRec)
|
||||
@@ -3351,11 +3333,14 @@ func (p *ReplicationPool) getMRF(ctx context.Context, bucket string) (ch chan ma
|
||||
mrfCh := make(chan madmin.ReplicationMRF, 100)
|
||||
go func() {
|
||||
defer close(mrfCh)
|
||||
for _, diskPath := range globalEndpoints.LocalDisksPaths() {
|
||||
file := filepath.Join(diskPath, minioMetaBucket, replicationMRFDir, globalLocalNodeNameHex+".bin")
|
||||
mrfRec, err := p.loadMRF(file)
|
||||
for _, localDrive := range globalLocalDrives {
|
||||
buf, err := localDrive.ReadAll(ctx, minioMetaBucket, pathJoin(replicationMRFDir, globalLocalNodeNameHex+".bin"))
|
||||
if err != nil {
|
||||
break
|
||||
continue
|
||||
}
|
||||
mrfRec, err := p.loadMRF(buf)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for vID, e := range mrfRec.Entries {
|
||||
if e.Bucket != bucket && bucket != "" {
|
||||
|
||||
@@ -175,6 +175,10 @@ func minioConfigToConsoleFeatures() {
|
||||
if value := env.Get(config.EnvBrowserLoginAnimation, "on"); value != "" {
|
||||
os.Setenv("CONSOLE_ANIMATED_LOGIN", value)
|
||||
}
|
||||
// Pass on the session duration environment variable, else we will default to 12 hours
|
||||
if value := env.Get(config.EnvBrowserSessionDuration, ""); value != "" {
|
||||
os.Setenv("CONSOLE_STS_DURATION", value)
|
||||
}
|
||||
|
||||
os.Setenv("CONSOLE_MINIO_REGION", globalSite.Region)
|
||||
os.Setenv("CONSOLE_CERT_PASSWD", env.Get("MINIO_CERT_PASSWD", ""))
|
||||
|
||||
@@ -440,7 +440,7 @@ func lookupConfigs(s config.Config, objAPI ObjectLayer) {
|
||||
logger.LogIf(ctx, fmt.Errorf("Unable to initialize remote webhook DNS config %w", err))
|
||||
}
|
||||
if err == nil && dnsURL != "" {
|
||||
bootstrapTrace("initialize remote bucket DNS store")
|
||||
bootstrapTraceMsg("initialize remote bucket DNS store")
|
||||
globalDNSConfig, err = dns.NewOperatorDNS(dnsURL,
|
||||
dns.Authentication(dnsUser, dnsPass),
|
||||
dns.RootCAs(globalRootCAs))
|
||||
@@ -455,7 +455,7 @@ func lookupConfigs(s config.Config, objAPI ObjectLayer) {
|
||||
}
|
||||
|
||||
if etcdCfg.Enabled {
|
||||
bootstrapTrace("initialize etcd store")
|
||||
bootstrapTraceMsg("initialize etcd store")
|
||||
globalEtcdClient, err = etcd.New(etcdCfg)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, fmt.Errorf("Unable to initialize etcd config: %w", err))
|
||||
@@ -514,19 +514,19 @@ func lookupConfigs(s config.Config, objAPI ObjectLayer) {
|
||||
|
||||
transport := NewHTTPTransport()
|
||||
|
||||
bootstrapTrace("initialize the event notification targets")
|
||||
bootstrapTraceMsg("initialize the event notification targets")
|
||||
globalNotifyTargetList, err = notify.FetchEnabledTargets(GlobalContext, s, transport)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, fmt.Errorf("Unable to initialize notification target(s): %w", err))
|
||||
}
|
||||
|
||||
bootstrapTrace("initialize the lambda targets")
|
||||
bootstrapTraceMsg("initialize the lambda targets")
|
||||
globalLambdaTargetList, err = lambda.FetchEnabledTargets(GlobalContext, s, transport)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, fmt.Errorf("Unable to initialize lambda target(s): %w", err))
|
||||
}
|
||||
|
||||
bootstrapTrace("applying the dynamic configuration")
|
||||
bootstrapTraceMsg("applying the dynamic configuration")
|
||||
// Apply dynamic config values
|
||||
if err := applyDynamicConfig(ctx, objAPI, s); err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
@@ -786,13 +786,13 @@ func getValidConfig(objAPI ObjectLayer) (config.Config, error) {
|
||||
// from env if found and valid
|
||||
// data is optional. If nil it will be loaded from backend.
|
||||
func loadConfig(objAPI ObjectLayer, data []byte) error {
|
||||
bootstrapTrace("load the configuration")
|
||||
bootstrapTraceMsg("load the configuration")
|
||||
srvCfg, err := readServerConfig(GlobalContext, objAPI, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bootstrapTrace("lookup the configuration")
|
||||
bootstrapTraceMsg("lookup the configuration")
|
||||
// Override any values from ENVs.
|
||||
lookupConfigs(srvCfg, objAPI)
|
||||
|
||||
|
||||
@@ -2423,7 +2423,7 @@ func migrateV27ToV28() error {
|
||||
// Migrates ${HOME}/.minio/config.json to '<export_path>/.minio.sys/config/config.json'
|
||||
// if etcd is configured then migrates /config/config.json to '<export_path>/.minio.sys/config/config.json'
|
||||
func migrateConfigToMinioSys(objAPI ObjectLayer) (err error) {
|
||||
bootstrapTrace("migrate config to .minio.sys/config/config.json")
|
||||
bootstrapTraceMsg("migrate config to .minio.sys/config/config.json")
|
||||
// Construct path to config.json for the given bucket.
|
||||
configFile := path.Join(minioConfigPrefix, minioConfigFile)
|
||||
|
||||
|
||||
+3
-3
@@ -197,10 +197,10 @@ func NewConfigSys() *ConfigSys {
|
||||
|
||||
// Initialize and load config from remote etcd or local config directory
|
||||
func initConfig(objAPI ObjectLayer) (err error) {
|
||||
bootstrapTrace("load the configuration")
|
||||
bootstrapTraceMsg("load the configuration")
|
||||
defer func() {
|
||||
if err != nil {
|
||||
bootstrapTrace(fmt.Sprintf("loading configuration failed: %v", err))
|
||||
bootstrapTraceMsg(fmt.Sprintf("loading configuration failed: %v", err))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -213,7 +213,7 @@ func initConfig(objAPI ObjectLayer) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
bootstrapTrace("lookup the configuration")
|
||||
bootstrapTraceMsg("lookup the configuration")
|
||||
|
||||
// Override any values from ENVs.
|
||||
lookupConfigs(srvCfg, objAPI)
|
||||
|
||||
+4
-5
@@ -550,7 +550,6 @@ func (f *folderScanner) scanFolder(ctx context.Context, folder cachedFolder, int
|
||||
dst = &dataUsageEntry{Compacted: false}
|
||||
}
|
||||
if err := f.scanFolder(ctx, folder, dst); err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return
|
||||
}
|
||||
if !into.Compacted {
|
||||
@@ -1186,10 +1185,10 @@ func applyExpiryOnNonTransitionedObjects(ctx context.Context, objLayer ObjectLay
|
||||
if lcEvent.Action.DeleteVersioned() {
|
||||
opts.VersionID = obj.VersionID
|
||||
}
|
||||
if opts.VersionID == "" {
|
||||
opts.Versioned = globalBucketVersioningSys.PrefixEnabled(obj.Bucket, obj.Name)
|
||||
opts.VersionSuspended = globalBucketVersioningSys.PrefixSuspended(obj.Bucket, obj.Name)
|
||||
}
|
||||
|
||||
opts.Versioned = globalBucketVersioningSys.PrefixEnabled(obj.Bucket, obj.Name)
|
||||
opts.VersionSuspended = globalBucketVersioningSys.PrefixSuspended(obj.Bucket, obj.Name)
|
||||
|
||||
if lcEvent.Action.DeleteAll() {
|
||||
opts.DeletePrefix = true
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
// Copyright (c) 2015-2023 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
@@ -101,7 +101,6 @@ func (er erasureObjects) checkUploadIDExists(ctx context.Context, bucket, object
|
||||
|
||||
// Pick one from the first valid metadata.
|
||||
fi, err = pickValidFileInfo(ctx, partsMetadata, modTime, etag, quorum)
|
||||
|
||||
return fi, partsMetadata, err
|
||||
}
|
||||
|
||||
@@ -310,7 +309,7 @@ func (er erasureObjects) ListMultipartUploads(ctx context.Context, bucket, objec
|
||||
populatedUploadIds.Add(uploadID)
|
||||
uploads = append(uploads, MultipartInfo{
|
||||
Object: object,
|
||||
UploadID: uploadID,
|
||||
UploadID: base64.RawURLEncoding.EncodeToString([]byte(fmt.Sprintf("%s.%s", globalDeploymentID, uploadID))),
|
||||
Initiated: fi.ModTime,
|
||||
})
|
||||
}
|
||||
@@ -954,10 +953,10 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str
|
||||
if err != nil {
|
||||
return oi, err
|
||||
}
|
||||
wctx := wlkctx.Context()
|
||||
ctx = wlkctx.Context()
|
||||
defer uploadIDLock.Unlock(wlkctx)
|
||||
|
||||
fi, partsMetadata, err := er.checkUploadIDExists(wctx, bucket, object, uploadID, true)
|
||||
fi, partsMetadata, err := er.checkUploadIDExists(ctx, bucket, object, uploadID, true)
|
||||
if err != nil {
|
||||
return oi, toObjectErr(err, bucket, object, uploadID)
|
||||
}
|
||||
@@ -1227,12 +1226,6 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str
|
||||
ctx = lkctx.Context()
|
||||
defer lk.Unlock(lkctx)
|
||||
|
||||
// Write final `xl.meta` at uploadID location
|
||||
onlineDisks, err = writeUniqueFileInfo(ctx, onlineDisks, minioMetaMultipartBucket, uploadIDPath, partsMetadata, writeQuorum)
|
||||
if err != nil {
|
||||
return oi, toObjectErr(err, minioMetaMultipartBucket, uploadIDPath)
|
||||
}
|
||||
|
||||
// Remove parts that weren't present in CompleteMultipartUpload request.
|
||||
for _, curpart := range currentFI.Parts {
|
||||
if objectPartIndex(fi.Parts, curpart.Number) == -1 {
|
||||
@@ -1242,13 +1235,13 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str
|
||||
// Request 3: PutObjectPart 2
|
||||
// Request 4: CompleteMultipartUpload --part 2
|
||||
// N.B. 1st part is not present. This part should be removed from the storage.
|
||||
er.removeObjectPart(bucket, object, uploadID, fi.DataDir, curpart.Number)
|
||||
er.removeObjectPart(bucket, object, uploadID, currentFI.DataDir, curpart.Number)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove part.meta which is not needed anymore.
|
||||
for _, part := range fi.Parts {
|
||||
er.removePartMeta(bucket, object, uploadID, fi.DataDir, part.Number)
|
||||
for _, part := range currentFI.Parts {
|
||||
er.removePartMeta(bucket, object, uploadID, currentFI.DataDir, part.Number)
|
||||
}
|
||||
|
||||
// Rename the multipart object to final location.
|
||||
|
||||
@@ -1488,7 +1488,7 @@ func (z *erasureServerPools) CopyObjectPart(ctx context.Context, srcBucket, srcO
|
||||
|
||||
// PutObjectPart - writes part of an object to hashedSet based on the object name.
|
||||
func (z *erasureServerPools) PutObjectPart(ctx context.Context, bucket, object, uploadID string, partID int, data *PutObjReader, opts ObjectOptions) (PartInfo, error) {
|
||||
if err := checkPutObjectPartArgs(ctx, bucket, object, z); err != nil {
|
||||
if err := checkPutObjectPartArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
return PartInfo{}, err
|
||||
}
|
||||
|
||||
@@ -1520,7 +1520,7 @@ func (z *erasureServerPools) PutObjectPart(ctx context.Context, bucket, object,
|
||||
}
|
||||
|
||||
func (z *erasureServerPools) GetMultipartInfo(ctx context.Context, bucket, object, uploadID string, opts ObjectOptions) (MultipartInfo, error) {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, z); err != nil {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
return MultipartInfo{}, err
|
||||
}
|
||||
|
||||
@@ -1551,7 +1551,7 @@ func (z *erasureServerPools) GetMultipartInfo(ctx context.Context, bucket, objec
|
||||
|
||||
// ListObjectParts - lists all uploaded parts to an object in hashedSet.
|
||||
func (z *erasureServerPools) ListObjectParts(ctx context.Context, bucket, object, uploadID string, partNumberMarker int, maxParts int, opts ObjectOptions) (ListPartsInfo, error) {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, z); err != nil {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
return ListPartsInfo{}, err
|
||||
}
|
||||
|
||||
@@ -1580,7 +1580,7 @@ func (z *erasureServerPools) ListObjectParts(ctx context.Context, bucket, object
|
||||
|
||||
// Aborts an in-progress multipart operation on hashedSet based on the object name.
|
||||
func (z *erasureServerPools) AbortMultipartUpload(ctx context.Context, bucket, object, uploadID string, opts ObjectOptions) error {
|
||||
if err := checkAbortMultipartArgs(ctx, bucket, object, z); err != nil {
|
||||
if err := checkAbortMultipartArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1611,7 +1611,7 @@ func (z *erasureServerPools) AbortMultipartUpload(ctx context.Context, bucket, o
|
||||
|
||||
// CompleteMultipartUpload - completes a pending multipart transaction, on hashedSet based on object name.
|
||||
func (z *erasureServerPools) CompleteMultipartUpload(ctx context.Context, bucket, object, uploadID string, uploadedParts []CompletePart, opts ObjectOptions) (objInfo ObjectInfo, err error) {
|
||||
if err = checkCompleteMultipartArgs(ctx, bucket, object, z); err != nil {
|
||||
if err = checkCompleteMultipartArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
return objInfo, err
|
||||
}
|
||||
|
||||
|
||||
+11
-9
@@ -384,10 +384,12 @@ func (iamOS *IAMObjectStore) listAllIAMConfigItems(ctx context.Context) (map[str
|
||||
|
||||
// Assumes cache is locked by caller.
|
||||
func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iamCache) error {
|
||||
bootstrapTrace("loading all IAM items")
|
||||
if iamOS.objAPI == nil {
|
||||
return errServerNotInitialized
|
||||
}
|
||||
|
||||
bootstrapTraceMsg("loading all IAM items")
|
||||
|
||||
listedConfigItems, err := iamOS.listAllIAMConfigItems(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list IAM data: %w", err)
|
||||
@@ -395,7 +397,7 @@ func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iam
|
||||
|
||||
// Loads things in the same order as `LoadIAMCache()`
|
||||
|
||||
bootstrapTrace("loading policy documents")
|
||||
bootstrapTraceMsg("loading policy documents")
|
||||
|
||||
policiesList := listedConfigItems[policiesListKey]
|
||||
for _, item := range policiesList {
|
||||
@@ -407,7 +409,7 @@ func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iam
|
||||
setDefaultCannedPolicies(cache.iamPolicyDocsMap)
|
||||
|
||||
if iamOS.usersSysType == MinIOUsersSysType {
|
||||
bootstrapTrace("loading regular IAM users")
|
||||
bootstrapTraceMsg("loading regular IAM users")
|
||||
regUsersList := listedConfigItems[usersListKey]
|
||||
for _, item := range regUsersList {
|
||||
userName := path.Dir(item)
|
||||
@@ -416,7 +418,7 @@ func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iam
|
||||
}
|
||||
}
|
||||
|
||||
bootstrapTrace("loading regular IAM groups")
|
||||
bootstrapTraceMsg("loading regular IAM groups")
|
||||
groupsList := listedConfigItems[groupsListKey]
|
||||
for _, item := range groupsList {
|
||||
group := path.Dir(item)
|
||||
@@ -426,7 +428,7 @@ func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iam
|
||||
}
|
||||
}
|
||||
|
||||
bootstrapTrace("loading user policy mapping")
|
||||
bootstrapTraceMsg("loading user policy mapping")
|
||||
userPolicyMappingsList := listedConfigItems[policyDBUsersListKey]
|
||||
for _, item := range userPolicyMappingsList {
|
||||
userName := strings.TrimSuffix(item, ".json")
|
||||
@@ -435,7 +437,7 @@ func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iam
|
||||
}
|
||||
}
|
||||
|
||||
bootstrapTrace("loading group policy mapping")
|
||||
bootstrapTraceMsg("loading group policy mapping")
|
||||
groupPolicyMappingsList := listedConfigItems[policyDBGroupsListKey]
|
||||
for _, item := range groupPolicyMappingsList {
|
||||
groupName := strings.TrimSuffix(item, ".json")
|
||||
@@ -444,7 +446,7 @@ func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iam
|
||||
}
|
||||
}
|
||||
|
||||
bootstrapTrace("loading service accounts")
|
||||
bootstrapTraceMsg("loading service accounts")
|
||||
svcAccList := listedConfigItems[svcAccListKey]
|
||||
for _, item := range svcAccList {
|
||||
userName := path.Dir(item)
|
||||
@@ -453,7 +455,7 @@ func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iam
|
||||
}
|
||||
}
|
||||
|
||||
bootstrapTrace("loading STS users")
|
||||
bootstrapTraceMsg("loading STS users")
|
||||
stsUsersList := listedConfigItems[stsListKey]
|
||||
for _, item := range stsUsersList {
|
||||
userName := path.Dir(item)
|
||||
@@ -462,7 +464,7 @@ func (iamOS *IAMObjectStore) loadAllFromObjStore(ctx context.Context, cache *iam
|
||||
}
|
||||
}
|
||||
|
||||
bootstrapTrace("loading STS policy mapping")
|
||||
bootstrapTraceMsg("loading STS policy mapping")
|
||||
stsPolicyMappingsList := listedConfigItems[policyDBSTSUsersListKey]
|
||||
for _, item := range stsPolicyMappingsList {
|
||||
stsName := strings.TrimSuffix(item, ".json")
|
||||
|
||||
+11
-11
@@ -109,7 +109,7 @@ func getUserIdentityPath(user string, userType IAMUserType) string {
|
||||
}
|
||||
|
||||
func saveIAMFormat(ctx context.Context, store IAMStorageAPI) error {
|
||||
bootstrapTrace("Load IAM format file")
|
||||
bootstrapTraceMsg("Load IAM format file")
|
||||
var iamFmt iamFormat
|
||||
path := getIAMFormatFilePath()
|
||||
if err := store.loadIAMConfig(ctx, &iamFmt, path); err != nil {
|
||||
@@ -127,7 +127,7 @@ func saveIAMFormat(ctx context.Context, store IAMStorageAPI) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
bootstrapTrace("Write IAM format file")
|
||||
bootstrapTraceMsg("Write IAM format file")
|
||||
// Save iam format to version 1.
|
||||
if err := store.saveIAMConfig(ctx, newIAMFormatVersion1(), path); err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
@@ -462,7 +462,7 @@ func setDefaultCannedPolicies(policies map[string]PolicyDoc) {
|
||||
// LoadIAMCache reads all IAM items and populates a new iamCache object and
|
||||
// replaces the in-memory cache object.
|
||||
func (store *IAMStoreSys) LoadIAMCache(ctx context.Context) error {
|
||||
bootstrapTrace("loading IAM data")
|
||||
bootstrapTraceMsg("loading IAM data")
|
||||
|
||||
newCache := newIamCache()
|
||||
|
||||
@@ -475,7 +475,7 @@ func (store *IAMStoreSys) LoadIAMCache(ctx context.Context) error {
|
||||
}
|
||||
} else {
|
||||
|
||||
bootstrapTrace("loading policy documents")
|
||||
bootstrapTraceMsg("loading policy documents")
|
||||
if err := store.loadPolicyDocs(ctx, newCache.iamPolicyDocsMap); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -484,41 +484,41 @@ func (store *IAMStoreSys) LoadIAMCache(ctx context.Context) error {
|
||||
setDefaultCannedPolicies(newCache.iamPolicyDocsMap)
|
||||
|
||||
if store.getUsersSysType() == MinIOUsersSysType {
|
||||
bootstrapTrace("loading regular users")
|
||||
bootstrapTraceMsg("loading regular users")
|
||||
if err := store.loadUsers(ctx, regUser, newCache.iamUsersMap); err != nil {
|
||||
return err
|
||||
}
|
||||
bootstrapTrace("loading regular groups")
|
||||
bootstrapTraceMsg("loading regular groups")
|
||||
if err := store.loadGroups(ctx, newCache.iamGroupsMap); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
bootstrapTrace("loading user policy mapping")
|
||||
bootstrapTraceMsg("loading user policy mapping")
|
||||
// load polices mapped to users
|
||||
if err := store.loadMappedPolicies(ctx, regUser, false, newCache.iamUserPolicyMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bootstrapTrace("loading group policy mapping")
|
||||
bootstrapTraceMsg("loading group policy mapping")
|
||||
// load policies mapped to groups
|
||||
if err := store.loadMappedPolicies(ctx, regUser, true, newCache.iamGroupPolicyMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bootstrapTrace("loading service accounts")
|
||||
bootstrapTraceMsg("loading service accounts")
|
||||
// load service accounts
|
||||
if err := store.loadUsers(ctx, svcUser, newCache.iamUsersMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bootstrapTrace("loading STS users")
|
||||
bootstrapTraceMsg("loading STS users")
|
||||
// load STS temp users
|
||||
if err := store.loadUsers(ctx, stsUser, newCache.iamUsersMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bootstrapTrace("loading STS policy mapping")
|
||||
bootstrapTraceMsg("loading STS policy mapping")
|
||||
// load STS policy mappings
|
||||
if err := store.loadMappedPolicies(ctx, stsUser, false, newCache.iamUserPolicyMap); err != nil {
|
||||
return err
|
||||
|
||||
+12
-18
@@ -187,7 +187,7 @@ func (sys *IAMSys) Initialized() bool {
|
||||
}
|
||||
|
||||
// Load - loads all credentials, policies and policy mappings.
|
||||
func (sys *IAMSys) Load(ctx context.Context) error {
|
||||
func (sys *IAMSys) Load(ctx context.Context, firstTime bool) error {
|
||||
loadStartTime := time.Now()
|
||||
err := sys.store.LoadIAMCache(ctx)
|
||||
if err != nil {
|
||||
@@ -200,6 +200,10 @@ func (sys *IAMSys) Load(ctx context.Context) error {
|
||||
atomic.StoreUint64(&sys.LastRefreshTimeUnixNano, uint64(loadStartTime.Add(loadDuration).UnixNano()))
|
||||
atomic.AddUint64(&sys.TotalRefreshSuccesses, 1)
|
||||
|
||||
if firstTime {
|
||||
bootstrapTraceMsg(fmt.Sprintf("globalIAMSys.Load(): (duration: %s)", loadDuration))
|
||||
}
|
||||
|
||||
select {
|
||||
case <-sys.configLoaded:
|
||||
default:
|
||||
@@ -210,7 +214,7 @@ func (sys *IAMSys) Load(ctx context.Context) error {
|
||||
|
||||
// Init - initializes config system by reading entries from config/iam
|
||||
func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer, etcdClient *etcd.Client, iamRefreshInterval time.Duration) {
|
||||
bootstrapTrace("IAM initialization started")
|
||||
bootstrapTraceMsg("IAM initialization started")
|
||||
globalServerConfigMu.RLock()
|
||||
s := globalServerConfig
|
||||
globalServerConfigMu.RUnlock()
|
||||
@@ -300,7 +304,7 @@ func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer, etcdClient *etc
|
||||
|
||||
// Load IAM data from storage.
|
||||
for {
|
||||
if err := sys.Load(retryCtx); err != nil {
|
||||
if err := sys.Load(retryCtx, true); err != nil {
|
||||
if configRetriableErrors(err) {
|
||||
logger.Info("Waiting for all MinIO IAM sub-system to be initialized.. possible cause (%v)", err)
|
||||
time.Sleep(time.Duration(r.Float64() * float64(5*time.Second)))
|
||||
@@ -313,8 +317,6 @@ func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer, etcdClient *etc
|
||||
break
|
||||
}
|
||||
|
||||
bootstrapTrace("finishing IAM loading")
|
||||
|
||||
refreshInterval := sys.iamRefreshInterval
|
||||
|
||||
// Set up polling for expired accounts and credentials purging.
|
||||
@@ -371,6 +373,8 @@ func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer, etcdClient *etc
|
||||
}
|
||||
|
||||
sys.printIAMRoles()
|
||||
|
||||
bootstrapTraceMsg("finishing IAM loading")
|
||||
}
|
||||
|
||||
func (sys *IAMSys) validateAndAddRolePolicyMappings(ctx context.Context, m map[arn.ARN]string) {
|
||||
@@ -446,7 +450,7 @@ func (sys *IAMSys) watch(ctx context.Context) {
|
||||
select {
|
||||
case <-timer.C:
|
||||
refreshStart := time.Now()
|
||||
if err := sys.Load(ctx); err != nil {
|
||||
if err := sys.Load(ctx, false); err != nil {
|
||||
logger.LogIf(ctx, fmt.Errorf("Failure in periodic refresh for IAM (took %.2fs): %v", time.Since(refreshStart).Seconds(), err))
|
||||
} else {
|
||||
took := time.Since(refreshStart).Seconds()
|
||||
@@ -590,12 +594,7 @@ func (sys *IAMSys) ListPolicies(ctx context.Context, bucketName string) (map[str
|
||||
return nil, errServerNotInitialized
|
||||
}
|
||||
|
||||
select {
|
||||
case <-sys.configLoaded:
|
||||
return sys.store.ListPolicies(ctx, bucketName)
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
return sys.store.ListPolicies(ctx, bucketName)
|
||||
}
|
||||
|
||||
// ListPolicyDocs - lists all canned policy docs.
|
||||
@@ -604,12 +603,7 @@ func (sys *IAMSys) ListPolicyDocs(ctx context.Context, bucketName string) (map[s
|
||||
return nil, errServerNotInitialized
|
||||
}
|
||||
|
||||
select {
|
||||
case <-sys.configLoaded:
|
||||
return sys.store.ListPolicyDocs(ctx, bucketName)
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
return sys.store.ListPolicyDocs(ctx, bucketName)
|
||||
}
|
||||
|
||||
// SetPolicy - sets a new named policy.
|
||||
|
||||
+50
-46
@@ -20,7 +20,9 @@ package cmd
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/minio/kes-go"
|
||||
@@ -258,15 +260,26 @@ func (a kmsAPIHandlers) KMSListKeysHandler(w http.ResponseWriter, r *http.Reques
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrKMSNotConfigured), r.URL)
|
||||
return
|
||||
}
|
||||
keys, err := manager.ListKeys(ctx, r.Form.Get("pattern"))
|
||||
keys, err := manager.ListKeys(ctx)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
values, err := keys.Values(0)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
|
||||
pattern := r.Form.Get("pattern")
|
||||
if !strings.Contains(pattern, "*") {
|
||||
pattern += "*"
|
||||
}
|
||||
|
||||
var values []kes.KeyInfo
|
||||
for name, err := keys.SeekTo(ctx, pattern); err != io.EOF; name, err = keys.Next(ctx) {
|
||||
if err != nil {
|
||||
writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL)
|
||||
return
|
||||
}
|
||||
values = append(values, kes.KeyInfo{
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
if res, err := json.Marshal(values); err != nil {
|
||||
writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL)
|
||||
@@ -454,37 +467,6 @@ func (a kmsAPIHandlers) KMSAssignPolicyHandler(w http.ResponseWriter, r *http.Re
|
||||
writeSuccessResponseHeadersOnly(w)
|
||||
}
|
||||
|
||||
// KMSSetPolicyHandler - POST /minio/kms/v1/policy/policy?policy=<policy>
|
||||
func (a kmsAPIHandlers) KMSSetPolicyHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "KMSSetPolicy")
|
||||
defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))
|
||||
|
||||
objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.KMSSetPolicyAction)
|
||||
if objectAPI == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if GlobalKMS == nil {
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrKMSNotConfigured), r.URL)
|
||||
return
|
||||
}
|
||||
manager, ok := GlobalKMS.(kms.PolicyManager)
|
||||
if !ok {
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||
return
|
||||
}
|
||||
var policy kes.Policy
|
||||
if err := json.NewDecoder(r.Body).Decode(&policy); err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
if err := manager.SetPolicy(ctx, r.Form.Get("policy"), &policy); err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
writeSuccessResponseHeadersOnly(w)
|
||||
}
|
||||
|
||||
// KMSDeletePolicyHandler - DELETE /minio/kms/v1/policy/delete?policy=<policy>
|
||||
func (a kmsAPIHandlers) KMSDeletePolicyHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "KMSDeletePolicy")
|
||||
@@ -531,15 +513,26 @@ func (a kmsAPIHandlers) KMSListPoliciesHandler(w http.ResponseWriter, r *http.Re
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||
return
|
||||
}
|
||||
policies, err := manager.ListPolicies(ctx, r.Form.Get("pattern"))
|
||||
policies, err := manager.ListPolicies(ctx)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
values, err := policies.Values(0)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
|
||||
pattern := r.Form.Get("pattern")
|
||||
if !strings.Contains(pattern, "*") {
|
||||
pattern += "*"
|
||||
}
|
||||
|
||||
var values []kes.PolicyInfo
|
||||
for name, err := policies.SeekTo(ctx, pattern); err != io.EOF; name, err = policies.Next(ctx) {
|
||||
if err != nil {
|
||||
writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL)
|
||||
return
|
||||
}
|
||||
values = append(values, kes.PolicyInfo{
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
if res, err := json.Marshal(values); err != nil {
|
||||
writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL)
|
||||
@@ -707,15 +700,26 @@ func (a kmsAPIHandlers) KMSListIdentitiesHandler(w http.ResponseWriter, r *http.
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||
return
|
||||
}
|
||||
identities, err := manager.ListIdentities(ctx, r.Form.Get("pattern"))
|
||||
identities, err := manager.ListIdentities(ctx)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
values, err := identities.Values(0)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
|
||||
pattern := r.Form.Get("pattern")
|
||||
if !strings.Contains(pattern, "*") {
|
||||
pattern += "*"
|
||||
}
|
||||
|
||||
var values []kes.IdentityInfo
|
||||
for name, err := identities.SeekTo(ctx, pattern); err != io.EOF; name, err = identities.Next(ctx) {
|
||||
if err != nil {
|
||||
writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL)
|
||||
return
|
||||
}
|
||||
values = append(values, kes.IdentityInfo{
|
||||
Identity: name,
|
||||
})
|
||||
}
|
||||
if res, err := json.Marshal(values); err != nil {
|
||||
writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL)
|
||||
|
||||
@@ -63,7 +63,6 @@ func registerKMSRouter(router *mux.Router) {
|
||||
kmsRouter.Methods(http.MethodGet).Path(version + "/key/status").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSKeyStatusHandler)))
|
||||
|
||||
// KMS Policy APIs
|
||||
kmsRouter.Methods(http.MethodPost).Path(version+"/policy/set").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSSetPolicyHandler))).Queries("policy", "{policy:.*}")
|
||||
kmsRouter.Methods(http.MethodPost).Path(version+"/policy/assign").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSAssignPolicyHandler))).Queries("policy", "{policy:.*}")
|
||||
kmsRouter.Methods(http.MethodGet).Path(version+"/policy/describe").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSDescribePolicyHandler))).Queries("policy", "{policy:.*}")
|
||||
kmsRouter.Methods(http.MethodGet).Path(version+"/policy/get").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSGetPolicyHandler))).Queries("policy", "{policy:.*}")
|
||||
|
||||
+2
-3
@@ -1520,15 +1520,14 @@ func (sys *NotificationSys) GetReplicationMRF(ctx context.Context, bucket, node
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return err
|
||||
default:
|
||||
mrfCh <- e
|
||||
case mrfCh <- e:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(mrfCh)
|
||||
go func(wg *sync.WaitGroup) {
|
||||
wg.Wait()
|
||||
defer close(mrfCh)
|
||||
close(mrfCh)
|
||||
}(&wg)
|
||||
return mrfCh, nil
|
||||
}
|
||||
|
||||
@@ -99,7 +99,6 @@ func checkListMultipartArgs(ctx context.Context, bucket, prefix, keyMarker, uplo
|
||||
}
|
||||
if uploadIDMarker != "" {
|
||||
if HasSuffix(keyMarker, SlashSeparator) {
|
||||
|
||||
logger.LogIf(ctx, InvalidUploadIDKeyCombination{
|
||||
UploadIDMarker: uploadIDMarker,
|
||||
KeyMarker: keyMarker,
|
||||
@@ -125,24 +124,34 @@ func checkNewMultipartArgs(ctx context.Context, bucket, object string, obj Objec
|
||||
return checkObjectArgs(ctx, bucket, object, obj)
|
||||
}
|
||||
|
||||
// Checks for PutObjectPart arguments validity, also validates if bucket exists.
|
||||
func checkPutObjectPartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
|
||||
func checkMultipartObjectArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
_, err := base64.RawURLEncoding.DecodeString(uploadID)
|
||||
if err != nil {
|
||||
return MalformedUploadID{
|
||||
UploadID: uploadID,
|
||||
}
|
||||
}
|
||||
return checkObjectArgs(ctx, bucket, object, obj)
|
||||
}
|
||||
|
||||
// Checks for PutObjectPart arguments validity, also validates if bucket exists.
|
||||
func checkPutObjectPartArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID, obj)
|
||||
}
|
||||
|
||||
// Checks for ListParts arguments validity, also validates if bucket exists.
|
||||
func checkListPartsArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
|
||||
return checkObjectArgs(ctx, bucket, object, obj)
|
||||
func checkListPartsArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID, obj)
|
||||
}
|
||||
|
||||
// Checks for CompleteMultipartUpload arguments validity, also validates if bucket exists.
|
||||
func checkCompleteMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
|
||||
return checkObjectArgs(ctx, bucket, object, obj)
|
||||
func checkCompleteMultipartArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID, obj)
|
||||
}
|
||||
|
||||
// Checks for AbortMultipartUpload arguments validity, also validates if bucket exists.
|
||||
func checkAbortMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
|
||||
return checkObjectArgs(ctx, bucket, object, obj)
|
||||
func checkAbortMultipartArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID, obj)
|
||||
}
|
||||
|
||||
// Checks Object arguments validity, also validates if bucket exists.
|
||||
|
||||
@@ -951,8 +951,6 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
|
||||
}
|
||||
}
|
||||
|
||||
setEventStreamHeaders(w)
|
||||
|
||||
opts, err := completeMultipartOpts(ctx, r, bucket, object)
|
||||
if err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||
|
||||
@@ -488,12 +488,10 @@ func (client *peerRESTClient) BackgroundHealStatus() (madmin.BgHealState, error)
|
||||
func (client *peerRESTClient) GetLocalDiskIDs(ctx context.Context) (diskIDs []string) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodGetLocalDiskIDs, nil, nil, -1)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return nil
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
if err = gob.NewDecoder(respBody).Decode(&diskIDs); err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return nil
|
||||
}
|
||||
return diskIDs
|
||||
@@ -513,7 +511,6 @@ func (client *peerRESTClient) GetMetacacheListing(ctx context.Context, o listPat
|
||||
}
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodGetMetacacheListing, nil, &reader, int64(reader.Len()))
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return nil, err
|
||||
}
|
||||
var resp metacache
|
||||
@@ -532,7 +529,6 @@ func (client *peerRESTClient) UpdateMetacacheListing(ctx context.Context, m meta
|
||||
}
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodUpdateMetacacheListing, nil, bytes.NewBuffer(b), int64(len(b)))
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return m, err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
@@ -543,7 +539,6 @@ func (client *peerRESTClient) UpdateMetacacheListing(ctx context.Context, m meta
|
||||
func (client *peerRESTClient) ReloadPoolMeta(ctx context.Context) error {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodReloadPoolMeta, nil, nil, 0)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
@@ -553,7 +548,6 @@ func (client *peerRESTClient) ReloadPoolMeta(ctx context.Context) error {
|
||||
func (client *peerRESTClient) StopRebalance(ctx context.Context) error {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodStopRebalance, nil, nil, 0)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
@@ -565,7 +559,6 @@ func (client *peerRESTClient) LoadRebalanceMeta(ctx context.Context, startRebala
|
||||
values.Set(peerRESTStartRebalance, strconv.FormatBool(startRebalance))
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodLoadRebalanceMeta, values, nil, 0)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
@@ -575,7 +568,6 @@ func (client *peerRESTClient) LoadRebalanceMeta(ctx context.Context, startRebala
|
||||
func (client *peerRESTClient) LoadTransitionTierConfig(ctx context.Context) error {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodLoadTransitionTierConfig, nil, nil, 0)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
|
||||
+216
-166
@@ -392,23 +392,51 @@ func configRetriableErrors(err error) bool {
|
||||
errors.Is(err, os.ErrDeadlineExceeded)
|
||||
}
|
||||
|
||||
func bootstrapTrace(msg string) {
|
||||
globalBootstrapTracer.Record(msg, 2)
|
||||
func bootstrapTraceMsg(msg string) {
|
||||
info := madmin.TraceInfo{
|
||||
TraceType: madmin.TraceBootstrap,
|
||||
Time: UTCNow(),
|
||||
NodeName: globalLocalNodeName,
|
||||
FuncName: "BOOTSTRAP",
|
||||
Message: fmt.Sprintf("%s %s", getSource(2), msg),
|
||||
}
|
||||
globalBootstrapTracer.Record(info)
|
||||
|
||||
if serverDebugLog {
|
||||
logger.Info(fmt.Sprint(time.Now().Round(time.Millisecond).Format(time.RFC3339), " bootstrap: ", msg))
|
||||
}
|
||||
|
||||
noSubs := globalTrace.NumSubscribers(madmin.TraceBootstrap) == 0
|
||||
if noSubs {
|
||||
return
|
||||
}
|
||||
|
||||
globalTrace.Publish(info)
|
||||
}
|
||||
|
||||
func bootstrapTrace(msg string, worker func()) {
|
||||
if serverDebugLog {
|
||||
logger.Info(fmt.Sprint(time.Now().Round(time.Millisecond).Format(time.RFC3339), " bootstrap: ", msg))
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
worker()
|
||||
dur := time.Since(now)
|
||||
|
||||
info := madmin.TraceInfo{
|
||||
TraceType: madmin.TraceBootstrap,
|
||||
Time: UTCNow(),
|
||||
NodeName: globalLocalNodeName,
|
||||
FuncName: "BOOTSTRAP",
|
||||
Message: fmt.Sprintf("%s %s (duration: %s)", getSource(2), msg, dur),
|
||||
}
|
||||
globalBootstrapTracer.Record(info)
|
||||
|
||||
if globalTrace.NumSubscribers(madmin.TraceBootstrap) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
globalTrace.Publish(madmin.TraceInfo{
|
||||
TraceType: madmin.TraceBootstrap,
|
||||
Time: time.Now().UTC(),
|
||||
NodeName: globalLocalNodeName,
|
||||
FuncName: "BOOTSTRAP",
|
||||
Message: fmt.Sprintf("%s %s", getSource(2), msg),
|
||||
})
|
||||
globalTrace.Publish(info)
|
||||
}
|
||||
|
||||
func initServerConfig(ctx context.Context, newObject ObjectLayer) error {
|
||||
@@ -548,40 +576,40 @@ func serverMain(ctx *cli.Context) {
|
||||
|
||||
setDefaultProfilerRates()
|
||||
|
||||
// Initialize globalConsoleSys system
|
||||
bootstrapTrace("newConsoleLogger")
|
||||
globalConsoleSys = NewConsoleLogger(GlobalContext)
|
||||
logger.AddSystemTarget(GlobalContext, globalConsoleSys)
|
||||
|
||||
// Perform any self-tests
|
||||
bootstrapTrace("selftests")
|
||||
bitrotSelfTest()
|
||||
erasureSelfTest()
|
||||
compressSelfTest()
|
||||
|
||||
// Handle all server environment vars.
|
||||
bootstrapTrace("serverHandleEnvVars")
|
||||
serverHandleEnvVars()
|
||||
|
||||
// Handle all server command args.
|
||||
bootstrapTrace("serverHandleCmdArgs")
|
||||
serverHandleCmdArgs(ctx)
|
||||
bootstrapTrace("serverHandleCmdArgs", func() {
|
||||
serverHandleCmdArgs(ctx)
|
||||
})
|
||||
|
||||
// Initialize globalConsoleSys system
|
||||
bootstrapTrace("newConsoleLogger", func() {
|
||||
globalConsoleSys = NewConsoleLogger(GlobalContext)
|
||||
logger.AddSystemTarget(GlobalContext, globalConsoleSys)
|
||||
|
||||
// Set node name, only set for distributed setup.
|
||||
globalConsoleSys.SetNodeName(globalLocalNodeName)
|
||||
})
|
||||
|
||||
// Perform any self-tests
|
||||
bootstrapTrace("selftests", func() {
|
||||
bitrotSelfTest()
|
||||
erasureSelfTest()
|
||||
compressSelfTest()
|
||||
})
|
||||
|
||||
// Initialize KMS configuration
|
||||
bootstrapTrace("handleKMSConfig")
|
||||
handleKMSConfig()
|
||||
|
||||
// Set node name, only set for distributed setup.
|
||||
bootstrapTrace("setNodeName")
|
||||
globalConsoleSys.SetNodeName(globalLocalNodeName)
|
||||
bootstrapTrace("handleKMSConfig", handleKMSConfig)
|
||||
|
||||
// Initialize all help
|
||||
bootstrapTrace("initHelp")
|
||||
initHelp()
|
||||
bootstrapTrace("initHelp", initHelp)
|
||||
|
||||
// Initialize all sub-systems
|
||||
bootstrapTrace("initAllSubsystems")
|
||||
initAllSubsystems(GlobalContext)
|
||||
bootstrapTrace("initAllSubsystems", func() {
|
||||
initAllSubsystems(GlobalContext)
|
||||
})
|
||||
|
||||
// Is distributed setup, error out if no certificates are found for HTTPS endpoints.
|
||||
if globalIsDistErasure {
|
||||
@@ -597,14 +625,16 @@ func serverMain(ctx *cli.Context) {
|
||||
go func() {
|
||||
if !globalCLIContext.Quiet && !globalInplaceUpdateDisabled {
|
||||
// Check for new updates from dl.min.io.
|
||||
bootstrapTrace("checkUpdate")
|
||||
checkUpdate(getMinioMode())
|
||||
bootstrapTrace("checkUpdate", func() {
|
||||
checkUpdate(getMinioMode())
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
// Set system resources to maximum.
|
||||
bootstrapTrace("setMaxResources")
|
||||
setMaxResources()
|
||||
bootstrapTrace("setMaxResources", func() {
|
||||
_ = setMaxResources()
|
||||
})
|
||||
|
||||
// Verify kernel release and version.
|
||||
if oldLinux() {
|
||||
@@ -617,64 +647,65 @@ func serverMain(ctx *cli.Context) {
|
||||
logger.Info(color.RedBoldf("WARNING: Detected GOMAXPROCS(%d) < NumCPU(%d), please make sure to provide all PROCS to MinIO for optimal performance", maxProcs, cpuProcs))
|
||||
}
|
||||
|
||||
// Configure server.
|
||||
bootstrapTrace("configureServerHandler")
|
||||
handler, err := configureServerHandler(globalEndpoints)
|
||||
if err != nil {
|
||||
logger.Fatal(config.ErrUnexpectedError(err), "Unable to configure one of server's RPC services")
|
||||
}
|
||||
|
||||
var getCert certs.GetCertificateFunc
|
||||
if globalTLSCerts != nil {
|
||||
getCert = globalTLSCerts.GetCertificate
|
||||
}
|
||||
|
||||
bootstrapTrace("xhttp.NewServer")
|
||||
httpServer := xhttp.NewServer(getServerListenAddrs()).
|
||||
UseHandler(setCriticalErrorHandler(corsHandler(handler))).
|
||||
UseTLSConfig(newTLSConfig(getCert)).
|
||||
UseShutdownTimeout(ctx.Duration("shutdown-timeout")).
|
||||
UseIdleTimeout(ctx.Duration("idle-timeout")).
|
||||
UseReadHeaderTimeout(ctx.Duration("read-header-timeout")).
|
||||
UseBaseContext(GlobalContext).
|
||||
UseCustomLogger(log.New(io.Discard, "", 0)). // Turn-off random logging by Go stdlib
|
||||
UseTCPOptions(globalTCPOptions)
|
||||
|
||||
httpServer.TCPOptions.Trace = bootstrapTrace
|
||||
go func() {
|
||||
serveFn, err := httpServer.Init(GlobalContext, func(listenAddr string, err error) {
|
||||
logger.LogIf(GlobalContext, fmt.Errorf("Unable to listen on `%s`: %v", listenAddr, err))
|
||||
})
|
||||
// Configure server.
|
||||
bootstrapTrace("configureServer", func() {
|
||||
handler, err := configureServerHandler(globalEndpoints)
|
||||
if err != nil {
|
||||
globalHTTPServerErrorCh <- err
|
||||
return
|
||||
logger.Fatal(config.ErrUnexpectedError(err), "Unable to configure one of server's RPC services")
|
||||
}
|
||||
globalHTTPServerErrorCh <- serveFn()
|
||||
}()
|
||||
|
||||
bootstrapTrace("setHTTPServer")
|
||||
setHTTPServer(httpServer)
|
||||
httpServer := xhttp.NewServer(getServerListenAddrs()).
|
||||
UseHandler(setCriticalErrorHandler(corsHandler(handler))).
|
||||
UseTLSConfig(newTLSConfig(getCert)).
|
||||
UseShutdownTimeout(ctx.Duration("shutdown-timeout")).
|
||||
UseIdleTimeout(ctx.Duration("idle-timeout")).
|
||||
UseReadHeaderTimeout(ctx.Duration("read-header-timeout")).
|
||||
UseBaseContext(GlobalContext).
|
||||
UseCustomLogger(log.New(io.Discard, "", 0)). // Turn-off random logging by Go stdlib
|
||||
UseTCPOptions(globalTCPOptions)
|
||||
|
||||
httpServer.TCPOptions.Trace = bootstrapTraceMsg
|
||||
go func() {
|
||||
serveFn, err := httpServer.Init(GlobalContext, func(listenAddr string, err error) {
|
||||
logger.LogIf(GlobalContext, fmt.Errorf("Unable to listen on `%s`: %v", listenAddr, err))
|
||||
})
|
||||
if err != nil {
|
||||
globalHTTPServerErrorCh <- err
|
||||
return
|
||||
}
|
||||
globalHTTPServerErrorCh <- serveFn()
|
||||
}()
|
||||
|
||||
setHTTPServer(httpServer)
|
||||
})
|
||||
|
||||
if globalIsDistErasure {
|
||||
bootstrapTrace("verifying system configuration")
|
||||
// Additionally in distributed setup, validate the setup and configuration.
|
||||
if err := verifyServerSystemConfig(GlobalContext, globalEndpoints); err != nil {
|
||||
logger.Fatal(err, "Unable to start the server")
|
||||
}
|
||||
bootstrapTrace("verifying system configuration", func() {
|
||||
// Additionally in distributed setup, validate the setup and configuration.
|
||||
if err := verifyServerSystemConfig(GlobalContext, globalEndpoints); err != nil {
|
||||
logger.Fatal(err, "Unable to start the server")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if !globalDisableFreezeOnBoot {
|
||||
// Freeze the services until the bucket notification subsystem gets initialized.
|
||||
bootstrapTrace("freezeServices")
|
||||
freezeServices()
|
||||
bootstrapTrace("freezeServices", freezeServices)
|
||||
}
|
||||
|
||||
bootstrapTrace("newObjectLayer")
|
||||
newObject, err := newObjectLayer(GlobalContext, globalEndpoints)
|
||||
if err != nil {
|
||||
logFatalErrs(err, Endpoint{}, true)
|
||||
}
|
||||
bootstrapTrace("newObjectLayer (initialized)")
|
||||
var newObject ObjectLayer
|
||||
bootstrapTrace("newObjectLayer", func() {
|
||||
var err error
|
||||
newObject, err = newObjectLayer(GlobalContext, globalEndpoints)
|
||||
if err != nil {
|
||||
logFatalErrs(err, Endpoint{}, true)
|
||||
}
|
||||
})
|
||||
|
||||
xhttp.SetDeploymentID(globalDeploymentID)
|
||||
xhttp.SetMinIOVersion(Version)
|
||||
@@ -688,43 +719,49 @@ func serverMain(ctx *cli.Context) {
|
||||
globalNodeNamesHex[hex.EncodeToString(nodeNameSum[:])] = struct{}{}
|
||||
}
|
||||
|
||||
bootstrapTrace("newSharedLock")
|
||||
globalLeaderLock = newSharedLock(GlobalContext, newObject, "leader.lock")
|
||||
bootstrapTrace("newSharedLock", func() {
|
||||
globalLeaderLock = newSharedLock(GlobalContext, newObject, "leader.lock")
|
||||
})
|
||||
|
||||
// Enable background operations on
|
||||
//
|
||||
// - Disk auto healing
|
||||
// - MRF (most recently failed) healing
|
||||
// - Background expiration routine for lifecycle policies
|
||||
bootstrapTrace("initAutoHeal")
|
||||
initAutoHeal(GlobalContext, newObject)
|
||||
bootstrapTrace("initAutoHeal", func() {
|
||||
initAutoHeal(GlobalContext, newObject)
|
||||
})
|
||||
|
||||
bootstrapTrace("initHealMRF")
|
||||
initHealMRF(GlobalContext, newObject)
|
||||
bootstrapTrace("initHealMRF", func() {
|
||||
initHealMRF(GlobalContext, newObject)
|
||||
})
|
||||
|
||||
bootstrapTrace("initBackgroundExpiry")
|
||||
initBackgroundExpiry(GlobalContext, newObject)
|
||||
bootstrapTrace("initBackgroundExpiry", func() {
|
||||
initBackgroundExpiry(GlobalContext, newObject)
|
||||
})
|
||||
|
||||
bootstrapTrace("initServerConfig")
|
||||
if err = initServerConfig(GlobalContext, newObject); err != nil {
|
||||
var cerr config.Err
|
||||
// For any config error, we don't need to drop into safe-mode
|
||||
// instead its a user error and should be fixed by user.
|
||||
if errors.As(err, &cerr) {
|
||||
logger.FatalIf(err, "Unable to initialize the server")
|
||||
var err error
|
||||
bootstrapTrace("initServerConfig", func() {
|
||||
if err = initServerConfig(GlobalContext, newObject); err != nil {
|
||||
var cerr config.Err
|
||||
// For any config error, we don't need to drop into safe-mode
|
||||
// instead its a user error and should be fixed by user.
|
||||
if errors.As(err, &cerr) {
|
||||
logger.FatalIf(err, "Unable to initialize the server")
|
||||
}
|
||||
|
||||
// If context was canceled
|
||||
if errors.Is(err, context.Canceled) {
|
||||
logger.FatalIf(err, "Server startup canceled upon user request")
|
||||
}
|
||||
|
||||
logger.LogIf(GlobalContext, err)
|
||||
}
|
||||
|
||||
// If context was canceled
|
||||
if errors.Is(err, context.Canceled) {
|
||||
logger.FatalIf(err, "Server startup canceled upon user request")
|
||||
if !globalCLIContext.StrictS3Compat {
|
||||
logger.Info(color.RedBold("WARNING: Strict AWS S3 compatible incoming PUT, POST content payload validation is turned off, caution is advised do not use in production"))
|
||||
}
|
||||
|
||||
logger.LogIf(GlobalContext, err)
|
||||
}
|
||||
|
||||
if !globalCLIContext.StrictS3Compat {
|
||||
logger.Info(color.RedBold("WARNING: Strict AWS S3 compatible incoming PUT, POST content payload validation is turned off, caution is advised do not use in production"))
|
||||
}
|
||||
})
|
||||
|
||||
if globalActiveCred.Equal(auth.DefaultCredentials) {
|
||||
msg := fmt.Sprintf("WARNING: Detected default credentials '%s', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables",
|
||||
@@ -734,43 +771,44 @@ func serverMain(ctx *cli.Context) {
|
||||
|
||||
// Initialize users credentials and policies in background right after config has initialized.
|
||||
go func() {
|
||||
bootstrapTrace("globalIAMSys.Init")
|
||||
globalIAMSys.Init(GlobalContext, newObject, globalEtcdClient, globalRefreshIAMInterval)
|
||||
bootstrapTrace("globalIAMSys.Initialized")
|
||||
bootstrapTrace("globalIAMSys.Init", func() {
|
||||
globalIAMSys.Init(GlobalContext, newObject, globalEtcdClient, globalRefreshIAMInterval)
|
||||
})
|
||||
|
||||
// Initialize Console UI
|
||||
if globalBrowserEnabled {
|
||||
bootstrapTrace("initConsoleServer")
|
||||
srv, err := initConsoleServer()
|
||||
if err != nil {
|
||||
logger.FatalIf(err, "Unable to initialize console service")
|
||||
}
|
||||
bootstrapTrace("initConsoleServer", func() {
|
||||
srv, err := initConsoleServer()
|
||||
if err != nil {
|
||||
logger.FatalIf(err, "Unable to initialize console service")
|
||||
}
|
||||
|
||||
bootstrapTrace("setConsoleSrv")
|
||||
setConsoleSrv(srv)
|
||||
setConsoleSrv(srv)
|
||||
|
||||
go func() {
|
||||
logger.FatalIf(newConsoleServerFn().Serve(), "Unable to initialize console server")
|
||||
}()
|
||||
go func() {
|
||||
logger.FatalIf(newConsoleServerFn().Serve(), "Unable to initialize console server")
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
// if we see FTP args, start FTP if possible
|
||||
if len(ctx.StringSlice("ftp")) > 0 {
|
||||
bootstrapTrace("startFTPServer")
|
||||
go startFTPServer(ctx)
|
||||
bootstrapTrace("go startFTPServer", func() {
|
||||
go startFTPServer(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
// If we see SFTP args, start SFTP if possible
|
||||
if len(ctx.StringSlice("sftp")) > 0 {
|
||||
bootstrapTrace("startFTPServer")
|
||||
go startSFTPServer(ctx)
|
||||
bootstrapTrace("go startFTPServer", func() {
|
||||
go startSFTPServer(ctx)
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
if !globalDisableFreezeOnBoot {
|
||||
defer unfreezeServices()
|
||||
defer bootstrapTrace("unfreezeServices")
|
||||
defer bootstrapTrace("unfreezeServices", unfreezeServices)
|
||||
t := time.AfterFunc(5*time.Minute, func() {
|
||||
logger.Info(color.Yellow("WARNING: Taking more time to initialize the config subsystem. Please set '_MINIO_DISABLE_API_FREEZE_ON_BOOT=true' to not freeze the APIs"))
|
||||
})
|
||||
@@ -778,32 +816,38 @@ func serverMain(ctx *cli.Context) {
|
||||
}
|
||||
|
||||
// Initialize data scanner.
|
||||
bootstrapTrace("initDataScanner")
|
||||
initDataScanner(GlobalContext, newObject)
|
||||
bootstrapTrace("initDataScanner", func() {
|
||||
initDataScanner(GlobalContext, newObject)
|
||||
})
|
||||
|
||||
// Initialize background replication
|
||||
bootstrapTrace("initBackgroundReplication")
|
||||
initBackgroundReplication(GlobalContext, newObject)
|
||||
bootstrapTrace("initBackgroundReplication", func() {
|
||||
initBackgroundReplication(GlobalContext, newObject)
|
||||
})
|
||||
|
||||
bootstrapTrace("globalTransitionState.Init")
|
||||
globalTransitionState.Init(newObject)
|
||||
bootstrapTrace("globalTransitionState.Init", func() {
|
||||
globalTransitionState.Init(newObject)
|
||||
})
|
||||
|
||||
// Initialize batch job pool.
|
||||
bootstrapTrace("newBatchJobPool")
|
||||
globalBatchJobPool = newBatchJobPool(GlobalContext, newObject, 100)
|
||||
bootstrapTrace("newBatchJobPool", func() {
|
||||
globalBatchJobPool = newBatchJobPool(GlobalContext, newObject, 100)
|
||||
})
|
||||
|
||||
// Initialize the license update job
|
||||
bootstrapTrace("initLicenseUpdateJob")
|
||||
initLicenseUpdateJob(GlobalContext, newObject)
|
||||
bootstrapTrace("initLicenseUpdateJob", func() {
|
||||
initLicenseUpdateJob(GlobalContext, newObject)
|
||||
})
|
||||
|
||||
go func() {
|
||||
// Initialize transition tier configuration manager
|
||||
bootstrapTrace("globalTierConfigMgr.Init")
|
||||
if err := globalTierConfigMgr.Init(GlobalContext, newObject); err != nil {
|
||||
logger.LogIf(GlobalContext, err)
|
||||
} else {
|
||||
logger.FatalIf(globalTierJournal.Init(GlobalContext), "Unable to initialize remote tier pending deletes journal")
|
||||
}
|
||||
bootstrapTrace("globalTierConfigMgr.Init", func() {
|
||||
if err := globalTierConfigMgr.Init(GlobalContext, newObject); err != nil {
|
||||
logger.LogIf(GlobalContext, err)
|
||||
} else {
|
||||
logger.FatalIf(globalTierJournal.Init(GlobalContext), "Unable to initialize remote tier pending deletes journal")
|
||||
}
|
||||
})
|
||||
}()
|
||||
|
||||
// initialize the new disk cache objects.
|
||||
@@ -817,40 +861,45 @@ func serverMain(ctx *cli.Context) {
|
||||
}
|
||||
|
||||
// Initialize bucket notification system.
|
||||
bootstrapTrace("initBucketTargets")
|
||||
logger.LogIf(GlobalContext, globalEventNotifier.InitBucketTargets(GlobalContext, newObject))
|
||||
bootstrapTrace("initBucketTargets", func() {
|
||||
logger.LogIf(GlobalContext, globalEventNotifier.InitBucketTargets(GlobalContext, newObject))
|
||||
})
|
||||
|
||||
var buckets []BucketInfo
|
||||
// List buckets to initialize bucket metadata sub-sys.
|
||||
bootstrapTrace("listBuckets")
|
||||
buckets, err := newObject.ListBuckets(GlobalContext, BucketOptions{})
|
||||
if err != nil {
|
||||
logger.LogIf(GlobalContext, fmt.Errorf("Unable to list buckets to initialize bucket metadata sub-system: %w", err))
|
||||
}
|
||||
bootstrapTrace("listBuckets", func() {
|
||||
buckets, err = newObject.ListBuckets(GlobalContext, BucketOptions{})
|
||||
if err != nil {
|
||||
logger.LogIf(GlobalContext, fmt.Errorf("Unable to list buckets to initialize bucket metadata sub-system: %w", err))
|
||||
}
|
||||
})
|
||||
|
||||
// Initialize bucket metadata sub-system.
|
||||
bootstrapTrace("globalBucketMetadataSys.Init")
|
||||
globalBucketMetadataSys.Init(GlobalContext, buckets, newObject)
|
||||
bootstrapTrace("globalBucketMetadataSys.Initialized")
|
||||
bootstrapTrace("globalBucketMetadataSys.Init", func() {
|
||||
globalBucketMetadataSys.Init(GlobalContext, buckets, newObject)
|
||||
})
|
||||
|
||||
// initialize replication resync state.
|
||||
bootstrapTrace("initResync")
|
||||
globalReplicationPool.initResync(GlobalContext, buckets, newObject)
|
||||
bootstrapTrace("initResync", func() {
|
||||
globalReplicationPool.initResync(GlobalContext, buckets, newObject)
|
||||
})
|
||||
|
||||
// Initialize site replication manager after bucket metadata
|
||||
bootstrapTrace("globalSiteReplicationSys.Init")
|
||||
globalSiteReplicationSys.Init(GlobalContext, newObject)
|
||||
bootstrapTrace("globalSiteReplicationSys.Initialized")
|
||||
bootstrapTrace("globalSiteReplicationSys.Init", func() {
|
||||
globalSiteReplicationSys.Init(GlobalContext, newObject)
|
||||
})
|
||||
|
||||
// Initialize quota manager.
|
||||
bootstrapTrace("globalBucketQuotaSys.Init")
|
||||
globalBucketQuotaSys.Init(newObject)
|
||||
bootstrapTrace("globalBucketQuotaSys.Initialized")
|
||||
bootstrapTrace("globalBucketQuotaSys.Init", func() {
|
||||
globalBucketQuotaSys.Init(newObject)
|
||||
})
|
||||
|
||||
// Populate existing buckets to the etcd backend
|
||||
if globalDNSConfig != nil {
|
||||
// Background this operation.
|
||||
bootstrapTrace("go initFederatorBackend")
|
||||
go initFederatorBackend(buckets, newObject)
|
||||
bootstrapTrace("go initFederatorBackend", func() {
|
||||
go initFederatorBackend(buckets, newObject)
|
||||
})
|
||||
}
|
||||
|
||||
// Prints the formatted startup message, if err is not nil then it prints additional information as well.
|
||||
@@ -866,14 +915,15 @@ func serverMain(ctx *cli.Context) {
|
||||
if region == "" {
|
||||
region = "us-east-1"
|
||||
}
|
||||
bootstrapTrace("globalMinioClient")
|
||||
globalMinioClient, err = minio.New(globalLocalNodeName, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(globalActiveCred.AccessKey, globalActiveCred.SecretKey, ""),
|
||||
Secure: globalIsTLS,
|
||||
Transport: globalProxyTransport,
|
||||
Region: region,
|
||||
bootstrapTrace("globalMinioClient", func() {
|
||||
globalMinioClient, err = minio.New(globalLocalNodeName, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(globalActiveCred.AccessKey, globalActiveCred.SecretKey, ""),
|
||||
Secure: globalIsTLS,
|
||||
Transport: globalProxyTransport,
|
||||
Region: region,
|
||||
})
|
||||
logger.FatalIf(err, "Unable to initialize MinIO client")
|
||||
})
|
||||
logger.FatalIf(err, "Unable to initialize MinIO client")
|
||||
|
||||
// Add User-Agent to differentiate the requests.
|
||||
globalMinioClient.SetAppInfo("minio-perf-test", ReleaseTag)
|
||||
|
||||
@@ -64,6 +64,8 @@ func (s *storageRESTServer) writeErrorResponse(w http.ResponseWriter, err error)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
case errInvalidAccessKeyID, errAccessKeyDisabled, errNoAuthToken, errMalformedAuth, errAuthentication, errSkewedAuthTime:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case context.Canceled, context.DeadlineExceeded:
|
||||
w.WriteHeader(499)
|
||||
default:
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
}
|
||||
|
||||
+1
-1
@@ -345,7 +345,7 @@ func getProfileData() (map[string][]byte, error) {
|
||||
}
|
||||
|
||||
func setDefaultProfilerRates() {
|
||||
runtime.MemProfileRate = 4096 // 512K -> 4K - Must be constant throughout application lifetime.
|
||||
runtime.MemProfileRate = 128 << 10 // 512KB -> 128K - Must be constant throughout application lifetime.
|
||||
runtime.SetMutexProfileFraction(0) // Disable until needed
|
||||
runtime.SetBlockProfileRate(0) // Disable until needed
|
||||
}
|
||||
|
||||
+8
-5
@@ -2528,11 +2528,14 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f
|
||||
}
|
||||
}
|
||||
|
||||
// srcFilePath is always in minioMetaTmpBucket, an attempt to
|
||||
// remove the temporary folder is enough since at this point
|
||||
// ideally all transaction should be complete.
|
||||
|
||||
Remove(pathutil.Dir(srcFilePath))
|
||||
if srcVolume != minioMetaMultipartBucket {
|
||||
// srcFilePath is some-times minioMetaTmpBucket, an attempt to
|
||||
// remove the temporary folder is enough since at this point
|
||||
// ideally all transaction should be complete.
|
||||
Remove(pathutil.Dir(srcFilePath))
|
||||
} else {
|
||||
s.deleteFile(srcVolumeDir, pathutil.Dir(srcFilePath), true, false)
|
||||
}
|
||||
return sign, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,11 @@ Note: This rule has an implicit zero NoncurrentDays, which makes the expiry of t
|
||||
#### 3.2.b Automatic removal of all versions (MinIO only extension)
|
||||
|
||||
This is available only on MinIO as an extension to the Expiration feature. The following rule makes it possible to remove all versions of an object under
|
||||
the prefix `user-uploads/` as soon as the latest object satisfies the expiration criteria.
|
||||
the prefix `user-uploads/` as soon as the latest object satisfies the expiration criteria.
|
||||
|
||||
> NOTE: If the latest object is a delete marker then filtering based on `Filter.Tags` is ignored and
|
||||
> if the DELETE marker modTime satisfies the `Expiration.Days` then all versions of the object are
|
||||
> immediately purged.
|
||||
|
||||
```
|
||||
{
|
||||
|
||||
@@ -1071,7 +1071,7 @@
|
||||
},
|
||||
"editorMode": "code",
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_bucket_total{job=\"$scrape_jobs\"}",
|
||||
"expr": "max(minio_cluster_bucket_total{job=\"$scrape_jobs\"})",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"interval": "1m",
|
||||
@@ -1505,7 +1505,7 @@
|
||||
},
|
||||
"editorMode": "code",
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_usage_object_total{job=\"$scrape_jobs\"}",
|
||||
"expr": "max(minio_cluster_usage_object_total{job=\"$scrape_jobs\"})",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"interval": "1m",
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '3.7'
|
||||
|
||||
# Settings and configurations that are common for all containers
|
||||
x-minio-common: &minio-common
|
||||
image: quay.io/minio/minio:RELEASE.2023-08-09T23-30-22Z
|
||||
image: quay.io/minio/minio:RELEASE.2023-08-16T20-17-30Z
|
||||
command: server --console-address ":9001" http://minio{1...4}/data{1...2}
|
||||
expose:
|
||||
- "9000"
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.19
|
||||
require (
|
||||
cloud.google.com/go/storage v1.31.0
|
||||
github.com/Azure/azure-storage-blob-go v0.15.0
|
||||
github.com/Shopify/sarama v1.38.1
|
||||
github.com/IBM/sarama v1.41.0
|
||||
github.com/alecthomas/participle v0.7.1
|
||||
github.com/bcicen/jstream v1.0.1
|
||||
github.com/beevik/ntp v1.3.0
|
||||
@@ -48,7 +48,7 @@ require (
|
||||
github.com/minio/dnscache v0.1.1
|
||||
github.com/minio/dperf v0.5.0
|
||||
github.com/minio/highwayhash v1.0.2
|
||||
github.com/minio/kes-go v0.1.0
|
||||
github.com/minio/kes-go v0.2.0
|
||||
github.com/minio/madmin-go/v3 v3.0.11
|
||||
github.com/minio/minio-go/v7 v7.0.61
|
||||
github.com/minio/mux v1.9.0
|
||||
@@ -87,10 +87,10 @@ require (
|
||||
go.uber.org/atomic v1.11.0
|
||||
go.uber.org/zap v1.24.0
|
||||
goftp.io/server/v2 v2.0.1
|
||||
golang.org/x/crypto v0.11.0
|
||||
golang.org/x/crypto v0.12.0
|
||||
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691
|
||||
golang.org/x/oauth2 v0.10.0
|
||||
golang.org/x/sys v0.10.0
|
||||
golang.org/x/sys v0.11.0
|
||||
golang.org/x/time v0.3.0
|
||||
google.golang.org/api v0.134.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
@@ -118,8 +118,8 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/eapache/go-resiliency v1.3.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6 // indirect
|
||||
github.com/eapache/go-resiliency v1.4.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/frankban/quicktest v1.14.3 // indirect
|
||||
@@ -223,10 +223,10 @@ require (
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.12.0 // indirect
|
||||
golang.org/x/net v0.14.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/term v0.10.0 // indirect
|
||||
golang.org/x/text v0.11.0 // indirect
|
||||
golang.org/x/term v0.11.0 // indirect
|
||||
golang.org/x/text v0.12.0 // indirect
|
||||
golang.org/x/tools v0.11.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
|
||||
@@ -35,11 +35,10 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/IBM/sarama v1.41.0 h1:c+fV23/HDO+M88dTYFg7TFRlxU0scgfdcFrQh/8s5Z8=
|
||||
github.com/IBM/sarama v1.41.0/go.mod h1:JFCPURVskaipJdKRFkiE/OZqQHw7jqliaJmRwXCmSSw=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/sarama v1.38.1 h1:lqqPUPQZ7zPqYlWpTh+LQ9bhYNu2xJL6k1SJN4WVe2A=
|
||||
github.com/Shopify/sarama v1.38.1/go.mod h1:iwv9a67Ha8VNa+TifujYoWGxWnu2kNVAQdSdZ4X2o5g=
|
||||
github.com/Shopify/toxiproxy/v2 v2.5.0 h1:i4LPT+qrSlKNtQf5QliVjdP08GyAH8+BUIc9gT0eahc=
|
||||
github.com/alecthomas/participle v0.7.1 h1:2bN7reTw//5f0cugJcTOnY/NYZcWQOaajW+BwZB5xWs=
|
||||
github.com/alecthomas/participle v0.7.1/go.mod h1:HfdmEuwvr12HXQN44HPWXR0lHmVolVYe4dyL6lQ3duY=
|
||||
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||
@@ -131,10 +130,10 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/eapache/go-resiliency v1.3.0 h1:RRL0nge+cWGlxXbUzJ7yMcq6w2XBEr19dCN6HECGaT0=
|
||||
github.com/eapache/go-resiliency v1.3.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6 h1:8yY/I9ndfrgrXUbOGObLHKBR4Fl3nZXwM2c7OYTT8hM=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
|
||||
github.com/eapache/go-resiliency v1.4.0 h1:3OK9bWpPk5q6pbFAaYSEwD9CLUSHG8bnZuqX2yMt3B0=
|
||||
github.com/eapache/go-resiliency v1.4.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik=
|
||||
@@ -483,8 +482,8 @@ github.com/minio/filepath v1.0.0 h1:fvkJu1+6X+ECRA6G3+JJETj4QeAYO9sV43I79H8ubDY=
|
||||
github.com/minio/filepath v1.0.0/go.mod h1:/nRZA2ldl5z6jT9/KQuvZcQlxZIMQoFFQPvEXx9T/Bw=
|
||||
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/kes-go v0.1.0 h1:h201DyOYP5sTqajkxFGxmXz/kPbT8HQNX1uh3Yx2PFc=
|
||||
github.com/minio/kes-go v0.1.0/go.mod h1:VorHLaIYis9/MxAHAtXN4d8PUMNKhIxTIlvFt0hBOEo=
|
||||
github.com/minio/kes-go v0.2.0 h1:HA33arq9s3MErbsj3PAXFVfFo4U4yw7lTKQ5kWFrpCA=
|
||||
github.com/minio/kes-go v0.2.0/go.mod h1:VorHLaIYis9/MxAHAtXN4d8PUMNKhIxTIlvFt0hBOEo=
|
||||
github.com/minio/madmin-go/v3 v3.0.11 h1:7QrZkgbQ5+qTKGy6Nok2A8OgLAcn/lcMYYuSgiZrgBE=
|
||||
github.com/minio/madmin-go/v3 v3.0.11/go.mod h1:DMXyWO670OXwZNN0v4ZrEodl9oLOcaPJIZhpoHpu7aw=
|
||||
github.com/minio/mc v0.0.0-20230726035150-6b8680a2f7ca h1:y/dJJuWhlVYN9tqBxoHvGCpJ7olVuPa1whg+GS1m1a8=
|
||||
@@ -784,8 +783,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 h1:/yRP+0AN7mf5DkD3BAI6TOFnd51gEoDEb8o35jIFtgw=
|
||||
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
@@ -830,8 +829,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
@@ -898,8 +897,9 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -909,8 +909,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/text v0.3.0/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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -924,8 +924,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"Statement": [
|
||||
{{- range $i, $statement := .statements }}
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Effect": "{{ $statement.effect | default "Allow" }}",
|
||||
"Action": [
|
||||
"{{ $statement.actions | join "\",\n\"" }}"
|
||||
]{{ if $statement.resources }},
|
||||
@@ -21,7 +21,7 @@
|
||||
{{- range $operator,$object := $v }}
|
||||
"{{ $operator }}": { {{ $object }} }{{- if lt $k $condition_len }},{{- end }}
|
||||
{{- end }}{{- end }}
|
||||
}{{- end }}
|
||||
}{{- end }}
|
||||
}{{ if lt $i $statements_length }},{{end }}
|
||||
{{- end }}
|
||||
]
|
||||
|
||||
@@ -273,7 +273,8 @@ policies: []
|
||||
## example.
|
||||
# - name: writeexamplepolicy
|
||||
# statements:
|
||||
# - resources:
|
||||
# - effect: Allow # this is the default
|
||||
# resources:
|
||||
# - 'arn:aws:s3:::example*/*'
|
||||
# actions:
|
||||
# - "s3:AbortMultipartUpload"
|
||||
|
||||
@@ -261,7 +261,7 @@ func (lc Lifecycle) FilterRules(obj ObjectOpts) []Rule {
|
||||
if !strings.HasPrefix(obj.Name, rule.GetPrefix()) {
|
||||
continue
|
||||
}
|
||||
if !rule.Filter.TestTags(obj.UserTags) {
|
||||
if !obj.DeleteMarker && !rule.Filter.TestTags(obj.UserTags) {
|
||||
continue
|
||||
}
|
||||
rules = append(rules, rule)
|
||||
|
||||
@@ -61,10 +61,11 @@ const (
|
||||
EnvMinIOCallhomeEnable = "MINIO_CALLHOME_ENABLE"
|
||||
EnvMinIOCallhomeFrequency = "MINIO_CALLHOME_FREQUENCY"
|
||||
|
||||
EnvMinIOServerURL = "MINIO_SERVER_URL"
|
||||
EnvBrowserRedirectURL = "MINIO_BROWSER_REDIRECT_URL"
|
||||
EnvRootDiskThresholdSize = "MINIO_ROOTDISK_THRESHOLD_SIZE"
|
||||
EnvBrowserLoginAnimation = "MINIO_BROWSER_LOGIN_ANIMATION"
|
||||
EnvMinIOServerURL = "MINIO_SERVER_URL"
|
||||
EnvBrowserRedirectURL = "MINIO_BROWSER_REDIRECT_URL"
|
||||
EnvRootDiskThresholdSize = "MINIO_ROOTDISK_THRESHOLD_SIZE"
|
||||
EnvBrowserLoginAnimation = "MINIO_BROWSER_LOGIN_ANIMATION"
|
||||
EnvBrowserSessionDuration = "MINIO_BROWSER_SESSION_DURATION"
|
||||
|
||||
EnvUpdate = "MINIO_UPDATE"
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -475,12 +474,10 @@ func (c *esClientV7) createIndex(args ElasticsearchArgs) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer DrainBody(resp.Body)
|
||||
if resp.IsError() {
|
||||
err := fmt.Errorf("Create index err: %s", res.String())
|
||||
return err
|
||||
return fmt.Errorf("Create index err: %v", res)
|
||||
}
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
@@ -493,8 +490,7 @@ func (c *esClientV7) ping(ctx context.Context, _ ElasticsearchArgs) (bool, error
|
||||
if err != nil {
|
||||
return false, store.ErrNotConnected
|
||||
}
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
resp.Body.Close()
|
||||
DrainBody(resp.Body)
|
||||
return !resp.IsError(), nil
|
||||
}
|
||||
|
||||
@@ -507,8 +503,7 @@ func (c *esClientV7) entryExists(ctx context.Context, index string, key string)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
io.Copy(io.Discard, res.Body)
|
||||
res.Body.Close()
|
||||
DrainBody(res.Body)
|
||||
return !res.IsError(), nil
|
||||
}
|
||||
|
||||
@@ -523,8 +518,7 @@ func (c *esClientV7) removeEntry(ctx context.Context, index string, key string)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
defer io.Copy(io.Discard, res.Body)
|
||||
defer DrainBody(res.Body)
|
||||
if res.IsError() {
|
||||
return fmt.Errorf("Delete err: %s", res.String())
|
||||
}
|
||||
@@ -552,8 +546,7 @@ func (c *esClientV7) updateEntry(ctx context.Context, index string, key string,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
defer io.Copy(io.Discard, res.Body)
|
||||
defer DrainBody(res.Body)
|
||||
if res.IsError() {
|
||||
return fmt.Errorf("Update err: %s", res.String())
|
||||
}
|
||||
@@ -579,8 +572,7 @@ func (c *esClientV7) addEntry(ctx context.Context, index string, eventData event
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
defer io.Copy(io.Discard, res.Body)
|
||||
defer DrainBody(res.Body)
|
||||
if res.IsError() {
|
||||
return fmt.Errorf("Add err: %s", res.String())
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ import (
|
||||
"github.com/minio/minio/internal/store"
|
||||
xnet "github.com/minio/pkg/net"
|
||||
|
||||
"github.com/Shopify/sarama"
|
||||
saramatls "github.com/Shopify/sarama/tools/tls"
|
||||
"github.com/IBM/sarama"
|
||||
saramatls "github.com/IBM/sarama/tools/tls"
|
||||
)
|
||||
|
||||
// Kafka input constants
|
||||
@@ -332,9 +332,20 @@ func (target *KafkaTarget) initKafka() error {
|
||||
config.Net.TLS.Config.ClientAuth = args.TLS.ClientAuth
|
||||
config.Net.TLS.Config.RootCAs = args.TLS.RootCAs
|
||||
|
||||
config.Producer.RequiredAcks = sarama.WaitForAll
|
||||
config.Producer.Retry.Max = 10
|
||||
// These settings are needed to ensure that kafka client doesn't hang on brokers
|
||||
// refer https://github.com/IBM/sarama/issues/765#issuecomment-254333355
|
||||
config.Producer.Retry.Max = 2
|
||||
config.Producer.Retry.Backoff = (10 * time.Second)
|
||||
config.Producer.Return.Successes = true
|
||||
config.Producer.Return.Errors = true
|
||||
config.Producer.RequiredAcks = 1
|
||||
config.Producer.Timeout = (10 * time.Second)
|
||||
config.Net.ReadTimeout = (10 * time.Second)
|
||||
config.Net.DialTimeout = (10 * time.Second)
|
||||
config.Net.WriteTimeout = (10 * time.Second)
|
||||
config.Metadata.Retry.Max = 1
|
||||
config.Metadata.Retry.Backoff = (10 * time.Second)
|
||||
config.Metadata.RefreshFrequency = (15 * time.Minute)
|
||||
|
||||
target.config = config
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ package target
|
||||
import (
|
||||
"crypto/sha512"
|
||||
|
||||
"github.com/Shopify/sarama"
|
||||
"github.com/IBM/sarama"
|
||||
"github.com/xdg/scram"
|
||||
|
||||
"github.com/minio/minio/internal/hash/sha256"
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/minio/minio/internal/event"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
"github.com/minio/minio/internal/once"
|
||||
@@ -194,8 +195,7 @@ func (target *WebhookTarget) send(eventData event.Event) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
defer DrainBody(resp.Body)
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||
return fmt.Errorf("sending event failed with %v", resp.Status)
|
||||
@@ -297,3 +297,23 @@ func NewWebhookTarget(ctx context.Context, id string, args WebhookArgs, loggerOn
|
||||
|
||||
return target, nil
|
||||
}
|
||||
|
||||
// DrainBody 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 DrainBody(respBody io.ReadCloser) {
|
||||
// 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 respBody != 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
|
||||
defer respBody.Close()
|
||||
io.CopyN(io.Discard, respBody, 1*humanize.MiByte)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ type IdentityManager interface {
|
||||
// The admin identity cannot be deleted.
|
||||
DeleteIdentity(ctx context.Context, identity string) error
|
||||
|
||||
// ListIdentities list all identity metadata that match the specified pattern.
|
||||
// In particular, the pattern * lists all identity metadata.
|
||||
ListIdentities(ctx context.Context, pattern string) (*kes.IdentityIterator, error)
|
||||
// ListIdentities lists all identities.
|
||||
ListIdentities(ctx context.Context) (*kes.ListIter[kes.Identity], error)
|
||||
}
|
||||
|
||||
+27
-64
@@ -104,23 +104,10 @@ func NewWithConfig(config Config) (KMS, error) {
|
||||
}
|
||||
client.Endpoints = endpoints
|
||||
|
||||
var bulkAvailable bool
|
||||
_, policy, err := client.DescribeSelf(context.Background())
|
||||
if err == nil {
|
||||
const BulkAPI = "/v1/key/bulk/decrypt/"
|
||||
for _, allow := range policy.Allow {
|
||||
if strings.HasPrefix(allow, BulkAPI) {
|
||||
bulkAvailable = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c := &kesClient{
|
||||
client: client,
|
||||
enclave: client.Enclave(config.Enclave),
|
||||
defaultKeyID: config.DefaultKeyID,
|
||||
bulkAvailable: bulkAvailable,
|
||||
client: client,
|
||||
enclave: client.Enclave(config.Enclave),
|
||||
defaultKeyID: config.DefaultKeyID,
|
||||
}
|
||||
go func() {
|
||||
if config.Certificate == nil || config.ReloadCertEvents == nil {
|
||||
@@ -166,11 +153,14 @@ type kesClient struct {
|
||||
defaultKeyID string
|
||||
client *kes.Client
|
||||
enclave *kes.Enclave
|
||||
|
||||
bulkAvailable bool
|
||||
}
|
||||
|
||||
var _ KMS = (*kesClient)(nil) // compiler check
|
||||
var ( // compiler checks
|
||||
_ KMS = (*kesClient)(nil)
|
||||
_ KeyManager = (*kesClient)(nil)
|
||||
_ IdentityManager = (*kesClient)(nil)
|
||||
_ PolicyManager = (*kesClient)(nil)
|
||||
)
|
||||
|
||||
// Stat returns the current KES status containing a
|
||||
// list of KES endpoints and the default key ID.
|
||||
@@ -259,13 +249,14 @@ func (c *kesClient) DeleteKey(ctx context.Context, keyID string) error {
|
||||
return c.enclave.DeleteKey(ctx, keyID)
|
||||
}
|
||||
|
||||
// ListKeys List all key names that match the specified pattern. In particular,
|
||||
// the pattern * lists all keys.
|
||||
func (c *kesClient) ListKeys(ctx context.Context, pattern string) (*kes.KeyIterator, error) {
|
||||
// ListKeys returns an iterator over all key names.
|
||||
func (c *kesClient) ListKeys(ctx context.Context) (*kes.ListIter[string], error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
return c.enclave.ListKeys(ctx, pattern)
|
||||
return &kes.ListIter[string]{
|
||||
NextFunc: c.enclave.ListKeys,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GenerateKey generates a new data encryption key using
|
||||
@@ -304,7 +295,9 @@ func (c *kesClient) ImportKey(ctx context.Context, keyID string, bytes []byte) e
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
return c.enclave.ImportKey(ctx, keyID, bytes)
|
||||
return c.enclave.ImportKey(ctx, keyID, &kes.ImportKeyRequest{
|
||||
Key: bytes,
|
||||
})
|
||||
}
|
||||
|
||||
// EncryptKey Encrypts and authenticates a (small) plaintext with the cryptographic key
|
||||
@@ -338,30 +331,6 @@ func (c *kesClient) DecryptAll(ctx context.Context, keyID string, ciphertexts []
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
if c.bulkAvailable {
|
||||
CCPs := make([]kes.CCP, 0, len(ciphertexts))
|
||||
for i := range ciphertexts {
|
||||
bCtx, err := contexts[i].MarshalText()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
CCPs = append(CCPs, kes.CCP{
|
||||
Ciphertext: ciphertexts[i],
|
||||
Context: bCtx,
|
||||
})
|
||||
}
|
||||
|
||||
PCPs, err := c.enclave.DecryptAll(ctx, keyID, CCPs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plaintexts := make([][]byte, 0, len(PCPs))
|
||||
for _, p := range PCPs {
|
||||
plaintexts = append(plaintexts, p.Plaintext)
|
||||
}
|
||||
return plaintexts, nil
|
||||
}
|
||||
|
||||
plaintexts := make([][]byte, 0, len(ciphertexts))
|
||||
for i := range ciphertexts {
|
||||
ctxBytes, err := contexts[i].MarshalText()
|
||||
@@ -407,21 +376,14 @@ func (c *kesClient) DeletePolicy(ctx context.Context, policy string) error {
|
||||
return c.enclave.DeletePolicy(ctx, policy)
|
||||
}
|
||||
|
||||
// ListPolicies list all policy metadata that match the specified pattern.
|
||||
// In particular, the pattern * lists all policy metadata.
|
||||
func (c *kesClient) ListPolicies(ctx context.Context, pattern string) (*kes.PolicyIterator, error) {
|
||||
// ListPolicies returns an iterator over all policy names.
|
||||
func (c *kesClient) ListPolicies(ctx context.Context) (*kes.ListIter[string], error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
return c.enclave.ListPolicies(ctx, pattern)
|
||||
}
|
||||
|
||||
// SetPolicy creates or updates a policy.
|
||||
func (c *kesClient) SetPolicy(ctx context.Context, policy string, policyItem *kes.Policy) error {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
return c.enclave.SetPolicy(ctx, policy, policyItem)
|
||||
return &kes.ListIter[string]{
|
||||
NextFunc: c.enclave.ListPolicies,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetPolicy gets a policy from KMS.
|
||||
@@ -461,13 +423,14 @@ func (c *kesClient) DeleteIdentity(ctx context.Context, identity string) error {
|
||||
return c.enclave.DeleteIdentity(ctx, kes.Identity(identity))
|
||||
}
|
||||
|
||||
// ListIdentities list all identity metadata that match the specified pattern.
|
||||
// In particular, the pattern * lists all identity metadata.
|
||||
func (c *kesClient) ListIdentities(ctx context.Context, pattern string) (*kes.IdentityIterator, error) {
|
||||
// ListPolicies returns an iterator over all identities.
|
||||
func (c *kesClient) ListIdentities(ctx context.Context) (*kes.ListIter[kes.Identity], error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
return c.enclave.ListIdentities(ctx, pattern)
|
||||
return &kes.ListIter[kes.Identity]{
|
||||
NextFunc: c.enclave.ListIdentities,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Verify verifies all KMS endpoints and returns details
|
||||
|
||||
@@ -34,9 +34,8 @@ type KeyManager interface {
|
||||
// anymore, and therefore, is lost.
|
||||
DeleteKey(ctx context.Context, keyID string) error
|
||||
|
||||
// ListKeys List all key names that match the specified pattern. In particular,
|
||||
// the pattern * lists all keys.
|
||||
ListKeys(ctx context.Context, pattern string) (*kes.KeyIterator, error)
|
||||
// ListKeys lists all key names.
|
||||
ListKeys(ctx context.Context) (*kes.ListIter[string], error)
|
||||
|
||||
// ImportKey imports a cryptographic key into the KMS.
|
||||
ImportKey(ctx context.Context, keyID string, bytes []byte) error
|
||||
|
||||
@@ -36,15 +36,11 @@ type PolicyManager interface {
|
||||
// Further, an identity cannot assign a policy to itself.
|
||||
AssignPolicy(ctx context.Context, policy, identity string) error
|
||||
|
||||
// SetPolicy creates or updates a policy.
|
||||
SetPolicy(ctx context.Context, policy string, policyItem *kes.Policy) error
|
||||
|
||||
// GetPolicy gets a policy from KMS.
|
||||
GetPolicy(ctx context.Context, policy string) (*kes.Policy, error)
|
||||
|
||||
// ListPolicies list all policy metadata that match the specified pattern.
|
||||
// In particular, the pattern * lists all policy metadata.
|
||||
ListPolicies(ctx context.Context, pattern string) (*kes.PolicyIterator, error)
|
||||
// ListPolicies lists all policies.
|
||||
ListPolicies(ctx context.Context) (*kes.ListIter[string], error)
|
||||
|
||||
// DeletePolicy deletes a policy from KMS.
|
||||
// All identities that have been assigned to this policy will lose all authorization privileges.
|
||||
|
||||
@@ -268,7 +268,10 @@ func errToEntry(ctx context.Context, err error, errKind ...interface{}) log.Entr
|
||||
req := GetReqInfo(ctx)
|
||||
|
||||
if req == nil {
|
||||
req = &ReqInfo{API: "SYSTEM"}
|
||||
req = &ReqInfo{
|
||||
API: "SYSTEM",
|
||||
RequestID: fmt.Sprintf("%X", time.Now().UTC().UnixNano()),
|
||||
}
|
||||
}
|
||||
req.RLock()
|
||||
defer req.RUnlock()
|
||||
|
||||
@@ -377,7 +377,11 @@ func (h *Target) Send(ctx context.Context, entry interface{}) error {
|
||||
select {
|
||||
case h.logCh <- entry:
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
// return error only for context timedout.
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
return ctx.Err()
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
nWorkers := atomic.LoadInt64(&h.workers)
|
||||
if nWorkers < maxWorkers {
|
||||
|
||||
@@ -32,8 +32,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/Shopify/sarama"
|
||||
saramatls "github.com/Shopify/sarama/tools/tls"
|
||||
"github.com/IBM/sarama"
|
||||
saramatls "github.com/IBM/sarama/tools/tls"
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
"github.com/minio/minio/internal/logger/target/types"
|
||||
@@ -287,9 +287,20 @@ func (h *Target) init() error {
|
||||
sconfig.Net.TLS.Config.ClientAuth = h.kconfig.TLS.ClientAuth
|
||||
sconfig.Net.TLS.Config.RootCAs = h.kconfig.TLS.RootCAs
|
||||
|
||||
sconfig.Producer.RequiredAcks = sarama.WaitForAll
|
||||
sconfig.Producer.Retry.Max = 10
|
||||
// These settings are needed to ensure that kafka client doesn't hang on brokers
|
||||
// refer https://github.com/IBM/sarama/issues/765#issuecomment-254333355
|
||||
sconfig.Producer.Retry.Max = 2
|
||||
sconfig.Producer.Retry.Backoff = (10 * time.Second)
|
||||
sconfig.Producer.Return.Successes = true
|
||||
sconfig.Producer.Return.Errors = true
|
||||
sconfig.Producer.RequiredAcks = 1
|
||||
sconfig.Producer.Timeout = (10 * time.Second)
|
||||
sconfig.Net.ReadTimeout = (10 * time.Second)
|
||||
sconfig.Net.DialTimeout = (10 * time.Second)
|
||||
sconfig.Net.WriteTimeout = (10 * time.Second)
|
||||
sconfig.Metadata.Retry.Max = 1
|
||||
sconfig.Metadata.Retry.Backoff = (10 * time.Second)
|
||||
sconfig.Metadata.RefreshFrequency = (15 * time.Minute)
|
||||
|
||||
h.config = sconfig
|
||||
|
||||
@@ -330,6 +341,12 @@ func (h *Target) Send(ctx context.Context, entry interface{}) error {
|
||||
|
||||
select {
|
||||
case h.logCh <- entry:
|
||||
case <-ctx.Done():
|
||||
// return error only for context timedout.
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
return ctx.Err()
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
// log channel is full, do not wait and return
|
||||
// an error immediately to the caller
|
||||
|
||||
@@ -20,7 +20,7 @@ package kafka
|
||||
import (
|
||||
"crypto/sha512"
|
||||
|
||||
"github.com/Shopify/sarama"
|
||||
"github.com/IBM/sarama"
|
||||
"github.com/xdg/scram"
|
||||
|
||||
"github.com/minio/minio/internal/hash/sha256"
|
||||
|
||||
Reference in New Issue
Block a user