Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add peerName to ExportedServices. #1239

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions charts/consul/templates/crd-exportedservices.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ spec:
description: Partition is the admin partition to export
the service to.
type: string
peerName:
description: PeerName is the name of the peer to export
the service to.
type: string
type: object
type: array
name:
Expand Down
30 changes: 26 additions & 4 deletions control-plane/api/v1alpha1/exportedservices_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ type ExportedService struct {
type ServiceConsumer struct {
// Partition is the admin partition to export the service to.
Partition string `json:"partition,omitempty"`
// PeerName is the name of the peer to export the service to.
PeerName string `json:"peerName,omitempty"`
}

func (in *ExportedServices) GetObjectMeta() metav1.ObjectMeta {
Expand Down Expand Up @@ -164,7 +166,11 @@ func (in *ExportedServices) ToConsul(datacenter string) api.ConfigEntry {
func (in *ExportedService) toConsul() capi.ExportedService {
var consumers []capi.ServiceConsumer
for _, consumer := range in.Consumers {
consumers = append(consumers, capi.ServiceConsumer{Partition: consumer.Partition})
if consumer.PeerName != "" {
consumers = append(consumers, capi.ServiceConsumer{PeerName: consumer.PeerName})
} else {
consumers = append(consumers, capi.ServiceConsumer{Partition: consumer.Partition})
}
}
return capi.ExportedService{
Name: in.Name,
Expand Down Expand Up @@ -199,7 +205,7 @@ func (in *ExportedServices) Validate(consulMeta common.ConsulMeta) error {
}
for i, service := range in.Spec.Services {
if err := service.validate(field.NewPath("spec").Child("services").Index(i)); err != nil {
errs = append(errs, err)
errs = append(errs, err...)
}
}
if len(errs) > 0 {
Expand All @@ -210,9 +216,25 @@ func (in *ExportedServices) Validate(consulMeta common.ConsulMeta) error {
return nil
}

func (in *ExportedService) validate(path *field.Path) *field.Error {
func (in *ExportedService) validate(path *field.Path) field.ErrorList {
var errs field.ErrorList
if len(in.Consumers) == 0 {
return field.Invalid(path, in.Consumers, "service must have at least 1 consumer.")
errs = append(errs, field.Invalid(path, in.Consumers, "service must have at least 1 consumer."))
}
for i, consumer := range in.Consumers {
if err := consumer.validate(path.Child("consumers").Index(i)); err != nil {
errs = append(errs, err)
}
}
return errs
}

func (in *ServiceConsumer) validate(path *field.Path) *field.Error {
if in.Partition != "" && in.PeerName != "" {
return field.Invalid(path, *in, "both partition and peerName cannot be specified.")
}
if in.Partition == "" && in.PeerName == "" {
return field.Invalid(path, *in, "either partition or peerName must be specified.")
}
return nil
}
Expand Down
160 changes: 160 additions & 0 deletions control-plane/api/v1alpha1/exportedservices_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ func TestExportedServices_MatchesConsul(t *testing.T) {
{
Partition: "third",
},
{
PeerName: "second-peer",
},
},
},
{
Expand All @@ -65,6 +68,9 @@ func TestExportedServices_MatchesConsul(t *testing.T) {
{
Partition: "fifth",
},
{
PeerName: "third-peer",
},
},
},
},
Expand All @@ -83,6 +89,9 @@ func TestExportedServices_MatchesConsul(t *testing.T) {
{
Partition: "third",
},
{
PeerName: "second-peer",
},
},
},
{
Expand All @@ -95,6 +104,9 @@ func TestExportedServices_MatchesConsul(t *testing.T) {
{
Partition: "fifth",
},
{
PeerName: "third-peer",
},
},
},
},
Expand Down Expand Up @@ -165,6 +177,9 @@ func TestExportedServices_ToConsul(t *testing.T) {
{
Partition: "third",
},
{
PeerName: "second-peer",
},
},
},
{
Expand All @@ -177,6 +192,9 @@ func TestExportedServices_ToConsul(t *testing.T) {
{
Partition: "fifth",
},
{
PeerName: "third-peer",
},
},
},
},
Expand All @@ -195,6 +213,9 @@ func TestExportedServices_ToConsul(t *testing.T) {
{
Partition: "third",
},
{
PeerName: "second-peer",
},
},
},
{
Expand All @@ -207,6 +228,9 @@ func TestExportedServices_ToConsul(t *testing.T) {
{
Partition: "fifth",
},
{
PeerName: "third-peer",
},
},
},
},
Expand All @@ -227,6 +251,142 @@ func TestExportedServices_ToConsul(t *testing.T) {
}
}

func TestExportedServices_Validate(t *testing.T) {
cases := map[string]struct {
input *ExportedServices
expectedErrMsgs []string
}{
"valid": {
input: &ExportedServices{
ObjectMeta: metav1.ObjectMeta{
Name: common.DefaultConsulPartition,
},
Spec: ExportedServicesSpec{
Services: []ExportedService{
{
Name: "service-frontend",
Namespace: "frontend",
Consumers: []ServiceConsumer{
{
Partition: "second",
},
{
PeerName: "second-peer",
},
},
},
},
},
},
expectedErrMsgs: []string{},
},
"no consumers specified": {
input: &ExportedServices{
ObjectMeta: metav1.ObjectMeta{
Name: common.DefaultConsulPartition,
},
Spec: ExportedServicesSpec{
Services: []ExportedService{
{
Name: "service-frontend",
Namespace: "frontend",
Consumers: []ServiceConsumer{},
},
},
},
},
expectedErrMsgs: []string{
`spec.services[0]: Invalid value: []v1alpha1.ServiceConsumer{}: service must have at least 1 consumer.`,
},
},
"both partition and peer name specified": {
input: &ExportedServices{
ObjectMeta: metav1.ObjectMeta{
Name: common.DefaultConsulPartition,
},
Spec: ExportedServicesSpec{
Services: []ExportedService{
{
Name: "service-frontend",
Namespace: "frontend",
Consumers: []ServiceConsumer{
{
Partition: "second",
PeerName: "second-peer",
},
},
},
},
},
},
expectedErrMsgs: []string{
`spec.services[0].consumers[0]: Invalid value: v1alpha1.ServiceConsumer{Partition:"second", PeerName:"second-peer"}: both partition and peerName cannot be specified.`,
},
},
"neither partition nor peer name specified": {
input: &ExportedServices{
ObjectMeta: metav1.ObjectMeta{
Name: common.DefaultConsulPartition,
},
Spec: ExportedServicesSpec{
Services: []ExportedService{
{
Name: "service-frontend",
Namespace: "frontend",
Consumers: []ServiceConsumer{
{},
},
},
},
},
},
expectedErrMsgs: []string{
`spec.services[0].consumers[0]: Invalid value: v1alpha1.ServiceConsumer{Partition:"", PeerName:""}: either partition or peerName must be specified.`,
},
},
"multiple errors": {
input: &ExportedServices{
ObjectMeta: metav1.ObjectMeta{
Name: common.DefaultConsulPartition,
},
Spec: ExportedServicesSpec{
Services: []ExportedService{
{
Name: "service-frontend",
Namespace: "frontend",
Consumers: []ServiceConsumer{
{
Partition: "second",
PeerName: "second-peer",
},
{},
},
},
},
},
},
expectedErrMsgs: []string{
`spec.services[0].consumers[0]: Invalid value: v1alpha1.ServiceConsumer{Partition:"second", PeerName:"second-peer"}: both partition and peerName cannot be specified.`,
`spec.services[0].consumers[1]: Invalid value: v1alpha1.ServiceConsumer{Partition:"", PeerName:""}: either partition or peerName must be specified.`,
},
},
}

for name, testCase := range cases {
t.Run(name, func(t *testing.T) {
err := testCase.input.Validate(common.ConsulMeta{NamespacesEnabled: true, PartitionsEnabled: true, Partition: common.DefaultConsulPartition})
if len(testCase.expectedErrMsgs) != 0 {
require.Error(t, err)
for _, s := range testCase.expectedErrMsgs {
require.Contains(t, err.Error(), s)
}
} else {
require.NoError(t, err)
}
})
}
}

func TestExportedServices_AddFinalizer(t *testing.T) {
exportedServices := &ExportedServices{}
exportedServices.AddFinalizer("finalizer")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ spec:
description: Partition is the admin partition to export
the service to.
type: string
peerName:
description: PeerName is the name of the peer to export
the service to.
type: string
type: object
type: array
name:
Expand Down
2 changes: 1 addition & 1 deletion control-plane/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/go-logr/logr v0.4.0
github.com/google/go-cmp v0.5.7
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/hashicorp/consul/api v1.10.1-0.20220425143126-6d0162a58a94
github.com/hashicorp/consul/api v1.10.1-0.20220519230759-6167400b28c9
github.com/hashicorp/consul/sdk v0.9.0
github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f
github.com/hashicorp/go-hclog v0.16.1
Expand Down
4 changes: 2 additions & 2 deletions control-plane/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.10.1-0.20220425143126-6d0162a58a94 h1:mPhpaeGO4BmD0Fi9gmevT7kYDyDml1kNjf0HKCFF5xM=
github.com/hashicorp/consul/api v1.10.1-0.20220425143126-6d0162a58a94/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
github.com/hashicorp/consul/api v1.10.1-0.20220519230759-6167400b28c9 h1:HWXZXOMz3EXKtpE+ETagwEtppdCywlcQ799oEpdxfxc=
github.com/hashicorp/consul/api v1.10.1-0.20220519230759-6167400b28c9/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.4.1-0.20220214194852-80dfcb1bcd68 h1:yw3OXf1OUgfnitE8rwnr+zaT9VluSgvrCHQGwSvA7V4=
github.com/hashicorp/consul/sdk v0.4.1-0.20220214194852-80dfcb1bcd68/go.mod h1:K9S7H8bLBwkBb2I4hq0Ddm4LCVGuhtenfzSTx2Y36RM=
Expand Down