Skip to content

Commit

Permalink
Merge pull request #9 from reactiveops/rs/better-config-parsing
Browse files Browse the repository at this point in the history
Improved config parsing, removing Viper
  • Loading branch information
JessicaGreben authored Dec 31, 2018
2 parents ff7c459 + 58b0497 commit 02cee12
Show file tree
Hide file tree
Showing 145 changed files with 185 additions and 24,692 deletions.
88 changes: 1 addition & 87 deletions Gopkg.lock

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

17 changes: 3 additions & 14 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ package main

import (
"flag"
"fmt"
"os"

conf "github.com/reactiveops/fairwinds/pkg/config"
"github.com/reactiveops/fairwinds/pkg/validator"
"github.com/spf13/viper"
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
corev1 "k8s.io/api/core/v1"
apitypes "k8s.io/apimachinery/pkg/types"
Expand All @@ -47,20 +45,11 @@ func main() {
logf.SetLogger(logf.ZapLogger(false))
entryLog := log.WithName("entrypoint")

// Parse config.
viper.SetConfigName("config")
viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil {
entryLog.Error(err, "config err")
}

var c conf.Configuration
if err := viper.Unmarshal(&c); err != nil {
entryLog.Error(err, "unmarshal config err")
c, err := conf.ParseFile("config.yml")
if err != nil {
entryLog.Error(err, "parse config err")
}

entryLog.Info(fmt.Sprintf("conf: %#v", c))

// Setup a Manager
entryLog.Info("setting up manager")
mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{})
Expand Down
34 changes: 32 additions & 2 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package config

import (
"bytes"
"fmt"
"io"
"io/ioutil"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/yaml"
)

type ResourceMinMax struct {
Min string
Max string
Min *resource.Quantity
Max *resource.Quantity
}

type ResourceList map[corev1.ResourceName]ResourceMinMax
Expand All @@ -19,3 +25,27 @@ type RequestsAndLimits struct {
type Configuration struct {
Resources RequestsAndLimits
}

// ParseFile parses config from a file
func ParseFile(path string) (Configuration, error) {
rawBytes, err := ioutil.ReadFile(path)
if err != nil {
return Configuration{}, err
}
return Parse(rawBytes)
}

// Parse parses config from a byte array
func Parse(rawBytes []byte) (Configuration, error) {
reader := bytes.NewReader(rawBytes)
conf := Configuration{}
d := yaml.NewYAMLOrJSONDecoder(reader, 4096)
for {
if err := d.Decode(&conf); err != nil {
if err == io.EOF {
return conf, nil
}
return Configuration{}, fmt.Errorf("Decoding config failed: %v", err)
}
}
}
106 changes: 106 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2018 ReactiveOps
//
// 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"

"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/api/resource"
)

var resourceConfInvalid1 = `test`

var resourceConfYaml1 = `---
resources:
requests:
cpu:
min: 100m
max: 1
memory:
min: 100M
max: 3G
limits:
cpu:
min: 150m
max: 2
memory:
min: 150M
max: 4G
`

var resourceConfJson1 = `{
"resources": {
"requests": {
"cpu": {
"min": "100m",
"max": "1"
},
"memory": {
"min": "100M",
"max": "3G"
}
},
"limits": {
"cpu": {
"min": "150m",
"max": "2"
},
"memory": {
"min": "150M",
"max": "4G"
}
}
}
}`

func TestParseError(t *testing.T) {
_, err := Parse([]byte(resourceConfInvalid1))
assert.EqualError(t, err, "Decoding config failed: error unmarshaling JSON: json: cannot unmarshal string into Go value of type config.Configuration")
}

func TestParseYaml(t *testing.T) {
parsedConf, err := Parse([]byte(resourceConfYaml1))
assert.NoError(t, err, "Expected no error when parsing config")

requests := parsedConf.Resources.Requests
assert.Equal(t, int64(100), requests["cpu"].Min.ScaledValue(resource.Milli))
assert.Equal(t, int64(1000), requests["cpu"].Max.ScaledValue(resource.Milli))
assert.Equal(t, int64(100), requests["memory"].Min.ScaledValue(resource.Mega))
assert.Equal(t, int64(3000), requests["memory"].Max.ScaledValue(resource.Mega))

limits := parsedConf.Resources.Limits
assert.Equal(t, int64(150), limits["cpu"].Min.ScaledValue(resource.Milli))
assert.Equal(t, int64(2000), limits["cpu"].Max.ScaledValue(resource.Milli))
assert.Equal(t, int64(150), limits["memory"].Min.ScaledValue(resource.Mega))
assert.Equal(t, int64(4000), limits["memory"].Max.ScaledValue(resource.Mega))
}

func TestParseJson(t *testing.T) {
parsedConf, err := Parse([]byte(resourceConfJson1))
assert.NoError(t, err, "Expected no error when parsing config")

requests := parsedConf.Resources.Requests
assert.Equal(t, int64(100), requests["cpu"].Min.ScaledValue(resource.Milli))
assert.Equal(t, int64(1000), requests["cpu"].Max.ScaledValue(resource.Milli))
assert.Equal(t, int64(100), requests["memory"].Min.ScaledValue(resource.Mega))
assert.Equal(t, int64(3000), requests["memory"].Max.ScaledValue(resource.Mega))

limits := parsedConf.Resources.Limits
assert.Equal(t, int64(150), limits["cpu"].Min.ScaledValue(resource.Milli))
assert.Equal(t, int64(2000), limits["cpu"].Max.ScaledValue(resource.Milli))
assert.Equal(t, int64(150), limits["memory"].Min.ScaledValue(resource.Mega))
assert.Equal(t, int64(4000), limits["memory"].Max.ScaledValue(resource.Mega))
}
16 changes: 4 additions & 12 deletions pkg/validator/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
package validator

import (
"fmt"

conf "github.com/reactiveops/fairwinds/pkg/config"
"github.com/reactiveops/fairwinds/pkg/types"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -58,17 +56,11 @@ func (cv *ContainerValidation) validateResources(conf conf.RequestsAndLimits) {
}

func (cv *ContainerValidation) withinRange(resourceName string, expectedRange conf.ResourceMinMax, actual *resource.Quantity) {
expectedMin, err := resource.ParseQuantity(expectedRange.Min)
if err != nil {
log.Error(err, fmt.Sprintf("Error parsing min quantity for %s", resourceName))
} else if expectedMin.MilliValue() > actual.MilliValue() {
expectedMin := expectedRange.Min
expectedMax := expectedRange.Max
if expectedMin != nil && expectedMin.MilliValue() > actual.MilliValue() {
cv.addFailure(resourceName, expectedMin.String(), actual.String())
}

expectedMax, err := resource.ParseQuantity(expectedRange.Max)
if err != nil {
log.Error(err, fmt.Sprintf("Error parsing max quantity for %s", resourceName))
} else if expectedMax.MilliValue() < actual.MilliValue() {
} else if expectedMax != nil && expectedMax.MilliValue() < actual.MilliValue() {
cv.addFailure(resourceName, expectedMax.String(), actual.String())
}
}
Expand Down
Loading

0 comments on commit 02cee12

Please sign in to comment.