mirror of
https://github.com/minio/minio.git
synced 2024-12-23 21:55:53 -05:00
move the dependency to minio/pkg for common libraries (#12397)
This commit is contained in:
parent
547bb7d0a1
commit
81d5688d56
@ -23,7 +23,7 @@ import (
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
"github.com/rs/cors"
|
||||
)
|
||||
|
||||
|
@ -34,7 +34,7 @@ import (
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/pkg/console"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -44,12 +44,12 @@ import (
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/ellipses"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/minio/pkg/handlers"
|
||||
"github.com/minio/minio/pkg/kms"
|
||||
"github.com/minio/pkg/certs"
|
||||
"github.com/minio/pkg/console"
|
||||
"github.com/minio/pkg/ellipses"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// serverDebugLog will enable debug printing
|
||||
|
@ -42,8 +42,8 @@ import (
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/cmd/logger/target/http"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/minio/pkg/kms"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
func initHelp() {
|
||||
|
@ -42,7 +42,7 @@ import (
|
||||
"github.com/minio/minio/pkg/event/target"
|
||||
"github.com/minio/minio/pkg/kms"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/minio/pkg/quick"
|
||||
"github.com/minio/pkg/quick"
|
||||
)
|
||||
|
||||
// DO NOT EDIT following message template, please open a GitHub issue to discuss instead.
|
||||
|
@ -31,7 +31,7 @@ import (
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/event/target"
|
||||
"github.com/minio/minio/pkg/quick"
|
||||
"github.com/minio/pkg/quick"
|
||||
)
|
||||
|
||||
/////////////////// Config V1 ///////////////////
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// API sub-system constants
|
||||
|
2
cmd/config/cache/config.go
vendored
2
cmd/config/cache/config.go
vendored
@ -24,7 +24,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/ellipses"
|
||||
"github.com/minio/pkg/ellipses"
|
||||
)
|
||||
|
||||
// Config represents cache config settings
|
||||
|
2
cmd/config/cache/lookup.go
vendored
2
cmd/config/cache/lookup.go
vendored
@ -22,7 +22,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Cache ENVs
|
||||
|
@ -27,7 +27,7 @@ import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// EnvCertPassword is the environment variable which contains the password used
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Config represents the compression settings.
|
||||
|
@ -27,7 +27,7 @@ import (
|
||||
"github.com/minio/madmin-go"
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Error config error type
|
||||
|
@ -24,8 +24,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/env"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/client/v3/namespace"
|
||||
"go.uber.org/zap"
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Compression environment variables
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
|
||||
ldap "github.com/go-ldap/ldap/v3"
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -32,9 +32,9 @@ import (
|
||||
jwtgo "github.com/dgrijalva/jwt-go"
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
iampolicy "github.com/minio/minio/pkg/iam/policy"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Config - OpenID Config
|
||||
|
@ -29,10 +29,10 @@ import (
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/minio/pkg/event"
|
||||
"github.com/minio/minio/pkg/event/target"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -25,9 +25,9 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
iampolicy "github.com/minio/minio/pkg/iam/policy"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Env IAM OPA URL
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Compression environment variables
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Standard constants for all storage class
|
||||
|
@ -19,7 +19,7 @@ package crypto
|
||||
|
||||
import (
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -39,9 +39,9 @@ import (
|
||||
"github.com/minio/minio/pkg/bucket/lifecycle"
|
||||
"github.com/minio/minio/pkg/bucket/replication"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/event"
|
||||
"github.com/minio/minio/pkg/hash"
|
||||
"github.com/minio/pkg/console"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -35,7 +35,7 @@ import (
|
||||
"github.com/bits-and-blooms/bloom/v3"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/pkg/console"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -36,7 +36,7 @@ import (
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/hash"
|
||||
"github.com/minio/minio/pkg/sync/errgroup"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -25,8 +25,8 @@ import (
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/ellipses"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/ellipses"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// This file implements and supports ellipses pattern for
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/minio/pkg/ellipses"
|
||||
"github.com/minio/pkg/ellipses"
|
||||
)
|
||||
|
||||
// Tests create endpoints with ellipses and without.
|
||||
|
@ -38,9 +38,9 @@ import (
|
||||
"github.com/minio/minio/cmd/config"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/minio/pkg/mountinfo"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// EndpointType - enum for endpoint type.
|
||||
|
@ -32,8 +32,8 @@ import (
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/mimedb"
|
||||
"github.com/minio/minio/pkg/sync/errgroup"
|
||||
"github.com/minio/pkg/mimedb"
|
||||
)
|
||||
|
||||
func (er erasureObjects) getUploadIDDir(bucket, object, uploadID string) string {
|
||||
|
@ -38,8 +38,8 @@ import (
|
||||
"github.com/minio/minio/pkg/event"
|
||||
"github.com/minio/minio/pkg/hash"
|
||||
xioutil "github.com/minio/minio/pkg/ioutil"
|
||||
"github.com/minio/minio/pkg/mimedb"
|
||||
"github.com/minio/minio/pkg/sync/errgroup"
|
||||
"github.com/minio/pkg/mimedb"
|
||||
)
|
||||
|
||||
// list all errors which can be ignored in object operations.
|
||||
|
@ -36,7 +36,7 @@ import (
|
||||
"github.com/minio/minio/cmd/config/storageclass"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/sync/errgroup"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
type erasureServerPools struct {
|
||||
|
@ -37,10 +37,10 @@ import (
|
||||
"github.com/minio/minio-go/v7/pkg/tags"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/bpool"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/dsync"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/minio/pkg/sync/errgroup"
|
||||
"github.com/minio/pkg/console"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// setsDsyncLockers is encapsulated type for Close()
|
||||
|
@ -31,9 +31,9 @@ import (
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/bpool"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/dsync"
|
||||
"github.com/minio/minio/pkg/sync/errgroup"
|
||||
"github.com/minio/pkg/console"
|
||||
)
|
||||
|
||||
// OfflineDisk represents an unavailable disk.
|
||||
|
@ -32,7 +32,7 @@ import (
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/lock"
|
||||
"github.com/minio/minio/pkg/mimedb"
|
||||
"github.com/minio/pkg/mimedb"
|
||||
)
|
||||
|
||||
// FS format, and object metadata.
|
||||
|
@ -33,7 +33,7 @@ import (
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
xioutil "github.com/minio/minio/pkg/ioutil"
|
||||
"github.com/minio/minio/pkg/trie"
|
||||
"github.com/minio/pkg/trie"
|
||||
)
|
||||
|
||||
// Returns EXPORT/.minio.sys/multipart/SHA256/UPLOADID
|
||||
|
@ -44,8 +44,8 @@ import (
|
||||
"github.com/minio/minio/pkg/color"
|
||||
xioutil "github.com/minio/minio/pkg/ioutil"
|
||||
"github.com/minio/minio/pkg/lock"
|
||||
"github.com/minio/minio/pkg/mimedb"
|
||||
"github.com/minio/minio/pkg/mountinfo"
|
||||
"github.com/minio/pkg/mimedb"
|
||||
)
|
||||
|
||||
// Default etag is used for pre-existing objects.
|
||||
|
@ -27,9 +27,9 @@ import (
|
||||
"github.com/minio/minio/cmd/config"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/minio/pkg/hash"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/env"
|
||||
|
||||
minio "github.com/minio/minio-go/v7"
|
||||
)
|
||||
|
@ -31,9 +31,9 @@ import (
|
||||
"github.com/minio/cli"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/certs"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -47,7 +47,7 @@ import (
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/bucket/policy"
|
||||
"github.com/minio/minio/pkg/bucket/policy/condition"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -44,7 +44,7 @@ import (
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/bucket/policy"
|
||||
"github.com/minio/minio/pkg/bucket/policy/condition"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
"google.golang.org/api/googleapi"
|
||||
"google.golang.org/api/iterator"
|
||||
"google.golang.org/api/option"
|
||||
|
@ -43,8 +43,8 @@ import (
|
||||
minio "github.com/minio/minio/cmd"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -27,8 +27,8 @@ import (
|
||||
"github.com/minio/madmin-go"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/console"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -42,9 +42,9 @@ import (
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
etcd "go.etcd.io/etcd/client/v3"
|
||||
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/event"
|
||||
"github.com/minio/minio/pkg/pubsub"
|
||||
"github.com/minio/pkg/certs"
|
||||
)
|
||||
|
||||
// minio configuration related constants.
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/minio/minio/cmd/config/api"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/sys"
|
||||
"github.com/minio/pkg/sys"
|
||||
)
|
||||
|
||||
type apiConfig struct {
|
||||
|
@ -32,9 +32,9 @@ import (
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/cmd/config/api"
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/minio/pkg/fips"
|
||||
"github.com/minio/pkg/certs"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/pkg/certs"
|
||||
)
|
||||
|
||||
func TestNewServer(t *testing.T) {
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/cmd/config"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// Console logger target
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
|
||||
"github.com/minio/minio/cmd/logger/message/log"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
c "github.com/minio/minio/pkg/console"
|
||||
c "github.com/minio/pkg/console"
|
||||
)
|
||||
|
||||
// Logger interface describes the methods that need to be implemented to satisfy the interface requirements.
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/cmd/logger/message/log"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/pkg/console"
|
||||
)
|
||||
|
||||
// Target implements loggerTarget to send log
|
||||
|
@ -23,9 +23,9 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/minio/cli"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/trie"
|
||||
"github.com/minio/minio/pkg/words"
|
||||
"github.com/minio/pkg/console"
|
||||
"github.com/minio/pkg/trie"
|
||||
"github.com/minio/pkg/words"
|
||||
)
|
||||
|
||||
// GlobalFlags - global flags for minio.
|
||||
|
@ -32,8 +32,8 @@ import (
|
||||
|
||||
"github.com/klauspost/compress/s2"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/hash"
|
||||
"github.com/minio/pkg/console"
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
|
@ -33,8 +33,8 @@ import (
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/hash"
|
||||
"github.com/minio/pkg/console"
|
||||
)
|
||||
|
||||
type listPathOptions struct {
|
||||
|
@ -47,8 +47,8 @@ import (
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/hash"
|
||||
"github.com/minio/minio/pkg/ioutil"
|
||||
"github.com/minio/minio/pkg/trie"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/trie"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
"github.com/klauspost/compress/s2"
|
||||
"github.com/minio/minio/cmd/config/compress"
|
||||
"github.com/minio/minio/cmd/crypto"
|
||||
"github.com/minio/minio/pkg/trie"
|
||||
"github.com/minio/pkg/trie"
|
||||
)
|
||||
|
||||
// Tests validate bucket name.
|
||||
|
@ -40,11 +40,11 @@ import (
|
||||
"github.com/minio/minio/cmd/rest"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/bucket/bandwidth"
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/minio/pkg/fips"
|
||||
"github.com/minio/minio/pkg/sync/errgroup"
|
||||
"github.com/minio/pkg/certs"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// ServerFlags - server command specific flags
|
||||
|
@ -20,7 +20,7 @@ package cmd
|
||||
import (
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/minio/minio/pkg/sys"
|
||||
"github.com/minio/pkg/sys"
|
||||
)
|
||||
|
||||
func setMaxResources() (err error) {
|
||||
|
@ -32,7 +32,7 @@ import (
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
iampolicy "github.com/minio/minio/pkg/iam/policy"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -37,8 +37,8 @@ import (
|
||||
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/env"
|
||||
"github.com/minio/selfupdate"
|
||||
)
|
||||
|
||||
|
@ -47,8 +47,8 @@ import (
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/cmd/rest"
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/handlers"
|
||||
"github.com/minio/pkg/certs"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -45,10 +45,10 @@ import (
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/bucket/lifecycle"
|
||||
"github.com/minio/minio/pkg/color"
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
xioutil "github.com/minio/minio/pkg/ioutil"
|
||||
"github.com/minio/pkg/console"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
const (
|
||||
|
9
go.mod
9
go.mod
@ -23,8 +23,7 @@ require (
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.0
|
||||
github.com/elastic/go-elasticsearch/v7 v7.12.0
|
||||
github.com/fatih/color v1.10.0
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/go-ldap/ldap/v3 v3.2.4
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/gomodule/redigo v2.0.0+incompatible
|
||||
@ -40,8 +39,6 @@ require (
|
||||
github.com/klauspost/readahead v1.3.1
|
||||
github.com/klauspost/reedsolomon v1.9.11
|
||||
github.com/lib/pq v1.9.0
|
||||
github.com/mattn/go-colorable v0.1.8
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/miekg/dns v1.1.35
|
||||
github.com/minio/cli v1.22.0
|
||||
github.com/minio/csvparser v1.0.0
|
||||
@ -50,6 +47,7 @@ require (
|
||||
github.com/minio/madmin-go v1.0.2
|
||||
github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78
|
||||
github.com/minio/parquet-go v1.0.0
|
||||
github.com/minio/pkg v1.0.2
|
||||
github.com/minio/rpc v1.0.0
|
||||
github.com/minio/selfupdate v0.3.1
|
||||
github.com/minio/sha256-simd v1.0.0
|
||||
@ -69,7 +67,6 @@ require (
|
||||
github.com/prometheus/client_golang v1.8.0
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/prometheus/procfs v0.6.0
|
||||
github.com/rjeczalik/notify v0.9.2
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/secure-io/sio-go v0.3.1
|
||||
github.com/shirou/gopsutil/v3 v3.21.3
|
||||
@ -85,7 +82,7 @@ require (
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007
|
||||
golang.org/x/tools v0.1.1 // indirect
|
||||
google.golang.org/api v0.31.0
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
replace google.golang.org/grpc => google.golang.org/grpc v1.29.1
|
||||
|
40
go.sum
40
go.sum
@ -148,6 +148,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4=
|
||||
github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
|
||||
github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 h1:sgNeV1VRMDzs6rzyPpxyM0jp317hnwiq58Filgag2xw=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0/go.mod h1:J70FGZSbzsjecRTiTzER+3f1KZLNaXkuv+yeFTKoxM8=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/djherbis/atime v1.0.0 h1:ySLvBAM0EvOGaX7TI4dAM5lWj+RdJUCKtGSEHN8SGBg=
|
||||
@ -173,8 +177,9 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
@ -211,6 +216,8 @@ github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gG
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/goccy/go-json v0.4.8 h1:TfwOxfSp8hXH+ivoOk36RyDNmXATUETRdaNWDaZglf8=
|
||||
github.com/goccy/go-json v0.4.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@ -428,6 +435,22 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.7 h1:i2SeK33aOFJlUNJZzf2IpXRBvqBBnaGXfY5Xaop/GsE=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.7/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
|
||||
github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=
|
||||
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
|
||||
github.com/lestrrat-go/codegen v1.0.0/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM=
|
||||
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=
|
||||
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
|
||||
github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A=
|
||||
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||
github.com/lestrrat-go/jwx v1.2.0 h1:n08WEu8cJy3uzuQ39KWAOIhM4XfeozgaEGA8mTiioZ8=
|
||||
github.com/lestrrat-go/jwx v1.2.0/go.mod h1:Tg2uP7bpxEHUDtuWjap/PxroJ4okxGzkQznXiG+a5Dc=
|
||||
github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/pdebug/v3 v3.0.1 h1:3G5sX/aw/TbMTtVc9U7IHBWRZtMvwvBziF1e4HoQtv8=
|
||||
github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4=
|
||||
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
@ -448,8 +471,9 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
@ -480,6 +504,8 @@ github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78 h1:v7OMbUnWky
|
||||
github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78/go.mod h1:mTh2uJuAbEqdhMVl6CMIIZLUeiMiWtJR4JB8/5g2skw=
|
||||
github.com/minio/parquet-go v1.0.0 h1:fcWsEvub04Nsl/4hiRBDWlbqd6jhacQieV07a+nhiIk=
|
||||
github.com/minio/parquet-go v1.0.0/go.mod h1:aQlkSOfOq2AtQKkuou3mosNVMwNokd+faTacxxk/oHA=
|
||||
github.com/minio/pkg v1.0.2 h1:vUlNMJbOgP/Hi/ekN+tl1xTOm3Q39gPr5XurDVOgvBA=
|
||||
github.com/minio/pkg v1.0.2/go.mod h1:e9WOU0bav8jd8AzloFjCTSiXSNqnXqxbzGwlH+2rQnI=
|
||||
github.com/minio/rpc v1.0.0 h1:tJCHyLfQF6k6HlMQFpKy2FO/7lc2WP8gLDGMZp18E70=
|
||||
github.com/minio/rpc v1.0.0/go.mod h1:b9xqF7J0xeMXr0cM4pnBlP7Te7PDsG5JrRxl5dG6Ldk=
|
||||
github.com/minio/selfupdate v0.3.1 h1:BWEFSNnrZVMUWXbXIgLDNDjbejkmpAmZvy/nCz1HlEs=
|
||||
@ -671,8 +697,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
|
||||
github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/gjson v1.7.5 h1:zmAN/xmX7OtpAkv4Ovfso60r/BiCi5IErCDYGNJu+uc=
|
||||
@ -764,6 +791,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||
@ -798,6 +826,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -986,9 +1015,11 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
@ -1110,8 +1141,9 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
|
||||
"github.com/beevik/ntp"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// RetMode - object retention mode.
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/s3utils"
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
func toStringLikeFuncString(n name, key Key, values set.StringSet) string {
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
// Principal - policy principal.
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/pkg/bucket/policy/condition"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
// ResourceARNPrefix - resource ARN prefix as per AWS S3 specification.
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
// DestinationARNPrefix - destination ARN prefix as per AWS S3 specification.
|
||||
|
@ -1,93 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// GetRootCAs loads all X.509 certificates at the given path and adds them
|
||||
// to the list of system root CAs, if available. The returned CA pool
|
||||
// is a conjunction of the system root CAs and the certificate(s) at
|
||||
// the given path.
|
||||
//
|
||||
// If path is a regular file, LoadCAs simply adds it to the CA pool
|
||||
// if the file contains a valid X.509 certificate
|
||||
//
|
||||
// If the path points to a directory, LoadCAs iterates over all top-level
|
||||
// files within the directory and adds them to the CA pool if they contain
|
||||
// a valid X.509 certificate.
|
||||
func GetRootCAs(path string) (*x509.CertPool, error) {
|
||||
rootCAs, _ := loadSystemRoots()
|
||||
if rootCAs == nil {
|
||||
// In some systems system cert pool is not supported
|
||||
// or no certificates are present on the
|
||||
// system - so we create a new cert pool.
|
||||
rootCAs = x509.NewCertPool()
|
||||
}
|
||||
|
||||
// Open the file path and check whether its a regular file
|
||||
// or a directory.
|
||||
f, err := os.Open(path)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return rootCAs, nil
|
||||
}
|
||||
if errors.Is(err, os.ErrPermission) {
|
||||
return rootCAs, nil
|
||||
}
|
||||
if err != nil {
|
||||
return rootCAs, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
stat, err := f.Stat()
|
||||
if err != nil {
|
||||
return rootCAs, err
|
||||
}
|
||||
|
||||
// In case of a file add it to the root CAs.
|
||||
if !stat.IsDir() {
|
||||
bytes, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return rootCAs, err
|
||||
}
|
||||
if !rootCAs.AppendCertsFromPEM(bytes) {
|
||||
return rootCAs, fmt.Errorf("cert: %q does not contain a valid X.509 PEM-encoded certificate", path)
|
||||
}
|
||||
return rootCAs, nil
|
||||
}
|
||||
|
||||
// Otherwise iterate over the files in the directory
|
||||
// and add each on to the root CAs.
|
||||
files, err := f.Readdirnames(0)
|
||||
if err != nil {
|
||||
return rootCAs, err
|
||||
}
|
||||
for _, file := range files {
|
||||
bytes, err := ioutil.ReadFile(filepath.Join(path, file))
|
||||
if err == nil { // ignore files which are not readable.
|
||||
rootCAs.AppendCertsFromPEM(bytes)
|
||||
}
|
||||
}
|
||||
return rootCAs, nil
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetRootCAs(t *testing.T) {
|
||||
emptydir, err := ioutil.TempDir("", "test-get-root-cas")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable create temp directory. %v", emptydir)
|
||||
}
|
||||
defer os.RemoveAll(emptydir)
|
||||
|
||||
dir1, err := ioutil.TempDir("", "test-get-root-cas")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable create temp directory. %v", dir1)
|
||||
}
|
||||
defer os.RemoveAll(dir1)
|
||||
if err = os.Mkdir(filepath.Join(dir1, "empty-dir"), 0755); err != nil {
|
||||
t.Fatalf("Unable create empty dir. %v", err)
|
||||
}
|
||||
|
||||
dir2, err := ioutil.TempDir("", "test-get-root-cas")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable create temp directory. %v", dir2)
|
||||
}
|
||||
defer os.RemoveAll(dir2)
|
||||
if err = ioutil.WriteFile(filepath.Join(dir2, "empty-file"), []byte{}, 0644); err != nil {
|
||||
t.Fatalf("Unable create test file. %v", err)
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
certCAsDir string
|
||||
expectedErr error
|
||||
}{
|
||||
// ignores non-existent directories.
|
||||
{"nonexistent-dir", nil},
|
||||
// Ignores directories.
|
||||
{dir1, nil},
|
||||
// Ignore empty directory.
|
||||
{emptydir, nil},
|
||||
// Loads the cert properly.
|
||||
{dir2, nil},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
_, err := GetRootCAs(testCase.certCAsDir)
|
||||
|
||||
if testCase.expectedErr == nil {
|
||||
if err != nil {
|
||||
t.Fatalf("error: expected = <nil>, got = %v", err)
|
||||
}
|
||||
} else if err == nil {
|
||||
t.Fatalf("error: expected = %v, got = <nil>", testCase.expectedErr)
|
||||
} else if testCase.expectedErr.Error() != err.Error() {
|
||||
t.Fatalf("error: expected = %v, got = %v", testCase.expectedErr, err)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Possible directories with certificate files, this is an extended
|
||||
// list from https://golang.org/src/crypto/x509/root_unix.go?#L18
|
||||
// for k8s platform
|
||||
var certDirectories = []string{
|
||||
"/var/run/secrets/kubernetes.io/serviceaccount",
|
||||
}
|
||||
|
||||
// readUniqueDirectoryEntries is like ioutil.ReadDir but omits
|
||||
// symlinks that point within the directory.
|
||||
func readUniqueDirectoryEntries(dir string) ([]os.FileInfo, error) {
|
||||
fis, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uniq := fis[:0]
|
||||
for _, fi := range fis {
|
||||
if !isSameDirSymlink(fi, dir) {
|
||||
uniq = append(uniq, fi)
|
||||
}
|
||||
}
|
||||
return uniq, nil
|
||||
}
|
||||
|
||||
// isSameDirSymlink reports whether fi in dir is a symlink with a
|
||||
// target not containing a slash.
|
||||
func isSameDirSymlink(fi os.FileInfo, dir string) bool {
|
||||
if fi.Mode()&os.ModeSymlink == 0 {
|
||||
return false
|
||||
}
|
||||
target, err := os.Readlink(filepath.Join(dir, fi.Name()))
|
||||
return err == nil && !strings.Contains(target, "/")
|
||||
}
|
||||
|
||||
func loadSystemRoots() (*x509.CertPool, error) {
|
||||
caPool, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
return caPool, err
|
||||
}
|
||||
|
||||
for _, directory := range certDirectories {
|
||||
fis, err := readUniqueDirectoryEntries(directory)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) || os.IsPermission(err) {
|
||||
return caPool, nil
|
||||
}
|
||||
return caPool, err
|
||||
}
|
||||
for _, fi := range fis {
|
||||
data, err := ioutil.ReadFile(directory + "/" + fi.Name())
|
||||
if err == nil {
|
||||
caPool.AppendCertsFromPEM(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
return caPool, nil
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func loadSystemRoots() (*x509.CertPool, error) {
|
||||
const CRYPTENOTFOUND = 0x80092004
|
||||
|
||||
store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CertCloseStore(store, 0)
|
||||
|
||||
roots := x509.NewCertPool()
|
||||
var cert *syscall.CertContext
|
||||
for {
|
||||
cert, err = syscall.CertEnumCertificatesInStore(store, cert)
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok {
|
||||
if errno == CRYPTENOTFOUND {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if cert == nil {
|
||||
break
|
||||
}
|
||||
// Copy the buf, since ParseCertificate does not create its own copy.
|
||||
buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
|
||||
buf2 := make([]byte, cert.Length)
|
||||
copy(buf2, buf)
|
||||
if c, err := x509.ParseCertificate(buf2); err == nil {
|
||||
roots.AddCert(c)
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
@ -1,347 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rjeczalik/notify"
|
||||
)
|
||||
|
||||
// LoadX509KeyPairFunc is a function that parses a private key and
|
||||
// certificate file and returns a TLS certificate on success.
|
||||
type LoadX509KeyPairFunc func(certFile, keyFile string) (tls.Certificate, error)
|
||||
|
||||
// GetCertificateFunc is a callback that allows a TLS stack deliver different
|
||||
// certificates based on the client trying to establish a TLS connection.
|
||||
//
|
||||
// For example, a GetCertificateFunc can return different TLS certificates depending
|
||||
// upon the TLS SNI sent by the client.
|
||||
type GetCertificateFunc func(hello *tls.ClientHelloInfo) (*tls.Certificate, error)
|
||||
|
||||
// Manager is a TLS certificate manager that can handle multiple certificates.
|
||||
// When a client tries to establish a TLS connection, Manager will try to
|
||||
// pick a certificate that can be validated by the client.
|
||||
//
|
||||
// For instance, if the client specifies a TLS SNI then Manager will try to
|
||||
// find the corresponding certificate. If there is no such certificate it
|
||||
// will fallback to the certificate named public.crt.
|
||||
//
|
||||
// Manager will automatically reload certificates if the corresponding file changes.
|
||||
type Manager struct {
|
||||
lock sync.RWMutex
|
||||
certificates map[pair]*tls.Certificate // Mapping: certificate file name => TLS certificates
|
||||
defaultCert pair
|
||||
|
||||
loadX509KeyPair LoadX509KeyPairFunc
|
||||
events chan notify.EventInfo
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// pair represents a certificate and private key file tuple.
|
||||
type pair struct {
|
||||
KeyFile string
|
||||
CertFile string
|
||||
}
|
||||
|
||||
// NewManager returns a new Manager that handles one certificate specified via
|
||||
// the certFile and keyFile. It will use the loadX509KeyPair function to (re)load
|
||||
// certificates.
|
||||
//
|
||||
// The certificate loaded from certFile is considered the default certificate.
|
||||
// If a client does not send the TLS SNI extension then Manager will return
|
||||
// this certificate.
|
||||
func NewManager(ctx context.Context, certFile, keyFile string, loadX509KeyPair LoadX509KeyPairFunc) (manager *Manager, err error) {
|
||||
certFile, err = filepath.Abs(certFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyFile, err = filepath.Abs(keyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
manager = &Manager{
|
||||
certificates: map[pair]*tls.Certificate{},
|
||||
defaultCert: pair{
|
||||
KeyFile: keyFile,
|
||||
CertFile: certFile,
|
||||
},
|
||||
loadX509KeyPair: loadX509KeyPair,
|
||||
events: make(chan notify.EventInfo, 1),
|
||||
ctx: ctx,
|
||||
}
|
||||
if err := manager.AddCertificate(certFile, keyFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go manager.watchFileEvents()
|
||||
return manager, nil
|
||||
}
|
||||
|
||||
// AddCertificate adds the TLS certificate in certFile resp. keyFile
|
||||
// to the Manager.
|
||||
//
|
||||
// If there is already a certificate with the same base name it will be
|
||||
// replaced by the newly added one.
|
||||
func (m *Manager) AddCertificate(certFile, keyFile string) (err error) {
|
||||
certFile, err = filepath.Abs(certFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyFile, err = filepath.Abs(keyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certFileIsLink, err := isSymlink(certFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyFileIsLink, err := isSymlink(keyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if certFileIsLink && !keyFileIsLink {
|
||||
return fmt.Errorf("certs: '%s' is a symlink but '%s' is a regular file", certFile, keyFile)
|
||||
}
|
||||
if keyFileIsLink && !certFileIsLink {
|
||||
return fmt.Errorf("certs: '%s' is a symlink but '%s' is a regular file", keyFile, certFile)
|
||||
}
|
||||
|
||||
certificate, err := m.loadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// We set the certificate leaf to the actual certificate such that
|
||||
// we don't have to do the parsing (multiple times) when matching the
|
||||
// certificate to the client hello. This a performance optimisation.
|
||||
if certificate.Leaf == nil {
|
||||
certificate.Leaf, err = x509.ParseCertificate(certificate.Certificate[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
p := pair{
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
}
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
// We don't allow IP SANs in certificates - except for the "default" certificate
|
||||
// which is, by convention, the first certificate added to the manager. The problem
|
||||
// with allowing IP SANs in more than one certificate is that the manager usually can't
|
||||
// match the client SNI to a SAN since the SNI is meant to communicate the destination
|
||||
// host name and clients will not set the SNI to an IP address.
|
||||
// Allowing multiple certificates with IP SANs lead to errors that confuses users - like:
|
||||
// "It works for `https://instance.minio.local` but not for `https://10.0.2.1`"
|
||||
if len(m.certificates) > 0 && len(certificate.Leaf.IPAddresses) > 0 {
|
||||
return errors.New("cert: certificate must not contain any IP SANs: only the default certificate may contain IP SANs")
|
||||
}
|
||||
m.certificates[p] = &certificate
|
||||
|
||||
if certFileIsLink && keyFileIsLink {
|
||||
go m.watchSymlinks(certFile, keyFile)
|
||||
} else {
|
||||
// Windows doesn't allow for watching file changes but instead allows
|
||||
// for directory changes only, while we can still watch for changes
|
||||
// on files on other platforms. Watch parent directory on all platforms
|
||||
// for simplicity.
|
||||
if err = notify.Watch(filepath.Dir(certFile), m.events, eventWrite...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = notify.Watch(filepath.Dir(keyFile), m.events, eventWrite...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// watchSymlinks starts an endless loop reloading the
|
||||
// certFile and keyFile periodically.
|
||||
func (m *Manager) watchSymlinks(certFile, keyFile string) {
|
||||
for {
|
||||
select {
|
||||
case <-m.ctx.Done():
|
||||
return // Once stopped exits this routine.
|
||||
case <-time.After(24 * time.Hour):
|
||||
certificate, err := m.loadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if certificate.Leaf == nil { // This is a performance optimisation
|
||||
certificate.Leaf, err = x509.ParseCertificate(certificate.Certificate[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
p := pair{
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
}
|
||||
m.lock.Lock()
|
||||
m.certificates[p] = &certificate
|
||||
m.lock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// watchFileEvents starts an endless loop waiting for file systems events.
|
||||
// Once an event occurs it reloads the private key and certificate that
|
||||
// has changed, if any.
|
||||
func (m *Manager) watchFileEvents() {
|
||||
for {
|
||||
select {
|
||||
case <-m.ctx.Done():
|
||||
return
|
||||
case event := <-m.events:
|
||||
if !isWriteEvent(event.Event()) {
|
||||
continue
|
||||
}
|
||||
|
||||
for pair := range m.certificates {
|
||||
if p := event.Path(); pair.KeyFile == p || pair.CertFile == p {
|
||||
certificate, err := m.loadX509KeyPair(pair.CertFile, pair.KeyFile)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if certificate.Leaf == nil { // This is performance optimisation
|
||||
certificate.Leaf, err = x509.ParseCertificate(certificate.Certificate[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
m.lock.Lock()
|
||||
m.certificates[pair] = &certificate
|
||||
m.lock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetCertificate returns a TLS certificate based on the client hello.
|
||||
//
|
||||
// It tries to find a certificate that would be accepted by the client
|
||||
// according to the client hello. However, if no certificate can be
|
||||
// found GetCertificate returns the certificate loaded from the
|
||||
// Public file.
|
||||
func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
|
||||
// If the client does not send a SNI we return the "default"
|
||||
// certificate. A client may not send a SNI - e.g. when trying
|
||||
// to connect to an IP directly (https://<ip>:<port>).
|
||||
//
|
||||
// In this case we don't know which the certificate the client
|
||||
// asks for. It may be a public-facing certificate issued by a
|
||||
// public CA or an internal certificate containing internal domain
|
||||
// names.
|
||||
// Now, we should not serve "the first" certificate that would be
|
||||
// accepted by the client based on the Client Hello. Otherwise, we
|
||||
// may expose an internal certificate to the client that contains
|
||||
// internal domain names. That way we would disclose internal
|
||||
// infrastructure details.
|
||||
//
|
||||
// Therefore, we serve the "default" certificate - which by convention
|
||||
// is the first certificate added to the Manager. It's the calling code's
|
||||
// responsibility to ensure that the "public-facing" certificate is used
|
||||
// when creating a Manager instance.
|
||||
if hello.ServerName == "" {
|
||||
certificate := m.certificates[m.defaultCert]
|
||||
return certificate, nil
|
||||
}
|
||||
|
||||
// Optimization: If there is just one certificate, always serve that one.
|
||||
if len(m.certificates) == 1 {
|
||||
for _, certificate := range m.certificates {
|
||||
return certificate, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over all certificates and return the first one that would
|
||||
// be accepted by the peer (TLS client) based on the client hello.
|
||||
// In particular, the client usually specifies the requested host/domain
|
||||
// via SNI.
|
||||
//
|
||||
// Note: The certificate.Leaf should be non-nil and contain the actual
|
||||
// client certificate of MinIO that should be presented to the peer (TLS client).
|
||||
// Otherwise, the leaf certificate has to be parsed again - which is kind of
|
||||
// expensive and may cause a performance issue. For more information, check the
|
||||
// docs of tls.ClientHelloInfo.SupportsCertificate.
|
||||
for _, certificate := range m.certificates {
|
||||
if err := hello.SupportsCertificate(certificate); err == nil {
|
||||
return certificate, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("certs: no server certificate is supported by peer")
|
||||
}
|
||||
|
||||
// GetClientCertificate returns a TLS certificate for mTLS based on the
|
||||
// certificate request.
|
||||
//
|
||||
// It tries to find a certificate that would be accepted by the server
|
||||
// according to the certificate request. However, if no certificate can be
|
||||
// found GetClientCertificate returns the certificate loaded from the
|
||||
// Public file.
|
||||
func (m *Manager) GetClientCertificate(reqInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
|
||||
// Optimization: If there is just one certificate, always serve that one.
|
||||
if len(m.certificates) == 1 {
|
||||
for _, certificate := range m.certificates {
|
||||
return certificate, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over all certificates and return the first one that would
|
||||
// be accepted by the peer (TLS server) based on reqInfo.
|
||||
//
|
||||
// Note: The certificate.Leaf should be non-nil and contain the actual
|
||||
// client certificate of MinIO that should be presented to the peer (TLS server).
|
||||
// Otherwise, the leaf certificate has to be parsed again - which is kind of
|
||||
// expensive and may cause a performance issue. For more information, check the
|
||||
// docs of tls.CertificateRequestInfo.SupportsCertificate.
|
||||
for _, certificate := range m.certificates {
|
||||
if err := reqInfo.SupportsCertificate(certificate); err == nil {
|
||||
return certificate, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("certs: no client certificate is supported by peer")
|
||||
}
|
||||
|
||||
// isSymlink returns true if the given file
|
||||
// is a symbolic link.
|
||||
func isSymlink(file string) (bool, error) {
|
||||
st, err := os.Lstat(file)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return st.Mode()&os.ModeSymlink == os.ModeSymlink, nil
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
)
|
||||
|
||||
func updateCerts(crt, key string) {
|
||||
// ignore error handling
|
||||
crtSource, _ := os.Open(crt)
|
||||
defer crtSource.Close()
|
||||
crtDest, _ := os.Create("public.crt")
|
||||
defer crtDest.Close()
|
||||
io.Copy(crtDest, crtSource)
|
||||
|
||||
keySource, _ := os.Open(key)
|
||||
defer keySource.Close()
|
||||
keyDest, _ := os.Create("private.key")
|
||||
defer keyDest.Close()
|
||||
io.Copy(keyDest, keySource)
|
||||
}
|
||||
|
||||
func TestNewManager(t *testing.T) {
|
||||
ctx, cancelFn := context.WithCancel(context.Background())
|
||||
defer cancelFn()
|
||||
c, err := certs.NewManager(ctx, "public.crt", "private.key", tls.LoadX509KeyPair)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hello := &tls.ClientHelloInfo{}
|
||||
gcert, err := c.GetCertificate(hello)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expectedCert, err := tls.LoadX509KeyPair("public.crt", "private.key")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(gcert.Certificate, expectedCert.Certificate) {
|
||||
t.Error("certificate doesn't match expected certificate")
|
||||
}
|
||||
_, err = certs.NewManager(ctx, "public.crt", "new-private.key", tls.LoadX509KeyPair)
|
||||
if err == nil {
|
||||
t.Fatal("Expected to fail but got success")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidPairAfterWrite(t *testing.T) {
|
||||
ctx, cancelFn := context.WithCancel(context.Background())
|
||||
defer cancelFn()
|
||||
expectedCert, err := tls.LoadX509KeyPair("new-public.crt", "new-private.key")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
c, err := certs.NewManager(ctx, "public.crt", "private.key", tls.LoadX509KeyPair)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
updateCerts("new-public.crt", "new-private.key")
|
||||
defer updateCerts("original-public.crt", "original-private.key")
|
||||
|
||||
// Wait for the write event..
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
hello := &tls.ClientHelloInfo{}
|
||||
gcert, err := c.GetCertificate(hello)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gcert.Certificate, expectedCert.Certificate) {
|
||||
t.Error("certificate doesn't match expected certificate")
|
||||
}
|
||||
|
||||
rInfo := &tls.CertificateRequestInfo{}
|
||||
gcert, err = c.GetClientCertificate(rInfo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gcert.Certificate, expectedCert.Certificate) {
|
||||
t.Error("client certificate doesn't match expected certificate")
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs
|
||||
|
||||
import (
|
||||
"github.com/rjeczalik/notify"
|
||||
)
|
||||
|
||||
// isWriteEvent checks if the event returned is a write event
|
||||
func isWriteEvent(event notify.Event) bool {
|
||||
for _, ev := range eventWrite {
|
||||
if event&ev != 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// +build linux
|
||||
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs
|
||||
|
||||
import "github.com/rjeczalik/notify"
|
||||
|
||||
var (
|
||||
// eventWrite contains the notify events that will cause a write
|
||||
eventWrite = []notify.Event{notify.InCloseWrite}
|
||||
)
|
@ -1,27 +0,0 @@
|
||||
// +build !linux
|
||||
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package certs
|
||||
|
||||
import "github.com/rjeczalik/notify"
|
||||
|
||||
var (
|
||||
// eventWrite contains the notify events that will cause a write
|
||||
eventWrite = []notify.Event{notify.Create, notify.Write}
|
||||
)
|
@ -1,28 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD4tnz56oMfKgK3
|
||||
scZAiFkr5lqAPFfMnrtrZXzyz+scHfOGLV3qFrqrmxyWOYI2qPbnR+NJakNDiGyx
|
||||
+rI0OZj8hRqmGdP14wE9lfpFdlUVca2lRQW8aKTmF53aDuPkmHL6W7PlAef3NHoT
|
||||
uuSpM+XdYlnZ97gsR+KPr9vNnYIxQWsrK3+6qfiVpOWbgM77COg5QYAeZoduSmSF
|
||||
hNv+ptbNXSoyHRnLiBC4VhwFVsBNx0CNXhtE2Qd3QIsSR3cD1p7llp46uDYeQ9Vy
|
||||
KfGDWWfmMF7YsGoMWoqRa53ObqN43D6gTiUorEN8cfwAPTw3yoVt+zVjFkCMvfAq
|
||||
lxhXDanNAgMBAAECggEBAIGAI5rNbPCxIzEas6uuUx/0lXLn+J9mlxfYhDK56CV/
|
||||
wuk+fgQBSblIzp252/8yAz1xxPrZBaUIR/B0JI3k36+8bp/GGwOQ63hxuxqn/q1n
|
||||
v46qXc44foQAEAUWc7r3Vgbd8NFxKKMjA916Fs2zZCDdsQM5ZQBJfcJrQvvQ45VY
|
||||
//UtXdNeIBQOb5Wg4o9fHJolKzCHWRaD2ExoIHZ5Fa6JpBmk9JBHcUbrHrlbOeep
|
||||
/SkbSa0ma9j3k3jqV970XRoQUCJf+K1Li49jmaYPPGXBUAp6AfU+yiAJ1aups38m
|
||||
BClLAV9g6vgE3xK2xozGPI1+j9lkruYbvGbPNkXexdECgYEA/47XnKITSnxtV+NK
|
||||
nDbWNOgpeaRbxAdjp1P0b4VI0S0SuRvKUOCp1UlPg5BjGL0JLPQpGlPzEfLlGWAa
|
||||
68vhyj0V6HL2+PAJNib1eu6yyRBsSbPdrAD5nydHpbxRcdShhVwb2MHMyBeYH5Al
|
||||
kL+ed5wCF32kXOOGzhoGzJEKNEcCgYEA+SSdcdbuVpQFkAecIoABwdx/qeOAeS19
|
||||
FsvVSTmWlhal8m2Mn8RWZ0IKXT9AoZJ0KQBIKHViPtyV7UQey05uRgLRHZapHpe8
|
||||
dhm6SsGYtU3BhLdHJBP0kI79qm2kzqsHp6ghSzaxT9CkRfMniN+TD+w8p7lrOaxv
|
||||
vV46UHoGX0sCgYB4LlCvVHkF+mXhgv4/YHpz/woiLm0JTwBKXG0DVQbdd/jqHGuU
|
||||
hVLY/tTp5ij0JVH/VgNOYlRZCIU83blLUmIonXmECyyh/SAX21JuMXram2KRdoi0
|
||||
rvC1K9/BzUHv6jLbaGmgEeOf5Zign0VLQRHg5fkF2wxEsqtemVbBNSQ7WQKBgBFk
|
||||
Y/VRervig2zlixnBc93zpZnXft12tnfD7PS6p298z0LYMOvqSdnVe2G9C6b70U4X
|
||||
bfIdF6mpvnGcwsWQiRQsGCsHnHC9SPO5og6b6ywk7HB2VuoG1pjM0pp2Iv4mZFdo
|
||||
3kIg5EndF8qmSck9SkffRvCyefDBv98pV8rMaet3AoGBALjlN2hLoNE5Cs5vTYH8
|
||||
W0AN4lEOaTlBRKG8a1h7Fm2vPgzGGkiwU6bVzsh0oTfytc8v8MW9lNQZpE3dBKne
|
||||
ms3FrNsnBbTczX+xJmndRnVRocdyON6u476VxAuz/dHSFFnZGXX+2lJse9xnWHUz
|
||||
OpSHUPq3TrUzhgZClE2ZKpNm
|
||||
-----END PRIVATE KEY-----
|
@ -1,21 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDYDCCAkigAwIBAgIJALIHkFXjtZ2yMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTgwNTIwMDg1MzI3WhcNMTkwNTIwMDg1MzI3WjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEA+LZ8+eqDHyoCt7HGQIhZK+ZagDxXzJ67a2V88s/rHB3zhi1d6ha6q5sc
|
||||
ljmCNqj250fjSWpDQ4hssfqyNDmY/IUaphnT9eMBPZX6RXZVFXGtpUUFvGik5hed
|
||||
2g7j5Jhy+luz5QHn9zR6E7rkqTPl3WJZ2fe4LEfij6/bzZ2CMUFrKyt/uqn4laTl
|
||||
m4DO+wjoOUGAHmaHbkpkhYTb/qbWzV0qMh0Zy4gQuFYcBVbATcdAjV4bRNkHd0CL
|
||||
Ekd3A9ae5ZaeOrg2HkPVcinxg1ln5jBe2LBqDFqKkWudzm6jeNw+oE4lKKxDfHH8
|
||||
AD08N8qFbfs1YxZAjL3wKpcYVw2pzQIDAQABo1MwUTAdBgNVHQ4EFgQU2Yywgv8p
|
||||
WfyZxYVx+MnH+VQ5TTUwHwYDVR0jBBgwFoAU2Yywgv8pWfyZxYVx+MnH+VQ5TTUw
|
||||
DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA2maF7DQ7CMpCho9B
|
||||
9gjGxvt8HqY1pCyuQwcSPb4PTyoKUZ/ZuIDhVOaBX+ox1RzlfGtYs2BUM63/QUDs
|
||||
dP0GO7/IL/XEqJi1flrFvM7LNSs89qAbPJ440m6jJDzsuL2VeyUX/M72IEsBK2uS
|
||||
ajtS1+HFQjPMvt7wR6fDPCP7wHPOrkTN4hcHlgzVJShKUnFaHtb2lOnWaoM/Sk91
|
||||
IsiyAhKRuCM9et7/bnOj7G8448QDVtQNniT8V/HpqQ7ltSuIGvs3QYTLDTege/74
|
||||
Q8Ph1oH7shyRE/PqPfyIuLq3p0N9Sah3oRMHLohYjJL0zAGt0jxSsnhrBSNUUD/v
|
||||
bAd5VQ==
|
||||
-----END CERTIFICATE-----
|
@ -1,28 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPszxaYwn+mIz6
|
||||
IGuUlmvWwUs/yWTH4MC17qey2N5MqcxlfIWHUugcBsbGhi/e1druFW0s7YGMxp+G
|
||||
+Q1IezxX+VmVaJCN8AgSowbYgpRdpRQ+mhGeQby0JcvO16fyPnUJBz3GGel2bcK8
|
||||
fcQyT0TVapCiD9oURVmdvDSsRXz+EoPlOve8AWciHHgm1ItO5qdPRP5YtcJfLiwK
|
||||
noYnpda2d9SzmYk+Q2JFArooF7/A1DYz9bXCMo3qp0gQlMpSMDR+MCbxHBzBBr+f
|
||||
QG8QdDrzWQ2slhniBhFDk0LuPCBLlSeIzkp+DoAGDXf3hWYhechlabZ7nfngg5er
|
||||
Ez776WCFAgMBAAECggEBAJcHRyCWmcLm3MRY5MF0K9BKV9R3NnBdTuQ8OPdE2Ui3
|
||||
w6gcRuBi+eK/TrU3CAIqUXsEW5Hq1mQuXfwAh5cn/XYfG/QXx91eKBCdOTIgqY/6
|
||||
pODsmVkRhg0c2rl6eWYd4m6BNHsjhm8WWx9C+HJ4z528UpV1n2dUElkvbMHD+aKp
|
||||
Ndwd0W+0PCn/BjMn/sdyy01f8sfaK2Zoy7HBw/fGeBDNLFFj3Iz7BqXYeS+OyfLN
|
||||
B4xD5I5fFqt1iJeyqVPzGkOAYSqisijbM1GtZJCeVp37/+IDylCKTO3l8Xd8x73U
|
||||
qTYcYT3heSHyUC2xCM6Va2YkSrOHeqbq91QgHh9LVrUCgYEA9t/wE2S8TE2l1IG9
|
||||
68SXdhyaXTnB2qSL7ggY0uazPzBNLQpNMOxicZ6/4QGEi3hSuCqGxxGo9UEoTsVd
|
||||
pk8oIeDULdPVi4NQxSmkxUyArs/dzOMygUPyosOiEc8z6jWFFKDcQ7mnZnay8dZ4
|
||||
e4j+/hZDONtDrJ+zH2xu98ZrJPcCgYEA12CbSRbCkTiRj/dq8Qvgp6+ceTVcAbnk
|
||||
MWpAhZQaXHrG3XP0L7QTIHG/7a09Mln92zjuAFXDp/Vc5NdxeXcnj9j6oUAxq+0I
|
||||
dq+vibzjROemmvnmQvXGY9tc0ns6u7GjM0+Sicmas+IH4vuum/aRasABfVe2XBwe
|
||||
4fVs0n7yU2MCgYA7KevFGg0uVCV7yiQTzqdlvPEZim/00B5gyzv3vyYR7KdyNdfN
|
||||
87ib9imR6OU0738Td82ZA5h0PktEpXQOGUZK6DCxUuUIbE39Ej/UsMLeIh7LrV87
|
||||
L2eErlG25utQI8di7DIdYO7HVYcJAhcZs/k4N2mgxJtxUUyCKWBmrPycfQKBgAo7
|
||||
0uUUKcaQs4ntra0qbVBKbdrsiCSk2ozmiY5PTTlbtBtNqSqjGc2O2hnHA4Ni90b1
|
||||
W4m0iYlvhSxyeDfXS4/wNWh4DmQm7SIGkwaubPYXM7llamWAHB8eiziNFmtYs3J6
|
||||
s3HMnIczlEBayR8sBhjWaruz8TxLMcR2zubplUYVAoGBAItxeC9IT8BGJoZB++qM
|
||||
f2LXCqJ383x0sDHhwPMFPtwUTzAwc5BJgQe9zFktW5CBxsER+MnUZjlrarT1HQfH
|
||||
1Y1mJQXtwuBKG4pPPZphH0yoVlYcWkBTMw/KmlVlwRclEzRQwV3TPD+i6ieKeZhz
|
||||
9eZwhS3H+Zb/693WbBDyH8L+
|
||||
-----END PRIVATE KEY-----
|
@ -1,22 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDqjCCApKgAwIBAgIJAOcv4FsrflS4MA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJDQTEVMBMGA1UEBwwMUmVkd29vZCBDaXR5MQ4wDAYD
|
||||
VQQKDAVNaW5pbzEUMBIGA1UECwwLRW5naW5lZXJpbmcxETAPBgNVBAMMCG1pbmlv
|
||||
LmlvMB4XDTE4MDUyMDA4NDc0MFoXDTE5MDUyMDA4NDc0MFowajELMAkGA1UEBhMC
|
||||
VVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENpdHkxDjAMBgNVBAoM
|
||||
BU1pbmlvMRQwEgYDVQQLDAtFbmdpbmVlcmluZzERMA8GA1UEAwwIbWluaW8uaW8w
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPszxaYwn+mIz6IGuUlmvW
|
||||
wUs/yWTH4MC17qey2N5MqcxlfIWHUugcBsbGhi/e1druFW0s7YGMxp+G+Q1IezxX
|
||||
+VmVaJCN8AgSowbYgpRdpRQ+mhGeQby0JcvO16fyPnUJBz3GGel2bcK8fcQyT0TV
|
||||
apCiD9oURVmdvDSsRXz+EoPlOve8AWciHHgm1ItO5qdPRP5YtcJfLiwKnoYnpda2
|
||||
d9SzmYk+Q2JFArooF7/A1DYz9bXCMo3qp0gQlMpSMDR+MCbxHBzBBr+fQG8QdDrz
|
||||
WQ2slhniBhFDk0LuPCBLlSeIzkp+DoAGDXf3hWYhechlabZ7nfngg5erEz776WCF
|
||||
AgMBAAGjUzBRMB0GA1UdDgQWBBRzC09a+3AlbFDg6BsvELolmO8jYjAfBgNVHSME
|
||||
GDAWgBRzC09a+3AlbFDg6BsvELolmO8jYjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQBl0cx7qbidKjhoZ1Iv4pCD8xHZgtuWEDApPoGuMtVS66jJ
|
||||
+oj0ncD5xCtv9XqXtshE65FIsEWnDOIwa+kyjMnxHbFwxveWBT4W0twtqwbVs7NE
|
||||
I0So6cEmSx4+rB0XorY6mIbD3O9YAStelNhB1jVfQfIMSByYkcGq2Fh+B1LHlOrz
|
||||
06LJdwYMiILzK0c5fvjZvsDq/9EK+Xo66hphKjs5cl1t9WK7wKOCoZDt2lOTZqEq
|
||||
UWYGPWlTAxSWQxO4WnvSKqFdsRi8fOO3KlDq1eNqeDSGGCI0DTGgJxidHIpfOPEF
|
||||
s/zojgc5npE32/1n8og6gLcv7LIKelBfMhUrFTp7
|
||||
-----END CERTIFICATE-----
|
@ -1,28 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPszxaYwn+mIz6
|
||||
IGuUlmvWwUs/yWTH4MC17qey2N5MqcxlfIWHUugcBsbGhi/e1druFW0s7YGMxp+G
|
||||
+Q1IezxX+VmVaJCN8AgSowbYgpRdpRQ+mhGeQby0JcvO16fyPnUJBz3GGel2bcK8
|
||||
fcQyT0TVapCiD9oURVmdvDSsRXz+EoPlOve8AWciHHgm1ItO5qdPRP5YtcJfLiwK
|
||||
noYnpda2d9SzmYk+Q2JFArooF7/A1DYz9bXCMo3qp0gQlMpSMDR+MCbxHBzBBr+f
|
||||
QG8QdDrzWQ2slhniBhFDk0LuPCBLlSeIzkp+DoAGDXf3hWYhechlabZ7nfngg5er
|
||||
Ez776WCFAgMBAAECggEBAJcHRyCWmcLm3MRY5MF0K9BKV9R3NnBdTuQ8OPdE2Ui3
|
||||
w6gcRuBi+eK/TrU3CAIqUXsEW5Hq1mQuXfwAh5cn/XYfG/QXx91eKBCdOTIgqY/6
|
||||
pODsmVkRhg0c2rl6eWYd4m6BNHsjhm8WWx9C+HJ4z528UpV1n2dUElkvbMHD+aKp
|
||||
Ndwd0W+0PCn/BjMn/sdyy01f8sfaK2Zoy7HBw/fGeBDNLFFj3Iz7BqXYeS+OyfLN
|
||||
B4xD5I5fFqt1iJeyqVPzGkOAYSqisijbM1GtZJCeVp37/+IDylCKTO3l8Xd8x73U
|
||||
qTYcYT3heSHyUC2xCM6Va2YkSrOHeqbq91QgHh9LVrUCgYEA9t/wE2S8TE2l1IG9
|
||||
68SXdhyaXTnB2qSL7ggY0uazPzBNLQpNMOxicZ6/4QGEi3hSuCqGxxGo9UEoTsVd
|
||||
pk8oIeDULdPVi4NQxSmkxUyArs/dzOMygUPyosOiEc8z6jWFFKDcQ7mnZnay8dZ4
|
||||
e4j+/hZDONtDrJ+zH2xu98ZrJPcCgYEA12CbSRbCkTiRj/dq8Qvgp6+ceTVcAbnk
|
||||
MWpAhZQaXHrG3XP0L7QTIHG/7a09Mln92zjuAFXDp/Vc5NdxeXcnj9j6oUAxq+0I
|
||||
dq+vibzjROemmvnmQvXGY9tc0ns6u7GjM0+Sicmas+IH4vuum/aRasABfVe2XBwe
|
||||
4fVs0n7yU2MCgYA7KevFGg0uVCV7yiQTzqdlvPEZim/00B5gyzv3vyYR7KdyNdfN
|
||||
87ib9imR6OU0738Td82ZA5h0PktEpXQOGUZK6DCxUuUIbE39Ej/UsMLeIh7LrV87
|
||||
L2eErlG25utQI8di7DIdYO7HVYcJAhcZs/k4N2mgxJtxUUyCKWBmrPycfQKBgAo7
|
||||
0uUUKcaQs4ntra0qbVBKbdrsiCSk2ozmiY5PTTlbtBtNqSqjGc2O2hnHA4Ni90b1
|
||||
W4m0iYlvhSxyeDfXS4/wNWh4DmQm7SIGkwaubPYXM7llamWAHB8eiziNFmtYs3J6
|
||||
s3HMnIczlEBayR8sBhjWaruz8TxLMcR2zubplUYVAoGBAItxeC9IT8BGJoZB++qM
|
||||
f2LXCqJ383x0sDHhwPMFPtwUTzAwc5BJgQe9zFktW5CBxsER+MnUZjlrarT1HQfH
|
||||
1Y1mJQXtwuBKG4pPPZphH0yoVlYcWkBTMw/KmlVlwRclEzRQwV3TPD+i6ieKeZhz
|
||||
9eZwhS3H+Zb/693WbBDyH8L+
|
||||
-----END PRIVATE KEY-----
|
@ -1,22 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDqjCCApKgAwIBAgIJAOcv4FsrflS4MA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJDQTEVMBMGA1UEBwwMUmVkd29vZCBDaXR5MQ4wDAYD
|
||||
VQQKDAVNaW5pbzEUMBIGA1UECwwLRW5naW5lZXJpbmcxETAPBgNVBAMMCG1pbmlv
|
||||
LmlvMB4XDTE4MDUyMDA4NDc0MFoXDTE5MDUyMDA4NDc0MFowajELMAkGA1UEBhMC
|
||||
VVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENpdHkxDjAMBgNVBAoM
|
||||
BU1pbmlvMRQwEgYDVQQLDAtFbmdpbmVlcmluZzERMA8GA1UEAwwIbWluaW8uaW8w
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPszxaYwn+mIz6IGuUlmvW
|
||||
wUs/yWTH4MC17qey2N5MqcxlfIWHUugcBsbGhi/e1druFW0s7YGMxp+G+Q1IezxX
|
||||
+VmVaJCN8AgSowbYgpRdpRQ+mhGeQby0JcvO16fyPnUJBz3GGel2bcK8fcQyT0TV
|
||||
apCiD9oURVmdvDSsRXz+EoPlOve8AWciHHgm1ItO5qdPRP5YtcJfLiwKnoYnpda2
|
||||
d9SzmYk+Q2JFArooF7/A1DYz9bXCMo3qp0gQlMpSMDR+MCbxHBzBBr+fQG8QdDrz
|
||||
WQ2slhniBhFDk0LuPCBLlSeIzkp+DoAGDXf3hWYhechlabZ7nfngg5erEz776WCF
|
||||
AgMBAAGjUzBRMB0GA1UdDgQWBBRzC09a+3AlbFDg6BsvELolmO8jYjAfBgNVHSME
|
||||
GDAWgBRzC09a+3AlbFDg6BsvELolmO8jYjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQBl0cx7qbidKjhoZ1Iv4pCD8xHZgtuWEDApPoGuMtVS66jJ
|
||||
+oj0ncD5xCtv9XqXtshE65FIsEWnDOIwa+kyjMnxHbFwxveWBT4W0twtqwbVs7NE
|
||||
I0So6cEmSx4+rB0XorY6mIbD3O9YAStelNhB1jVfQfIMSByYkcGq2Fh+B1LHlOrz
|
||||
06LJdwYMiILzK0c5fvjZvsDq/9EK+Xo66hphKjs5cl1t9WK7wKOCoZDt2lOTZqEq
|
||||
UWYGPWlTAxSWQxO4WnvSKqFdsRi8fOO3KlDq1eNqeDSGGCI0DTGgJxidHIpfOPEF
|
||||
s/zojgc5npE32/1n8og6gLcv7LIKelBfMhUrFTp7
|
||||
-----END CERTIFICATE-----
|
@ -1,22 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDqjCCApKgAwIBAgIJAOcv4FsrflS4MA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJDQTEVMBMGA1UEBwwMUmVkd29vZCBDaXR5MQ4wDAYD
|
||||
VQQKDAVNaW5pbzEUMBIGA1UECwwLRW5naW5lZXJpbmcxETAPBgNVBAMMCG1pbmlv
|
||||
LmlvMB4XDTE4MDUyMDA4NDc0MFoXDTE5MDUyMDA4NDc0MFowajELMAkGA1UEBhMC
|
||||
VVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENpdHkxDjAMBgNVBAoM
|
||||
BU1pbmlvMRQwEgYDVQQLDAtFbmdpbmVlcmluZzERMA8GA1UEAwwIbWluaW8uaW8w
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPszxaYwn+mIz6IGuUlmvW
|
||||
wUs/yWTH4MC17qey2N5MqcxlfIWHUugcBsbGhi/e1druFW0s7YGMxp+G+Q1IezxX
|
||||
+VmVaJCN8AgSowbYgpRdpRQ+mhGeQby0JcvO16fyPnUJBz3GGel2bcK8fcQyT0TV
|
||||
apCiD9oURVmdvDSsRXz+EoPlOve8AWciHHgm1ItO5qdPRP5YtcJfLiwKnoYnpda2
|
||||
d9SzmYk+Q2JFArooF7/A1DYz9bXCMo3qp0gQlMpSMDR+MCbxHBzBBr+fQG8QdDrz
|
||||
WQ2slhniBhFDk0LuPCBLlSeIzkp+DoAGDXf3hWYhechlabZ7nfngg5erEz776WCF
|
||||
AgMBAAGjUzBRMB0GA1UdDgQWBBRzC09a+3AlbFDg6BsvELolmO8jYjAfBgNVHSME
|
||||
GDAWgBRzC09a+3AlbFDg6BsvELolmO8jYjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQBl0cx7qbidKjhoZ1Iv4pCD8xHZgtuWEDApPoGuMtVS66jJ
|
||||
+oj0ncD5xCtv9XqXtshE65FIsEWnDOIwa+kyjMnxHbFwxveWBT4W0twtqwbVs7NE
|
||||
I0So6cEmSx4+rB0XorY6mIbD3O9YAStelNhB1jVfQfIMSByYkcGq2Fh+B1LHlOrz
|
||||
06LJdwYMiILzK0c5fvjZvsDq/9EK+Xo66hphKjs5cl1t9WK7wKOCoZDt2lOTZqEq
|
||||
UWYGPWlTAxSWQxO4WnvSKqFdsRi8fOO3KlDq1eNqeDSGGCI0DTGgJxidHIpfOPEF
|
||||
s/zojgc5npE32/1n8og6gLcv7LIKelBfMhUrFTp7
|
||||
-----END CERTIFICATE-----
|
@ -1,28 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPszxaYwn+mIz6
|
||||
IGuUlmvWwUs/yWTH4MC17qey2N5MqcxlfIWHUugcBsbGhi/e1druFW0s7YGMxp+G
|
||||
+Q1IezxX+VmVaJCN8AgSowbYgpRdpRQ+mhGeQby0JcvO16fyPnUJBz3GGel2bcK8
|
||||
fcQyT0TVapCiD9oURVmdvDSsRXz+EoPlOve8AWciHHgm1ItO5qdPRP5YtcJfLiwK
|
||||
noYnpda2d9SzmYk+Q2JFArooF7/A1DYz9bXCMo3qp0gQlMpSMDR+MCbxHBzBBr+f
|
||||
QG8QdDrzWQ2slhniBhFDk0LuPCBLlSeIzkp+DoAGDXf3hWYhechlabZ7nfngg5er
|
||||
Ez776WCFAgMBAAECggEBAJcHRyCWmcLm3MRY5MF0K9BKV9R3NnBdTuQ8OPdE2Ui3
|
||||
w6gcRuBi+eK/TrU3CAIqUXsEW5Hq1mQuXfwAh5cn/XYfG/QXx91eKBCdOTIgqY/6
|
||||
pODsmVkRhg0c2rl6eWYd4m6BNHsjhm8WWx9C+HJ4z528UpV1n2dUElkvbMHD+aKp
|
||||
Ndwd0W+0PCn/BjMn/sdyy01f8sfaK2Zoy7HBw/fGeBDNLFFj3Iz7BqXYeS+OyfLN
|
||||
B4xD5I5fFqt1iJeyqVPzGkOAYSqisijbM1GtZJCeVp37/+IDylCKTO3l8Xd8x73U
|
||||
qTYcYT3heSHyUC2xCM6Va2YkSrOHeqbq91QgHh9LVrUCgYEA9t/wE2S8TE2l1IG9
|
||||
68SXdhyaXTnB2qSL7ggY0uazPzBNLQpNMOxicZ6/4QGEi3hSuCqGxxGo9UEoTsVd
|
||||
pk8oIeDULdPVi4NQxSmkxUyArs/dzOMygUPyosOiEc8z6jWFFKDcQ7mnZnay8dZ4
|
||||
e4j+/hZDONtDrJ+zH2xu98ZrJPcCgYEA12CbSRbCkTiRj/dq8Qvgp6+ceTVcAbnk
|
||||
MWpAhZQaXHrG3XP0L7QTIHG/7a09Mln92zjuAFXDp/Vc5NdxeXcnj9j6oUAxq+0I
|
||||
dq+vibzjROemmvnmQvXGY9tc0ns6u7GjM0+Sicmas+IH4vuum/aRasABfVe2XBwe
|
||||
4fVs0n7yU2MCgYA7KevFGg0uVCV7yiQTzqdlvPEZim/00B5gyzv3vyYR7KdyNdfN
|
||||
87ib9imR6OU0738Td82ZA5h0PktEpXQOGUZK6DCxUuUIbE39Ej/UsMLeIh7LrV87
|
||||
L2eErlG25utQI8di7DIdYO7HVYcJAhcZs/k4N2mgxJtxUUyCKWBmrPycfQKBgAo7
|
||||
0uUUKcaQs4ntra0qbVBKbdrsiCSk2ozmiY5PTTlbtBtNqSqjGc2O2hnHA4Ni90b1
|
||||
W4m0iYlvhSxyeDfXS4/wNWh4DmQm7SIGkwaubPYXM7llamWAHB8eiziNFmtYs3J6
|
||||
s3HMnIczlEBayR8sBhjWaruz8TxLMcR2zubplUYVAoGBAItxeC9IT8BGJoZB++qM
|
||||
f2LXCqJ383x0sDHhwPMFPtwUTzAwc5BJgQe9zFktW5CBxsER+MnUZjlrarT1HQfH
|
||||
1Y1mJQXtwuBKG4pPPZphH0yoVlYcWkBTMw/KmlVlwRclEzRQwV3TPD+i6ieKeZhz
|
||||
9eZwhS3H+Zb/693WbBDyH8L+
|
||||
-----END PRIVATE KEY-----
|
@ -1,178 +0,0 @@
|
||||
// +build linux
|
||||
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Package cgroup implements parsing for all the cgroup
|
||||
// categories and functionality in a simple way.
|
||||
package cgroup
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DO NOT EDIT following constants are chosen defaults for any kernel
|
||||
// after 3.x, please open a GitHub issue https://github.com/minio/minio/issues
|
||||
// and discuss first if you wish to change this.
|
||||
const (
|
||||
// Default string for looking for kernel memory param.
|
||||
memoryLimitKernelParam = "memory.limit_in_bytes"
|
||||
|
||||
// Points to sys path memory path.
|
||||
cgroupMemSysPath = "/sys/fs/cgroup/memory"
|
||||
|
||||
// Default docker prefix.
|
||||
dockerPrefixName = "/docker/"
|
||||
|
||||
// Proc controller group path.
|
||||
cgroupFileTemplate = "/proc/%d/cgroup"
|
||||
)
|
||||
|
||||
// CGEntries - represents all the entries in a process cgroup file
|
||||
// at /proc/<pid>/cgroup as key value pairs.
|
||||
type CGEntries map[string]string
|
||||
|
||||
// GetEntries reads and parses all the cgroup entries for a given process.
|
||||
func GetEntries(pid int) (CGEntries, error) {
|
||||
r, err := os.Open(fmt.Sprintf(cgroupFileTemplate, pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
return parseProcCGroup(r)
|
||||
}
|
||||
|
||||
// parseProcCGroup - cgroups are always in the following
|
||||
// format once enabled you need to know the pid of the
|
||||
// application you are looking for so that the the
|
||||
// following parsing logic only parses the file located
|
||||
// at /proc/<pid>/cgroup.
|
||||
//
|
||||
// CGROUP entries id, component and path are always in
|
||||
// the following format. ``ID:COMPONENT:PATH``
|
||||
//
|
||||
// Following code block parses this information and
|
||||
// returns a procCGroup which is a parsed list of all
|
||||
// the line by line entires from /proc/<pid>/cgroup.
|
||||
func parseProcCGroup(r io.Reader) (CGEntries, error) {
|
||||
var cgEntries = CGEntries{}
|
||||
|
||||
// Start reading cgroup categories line by line
|
||||
// and process them into procCGroup structure.
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
tokens := strings.SplitN(line, ":", 3)
|
||||
if len(tokens) < 3 {
|
||||
continue
|
||||
}
|
||||
|
||||
name, path := tokens[1], tokens[2]
|
||||
for _, token := range strings.Split(name, ",") {
|
||||
name = strings.TrimPrefix(token, "name=")
|
||||
cgEntries[name] = path
|
||||
}
|
||||
}
|
||||
|
||||
// Return upon any error while reading the cgroup categories.
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cgEntries, nil
|
||||
}
|
||||
|
||||
// Fetch value of the cgroup kernel param from the cgroup manager,
|
||||
// if cgroup manager is configured we should just rely on `cgm` cli
|
||||
// to fetch all the values for us.
|
||||
func getManagerKernValue(cname, path, kernParam string) (limit uint64, err error) {
|
||||
|
||||
cmd := exec.Command("cgm", "getvalue", cname, path, kernParam)
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
if err = cmd.Run(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Parse the cgm output.
|
||||
limit, err = strconv.ParseUint(strings.TrimSpace(out.String()), 10, 64)
|
||||
return limit, err
|
||||
}
|
||||
|
||||
// Get cgroup memory limit file path.
|
||||
func getMemoryLimitFilePath(cgPath string) string {
|
||||
path := cgroupMemSysPath
|
||||
|
||||
// Docker generates weird cgroup paths that don't
|
||||
// really exist on the file system.
|
||||
//
|
||||
// For example on regular Linux OS :
|
||||
// `/user.slice/user-1000.slice/session-1.scope`
|
||||
//
|
||||
// But they exist as a bind mount on Docker and
|
||||
// are not accessible : `/docker/<hash>`
|
||||
//
|
||||
// We we will just ignore if there is `/docker` in the
|
||||
// path ignore and fall back to :
|
||||
// `/sys/fs/cgroup/memory/memory.limit_in_bytes`
|
||||
if !strings.HasPrefix(cgPath, dockerPrefixName) {
|
||||
path = filepath.Join(path, cgPath)
|
||||
}
|
||||
|
||||
// Final path.
|
||||
return filepath.Join(path, memoryLimitKernelParam)
|
||||
}
|
||||
|
||||
// GetMemoryLimit - Fetches cgroup memory limit either from
|
||||
// a file path at '/sys/fs/cgroup/memory', if path fails then
|
||||
// fallback to querying cgroup manager.
|
||||
func GetMemoryLimit(pid int) (limit uint64, err error) {
|
||||
var cg CGEntries
|
||||
cg, err = GetEntries(pid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
path := cg["memory"]
|
||||
|
||||
limit, err = getManagerKernValue("memory", path, memoryLimitKernelParam)
|
||||
if err != nil {
|
||||
|
||||
// Upon any failure returned from `cgm`, on some systems cgm
|
||||
// might not be installed. We fallback to using the the sysfs
|
||||
// path instead to lookup memory limits.
|
||||
var b []byte
|
||||
b, err = ioutil.ReadFile(getMemoryLimitFilePath(path))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
limit, err = strconv.ParseUint(strings.TrimSpace(string(b)), 10, 64)
|
||||
}
|
||||
|
||||
return limit, err
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
// +build linux
|
||||
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cgroup
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Testing parsing correctness for various process cgroup files.
|
||||
func TestProcCGroup(t *testing.T) {
|
||||
tmpPath, err := ioutil.TempFile("", "cgroup")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(tmpPath.Name())
|
||||
|
||||
cgroup := `
|
||||
11:memory:/user.slice
|
||||
10:blkio:/user.slice
|
||||
9:hugetlb:/
|
||||
8:net_cls,net_prio:/
|
||||
7:perf_event:/
|
||||
6:pids:/user.slice/user-1000.slice
|
||||
5:devices:/user.slice
|
||||
4:cpuset:/
|
||||
3:cpu,cpuacct:/user.slice
|
||||
2:freezer:/
|
||||
1:name=systemd:/user.slice/user-1000.slice/session-1.scope
|
||||
`
|
||||
_, err = tmpPath.WriteString(cgroup)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Seek back to read from the beginning.
|
||||
tmpPath.Seek(0, 0)
|
||||
|
||||
cg, err := parseProcCGroup(tmpPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
path := cg["memory"]
|
||||
if len(path) == 0 {
|
||||
t.Fatal("Path component cannot be empty")
|
||||
}
|
||||
|
||||
if path != "/user.slice" {
|
||||
t.Fatal("Path component cannot be empty")
|
||||
}
|
||||
|
||||
path = cg["systemd"]
|
||||
if path != "/user.slice/user-1000.slice/session-1.scope" {
|
||||
t.Fatal("Path component cannot be empty")
|
||||
}
|
||||
|
||||
// Mixed cgroups with different group names.
|
||||
cgroup = `
|
||||
11:memory:/newtest/newtest
|
||||
10:blkio:/user.slice
|
||||
9:hugetlb:/
|
||||
8:net_cls,net_prio:/
|
||||
7:perf_event:/
|
||||
6:pids:/user.slice/user-1000.slice
|
||||
5:devices:/user.slice
|
||||
4:cpuset:/
|
||||
3:cpu,cpuacct:/newtest/newtest
|
||||
2:freezer:/
|
||||
1:name=systemd:/user.slice/user-1000.slice/session-1.scope
|
||||
`
|
||||
|
||||
// Seek back to read from the beginning.
|
||||
tmpPath.Seek(0, 0)
|
||||
|
||||
_, err = tmpPath.WriteString(cgroup)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Seek back to read from the beginning.
|
||||
tmpPath.Seek(0, 0)
|
||||
|
||||
cg, err = parseProcCGroup(tmpPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
path = cg["memory"]
|
||||
if path != "/newtest/newtest" {
|
||||
t.Fatal("Path component cannot be empty")
|
||||
}
|
||||
|
||||
path = cg["systemd"]
|
||||
if path != "/user.slice/user-1000.slice/session-1.scope" {
|
||||
t.Fatal("Path component cannot be empty")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Tests cgroup memory limit path construction.
|
||||
func TestMemoryLimitPath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
cgroupPath string
|
||||
expectedPath string
|
||||
}{
|
||||
{
|
||||
cgroupPath: "/user.slice",
|
||||
expectedPath: "/sys/fs/cgroup/memory/user.slice/memory.limit_in_bytes",
|
||||
},
|
||||
{
|
||||
cgroupPath: "/docker/testing",
|
||||
expectedPath: "/sys/fs/cgroup/memory/memory.limit_in_bytes",
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
actualPath := getMemoryLimitFilePath(testCase.cgroupPath)
|
||||
if actualPath != testCase.expectedPath {
|
||||
t.Fatalf("Test: %d: Expected: %s, got %s", i+1, testCase.expectedPath, actualPath)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
// +build !linux
|
||||
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cgroup
|
@ -1,436 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Package console implements console printing helpers
|
||||
package console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/mattn/go-colorable"
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
var (
|
||||
// Used by the caller to print multiple lines atomically. Exposed by Lock/Unlock methods.
|
||||
publicMutex sync.Mutex
|
||||
|
||||
// Used internally by console.
|
||||
privateMutex sync.Mutex
|
||||
|
||||
stderrColoredOutput = colorable.NewColorableStderr()
|
||||
|
||||
// Print prints a message.
|
||||
Print = func(data ...interface{}) {
|
||||
consolePrint("Print", Theme["Print"], data...)
|
||||
}
|
||||
|
||||
// PrintC prints a message with color.
|
||||
PrintC = func(data ...interface{}) {
|
||||
consolePrint("PrintC", Theme["PrintC"], data...)
|
||||
}
|
||||
|
||||
// Printf prints a formatted message.
|
||||
Printf = func(format string, data ...interface{}) {
|
||||
consolePrintf("Print", Theme["Print"], format, data...)
|
||||
}
|
||||
|
||||
// Println prints a message with a newline.
|
||||
Println = func(data ...interface{}) {
|
||||
consolePrintln("Print", Theme["Print"], data...)
|
||||
}
|
||||
|
||||
// Fatal print a error message and exit.
|
||||
Fatal = func(data ...interface{}) {
|
||||
consolePrint("Fatal", Theme["Fatal"], data...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalf print a error message with a format specified and exit.
|
||||
Fatalf = func(format string, data ...interface{}) {
|
||||
consolePrintf("Fatal", Theme["Fatal"], format, data...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalln print a error message with a new line and exit.
|
||||
Fatalln = func(data ...interface{}) {
|
||||
consolePrintln("Fatal", Theme["Fatal"], data...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Error prints a error message.
|
||||
Error = func(data ...interface{}) {
|
||||
consolePrint("Error", Theme["Error"], data...)
|
||||
}
|
||||
|
||||
// Errorf print a error message with a format specified.
|
||||
Errorf = func(format string, data ...interface{}) {
|
||||
consolePrintf("Error", Theme["Error"], format, data...)
|
||||
}
|
||||
|
||||
// Errorln prints a error message with a new line.
|
||||
Errorln = func(data ...interface{}) {
|
||||
consolePrintln("Error", Theme["Error"], data...)
|
||||
}
|
||||
|
||||
// Info prints a informational message.
|
||||
Info = func(data ...interface{}) {
|
||||
consolePrint("Info", Theme["Info"], data...)
|
||||
}
|
||||
|
||||
// Infof prints a informational message in custom format.
|
||||
Infof = func(format string, data ...interface{}) {
|
||||
consolePrintf("Info", Theme["Info"], format, data...)
|
||||
}
|
||||
|
||||
// Infoln prints a informational message with a new line.
|
||||
Infoln = func(data ...interface{}) {
|
||||
consolePrintln("Info", Theme["Info"], data...)
|
||||
}
|
||||
|
||||
// Debug prints a debug message without a new line
|
||||
// Debug prints a debug message.
|
||||
Debug = func(data ...interface{}) {
|
||||
consolePrint("Debug", Theme["Debug"], data...)
|
||||
}
|
||||
|
||||
// Debugf prints a debug message with a new line.
|
||||
Debugf = func(format string, data ...interface{}) {
|
||||
consolePrintf("Debug", Theme["Debug"], format, data...)
|
||||
}
|
||||
|
||||
// Debugln prints a debug message with a new line.
|
||||
Debugln = func(data ...interface{}) {
|
||||
consolePrintln("Debug", Theme["Debug"], data...)
|
||||
}
|
||||
|
||||
// Colorize prints message in a colorized form, dictated by the corresponding tag argument.
|
||||
Colorize = func(tag string, data interface{}) string {
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
colorized, ok := Theme[tag]
|
||||
if ok {
|
||||
return colorized.SprintFunc()(data)
|
||||
} // else: No theme found. Return as string.
|
||||
}
|
||||
return fmt.Sprint(data)
|
||||
}
|
||||
|
||||
// Eraseline Print in new line and adjust to top so that we don't print over the ongoing progress bar.
|
||||
Eraseline = func() {
|
||||
consolePrintf("Print", Theme["Print"], "%c[2K\n", 27)
|
||||
consolePrintf("Print", Theme["Print"], "%c[A", 27)
|
||||
}
|
||||
)
|
||||
|
||||
// wrap around standard fmt functions.
|
||||
// consolePrint prints a message prefixed with message type and program name.
|
||||
func consolePrint(tag string, c *color.Color, a ...interface{}) {
|
||||
privateMutex.Lock()
|
||||
defer privateMutex.Unlock()
|
||||
|
||||
switch tag {
|
||||
case "Debug":
|
||||
// if no arguments are given do not invoke debug printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
output := color.Output
|
||||
color.Output = stderrColoredOutput
|
||||
if isatty.IsTerminal(os.Stderr.Fd()) {
|
||||
c.Print(ProgramName() + ": <DEBUG> ")
|
||||
c.Print(a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
|
||||
fmt.Fprint(color.Output, a...)
|
||||
}
|
||||
color.Output = output
|
||||
case "Fatal":
|
||||
fallthrough
|
||||
case "Error":
|
||||
// if no arguments are given do not invoke fatal and error printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
output := color.Output
|
||||
color.Output = stderrColoredOutput
|
||||
if isatty.IsTerminal(os.Stderr.Fd()) {
|
||||
c.Print(ProgramName() + ": <ERROR> ")
|
||||
c.Print(a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
|
||||
fmt.Fprint(color.Output, a...)
|
||||
}
|
||||
color.Output = output
|
||||
case "Info":
|
||||
// if no arguments are given do not invoke info printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
c.Print(ProgramName() + ": ")
|
||||
c.Print(a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": ")
|
||||
fmt.Fprint(color.Output, a...)
|
||||
}
|
||||
default:
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
c.Print(a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, a...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// consolePrintf - same as print with a new line.
|
||||
func consolePrintf(tag string, c *color.Color, format string, a ...interface{}) {
|
||||
privateMutex.Lock()
|
||||
defer privateMutex.Unlock()
|
||||
|
||||
switch tag {
|
||||
case "Debug":
|
||||
// if no arguments are given do not invoke debug printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
output := color.Output
|
||||
color.Output = stderrColoredOutput
|
||||
if isatty.IsTerminal(os.Stderr.Fd()) {
|
||||
c.Print(ProgramName() + ": <DEBUG> ")
|
||||
c.Printf(format, a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
|
||||
fmt.Fprintf(color.Output, format, a...)
|
||||
}
|
||||
color.Output = output
|
||||
case "Fatal":
|
||||
fallthrough
|
||||
case "Error":
|
||||
// if no arguments are given do not invoke fatal and error printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
output := color.Output
|
||||
color.Output = stderrColoredOutput
|
||||
if isatty.IsTerminal(os.Stderr.Fd()) {
|
||||
c.Print(ProgramName() + ": <ERROR> ")
|
||||
c.Printf(format, a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
|
||||
fmt.Fprintf(color.Output, format, a...)
|
||||
}
|
||||
color.Output = output
|
||||
case "Info":
|
||||
// if no arguments are given do not invoke info printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
c.Print(ProgramName() + ": ")
|
||||
c.Printf(format, a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": ")
|
||||
fmt.Fprintf(color.Output, format, a...)
|
||||
}
|
||||
default:
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
c.Printf(format, a...)
|
||||
} else {
|
||||
fmt.Fprintf(color.Output, format, a...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// consolePrintln - same as print with a new line.
|
||||
func consolePrintln(tag string, c *color.Color, a ...interface{}) {
|
||||
privateMutex.Lock()
|
||||
defer privateMutex.Unlock()
|
||||
|
||||
switch tag {
|
||||
case "Debug":
|
||||
// if no arguments are given do not invoke debug printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
output := color.Output
|
||||
color.Output = stderrColoredOutput
|
||||
if isatty.IsTerminal(os.Stderr.Fd()) {
|
||||
c.Print(ProgramName() + ": <DEBUG> ")
|
||||
c.Println(a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
|
||||
fmt.Fprintln(color.Output, a...)
|
||||
}
|
||||
color.Output = output
|
||||
case "Fatal":
|
||||
fallthrough
|
||||
case "Error":
|
||||
// if no arguments are given do not invoke fatal and error printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
output := color.Output
|
||||
color.Output = stderrColoredOutput
|
||||
if isatty.IsTerminal(os.Stderr.Fd()) {
|
||||
c.Print(ProgramName() + ": <ERROR> ")
|
||||
c.Println(a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
|
||||
fmt.Fprintln(color.Output, a...)
|
||||
}
|
||||
color.Output = output
|
||||
case "Info":
|
||||
// if no arguments are given do not invoke info printer.
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
c.Print(ProgramName() + ": ")
|
||||
c.Println(a...)
|
||||
} else {
|
||||
fmt.Fprint(color.Output, ProgramName()+": ")
|
||||
fmt.Fprintln(color.Output, a...)
|
||||
}
|
||||
default:
|
||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||
c.Println(a...)
|
||||
} else {
|
||||
fmt.Fprintln(color.Output, a...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lock console.
|
||||
func Lock() {
|
||||
publicMutex.Lock()
|
||||
}
|
||||
|
||||
// Unlock locked console.
|
||||
func Unlock() {
|
||||
publicMutex.Unlock()
|
||||
}
|
||||
|
||||
// ProgramName - return the name of the executable program.
|
||||
func ProgramName() string {
|
||||
_, progName := filepath.Split(os.Args[0])
|
||||
return progName
|
||||
}
|
||||
|
||||
// Table - data to print in table format with fixed row widths.
|
||||
type Table struct {
|
||||
// per-row colors
|
||||
RowColors []*color.Color
|
||||
|
||||
// per-column align-right flag (aligns left by default)
|
||||
AlignRight []bool
|
||||
|
||||
// Left margin width for table
|
||||
TableIndentWidth int
|
||||
|
||||
// Flag to print separator under heading. Row 0 is considered heading
|
||||
HeaderRowSeparator bool
|
||||
}
|
||||
|
||||
// NewTable - create a new Table instance. Takes per-row colors and
|
||||
// per-column right-align flags and table indentation width (i.e. left
|
||||
// margin width)
|
||||
func NewTable(rowColors []*color.Color, alignRight []bool, indentWidth int) *Table {
|
||||
return &Table{rowColors, alignRight, indentWidth, false}
|
||||
}
|
||||
|
||||
// DisplayTable - prints the table
|
||||
func (t *Table) DisplayTable(rows [][]string) error {
|
||||
numRows := len(rows)
|
||||
numCols := len(rows[0])
|
||||
if numRows != len(t.RowColors) {
|
||||
return fmt.Errorf("row count and row-colors mismatch")
|
||||
}
|
||||
|
||||
// Compute max. column widths
|
||||
maxColWidths := make([]int, numCols)
|
||||
for _, row := range rows {
|
||||
if len(row) != len(t.AlignRight) {
|
||||
return fmt.Errorf("col count and align-right mismatch")
|
||||
}
|
||||
for i, v := range row {
|
||||
if len([]rune(v)) > maxColWidths[i] {
|
||||
maxColWidths[i] = len([]rune(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute per-cell text with padding and alignment applied.
|
||||
paddedText := make([][]string, numRows)
|
||||
for r, row := range rows {
|
||||
paddedText[r] = make([]string, numCols)
|
||||
for c, cell := range row {
|
||||
if t.AlignRight[c] {
|
||||
fmtStr := fmt.Sprintf("%%%ds", maxColWidths[c])
|
||||
paddedText[r][c] = fmt.Sprintf(fmtStr, cell)
|
||||
} else {
|
||||
extraWidth := maxColWidths[c] - len([]rune(cell))
|
||||
fmtStr := fmt.Sprintf("%%s%%%ds", extraWidth)
|
||||
paddedText[r][c] = fmt.Sprintf(fmtStr, cell, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw table top border
|
||||
segments := make([]string, numCols)
|
||||
for i, c := range maxColWidths {
|
||||
segments[i] = strings.Repeat("─", c+2)
|
||||
}
|
||||
indentText := strings.Repeat(" ", t.TableIndentWidth)
|
||||
border := fmt.Sprintf("%s┌%s┐", indentText, strings.Join(segments, "┬"))
|
||||
fmt.Println(border)
|
||||
|
||||
// Print the table with colors
|
||||
for r, row := range paddedText {
|
||||
if t.HeaderRowSeparator && r == 1 {
|
||||
// Draw table header-row border
|
||||
border = fmt.Sprintf("%s├%s┤", indentText, strings.Join(segments, "┼"))
|
||||
fmt.Println(border)
|
||||
}
|
||||
fmt.Print(indentText + "│ ")
|
||||
for c, text := range row {
|
||||
t.RowColors[r].Print(text)
|
||||
if c != numCols-1 {
|
||||
fmt.Print(" │ ")
|
||||
}
|
||||
}
|
||||
fmt.Println(" │")
|
||||
}
|
||||
|
||||
// Draw table bottom border
|
||||
border = fmt.Sprintf("%s└%s┘", indentText, strings.Join(segments, "┴"))
|
||||
fmt.Println(border)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RewindLines - uses terminal escape symbols to clear and rewind
|
||||
// upwards on the console for `n` lines.
|
||||
func RewindLines(n int) {
|
||||
for i := 0; i < n; i++ {
|
||||
fmt.Printf("\033[1A\033[K")
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
func TestSetColor(t *testing.T) {
|
||||
SetColor("unknown", color.New(color.FgWhite))
|
||||
_, ok := Theme["unknown"]
|
||||
if !ok {
|
||||
t.Fatal("missing theme")
|
||||
}
|
||||
}
|
||||
|
||||
func TestColorLock(t *testing.T) {
|
||||
Lock()
|
||||
Print("") // Test for deadlocks.
|
||||
Unlock()
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package console
|
||||
|
||||
import "github.com/fatih/color"
|
||||
|
||||
var (
|
||||
// Theme contains default color mapping.
|
||||
Theme = map[string]*color.Color{
|
||||
"Debug": color.New(color.FgWhite, color.Faint, color.Italic),
|
||||
"Fatal": color.New(color.FgRed, color.Italic, color.Bold),
|
||||
"Error": color.New(color.FgYellow, color.Italic),
|
||||
"Info": color.New(color.FgGreen, color.Bold),
|
||||
"Print": color.New(),
|
||||
"PrintB": color.New(color.FgBlue, color.Bold),
|
||||
"PrintC": color.New(color.FgGreen, color.Bold),
|
||||
}
|
||||
)
|
||||
|
||||
// SetColorOff disables coloring for the entire session.
|
||||
func SetColorOff() {
|
||||
privateMutex.Lock()
|
||||
defer privateMutex.Unlock()
|
||||
color.NoColor = true
|
||||
}
|
||||
|
||||
// SetColorOn enables coloring for the entire session.
|
||||
func SetColorOn() {
|
||||
privateMutex.Lock()
|
||||
defer privateMutex.Unlock()
|
||||
color.NoColor = false
|
||||
}
|
||||
|
||||
// SetColor sets a color for a particular tag.
|
||||
func SetColor(tag string, cl *color.Color) {
|
||||
privateMutex.Lock()
|
||||
defer privateMutex.Unlock()
|
||||
// add new theme
|
||||
Theme[tag] = cl
|
||||
}
|
@ -25,7 +25,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/pkg/console"
|
||||
)
|
||||
|
||||
// Indicator if logging is enabled.
|
||||
|
@ -1,227 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package ellipses
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// Regex to extract ellipses syntax inputs.
|
||||
regexpEllipses = regexp.MustCompile(`(.*)({[0-9a-z]*\.\.\.[0-9a-z]*})(.*)`)
|
||||
|
||||
// Ellipses constants
|
||||
openBraces = "{"
|
||||
closeBraces = "}"
|
||||
ellipses = "..."
|
||||
)
|
||||
|
||||
// Parses an ellipses range pattern of following style
|
||||
// `{1...64}`
|
||||
// `{33...64}`
|
||||
func parseEllipsesRange(pattern string) (seq []string, err error) {
|
||||
if !strings.Contains(pattern, openBraces) {
|
||||
return nil, errors.New("Invalid argument")
|
||||
}
|
||||
if !strings.Contains(pattern, closeBraces) {
|
||||
return nil, errors.New("Invalid argument")
|
||||
}
|
||||
|
||||
pattern = strings.TrimPrefix(pattern, openBraces)
|
||||
pattern = strings.TrimSuffix(pattern, closeBraces)
|
||||
|
||||
ellipsesRange := strings.Split(pattern, ellipses)
|
||||
if len(ellipsesRange) != 2 {
|
||||
return nil, errors.New("Invalid argument")
|
||||
}
|
||||
|
||||
var hexadecimal bool
|
||||
var start, end uint64
|
||||
if start, err = strconv.ParseUint(ellipsesRange[0], 10, 64); err != nil {
|
||||
// Look for hexadecimal conversions if any.
|
||||
start, err = strconv.ParseUint(ellipsesRange[0], 16, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hexadecimal = true
|
||||
}
|
||||
|
||||
if end, err = strconv.ParseUint(ellipsesRange[1], 10, 64); err != nil {
|
||||
// Look for hexadecimal conversions if any.
|
||||
end, err = strconv.ParseUint(ellipsesRange[1], 16, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hexadecimal = true
|
||||
}
|
||||
|
||||
if start > end {
|
||||
return nil, fmt.Errorf("Incorrect range start %d cannot be bigger than end %d", start, end)
|
||||
}
|
||||
|
||||
for i := start; i <= end; i++ {
|
||||
if strings.HasPrefix(ellipsesRange[0], "0") && len(ellipsesRange[0]) > 1 || strings.HasPrefix(ellipsesRange[1], "0") {
|
||||
if hexadecimal {
|
||||
seq = append(seq, fmt.Sprintf(fmt.Sprintf("%%0%dx", len(ellipsesRange[1])), i))
|
||||
} else {
|
||||
seq = append(seq, fmt.Sprintf(fmt.Sprintf("%%0%dd", len(ellipsesRange[1])), i))
|
||||
}
|
||||
} else {
|
||||
if hexadecimal {
|
||||
seq = append(seq, fmt.Sprintf("%x", i))
|
||||
} else {
|
||||
seq = append(seq, fmt.Sprintf("%d", i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return seq, nil
|
||||
}
|
||||
|
||||
// Pattern - ellipses pattern, describes the range and also the
|
||||
// associated prefix and suffixes.
|
||||
type Pattern struct {
|
||||
Prefix string
|
||||
Suffix string
|
||||
Seq []string
|
||||
}
|
||||
|
||||
// argExpander - recursively expands labels into its respective forms.
|
||||
func argExpander(labels [][]string) (out [][]string) {
|
||||
if len(labels) == 1 {
|
||||
for _, v := range labels[0] {
|
||||
out = append(out, []string{v})
|
||||
}
|
||||
return out
|
||||
}
|
||||
for _, lbl := range labels[0] {
|
||||
rs := argExpander(labels[1:])
|
||||
for _, rlbls := range rs {
|
||||
r := append(rlbls, []string{lbl}...)
|
||||
out = append(out, r)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ArgPattern contains a list of patterns provided in the input.
|
||||
type ArgPattern []Pattern
|
||||
|
||||
// Expand - expands all the ellipses patterns in
|
||||
// the given argument.
|
||||
func (a ArgPattern) Expand() [][]string {
|
||||
labels := make([][]string, len(a))
|
||||
for i := range labels {
|
||||
labels[i] = a[i].Expand()
|
||||
}
|
||||
return argExpander(labels)
|
||||
}
|
||||
|
||||
// Expand - expands a ellipses pattern.
|
||||
func (p Pattern) Expand() []string {
|
||||
var labels []string
|
||||
for i := range p.Seq {
|
||||
switch {
|
||||
case p.Prefix != "" && p.Suffix == "":
|
||||
labels = append(labels, fmt.Sprintf("%s%s", p.Prefix, p.Seq[i]))
|
||||
case p.Suffix != "" && p.Prefix == "":
|
||||
labels = append(labels, fmt.Sprintf("%s%s", p.Seq[i], p.Suffix))
|
||||
case p.Suffix == "" && p.Prefix == "":
|
||||
labels = append(labels, p.Seq[i])
|
||||
default:
|
||||
labels = append(labels, fmt.Sprintf("%s%s%s", p.Prefix, p.Seq[i], p.Suffix))
|
||||
}
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
||||
// HasEllipses - returns true if input arg has ellipses type pattern.
|
||||
func HasEllipses(args ...string) bool {
|
||||
var ok = true
|
||||
for _, arg := range args {
|
||||
ok = ok && (strings.Count(arg, ellipses) > 0 || (strings.Count(arg, openBraces) > 0 && strings.Count(arg, closeBraces) > 0))
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrInvalidEllipsesFormatFn error returned when invalid ellipses format is detected.
|
||||
var ErrInvalidEllipsesFormatFn = func(arg string) error {
|
||||
return fmt.Errorf("Invalid ellipsis format in (%s), Ellipsis range must be provided in format {N...M} where N and M are positive integers, M must be greater than N, with an allowed minimum range of 4", arg)
|
||||
}
|
||||
|
||||
// FindEllipsesPatterns - finds all ellipses patterns, recursively and parses the ranges numerically.
|
||||
func FindEllipsesPatterns(arg string) (ArgPattern, error) {
|
||||
var patterns []Pattern
|
||||
parts := regexpEllipses.FindStringSubmatch(arg)
|
||||
if len(parts) == 0 {
|
||||
// We throw an error if arg doesn't have any recognizable ellipses pattern.
|
||||
return nil, ErrInvalidEllipsesFormatFn(arg)
|
||||
}
|
||||
|
||||
parts = parts[1:]
|
||||
patternFound := regexpEllipses.MatchString(parts[0])
|
||||
for patternFound {
|
||||
seq, err := parseEllipsesRange(parts[1])
|
||||
if err != nil {
|
||||
return patterns, err
|
||||
}
|
||||
patterns = append(patterns, Pattern{
|
||||
Prefix: "",
|
||||
Suffix: parts[2],
|
||||
Seq: seq,
|
||||
})
|
||||
parts = regexpEllipses.FindStringSubmatch(parts[0])
|
||||
if len(parts) > 0 {
|
||||
parts = parts[1:]
|
||||
patternFound = HasEllipses(parts[0])
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if len(parts) > 0 {
|
||||
seq, err := parseEllipsesRange(parts[1])
|
||||
if err != nil {
|
||||
return patterns, err
|
||||
}
|
||||
|
||||
patterns = append(patterns, Pattern{
|
||||
Prefix: parts[0],
|
||||
Suffix: parts[2],
|
||||
Seq: seq,
|
||||
})
|
||||
}
|
||||
|
||||
// Check if any of the prefix or suffixes now have flower braces
|
||||
// left over, in such a case we generally think that there is
|
||||
// perhaps a typo in users input and error out accordingly.
|
||||
for _, pattern := range patterns {
|
||||
if strings.Count(pattern.Prefix, openBraces) > 0 || strings.Count(pattern.Prefix, closeBraces) > 0 {
|
||||
return nil, ErrInvalidEllipsesFormatFn(arg)
|
||||
}
|
||||
if strings.Count(pattern.Suffix, openBraces) > 0 || strings.Count(pattern.Suffix, closeBraces) > 0 {
|
||||
return nil, ErrInvalidEllipsesFormatFn(arg)
|
||||
}
|
||||
}
|
||||
|
||||
return patterns, nil
|
||||
}
|
@ -1,256 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package ellipses
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test tests args with ellipses.
|
||||
func TestHasEllipses(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
expectedOk bool
|
||||
}{
|
||||
// Tests for all args without ellipses.
|
||||
{
|
||||
[]string{"64"},
|
||||
false,
|
||||
},
|
||||
// Found flower braces, still attempt to parse and throw an error.
|
||||
{
|
||||
[]string{"{1..64}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"{1..2..}"},
|
||||
true,
|
||||
},
|
||||
// Test for valid input.
|
||||
{
|
||||
[]string{"1...64"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"{1...2O}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"..."},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"{-1...1}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"{0...-1}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"{1....4}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"{1...64}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"{...}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"{1...64}", "{65...128}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"http://minio{2...3}/export/set{1...64}"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{
|
||||
"http://minio{2...3}/export/set{1...64}",
|
||||
"http://minio{2...3}/export/set{65...128}",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{
|
||||
"mydisk-{a...z}{1...20}",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
|
||||
[]string{
|
||||
"mydisk-{1...4}{1..2.}",
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
|
||||
gotOk := HasEllipses(testCase.args...)
|
||||
if gotOk != testCase.expectedOk {
|
||||
t.Errorf("Expected %t, got %t", testCase.expectedOk, gotOk)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test tests find ellipses patterns.
|
||||
func TestFindEllipsesPatterns(t *testing.T) {
|
||||
testCases := []struct {
|
||||
pattern string
|
||||
success bool
|
||||
expectedCount int
|
||||
}{
|
||||
// Tests for all invalid inputs
|
||||
{
|
||||
"{1..64}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"1...64",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"...",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{1...",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"...64}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{...}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{-1...1}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{0...-1}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{1...2O}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{64...1}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{1....4}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"mydisk-{a...z}{1...20}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"mydisk-{1...4}{1..2.}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{1..2.}-mydisk-{1...4}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{{1...4}}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{4...02}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"{f...z}",
|
||||
false,
|
||||
0,
|
||||
},
|
||||
// Test for valid input.
|
||||
{
|
||||
"{1...64}",
|
||||
true,
|
||||
64,
|
||||
},
|
||||
{
|
||||
"{1...64} {65...128}",
|
||||
true,
|
||||
4096,
|
||||
},
|
||||
{
|
||||
"{01...036}",
|
||||
true,
|
||||
36,
|
||||
},
|
||||
{
|
||||
"{001...036}",
|
||||
true,
|
||||
36,
|
||||
},
|
||||
{
|
||||
"{1...a}",
|
||||
true,
|
||||
10,
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
|
||||
argP, err := FindEllipsesPatterns(testCase.pattern)
|
||||
if err != nil && testCase.success {
|
||||
t.Errorf("Expected success but failed instead %s", err)
|
||||
}
|
||||
if err == nil && !testCase.success {
|
||||
t.Errorf("Expected failure but passed instead")
|
||||
}
|
||||
if err == nil {
|
||||
gotCount := len(argP.Expand())
|
||||
if gotCount != testCase.expectedCount {
|
||||
t.Errorf("Expected %d, got %d", testCase.expectedCount, gotCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
100
pkg/env/env.go
vendored
100
pkg/env/env.go
vendored
@ -1,100 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package env
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
privateMutex sync.RWMutex
|
||||
lockEnvMutex sync.Mutex
|
||||
envOff bool
|
||||
)
|
||||
|
||||
// LockSetEnv locks modifications to environment.
|
||||
// Call returned function to unlock.
|
||||
func LockSetEnv() func() {
|
||||
lockEnvMutex.Lock()
|
||||
return lockEnvMutex.Unlock
|
||||
}
|
||||
|
||||
// SetEnvOff - turns off env lookup
|
||||
// A global lock above this MUST ensure that
|
||||
func SetEnvOff() {
|
||||
privateMutex.Lock()
|
||||
defer privateMutex.Unlock()
|
||||
|
||||
envOff = true
|
||||
}
|
||||
|
||||
// SetEnvOn - turns on env lookup
|
||||
func SetEnvOn() {
|
||||
privateMutex.Lock()
|
||||
defer privateMutex.Unlock()
|
||||
|
||||
envOff = false
|
||||
}
|
||||
|
||||
// IsSet returns if the given env key is set.
|
||||
func IsSet(key string) bool {
|
||||
_, _, _, ok := LookupEnv(key)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Get retrieves the value of the environment variable named
|
||||
// by the key. If the variable is present in the environment the
|
||||
// value (which may be empty) is returned. Otherwise it returns
|
||||
// the specified default value.
|
||||
func Get(key, defaultValue string) string {
|
||||
privateMutex.RLock()
|
||||
ok := envOff
|
||||
privateMutex.RUnlock()
|
||||
if ok {
|
||||
return defaultValue
|
||||
}
|
||||
if v, _, _, ok := LookupEnv(key); ok {
|
||||
return v
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// GetInt returns an integer if found in the environment
|
||||
// and returns the default value otherwise.
|
||||
func GetInt(key string, defaultValue int) (int, error) {
|
||||
v := Get(key, "")
|
||||
if v == "" {
|
||||
return defaultValue, nil
|
||||
}
|
||||
return strconv.Atoi(v)
|
||||
}
|
||||
|
||||
// List all envs with a given prefix.
|
||||
func List(prefix string) (envs []string) {
|
||||
for _, env := range Environ() {
|
||||
if strings.HasPrefix(env, prefix) {
|
||||
values := strings.SplitN(env, "=", 2)
|
||||
if len(values) == 2 {
|
||||
envs = append(envs, values[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
return envs
|
||||
}
|
187
pkg/env/web_env.go
vendored
187
pkg/env/web_env.go
vendored
@ -1,187 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package env
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
const (
|
||||
webEnvScheme = "env"
|
||||
webEnvSchemeSecure = "env+tls"
|
||||
)
|
||||
|
||||
var (
|
||||
globalRootCAs *x509.CertPool
|
||||
)
|
||||
|
||||
// RegisterGlobalCAs register the global root CAs
|
||||
func RegisterGlobalCAs(CAs *x509.CertPool) {
|
||||
globalRootCAs = CAs
|
||||
}
|
||||
|
||||
var (
|
||||
hostKeys = regexp.MustCompile("^(https?://)(.*?):(.*?)@(.*?)$")
|
||||
)
|
||||
|
||||
func fetchHTTPConstituentParts(u *url.URL) (username string, password string, envURL string, err error) {
|
||||
envURL = u.String()
|
||||
if hostKeys.MatchString(envURL) {
|
||||
parts := hostKeys.FindStringSubmatch(envURL)
|
||||
if len(parts) != 5 {
|
||||
return "", "", "", errors.New("invalid arguments")
|
||||
}
|
||||
username = parts[2]
|
||||
password = parts[3]
|
||||
envURL = fmt.Sprintf("%s%s", parts[1], parts[4])
|
||||
}
|
||||
|
||||
if username == "" && password == "" && u.User != nil {
|
||||
username = u.User.Username()
|
||||
password, _ = u.User.Password()
|
||||
}
|
||||
return username, password, envURL, nil
|
||||
}
|
||||
|
||||
func getEnvValueFromHTTP(urlStr, envKey string) (string, string, string, error) {
|
||||
u, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case webEnvScheme:
|
||||
u.Scheme = "http"
|
||||
case webEnvSchemeSecure:
|
||||
u.Scheme = "https"
|
||||
default:
|
||||
return "", "", "", errors.New("invalid arguments")
|
||||
}
|
||||
|
||||
username, password, envURL, err := fetchHTTPConstituentParts(u)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, envURL+"?key="+envKey, nil)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
claims := &jwt.StandardClaims{
|
||||
ExpiresAt: int64(15 * time.Minute),
|
||||
Issuer: username,
|
||||
Subject: envKey,
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
|
||||
ss, err := token.SignedString([]byte(password))
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", "Bearer "+ss)
|
||||
|
||||
clnt := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 3 * time.Second,
|
||||
KeepAlive: 5 * time.Second,
|
||||
}).DialContext,
|
||||
ResponseHeaderTimeout: 3 * time.Second,
|
||||
TLSHandshakeTimeout: 3 * time.Second,
|
||||
ExpectContinueTimeout: 3 * time.Second,
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: globalRootCAs,
|
||||
},
|
||||
// Go net/http automatically unzip if content-type is
|
||||
// gzip disable this feature, as we are always interested
|
||||
// in raw stream.
|
||||
DisableCompression: true,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := clnt.Do(req)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
envValueBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
return string(envValueBytes), username, password, nil
|
||||
}
|
||||
|
||||
// Environ returns a copy of strings representing the
|
||||
// environment, in the form "key=value".
|
||||
func Environ() []string {
|
||||
return os.Environ()
|
||||
}
|
||||
|
||||
// LookupEnv retrieves the value of the environment variable
|
||||
// named by the key. If the variable is present in the
|
||||
// environment the value (which may be empty) is returned
|
||||
// and the boolean is true. Otherwise the returned value
|
||||
// will be empty and the boolean will be false.
|
||||
//
|
||||
// Additionally if the input is env://username:password@remote:port/
|
||||
// to fetch ENV values for the env value from a remote server.
|
||||
// In this case, it also returns the credentials username and password
|
||||
func LookupEnv(key string) (string, string, string, bool) {
|
||||
v, ok := os.LookupEnv(key)
|
||||
if ok && strings.HasPrefix(v, webEnvScheme) {
|
||||
// If env value starts with `env*://`
|
||||
// continue to parse and fetch from remote
|
||||
var err error
|
||||
v, user, pwd, err := getEnvValueFromHTTP(strings.TrimSpace(v), key)
|
||||
if err != nil {
|
||||
env, eok := os.LookupEnv("_" + key)
|
||||
if eok {
|
||||
// fallback to cached value if-any.
|
||||
return env, user, pwd, eok
|
||||
}
|
||||
}
|
||||
// Set the ENV value to _env value,
|
||||
// this value is a fallback in-case of
|
||||
// server restarts when webhook server
|
||||
// is down.
|
||||
os.Setenv("_"+key, v)
|
||||
return v, user, pwd, true
|
||||
}
|
||||
return v, "", "", ok
|
||||
}
|
89
pkg/env/web_env_test.go
vendored
89
pkg/env/web_env_test.go
vendored
@ -1,89 +0,0 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func GetenvHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
if vars["namespace"] != "default" {
|
||||
http.Error(w, "namespace not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if vars["name"] != "minio" {
|
||||
http.Error(w, "tenant not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if vars["key"] != "MINIO_ARGS" {
|
||||
http.Error(w, "key not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
w.Write([]byte("http://127.0.0.{1..4}:9000/data{1...4}"))
|
||||
w.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
func startTestServer(t *testing.T) *httptest.Server {
|
||||
router := mux.NewRouter().SkipClean(true).UseEncodedPath()
|
||||
router.Methods(http.MethodGet).
|
||||
Path("/webhook/v1/getenv/{namespace}/{name}").
|
||||
HandlerFunc(GetenvHandler).Queries("key", "{key:.*}")
|
||||
|
||||
ts := httptest.NewServer(router)
|
||||
t.Cleanup(func() {
|
||||
ts.Close()
|
||||
})
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
func TestWebEnv(t *testing.T) {
|
||||
ts := startTestServer(t)
|
||||
|
||||
u, err := url.Parse(ts.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
v, user, pwd, err := getEnvValueFromHTTP(
|
||||
fmt.Sprintf("env://minio:minio123@%s/webhook/v1/getenv/default/minio",
|
||||
u.Host),
|
||||
"MINIO_ARGS")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if v != "http://127.0.0.{1..4}:9000/data{1...4}" {
|
||||
t.Fatalf("Unexpected value %s", v)
|
||||
}
|
||||
|
||||
if user != "minio" {
|
||||
t.Fatalf("Unexpected value %s", v)
|
||||
}
|
||||
|
||||
if pwd != "minio123" {
|
||||
t.Fatalf("Unexpected value %s", v)
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ package event
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
// NewPattern - create new pattern for prefix/suffix.
|
||||
|
@ -27,7 +27,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/minio/minio/pkg/event"
|
||||
"github.com/minio/minio/pkg/sys"
|
||||
"github.com/minio/pkg/sys"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -32,9 +32,9 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/event"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
"github.com/minio/pkg/certs"
|
||||
)
|
||||
|
||||
// Webhook constants
|
||||
|
@ -19,7 +19,7 @@ package iampolicy
|
||||
|
||||
import (
|
||||
"github.com/minio/minio/pkg/bucket/policy/condition"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
// Action - policy action.
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/pkg/bucket/policy/condition"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
"github.com/minio/pkg/wildcard"
|
||||
)
|
||||
|
||||
// ResourceARNPrefix - resource ARN prefix as per AWS S3 specification.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user