github.com/TIBCOSoftware/flogo-lib@v0.5.9/app/config.go (about) 1 package app 2 3 import ( 4 "encoding/json" 5 "fmt" 6 7 "os" 8 9 "errors" 10 "io/ioutil" 11 "regexp" 12 "strings" 13 14 "github.com/TIBCOSoftware/flogo-lib/app/resource" 15 "github.com/TIBCOSoftware/flogo-lib/config" 16 "github.com/TIBCOSoftware/flogo-lib/core/action" 17 "github.com/TIBCOSoftware/flogo-lib/core/data" 18 "github.com/TIBCOSoftware/flogo-lib/core/trigger" 19 "github.com/TIBCOSoftware/flogo-lib/logger" 20 21 "github.com/TIBCOSoftware/flogo-lib/util" 22 ) 23 24 // Config is the configuration for the App 25 type Config struct { 26 Name string `json:"name"` 27 Type string `json:"type"` 28 Version string `json:"version"` 29 Description string `json:"description"` 30 31 Properties []*data.Attribute `json:"properties"` 32 Channels []string `json:"channels"` 33 Triggers []*trigger.Config `json:"triggers"` 34 Resources []*resource.Config `json:"resources"` 35 Actions []*action.Config `json:"actions"` 36 } 37 38 var appName, appVersion string 39 40 // Returns name of the application 41 func GetName() string { 42 return appName 43 } 44 45 // Returns version of the application 46 func GetVersion() string { 47 return appVersion 48 } 49 50 // defaultConfigProvider implementation of ConfigProvider 51 type defaultConfigProvider struct { 52 } 53 54 // ConfigProvider interface to implement to provide the app configuration 55 type ConfigProvider interface { 56 GetApp() (*Config, error) 57 } 58 59 // DefaultSerializer returns the default App Serializer 60 func DefaultConfigProvider() ConfigProvider { 61 return &defaultConfigProvider{} 62 } 63 64 // GetApp returns the app configuration 65 func (d *defaultConfigProvider) GetApp() (*Config, error) { 66 return LoadConfig("") 67 } 68 69 func LoadConfig(flogoJson string) (*Config, error) { 70 app := &Config{} 71 if flogoJson == "" { 72 configPath := config.GetFlogoConfigPath() 73 74 flogo, err := os.Open(configPath) 75 if err != nil { 76 return nil, err 77 } 78 79 file, err := ioutil.ReadAll(flogo) 80 if err != nil { 81 return nil, err 82 } 83 84 updated, err := preprocessConfig(file) 85 if err != nil { 86 return nil, err 87 } 88 89 err = json.Unmarshal(updated, &app) 90 if err != nil { 91 return nil, err 92 } 93 94 } else { 95 updated, err := preprocessConfig([]byte(flogoJson)) 96 if err != nil { 97 return nil, err 98 } 99 err = json.Unmarshal(updated, &app) 100 if err != nil { 101 return nil, err 102 } 103 } 104 appName = app.Name 105 appVersion = app.Version 106 return app, nil 107 } 108 109 func preprocessConfig(appJson []byte) ([]byte, error) { 110 111 // For now decode secret values 112 re := regexp.MustCompile("SECRET:[^\\\\\"]*") 113 for _, match := range re.FindAll(appJson, -1) { 114 decodedValue, err := resolveSecretValue(string(match)) 115 if err != nil { 116 return nil, err 117 } 118 appstring := strings.Replace(string(appJson), string(match), decodedValue, -1) 119 appJson = []byte(appstring) 120 } 121 122 return appJson, nil 123 } 124 125 func resolveSecretValue(encrypted string) (string, error) { 126 encodedValue := string(encrypted[7:]) 127 decodedValue, err := data.GetSecretValueHandler().DecodeValue(encodedValue) 128 if err != nil { 129 return "", err 130 } 131 return decodedValue, nil 132 } 133 134 func GetProperties(properties []*data.Attribute) (map[string]interface{}, error) { 135 136 props := make(map[string]interface{}) 137 if properties != nil { 138 overriddenProps, err := loadExternalProperties(properties) 139 if err != nil { 140 return props, err 141 } 142 for _, property := range properties { 143 pValue := property.Value() 144 if newValue, ok := overriddenProps[property.Name()]; ok { 145 pValue = newValue 146 } 147 value, err := data.CoerceToValue(pValue, property.Type()) 148 if err != nil { 149 return props, err 150 } 151 152 strVal, ok := value.(string) 153 if ok && strings.HasPrefix(strVal, "SECRET:") { 154 // Resolve secret value 155 newVal, err := resolveSecretValue(value.(string)) 156 if err != nil { 157 return nil, err 158 } 159 props[property.Name()] = newVal 160 } else { 161 props[property.Name()] = value 162 } 163 } 164 return props, nil 165 } 166 167 return props, nil 168 } 169 170 func loadExternalProperties(properties []*data.Attribute) (map[string]interface{}, error) { 171 172 props := make(map[string]interface{}) 173 propFile := config.GetAppPropertiesOverride() 174 if propFile != "" { 175 logger.Infof("'%s' is set. Loading overridden properties", config.ENV_APP_PROPERTY_OVERRIDE_KEY) 176 //TODO move to file resolver 177 if strings.HasSuffix(propFile, ".json") { 178 // Override through file 179 file, e := ioutil.ReadFile(propFile) 180 if e != nil { 181 return nil, e 182 } 183 e = json.Unmarshal(file, &props) 184 if e != nil { 185 return nil, e 186 } 187 } else if strings.ContainsRune(propFile, '=') { 188 // Override through P1=V1,P2=V2 189 overrideProps := util.ParseKeyValuePairs(propFile) 190 for k, v := range overrideProps { 191 props[k] = v 192 } 193 } 194 } 195 196 resolverType := config.GetAppPropertiesValueResolver() 197 if resolverType != "" { 198 logger.Infof("'%s' is set to '%s'. ", config.ENV_APP_PROPERTY_RESOLVER_KEY, resolverType) 199 200 var resolvers []PropertyValueResolver 201 for _, resName := range strings.Split(resolverType, ",") { 202 resolver := GetPropertyValueResolver(resName) 203 if resolver == nil { 204 errMag := fmt.Sprintf("Unsupported resolver type - %s. Resolver not registered.", resolverType) 205 return nil, errors.New(errMag) 206 } 207 resolvers = append(resolvers, resolver) 208 } 209 210 // Resolver is set. Get values using app prop name 211 for i, _ := range properties { 212 propName := properties[i].Name() 213 found := false 214 for i, _ := range resolvers { 215 // Use resolver 216 newVal, resolved := resolvers[i].LookupValue(propName) 217 if resolved { 218 props[propName] = newVal 219 found = true 220 break 221 } 222 } 223 if !found { 224 logger.Warnf("Property '%s' could not be resolved using resolver(s) '%s'. Using default value.", propName, resolverType) 225 } 226 } 227 } 228 229 return props, nil 230 } 231 232 //used for old action config 233 234 //func FixUpApp(cfg *Config) { 235 // 236 // if cfg.Resources != nil || cfg.Actions == nil { 237 // //already new app format 238 // return 239 // } 240 // 241 // idToAction := make(map[string]*action.Config) 242 // for _, act := range cfg.Actions { 243 // idToAction[act.Id] = act 244 // } 245 // 246 // for _, trg := range cfg.Triggers { 247 // for _, handler := range trg.Handlers { 248 // 249 // oldAction := idToAction[handler.ActionId] 250 // 251 // newAction := &action.Config{Ref: oldAction.Ref} 252 // 253 // if oldAction != nil { 254 // newAction.Mappings = oldAction.Mappings 255 // } else { 256 // if handler.ActionInputMappings != nil { 257 // newAction.Mappings = &data.IOMappings{} 258 // newAction.Mappings.Input = handler.ActionInputMappings 259 // newAction.Mappings.Output = handler.ActionOutputMappings 260 // } 261 // } 262 // 263 // newAction.Data = oldAction.Data 264 // newAction.Metadata = oldAction.Metadata 265 // 266 // handler.Action = newAction 267 // } 268 // } 269 // 270 // cfg.Actions = nil 271 //}