Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add loading configuration from file. #7

Merged
merged 2 commits into from
Jul 27, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions config/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# 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.

all: generated/config.pb.go

generated/config.pb.go: config.proto
protoc --go_out=generated/ config.proto
69 changes: 69 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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"
"time"

"code.google.com/p/goprotobuf/proto"

pb "github.com/prometheus/alert_manager/config/generated"

"github.com/prometheus/alert_manager/manager"
)

// Config encapsulates the configuration of an Alert Manager instance. It wraps
// the raw configuration protocol buffer to be able to add custom methods to
// it.
type Config struct {
// The protobuf containing the actual configuration values.
pb.AlertManagerConfig
}

// String returns an ASCII serialization of the loaded configuration protobuf.
func (c Config) String() string {
return proto.MarshalTextString(&c.AlertManagerConfig)
}

// Validate checks an entire parsed Config for the validity of its fields.
func (c Config) Validate() error {
for _, a := range c.AggregationRule {
for _, f := range a.Filter {
if f.NameRe == nil {
return fmt.Errorf("Missing name pattern (name_re) in filter definition: %s", proto.MarshalTextString(f))
}
if f.ValueRe == nil {
return fmt.Errorf("Missing value pattern (value_re) in filter definition: %s", proto.MarshalTextString(f))
}
}
}
return nil
}

// Rules returns all the AggregationRules in a Config object.
func (c Config) AggregationRules() manager.AggregationRules {
rules := make(manager.AggregationRules, 0, len(c.AggregationRule))
for _, r := range c.AggregationRule {
filters := make(manager.Filters, 0, len(r.Filter))
for _, filter := range r.Filter {
filters = append(filters, manager.NewFilter(filter.GetNameRe(), filter.GetValueRe()))
}
rules = append(rules, &manager.AggregationRule{
Filters: filters,
RepeatRate: time.Duration(r.GetRepeatRateSeconds()) * time.Second,
})
}
return rules
}
31 changes: 31 additions & 0 deletions config/config.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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 io.prometheus.alert_manager;

// A regex-based label filter used in aggregations.
message Filter {
// The regex matching the label name.
optional string name_re = 1;
// The regex matching the label value.
optional string value_re = 2;
}

message AggregationRule {
repeated Filter filter = 1;
optional int32 repeat_rate_seconds = 2 [default = 7200];
}

message AlertManagerConfig {
repeated AggregationRule aggregation_rule = 1;
}
64 changes: 64 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// 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 (
"path"
"strings"
"testing"
)

var fixturesPath = "fixtures"

type configTest struct {
inputFile string
shouldFail bool
errContains string
}

func (ct *configTest) test(i int, t *testing.T) {
_, err := LoadFromFile(path.Join(fixturesPath, ct.inputFile))

if err != nil {
if !ct.shouldFail {
t.Fatalf("%d. Error parsing config %v: %v", i, ct.inputFile, err)
} else {
if !strings.Contains(err.Error(), ct.errContains) {
t.Fatalf("%d. Expected error containing '%v', got: %v", i, ct.errContains, err)
}
}
}
}

func TestConfigs(t *testing.T) {
var configTests = []configTest{
{
inputFile: "empty.conf.input",
}, {
inputFile: "sample.conf.input",
}, {
inputFile: "missing_name_re.conf.input",
shouldFail: true,
errContains: "Missing name pattern",
}, {
inputFile: "invalid_proto_format.conf.input",
shouldFail: true,
errContains: "unknown field name",
},
}

for i, ct := range configTests {
ct.test(i, t)
}
}
Empty file.
18 changes: 18 additions & 0 deletions config/fixtures/invalid_proto_format.conf.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
aggregation_rule {
filter {
label_re: "service" // Unknown protobuf field name.
value_re: "discovery"
}
filter {
name_re: "zone"
value_re: "aa"
}
repeat_rate: 3600
}

aggregation_rule {
filter {
name_re: "service"
value_re: "test"
}
}
18 changes: 18 additions & 0 deletions config/fixtures/sample.conf.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
aggregation_rule {
filter {
name_re: "service"
value_re: "discovery"
}
filter {
name_re: "zone"
value_re: "aa"
}
repeat_rate_seconds: 3600
}

aggregation_rule {
filter {
name_re: "service"
value_re: "test"
}
}
83 changes: 83 additions & 0 deletions config/generated/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions config/load.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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 (
"io/ioutil"

"code.google.com/p/goprotobuf/proto"

pb "github.com/prometheus/alert_manager/config/generated"
)

func LoadFromString(configStr string) (Config, error) {
configProto := pb.AlertManagerConfig{}
if err := proto.UnmarshalText(configStr, &configProto); err != nil {
return Config{}, err
}

config := Config{AlertManagerConfig: configProto}
err := config.Validate()

return config, err
}

func LoadFromFile(fileName string) (Config, error) {
configStr, err := ioutil.ReadFile(fileName)
if err != nil {
return Config{}, err
}

return LoadFromString(string(configStr))
}
25 changes: 25 additions & 0 deletions config/load_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// 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 (
"testing"
)

func TestLoadFromFile(t *testing.T) {
_, err := LoadFromFile("file-does-not-exist.conf")
if err == nil {
t.Error(err)
}
}
Loading