github.com/minio/madmin-go@v1.7.5/tier-config.go (about)

     1  //
     2  // MinIO Object Storage (c) 2021 MinIO, Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //      http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package madmin
    18  
    19  import (
    20  	"encoding/json"
    21  	"errors"
    22  	"log"
    23  )
    24  
    25  //go:generate msgp -file $GOFILE
    26  
    27  // TierConfigVer refers to the current tier config version
    28  const TierConfigVer = "v1"
    29  
    30  // TierType enumerates different remote tier backends.
    31  type TierType int
    32  
    33  const (
    34  	// Unsupported refers to remote tier backend that is not supported in this version
    35  	Unsupported TierType = iota
    36  	// S3 refers to AWS S3 compatible backend
    37  	S3
    38  	// Azure refers to Azure Blob Storage
    39  	Azure
    40  	// GCS refers to Google Cloud Storage
    41  	GCS
    42  	// MinIO refers to MinIO object storage backend
    43  	MinIO
    44  )
    45  
    46  // String returns the name of tt's remote tier backend.
    47  func (tt TierType) String() string {
    48  	switch tt {
    49  	case S3:
    50  		return "s3"
    51  	case Azure:
    52  		return "azure"
    53  	case GCS:
    54  		return "gcs"
    55  	case MinIO:
    56  		return "minio"
    57  	}
    58  	return "unsupported"
    59  }
    60  
    61  // MarshalJSON returns the canonical json representation of tt.
    62  func (tt TierType) MarshalJSON() ([]byte, error) {
    63  	typ := tt.String()
    64  	return json.Marshal(typ)
    65  }
    66  
    67  // UnmarshalJSON parses the provided tier type string, failing unmarshal
    68  // if data contains invalid tier type.
    69  func (tt *TierType) UnmarshalJSON(data []byte) error {
    70  	var s string
    71  	err := json.Unmarshal(data, &s)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	newtt, err := NewTierType(s)
    77  	if err != nil {
    78  		return err
    79  	}
    80  	*tt = newtt
    81  	return nil
    82  }
    83  
    84  // NewTierType creates TierType if scType is a valid tier type string, otherwise
    85  // returns an error.
    86  func NewTierType(scType string) (TierType, error) {
    87  	switch scType {
    88  	case S3.String():
    89  		return S3, nil
    90  	case Azure.String():
    91  		return Azure, nil
    92  	case GCS.String():
    93  		return GCS, nil
    94  	case MinIO.String():
    95  		return MinIO, nil
    96  	}
    97  
    98  	return Unsupported, ErrTierTypeUnsupported
    99  }
   100  
   101  // TierConfig represents the different remote tier backend configurations
   102  // supported. The specific backend is identified by the Type field. It has a
   103  // Version field to allow for backwards-compatible extension in the future.
   104  type TierConfig struct {
   105  	Version string
   106  	Type    TierType   `json:",omitempty"`
   107  	Name    string     `json:",omitempty"`
   108  	S3      *TierS3    `json:",omitempty"`
   109  	Azure   *TierAzure `json:",omitempty"`
   110  	GCS     *TierGCS   `json:",omitempty"`
   111  	MinIO   *TierMinIO `json:",omitempty"`
   112  }
   113  
   114  var (
   115  	// ErrTierNameEmpty "remote tier name empty"
   116  	ErrTierNameEmpty = errors.New("remote tier name empty")
   117  	// ErrTierInvalidConfig "invalid tier config"
   118  	ErrTierInvalidConfig = errors.New("invalid tier config")
   119  	// ErrTierInvalidConfigVersion "invalid tier config version"
   120  	ErrTierInvalidConfigVersion = errors.New("invalid tier config version")
   121  	// ErrTierTypeUnsupported "unsupported tier type"
   122  	ErrTierTypeUnsupported = errors.New("unsupported tier type")
   123  )
   124  
   125  // Clone returns a copy of TierConfig with secret key/credentials redacted.
   126  func (cfg *TierConfig) Clone() TierConfig {
   127  	var (
   128  		s3  TierS3
   129  		az  TierAzure
   130  		gcs TierGCS
   131  		m   TierMinIO
   132  	)
   133  	switch cfg.Type {
   134  	case S3:
   135  		s3 = *cfg.S3
   136  		s3.SecretKey = "REDACTED"
   137  	case Azure:
   138  		az = *cfg.Azure
   139  		az.AccountKey = "REDACTED"
   140  	case GCS:
   141  		gcs = *cfg.GCS
   142  		gcs.Creds = "REDACTED"
   143  	case MinIO:
   144  		m = *cfg.MinIO
   145  		m.SecretKey = "REDACTED"
   146  	}
   147  	return TierConfig{
   148  		Version: cfg.Version,
   149  		Type:    cfg.Type,
   150  		Name:    cfg.Name,
   151  		S3:      &s3,
   152  		Azure:   &az,
   153  		GCS:     &gcs,
   154  		MinIO:   &m,
   155  	}
   156  }
   157  
   158  // UnmarshalJSON unmarshals json value to ensure that Type field is filled in
   159  // correspondence with the tier config supplied.
   160  // See TestUnmarshalTierConfig for an example json.
   161  func (cfg *TierConfig) UnmarshalJSON(b []byte) error {
   162  	type tierConfig TierConfig
   163  	var m tierConfig
   164  	err := json.Unmarshal(b, &m)
   165  	if err != nil {
   166  		return err
   167  	}
   168  
   169  	switch m.Version {
   170  	case TierConfigVer:
   171  	default:
   172  		return ErrTierInvalidConfigVersion
   173  	}
   174  
   175  	switch m.Type {
   176  	case S3:
   177  		if m.S3 == nil {
   178  			return ErrTierInvalidConfig
   179  		}
   180  	case Azure:
   181  		if m.Azure == nil {
   182  			return ErrTierInvalidConfig
   183  		}
   184  	case GCS:
   185  		if m.GCS == nil {
   186  			return ErrTierInvalidConfig
   187  		}
   188  	case MinIO:
   189  		if m.MinIO == nil {
   190  			return ErrTierInvalidConfig
   191  		}
   192  	}
   193  
   194  	if m.Name == "" {
   195  		return ErrTierNameEmpty
   196  	}
   197  
   198  	*cfg = TierConfig(m)
   199  	return nil
   200  }
   201  
   202  // Endpoint returns the remote tier backend endpoint.
   203  func (cfg *TierConfig) Endpoint() string {
   204  	switch cfg.Type {
   205  	case S3:
   206  		return cfg.S3.Endpoint
   207  	case Azure:
   208  		return cfg.Azure.Endpoint
   209  	case GCS:
   210  		return cfg.GCS.Endpoint
   211  	case MinIO:
   212  		return cfg.MinIO.Endpoint
   213  	}
   214  	log.Printf("unexpected tier type %s", cfg.Type)
   215  	return ""
   216  }
   217  
   218  // Bucket returns the remote tier backend bucket.
   219  func (cfg *TierConfig) Bucket() string {
   220  	switch cfg.Type {
   221  	case S3:
   222  		return cfg.S3.Bucket
   223  	case Azure:
   224  		return cfg.Azure.Bucket
   225  	case GCS:
   226  		return cfg.GCS.Bucket
   227  	case MinIO:
   228  		return cfg.MinIO.Bucket
   229  	}
   230  	log.Printf("unexpected tier type %s", cfg.Type)
   231  	return ""
   232  }
   233  
   234  // Prefix returns the remote tier backend prefix.
   235  func (cfg *TierConfig) Prefix() string {
   236  	switch cfg.Type {
   237  	case S3:
   238  		return cfg.S3.Prefix
   239  	case Azure:
   240  		return cfg.Azure.Prefix
   241  	case GCS:
   242  		return cfg.GCS.Prefix
   243  	case MinIO:
   244  		return cfg.MinIO.Prefix
   245  	}
   246  	log.Printf("unexpected tier type %s", cfg.Type)
   247  	return ""
   248  }
   249  
   250  // Region returns the remote tier backend region.
   251  func (cfg *TierConfig) Region() string {
   252  	switch cfg.Type {
   253  	case S3:
   254  		return cfg.S3.Region
   255  	case Azure:
   256  		return cfg.Azure.Region
   257  	case GCS:
   258  		return cfg.GCS.Region
   259  	case MinIO:
   260  		return cfg.MinIO.Region
   261  	}
   262  	log.Printf("unexpected tier type %s", cfg.Type)
   263  	return ""
   264  }