Skip to content

Commit

Permalink
Normalize path-config key
Browse files Browse the repository at this point in the history
  • Loading branch information
tatsuhiro-t committed Nov 12, 2018
1 parent a1dfedf commit 6e46aaa
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 4 deletions.
9 changes: 5 additions & 4 deletions README.md
Expand Up @@ -351,11 +351,12 @@ nghttpx-ingress-controller understands
`ingress.zlab.co.jp/path-config` key in Ingress
`.metadata.annotations` to allow additional configuration per host and
path pattern. Its value is a serialized YAML or JSON dictionary. The
configuration is done per host and port pattern. The key under the
root dictionary is the concatenation of host and port. For example,
configuration is done per host and path pattern. The key under the
root dictionary is the concatenation of host and path. For example,
if host is "www.example.com" and path is "/foo", its key is
"www.example.com/foo". Its value is the dictionary and can contain
the following key value pairs:
"www.example.com/foo". For convenience, if "www.example.com" is
specified as a key, it is normalized as "www.example.com/". Its value
is the dictionary and can contain the following key value pairs:

* `mruby`: Specify mruby script which is invoked when the given
pattern is selected. For mruby script, see [nghttpx manual
Expand Down
21 changes: 21 additions & 0 deletions pkg/controller/annotation.go
Expand Up @@ -11,6 +11,7 @@ package controller
import (
"encoding/json"
"fmt"
"strings"

"github.com/ghodss/yaml"
"github.com/golang/glog"
Expand Down Expand Up @@ -87,6 +88,8 @@ func (ia ingressAnnotation) getPathConfig() (*nghttpx.PathConfig, map[string]*ng
}
}

config = normalizePathKey(config)

for _, v := range config {
nghttpx.FixupPathConfig(v)
}
Expand All @@ -111,6 +114,24 @@ func (ia ingressAnnotation) getPathConfig() (*nghttpx.PathConfig, map[string]*ng
return &defaultConfig, config
}

// normalizePathKey prepends "/" if key does not contain "/".
func normalizePathKey(src map[string]*nghttpx.PathConfig) map[string]*nghttpx.PathConfig {
if len(src) == 0 {
return src
}

dst := make(map[string]*nghttpx.PathConfig)
for k, v := range src {
if strings.Index(k, "/") == -1 {
dst[k+"/"] = v
} else {
dst[k] = v
}
}

return dst
}

// unmarshal deserializes data into dest. This function first tries yaml and then JSON.
func unmarshal(data []byte, dest interface{}) error {
if err := yaml.Unmarshal(data, dest); err != nil {
Expand Down
75 changes: 75 additions & 0 deletions pkg/controller/annotation_test.go
Expand Up @@ -3,6 +3,9 @@ package controller
import (
"reflect"
"testing"
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/zlabjp/nghttpx-ingress-lb/pkg/nghttpx"
)
Expand Down Expand Up @@ -91,3 +94,75 @@ svc:
}
}
}

// TestGetPathConfig verifies getPathConfig.
func TestGetPathConfig(t *testing.T) {
d120 := metav1.Duration{120 * time.Second}
rb := "rb"
tests := []struct {
annotationDefaultConfig string
annotationConfig string
wantDefaultConfig *nghttpx.PathConfig
wantConfig map[string]*nghttpx.PathConfig
}{
// 0
{
annotationConfig: `{"example.com/alpha": {"readTimeout": "120s"}}`,
wantConfig: map[string]*nghttpx.PathConfig{
"example.com/alpha": &nghttpx.PathConfig{
ReadTimeout: &d120,
},
},
},
// 1
{
annotationDefaultConfig: `{"mruby": "rb"}`,
annotationConfig: `{"example.com/alpha": {"readTimeout": "120s"}}`,
wantDefaultConfig: &nghttpx.PathConfig{
Mruby: &rb,
},
wantConfig: map[string]*nghttpx.PathConfig{
"example.com/alpha": &nghttpx.PathConfig{
ReadTimeout: &d120,
Mruby: &rb,
},
},
},
// 3
{
annotationConfig: `
example.com/alpha:
readTimeout: 120s
`,
wantConfig: map[string]*nghttpx.PathConfig{
"example.com/alpha": &nghttpx.PathConfig{
ReadTimeout: &d120,
},
},
},
// 4
{
annotationConfig: `{"example.com": {"readTimeout": "120s"}}`,
wantConfig: map[string]*nghttpx.PathConfig{
"example.com/": &nghttpx.PathConfig{
ReadTimeout: &d120,
},
},
},
}

for i, tt := range tests {
ann := ingressAnnotation(map[string]string{
defaultPathConfigKey: tt.annotationDefaultConfig,
pathConfigKey: tt.annotationConfig,
})
defaultConfig, config := ann.getPathConfig()

if !reflect.DeepEqual(defaultConfig, tt.wantDefaultConfig) {
t.Errorf("#%v: defaultConfig = %+v, want %+v", i, defaultConfig, tt.wantDefaultConfig)
}
if !reflect.DeepEqual(config, tt.wantConfig) {
t.Errorf("#%v: config = %+v, want %+v", i, config, tt.wantConfig)
}
}
}

0 comments on commit 6e46aaa

Please sign in to comment.