github.com/rafflecopter/deis@v1.12.2/client/cmd/config.go (about)

     1  package cmd
     2  
     3  import (
     4  	"encoding/base64"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"regexp"
     9  	"sort"
    10  	"strings"
    11  
    12  	"github.com/deis/deis/pkg/prettyprint"
    13  
    14  	"github.com/deis/deis/client/controller/api"
    15  	"github.com/deis/deis/client/controller/models/config"
    16  )
    17  
    18  // ConfigList lists an app's config.
    19  func ConfigList(appID string, oneLine bool) error {
    20  	c, appID, err := load(appID)
    21  
    22  	if err != nil {
    23  		return err
    24  	}
    25  
    26  	config, err := config.List(c, appID)
    27  
    28  	if err != nil {
    29  		return err
    30  	}
    31  
    32  	var keys []string
    33  	for k := range config.Values {
    34  		keys = append(keys, k)
    35  	}
    36  	sort.Strings(keys)
    37  
    38  	if oneLine {
    39  		for _, key := range keys {
    40  			fmt.Printf("%s=%s ", key, config.Values[key])
    41  		}
    42  		fmt.Println()
    43  	} else {
    44  		fmt.Printf("=== %s Config\n", appID)
    45  
    46  		configMap := make(map[string]string)
    47  
    48  		// config.Values is type interface, so it needs to be converted to a string
    49  		for _, key := range keys {
    50  			configMap[key] = fmt.Sprintf("%v", config.Values[key])
    51  		}
    52  
    53  		fmt.Print(prettyprint.PrettyTabs(configMap, 6))
    54  	}
    55  
    56  	return nil
    57  }
    58  
    59  // ConfigSet sets an app's config variables.
    60  func ConfigSet(appID string, configVars []string) error {
    61  	c, appID, err := load(appID)
    62  
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	configMap := parseConfig(configVars)
    68  
    69  	value, ok := configMap["SSH_KEY"]
    70  
    71  	if ok {
    72  		sshKey := value.(string)
    73  
    74  		if _, err := os.Stat(value.(string)); err == nil {
    75  			contents, err := ioutil.ReadFile(value.(string))
    76  
    77  			if err != nil {
    78  				return err
    79  			}
    80  
    81  			sshKey = string(contents)
    82  		}
    83  
    84  		sshRegex := regexp.MustCompile("^-.+ .SA PRIVATE KEY-*")
    85  
    86  		if !sshRegex.MatchString(sshKey) {
    87  			return fmt.Errorf("Could not parse SSH private key:\n %s", sshKey)
    88  		}
    89  
    90  		configMap["SSH_KEY"] = base64.StdEncoding.EncodeToString([]byte(sshKey))
    91  	}
    92  
    93  	fmt.Print("Creating config... ")
    94  
    95  	quit := progress()
    96  	configObj := api.Config{Values: configMap}
    97  	configObj, err = config.Set(c, appID, configObj)
    98  
    99  	quit <- true
   100  	<-quit
   101  
   102  	if err != nil {
   103  		return err
   104  	}
   105  
   106  	if release, ok := configObj.Values["DEIS_RELEASE"]; ok {
   107  		fmt.Printf("done, %s\n\n", release)
   108  	} else {
   109  		fmt.Print("done\n\n")
   110  	}
   111  
   112  	return ConfigList(appID, false)
   113  }
   114  
   115  // ConfigUnset removes a config variable from an app.
   116  func ConfigUnset(appID string, configVars []string) error {
   117  	c, appID, err := load(appID)
   118  
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	fmt.Print("Removing config... ")
   124  
   125  	quit := progress()
   126  
   127  	configObj := api.Config{}
   128  
   129  	valuesMap := make(map[string]interface{})
   130  
   131  	for _, configVar := range configVars {
   132  		valuesMap[configVar] = nil
   133  	}
   134  
   135  	configObj.Values = valuesMap
   136  
   137  	_, err = config.Set(c, appID, configObj)
   138  
   139  	quit <- true
   140  	<-quit
   141  
   142  	if err != nil {
   143  		return err
   144  	}
   145  
   146  	fmt.Print("done\n\n")
   147  
   148  	return ConfigList(appID, false)
   149  }
   150  
   151  // ConfigPull pulls an app's config to a file.
   152  func ConfigPull(appID string, interactive bool, overwrite bool) error {
   153  	filename := ".env"
   154  
   155  	if !overwrite {
   156  		if _, err := os.Stat(filename); err == nil {
   157  			return fmt.Errorf("%s already exists, pass -o to overwrite", filename)
   158  		}
   159  	}
   160  
   161  	c, appID, err := load(appID)
   162  
   163  	if err != nil {
   164  		return err
   165  	}
   166  
   167  	configVars, err := config.List(c, appID)
   168  
   169  	if interactive {
   170  		contents, err := ioutil.ReadFile(filename)
   171  
   172  		if err != nil {
   173  			return err
   174  		}
   175  		localConfigVars := strings.Split(string(contents), "\n")
   176  
   177  		configMap := parseConfig(localConfigVars[:len(localConfigVars)-1])
   178  
   179  		for key, value := range configVars.Values {
   180  			localValue, ok := configMap[key]
   181  
   182  			if ok {
   183  				if value != localValue {
   184  					var confirm string
   185  					fmt.Printf("%s: overwrite %s with %s? (y/N) ", key, localValue, value)
   186  
   187  					fmt.Scanln(&confirm)
   188  
   189  					if strings.ToLower(confirm) == "y" {
   190  						configMap[key] = value
   191  					}
   192  				}
   193  			} else {
   194  				configMap[key] = value
   195  			}
   196  		}
   197  
   198  		return ioutil.WriteFile(filename, []byte(formatConfig(configMap)), 0755)
   199  	}
   200  
   201  	return ioutil.WriteFile(filename, []byte(formatConfig(configVars.Values)), 0755)
   202  }
   203  
   204  // ConfigPush pushes an app's config from a file.
   205  func ConfigPush(appID string, fileName string) error {
   206  	contents, err := ioutil.ReadFile(fileName)
   207  
   208  	if err != nil {
   209  		return err
   210  	}
   211  
   212  	config := strings.Split(string(contents), "\n")
   213  	return ConfigSet(appID, config[:len(config)-1])
   214  }
   215  
   216  func parseConfig(configVars []string) map[string]interface{} {
   217  	configMap := make(map[string]interface{})
   218  
   219  	regex := regexp.MustCompile(`^([A-z_]+[A-z0-9_]*)=([\s\S]+)$`)
   220  	for _, config := range configVars {
   221  		if regex.MatchString(config) {
   222  			captures := regex.FindStringSubmatch(config)
   223  			configMap[captures[1]] = captures[2]
   224  		} else {
   225  			fmt.Printf("'%s' does not match the pattern 'key=var', ex: MODE=test\n", config)
   226  		}
   227  	}
   228  
   229  	return configMap
   230  }
   231  
   232  func formatConfig(configVars map[string]interface{}) string {
   233  	var formattedConfig string
   234  
   235  	for key, value := range configVars {
   236  		formattedConfig += fmt.Sprintf("%s=%s\n", key, value)
   237  	}
   238  
   239  	return formattedConfig
   240  }