github.com/greenboxal/deis@v1.12.1/logger/configurer/configurer.go (about)

     1  package configurer
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"time"
     7  
     8  	"github.com/coreos/go-etcd/etcd"
     9  	"github.com/deis/deis/logger/drain"
    10  	"github.com/deis/deis/logger/storage"
    11  	"github.com/deis/deis/logger/syslogish"
    12  )
    13  
    14  // Exported so it can be set by an external agent-- namely main.go, which does some flag parsing.
    15  var DefaultDrainURI string
    16  
    17  // Configurer takes responsibility for dynamically reconfiguring a syslogish.Server based on
    18  // changes in etcd.
    19  type Configurer struct {
    20  	etcdClient                *etcd.Client
    21  	etcdPath                  string
    22  	ticker                    *time.Ticker
    23  	syslogishServer           *syslogish.Server
    24  	running                   bool
    25  	currentStorageAdapterType string
    26  	currentDrainURL           string
    27  }
    28  
    29  // NewConfigurer returns a pointer to a new Configurer instance.
    30  func NewConfigurer(etcdHost string, etcdPort int, etcdPath string, configInterval int,
    31  	syslogishServer *syslogish.Server) (*Configurer, error) {
    32  	etcdClient := etcd.NewClient([]string{fmt.Sprintf("http://%s:%d", etcdHost, etcdPort)})
    33  	ticker := time.NewTicker(time.Duration(configInterval) * time.Second)
    34  	configurer := &Configurer{
    35  		etcdClient:      etcdClient,
    36  		etcdPath:        etcdPath,
    37  		syslogishServer: syslogishServer,
    38  		ticker:          ticker,
    39  	}
    40  
    41  	// Support legacy behavior that allows default drain uri to be specified using a drain-uri flag
    42  	if _, err := etcdClient.Get(etcdPath+"/drain", false, false); err != nil {
    43  		etcdErr, ok := err.(*etcd.EtcdError)
    44  		// Error code 100 is key not found
    45  		if ok && etcdErr.ErrorCode == 100 {
    46  			configurer.setEtcd("/drain", DefaultDrainURI)
    47  		} else {
    48  			log.Println(err)
    49  		}
    50  	}
    51  
    52  	return configurer, nil
    53  }
    54  
    55  // Start begins the configurer's main loop.
    56  func (c *Configurer) Start() {
    57  	// Should only ever be called once
    58  	if !c.running {
    59  		c.running = true
    60  		go c.configure()
    61  		log.Println("configurer running")
    62  	}
    63  }
    64  
    65  func (c *Configurer) configure() {
    66  	for {
    67  		<-c.ticker.C
    68  		c.manageStorageAdapter()
    69  		c.manageDrain()
    70  	}
    71  }
    72  
    73  func (c *Configurer) manageStorageAdapter() {
    74  	newStorageAdapterType, err := c.getEtcd("/storageAdapterType", "file")
    75  	if err != nil {
    76  		log.Println("configurer: Error retrieving storage adapter type from etcd.  Skipping.", err)
    77  		return
    78  	}
    79  	if newStorageAdapterType == c.currentStorageAdapterType {
    80  		return
    81  	}
    82  	newStorageAdapter, err := storage.NewAdapter(newStorageAdapterType)
    83  	if err != nil {
    84  		log.Println("configurer: Error creating new storage adapter.  Skipping.", err)
    85  		return
    86  	}
    87  	c.syslogishServer.SetStorageAdapter(newStorageAdapter)
    88  	c.currentStorageAdapterType = newStorageAdapterType
    89  	log.Printf("configurer: Activated new storage adapter: %s", newStorageAdapterType)
    90  }
    91  
    92  func (c *Configurer) manageDrain() {
    93  	newDrainURL, err := c.getEtcd("/drain", "")
    94  	if err != nil {
    95  		log.Println("configurer: Error retrieving drain URL from etcd.  Skipping.", err)
    96  		return
    97  	}
    98  	if newDrainURL == c.currentDrainURL {
    99  		return
   100  	}
   101  	newDrain, err := drain.NewDrain(newDrainURL)
   102  	if err != nil {
   103  		log.Println("configurer: Error creating new drain.  Skipping.", err)
   104  		return
   105  	}
   106  	c.syslogishServer.SetDrain(newDrain)
   107  	c.currentDrainURL = newDrainURL
   108  	if newDrainURL == "" {
   109  		log.Println("configurer: Deactivated drain")
   110  	} else {
   111  		log.Printf("configurer: Activated new drain: %s", newDrainURL)
   112  	}
   113  }
   114  
   115  func (c *Configurer) getEtcd(key string, defaultValue string) (string, error) {
   116  	resp, err := c.etcdClient.Get(fmt.Sprintf("%s%s", c.etcdPath, key), false, false)
   117  	if err != nil {
   118  		etcdErr, ok := err.(*etcd.EtcdError)
   119  		// Error code 100 is key not found
   120  		if ok && etcdErr.ErrorCode == 100 {
   121  			return defaultValue, nil
   122  		}
   123  		return "", err
   124  	}
   125  	return resp.Node.Value, nil
   126  }
   127  
   128  func (c *Configurer) setEtcd(key string, value string) {
   129  	_, err := c.etcdClient.Set(fmt.Sprintf("%s%s", c.etcdPath, key), value, 0)
   130  	if err != nil {
   131  		etcdErr, ok := err.(*etcd.EtcdError)
   132  		// Error code 105 is key already exists
   133  		if !ok || etcdErr.ErrorCode != 105 {
   134  			log.Println(err)
   135  		}
   136  	}
   137  }