func (m *Monkey) DatabaseEncryptedPassword() string {
	return m.v.GetString(param.DatabaseEncryptedPassword)
}
DatabaseEncryptedPassword returns an encrypted version of the database
credentials
package config
import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"strings"
	"time"
	"github.com/pkg/errors"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"github.com/Netflix/chaosmonkey/config/param"
)
type Monkey struct {
	remote bool  
	v      *viper.Viper
}
const (
	clockStartHour      int = 0
	clockEndHour        int = 23
	hoursInClock        int = 24
	cronBeforeStartHour int = 2
)
func (m *Monkey) setDefaults() {
	m.v.SetDefault(param.Enabled, false)
	m.v.SetDefault(param.Leashed, true)
	m.v.SetDefault(param.ScheduleEnabled, false)
	m.v.SetDefault(param.Accounts, []string{})
	m.v.SetDefault(param.StartHour, 9)
	m.v.SetDefault(param.EndHour, 15)
	m.v.SetDefault(param.TimeZone, "America/Los_Angeles")
	m.v.SetDefault(param.CronPath, "/etc/cron.d/chaosmonkey-daily-terminations")
	m.v.SetDefault(param.TermPath, "/apps/chaosmonkey/chaosmonkey-terminate.sh")
	m.v.SetDefault(param.TermAccount, "root")
	m.v.SetDefault(param.MaxApps, math.MaxInt32)
	m.v.SetDefault(param.Trackers, []string{})
	m.v.SetDefault(param.Decryptor, "")
	m.v.SetDefault(param.OutageChecker, "")
	m.v.SetDefault(param.DatabasePort, 3306)
	m.v.SetDefault(param.SpinnakerEndpoint, "")
	m.v.SetDefault(param.SpinnakerCertificate, "")
	m.v.SetDefault(param.SpinnakerEncryptedPassword, "")
	m.v.SetDefault(param.SpinnakerUser, "")
	m.v.SetDefault(param.SpinnakerX509Cert, "")
	m.v.SetDefault(param.SpinnakerX509Key, "")
	m.v.SetDefault(param.DynamicProvider, "")
	m.v.SetDefault(param.DynamicEndpoint, "")
	m.v.SetDefault(param.DynamicPath, "")
	m.v.SetDefault(param.ScheduleCronPath, "/etc/cron.d/chaosmonkey-schedule")
	m.v.SetDefault(param.SchedulePath, "/apps/chaosmonkey/chaosmonkey-schedule.sh")
	m.v.SetDefault(param.LogPath, "/var/log")
}
func (m *Monkey) setupEnvVarReader() {
	m.v.AutomaticEnv()
	m.v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
}
func Load(configPaths []string) (*Monkey, error) {
	m := &Monkey{v: viper.New()}
	m.setDefaults()
	m.setupEnvVarReader()
	for _, dir := range configPaths {
		m.v.AddConfigPath(dir)
	}
	m.v.SetConfigType("toml")
	m.v.SetConfigName("chaosmonkey")
	err := m.v.ReadInConfig()
	if err != nil {
		if !os.IsNotExist(err) {
			return nil, errors.Wrapf(err, "failed to read config file")
		}
		log.Printf("no config file found, proceeding without one")
	}
	err = m.configureRemote()
	if err != nil {
		return nil, err
	}
	return m, nil
}
func Defaults() *Monkey {
	v := &Monkey{v: viper.New()}
	v.setDefaults()
	return v
}
func NewFromReader(in io.Reader) (*Monkey, error) {
	m := &Monkey{v: viper.New()}
	m.setDefaults()
	m.v.SetConfigType("toml")
	err := m.v.ReadConfig(in)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse config")
	}
	err = m.configureRemote()
	if err != nil {
		return nil, err
	}
	return m, nil
}
func (m *Monkey) configureRemote() error {
	provider := m.v.GetString(param.DynamicProvider)
	endpoint := m.v.GetString(param.DynamicEndpoint)
	path := m.v.GetString(param.DynamicPath)
	if provider != "" {
		m.remote = true
		m.v.SetConfigType("json")
		err := m.v.AddRemoteProvider(provider, endpoint, path)
		if err != nil {
			return errors.Wrapf(err, "failed viper.AddRemoteProvider(provider=\"%s\", endpoint=\"%s\", path=\"%s\"):", provider, endpoint, path)
		}
	}
	return nil
}
func (m *Monkey) SetRemoteProvider(provider string, endpoint string, path string) error {
	m.v.Set(param.DynamicProvider, provider)
	m.v.Set(param.DynamicEndpoint, endpoint)
	m.v.Set(param.DynamicPath, path)
	return m.configureRemote()
}
func (m *Monkey) Set(key string, value interface{}) {
	m.v.Set(key, value)
}
func (m *Monkey) readRemoteConfig() error {
	if !m.remote {
		return nil
	}
	return m.v.ReadRemoteConfig()
}
func (m *Monkey) Enabled() (bool, error) {
	return m.getDynamicBool(param.Enabled)
}
func (m *Monkey) Leashed() (bool, error) {
	return m.getDynamicBool(param.Leashed)
}
func (m *Monkey) ScheduleEnabled() (bool, error) {
	return m.getDynamicBool(param.ScheduleEnabled)
}
func (m *Monkey) getDynamicBool(param string) (bool, error) {
	err := m.readRemoteConfig()
	if err != nil {
		return false, err
	}
	return m.v.GetBool(param), nil
}
func (m *Monkey) AccountEnabled(account string) (bool, error) {
	accounts, err := m.Accounts()
	if err != nil {
		return false, err
	}
	for _, x := range accounts {
		if account == x {
			return true, nil
		}
	}
	return false, nil
}
func (m *Monkey) Accounts() ([]string, error) {
	err := m.readRemoteConfig()
	if err != nil {
		return nil, err
	}
	return m.getStringSlice(param.Accounts)
}
func toStrings(values []interface{}) ([]string, error) {
	result := make([]string, len(values))
	for i, x := range values {
		x, valid := x.(string)
		if !valid {
			return nil, errors.Errorf("non-string in %v", values)
		}
		result[i] = x
	}
	return result, nil
}
func (m *Monkey) StartHour() int { return m.v.GetInt(param.StartHour) }
func (m *Monkey) EndHour() int {
	return m.v.GetInt(param.EndHour)
}
func (m *Monkey) Location() (*time.Location, error) {
	return time.LoadLocation(m.v.GetString(param.TimeZone))
}
func (m *Monkey) CronPath() string {
	return m.v.GetString(param.CronPath)
}
func (m *Monkey) TermPath() string {
	return m.v.GetString(param.TermPath)
}
func (m *Monkey) TermAccount() string {
	return m.v.GetString(param.TermAccount)
}
func (m *Monkey) MaxApps() int {
	return m.v.GetInt(param.MaxApps)
}
func (m *Monkey) Trackers() ([]string, error) {
	return m.getStringSlice(param.Trackers)
}
func (m *Monkey) ErrorCounter() string {
	return m.v.GetString(param.ErrorCounter)
}
func (m *Monkey) getStringSlice(key string) ([]string, error) {
	t := m.v.Get(key)
	if t == nil {
		return nil, fmt.Errorf("%s not specified", param.Accounts)
	}
	switch t := t.(type) {
	default:
		return nil, fmt.Errorf("%s: unexpected type %T", param.Accounts, t)
	case []string:  
		return t, nil
	case []interface{}:  
		return toStrings(t)
	case string:  
		var result []string
		err := json.Unmarshal([]byte(t), &result)
		return result, err
	}
}
func (m *Monkey) SpinnakerEndpoint() string {
	return m.v.GetString(param.SpinnakerEndpoint)
}
func (m *Monkey) SpinnakerCertificate() string {
	return m.v.GetString(param.SpinnakerCertificate)
}
func (m *Monkey) SpinnakerEncryptedPassword() string {
	return m.v.GetString(param.SpinnakerEncryptedPassword)
}
func (m *Monkey) SpinnakerUser() string {
	return m.v.GetString(param.SpinnakerUser)
}
func (m *Monkey) SpinnakerX509Cert() string {
	return m.v.GetString(param.SpinnakerX509Cert)
}
func (m *Monkey) SpinnakerX509Key() string {
	return m.v.GetString(param.SpinnakerX509Key)
}
func (m *Monkey) Decryptor() string {
	return m.v.GetString(param.Decryptor)
}
func (m *Monkey) OutageChecker() string {
	return m.v.GetString(param.OutageChecker)
}
func (m *Monkey) DatabaseHost() string {
	return m.v.GetString(param.DatabaseHost)
}
func (m *Monkey) DatabasePort() int {
	return m.v.GetInt(param.DatabasePort)
}
func (m *Monkey) DatabaseUser() string {
	return m.v.GetString(param.DatabaseUser)
}
func (m *Monkey) DatabaseName() string {
	return m.v.GetString(param.DatabaseName)
}