diff --git a/lib/backend/model/keys.go b/lib/backend/model/keys.go index 4fce79e5d..a2bdd705c 100644 --- a/lib/backend/model/keys.go +++ b/lib/backend/model/keys.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -167,24 +167,24 @@ func KeyFromDefaultPath(path string) Key { log.Debugf("Path is a workload endpoint: %v", path) return WorkloadEndpointKey{ Hostname: m[1], - OrchestratorID: m[2], - WorkloadID: m[3], - EndpointID: m[4], + OrchestratorID: unescapeName(m[2]), + WorkloadID: unescapeName(m[3]), + EndpointID: unescapeName(m[4]), } } else if m := matchHostEndpoint.FindStringSubmatch(path); m != nil { log.Debugf("Path is a host endpoint: %v", path) return HostEndpointKey{ Hostname: m[1], - EndpointID: m[2], + EndpointID: unescapeName(m[2]), } } else if m := matchPolicy.FindStringSubmatch(path); m != nil { log.Debugf("Path is a policy: %v", path) return PolicyKey{ - Name: m[2], + Name: unescapeName(m[2]), } } else if m := matchProfile.FindStringSubmatch(path); m != nil { log.Debugf("Path is a profile: %v (%v)", path, m[2]) - pk := ProfileKey{m[1]} + pk := ProfileKey{unescapeName(m[1])} switch m[2] { case "tags": log.Debugf("Profile tags") diff --git a/lib/backend/model/keys_test.go b/lib/backend/model/keys_test.go new file mode 100644 index 000000000..2c5d7f161 --- /dev/null +++ b/lib/backend/model/keys_test.go @@ -0,0 +1,105 @@ +// Copyright (c) 2017 Tigera, Inc. All rights reserved. + +// 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 model_test + +import ( + . "github.com/projectcalico/libcalico-go/lib/backend/model" + + . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/gomega" + "github.com/projectcalico/libcalico-go/lib/net" +) + +var _ = DescribeTable( + "key parsing", + func(strKey string, expected Key) { + key := KeyFromDefaultPath(strKey) + Expect(key).To(Equal(expected)) + serialized, err := KeyToDefaultPath(expected) + Expect(err).ToNot(HaveOccurred()) + Expect(serialized).To(Equal(strKey)) + }, + Entry( + "profile rules with a /", + "/calico/v1/policy/profile/foo%2fbar/rules", + ProfileRulesKey{ProfileKey: ProfileKey{Name: "foo/bar"}}, + ), + Entry( + "profile tags with a /", + "/calico/v1/policy/profile/foo%2fbar/tags", + ProfileTagsKey{ProfileKey: ProfileKey{Name: "foo/bar"}}, + ), + Entry( + "profile labels with a /", + "/calico/v1/policy/profile/foo%2fbar/labels", + ProfileLabelsKey{ProfileKey: ProfileKey{Name: "foo/bar"}}, + ), + Entry( + "policy with a /", + "/calico/v1/policy/tier/default/policy/biff%2fbop", + PolicyKey{Name: "biff/bop"}, + ), + Entry( + "workload with a /", + "/calico/v1/host/foobar/workload/open%2fstack/work%2fload/endpoint/end%2fpoint", + WorkloadEndpointKey{ + Hostname: "foobar", + OrchestratorID: "open/stack", + WorkloadID: "work/load", + EndpointID: "end/point", + }, + ), + Entry( + "host endpoint with a /", + "/calico/v1/host/foobar/endpoint/end%2fpoint", + HostEndpointKey{ + Hostname: "foobar", + EndpointID: "end/point", + }, + ), + Entry( + "host IP", + "/calico/v1/host/foobar/bird_ip", + HostIPKey{Hostname: "foobar"}, + ), + Entry( + "IP pool", + "/calico/v1/ipam/v4/pool/10.0.0.0-8", + IPPoolKey{CIDR: mustParseCIDR("10.0.0.0/8")}, + ), + Entry( + "global config", + "/calico/v1/config/foo", + GlobalConfigKey{Name: "foo"}, + ), + Entry( + "host config", + "/calico/v1/host/hostname/config/foo", + HostConfigKey{Hostname: "hostname", Name: "foo"}, + ), + Entry( + "ready flag", + "/calico/v1/Ready", + ReadyFlagKey{}, + ), +) + +func mustParseCIDR(s string) net.IPNet { + _, ipNet, err := net.ParseCIDR(s) + if err != nil { + panic(err) + } + return *ipNet +}