github.com/xl1605368195/viper@v1.1.8/remote/remote.go (about)

     1  // Copyright © 2015 Steve Francia <spf@spf13.com>.
     2  //
     3  // Use of this source code is governed by an MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  // Package remote integrates the remote features of Viper.
     7  package remote
     8  
     9  import (
    10  	"bytes"
    11  	"io"
    12  	"os"
    13  	"strings"
    14  
    15  	crypt "github.com/xl1605368195/crypt/config"
    16  
    17  	"github.com/xl1605368195/viper"
    18  )
    19  
    20  type remoteConfigProvider struct{}
    21  
    22  func (rc remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
    23  	cm, err := getConfigManager(rp)
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	b, err := cm.Get(rp.Path())
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	return bytes.NewReader(b), nil
    32  }
    33  
    34  func (rc remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
    35  	cm, err := getConfigManager(rp)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	resp, err := cm.Get(rp.Path())
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  
    44  	return bytes.NewReader(resp), nil
    45  }
    46  
    47  func (rc remoteConfigProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) {
    48  	cm, err := getConfigManager(rp)
    49  	if err != nil {
    50  		return nil, nil
    51  	}
    52  	quit := make(chan bool)
    53  	quitwc := make(chan bool)
    54  	viperResponsCh := make(chan *viper.RemoteResponse)
    55  	cryptoResponseCh := cm.Watch(rp.Path(), quit)
    56  	// need this function to convert the Channel response form crypt.Response to viper.Response
    57  	go func(cr <-chan *crypt.Response, vr chan<- *viper.RemoteResponse, quitwc <-chan bool, quit chan<- bool) {
    58  		for {
    59  			select {
    60  			case <-quitwc:
    61  				quit <- true
    62  				return
    63  			case resp := <-cr:
    64  				vr <- &viper.RemoteResponse{
    65  					Error: resp.Error,
    66  					Value: resp.Value,
    67  				}
    68  			}
    69  		}
    70  	}(cryptoResponseCh, viperResponsCh, quitwc, quit)
    71  
    72  	return viperResponsCh, quitwc
    73  }
    74  
    75  func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
    76  	var cm crypt.ConfigManager
    77  	var err error
    78  
    79  	endpoints := strings.Split(rp.Endpoint(), ";")
    80  	if rp.SecretKeyring() != "" {
    81  		var kr *os.File
    82  		kr, err = os.Open(rp.SecretKeyring())
    83  		if err != nil {
    84  			return nil, err
    85  		}
    86  		defer kr.Close()
    87  		switch rp.Provider() {
    88  		case "etcd":
    89  			cm, err = crypt.NewEtcdConfigManager(endpoints, kr)
    90  		case "etcd3":
    91  			cm, err = crypt.NewEtcdV3ConfigManager(endpoints, kr)
    92  		case "firestore":
    93  			cm, err = crypt.NewFirestoreConfigManager(endpoints, kr)
    94  		case "http":
    95  			cm, err = crypt.NewHttpConfigManager(endpoints, kr)
    96  		default:
    97  			cm, err = crypt.NewConsulConfigManager(endpoints, kr)
    98  		}
    99  	} else {
   100  		switch rp.Provider() {
   101  		case "etcd":
   102  			cm, err = crypt.NewStandardEtcdConfigManager(endpoints)
   103  		case "etcd3":
   104  			cm, err = crypt.NewStandardEtcdV3ConfigManager(endpoints)
   105  		case "firestore":
   106  			cm, err = crypt.NewStandardFirestoreConfigManager(endpoints)
   107  		case "http":
   108  			cm, err = crypt.NewStandardHttpConfigManager(endpoints)
   109  		default:
   110  			cm, err = crypt.NewStandardConsulConfigManager(endpoints)
   111  		}
   112  	}
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	return cm, nil
   117  }
   118  
   119  func init() {
   120  	viper.RemoteConfig = &remoteConfigProvider{}
   121  }