Config tests and config cleanups+fixes.

This commit is contained in:
Julius Volz 2013-02-14 01:04:07 +01:00
parent 23374788d3
commit d137362257
6 changed files with 186 additions and 12 deletions

86
config/config_test.go Normal file
View file

@ -0,0 +1,86 @@
// Copyright 2013 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"fmt"
"io/ioutil"
"path"
"strings"
"testing"
)
var fixturesPath = "fixtures"
var configTests = []struct {
inputFile string
printedFile string
shouldFail bool
errContains string
}{
{
inputFile: "minimal.conf",
printedFile: "minimal.conf.printed",
}, {
inputFile: "sample.conf",
printedFile: "sample.conf.printed",
}, {
// TODO: Options that are not provided should be set to sane defaults or
// create errors during config loading (as appropriate). Right now, these
// options remain at their zero-values, which is probably not what we want.
inputFile: "empty.conf",
printedFile: "empty.conf.printed",
},
// TODO: To enable testing of bad configs, we first need to change config
// loading so that it doesn't exit when loading a bad config. Instead, the
// configuration error should be passed back all the way to the caller.
//
//{
// inputFile: "bad_job_option.conf",
// shouldFail: true,
// errContains: "Missing job name",
//},
}
func TestConfigs(t *testing.T) {
for _, configTest := range configTests {
testConfig, err := LoadFromFile(path.Join(fixturesPath, configTest.inputFile))
if err != nil {
if !configTest.shouldFail {
t.Errorf("Error parsing config %v: %v", configTest.inputFile, err)
} else {
if !strings.Contains(err.Error(), configTest.errContains) {
t.Errorf("Expected error containing '%v', got: %v", configTest.errContains, err)
}
}
} else {
printedConfig, err := ioutil.ReadFile(path.Join(fixturesPath, configTest.printedFile))
if err != nil {
t.Errorf("Error reading config %v: %v", configTest.inputFile, err)
continue
}
expected := string(printedConfig)
actual := testConfig.ToString(0)
if actual != expected {
t.Errorf("%v: printed config doesn't match expected output", configTest.inputFile)
t.Errorf("Expected:\n%v\n\nActual:\n%v\n", expected, actual)
t.Errorf("Writing expected and actual printed configs to /tmp for diffing (see test source for paths)")
ioutil.WriteFile(fmt.Sprintf("/tmp/%s.expected", configTest.printedFile), []byte(expected), 0600)
ioutil.WriteFile(fmt.Sprintf("/tmp/%s.actual", configTest.printedFile), []byte(actual), 0600)
}
}
}
}

View file

@ -0,0 +1,8 @@
global {
scrape_interval = "0y"
evaluation_interval = "0y"
rule_files = [
]
}

View file

@ -0,0 +1,20 @@
global {
scrape_interval = "30s"
evaluation_interval = "30s"
labels {
monitor = "test"
}
rule_files = [
"prometheus.rules"
]
}
job {
name = "prometheus"
scrape_interval = "15s"
targets {
endpoints = [
"http://localhost:9090/metrics.json"
]
}
}

View file

@ -0,0 +1,49 @@
global {
scrape_interval = "30s"
evaluation_interval = "30s"
labels {
monitor = "test"
}
rule_files = [
"prometheus.rules"
]
}
job {
name = "prometheus"
scrape_interval = "15s"
targets {
endpoints = [
"http://localhost:9090/metrics.json"
]
labels {
group = "canary"
}
}
}
job {
name = "random"
scrape_interval = "30s"
targets {
endpoints = [
"http://random.com:8080/metrics.json",
"http://random.com:8081/metrics.json",
"http://random.com:8082/metrics.json",
"http://random.com:8083/metrics.json",
"http://random.com:8084/metrics.json"
]
labels {
group = "production"
}
}
targets {
endpoints = [
"http://random.com:8085/metrics.json",
"http://random.com:8086/metrics.json"
]
labels {
group = "canary"
}
}
}

View file

@ -27,7 +27,7 @@ import (
var yylval *yySymType // For storing extra token information, like the contents of a string.
var yyline int // Line number within the current file or buffer.
var yypos int // Character position within the current line.
var parsedConfig = New() // Temporary variable for storing the parsed configuration.
var parsedConfig *Config // Temporary variable for storing the parsed configuration.
type ConfigLexer struct {
errors []string
@ -45,6 +45,7 @@ func (lexer *ConfigLexer) Error(errorStr string) {
}
func LoadFromReader(configReader io.Reader) (*Config, error) {
parsedConfig = New()
yyin = configReader
yypos = 1
yyline = 1

View file

@ -34,29 +34,39 @@ func (config *Config) ToString(indent int) string {
for _, job := range config.Jobs {
jobs = append(jobs, job.ToString(indent))
}
return indentStr(indent, "%v\n%v\n", global, strings.Join(jobs, "\n"))
return indentStr(indent, "%v\n%v", global, strings.Join(jobs, "\n"))
}
func labelsToString(indent int, labels model.LabelSet) string {
str := indentStr(indent, "labels {\n")
labelStrings := []string{}
for label, value := range labels {
str += indentStr(indent+1, "%v = \"%v\",\n", label, value)
labelStrings = append(labelStrings, indentStr(indent+1, "%v = \"%v\"", label, value))
}
str += strings.Join(labelStrings, ",\n") + "\n"
str += indentStr(indent, "}\n")
return str
}
func stringListToString(indent int, list []string) string {
listString := []string{}
for _, item := range list {
listString = append(listString, indentStr(indent, "\"%v\"", item))
}
return strings.Join(listString, ",\n") + "\n"
}
func (global *GlobalConfig) ToString(indent int) string {
str := indentStr(indent, "global {\n")
str += indentStr(indent+1, "scrape_interval = \"%s\"\n", utility.DurationToString(global.ScrapeInterval))
str += indentStr(indent+1, "evaluation_interval = \"%s\"\n", utility.DurationToString(global.EvaluationInterval))
if len(global.Labels) > 0 {
str += labelsToString(indent+1, global.Labels)
str += indentStr(indent, "}\n")
str += indentStr(indent+1, "rule_files = [\n")
for _, ruleFile := range global.RuleFiles {
str += indentStr(indent+2, "\"%v\",\n", ruleFile)
}
str += indentStr(indent+1, "rule_files = [\n")
str += stringListToString(indent+2, global.RuleFiles)
str += indentStr(indent+1, "]\n")
str += indentStr(indent, "}\n")
return str
}
@ -67,11 +77,11 @@ func (job *JobConfig) ToString(indent int) string {
for _, targets := range job.Targets {
str += indentStr(indent+1, "targets {\n")
str += indentStr(indent+2, "endpoints = [\n")
for _, endpoint := range targets.Endpoints {
str += indentStr(indent+3, "\"%v\",\n", endpoint)
}
str += stringListToString(indent+3, targets.Endpoints)
str += indentStr(indent+2, "]\n")
if len(targets.Labels) > 0 {
str += labelsToString(indent+2, targets.Labels)
}
str += indentStr(indent+1, "}\n")
}
str += indentStr(indent, "}\n")