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  //}