github.com/minio/madmin-go/v2@v2.2.1/replication-api.go (about)

     1  //
     2  // Copyright (c) 2015-2022 MinIO, Inc.
     3  //
     4  // This file is part of MinIO Object Storage stack
     5  //
     6  // This program is free software: you can redistribute it and/or modify
     7  // it under the terms of the GNU Affero General Public License as
     8  // published by the Free Software Foundation, either version 3 of the
     9  // License, or (at your option) any later version.
    10  //
    11  // This program is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU Affero General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU Affero General Public License
    17  // along with this program. If not, see <http://www.gnu.org/licenses/>.
    18  //
    19  
    20  package madmin
    21  
    22  import (
    23  	"context"
    24  	"encoding/json"
    25  	"net/http"
    26  	"net/url"
    27  	"time"
    28  )
    29  
    30  // ReplDiffOpts holds options for `mc replicate diff` command
    31  type ReplDiffOpts struct {
    32  	ARN     string
    33  	Verbose bool
    34  	Prefix  string
    35  }
    36  
    37  // TgtDiffInfo returns status of unreplicated objects
    38  // for the target ARN
    39  type TgtDiffInfo struct {
    40  	ReplicationStatus       string `json:"rStatus,omitempty"`  // target replication status
    41  	DeleteReplicationStatus string `json:"drStatus,omitempty"` // target delete replication status
    42  }
    43  
    44  // DiffInfo represents relevant replication status and last attempt to replicate
    45  // for the replication targets configured for the bucket
    46  type DiffInfo struct {
    47  	Object                  string                 `json:"object"`
    48  	VersionID               string                 `json:"versionId"`
    49  	Targets                 map[string]TgtDiffInfo `json:"targets,omitempty"`
    50  	Err                     error                  `json:"error,omitempty"`
    51  	ReplicationStatus       string                 `json:"rStatus,omitempty"` // overall replication status
    52  	DeleteReplicationStatus string                 `json:"dStatus,omitempty"` // overall replication status of version delete
    53  	ReplicationTimestamp    time.Time              `json:"replTimestamp,omitempty"`
    54  	LastModified            time.Time              `json:"lastModified,omitempty"`
    55  	IsDeleteMarker          bool                   `json:"deletemarker"`
    56  }
    57  
    58  // BucketReplicationDiff - gets diff for non-replicated entries.
    59  func (adm *AdminClient) BucketReplicationDiff(ctx context.Context, bucketName string, opts ReplDiffOpts) <-chan DiffInfo {
    60  	diffCh := make(chan DiffInfo)
    61  
    62  	// start a routine to start reading line by line.
    63  	go func(diffCh chan<- DiffInfo) {
    64  		defer close(diffCh)
    65  		queryValues := url.Values{}
    66  		queryValues.Set("bucket", bucketName)
    67  
    68  		if opts.Verbose {
    69  			queryValues.Set("verbose", "true")
    70  		}
    71  		if opts.ARN != "" {
    72  			queryValues.Set("arn", opts.ARN)
    73  		}
    74  		if opts.Prefix != "" {
    75  			queryValues.Set("prefix", opts.Prefix)
    76  		}
    77  
    78  		reqData := requestData{
    79  			relPath:     adminAPIPrefix + "/replication/diff",
    80  			queryValues: queryValues,
    81  		}
    82  
    83  		// Execute PUT on /minio/admin/v3/diff to set quota for a bucket.
    84  		resp, err := adm.executeMethod(ctx, http.MethodPost, reqData)
    85  		if err != nil {
    86  			diffCh <- DiffInfo{Err: err}
    87  			return
    88  		}
    89  		defer closeResponse(resp)
    90  
    91  		if resp.StatusCode != http.StatusOK {
    92  			diffCh <- DiffInfo{Err: httpRespToErrorResponse(resp)}
    93  			return
    94  		}
    95  
    96  		dec := json.NewDecoder(resp.Body)
    97  		for {
    98  			var di DiffInfo
    99  			if err = dec.Decode(&di); err != nil {
   100  				break
   101  			}
   102  			select {
   103  			case <-ctx.Done():
   104  				return
   105  			case diffCh <- di:
   106  			}
   107  		}
   108  	}(diffCh)
   109  	// Returns the diff channel, for caller to start reading from.
   110  	return diffCh
   111  }