Support partitions in parseIntentionStringComponent (#11202)

This commit is contained in:
Chris S. Kim 2021-10-01 12:36:12 -04:00 committed by GitHub
parent a5b09493ab
commit 53a35181e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 39 deletions

View File

@ -136,7 +136,7 @@ func (s *HTTPHandlers) IntentionMatch(resp http.ResponseWriter, req *http.Reques
// order of the returned responses.
args.Match.Entries = make([]structs.IntentionMatchEntry, len(names))
for i, n := range names {
ns, name, err := parseIntentionStringComponent(n, &entMeta)
_, ns, name, err := parseIntentionStringComponent(n, &entMeta)
if err != nil {
return nil, fmt.Errorf("name %q is invalid: %s", n, err)
}
@ -227,7 +227,7 @@ func (s *HTTPHandlers) IntentionCheck(resp http.ResponseWriter, req *http.Reques
args.Check.SourceName = source[0]
if args.Check.SourceType == structs.IntentionSourceConsul {
// TODO(partitions): this func should return partition
ns, name, err := parseIntentionStringComponent(source[0], &entMeta)
_, ns, name, err := parseIntentionStringComponent(source[0], &entMeta)
if err != nil {
return nil, fmt.Errorf("source %q is invalid: %s", source[0], err)
}
@ -237,7 +237,7 @@ func (s *HTTPHandlers) IntentionCheck(resp http.ResponseWriter, req *http.Reques
}
// The destination is always in the Consul format
ns, name, err := parseIntentionStringComponent(destination[0], &entMeta)
_, ns, name, err := parseIntentionStringComponent(destination[0], &entMeta)
if err != nil {
return nil, fmt.Errorf("destination %q is invalid: %s", destination[0], err)
}
@ -280,7 +280,7 @@ func (s *HTTPHandlers) IntentionGetExact(resp http.ResponseWriter, req *http.Req
}
{
ns, name, err := parseIntentionStringComponent(source[0], &entMeta)
_, ns, name, err := parseIntentionStringComponent(source[0], &entMeta)
if err != nil {
return nil, fmt.Errorf("source %q is invalid: %s", source[0], err)
}
@ -290,7 +290,7 @@ func (s *HTTPHandlers) IntentionGetExact(resp http.ResponseWriter, req *http.Req
}
{
ns, name, err := parseIntentionStringComponent(destination[0], &entMeta)
_, ns, name, err := parseIntentionStringComponent(destination[0], &entMeta)
if err != nil {
return nil, fmt.Errorf("destination %q is invalid: %s", destination[0], err)
}
@ -553,7 +553,7 @@ func parseIntentionQueryExact(req *http.Request, entMeta *structs.EnterpriseMeta
var exact structs.IntentionQueryExact
{
ns, name, err := parseIntentionStringComponent(source[0], entMeta)
_, ns, name, err := parseIntentionStringComponent(source[0], entMeta)
if err != nil {
return nil, fmt.Errorf("source %q is invalid: %s", source[0], err)
}
@ -563,7 +563,7 @@ func parseIntentionQueryExact(req *http.Request, entMeta *structs.EnterpriseMeta
}
{
ns, name, err := parseIntentionStringComponent(destination[0], entMeta)
_, ns, name, err := parseIntentionStringComponent(destination[0], entMeta)
if err != nil {
return nil, fmt.Errorf("destination %q is invalid: %s", destination[0], err)
}
@ -575,21 +575,19 @@ func parseIntentionQueryExact(req *http.Request, entMeta *structs.EnterpriseMeta
return &exact, nil
}
// TODO(partitions): update to handle partitions
func parseIntentionStringComponent(input string, entMeta *structs.EnterpriseMeta) (string, string, error) {
// Get the index to the '/'. If it doesn't exist, we have just a name
// so just set that and return.
idx := strings.IndexByte(input, '/')
if idx == -1 {
func parseIntentionStringComponent(input string, entMeta *structs.EnterpriseMeta) (string, string, string, error) {
ss := strings.Split(input, "/")
switch len(ss) {
case 1: // Name only
ns := entMeta.NamespaceOrEmpty()
return ns, input, nil
ap := entMeta.PartitionOrEmpty()
return ap, ns, ss[0], nil
case 2: // namespace/name
ap := entMeta.PartitionOrEmpty()
return ap, ss[0], ss[1], nil
case 3: // partition/namespace/name
return ss[0], ss[1], ss[2], nil
default:
return "", "", "", fmt.Errorf("input can contain at most two '/'")
}
ns, name := input[:idx], input[idx+1:]
if strings.IndexByte(name, '/') != -1 {
return "", "", fmt.Errorf("input can contain at most one '/'")
}
return ns, name, nil
}

View File

@ -701,41 +701,58 @@ func TestIntentionSpecificDelete(t *testing.T) {
func TestParseIntentionStringComponent(t *testing.T) {
cases := []struct {
Input string
ExpectedNS, ExpectedName string
Err bool
TestName string
Input string
ExpectedAP string
ExpectedNS string
ExpectedName string
Err bool
}{
{
"foo",
"", "foo",
false,
TestName: "single name",
Input: "foo",
ExpectedAP: "",
ExpectedNS: "",
ExpectedName: "foo",
},
{
"foo/bar",
"foo", "bar",
false,
TestName: "namespace and name",
Input: "foo/bar",
ExpectedAP: "",
ExpectedNS: "foo",
ExpectedName: "bar",
},
{
"/bar",
"", "bar",
false,
TestName: "partition, namespace, and name",
Input: "foo/bar/baz",
ExpectedAP: "foo",
ExpectedNS: "bar",
ExpectedName: "baz",
},
{
"foo/bar/baz",
"", "",
true,
TestName: "empty ns",
Input: "/bar",
ExpectedAP: "",
ExpectedNS: "",
ExpectedName: "bar",
},
{
TestName: "invalid input",
Input: "uhoh/blah/foo/bar",
Err: true,
},
}
for _, tc := range cases {
t.Run(tc.Input, func(t *testing.T) {
t.Run(tc.TestName, func(t *testing.T) {
var entMeta structs.EnterpriseMeta
ns, name, err := parseIntentionStringComponent(tc.Input, &entMeta)
ap, ns, name, err := parseIntentionStringComponent(tc.Input, &entMeta)
if tc.Err {
require.Error(t, err)
} else {
require.NoError(t, err)
assert.Equal(t, tc.ExpectedAP, ap)
assert.Equal(t, tc.ExpectedNS, ns)
assert.Equal(t, tc.ExpectedName, name)
}