func (gc *GlobalConfig) Parse(data map[interface{}]interface{}, config *entity.Config) (err error) { if config == nil { config = entity.NewConfig() } //Parse default section. defaultSection, ok := data["default"].(map[interface{}]interface{}) if ok { config.DefaultCredential.User, ok = defaultSection["user"].(string) config.DefaultCredential.Pass, ok = defaultSection["pass"].(string) config.DefaultCredential.Identity, ok = defaultSection["identity"].(string) } //Parse host section. hostSection, ok := data["host"].(map[interface{}]interface{}) if ok { var tmpCred *entity.Credential for hostName, _ := range hostSection { hostEntry, ok := hostSection[hostName.(string)].(map[interface{}]interface{}) if !ok { err = errors.New("Invalid host section entry. host name: " + hostName.(string)) return } tmpCred = entity.NewCredential() tmpCred.User, ok = hostEntry["user"].(string) tmpCred.Pass, ok = hostEntry["pass"].(string) tmpCred.Identity, ok = hostEntry["identity"].(string) config.Hosts[hostName.(string)] = tmpCred } } return }
// Parse data from given byte slices. func (c *Config) Parse(data []byte, conf *entity.Config) (err error) { var parseResult interface{} err = yaml.Unmarshal(data, &parseResult) if err != nil { return } if conf == nil { conf = entity.NewConfig() } // Get "input" section. inputSettingSection, ok := parseResult.(map[interface{}]interface{})["input"] if !ok { err = errors.New("'input' section not found.") return } inputSettingEntries, _ := inputSettingSection.(map[interface{}]interface{}) for name, entry := range inputSettingEntries { err = c.parseInputSectionEntry(conf, name.(string), entry.(map[interface{}]interface{})) if err != nil { return } } logSection, ok := parseResult.(map[interface{}]interface{})["log"].(map[interface{}]interface{}) if ok { err = c.parseLogSection(conf, logSection) if err != nil { return } } return }
func TestGetDefaultCrediential(t *testing.T) { config := entity.NewConfig() defaultCred := entity.NewCredential() defaultCred.User = "******" hostACred := entity.NewCredential() hostACred.User = "******" hostBCred := entity.NewCredential() hostBCred.User = "******" config.DefaultCredential = defaultCred config.Hosts["host-a"] = hostACred config.Hosts["host-b"] = hostBCred result := config.GetDefaultCredential("host-a") if result.User != "host-a-user" { t.Log("host-a user not matched.") t.Fail() } result = config.GetDefaultCredential("host-b") if result.User != "host-b-user" { t.Log("host-b user not matched.") t.Fail() } result = config.GetDefaultCredential("host-c") if result.User != "default-user" { t.Log("host-c user not matched.") t.Fail() } result = config.GetDefaultCredential("") if result.User != "default-user" { t.Log("empty host user not matched.") t.Fail() } }
func TestCreateEntitiesFromData(t *testing.T) { yamlString := []byte(`input: logA: type: ssh host: - 1.1.1.1 - 2.2.2.2 user: test pass: password command: abc logB: type: ssh host: 3.3.3.3 user: test2 pass: password2 command: abc `) var yamlData interface{} err := yaml.Unmarshal(yamlString, &yamlData) if err != nil { t.Log("Failed to parse yaml.") t.Fail() return } inputSection, ok := yamlData.(map[interface{}]interface{})["input"].(map[interface{}]interface{}) if !ok { t.Log("Failed to find input section.") t.Fail() return } var entries []entity.InputEntry var tempEntries []entity.InputEntry config := entity.NewConfig() inputEntryParser := extssh.NewInputEntryParser() for name, inputEntry := range inputSection { input, ok := inputEntry.(map[interface{}]interface{}) if !ok { t.Log("Failed to find input entry.") t.Fail() return } tempEntries, err = inputEntryParser.CreateInputEntriesFromData(config, name.(string), input) if err != nil { t.Log("Failed to parse input entry.") t.Fail() return } entries = append(entries, tempEntries...) } if len(entries) != 3 { t.Logf("Config entry count does not matched. expected: 3, actual: %d", len(entries)) t.Fail() return } expects := []map[string]string{ {"host": "1.1.1.1", "name": "logA", "user": "******"}, {"host": "2.2.2.2", "name": "logA", "user": "******"}, {"host": "3.3.3.3", "name": "logB", "user": "******"}, } for i, expected := range expects { entry := entries[i].(*extssh.InputEntry) if entry.Host != expected["host"] { t.Logf("Host is not expected. index=%d: value=%s", i, entry.Host) t.Fail() } if entry.Name != expected["name"] { t.Logf("Log name is not expected. index=%d: value=%s", i, entry.Name) t.Fail() } if entry.Cred.User != expected["user"] { t.Logf("user is not expected. index=%d: value=%s", i, entry.Cred.User) t.Fail() } } }
func TestParse(t *testing.T) { extensionManager := lib.NewExtensionManager() extensionManager.RegisterExtensionPoint(ext.POINT_INPUT_CONFIG_PARSER, extssh.NewInputEntryParser()) cs := service.NewConfig(extensionManager) yaml := []byte(` input: test01: type: ssh host: - example.com - example02.com user: user_name identity: identity-file-name command: testtest log: logging: true path: /tmp/test.log `) conf := entity.NewConfig() err := cs.Parse(yaml, conf) if err != nil { t.Logf(err.Error()) t.Fail() } if len(conf.InputEntries) != 2 { t.Logf("input handler count. expected: 1, actual: %d", len(conf.InputEntries)) t.Fail() } inputSsh := conf.InputEntries[0].(*extssh.InputEntry) if inputSsh.Name != "test01" { t.Logf("input handler name not matched. expected: test01, actual: %s", inputSsh.Name) t.Fail() } if inputSsh.Host != "example.com" { t.Logf("host name not matched. expected: example.com, actual: %s", inputSsh.Host) t.Fail() } inputSsh2 := conf.InputEntries[1].(*extssh.InputEntry) if inputSsh2.Name != "test01" { t.Logf("input handler name not matched. expected: test01, actual: %s", inputSsh2.Name) t.Fail() } if inputSsh2.Host != "example02.com" { t.Logf("host name not matched. expected: example02.com, actual: %s", inputSsh2.Host) t.Fail() } if conf.Logging != true { t.Logf("Logging not enabled.") t.Fail() } if conf.LogPath != "/tmp/test.log" { t.Logf("LogPath not matched. actual: " + conf.LogPath) t.Fail() } }
// This function is application main procedure. // Open input handlers and read them output until all input handler ends. func (a *Application) mainCommand(options *StartupOptions) { var err error a.config = entity.NewConfig() err = a.loadConfig(options.ConfigFile, a.config) if err != nil { log.Println(err.Error()) return } //Prepare logging if needed. if a.config.Logging { err = a.initLogging(a.config.LogPath) if err != nil { log.Println(err.Error()) return } } //Create output channel. //All input handler communicate with this channel. outputData := make(chan entity.InputData, 0) //Initialize input handlers. inputHandlers := make(map[string]ext.InputHandler) endFlagList := make(map[string]bool) for _, inputEntry := range a.config.InputEntries { inputHandlerFactory, found := a.extensionManager.GetExtensionPoint(ext.POINT_INPUT_HANDLER_FACTORY, inputEntry.GetType()) if !found { panic(fmt.Sprintf("invalid input handler: %s", inputEntry.GetType())) } inputHandler := inputHandlerFactory.(ext.InputHandlerFactory).NewInputHandler(inputEntry) inputHandlers[inputHandler.GetName()] = inputHandler } //Start listen. //Handler runs asynchronously in goroutine. for name, ih := range inputHandlers { go ih.ReadInput(outputData) endFlagList[name] = false } //Wait outputData channel receive a data. //This loop continues until all input handler exits. var inputData entity.InputData allEndFlag := false for { inputData = <-outputData if inputData.State == entity.INPUT_DATA_END { endFlagList[inputData.Name] = true } allEndFlag = true for _, isEnd := range endFlagList { if !isEnd { allEndFlag = false } } if allEndFlag { log.Println("all handler stopped correctly.") break } //Output read data line by line. a.outputLines(inputData.Name, inputData.Data) } }
func TestGlobalConfigParse(t *testing.T) { globalConfigService := service.NewGlobalConfig() yamlData := []byte(`default: user: default-user pass: default-pass identity: default-identity host: host-a: user: host-a-user pass: host-a-pass identity: host-a-identity host-b: user: host-b-user pass: host-b-pass identity: host-b-identity `) var data map[interface{}]interface{} data = make(map[interface{}]interface{}) err := yaml.Unmarshal(yamlData, data) if err != nil { t.Log(err.Error()) t.Fail() return } config := entity.NewConfig() err = globalConfigService.Parse(data, config) if err != nil { t.Log(err.Error()) t.Fail() return } if config.DefaultCredential.User != "default-user" { t.Log("DefaultCredential.User not matched.") t.Logf("%#v", config.DefaultCredential) t.Fail() } if config.DefaultCredential.Pass != "default-pass" { t.Log("DefaultCredential.Pass not matched.") t.Fail() } if config.DefaultCredential.Identity != "default-identity" { t.Log("DefaultCredential.Identity not matched.") t.Fail() } hosts := map[string]map[string]string{ "host-a": {"user": "******", "pass": "******", "identity": "host-a-identity"}, "host-b": {"user": "******", "pass": "******", "identity": "host-b-identity"}, } for hostName, host := range hosts { hostCredential := config.Hosts[hostName] if config.Hosts[hostName].User != host["user"] { t.Logf("host '%s': user does not matched.", hostCredential.User) t.Fail() return } if config.Hosts[hostName].Pass != host["pass"] { t.Logf("host '%s': pass does not matched.", hostCredential.Pass) t.Fail() return } if config.Hosts[hostName].Identity != host["identity"] { t.Logf("host '%s': identity does not matched.", hostCredential.Identity) t.Fail() return } } }