github.com/jcarley/cli@v0.0.0-20180201210820-966d90434c30/commands/vars/set.go (about)

     1  package vars
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"regexp"
    10  	"strings"
    11  
    12  	yaml "gopkg.in/yaml.v2"
    13  
    14  	"github.com/Sirupsen/logrus"
    15  	"github.com/daticahealth/cli/commands/services"
    16  )
    17  
    18  func CmdSet(svcName string, variables []string, fileName string, iv IVars, is services.IServices) error {
    19  	var envVarsMap map[string]string
    20  	var err error
    21  	if fileName != "" {
    22  		if _, err = os.Stat(fileName); err != nil {
    23  			return fmt.Errorf("A file does not exist at path '%s'", fileName)
    24  		}
    25  		fileData, err := ioutil.ReadFile(fileName)
    26  		if err != nil {
    27  			return err
    28  		}
    29  		envVarsMap, err = parseFileData(fileData)
    30  		if err != nil {
    31  			return err
    32  		}
    33  	} else {
    34  		envVarsMap, err = parseKeyValue(variables)
    35  		if err != nil {
    36  			return err
    37  		}
    38  	}
    39  
    40  	service, err := is.RetrieveByLabel(svcName)
    41  	if err != nil {
    42  		return err
    43  	}
    44  	if service == nil {
    45  		return fmt.Errorf("Could not find a service with the label \"%s\". You can list services with the \"datica services list\" command.", svcName)
    46  	}
    47  
    48  	err = iv.Set(service.ID, envVarsMap)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	logrus.Printf("Set. For these environment variables to take effect, you will need to redeploy your service with \"datica redeploy %s\"", svcName)
    53  	return nil
    54  }
    55  
    56  func parseFileData(fileData []byte) (map[string]string, error) {
    57  	envVarsMap, err := parseYAML(fileData)
    58  	if err != nil {
    59  		envVarsMap, err = parseJSON(fileData)
    60  		if err != nil {
    61  			variables := strings.Split(string(fileData), "\n")
    62  			envVarsMap, err = parseKeyValue(variables)
    63  			if err != nil {
    64  				return nil, errors.New("Invalid file format. Specified file must be contain key-value pairs in YAML, JSON, or KEY=VALUE format.")
    65  			}
    66  		}
    67  	}
    68  	return envVarsMap, nil
    69  }
    70  
    71  func parseYAML(fileData []byte) (map[string]string, error) {
    72  	data := map[string]string{}
    73  	err := yaml.Unmarshal(fileData, &data)
    74  	return data, err
    75  }
    76  
    77  func parseJSON(fileData []byte) (map[string]string, error) {
    78  	data := map[string]string{}
    79  	err := json.Unmarshal(fileData, &data)
    80  	return data, err
    81  }
    82  
    83  func parseKeyValue(variables []string) (map[string]string, error) {
    84  	data := map[string]string{}
    85  	r := regexp.MustCompile("^[a-zA-Z_]+[a-zA-Z0-9_]*$")
    86  	for _, envVar := range variables {
    87  		if len(envVar) == 0 {
    88  			continue
    89  		}
    90  		pieces := strings.SplitN(envVar, "=", 2)
    91  		if len(pieces) != 2 {
    92  			return nil, fmt.Errorf("Invalid variable format. Expected <key>=<value> but got %s", envVar)
    93  		}
    94  		name, value := pieces[0], pieces[1]
    95  		if !r.MatchString(name) {
    96  			return nil, fmt.Errorf("Invalid environment variable name '%s'. Environment variable names must only contain letters, numbers, and underscores and must not start with a number.", name)
    97  		}
    98  		data[name] = value
    99  	}
   100  	return data, nil
   101  }
   102  
   103  // Set adds a new environment variables or updates the value of an existing
   104  // environment variables. Any changes to environment variables will not take
   105  // effect until the service is redeployed by pushing new code or via
   106  // `datica redeploy`.
   107  func (v *SVars) Set(svcID string, envVarsMap map[string]string) error {
   108  	b, err := json.Marshal(envVarsMap)
   109  	if err != nil {
   110  		return err
   111  	}
   112  	headers := v.Settings.HTTPManager.GetHeaders(v.Settings.SessionToken, v.Settings.Version, v.Settings.Pod, v.Settings.UsersID)
   113  	resp, statusCode, err := v.Settings.HTTPManager.Post(b, fmt.Sprintf("%s%s/environments/%s/services/%s/env", v.Settings.PaasHost, v.Settings.PaasHostVersion, v.Settings.EnvironmentID, svcID), headers)
   114  	if err != nil {
   115  		return err
   116  	}
   117  	return v.Settings.HTTPManager.ConvertResp(resp, statusCode, nil)
   118  }