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 }