github.com/minio/madmin-go@v1.7.5/tier.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  	"context"
    21  	"encoding/json"
    22  	"io/ioutil"
    23  	"net/http"
    24  	"path"
    25  	"time"
    26  )
    27  
    28  // tierAPI is API path prefix for tier related admin APIs
    29  const tierAPI = "tier"
    30  
    31  // AddTier adds a new remote tier.
    32  func (adm *AdminClient) AddTier(ctx context.Context, cfg *TierConfig) error {
    33  	data, err := json.Marshal(cfg)
    34  	if err != nil {
    35  		return err
    36  	}
    37  
    38  	encData, err := EncryptData(adm.getSecretKey(), data)
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	reqData := requestData{
    44  		relPath: path.Join(adminAPIPrefix, tierAPI),
    45  		content: encData,
    46  	}
    47  
    48  	// Execute PUT on /minio/admin/v3/tier to add a remote tier
    49  	resp, err := adm.executeMethod(ctx, http.MethodPut, reqData)
    50  	defer closeResponse(resp)
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	if resp.StatusCode != http.StatusNoContent {
    56  		return httpRespToErrorResponse(resp)
    57  	}
    58  	return nil
    59  }
    60  
    61  // ListTiers returns a list of remote tiers configured.
    62  func (adm *AdminClient) ListTiers(ctx context.Context) ([]*TierConfig, error) {
    63  	reqData := requestData{
    64  		relPath: path.Join(adminAPIPrefix, tierAPI),
    65  	}
    66  
    67  	// Execute GET on /minio/admin/v3/tier to list remote tiers configured.
    68  	resp, err := adm.executeMethod(ctx, http.MethodGet, reqData)
    69  	defer closeResponse(resp)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	if resp.StatusCode != http.StatusOK {
    75  		return nil, httpRespToErrorResponse(resp)
    76  	}
    77  
    78  	var tiers []*TierConfig
    79  	b, err := ioutil.ReadAll(resp.Body)
    80  	if err != nil {
    81  		return tiers, err
    82  	}
    83  
    84  	err = json.Unmarshal(b, &tiers)
    85  	if err != nil {
    86  		return tiers, err
    87  	}
    88  
    89  	return tiers, nil
    90  }
    91  
    92  // TierCreds is used to pass remote tier credentials in a tier-edit operation.
    93  type TierCreds struct {
    94  	AccessKey string `json:"access,omitempty"`
    95  	SecretKey string `json:"secret,omitempty"`
    96  	CredsJSON []byte `json:"creds,omitempty"`
    97  	AWSRole   bool   `json:"awsrole"`
    98  }
    99  
   100  // EditTier supports updating credentials for the remote tier identified by tierName.
   101  func (adm *AdminClient) EditTier(ctx context.Context, tierName string, creds TierCreds) error {
   102  	data, err := json.Marshal(creds)
   103  	if err != nil {
   104  		return err
   105  	}
   106  
   107  	var encData []byte
   108  	encData, err = EncryptData(adm.getSecretKey(), data)
   109  	if err != nil {
   110  		return err
   111  	}
   112  
   113  	reqData := requestData{
   114  		relPath: path.Join(adminAPIPrefix, tierAPI, tierName),
   115  		content: encData,
   116  	}
   117  
   118  	// Execute POST on /minio/admin/v3/tier/tierName to edit a tier
   119  	// configured.
   120  	resp, err := adm.executeMethod(ctx, http.MethodPost, reqData)
   121  	defer closeResponse(resp)
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	if resp.StatusCode != http.StatusNoContent {
   127  		return httpRespToErrorResponse(resp)
   128  	}
   129  
   130  	return nil
   131  }
   132  
   133  // RemoveTier removes an empty tier identified by tierName
   134  func (adm *AdminClient) RemoveTier(ctx context.Context, tierName string) error {
   135  	if tierName == "" {
   136  		return ErrTierNameEmpty
   137  	}
   138  	reqData := requestData{
   139  		relPath: path.Join(adminAPIPrefix, tierAPI, tierName),
   140  	}
   141  
   142  	// Execute DELETE on /minio/admin/v3/tier/tierName to remove an empty tier.
   143  	resp, err := adm.executeMethod(ctx, http.MethodDelete, reqData)
   144  	defer closeResponse(resp)
   145  	if err != nil {
   146  		return err
   147  	}
   148  
   149  	if resp.StatusCode != http.StatusNoContent {
   150  		return httpRespToErrorResponse(resp)
   151  	}
   152  
   153  	return nil
   154  }
   155  
   156  // VerifyTier verifies tierName's remote tier config
   157  func (adm *AdminClient) VerifyTier(ctx context.Context, tierName string) error {
   158  	if tierName == "" {
   159  		return ErrTierNameEmpty
   160  	}
   161  	reqData := requestData{
   162  		relPath: path.Join(adminAPIPrefix, tierAPI, tierName),
   163  	}
   164  
   165  	// Execute GET on /minio/admin/v3/tier/tierName to verify tierName's config.
   166  	resp, err := adm.executeMethod(ctx, http.MethodGet, reqData)
   167  	defer closeResponse(resp)
   168  	if err != nil {
   169  		return err
   170  	}
   171  
   172  	if resp.StatusCode != http.StatusNoContent {
   173  		return httpRespToErrorResponse(resp)
   174  	}
   175  
   176  	return nil
   177  }
   178  
   179  // TierInfo contains tier name, type and statistics
   180  type TierInfo struct {
   181  	Name       string
   182  	Type       string
   183  	Stats      TierStats
   184  	DailyStats DailyTierStats
   185  }
   186  
   187  type DailyTierStats struct {
   188  	Bins      [24]TierStats
   189  	UpdatedAt time.Time
   190  }
   191  
   192  // TierStats returns per-tier stats of all configured tiers (incl. internal
   193  // hot-tier)
   194  func (adm *AdminClient) TierStats(ctx context.Context) ([]TierInfo, error) {
   195  	reqData := requestData{
   196  		relPath: path.Join(adminAPIPrefix, "tier-stats"),
   197  	}
   198  
   199  	// Execute GET on /minio/admin/v3/tier-stats to list tier-stats.
   200  	resp, err := adm.executeMethod(ctx, http.MethodGet, reqData)
   201  	defer closeResponse(resp)
   202  	if err != nil {
   203  		return nil, err
   204  	}
   205  
   206  	if resp.StatusCode != http.StatusOK {
   207  		return nil, httpRespToErrorResponse(resp)
   208  	}
   209  
   210  	var tierInfos []TierInfo
   211  	b, err := ioutil.ReadAll(resp.Body)
   212  	if err != nil {
   213  		return tierInfos, err
   214  	}
   215  
   216  	err = json.Unmarshal(b, &tierInfos)
   217  	if err != nil {
   218  		return tierInfos, err
   219  	}
   220  
   221  	return tierInfos, nil
   222  }