github.com/andrewseidl/viper@v0.0.0-20191228040610-757ecc9b7b3e/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  	"github.com/spf13/viper"
    12  	crypt "github.com/xordataexchange/crypt/config"
    13  	"io"
    14  	"os"
    15  )
    16  
    17  type remoteConfigProvider struct{}
    18  
    19  func (rc remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
    20  	cm, err := getConfigManager(rp)
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  	b, err := cm.Get(rp.Path())
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	return bytes.NewReader(b), nil
    29  }
    30  
    31  func (rc remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
    32  	cm, err := getConfigManager(rp)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	resp,err := cm.Get(rp.Path())
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	return bytes.NewReader(resp), nil
    42  }
    43  func (rc remoteConfigProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) {
    44  	cm, err := getConfigManager(rp)
    45  	if err != nil {
    46  		return nil, nil
    47  	}
    48  	quit := make(chan bool)
    49  	quitwc := make(chan bool)
    50  	viperResponsCh := make(chan  *viper.RemoteResponse)
    51  	cryptoResponseCh := cm.Watch(rp.Path(), quit)
    52  	// need this function to convert the Channel response form crypt.Response to viper.Response
    53  	go func(cr <-chan *crypt.Response,vr chan<- *viper.RemoteResponse, quitwc <-chan bool, quit chan<- bool) {
    54  		for {
    55  			select {
    56  			case <- quitwc:
    57  				quit <- true
    58  				return
    59  			case resp := <-cr:
    60  				vr <- &viper.RemoteResponse{
    61  					Error: resp.Error,
    62  					Value: resp.Value,
    63  				}
    64  
    65  			}
    66  
    67  		}
    68  	}(cryptoResponseCh,viperResponsCh,quitwc,quit)
    69  
    70  	return  viperResponsCh,quitwc
    71  
    72  }
    73  
    74  
    75  func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
    76  
    77  	var cm crypt.ConfigManager
    78  	var err error
    79  
    80  	if rp.SecretKeyring() != "" {
    81  		kr, err := os.Open(rp.SecretKeyring())
    82  		defer kr.Close()
    83  		if err != nil {
    84  			return nil, err
    85  		}
    86  		if rp.Provider() == "etcd" {
    87  			cm, err = crypt.NewEtcdConfigManager([]string{rp.Endpoint()}, kr)
    88  		} else {
    89  			cm, err = crypt.NewConsulConfigManager([]string{rp.Endpoint()}, kr)
    90  		}
    91  	} else {
    92  		if rp.Provider() == "etcd" {
    93  			cm, err = crypt.NewStandardEtcdConfigManager([]string{rp.Endpoint()})
    94  		} else {
    95  			cm, err = crypt.NewStandardConsulConfigManager([]string{rp.Endpoint()})
    96  		}
    97  	}
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	return cm, nil
   102  
   103  }
   104  
   105  func init() {
   106  	viper.RemoteConfig = &remoteConfigProvider{}
   107  }