mirror of https://github.com/hashicorp/consul
238 lines
6.4 KiB
Go
238 lines
6.4 KiB
Go
|
// Copyright (c) HashiCorp, Inc.
|
||
|
// SPDX-License-Identifier: BUSL-1.1
|
||
|
|
||
|
package resource
|
||
|
|
||
|
import (
|
||
|
"strings"
|
||
|
"testing"
|
||
|
|
||
|
"google.golang.org/protobuf/proto"
|
||
|
|
||
|
"github.com/hashicorp/consul/proto-public/pbresource"
|
||
|
"github.com/hashicorp/consul/proto/private/prototest"
|
||
|
)
|
||
|
|
||
|
func TestDefaultReferenceTenancy(t *testing.T) {
|
||
|
// Just do a few small tests here and let the more complicated cases be covered by
|
||
|
// TestDefaultTenancy below.
|
||
|
|
||
|
t.Run("partition inference", func(t *testing.T) {
|
||
|
ref := &pbresource.Reference{
|
||
|
Type: &pbresource.Type{
|
||
|
Group: "fake",
|
||
|
GroupVersion: "v1fake",
|
||
|
Kind: "artificial",
|
||
|
},
|
||
|
Name: "blah",
|
||
|
Tenancy: &pbresource.Tenancy{
|
||
|
Namespace: "zim",
|
||
|
},
|
||
|
}
|
||
|
|
||
|
expect := &pbresource.Reference{
|
||
|
Type: &pbresource.Type{
|
||
|
Group: "fake",
|
||
|
GroupVersion: "v1fake",
|
||
|
Kind: "artificial",
|
||
|
},
|
||
|
Name: "blah",
|
||
|
Tenancy: newTestTenancy("gir.zim"),
|
||
|
}
|
||
|
|
||
|
parent := newTestTenancy("gir.gaz")
|
||
|
|
||
|
DefaultReferenceTenancy(ref, parent, DefaultNamespacedTenancy())
|
||
|
prototest.AssertDeepEqual(t, expect, ref)
|
||
|
})
|
||
|
|
||
|
t.Run("full default", func(t *testing.T) {
|
||
|
ref := &pbresource.Reference{
|
||
|
Type: &pbresource.Type{
|
||
|
Group: "fake",
|
||
|
GroupVersion: "v1fake",
|
||
|
Kind: "artificial",
|
||
|
},
|
||
|
Name: "blah",
|
||
|
}
|
||
|
|
||
|
expect := &pbresource.Reference{
|
||
|
Type: &pbresource.Type{
|
||
|
Group: "fake",
|
||
|
GroupVersion: "v1fake",
|
||
|
Kind: "artificial",
|
||
|
},
|
||
|
Name: "blah",
|
||
|
Tenancy: newTestTenancy("gir.gaz"),
|
||
|
}
|
||
|
|
||
|
parent := newTestTenancy("gir.gaz")
|
||
|
|
||
|
DefaultReferenceTenancy(ref, parent, DefaultNamespacedTenancy())
|
||
|
prototest.AssertDeepEqual(t, expect, ref)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestDefaultTenancy(t *testing.T) {
|
||
|
type testcase struct {
|
||
|
ref *pbresource.Tenancy
|
||
|
parent *pbresource.Tenancy
|
||
|
scope *pbresource.Tenancy
|
||
|
expect *pbresource.Tenancy
|
||
|
}
|
||
|
|
||
|
run := func(t *testing.T, tc testcase) {
|
||
|
got := proto.Clone(tc.ref).(*pbresource.Tenancy)
|
||
|
|
||
|
defaultTenancy(got, tc.parent, tc.scope)
|
||
|
prototest.AssertDeepEqual(t, tc.expect, got)
|
||
|
}
|
||
|
|
||
|
cases := map[string]testcase{
|
||
|
// Completely empty values get backfilled from the scope.
|
||
|
"clustered/empty/no-parent": {
|
||
|
ref: newTestTenancy(""),
|
||
|
parent: nil,
|
||
|
scope: DefaultClusteredTenancy(),
|
||
|
expect: DefaultClusteredTenancy(),
|
||
|
},
|
||
|
"partitioned/empty/no-parent": {
|
||
|
ref: newTestTenancy(""),
|
||
|
parent: nil,
|
||
|
scope: DefaultPartitionedTenancy(),
|
||
|
expect: DefaultPartitionedTenancy(),
|
||
|
},
|
||
|
"namespaced/empty/no-parent": {
|
||
|
ref: newTestTenancy(""),
|
||
|
parent: nil,
|
||
|
scope: DefaultNamespacedTenancy(),
|
||
|
expect: DefaultNamespacedTenancy(),
|
||
|
},
|
||
|
// Completely provided values are limited by the scope.
|
||
|
"clustered/full/no-parent": {
|
||
|
ref: newTestTenancy("foo.bar"),
|
||
|
parent: nil,
|
||
|
scope: DefaultClusteredTenancy(),
|
||
|
expect: DefaultClusteredTenancy(),
|
||
|
},
|
||
|
"partitioned/full/no-parent": {
|
||
|
ref: newTestTenancy("foo.bar"),
|
||
|
parent: nil,
|
||
|
scope: DefaultPartitionedTenancy(),
|
||
|
expect: newTestTenancy("foo"),
|
||
|
},
|
||
|
"namespaced/full/no-parent": {
|
||
|
ref: newTestTenancy("foo.bar"),
|
||
|
parent: nil,
|
||
|
scope: DefaultNamespacedTenancy(),
|
||
|
expect: newTestTenancy("foo.bar"),
|
||
|
},
|
||
|
// Completely provided parent values are limited by the scope before
|
||
|
// being blindly used for to fill in for the empty provided value.
|
||
|
"clustered/empty/full-parent": {
|
||
|
ref: newTestTenancy(""),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultClusteredTenancy(),
|
||
|
expect: DefaultClusteredTenancy(),
|
||
|
},
|
||
|
"partitioned/empty/full-parent": {
|
||
|
ref: newTestTenancy(""),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultPartitionedTenancy(),
|
||
|
expect: newTestTenancy("foo"),
|
||
|
},
|
||
|
"namespaced/empty/full-parent": {
|
||
|
ref: newTestTenancy(""),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultNamespacedTenancy(),
|
||
|
expect: newTestTenancy("foo.bar"),
|
||
|
},
|
||
|
// (1) Partially filled values are only partially populated by parents.
|
||
|
"clustered/part-only/full-parent": {
|
||
|
ref: newTestTenancy("zim"),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultClusteredTenancy(),
|
||
|
expect: DefaultClusteredTenancy(),
|
||
|
},
|
||
|
"partitioned/part-only/full-parent": {
|
||
|
ref: newTestTenancy("zim"),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultPartitionedTenancy(),
|
||
|
expect: newTestTenancy("zim"),
|
||
|
},
|
||
|
"namespaced/part-only/full-parent": {
|
||
|
ref: newTestTenancy("zim"),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultNamespacedTenancy(),
|
||
|
// partitions don't match so the namespace comes from the scope
|
||
|
expect: newTestTenancy("zim.default"),
|
||
|
},
|
||
|
// (2) Partially filled values are only partially populated by parents.
|
||
|
"clustered/ns-only/full-parent": {
|
||
|
// Leading dot implies no partition
|
||
|
ref: newTestTenancy(".gir"),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultClusteredTenancy(),
|
||
|
expect: DefaultClusteredTenancy(),
|
||
|
},
|
||
|
"partitioned/ns-only/full-parent": {
|
||
|
// Leading dot implies no partition
|
||
|
ref: newTestTenancy(".gir"),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultPartitionedTenancy(),
|
||
|
expect: newTestTenancy("foo"),
|
||
|
},
|
||
|
"namespaced/ns-only/full-parent": {
|
||
|
// Leading dot implies no partition
|
||
|
ref: newTestTenancy(".gir"),
|
||
|
parent: newTestTenancy("foo.bar"),
|
||
|
scope: DefaultNamespacedTenancy(),
|
||
|
expect: newTestTenancy("foo.gir"),
|
||
|
},
|
||
|
// Fully specified ignores parent.
|
||
|
"clustered/full/full-parent": {
|
||
|
ref: newTestTenancy("foo.bar"),
|
||
|
parent: newTestTenancy("zim.gir"),
|
||
|
scope: DefaultClusteredTenancy(),
|
||
|
expect: DefaultClusteredTenancy(),
|
||
|
},
|
||
|
"partitioned/full/full-parent": {
|
||
|
ref: newTestTenancy("foo.bar"),
|
||
|
parent: newTestTenancy("zim.gir"),
|
||
|
scope: DefaultPartitionedTenancy(),
|
||
|
expect: newTestTenancy("foo"),
|
||
|
},
|
||
|
"namespaced/full/full-parent": {
|
||
|
ref: newTestTenancy("foo.bar"),
|
||
|
parent: newTestTenancy("zim.gir"),
|
||
|
scope: DefaultNamespacedTenancy(),
|
||
|
expect: newTestTenancy("foo.bar"),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for name, tc := range cases {
|
||
|
t.Run(name, func(t *testing.T) {
|
||
|
run(t, tc)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func newTestTenancy(s string) *pbresource.Tenancy {
|
||
|
parts := strings.Split(s, ".")
|
||
|
switch len(parts) {
|
||
|
case 0:
|
||
|
return DefaultClusteredTenancy()
|
||
|
case 1:
|
||
|
v := DefaultPartitionedTenancy()
|
||
|
v.Partition = parts[0]
|
||
|
return v
|
||
|
case 2:
|
||
|
v := DefaultNamespacedTenancy()
|
||
|
v.Partition = parts[0]
|
||
|
v.Namespace = parts[1]
|
||
|
return v
|
||
|
default:
|
||
|
return &pbresource.Tenancy{Partition: "BAD", Namespace: "BAD", PeerName: "BAD"}
|
||
|
}
|
||
|
}
|