github.com/devcamcar/cli@v0.0.0-20181107134215-706a05759d18/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/fnproject/fn_go/provider"
    10  	"github.com/spf13/viper"
    11  	"github.com/urfave/cli"
    12  )
    13  
    14  const (
    15  	rootConfigPathName = ".fn"
    16  
    17  	contextsPathName       = "contexts"
    18  	configName             = "config"
    19  	contextConfigFileName  = "config.yaml"
    20  	defaultContextFileName = "default.yaml"
    21  	defaultLocalAPIURL     = "http://localhost:8080"
    22  	DefaultProvider        = "default"
    23  
    24  	ReadWritePerms = os.FileMode(0755)
    25  
    26  	CurrentContext    = "current-context"
    27  	ContextProvider   = "provider"
    28  	CurrentCliVersion = "cli-version"
    29  
    30  	EnvFnRegistry = "registry"
    31  	EnvFnContext  = "context"
    32  )
    33  
    34  var defaultRootConfigContents = &ContextMap{CurrentContext: "", CurrentCliVersion: ""}
    35  var DefaultContextConfigContents = &ContextMap{
    36  	ContextProvider:      DefaultProvider,
    37  	provider.CfgFnAPIURL: defaultLocalAPIURL,
    38  	EnvFnRegistry:        "",
    39  }
    40  
    41  type ContextMap map[string]string
    42  
    43  // Init : Initialise/load config direc
    44  func Init() error {
    45  	viper.AutomaticEnv() // read in environment variables that match
    46  	viper.SetEnvPrefix("fn")
    47  
    48  	replacer := strings.NewReplacer("-", "_")
    49  	viper.SetEnvKeyReplacer(replacer)
    50  
    51  	viper.SetDefault(provider.CfgFnAPIURL, defaultLocalAPIURL)
    52  
    53  	return ensureConfiguration()
    54  }
    55  
    56  // EnsureConfiguration ensures context configuration directory hierarchy is in place, if not
    57  // creates it and the default context configuration files
    58  func ensureConfiguration() error {
    59  	home := GetHomeDir()
    60  
    61  	rootConfigPath := filepath.Join(home, rootConfigPathName)
    62  	if _, err := os.Stat(rootConfigPath); os.IsNotExist(err) {
    63  		if err = os.Mkdir(rootConfigPath, ReadWritePerms); err != nil {
    64  			return fmt.Errorf("error creating .fn directory %v", err)
    65  		}
    66  	}
    67  
    68  	contextConfigFilePath := filepath.Join(rootConfigPath, contextConfigFileName)
    69  	if _, err := os.Stat(contextConfigFilePath); os.IsNotExist(err) {
    70  		file, err := os.Create(contextConfigFilePath)
    71  		if err != nil {
    72  			return fmt.Errorf("error creating config.yaml file %v", err)
    73  		}
    74  
    75  		err = WriteYamlFile(file.Name(), defaultRootConfigContents)
    76  		if err != nil {
    77  			return err
    78  		}
    79  	}
    80  	contextsPath := filepath.Join(rootConfigPath, contextsPathName)
    81  	if _, err := os.Stat(contextsPath); os.IsNotExist(err) {
    82  		if err = os.Mkdir(contextsPath, ReadWritePerms); err != nil {
    83  			return fmt.Errorf("error creating contexts directory %v", err)
    84  		}
    85  	}
    86  
    87  	defaultContextPath := filepath.Join(contextsPath, defaultContextFileName)
    88  	if _, err := os.Stat(defaultContextPath); os.IsNotExist(err) {
    89  		_, err = os.Create(defaultContextPath)
    90  		if err != nil {
    91  			return fmt.Errorf("error creating default.yaml context file %v", err)
    92  		}
    93  
    94  		err = WriteYamlFile(defaultContextPath, DefaultContextConfigContents)
    95  		if err != nil {
    96  			return err
    97  		}
    98  	}
    99  
   100  	return nil
   101  }
   102  
   103  // GetContextsPath : Returns the path to the contexts directory.
   104  func GetContextsPath() string {
   105  	contextsPath := filepath.Join(rootConfigPathName, contextsPathName)
   106  	return contextsPath
   107  }
   108  
   109  func LoadConfiguration(c *cli.Context) error {
   110  	// Find home directory.
   111  	home := GetHomeDir()
   112  	context := ""
   113  
   114  	viper.AddConfigPath(filepath.Join(home, rootConfigPathName))
   115  	viper.SetConfigName(configName)
   116  
   117  	if err := viper.ReadInConfig(); err != nil {
   118  		return err
   119  	}
   120  
   121  	if context = c.String(EnvFnContext); context == "" {
   122  		context = viper.GetString(CurrentContext)
   123  	}
   124  
   125  	viper.AddConfigPath(filepath.Join(home, rootConfigPathName, contextsPathName))
   126  	viper.SetConfigName(context)
   127  
   128  	WriteConfigValueToConfigFile(CurrentCliVersion, Version)
   129  
   130  	if err := viper.ReadInConfig(); err != nil {
   131  		fmt.Printf("%v \n", err)
   132  		err := WriteConfigValueToConfigFile(CurrentContext, "default")
   133  		if err != nil {
   134  			return err
   135  		}
   136  		WriteConfigValueToConfigFile(CurrentCliVersion, Version)
   137  		if err != nil {
   138  			return err
   139  		}
   140  
   141  		fmt.Println("current context has been set to default")
   142  		return nil
   143  	}
   144  
   145  	viper.Set(CurrentContext, context)
   146  	return nil
   147  }
   148  
   149  func WriteConfigValueToConfigFile(key, value string) error {
   150  	home := GetHomeDir()
   151  
   152  	configFilePath := filepath.Join(home, rootConfigPathName, contextConfigFileName)
   153  	f, err := os.OpenFile(configFilePath, os.O_RDWR, ReadWritePerms)
   154  	if err != nil {
   155  		return err
   156  	}
   157  	defer f.Close()
   158  
   159  	file, err := DecodeYAMLFile(f.Name())
   160  	if err != nil {
   161  		return err
   162  	}
   163  
   164  	configValues := ContextMap{}
   165  	for k, v := range *file {
   166  		if k == key {
   167  			configValues[k] = value
   168  		} else {
   169  			configValues[k] = v
   170  		}
   171  	}
   172  	configValues[key] = value
   173  
   174  	err = WriteYamlFile(f.Name(), &configValues)
   175  	if err != nil {
   176  		return err
   177  	}
   178  
   179  	return nil
   180  }