...
 
Commits (5)
......@@ -42,6 +42,7 @@ import (
"github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/cmd/logger/message/log"
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/cpu"
"github.com/minio/minio/pkg/event/target"
......@@ -1227,8 +1228,8 @@ func (a adminAPIHandlers) ConsoleLogHandler(w http.ResponseWriter, r *http.Reque
for {
select {
case entry := <-logCh:
log := entry.(madmin.LogInfo)
if log.SendLog(node, logKind) {
log, ok := entry.(log.Info)
if ok && log.SendLog(node, logKind) {
if err := enc.Encode(log); err != nil {
return
}
......@@ -1436,7 +1437,7 @@ func (a adminAPIHandlers) ServerInfoHandler(w http.ResponseWriter, r *http.Reque
OffDisks += v
}
backend = madmin.XlBackend{
backend = madmin.XLBackend{
Type: madmin.ErasureType,
OnlineDisks: OnDisks,
OfflineDisks: OffDisks,
......@@ -1446,7 +1447,7 @@ func (a adminAPIHandlers) ServerInfoHandler(w http.ResponseWriter, r *http.Reque
RRSCParity: storageInfo.Backend.RRSCParity,
}
} else {
backend = madmin.FsBackend{
backend = madmin.FSBackend{
Type: madmin.FsType,
}
}
......
......@@ -165,6 +165,12 @@ var (
Optional: true,
Type: "string",
},
config.HelpKV{
Key: target.KafkaSASLMechanism,
Description: "sasl authentication mechanism, default 'plain'",
Optional: true,
Type: "string",
},
config.HelpKV{
Key: target.KafkaTLSClientAuth,
Description: "clientAuth determines the Kafka server's policy for TLS client auth",
......
......@@ -352,6 +352,10 @@ var (
Key: target.KafkaSASLPassword,
Value: "",
},
config.KV{
Key: target.KafkaSASLMechanism,
Value: "plain",
},
config.KV{
Key: target.KafkaClientTLSCert,
Value: "",
......@@ -507,9 +511,14 @@ func GetNotifyKafka(kafkaKVS map[string]config.KVS) (map[string]target.KafkaArgs
if k != config.Default {
saslPasswordEnv = saslPasswordEnv + config.Default + k
}
saslMechanismEnv := target.EnvKafkaSASLMechanism
if k != config.Default {
saslMechanismEnv = saslMechanismEnv + config.Default + k
}
kafkaArgs.SASL.Enable = env.Get(saslEnableEnv, kv.Get(target.KafkaSASL)) == config.EnableOn
kafkaArgs.SASL.User = env.Get(saslUsernameEnv, kv.Get(target.KafkaSASLUsername))
kafkaArgs.SASL.Password = env.Get(saslPasswordEnv, kv.Get(target.KafkaSASLPassword))
kafkaArgs.SASL.Mechanism = env.Get(saslMechanismEnv, kv.Get(target.KafkaSASLMechanism))
if err = kafkaArgs.Validate(); err != nil {
return nil, err
......
......@@ -24,7 +24,6 @@ import (
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/cmd/logger/message/log"
"github.com/minio/minio/cmd/logger/target/console"
"github.com/minio/minio/pkg/madmin"
xnet "github.com/minio/minio/pkg/net"
"github.com/minio/minio/pkg/pubsub"
)
......@@ -84,17 +83,20 @@ func (sys *HTTPConsoleLoggerSys) Subscribe(subCh chan interface{}, doneCh chan s
cnt := 0
// by default send all console logs in the ring buffer unless node or limit query parameters
// are set.
var lastN []madmin.LogInfo
var lastN []log.Info
if last > defaultLogBufferCount || last <= 0 {
last = defaultLogBufferCount
}
lastN = make([]madmin.LogInfo, last)
lastN = make([]log.Info, last)
sys.RLock()
sys.logBuf.Do(func(p interface{}) {
if p != nil && (p.(madmin.LogInfo)).SendLog(node, logKind) {
lastN[cnt%last] = p.(madmin.LogInfo)
cnt++
if p != nil {
lg, ok := p.(log.Info)
if ok && lg.SendLog(node, logKind) {
lastN[cnt%last] = lg
cnt++
}
}
})
sys.RUnlock()
......@@ -102,7 +104,7 @@ func (sys *HTTPConsoleLoggerSys) Subscribe(subCh chan interface{}, doneCh chan s
if cnt > 0 {
for i := 0; i < last; i++ {
entry := lastN[(cnt+i)%last]
if (entry == madmin.LogInfo{}) {
if (entry == log.Info{}) {
continue
}
select {
......@@ -118,12 +120,12 @@ func (sys *HTTPConsoleLoggerSys) Subscribe(subCh chan interface{}, doneCh chan s
// Send log message 'e' to console and publish to console
// log pubsub system
func (sys *HTTPConsoleLoggerSys) Send(e interface{}, logKind string) error {
var lg madmin.LogInfo
var lg log.Info
switch e := e.(type) {
case log.Entry:
lg = madmin.LogInfo{Entry: e, NodeName: sys.nodeName}
lg = log.Info{Entry: e, NodeName: sys.nodeName}
case string:
lg = madmin.LogInfo{ConsoleMsg: e, NodeName: sys.nodeName}
lg = log.Info{ConsoleMsg: e, NodeName: sys.nodeName}
}
sys.pubsub.Publish(lg)
......
/*
* MinIO Cloud Storage, (C) 2018 MinIO, Inc.
* MinIO Cloud Storage, (C) 2018, 2020 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -16,6 +16,8 @@
package log
import "strings"
// Args - defines the arguments for the API.
type Args struct {
Bucket string `json:"bucket,omitempty"`
......@@ -50,3 +52,18 @@ type Entry struct {
Message string `json:"message,omitempty"`
Trace *Trace `json:"error,omitempty"`
}
// Info holds console log messages
type Info struct {
Entry
ConsoleMsg string
NodeName string `json:"node"`
Err error `json:"-"`
}
// SendLog returns true if log pertains to node specified in args.
func (l Info) SendLog(node, logKind string) bool {
nodeFltr := (node == "" || strings.EqualFold(node, l.NodeName))
typeFltr := strings.EqualFold(logKind, "all") || strings.EqualFold(l.LogKind, logKind)
return nodeFltr && typeFltr
}
......@@ -1063,6 +1063,7 @@ brokers* (csv) comma separated list of Kafka broker addresses
topic (string) Kafka topic used for bucket notifications
sasl_username (string) username for SASL/PLAIN or SASL/SCRAM authentication
sasl_password (string) password for SASL/PLAIN or SASL/SCRAM authentication
sasl_mechanism (string) sasl authentication mechanism, default 'PLAIN'
tls_client_auth (string) clientAuth determines the Kafka server's policy for TLS client auth
sasl (on|off) set to 'on' to enable SASL authentication
tls (on|off) set to 'on' to enable TLS
......@@ -1081,21 +1082,22 @@ KEY:
notify_kafka[:name] publish bucket notifications to Kafka endpoints
ARGS:
MINIO_NOTIFY_KAFKA_ENABLE* (on|off) enable notify_kafka target, default is 'off'
MINIO_NOTIFY_KAFKA_BROKERS* (csv) comma separated list of Kafka broker addresses
MINIO_NOTIFY_KAFKA_TOPIC (string) Kafka topic used for bucket notifications
MINIO_NOTIFY_KAFKA_SASL_USERNAME (string) username for SASL/PLAIN or SASL/SCRAM authentication
MINIO_NOTIFY_KAFKA_SASL_PASSWORD (string) password for SASL/PLAIN or SASL/SCRAM authentication
MINIO_NOTIFY_KAFKA_TLS_CLIENT_AUTH (string) clientAuth determines the Kafka server's policy for TLS client auth
MINIO_NOTIFY_KAFKA_SASL (on|off) set to 'on' to enable SASL authentication
MINIO_NOTIFY_KAFKA_TLS (on|off) set to 'on' to enable TLS
MINIO_NOTIFY_KAFKA_TLS_SKIP_VERIFY (on|off) trust server TLS without verification, defaults to "on" (verify)
MINIO_NOTIFY_KAFKA_CLIENT_TLS_CERT (path) path to client certificate for mTLS auth
MINIO_NOTIFY_KAFKA_CLIENT_TLS_KEY (path) path to client key for mTLS auth
MINIO_NOTIFY_KAFKA_QUEUE_DIR (path) staging dir for undelivered messages e.g. '/home/events'
MINIO_NOTIFY_KAFKA_QUEUE_LIMIT (number) maximum limit for undelivered messages, defaults to '10000'
MINIO_NOTIFY_KAFKA_COMMENT (sentence) optionally add a comment to this setting
MINIO_NOTIFY_KAFKA_VERSION (string) specify the version of the Kafka cluster e.g. '2.2.0'
MINIO_NOTIFY_KAFKA_ENABLE* (on|off) enable notify_kafka target, default is 'off'
MINIO_NOTIFY_KAFKA_BROKERS* (csv) comma separated list of Kafka broker addresses
MINIO_NOTIFY_KAFKA_TOPIC (string) Kafka topic used for bucket notifications
MINIO_NOTIFY_KAFKA_SASL_USERNAME (string) username for SASL/PLAIN or SASL/SCRAM authentication
MINIO_NOTIFY_KAFKA_SASL_PASSWORD (string) password for SASL/PLAIN or SASL/SCRAM authentication
MINIO_NOTIFY_KAFKA_SASL_MECHANISM (plain*|sha256|sha512) sasl authentication mechanism, default 'plain'
MINIO_NOTIFY_KAFKA_TLS_CLIENT_AUTH (string) clientAuth determines the Kafka server's policy for TLS client auth
MINIO_NOTIFY_KAFKA_SASL (on|off) set to 'on' to enable SASL authentication
MINIO_NOTIFY_KAFKA_TLS (on|off) set to 'on' to enable TLS
MINIO_NOTIFY_KAFKA_TLS_SKIP_VERIFY (on|off) trust server TLS without verification, defaults to "on" (verify)
MINIO_NOTIFY_KAFKA_CLIENT_TLS_CERT (path) path to client certificate for mTLS auth
MINIO_NOTIFY_KAFKA_CLIENT_TLS_KEY (path) path to client key for mTLS auth
MINIO_NOTIFY_KAFKA_QUEUE_DIR (path) staging dir for undelivered messages e.g. '/home/events'
MINIO_NOTIFY_KAFKA_QUEUE_LIMIT (number) maximum limit for undelivered messages, defaults to '10000'
MINIO_NOTIFY_KAFKA_COMMENT (sentence) optionally add a comment to this setting
MINIO_NOTIFY_KAFKA_VERSION (string) specify the version of the Kafka cluster e.g. '2.2.0'
```
To update the configuration, use `mc admin config get` command to get the current configuration.
......
......@@ -68,7 +68,7 @@ require (
github.com/minio/hdfs/v3 v3.0.1
github.com/minio/highwayhash v1.0.0
github.com/minio/lsync v1.0.1
github.com/minio/minio-go/v6 v6.0.50-0.20200306231101-b882ba63d570
github.com/minio/minio-go/v6 v6.0.51-0.20200319192131-097caa7760c7
github.com/minio/parquet-go v0.0.0-20200125064549-a1e49702e174
github.com/minio/sha256-simd v0.1.1
github.com/minio/simdjson-go v0.1.5-0.20200303142138-b17fe061ea37
......@@ -106,6 +106,7 @@ require (
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
github.com/ugorji/go v1.1.5-pre // indirect
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.etcd.io/bbolt v1.3.3 // indirect
go.uber.org/atomic v1.3.2
......
......@@ -45,7 +45,6 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb v1.0.28 h1:kWGpdAcSp3MxMU9CCHOwz/8V0kCHN4+9yQm2MzWuI98=
......@@ -279,8 +278,8 @@ github.com/minio/lsync v1.0.1 h1:AVvILxA976xc27hstd1oR+X9PQG0sPSom1MNb1ImfUs=
github.com/minio/lsync v1.0.1/go.mod h1:tCFzfo0dlvdGl70IT4IAK/5Wtgb0/BrTmo/jE8pArKA=
github.com/minio/minio-go/v6 v6.0.45 h1:aY4NI/DOgSbZiwGN3fEF4NAkC9An4bhaIWuJrQrRYew=
github.com/minio/minio-go/v6 v6.0.45/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
github.com/minio/minio-go/v6 v6.0.50-0.20200306231101-b882ba63d570 h1:GLTZoRC6rhCTucnkJAQ63LhMU2S4CM71MRc9gfX7ohE=
github.com/minio/minio-go/v6 v6.0.50-0.20200306231101-b882ba63d570/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
github.com/minio/minio-go/v6 v6.0.51-0.20200319192131-097caa7760c7 h1:WQmYVUDRGdcEWhJeb42/Fn1IO7SBLem173DTE4+jp/E=
github.com/minio/minio-go/v6 v6.0.51-0.20200319192131-097caa7760c7/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
github.com/minio/parquet-go v0.0.0-20200125064549-a1e49702e174 h1:WYFHZIJ5LTWd4C3CW26jguaBLLDdX7l1/Xa3QSKGkIc=
github.com/minio/parquet-go v0.0.0-20200125064549-a1e49702e174/go.mod h1:PXYM9yI2l0YPmxHUXe6mFTmkQcyaVasDshAPTbGpDoo=
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
......@@ -429,7 +428,9 @@ github.com/ugorji/go/codec v1.1.5-pre h1:5YV9PsFAN+ndcCtTM7s60no7nY7eTG3LPtxhSwu
github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
......
......@@ -46,6 +46,7 @@ const (
KafkaSASL = "sasl"
KafkaSASLUsername = "sasl_username"
KafkaSASLPassword = "sasl_password"
KafkaSASLMechanism = "sasl_mechanism"
KafkaClientTLSCert = "client_tls_cert"
KafkaClientTLSKey = "client_tls_key"
KafkaVersion = "version"
......@@ -61,6 +62,7 @@ const (
EnvKafkaSASLEnable = "MINIO_NOTIFY_KAFKA_SASL"
EnvKafkaSASLUsername = "MINIO_NOTIFY_KAFKA_SASL_USERNAME"
EnvKafkaSASLPassword = "MINIO_NOTIFY_KAFKA_SASL_PASSWORD"
EnvKafkaSASLMechanism = "MINIO_NOTIFY_KAFKA_SASL_MECHANISM"
EnvKafkaClientTLSCert = "MINIO_NOTIFY_KAFKA_CLIENT_TLS_CERT"
EnvKafkaClientTLSKey = "MINIO_NOTIFY_KAFKA_CLIENT_TLS_KEY"
EnvKafkaVersion = "MINIO_NOTIFY_KAFKA_VERSION"
......@@ -83,9 +85,10 @@ type KafkaArgs struct {
ClientTLSKey string `json:"clientTLSKey"`
} `json:"tls"`
SASL struct {
Enable bool `json:"enable"`
User string `json:"username"`
Password string `json:"password"`
Enable bool `json:"enable"`
User string `json:"username"`
Password string `json:"password"`
Mechanism string `json:"mechanism"`
} `json:"sasl"`
}
......@@ -255,6 +258,16 @@ func NewKafkaTarget(id string, args KafkaArgs, doneCh <-chan struct{}, loggerOnc
config.Net.SASL.User = args.SASL.User
config.Net.SASL.Password = args.SASL.Password
if args.SASL.Mechanism == "sha512" {
config.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { return &XDGSCRAMClient{HashGeneratorFcn: KafkaSHA512} }
config.Net.SASL.Mechanism = sarama.SASLMechanism(sarama.SASLTypeSCRAMSHA512)
} else if args.SASL.Mechanism == "sha256" {
config.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { return &XDGSCRAMClient{HashGeneratorFcn: KafkaSHA256} }
config.Net.SASL.Mechanism = sarama.SASLMechanism(sarama.SASLTypeSCRAMSHA256)
} else {
// default to PLAIN
config.Net.SASL.Mechanism = sarama.SASLMechanism(sarama.SASLTypePlaintext)
}
config.Net.SASL.Enable = args.SASL.Enable
tlsConfig, err := saramatls.NewConfig(args.TLS.ClientTLSCert, args.TLS.ClientTLSKey)
......
/*
* MinIO Cloud Storage, (C) 2020 MinIO, Inc.
*
* 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.
*/
package target
import (
"crypto/sha512"
"hash"
"github.com/minio/sha256-simd"
"github.com/xdg/scram"
)
// KafkaSHA256 is a function that returns a crypto/sha256 hasher and should be used
// to create Client objects configured for SHA-256 hashing.
var KafkaSHA256 scram.HashGeneratorFcn = func() hash.Hash { return sha256.New() }
// KafkaSHA512 is a function that returns a crypto/sha512 hasher and should be used
// to create Client objects configured for SHA-512 hashing.
var KafkaSHA512 scram.HashGeneratorFcn = func() hash.Hash { return sha512.New() }
// XDGSCRAMClient implements the client-side of an authentication
// conversation with a server. A new conversation must be created for
// each authentication attempt.
type XDGSCRAMClient struct {
*scram.Client
*scram.ClientConversation
scram.HashGeneratorFcn
}
// Begin constructs a SCRAM client component based on a given hash.Hash
// factory receiver. This constructor will normalize the username, password
// and authzID via the SASLprep algorithm, as recommended by RFC-5802. If
// SASLprep fails, the method returns an error.
func (x *XDGSCRAMClient) Begin(userName, password, authzID string) (err error) {
x.Client, err = x.HashGeneratorFcn.NewClient(userName, password, authzID)
if err != nil {
return err
}
x.ClientConversation = x.Client.NewConversation()
return nil
}
// Step takes a string provided from a server (or just an empty string for the
// very first conversation step) and attempts to move the authentication
// conversation forward. It returns a string to be sent to the server or an
// error if the server message is invalid. Calling Step after a conversation
// completes is also an error.
func (x *XDGSCRAMClient) Step(challenge string) (response string, err error) {
response, err = x.ClientConversation.Step(challenge)
return
}
// Done returns true if the conversation is completed or has errored.
func (x *XDGSCRAMClient) Done() bool {
return x.ClientConversation.Done()
}
......@@ -25,7 +25,7 @@ import (
// AppendFile - appends the file "src" to the file "dst"
func AppendFile(dst string, src string) error {
appendFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
appendFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
return err
}
......
/*
* MinIO Cloud Storage, (C) 2020 MinIO, Inc.
*
* 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.
*/
package madmin
// Args - defines the arguments for the API.
type logArgs struct {
Bucket string `json:"bucket,omitempty"`
Object string `json:"object,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
// Trace - defines the trace.
type logTrace struct {
Message string `json:"message,omitempty"`
Source []string `json:"source,omitempty"`
Variables map[string]string `json:"variables,omitempty"`
}
// API - defines the api type and its args.
type logAPI struct {
Name string `json:"name,omitempty"`
Args *logArgs `json:"args,omitempty"`
}
// Entry - defines fields and values of each log entry.
type logEntry struct {
DeploymentID string `json:"deploymentid,omitempty"`
Level string `json:"level"`
LogKind string `json:"errKind"`
Time string `json:"time"`
API *logAPI `json:"api,omitempty"`
RemoteHost string `json:"remotehost,omitempty"`
Host string `json:"host,omitempty"`
RequestID string `json:"requestID,omitempty"`
UserAgent string `json:"userAgent,omitempty"`
Message string `json:"message,omitempty"`
Trace *logTrace `json:"error,omitempty"`
}
......@@ -17,32 +17,23 @@
package madmin
import (
"context"
"encoding/json"
"net/http"
"net/url"
"strconv"
"strings"
"github.com/minio/minio/cmd/logger/message/log"
)
// LogInfo holds console log messages
type LogInfo struct {
log.Entry
logEntry
ConsoleMsg string
NodeName string `json:"node"`
Err error `json:"-"`
}
// SendLog returns true if log pertains to node specified in args.
func (l LogInfo) SendLog(node, logKind string) bool {
nodeFltr := (node == "" || strings.EqualFold(node, l.NodeName))
typeFltr := strings.EqualFold(logKind, "all") || strings.EqualFold(l.LogKind, logKind)
return nodeFltr && typeFltr
}
// GetLogs - listen on console log messages.
func (adm AdminClient) GetLogs(node string, lineCnt int, logKind string, doneCh <-chan struct{}) <-chan LogInfo {
func (adm AdminClient) GetLogs(ctx context.Context, node string, lineCnt int, logKind string) <-chan LogInfo {
logCh := make(chan LogInfo, 1)
// Only success, start a routine to start reading line by line.
......@@ -58,7 +49,7 @@ func (adm AdminClient) GetLogs(node string, lineCnt int, logKind string, doneCh
queryValues: urlValues,
}
// Execute GET to call log handler
resp, err := adm.executeMethod("GET", reqData)
resp, err := adm.executeMethod(ctx, http.MethodGet, reqData)
if err != nil {
closeResponse(resp)
return
......@@ -75,7 +66,7 @@ func (adm AdminClient) GetLogs(node string, lineCnt int, logKind string, doneCh
break
}
select {
case <-doneCh:
case <-ctx.Done():
return
case logCh <- info:
}
......
......@@ -18,7 +18,9 @@ package madmin
import (
"bytes"
"context"
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
......@@ -109,7 +111,7 @@ func privateNew(endpoint, accessKeyID, secretAccessKey string, secure bool) (*Ad
endpointURL: *endpointURL,
// Instantiate http client and bucket location cache.
httpClient: &http.Client{
Transport: http.DefaultTransport,
Transport: DefaultTransport(secure),
},
// Introduce a new locked random seed.
random: rand.New(&lockedRandSource{src: rand.NewSource(time.Now().UTC().UnixNano())}),
......@@ -263,38 +265,19 @@ func (adm AdminClient) dumpHTTP(req *http.Request, resp *http.Response) error {
// do - execute http request.
func (adm AdminClient) do(req *http.Request) (*http.Response, error) {
var resp *http.Response
var err error
// Do the request in a loop in case of 307 http is met since golang still doesn't
// handle properly this situation (https://github.com/golang/go/issues/7912)
for {
resp, err = adm.httpClient.Do(req)
if err != nil {
// Close idle connections upon error.
adm.httpClient.CloseIdleConnections()
// Handle this specifically for now until future Golang
// versions fix this issue properly.
urlErr, ok := err.(*url.Error)
if ok && strings.Contains(urlErr.Err.Error(), "EOF") {
resp, err := adm.httpClient.Do(req)
if err != nil {
// Handle this specifically for now until future Golang versions fix this issue properly.
if urlErr, ok := err.(*url.Error); ok {
if strings.Contains(urlErr.Err.Error(), "EOF") {
return nil, &url.Error{
Op: urlErr.Op,
URL: urlErr.URL,
Err: fmt.Errorf("Connection closed by foreign host %s", urlErr.URL),
Err: errors.New("Connection closed by foreign host " + urlErr.URL + ". Retry again."),
}
}
return nil, err
}
// Redo the request with the new redirect url if http 307 is returned, quit the loop otherwise
if resp != nil && resp.StatusCode == http.StatusTemporaryRedirect {
newURL, uErr := url.Parse(resp.Header.Get("Location"))
if uErr != nil {
break
}
req.URL = newURL
} else {
break
}
return nil, err
}
// Response cannot be non-nil, report if its the case.
......@@ -323,16 +306,23 @@ var successStatus = []int{
// executeMethod - instantiates a given method, and retries the
// request upon any error up to maxRetries attempts in a binomially
// delayed manner using a standard back off algorithm.
func (adm AdminClient) executeMethod(method string, reqData requestData) (res *http.Response, err error) {
func (adm AdminClient) executeMethod(ctx context.Context, method string, reqData requestData) (res *http.Response, err error) {
var reqRetry = MaxRetry // Indicates how many times we can retry the request
// Create a done channel to control 'ListObjects' go routine.
doneCh := make(chan struct{}, 1)
defer func() {
if err != nil {
// close idle connections before returning, upon error.
adm.httpClient.CloseIdleConnections()
}
}()
// Create cancel context to control 'newRetryTimer' go routine.
retryCtx, cancel := context.WithCancel(ctx)
// Indicate to our routine to exit cleanly upon return.
defer close(doneCh)
defer cancel()
for range adm.newRetryTimer(reqRetry, DefaultRetryUnit, DefaultRetryCap, MaxJitter, doneCh) {
for range adm.newRetryTimer(retryCtx, reqRetry, DefaultRetryUnit, DefaultRetryCap, MaxJitter) {
// Instantiate a new request.
var req *http.Request
req, err = adm.newRequest(method, reqData)
......@@ -340,6 +330,9 @@ func (adm AdminClient) executeMethod(method string, reqData requestData) (res *h
return nil, err
}
// Add context to request
req = req.WithContext(ctx)
// Initiate the request.
res, err = adm.do(req)
if err != nil {
......
......@@ -19,14 +19,16 @@ package madmin
import (
"bytes"
"context"
"io"
"net/http"
)
// GetConfig - returns the config.json of a minio setup, incoming data is encrypted.
func (adm *AdminClient) GetConfig() ([]byte, error) {
func (adm *AdminClient) GetConfig(ctx context.Context) ([]byte, error) {
// Execute GET on /minio/admin/v2/config to get config of a setup.
resp, err := adm.executeMethod(http.MethodGet,
resp, err := adm.executeMethod(ctx,
http.MethodGet,
requestData{relPath: adminAPIPrefix + "/config"})
defer closeResponse(resp)
if err != nil {
......@@ -41,7 +43,7 @@ func (adm *AdminClient) GetConfig() ([]byte, error) {
}
// SetConfig - set config supplied as config.json for the setup.
func (adm *AdminClient) SetConfig(config io.Reader) (err error) {
func (adm *AdminClient) SetConfig(ctx context.Context, config io.Reader) (err error) {
const maxConfigJSONSize = 256 * 1024 // 256KiB
// Read configuration bytes
......@@ -65,7 +67,7 @@ func (adm *AdminClient) SetConfig(config io.Reader) (err error) {
}
// Execute PUT on /minio/admin/v2/config to set config.
resp, err := adm.executeMethod(http.MethodPut, reqData)
resp, err := adm.executeMethod(ctx, http.MethodPut, reqData)
defer closeResponse(resp)
if err != nil {
......
......@@ -18,6 +18,7 @@
package madmin
import (
"context"
"encoding/json"
"net/http"
"net/url"
......@@ -45,7 +46,7 @@ type HelpKV struct {
type HelpKVS []HelpKV
// HelpConfigKV - return help for a given sub-system.
func (adm *AdminClient) HelpConfigKV(subSys, key string, envOnly bool) (Help, error) {
func (adm *AdminClient) HelpConfigKV(ctx context.Context, subSys, key string, envOnly bool) (Help, error) {
v := url.Values{}
v.Set("subSys", subSys)
v.Set("key", key)
......@@ -59,7 +60,7 @@ func (adm *AdminClient) HelpConfigKV(subSys, key string, envOnly bool) (Help, er
}
// Execute GET on /minio/admin/v2/help-config-kv
resp, err := adm.executeMethod(http.MethodGet, reqData)
resp, err := adm.executeMethod(ctx, http.MethodGet, reqData)
if err != nil {
return Help{}, err
}
......
......@@ -18,6 +18,7 @@
package madmin
import (
"context"
"encoding/json"
"net/http"
"net/url"
......@@ -28,7 +29,7 @@ import (
// ClearConfigHistoryKV - clears the config entry represented by restoreID.
// optionally allows setting `all` as a special keyword to automatically
// erase all config set history entires.
func (adm *AdminClient) ClearConfigHistoryKV(restoreID string) (err error) {
func (adm *AdminClient) ClearConfigHistoryKV(ctx context.Context, restoreID string) (err error) {
v := url.Values{}
v.Set("restoreId", restoreID)
reqData := requestData{
......@@ -37,7 +38,7 @@ func (adm *AdminClient) ClearConfigHistoryKV(restoreID string) (err error) {
}
// Execute DELETE on /minio/admin/v2/clear-config-history-kv
resp, err := adm.executeMethod(http.MethodDelete, reqData)
resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData)
defer closeResponse(resp)
if err != nil {
......@@ -53,7 +54,7 @@ func (adm *AdminClient) ClearConfigHistoryKV(restoreID string) (err error) {
// RestoreConfigHistoryKV - Restore a previous config set history.
// Input is a unique id which represents the previous setting.
func (adm *AdminClient) RestoreConfigHistoryKV(restoreID string) (err error) {
func (adm *AdminClient) RestoreConfigHistoryKV(ctx context.Context, restoreID string) (err error) {
v := url.Values{}
v.Set("restoreId", restoreID)
reqData := requestData{
......@@ -62,7 +63,7 @@ func (adm *AdminClient) RestoreConfigHistoryKV(restoreID string) (err error) {
}
// Execute PUT on /minio/admin/v2/set-config-kv to set config key/value.
resp, err := adm.executeMethod(http.MethodPut, reqData)
resp, err := adm.executeMethod(ctx, http.MethodPut, reqData)
defer closeResponse(resp)
if err != nil {
......@@ -90,7 +91,7 @@ func (ch ConfigHistoryEntry) CreateTimeFormatted() string {
}
// ListConfigHistoryKV - lists a slice of ConfigHistoryEntries sorted by createTime.
func (adm *AdminClient) ListConfigHistoryKV(count int) ([]ConfigHistoryEntry, error) {
func (adm *AdminClient) ListConfigHistoryKV(ctx context.Context, count int) ([]ConfigHistoryEntry, error) {
if count == 0 {
count = 10
}
......@@ -98,7 +99,8 @@ func (adm *AdminClient) ListConfigHistoryKV(count int) ([]ConfigHistoryEntry, er
v.Set("count", strconv.Itoa(count))
// Execute GET on /minio/admin/v2/list-config-history-kv
resp, err := adm.executeMethod(http.MethodGet,
resp, err := adm.executeMethod(ctx,
http.MethodGet,
requestData{
relPath: adminAPIPrefix + "/list-config-history-kv",
queryValues: v,
......
......@@ -18,12 +18,13 @@
package madmin
import (
"context"
"net/http"
"net/url"
)
// DelConfigKV - delete key from server config.
func (adm *AdminClient) DelConfigKV(k string) (err error) {
func (adm *AdminClient) DelConfigKV(ctx context.Context, k string) (err error) {
econfigBytes, err := EncryptData(adm.secretAccessKey, []byte(k))
if err != nil {
return err
......@@ -35,7 +36,7 @@ func (adm *AdminClient) DelConfigKV(k string) (err error) {
}
// Execute DELETE on /minio/admin/v2/del-config-kv to delete config key.
resp, err := adm.executeMethod(http.MethodDelete, reqData)
resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData)
defer closeResponse(resp)
if err != nil {
......@@ -50,7 +51,7 @@ func (adm *AdminClient) DelConfigKV(k string) (err error) {
}
// SetConfigKV - set key value config to server.
func (adm *AdminClient) SetConfigKV(kv string) (err error) {
func (adm *AdminClient) SetConfigKV(ctx context.Context, kv string) (err error) {
econfigBytes, err := EncryptData(adm.secretAccessKey, []byte(kv))
if err != nil {
return err
......@@ -62,7 +63,7 @@ func (adm *AdminClient) SetConfigKV(kv string) (err error) {
}
// Execute PUT on /minio/admin/v2/set-config-kv to set config key/value.
resp, err := adm.executeMethod(http.MethodPut, reqData)
resp, err := adm.executeMethod(ctx, http.MethodPut, reqData)
defer closeResponse(resp)
if err != nil {
......@@ -77,12 +78,13 @@ func (adm *AdminClient) SetConfigKV(kv string) (err error) {
}
// GetConfigKV - returns the key, value of the requested key, incoming data is encrypted.
func (adm *AdminClient) GetConfigKV(key string) (Targets, error) {
func (adm *AdminClient) GetConfigKV(ctx context.Context, key string) (Targets, error) {
v := url.Values{}
v.Set("key", key)
// Execute GET on /minio/admin/v2/get-config-kv?key={key} to get value of key.
resp, err := adm.executeMethod(http.MethodGet,
resp, err := adm.executeMethod(ctx,
http.MethodGet,
requestData{
relPath: adminAPIPrefix + "/get-config-kv",
queryValues: v,
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
accountingUsageInfo, err := madmClnt.AccountingUsageInfo()
accountingUsageInfo, err := madmClnt.AccountingUsageInfo(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"fmt"
"log"
......@@ -43,7 +44,7 @@ func main() {
// Create policy
policy := `{"Version": "2012-10-17","Statement": [{"Action": ["s3:GetObject"],"Effect": "Allow","Resource": ["arn:aws:s3:::testbucket/*"],"Sid": ""}]}`
creds, err := madmClnt.AddServiceAccount("parentuser", policy)
creds, err := madmClnt.AddServiceAccount(context.Background(), "parentuser", policy)
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -39,18 +40,18 @@ func main() {
log.Fatalln(err)
}
if err = madmClnt.AddUser("newuser", "newstrongpassword"); err != nil {
if err = madmClnt.AddUser(context.Background(), "newuser", "newstrongpassword"); err != nil {
log.Fatalln(err)
}
// Create policy
policy := `{"Version": "2012-10-17","Statement": [{"Action": ["s3:GetObject"],"Effect": "Allow","Resource": ["arn:aws:s3:::my-bucketname/*"],"Sid": ""}]}`
if err = madmClnt.AddCannedPolicy("get-only", policy); err != nil {
if err = madmClnt.AddCannedPolicy(context.Background(), "get-only", policy); err != nil {
log.Fatalln(err)
}
if err = madmClnt.SetUserPolicy("newuser", "get-only"); err != nil {
if err = madmClnt.SetUserPolicy(context.Background(), "newuser", "get-only"); err != nil {
log.Fatalln(err)
}
}
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
st, err := madmClnt.ServerCPULoadInfo()
st, err := madmClnt.ServerCPULoadInfo(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
dataUsageInfo, err := madmClnt.DataUsageInfo()
dataUsageInfo, err := madmClnt.DataUsageInfo(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
st, err := madmClnt.ServerDrivesPerfInfo(madmin.DefaultDrivePerfSize)
st, err := madmClnt.ServerDrivesPerfInfo(context.Background(), madmin.DefaultDrivePerfSize)
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"fmt"
"log"
......@@ -40,7 +41,7 @@ func main() {
log.Fatalln(err)
}
creds, err := madmClnt.GetServiceAccount("service-account-access-key")
creds, err := madmClnt.GetServiceAccount(context.Background(), "service-account-access-key")
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -38,7 +39,7 @@ func main() {
// Heal bucket mybucket - dry run
isDryRun := true
err = madmClnt.HealBucket("mybucket", isDryRun)
err = madmClnt.HealBucket(context.Background(), "mybucket", isDryRun)
if err != nil {
log.Fatalln(err)
......@@ -46,7 +47,7 @@ func main() {
// Heal bucket mybucket - for real this time.
isDryRun := false
err = madmClnt.HealBucket("mybucket", isDryRun)
err = madmClnt.HealBucket(context.Background(), "mybucket", isDryRun)
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@ package main
*/
import (
"context"
"fmt"
"log"
......@@ -39,7 +40,7 @@ func main() {
}
// List buckets that need healing
healBucketsList, err := madmClnt.ListBucketsHeal()
healBucketsList, err := madmClnt.ListBucketsHeal(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -41,14 +42,14 @@ func main() {
// Attempt healing format in dry-run mode.
isDryRun := true
err = madmClnt.HealFormat(isDryRun)
err = madmClnt.HealFormat(context.Background(), isDryRun)
if err != nil {
log.Fatalln(err)
}
// Perform actual healing of format.
isDryRun = false
err = madmClnt.HealFormat(isDryRun)
err = madmClnt.HealFormat(context.Background(), isDryRun)
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -41,14 +42,14 @@ func main() {
// Heal object mybucket/myobject - dry run.
isDryRun := true
_, err = madmClnt.HealObject("mybucket", "myobject", isDryRun)
_, err = madmClnt.HealObject(context.Background(), "mybucket", "myobject", isDryRun)
if err != nil {
log.Fatalln(err)
}
// Heal object mybucket/myobject - this time for real.
isDryRun = false
healResult, err := madmClnt.HealObject("mybucket", "myobject", isDryRun)
healResult, err := madmClnt.HealObject(context.Background(), "mybucket", "myobject", isDryRun)
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
healStatusResult, err := madmClnt.BackgroundHealStatus()
healStatusResult, err := madmClnt.BackgroundHealStatus(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -35,7 +36,7 @@ func main() {
if err != nil {
log.Fatalln(err)
}
st, err := madmClnt.ServerCPUHardwareInfo()
st, err := madmClnt.ServerCPUHardwareInfo(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -35,7 +36,7 @@ func main() {
if err != nil {
log.Fatalln(err)
}
st, err := madmClnt.ServerNetworkHardwareInfo()
st, err := madmClnt.ServerNetworkHardwareInfo(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
status, err := madmClnt.GetKeyStatus("") // empty string refers to the default master key
status, err := madmClnt.GetKeyStatus(context.Background(), "") // empty string refers to the default master key
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"time"
......@@ -39,7 +40,7 @@ func main() {
// Clear locks held on mybucket/myprefix for longer than 30s.
olderThan := time.Duration(30 * time.Second)
locksCleared, err := madmClnt.ClearLocks("mybucket", "myprefix", olderThan)
locksCleared, err := madmClnt.ClearLocks(context.Background(), "mybucket", "myprefix", olderThan)
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
st, err := madmClnt.ServerMemUsageInfo()
st, err := madmClnt.ServerMemUsageInfo(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
st, err := madmClnt.NetPerfInfo(madmin.DefaultNetPerfSize)
st, err := madmClnt.NetPerfInfo(context.Background(), madmin.DefaultNetPerfSize)
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"io"
"log"
"os"
......@@ -45,7 +46,7 @@ func main() {
profiler := madmin.ProfilerCPU
log.Println("Starting " + profiler + " profiling..")
startResults, err := madmClnt.StartProfiling(profiler)
startResults, err := madmClnt.StartProfiling(context.Background(), profiler)
if err != nil {
log.Fatalln(err)
}
......@@ -63,7 +64,7 @@ func main() {
log.Println("Stopping profiling..")
profilingData, err := madmClnt.DownloadProfilingData()
profilingData, err := madmClnt.DownloadProfilingData(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
st, err := madmClnt.ServerInfo()
st, err := madmClnt.ServerInfo(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
err = madmClnt.ServiceRestart()
err = madmClnt.ServiceRestart(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"fmt"
"log"
......@@ -43,7 +44,7 @@ func main() {
// in the minio cluster.
allTrace := false
errTrace := false
traceCh := madmClnt.ServiceTrace(allTrace, errTrace, doneCh)
traceCh := madmClnt.ServiceTrace(context.Background(), allTrace, errTrace, doneCh)
for traceInfo := range traceCh {
if traceInfo.Err != nil {
fmt.Println(traceInfo.Err)
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"log"
"github.com/minio/minio/pkg/madmin"
......@@ -36,7 +37,7 @@ func main() {
log.Fatalln(err)
}
st, err := madmClnt.StorageInfo()
st, err := madmClnt.StorageInfo(context.Background())
if err != nil {
log.Fatalln(err)
}
......
......@@ -20,6 +20,7 @@
package main
import (
"context"
"encoding/json"
"log"
......@@ -37,7 +38,7 @@ func main() {
log.Fatalln(err)
}
locks, err := madmClnt.TopLocks()
locks, err := madmClnt.TopLocks(context.Background())
if err != nil {
log.Fatalf("failed due to: %v", err)
}
......
......@@ -18,6 +18,7 @@
package madmin
import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
......@@ -34,7 +35,7 @@ type GroupAddRemove struct {
// UpdateGroupMembers - adds/removes users to/from a group. Server
// creates the group as needed. Group is removed if remove request is
// made on empty group.
func (adm *AdminClient) UpdateGroupMembers(g GroupAddRemove) error {
func (adm *AdminClient) UpdateGroupMembers(ctx context.Context, g GroupAddRemove) error {
data, err := json.Marshal(g)
if err != nil {
return err
......@@ -46,7 +47,7 @@ func (adm *AdminClient) UpdateGroupMembers(g GroupAddRemove) error {
}
// Execute PUT on /minio/admin/v2/update-group-members
resp, err := adm.executeMethod("PUT", reqData)
resp, err := adm.executeMethod(ctx, http.MethodPut, reqData)
defer closeResponse(resp)
if err != nil {
......@@ -70,7 +71,7 @@ type GroupDesc struct {
}
// GetGroupDescription - fetches information on a group.
func (adm *AdminClient) GetGroupDescription(group string) (*GroupDesc, error) {
func (adm *AdminClient) GetGroupDescription(ctx context.Context, group string) (*GroupDesc, error) {
v := url.Values{}
v.Set("group", group)
reqData := requestData{
......@@ -78,7 +79,7 @@ func (adm *AdminClient) GetGroupDescription(group string) (*GroupDesc, error) {
queryValues: v,
}
resp, err := adm.executeMethod("GET", reqData)
resp, err := adm.executeMethod(ctx, http.MethodGet, reqData)
defer closeResponse(resp)
if err != nil {
return nil, err
......@@ -102,12 +103,12 @@ func (adm *AdminClient) GetGroupDescription(group string) (*GroupDesc, error) {
}
// ListGroups - lists all groups names present on the server.
func (adm *AdminClient) ListGroups() ([]string, error) {
func (adm *AdminClient) ListGroups(ctx context.Context) ([]string, error) {
reqData := requestData{
relPath: adminAPIPrefix + "/groups",
}
resp, err := adm.executeMethod("GET", reqData)
resp, err := adm.executeMethod(ctx, http.MethodGet, reqData)
defer closeResponse(resp)
if err != nil {
return nil, err
......@@ -140,7 +141,7 @@ const (
)
// SetGroupStatus - sets the status of a group.
func (adm *AdminClient) SetGroupStatus(group string, status GroupStatus) error {
func (adm *AdminClient) SetGroupStatus(ctx context.Context, group string, status GroupStatus) error {
v := url.Values{}
v.Set("group", group)
v.Set("status", string(status))
......@@ -150,7 +151,7 @@ func (adm *AdminClient) SetGroupStatus(group string, status GroupStatus) error {
queryValues: v,
}
resp, err := adm.executeMethod("PUT", reqData)
resp, err := adm.executeMethod(ctx, http.MethodPut, reqData)
defer closeResponse(resp)
if err != nil {
return err
......
......@@ -18,6 +18,7 @@
package madmin
import (
"context"
"encoding/json"
"io/ioutil"
"net"
......@@ -47,13 +48,15 @@ type ServerCPUHardwareInfo struct {
}
// ServerCPUHardwareInfo - Returns cpu hardware information
func (adm *AdminClient) ServerCPUHardwareInfo() ([]ServerCPUHardwareInfo, error) {
func (adm *AdminClient) ServerCPUHardwareInfo(ctx context.Context) ([]ServerCPUHardwareInfo, error) {
v := url.Values{}
v.Set(HARDWARE, string(CPU))
resp, err := adm.executeMethod("GET", requestData{
relPath: adminAPIPrefix + "/hardware",
queryValues: v,
})
resp, err := adm.executeMethod(ctx,
http.MethodGet, requestData{
relPath: adminAPIPrefix + "/hardware",
queryValues: v,
},
)
defer closeResponse(resp)
if err != nil {
......@@ -88,13 +91,15 @@ type ServerNetworkHardwareInfo struct {
}
// ServerNetworkHardwareInfo - Returns network hardware information
func (adm *AdminClient) ServerNetworkHardwareInfo() ([]ServerNetworkHardwareInfo, error) {
func (adm *AdminClient) ServerNetworkHardwareInfo(ctx context.Context) ([]ServerNetworkHardwareInfo, error) {
v := url.Values{}
v.Set(HARDWARE, string(NETWORK))
resp, err := adm.executeMethod("GET", requestData{
relPath: "/v1/hardware",
queryValues: v,
})
resp, err := adm.executeMethod(ctx,
http.MethodGet, requestData{
relPath: "/v1/hardware",
queryValues: v,
},
)
defer closeResponse(resp)
if err != nil {
......
......@@ -18,6 +18,7 @@
package madmin
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
......@@ -195,8 +196,8 @@ func (hri *HealResultItem) GetOnlineCounts() (b, a int) {
// forceStart and forceStop are mutually exclusive, you can either
// set one of them to 'true'. If both are set 'forceStart' will be
// honored.
func (adm *AdminClient) Heal(bucket, prefix string, healOpts HealOpts,
clientToken string, forceStart, forceStop bool) (
func (adm *AdminClient) Heal(ctx context.Context, bucket, prefix string,
healOpts HealOpts, clientToken string, forceStart, forceStop bool) (
healStart HealStartSuccess, healTaskStatus HealTaskStatus, err error) {
if forceStart && forceStop {
......@@ -227,11 +228,12 @@ func (adm *AdminClient) Heal(bucket, prefix string, healOpts HealOpts,
queryVals.Set("forceStop", "true")
}
resp, err := adm.executeMethod("POST", requestData{
relPath: path,
content: body,
queryValues: queryVals,
})
resp, err := adm.executeMethod(ctx,
http.MethodPost, requestData{
relPath: path,
content: body,
queryValues: queryVals,
})
defer closeResponse(resp)
if err != nil {
return healStart, healTaskStatus, err
......@@ -279,9 +281,11 @@ type BgHealState struct {
// BackgroundHealStatus returns the background heal status of the
// current server or cluster.
func (adm *AdminClient) BackgroundHealStatus() (BgHealState, error) {
func (adm *AdminClient) BackgroundHealStatus(ctx context.Context) (BgHealState, error) {
// Execute POST request to background heal status api
resp, err := adm.executeMethod("POST", requestData{relPath: adminAPIPrefix + "/background-heal/status"})
resp, err := adm.executeMethod(ctx,
http.MethodPost,
requestData{relPath: adminAPIPrefix + "/background-heal/status"})
if err != nil {
return BgHealState{}, err
}
......
......@@ -18,6 +18,7 @@
package madmin
import (
"context"
"encoding/json"
"errors"
"io/ioutil"
......@@ -114,8 +115,8 @@ func (d1 BackendDisks) Merge(d2 BackendDisks) BackendDisks {
// StorageInfo - Connect to a minio server and call Storage Info Management API
// to fetch server's information represented by StorageInfo structure
func (adm *AdminClient) StorageInfo() (StorageInfo, error) {
resp, err := adm.executeMethod("GET", requestData{relPath: adminAPIPrefix + "/storageinfo"})
func (adm *AdminClient) StorageInfo(ctx context.Context) (StorageInfo, error) {
resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/storageinfo"})
defer closeResponse(resp)
if err != nil {
return StorageInfo{}, err
......@@ -178,8 +179,8 @@ type DataUsageInfo struct {
}
// DataUsageInfo - returns data usage of the current object API
func (adm *AdminClient) DataUsageInfo() (DataUsageInfo, error) {
resp, err := adm.executeMethod("GET", requestData{relPath: adminAPIPrefix + "/datausageinfo"})
func (adm *AdminClient) DataUsageInfo(ctx context.Context) (DataUsageInfo, error) {
resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/datausageinfo"})
defer closeResponse(resp)
if err != nil {
return DataUsageInfo{}, err
......@@ -222,8 +223,8 @@ type BucketAccountingUsage struct {
// AccountingUsageInfo returns the accounting usage info, currently it returns
// the type of access of different accounts to the different buckets.
func (adm *AdminClient) AccountingUsageInfo() (map[string]BucketAccountingUsage, error) {
resp, err := adm.executeMethod(http.MethodGet, requestData{relPath: adminAPIPrefix + "/accountingusageinfo"})
func (adm *AdminClient) AccountingUsageInfo(ctx context.Context) (map[string]BucketAccountingUsage, error) {
resp, err := adm.executeMethod(ctx, http.MethodGet, requestData{relPath: adminAPIPrefix + "/accountingusageinfo"})
defer closeResponse(resp)
if err != nil {
return nil, err
......@@ -260,16 +261,18 @@ type ServerDrivesPerfInfo struct {
}
// ServerDrivesPerfInfo - Returns drive's read and write performance information