diff --git a/changelog/v1.18.0-rc4/kubegateway-clusternames.yaml b/changelog/v1.18.0-rc4/kubegateway-clusternames.yaml new file mode 100644 index 00000000000..f54ab58bde9 --- /dev/null +++ b/changelog/v1.18.0-rc4/kubegateway-clusternames.yaml @@ -0,0 +1,10 @@ +changelog: + - type: BREAKING_CHANGE + issueLink: https://github.com/solo-io/solo-projects/issues/7105 + resolvesIssue: false + description: >- + When using the Kubernetes Gateway API, envoy cluster names corresponding to Kubernetes Service Upstreams + are now in a new more parseable format that allows us to extract info about the Service for metrics: + `upstreamName_upstreamNs_svcNs_svcName_svcPort` (underscore-separated). Note that as long as Kubernetes + Gateway integration is enabled (i.e. Gloo Gateway installed with `kubeGateway.enabled=true`), both + Edge and Kubernetes Gateway proxies will use the new cluster format. diff --git a/projects/discovery/pkg/fds/updater.go b/projects/discovery/pkg/fds/updater.go index 70320c23c81..9d33116fef4 100644 --- a/projects/discovery/pkg/fds/updater.go +++ b/projects/discovery/pkg/fds/updater.go @@ -16,7 +16,6 @@ import ( v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" plugins "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" ) var errorUndetectableUpstream = errors.New("upstream type cannot be detected") @@ -115,7 +114,7 @@ func (u *Updater) UpstreamUpdated(upstream *v1.Upstream) { func (u *Updater) UpstreamAdded(upstream *v1.Upstream) { // upstream already tracked. ignore. - key := translator.UpstreamToClusterName(upstream.GetMetadata().Ref()) + key := upstream.GetMetadata().Ref().Key() if _, ok := u.activeUpstreams[key]; ok { return } @@ -144,7 +143,7 @@ func (u *Updater) UpstreamAdded(upstream *v1.Upstream) { } func (u *Updater) UpstreamRemoved(upstream *v1.Upstream) { - key := translator.UpstreamToClusterName(upstream.GetMetadata().Ref()) + key := upstream.GetMetadata().Ref().Key() if upstreamState, ok := u.activeUpstreams[key]; ok { upstreamState.cancel() delete(u.activeUpstreams, key) diff --git a/projects/gateway/pkg/syncer/translator_syncer.go b/projects/gateway/pkg/syncer/translator_syncer.go index 3bb38701bfb..89f7c7214d4 100644 --- a/projects/gateway/pkg/syncer/translator_syncer.go +++ b/projects/gateway/pkg/syncer/translator_syncer.go @@ -12,7 +12,6 @@ import ( "github.com/solo-io/gloo/pkg/utils/statsutils/metrics" "github.com/solo-io/gloo/pkg/utils/syncutil" - gloo_translator "github.com/solo-io/gloo/projects/gloo/pkg/translator" "github.com/solo-io/solo-kit/pkg/api/v1/clients" "github.com/solo-io/solo-kit/pkg/errors" "go.uber.org/zap/zapcore" @@ -230,7 +229,7 @@ func (s *statusSyncer) setCurrentProxies(desiredProxies reconciler.GeneratedProx // floating around. Historically, they were there to envorce an alphabetical processing of // `proxyToLastStatus`. See https://github.com/solo-io/gloo/issues/5812 for more details. for proxyRef, reports := range proxyReportsByRef { - refKey := gloo_translator.UpstreamToClusterName(proxyRef) + refKey := glooutils.ResourceRefToKey(proxyRef) if _, ok := s.proxyToLastStatus[refKey]; !ok { s.proxyToLastStatus[refKey] = reportsAndStatus{} } @@ -295,7 +294,7 @@ func (s *statusSyncer) setStatuses(list gloov1.ProxyList) { defer s.mapLock.Unlock() for _, proxy := range list { ref := proxy.GetMetadata().Ref() - refKey := gloo_translator.UpstreamToClusterName(ref) + refKey := glooutils.ResourceRefToKey(ref) status := s.statusClient.GetStatus(proxy) if current, ok := s.proxyToLastStatus[refKey]; ok { current.Status = status @@ -359,7 +358,7 @@ func (s *statusSyncer) extractCurrentReports() (reporter.ResourceReports, map[re var refKeys []string for _, ref := range s.currentGeneratedProxies { - refKeys = append(refKeys, gloo_translator.UpstreamToClusterName(ref)) + refKeys = append(refKeys, glooutils.ResourceRefToKey(ref)) } // iterate over proxyToLastStatus by alphabetical ordering of keys diff --git a/projects/gateway/pkg/syncer/translator_syncer_test.go b/projects/gateway/pkg/syncer/translator_syncer_test.go index 8d4b84d2eae..36aa3fd21c7 100644 --- a/projects/gateway/pkg/syncer/translator_syncer_test.go +++ b/projects/gateway/pkg/syncer/translator_syncer_test.go @@ -22,7 +22,7 @@ import ( gloov1snap "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/gloosnapshot" "github.com/solo-io/gloo/projects/gloo/pkg/defaults" gloomocks "github.com/solo-io/gloo/projects/gloo/pkg/mocks" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/utils" "github.com/solo-io/solo-kit/pkg/api/v1/resources" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" "github.com/solo-io/solo-kit/pkg/api/v2/reporter" @@ -82,7 +82,7 @@ var _ = Describe("TranslatorSyncer", func() { err := syncer.syncStatus(context.Background()) Expect(err).NotTo(HaveOccurred()) reportedKey := getMapOnlyKey(mockReporter.Reports()) - Expect(reportedKey).To(Equal(translator.UpstreamToClusterName(vs.GetMetadata().Ref()))) + Expect(reportedKey).To(Equal(utils.ResourceRefToKey(vs.GetMetadata().Ref()))) Expect(mockReporter.Reports()[reportedKey]).To(BeEquivalentTo(errs[vs])) m := map[string]*core.Status{ "*v1.Proxy.test_gloo-system": {State: core.Status_Accepted}, @@ -137,7 +137,7 @@ var _ = Describe("TranslatorSyncer", func() { Expect(err).NotTo(HaveOccurred()) reportedKey := getMapOnlyKey(mockReporter.Reports()) - Expect(reportedKey).To(Equal(translator.UpstreamToClusterName(rt.GetMetadata().Ref()))) + Expect(reportedKey).To(Equal(utils.ResourceRefToKey(rt.GetMetadata().Ref()))) Expect(reportContainsWarning(mockReporter.Reports()[reportedKey], "warning 1")).To(BeTrue()) Expect(reportContainsWarning(mockReporter.Reports()[reportedKey], "warning 2")).To(BeTrue()) @@ -183,7 +183,7 @@ var _ = Describe("TranslatorSyncer", func() { syncer.handleUpdatedProxies(ctx) Eventually(mockReporter.Reports, "5s", "0.5s").ShouldNot(BeEmpty()) reportedKey := getMapOnlyKey(mockReporter.Reports()) - Expect(reportedKey).To(Equal(translator.UpstreamToClusterName(vs.GetMetadata().Ref()))) + Expect(reportedKey).To(Equal(utils.ResourceRefToKey(vs.GetMetadata().Ref()))) Expect(mockReporter.Reports()[reportedKey]).To(BeEquivalentTo(errs[vs])) m := map[string]*core.Status{ "*v1.Proxy.test_gloo-system": {State: core.Status_Accepted}, @@ -218,7 +218,7 @@ var _ = Describe("TranslatorSyncer", func() { syncer.handleUpdatedProxies(ctx) Eventually(mockReporter.Reports, "5s", "0.5s").ShouldNot(BeEmpty()) reportedKey := getMapOnlyKey(mockReporter.Reports()) - Expect(reportedKey).To(Equal(translator.UpstreamToClusterName(vs.GetMetadata().Ref()))) + Expect(reportedKey).To(Equal(utils.ResourceRefToKey(vs.GetMetadata().Ref()))) Expect(mockReporter.Reports()[reportedKey]).To(BeEquivalentTo(errs[vs])) m := map[string]*core.Status{ "*v1.Proxy.test_gloo-system": {State: core.Status_Accepted}, @@ -253,7 +253,7 @@ var _ = Describe("TranslatorSyncer", func() { Expect(err).NotTo(HaveOccurred()) reportedKey := getMapOnlyKey(mockReporter.Reports()) - Expect(reportedKey).To(Equal(translator.UpstreamToClusterName(vs.GetMetadata().Ref()))) + Expect(reportedKey).To(Equal(utils.ResourceRefToKey(vs.GetMetadata().Ref()))) Expect(mockReporter.Reports()[reportedKey]).To(BeEquivalentTo(errs[vs])) m := map[string]*core.Status{ @@ -290,7 +290,7 @@ var _ = Describe("TranslatorSyncer", func() { Expect(err).NotTo(HaveOccurred()) reportedKey := getMapOnlyKey(mockReporter.Reports()) - Expect(reportedKey).To(Equal(translator.UpstreamToClusterName(vs.GetMetadata().Ref()))) + Expect(reportedKey).To(Equal(utils.ResourceRefToKey(vs.GetMetadata().Ref()))) Expect(mockReporter.Reports()[reportedKey]).To(BeEquivalentTo(errs[vs])) m := map[string]*core.Status{ @@ -334,7 +334,7 @@ var _ = Describe("TranslatorSyncer", func() { mergedErrs.AddError(vs, fmt.Errorf("invalid 2")) reportedKey := getMapOnlyKey(mockReporter.Reports()) - Expect(reportedKey).To(Equal(translator.UpstreamToClusterName(vs.GetMetadata().Ref()))) + Expect(reportedKey).To(Equal(utils.ResourceRefToKey(vs.GetMetadata().Ref()))) Expect(mockReporter.Reports()[reportedKey]).To(BeEquivalentTo(mergedErrs[vs])) m := map[string]*core.Status{ @@ -451,7 +451,7 @@ func (f *fakeReporter) WriteReports(ctx context.Context, errs reporter.ResourceR newreports[k] = v } for k, v := range errs { - newreports[translator.UpstreamToClusterName(k.GetMetadata().Ref())] = v + newreports[utils.ResourceRefToKey(k.GetMetadata().Ref())] = v } f.reports = newreports @@ -460,7 +460,7 @@ func (f *fakeReporter) WriteReports(ctx context.Context, errs reporter.ResourceR newstatus[k] = v } for k := range errs { - newstatus[translator.UpstreamToClusterName(k.GetMetadata().Ref())] = subresourceStatuses + newstatus[utils.ResourceRefToKey(k.GetMetadata().Ref())] = subresourceStatuses } f.statuses = newstatus diff --git a/projects/gateway2/krtcollections/endpoints.go b/projects/gateway2/krtcollections/endpoints.go index cc8ba5f0921..88f978643c8 100644 --- a/projects/gateway2/krtcollections/endpoints.go +++ b/projects/gateway2/krtcollections/endpoints.go @@ -18,6 +18,7 @@ import ( glookubev1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/kube/apis/gloo.solo.io/v1" kubeplugin "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/kubernetes" "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/go-utils/contextutils" "istio.io/istio/pkg/kube" "istio.io/istio/pkg/kube/kclient" @@ -429,7 +430,7 @@ func findPortInEndpointSlice(endpointSlice *discoveryv1.EndpointSlice, singlePor // TODO: use exported version from translator? func GetEndpointClusterName(upstream *v1.Upstream) string { - clusterName := translator.UpstreamToClusterName(upstream.GetMetadata().Ref()) + clusterName := upstreams.UpstreamToClusterName(upstream) endpointClusterName, err := translator.GetEndpointClusterName(clusterName, upstream) if err != nil { panic(err) diff --git a/projects/gateway2/proxy_syncer/cla.go b/projects/gateway2/proxy_syncer/cla.go index d0abafe561b..ca318b8c6b3 100644 --- a/projects/gateway2/proxy_syncer/cla.go +++ b/projects/gateway2/proxy_syncer/cla.go @@ -133,7 +133,7 @@ func PrioritizeEndpoints(logger *zap.Logger, destrule *DestinationRuleWrapper, e var priorityInfo *PriorityInfo if destrule != nil { - trafficPolicy := getTraficPolicy(destrule, ep.Port) + trafficPolicy := getTrafficPolicy(destrule, ep.Port) localityLb := getLocalityLbSetting(trafficPolicy) if localityLb != nil { priorityInfo = getPriorityInfoFromDestrule(localityLb) diff --git a/projects/gateway2/proxy_syncer/destrule.go b/projects/gateway2/proxy_syncer/destrule.go index 8d0d1c4bfbf..14aaae51cc9 100644 --- a/projects/gateway2/proxy_syncer/destrule.go +++ b/projects/gateway2/proxy_syncer/destrule.go @@ -141,7 +141,7 @@ func getLocalityLbSetting(trafficPolicy *v1alpha3.TrafficPolicy) *v1alpha3.Local return localityLb } -func getTraficPolicy(destrule *DestinationRuleWrapper, port uint32) *v1alpha3.TrafficPolicy { +func getTrafficPolicy(destrule *DestinationRuleWrapper, port uint32) *v1alpha3.TrafficPolicy { trafficPolicy := destrule.Spec.GetTrafficPolicy() if trafficPolicy == nil { return nil diff --git a/projects/gateway2/proxy_syncer/upstreams.go b/projects/gateway2/proxy_syncer/upstreams.go index c9bfecc249a..7e66f0db897 100644 --- a/projects/gateway2/proxy_syncer/upstreams.go +++ b/projects/gateway2/proxy_syncer/upstreams.go @@ -138,7 +138,7 @@ func translate(ctx context.Context, settings *gloov1.Settings, translator setup. func ApplyDestRulesForUpstream(destrule *DestinationRuleWrapper, u *gloov1.Upstream) (*gloov1.Upstream, string) { if destrule != nil { - trafficPolicy := getTraficPolicy(destrule, ggv2utils.GetPortForUpstream(u)) + trafficPolicy := getTrafficPolicy(destrule, ggv2utils.GetPortForUpstream(u)) if outlier := trafficPolicy.GetOutlierDetection(); outlier != nil { name := krtcollections.GetEndpointClusterName(u) diff --git a/projects/gateway2/setup/ggv2setup.go b/projects/gateway2/setup/ggv2setup.go index f67e62eb0eb..93b39959e11 100644 --- a/projects/gateway2/setup/ggv2setup.go +++ b/projects/gateway2/setup/ggv2setup.go @@ -217,7 +217,7 @@ func (g *genericStatusReporter) WriteReports(ctx context.Context, resourceErrs r for resource, report := range resourceErrsCopy { // check if resource is an internal upstream. if so skip it.. - if kubernetes.IsKubeUpstream(resource.GetMetadata().GetName()) { + if kubernetes.IsFakeKubeUpstream(resource.GetMetadata().GetName()) { continue } // check if resource is an internal upstream. Internal upstreams have ':' in their names so diff --git a/projects/gloo/cli/pkg/printers/upstream.go b/projects/gloo/cli/pkg/printers/upstream.go index 8f765fcdfb0..66889765152 100644 --- a/projects/gloo/cli/pkg/printers/upstream.go +++ b/projects/gloo/cli/pkg/printers/upstream.go @@ -135,7 +135,7 @@ func upstreamDetails(up *v1.Upstream, xdsDump *xdsinspection.XdsDump) []string { fmt.Sprintf("port: %v", usType.AwsEc2.GetPort()), ) add(getEc2TagFiltersString(usType.AwsEc2.GetFilters())...) - instances := xdsDump.GetEc2InstancesForUpstream(up.GetMetadata().Ref()) + instances := xdsDump.GetEc2InstancesForUpstream(up) add( "EC2 Instance Ids:", ) diff --git a/projects/gloo/cli/pkg/xdsinspection/ec2.go b/projects/gloo/cli/pkg/xdsinspection/ec2.go index 09bff813cfa..f1331b664c2 100644 --- a/projects/gloo/cli/pkg/xdsinspection/ec2.go +++ b/projects/gloo/cli/pkg/xdsinspection/ec2.go @@ -1,19 +1,19 @@ package xdsinspection import ( + gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/aws/ec2" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" - "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" ) -func (xd *XdsDump) GetEc2InstancesForUpstream(upstream *core.ResourceRef) []string { +func (xd *XdsDump) GetEc2InstancesForUpstream(upstream *gloov1.Upstream) []string { var out []string if xd == nil { out = append(out, "use -o wide for instance details") return out } - clusterName := translator.UpstreamToClusterName(upstream) + clusterName := upstreams.UpstreamToClusterName(upstream) endpointCount := 0 for _, clusterEndpoints := range xd.Endpoints { if clusterEndpoints.GetClusterName() == clusterName { diff --git a/projects/gloo/pkg/plugins/als/plugin_test.go b/projects/gloo/pkg/plugins/als/plugin_test.go index 21af7d8946d..e8086904e96 100644 --- a/projects/gloo/pkg/plugins/als/plugin_test.go +++ b/projects/gloo/pkg/plugins/als/plugin_test.go @@ -23,10 +23,10 @@ import ( "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" "github.com/solo-io/solo-kit/test/matchers" + envoygrpc "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/grpc/v3" . "github.com/solo-io/gloo/projects/gloo/pkg/plugins/als" translatorutil "github.com/solo-io/gloo/projects/gloo/pkg/translator" - - envoygrpc "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/grpc/v3" + "github.com/solo-io/gloo/projects/gloo/pkg/utils" ) var _ = Describe("Plugin", func() { @@ -72,7 +72,7 @@ var _ = Describe("Plugin", func() { GrpcService: &accessLogService.GrpcService{ LogName: logName, ServiceRef: &accessLogService.GrpcService_StaticClusterName{ - StaticClusterName: translatorutil.UpstreamToClusterName(usRef), + StaticClusterName: utils.ResourceRefToKey(usRef), }, AdditionalRequestHeadersToLog: extraHeaders, AdditionalResponseHeadersToLog: extraHeaders, @@ -98,7 +98,7 @@ var _ = Describe("Plugin", func() { Expect(falCfg.CommonConfig.LogName).To(Equal(logName)) envoyGrpc := falCfg.CommonConfig.GetGrpcService().GetEnvoyGrpc() Expect(envoyGrpc).NotTo(BeNil()) - Expect(envoyGrpc.ClusterName).To(Equal(translatorutil.UpstreamToClusterName(usRef))) + Expect(envoyGrpc.ClusterName).To(Equal(utils.ResourceRefToKey(usRef))) }) DescribeTable("Test each filter is translated properly", @@ -605,7 +605,7 @@ var _ = Describe("Plugin", func() { GrpcService: &accessLogService.GrpcService{ LogName: logName, ServiceRef: &accessLogService.GrpcService_StaticClusterName{ - StaticClusterName: translatorutil.UpstreamToClusterName(usRef), + StaticClusterName: utils.ResourceRefToKey(usRef), }, AdditionalRequestHeadersToLog: extraHeaders, AdditionalResponseHeadersToLog: extraHeaders, @@ -634,7 +634,7 @@ var _ = Describe("Plugin", func() { Expect(falCfg.CommonConfig.LogName).To(Equal(logName)) envoyGrpc := falCfg.CommonConfig.GetGrpcService().GetEnvoyGrpc() Expect(envoyGrpc).NotTo(BeNil()) - Expect(envoyGrpc.ClusterName).To(Equal(translatorutil.UpstreamToClusterName(usRef))) + Expect(envoyGrpc.ClusterName).To(Equal(utils.ResourceRefToKey(usRef))) }) }) @@ -787,7 +787,7 @@ var _ = Describe("Plugin", func() { GrpcService: &accessLogService.GrpcService{ LogName: logName, ServiceRef: &accessLogService.GrpcService_StaticClusterName{ - StaticClusterName: translatorutil.UpstreamToClusterName(usRef), + StaticClusterName: utils.ResourceRefToKey(usRef), }, AdditionalRequestHeadersToLog: extraHeaders, AdditionalResponseHeadersToLog: extraHeaders, @@ -826,7 +826,7 @@ var _ = Describe("Plugin", func() { GrpcService: &accessLogService.GrpcService{ LogName: logName, ServiceRef: &accessLogService.GrpcService_StaticClusterName{ - StaticClusterName: translatorutil.UpstreamToClusterName(usRef), + StaticClusterName: utils.ResourceRefToKey(usRef), }, AdditionalRequestHeadersToLog: extraHeaders, AdditionalResponseHeadersToLog: extraHeaders, @@ -878,7 +878,7 @@ var _ = Describe("Plugin", func() { GrpcService: &accessLogService.GrpcService{ LogName: logName, ServiceRef: &accessLogService.GrpcService_StaticClusterName{ - StaticClusterName: translatorutil.UpstreamToClusterName(usRef), + StaticClusterName: utils.ResourceRefToKey(usRef), }, AdditionalRequestHeadersToLog: extraHeaders, AdditionalResponseHeadersToLog: extraHeaders, @@ -932,7 +932,7 @@ var _ = Describe("Plugin", func() { GrpcService: &accessLogService.GrpcService{ LogName: logName, ServiceRef: &accessLogService.GrpcService_StaticClusterName{ - StaticClusterName: translatorutil.UpstreamToClusterName(usRef), + StaticClusterName: utils.ResourceRefToKey(usRef), }, AdditionalRequestHeadersToLog: extraHeaders, AdditionalResponseHeadersToLog: extraHeaders, @@ -962,7 +962,7 @@ var _ = Describe("Plugin", func() { GrpcService: &accessLogService.GrpcService{ LogName: logName, ServiceRef: &accessLogService.GrpcService_StaticClusterName{ - StaticClusterName: translatorutil.UpstreamToClusterName(usRef), + StaticClusterName: utils.ResourceRefToKey(usRef), }, AdditionalRequestHeadersToLog: extraHeaders, AdditionalResponseHeadersToLog: extraHeaders, diff --git a/projects/gloo/pkg/plugins/aws/plugin.go b/projects/gloo/pkg/plugins/aws/plugin.go index 79ba16c7241..806dae33f3c 100644 --- a/projects/gloo/pkg/plugins/aws/plugin.go +++ b/projects/gloo/pkg/plugins/aws/plugin.go @@ -26,7 +26,6 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/pluginutils" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/transformation" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" "github.com/solo-io/go-utils/contextutils" @@ -99,7 +98,7 @@ func (p *Plugin) ProcessUpstream(params plugins.Params, in *v1.Upstream, out *en return nil } // even if it failed, route should still be valid - p.recordedUpstreams[translator.UpstreamToClusterName(in.GetMetadata().Ref())] = upstreamSpec.Aws + p.recordedUpstreams[in.GetMetadata().Ref().Key()] = upstreamSpec.Aws lambdaHostname := getLambdaHostname(upstreamSpec.Aws) @@ -208,7 +207,7 @@ func (p *Plugin) ProcessRoute(params plugins.RouteParams, in *v1.Route, out *env } // validate that the upstream is one that we have previously recorded as an aws upstream - lambdaSpec, ok := p.recordedUpstreams[translator.UpstreamToClusterName(upstreamRef)] + lambdaSpec, ok := p.recordedUpstreams[upstreamRef.Key()] if !ok { if tryingNonExplicitAWSDest { // skip the lambda plugin as the route was not explicitly set to be an aws route diff --git a/projects/gloo/pkg/plugins/azure/plugin.go b/projects/gloo/pkg/plugins/azure/plugin.go index c0fb81a5855..87840fda6ac 100644 --- a/projects/gloo/pkg/plugins/azure/plugin.go +++ b/projects/gloo/pkg/plugins/azure/plugin.go @@ -17,7 +17,6 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/pluginutils" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/transformation" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" "github.com/solo-io/go-utils/contextutils" @@ -64,7 +63,7 @@ func (p *plugin) ProcessUpstream(params plugins.Params, in *v1.Upstream, out *en return nil } azureUpstream := upstreamSpec.Azure - p.recordedUpstreams[translator.UpstreamToClusterName(in.GetMetadata().Ref())] = azureUpstream + p.recordedUpstreams[in.GetMetadata().Ref().Key()] = azureUpstream // configure Envoy cluster routing info out.ClusterDiscoveryType = &envoy_config_cluster_v3.Cluster_Type{ @@ -126,7 +125,7 @@ func (p *plugin) ProcessRoute(params plugins.RouteParams, in *v1.Route, out *env contextutils.LoggerFrom(p.ctx).Error(err) return nil, err } - upstreamSpec, ok := p.recordedUpstreams[translator.UpstreamToClusterName(upstreamRef)] + upstreamSpec, ok := p.recordedUpstreams[upstreamRef.Key()] if !ok { // TODO(yuval-k): panic in debug return nil, errors.Errorf("%v is not an Azure upstream", *upstreamRef) diff --git a/projects/gloo/pkg/plugins/consul/subsets.go b/projects/gloo/pkg/plugins/consul/subsets.go index b91a352a741..e151fff9323 100644 --- a/projects/gloo/pkg/plugins/consul/subsets.go +++ b/projects/gloo/pkg/plugins/consul/subsets.go @@ -11,7 +11,6 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins/pluginutils" "github.com/solo-io/gloo/projects/gloo/pkg/translator" "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" - "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" ) func (p *plugin) ProcessRouteAction( @@ -66,7 +65,7 @@ func (p *plugin) ProcessRouteAction( func getMetadataMatch( dest *v1.Destination, allUpstreams v1.UpstreamList, -) (*envoy_config_core_v3.Metadata, *core.ResourceRef, error) { +) (*envoy_config_core_v3.Metadata, *v1.Upstream, error) { usRef, err := upstreams.DestinationToUpstreamRef(dest) if err != nil { return nil, nil, err @@ -77,7 +76,7 @@ func getMetadataMatch( return nil, nil, pluginutils.NewUpstreamNotFoundErr(usRef) // should never happen, as we already validated the destination } - return getSubsetMatch(dest, upstream), usRef, nil + return getSubsetMatch(dest, upstream), upstream, nil } func setWeightedClusters(params plugins.Params, multiDest *v1.MultiDestination, out *envoy_config_route_v3.RouteAction) error { @@ -94,12 +93,12 @@ func setWeightedClusters(params plugins.Params, multiDest *v1.MultiDestination, continue } - metadataMatch, usRef, err := getMetadataMatch(weightedDest.GetDestination(), params.Snapshot.Upstreams) + metadataMatch, upstream, err := getMetadataMatch(weightedDest.GetDestination(), params.Snapshot.Upstreams) if err != nil { return err } - clusterName := translator.UpstreamToClusterName(usRef) + clusterName := upstreams.UpstreamToClusterName(upstream) correspondentCluster := clusterMap[clusterName] correspondentCluster.MetadataMatch = metadataMatch diff --git a/projects/gloo/pkg/plugins/extauth/config_generator.go b/projects/gloo/pkg/plugins/extauth/config_generator.go index 42baa923264..4f7fda780c8 100644 --- a/projects/gloo/pkg/plugins/extauth/config_generator.go +++ b/projects/gloo/pkg/plugins/extauth/config_generator.go @@ -18,7 +18,7 @@ import ( extauthv1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/enterprise/options/extauth/v1" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" "github.com/solo-io/gloo/projects/gloo/pkg/syncer/extauth" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" "github.com/solo-io/solo-kit/pkg/utils/prototime" ) @@ -222,7 +222,7 @@ func GenerateEnvoyConfigForFilter(settings *extauthv1.Settings, upstreams v1.Ups } // Make sure the server exists - _, err := upstreams.Find(extauthUpstreamRef.GetNamespace(), extauthUpstreamRef.GetName()) + extauthUpstream, err := upstreams.Find(extauthUpstreamRef.GetNamespace(), extauthUpstreamRef.GetName()) if err != nil { return nil, ServerNotFound(extauthUpstreamRef) } @@ -236,7 +236,7 @@ func GenerateEnvoyConfigForFilter(settings *extauthv1.Settings, upstreams v1.Ups svc := &envoycore.GrpcService{ TargetSpecifier: &envoycore.GrpcService_EnvoyGrpc_{ EnvoyGrpc: &envoycore.GrpcService_EnvoyGrpc{ - ClusterName: translator.UpstreamToClusterName(extauthUpstreamRef), + ClusterName: glooupstreams.UpstreamToClusterName(extauthUpstream), }, }} @@ -259,7 +259,7 @@ func GenerateEnvoyConfigForFilter(settings *extauthv1.Settings, upstreams v1.Ups Uri: HttpServerUri, Timeout: settings.GetRequestTimeout(), HttpUpstreamType: &envoycore.HttpUri_Cluster{ - Cluster: translator.UpstreamToClusterName(extauthUpstreamRef), + Cluster: glooupstreams.UpstreamToClusterName(extauthUpstream), }, } if httpURI.GetTimeout() == nil { diff --git a/projects/gloo/pkg/plugins/extauth/config_generator_test.go b/projects/gloo/pkg/plugins/extauth/config_generator_test.go index dec837d4abf..6594b197f17 100644 --- a/projects/gloo/pkg/plugins/extauth/config_generator_test.go +++ b/projects/gloo/pkg/plugins/extauth/config_generator_test.go @@ -18,7 +18,7 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/static" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" . "github.com/solo-io/gloo/projects/gloo/pkg/plugins/extauth" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" . "github.com/solo-io/go-utils/testutils" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" "github.com/solo-io/solo-kit/pkg/utils/prototime" @@ -197,7 +197,7 @@ var _ = Describe("ExtAuthzConfigGenerator", func() { Timeout: DefaultTimeout, TargetSpecifier: &envoycore.GrpcService_EnvoyGrpc_{ EnvoyGrpc: &envoycore.GrpcService_EnvoyGrpc{ - ClusterName: translator.UpstreamToClusterName(usRef), + ClusterName: upstreams.UpstreamToClusterName(upstream), }, }, }, @@ -261,7 +261,7 @@ var _ = Describe("ExtAuthzConfigGenerator", func() { Timeout: customTimeout, TargetSpecifier: &envoycore.GrpcService_EnvoyGrpc_{ EnvoyGrpc: &envoycore.GrpcService_EnvoyGrpc{ - ClusterName: translator.UpstreamToClusterName(usRef), + ClusterName: upstreams.UpstreamToClusterName(upstream), }, }, }, @@ -374,7 +374,7 @@ var _ = Describe("ExtAuthzConfigGenerator", func() { Timeout: DefaultTimeout, Uri: HttpServerUri, HttpUpstreamType: &envoycore.HttpUri_Cluster{ - Cluster: translator.UpstreamToClusterName(usRef), + Cluster: upstreams.UpstreamToClusterName(upstream), }, }, }, @@ -413,7 +413,7 @@ var _ = Describe("ExtAuthzConfigGenerator", func() { Timeout: DefaultTimeout, TargetSpecifier: &envoycore.GrpcService_EnvoyGrpc_{ EnvoyGrpc: &envoycore.GrpcService_EnvoyGrpc{ - ClusterName: translator.UpstreamToClusterName(usRef), + ClusterName: upstreams.UpstreamToClusterName(upstream), Authority: authority, }, }, diff --git a/projects/gloo/pkg/plugins/grpc/plugin.go b/projects/gloo/pkg/plugins/grpc/plugin.go index 9080cdb554c..c2cb05bd630 100644 --- a/projects/gloo/pkg/plugins/grpc/plugin.go +++ b/projects/gloo/pkg/plugins/grpc/plugin.go @@ -23,7 +23,6 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins/pluginutils" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/transformation" transformutils "github.com/solo-io/gloo/projects/gloo/pkg/plugins/utils/transformation" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" "github.com/solo-io/go-utils/contextutils" @@ -81,7 +80,7 @@ func (p *plugin) ProcessUpstream(params plugins.Params, in *v1.Upstream, out *en // If the upstream uses the new API we should record that it exists for use in `ProcessRoute` but not make any changes _, ok = upstreamType.GetServiceSpec().GetPluginType().(*glooplugins.ServiceSpec_GrpcJsonTranscoder) if ok { - p.recordedUpstreams[translator.UpstreamToClusterName(in.GetMetadata().Ref())] = in + p.recordedUpstreams[in.GetMetadata().Ref().Key()] = in return nil } grpcWrapper, ok := upstreamType.GetServiceSpec().GetPluginType().(*glooplugins.ServiceSpec_Grpc) @@ -116,12 +115,12 @@ func (p *plugin) ProcessUpstream(params plugins.Params, in *v1.Upstream, out *en addWellKnownProtos(descriptors) - p.recordedUpstreams[translator.UpstreamToClusterName(in.GetMetadata().Ref())] = in + p.recordedUpstreams[in.GetMetadata().Ref().Key()] = in p.upstreamServices = append(p.upstreamServices, ServicesAndDescriptor{ Descriptors: descriptors, Spec: grpcSpec, }) - contextutils.LoggerFrom(params.Ctx).Debugf("record grpc upstream in.Metadata.Namespace: %s, in.Metadata.Name: %s cluster: %s", in.GetMetadata().GetNamespace(), in.GetMetadata().GetName(), translator.UpstreamToClusterName(in.GetMetadata().Ref())) + contextutils.LoggerFrom(params.Ctx).Debugf("record grpc upstream in.Metadata.Namespace: %s, in.Metadata.Name: %s", in.GetMetadata().GetNamespace(), in.GetMetadata().GetName()) return nil } @@ -184,7 +183,7 @@ func (p *plugin) ProcessRoute(params plugins.RouteParams, in *v1.Route, out *env return nil, err } - upstream := p.recordedUpstreams[translator.UpstreamToClusterName(upstreamRef)] + upstream := p.recordedUpstreams[upstreamRef.Key()] if upstream == nil { return nil, errors.New(fmt.Sprintf("upstream %v was not recorded for grpc route", upstreamRef)) } diff --git a/projects/gloo/pkg/plugins/kubernetes/uds_convert.go b/projects/gloo/pkg/plugins/kubernetes/uds_convert.go index b52048b3ae2..1503d069486 100644 --- a/projects/gloo/pkg/plugins/kubernetes/uds_convert.go +++ b/projects/gloo/pkg/plugins/kubernetes/uds_convert.go @@ -5,16 +5,13 @@ import ( "fmt" "reflect" - "github.com/solo-io/gloo/projects/gloo/pkg/plugins/kubernetes/serviceconverter" - "github.com/solo-io/go-utils/contextutils" - - "github.com/solo-io/gloo/projects/gloo/pkg/plugins/utils" - - sanitizer "github.com/solo-io/k8s-utils/kubeutils" - v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" kubeplugin "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/kubernetes" "github.com/solo-io/gloo/projects/gloo/pkg/discovery" + "github.com/solo-io/gloo/projects/gloo/pkg/plugins/kubernetes/serviceconverter" + "github.com/solo-io/gloo/projects/gloo/pkg/plugins/utils" + "github.com/solo-io/go-utils/contextutils" + sanitizer "github.com/solo-io/k8s-utils/kubeutils" "github.com/solo-io/solo-kit/pkg/errors" "github.com/solo-io/solo-kit/pkg/utils/kubeutils" corev1 "k8s.io/api/core/v1" @@ -34,6 +31,7 @@ type KubeUpstreamConverter struct { serviceConverters []serviceconverter.ServiceConverter } +// UpstreamsForService is called by the k8s uds plugin to convert a service to list of upstreams func (uc *KubeUpstreamConverter) UpstreamsForService(ctx context.Context, svc *corev1.Service) v1.UpstreamList { var upstreams v1.UpstreamList for _, port := range svc.Spec.Ports { @@ -42,6 +40,9 @@ func (uc *KubeUpstreamConverter) UpstreamsForService(ctx context.Context, svc *c return upstreams } +// CreateUpstream is called by both: +// - discovery (when creating an upstream from a k8s service) +// - controller code that converts services to in-memory upstreams func (uc *KubeUpstreamConverter) CreateUpstream(ctx context.Context, svc *corev1.Service, port corev1.ServicePort) *v1.Upstream { meta := svc.ObjectMeta coremeta := kubeutils.FromKubeMeta(meta, false) @@ -74,6 +75,10 @@ func (uc *KubeUpstreamConverter) CreateUpstream(ctx context.Context, svc *corev1 return us } +// UpstreamName creates an upstream name from a k8s Service name/namespace/port. +// +// This function is used in the context of both "real" upstreams written to etcd (e.g. upstreams created by UDS) +// as well as "fake" upstreams (i.e. those upstreams we only create in the in-memory input snapshot). func UpstreamName(serviceNamespace, serviceName string, servicePort int32) string { return sanitizer.SanitizeNameV2(fmt.Sprintf("%s-%s-%v", serviceNamespace, serviceName, servicePort)) } diff --git a/projects/gloo/pkg/plugins/linkerd/plugin.go b/projects/gloo/pkg/plugins/linkerd/plugin.go index 7c0dd50acd4..efcc0a77b64 100644 --- a/projects/gloo/pkg/plugins/linkerd/plugin.go +++ b/projects/gloo/pkg/plugins/linkerd/plugin.go @@ -13,7 +13,6 @@ import ( v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/kubernetes" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" ) var ( @@ -132,7 +131,7 @@ func configForMultiDestination( continue } header := createHeaderForUpstream(kubeUs) - clusterName := translator.UpstreamToClusterName(us.GetMetadata().Ref()) + clusterName := usconversions.UpstreamToClusterName(us) clusters := findClustersForName(clusterName, weightedCluster.GetClusters()) for _, cluster := range clusters { if _, ok := processedClusters[cluster.GetName()]; ok { diff --git a/projects/gloo/pkg/plugins/linkerd/plugin_test.go b/projects/gloo/pkg/plugins/linkerd/plugin_test.go index ec6f615de26..71ce7c01570 100644 --- a/projects/gloo/pkg/plugins/linkerd/plugin_test.go +++ b/projects/gloo/pkg/plugins/linkerd/plugin_test.go @@ -14,7 +14,7 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/kubernetes" "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/static" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" "github.com/solo-io/solo-kit/test/matchers" ) @@ -78,17 +78,17 @@ var _ = Describe("linkerd plugin", func() { } var clustersAndDestinationsForUpstreams = func( - upstreamRefs []*core.ResourceRef, + upstreams v1.UpstreamList, ) ([]*envoy_config_route_v3.WeightedCluster_ClusterWeight, []*v1.WeightedDestination) { - clusters := make([]*envoy_config_route_v3.WeightedCluster_ClusterWeight, len(upstreamRefs)) - for i, v := range upstreamRefs { + clusters := make([]*envoy_config_route_v3.WeightedCluster_ClusterWeight, len(upstreams)) + for i, up := range upstreams { clusters[i] = &envoy_config_route_v3.WeightedCluster_ClusterWeight{ - Name: translator.UpstreamToClusterName(v), + Name: glooupstreams.UpstreamToClusterName(up), } } - destinations := make([]*v1.WeightedDestination, len(upstreamRefs)) - for i, v := range upstreamRefs { - usRef := v + destinations := make([]*v1.WeightedDestination, len(upstreams)) + for i, up := range upstreams { + usRef := up.GetMetadata().Ref() destinations[i] = &v1.WeightedDestination{ Destination: &v1.Destination{ DestinationType: &v1.Destination_Upstream{ @@ -163,7 +163,8 @@ var _ = Describe("linkerd plugin", func() { {ServicePort: port, ServiceName: "two", ServiceNamespace: "one"}, {ServicePort: port, ServiceName: "three", ServiceNamespace: "one"}, } - clusters, destinations := clustersAndDestinationsForUpstreams(upstreamRefs) + upstreams := createUpstreamList(upstreamRefs, kubeSpecs) + clusters, destinations := clustersAndDestinationsForUpstreams(upstreams) out.Action = &envoy_config_route_v3.Route_Route{ Route: &envoy_config_route_v3.RouteAction{ ClusterSpecifier: &envoy_config_route_v3.RouteAction_WeightedClusters{ @@ -173,7 +174,6 @@ var _ = Describe("linkerd plugin", func() { }, }, } - upstreams := createUpstreamList(upstreamRefs, kubeSpecs) outCopy := proto.Clone(out) Expect(configForMultiDestination(destinations, upstreams, out)).To(Succeed()) Expect(out).NotTo(BeEquivalentTo(outCopy)) @@ -199,7 +199,8 @@ var _ = Describe("linkerd plugin", func() { {ServicePort: port, ServiceName: "two", ServiceNamespace: "one"}, nil, } - clusters, destinations := clustersAndDestinationsForUpstreams(upstreamRefs) + upstreams := createUpstreamList(upstreamRefs, kubeSpecs) + clusters, destinations := clustersAndDestinationsForUpstreams(upstreams) out.Action = &envoy_config_route_v3.Route_Route{ Route: &envoy_config_route_v3.RouteAction{ ClusterSpecifier: &envoy_config_route_v3.RouteAction_WeightedClusters{ @@ -209,7 +210,6 @@ var _ = Describe("linkerd plugin", func() { }, }, } - upstreams := createUpstreamList(upstreamRefs, kubeSpecs) outCopy := proto.Clone(out) Expect(configForMultiDestination(destinations, upstreams, out)).To(Succeed()) Expect(out).NotTo(BeEquivalentTo(outCopy)) @@ -242,7 +242,8 @@ var _ = Describe("linkerd plugin", func() { {ServicePort: port, ServiceName: "two", ServiceNamespace: "one"}, nil, } - clusters, _ := clustersAndDestinationsForUpstreams(upstreamRefs) + upstreams := createUpstreamList(upstreamRefs, kubeSpecs) + clusters, _ := clustersAndDestinationsForUpstreams(upstreams) out.Action = &envoy_config_route_v3.Route_Route{ Route: &envoy_config_route_v3.RouteAction{ ClusterSpecifier: &envoy_config_route_v3.RouteAction_WeightedClusters{ @@ -252,7 +253,6 @@ var _ = Describe("linkerd plugin", func() { }, }, } - upstreams := createUpstreamList(upstreamRefs, kubeSpecs) params.Snapshot = &v1snap.ApiSnapshot{ Upstreams: upstreams, } diff --git a/projects/gloo/pkg/plugins/ratelimit/plugin.go b/projects/gloo/pkg/plugins/ratelimit/plugin.go index 55ea6777293..1ad1fab14c9 100644 --- a/projects/gloo/pkg/plugins/ratelimit/plugin.go +++ b/projects/gloo/pkg/plugins/ratelimit/plugin.go @@ -115,12 +115,12 @@ func (p *plugin) HttpFilters(params plugins.Params, listener *v1.HttpListener) ( } // Make sure the server exists - _, err := params.Snapshot.Upstreams.Find(upstreamRef.GetNamespace(), upstreamRef.GetName()) + upstream, err := params.Snapshot.Upstreams.Find(upstreamRef.GetNamespace(), upstreamRef.GetName()) if err != nil { return nil, ServerNotFound(upstreamRef) } - rateLimitFilter := GenerateEnvoyHttpFilterConfig(serverSettings) + rateLimitFilter := generateEnvoyHttpFilterConfig(upstream, serverSettings) rateLimitFilterStage := GetFilterStageForRateLimitStage(rateLimitFilter.GetStage()) stagedRateLimitFilter, err := plugins.NewStagedFilter( @@ -137,11 +137,11 @@ func (p *plugin) HttpFilters(params plugins.Params, listener *v1.HttpListener) ( }, nil } -func GenerateEnvoyHttpFilterConfig(serverSettings *ratelimit.Settings) *envoy_extensions_filters_http_ratelimit_v3.RateLimit { +func generateEnvoyHttpFilterConfig(rlServerUpstream *v1.Upstream, serverSettings *ratelimit.Settings) *envoy_extensions_filters_http_ratelimit_v3.RateLimit { rateLimitStage := GetRateLimitStageForServerSettings(serverSettings) return GenerateEnvoyConfigForFilterWith( - serverSettings.GetRatelimitServerRef(), + rlServerUpstream, serverSettings.GetGrpcService(), CustomDomain, rateLimitStage, diff --git a/projects/gloo/pkg/plugins/ratelimit/plugin_test.go b/projects/gloo/pkg/plugins/ratelimit/plugin_test.go index d854097119e..db47d409589 100644 --- a/projects/gloo/pkg/plugins/ratelimit/plugin_test.go +++ b/projects/gloo/pkg/plugins/ratelimit/plugin_test.go @@ -20,7 +20,7 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/extauth" . "github.com/solo-io/gloo/projects/gloo/pkg/plugins/ratelimit" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" "github.com/solo-io/solo-kit/pkg/utils/prototime" "github.com/solo-io/solo-kit/test/matchers" @@ -33,13 +33,14 @@ var _ = Describe("RateLimit Plugin", func() { initParams plugins.InitParams params plugins.Params rlPlugin plugins.HttpFilterPlugin + rlServerUpstream *gloov1.Upstream rlServerRef *core.ResourceRef extAuthServerRef *core.ResourceRef ) BeforeEach(func() { rlPlugin = NewPlugin() - rlServerUpstream := &gloov1.Upstream{ + rlServerUpstream = &gloov1.Upstream{ Metadata: &core.Metadata{ Name: "rl-upstream", Namespace: "ns", @@ -123,7 +124,7 @@ var _ = Describe("RateLimit Plugin", func() { TransportApiVersion: envoycore.ApiVersion_V3, GrpcService: &envoycore.GrpcService{TargetSpecifier: &envoycore.GrpcService_EnvoyGrpc_{ EnvoyGrpc: &envoycore.GrpcService_EnvoyGrpc{ - ClusterName: translator.UpstreamToClusterName(rlServerRef), + ClusterName: upstreams.UpstreamToClusterName(rlServerUpstream), }, }}, }, @@ -154,7 +155,7 @@ var _ = Describe("RateLimit Plugin", func() { TransportApiVersion: envoycore.ApiVersion_V3, GrpcService: &envoycore.GrpcService{TargetSpecifier: &envoycore.GrpcService_EnvoyGrpc_{ EnvoyGrpc: &envoycore.GrpcService_EnvoyGrpc{ - ClusterName: translator.UpstreamToClusterName(rlServerRef), + ClusterName: upstreams.UpstreamToClusterName(rlServerUpstream), Authority: "xyz", }, }}, diff --git a/projects/gloo/pkg/plugins/ratelimit/util.go b/projects/gloo/pkg/plugins/ratelimit/util.go index 471bf8b9bf4..d307eba3e5f 100644 --- a/projects/gloo/pkg/plugins/ratelimit/util.go +++ b/projects/gloo/pkg/plugins/ratelimit/util.go @@ -5,13 +5,13 @@ import ( rlconfig "github.com/envoyproxy/go-control-plane/envoy/config/ratelimit/v3" envoyratelimit "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ratelimit/v3" "github.com/golang/protobuf/ptypes/duration" + gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/enterprise/options/ratelimit" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" - "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" ) func GenerateEnvoyConfigForFilterWith( - upstreamRef *core.ResourceRef, + upstream *gloov1.Upstream, grpcService *ratelimit.GrpcService, domain string, stage uint32, @@ -23,7 +23,7 @@ func GenerateEnvoyConfigForFilterWith( svc := &envoycore.GrpcService{ TargetSpecifier: &envoycore.GrpcService_EnvoyGrpc_{ EnvoyGrpc: &envoycore.GrpcService_EnvoyGrpc{ - ClusterName: translator.UpstreamToClusterName(upstreamRef), + ClusterName: upstreams.UpstreamToClusterName(upstream), Authority: grpcService.GetAuthority(), }, }} diff --git a/projects/gloo/pkg/plugins/registry/registry_test.go b/projects/gloo/pkg/plugins/registry/registry_test.go index 0ef3c120510..efb2f836a4b 100644 --- a/projects/gloo/pkg/plugins/registry/registry_test.go +++ b/projects/gloo/pkg/plugins/registry/registry_test.go @@ -151,11 +151,17 @@ func TestPluginsHttpFilterUsefulness(t *testing.T) { configuredListener, }, } - + upstream := &gloov1.Upstream{ + Metadata: &core.Metadata{ + Name: "upstream-name", + Namespace: "upstream-namespace", + }, + } params := plugins.Params{ Ctx: ctx, Snapshot: &gloov1snap.ApiSnapshot{ - Proxies: gloov1.ProxyList{proxy}, + Proxies: gloov1.ProxyList{proxy}, + Upstreams: gloov1.UpstreamList{upstream}, }, } // Filters should not be added to this map without due consideration diff --git a/projects/gloo/pkg/plugins/rest/plugin.go b/projects/gloo/pkg/plugins/rest/plugin.go index 906e501c141..c7fb1090eef 100644 --- a/projects/gloo/pkg/plugins/rest/plugin.go +++ b/projects/gloo/pkg/plugins/rest/plugin.go @@ -11,7 +11,6 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins/pluginutils" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/transformation" transformutils "github.com/solo-io/gloo/projects/gloo/pkg/plugins/utils/transformation" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/go-utils/contextutils" "github.com/solo-io/solo-kit/pkg/errors" @@ -69,7 +68,7 @@ func (p *plugin) ProcessUpstream(params plugins.Params, in *v1.Upstream, _ *envo if restServiceSpec.Rest == nil { return errors.Errorf("%v has an empty rest service spec", in.GetMetadata().Ref()) } - p.recordedUpstreams[translator.UpstreamToClusterName(in.GetMetadata().Ref())] = restServiceSpec + p.recordedUpstreams[in.GetMetadata().Ref().Key()] = restServiceSpec } return nil } @@ -92,7 +91,7 @@ func (p *plugin) ProcessRoute(params plugins.RouteParams, in *v1.Route, out *env contextutils.LoggerFrom(params.Ctx).Error(err) return nil, err } - restServiceSpec, ok := p.recordedUpstreams[translator.UpstreamToClusterName(upstreamRef)] + restServiceSpec, ok := p.recordedUpstreams[upstreamRef.Key()] if !ok { return nil, errors.Errorf("%s does not have a rest service spec", upstreamRef) } diff --git a/projects/gloo/pkg/plugins/shadowing/plugin.go b/projects/gloo/pkg/plugins/shadowing/plugin.go index 6c1cd0f3547..f630f63f470 100644 --- a/projects/gloo/pkg/plugins/shadowing/plugin.go +++ b/projects/gloo/pkg/plugins/shadowing/plugin.go @@ -8,7 +8,8 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/shadowing" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/internal/common" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/plugins/pluginutils" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" ) var ( @@ -60,19 +61,24 @@ func (p *plugin) ProcessRoute(params plugins.RouteParams, in *v1.Route, out *env } outRa = out.GetRoute() } - return applyShadowSpec(outRa, shadowSpec) + allUpstreams := params.Snapshot.Upstreams + return applyShadowSpec(allUpstreams, outRa, shadowSpec) } -func applyShadowSpec(out *envoy_config_route_v3.RouteAction, spec *shadowing.RouteShadowing) error { +func applyShadowSpec(allUpstreams v1.UpstreamList, out *envoy_config_route_v3.RouteAction, spec *shadowing.RouteShadowing) error { if spec.GetUpstream() == nil { return UnspecifiedUpstreamError } if spec.GetPercentage() < 0 || spec.GetPercentage() > 100 { return InvalidNumeratorError(spec.GetPercentage()) } + upstream, err := allUpstreams.Find(spec.GetUpstream().GetNamespace(), spec.GetUpstream().GetName()) + if err != nil { + return pluginutils.NewUpstreamNotFoundErr(spec.GetUpstream()) + } out.RequestMirrorPolicies = []*envoy_config_route_v3.RouteAction_RequestMirrorPolicy{ { - Cluster: translator.UpstreamToClusterName(spec.GetUpstream()), + Cluster: upstreams.UpstreamToClusterName(upstream), RuntimeFraction: getFractionalPercent(spec.GetPercentage()), }, } diff --git a/projects/gloo/pkg/plugins/shadowing/plugin_test.go b/projects/gloo/pkg/plugins/shadowing/plugin_test.go index 18977210f10..735c93369b1 100644 --- a/projects/gloo/pkg/plugins/shadowing/plugin_test.go +++ b/projects/gloo/pkg/plugins/shadowing/plugin_test.go @@ -6,6 +6,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" + v1snap "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/gloosnapshot" "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/shadowing" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" . "github.com/solo-io/go-utils/testutils" @@ -14,6 +15,29 @@ import ( var _ = Describe("Plugin", func() { + var ( + params plugins.RouteParams + ) + + BeforeEach(func() { + params = plugins.RouteParams{ + VirtualHostParams: plugins.VirtualHostParams{ + Params: plugins.Params{ + Snapshot: &v1snap.ApiSnapshot{ + Upstreams: v1.UpstreamList{ + { + Metadata: &core.Metadata{ + Name: "some-upstream", + Namespace: "default", + }, + }, + }, + }, + }, + }, + } + }) + It("should work on valid inputs, with uninitialized outputs", func() { p := NewPlugin() @@ -30,7 +54,7 @@ var _ = Describe("Plugin", func() { }, } out := &envoy_config_route_v3.Route{} - err := p.ProcessRoute(plugins.RouteParams{}, in, out) + err := p.ProcessRoute(params, in, out) Expect(err).NotTo(HaveOccurred()) checkFraction(out.GetRoute().GetRequestMirrorPolicies()[0].GetRuntimeFraction(), 100) Expect(out.GetRoute().GetRequestMirrorPolicies()[0].GetCluster()).To(Equal("some-upstream_default")) @@ -58,7 +82,7 @@ var _ = Describe("Plugin", func() { }, }, } - err := p.ProcessRoute(plugins.RouteParams{}, in, out) + err := p.ProcessRoute(params, in, out) Expect(err).NotTo(HaveOccurred()) checkFraction(out.GetRoute().GetRequestMirrorPolicies()[0].RuntimeFraction, 100) Expect(out.GetRoute().GetRequestMirrorPolicies()[0].Cluster).To(Equal("some-upstream_default")) @@ -69,7 +93,7 @@ var _ = Describe("Plugin", func() { p := NewPlugin() in := &v1.Route{} out := &envoy_config_route_v3.Route{} - err := p.ProcessRoute(plugins.RouteParams{}, in, out) + err := p.ProcessRoute(params, in, out) Expect(err).NotTo(HaveOccurred()) }) @@ -94,7 +118,7 @@ var _ = Describe("Plugin", func() { Redirect: &envoy_config_route_v3.RedirectAction{}, }, } - err := p.ProcessRoute(plugins.RouteParams{}, in, out) + err := p.ProcessRoute(params, in, out) Expect(err).To(HaveOccurred()) Expect(err).To(HaveInErrorChain(InvalidRouteActionError)) @@ -104,7 +128,7 @@ var _ = Describe("Plugin", func() { DirectResponse: &envoy_config_route_v3.DirectResponseAction{}, }, } - err = p.ProcessRoute(plugins.RouteParams{}, in, out) + err = p.ProcessRoute(params, in, out) Expect(err).To(HaveOccurred()) Expect(err).To(HaveInErrorChain(InvalidRouteActionError)) }) @@ -125,7 +149,7 @@ var _ = Describe("Plugin", func() { }, } out := &envoy_config_route_v3.Route{} - err := p.ProcessRoute(plugins.RouteParams{}, in, out) + err := p.ProcessRoute(params, in, out) Expect(err).To(HaveOccurred()) Expect(err).To(HaveInErrorChain(InvalidNumeratorError(200))) @@ -137,7 +161,7 @@ var _ = Describe("Plugin", func() { }, } out = &envoy_config_route_v3.Route{} - err = p.ProcessRoute(plugins.RouteParams{}, in, out) + err = p.ProcessRoute(params, in, out) Expect(err).To(HaveOccurred()) Expect(err).To(HaveInErrorChain(UnspecifiedUpstreamError)) }) diff --git a/projects/gloo/pkg/plugins/tcp/plugin.go b/projects/gloo/pkg/plugins/tcp/plugin.go index 13d282c5f1e..a4074f466ef 100644 --- a/projects/gloo/pkg/plugins/tcp/plugin.go +++ b/projects/gloo/pkg/plugins/tcp/plugin.go @@ -150,11 +150,15 @@ func (p *plugin) tcpProxyFilters( if err != nil { return nil, err } + upstream, err := params.Snapshot.Upstreams.Find(usRef.GetNamespace(), usRef.GetName()) + if err != nil { + return nil, pluginutils.NewUpstreamNotFoundErr(usRef) + } cfg.ClusterSpecifier = &envoytcp.TcpProxy_Cluster{ - Cluster: translatorutil.UpstreamToClusterName(usRef), + Cluster: usconversion.UpstreamToClusterName(upstream), } case *v1.TcpHost_TcpAction_Multi: - wc, err := p.convertToWeightedCluster(dest.Multi) + wc, err := p.convertToWeightedCluster(params.Snapshot.Upstreams, dest.Multi) if err != nil { return nil, err } @@ -171,7 +175,7 @@ func (p *plugin) tcpProxyFilters( Destinations: upstreamGroup.GetDestinations(), } - wc, err := p.convertToWeightedCluster(md) + wc, err := p.convertToWeightedCluster(params.Snapshot.Upstreams, md) if err != nil { return nil, err } @@ -213,7 +217,7 @@ func (p *plugin) tcpProxyFilters( return filters, nil } -func (p *plugin) convertToWeightedCluster(multiDest *v1.MultiDestination) (*envoytcp.TcpProxy_WeightedCluster, error) { +func (p *plugin) convertToWeightedCluster(allUpstreams v1.UpstreamList, multiDest *v1.MultiDestination) (*envoytcp.TcpProxy_WeightedCluster, error) { if len(multiDest.GetDestinations()) == 0 { return nil, translatorutil.NoDestinationSpecifiedError } @@ -225,9 +229,12 @@ func (p *plugin) convertToWeightedCluster(multiDest *v1.MultiDestination) (*envo if err != nil { return nil, err } - + upstream, err := allUpstreams.Find(usRef.GetNamespace(), usRef.GetName()) + if err != nil { + return nil, pluginutils.NewUpstreamNotFoundErr(usRef) + } wc[i] = &envoytcp.TcpProxy_WeightedCluster_ClusterWeight{ - Name: translatorutil.UpstreamToClusterName(usRef), + Name: usconversion.UpstreamToClusterName(upstream), Weight: weightedDest.GetWeight().GetValue(), } } diff --git a/projects/gloo/pkg/plugins/tcp/plugin_test.go b/projects/gloo/pkg/plugins/tcp/plugin_test.go index b3ccb57e1a9..67ec2702b05 100644 --- a/projects/gloo/pkg/plugins/tcp/plugin_test.go +++ b/projects/gloo/pkg/plugins/tcp/plugin_test.go @@ -21,6 +21,7 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins" . "github.com/solo-io/gloo/projects/gloo/pkg/plugins/tcp" translatorutil "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" mock_utils "github.com/solo-io/gloo/projects/gloo/pkg/utils/mocks" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" @@ -51,8 +52,11 @@ var _ = Describe("Plugin", func() { Context("listener filter chain plugin", func() { var ( - snap *v1snap.ApiSnapshot - tcps *tcp.TcpProxySettings + snap *v1snap.ApiSnapshot + tcps *tcp.TcpProxySettings + upstream1 *v1.Upstream + upstream2 *v1.Upstream + upstream3 *v1.Upstream ns = "one" wd = []*v1.WeightedDestination{ @@ -82,26 +86,29 @@ var _ = Describe("Plugin", func() { ) BeforeEach(func() { + upstream1 = &v1.Upstream{ + Metadata: &core.Metadata{ + Name: "one", + Namespace: ns, + }, + } + upstream2 = &v1.Upstream{ + Metadata: &core.Metadata{ + Name: "two", + Namespace: ns, + }, + } + upstream3 = &v1.Upstream{ + Metadata: &core.Metadata{ + Name: "three", + Namespace: ns, + }, + } snap = &v1snap.ApiSnapshot{ Upstreams: v1.UpstreamList{ - { - Metadata: &core.Metadata{ - Name: "one", - Namespace: ns, - }, - }, - { - Metadata: &core.Metadata{ - Name: "two", - Namespace: ns, - }, - }, - { - Metadata: &core.Metadata{ - Name: "three", - Namespace: ns, - }, - }, + upstream1, + upstream2, + upstream3, }, } tcps = &tcp.TcpProxySettings{ @@ -235,7 +242,7 @@ var _ = Describe("Plugin", func() { err = translatorutil.ParseTypedConfig(filterChains[0].Filters[0], &cfg) Expect(err).NotTo(HaveOccurred()) cluster := cfg.GetCluster() - Expect(cluster).To(Equal(translatorutil.UpstreamToClusterName(&core.ResourceRef{Namespace: ns, Name: "one"}))) + Expect(cluster).To(Equal(glooupstreams.UpstreamToClusterName(upstream1))) }) It("can transform a multi destination", func() { @@ -259,9 +266,9 @@ var _ = Describe("Plugin", func() { Expect(err).NotTo(HaveOccurred()) clusters := cfg.GetWeightedClusters() Expect(clusters.Clusters).To(HaveLen(2)) - Expect(clusters.Clusters[0].Name).To(Equal(translatorutil.UpstreamToClusterName(&core.ResourceRef{Namespace: ns, Name: "one"}))) + Expect(clusters.Clusters[0].Name).To(Equal(glooupstreams.UpstreamToClusterName(upstream1))) Expect(clusters.Clusters[0].Weight).To(Equal(uint32(5))) - Expect(clusters.Clusters[1].Name).To(Equal(translatorutil.UpstreamToClusterName(&core.ResourceRef{Namespace: ns, Name: "two"}))) + Expect(clusters.Clusters[1].Name).To(Equal(glooupstreams.UpstreamToClusterName(upstream2))) Expect(clusters.Clusters[1].Weight).To(Equal(uint32(1))) }) @@ -294,9 +301,9 @@ var _ = Describe("Plugin", func() { Expect(err).NotTo(HaveOccurred()) clusters := cfg.GetWeightedClusters() Expect(clusters.Clusters).To(HaveLen(2)) - Expect(clusters.Clusters[0].Name).To(Equal(translatorutil.UpstreamToClusterName(&core.ResourceRef{Namespace: ns, Name: "one"}))) + Expect(clusters.Clusters[0].Name).To(Equal(glooupstreams.UpstreamToClusterName(upstream1))) Expect(clusters.Clusters[0].Weight).To(Equal(uint32(5))) - Expect(clusters.Clusters[1].Name).To(Equal(translatorutil.UpstreamToClusterName(&core.ResourceRef{Namespace: ns, Name: "two"}))) + Expect(clusters.Clusters[1].Name).To(Equal(glooupstreams.UpstreamToClusterName(upstream2))) Expect(clusters.Clusters[1].Weight).To(Equal(uint32(1))) }) diff --git a/projects/gloo/pkg/plugins/tracing/plugin.go b/projects/gloo/pkg/plugins/tracing/plugin.go index 5c32447cd3b..53ed225cc72 100644 --- a/projects/gloo/pkg/plugins/tracing/plugin.go +++ b/projects/gloo/pkg/plugins/tracing/plugin.go @@ -17,7 +17,7 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/internal/common" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/pluginutils" - translatorutil "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" ) @@ -306,12 +306,12 @@ func getEnvoyTracingCollectorClusterName(snapshot *v1snap.ApiSnapshot, collector } // Make sure the upstream exists - _, err := snapshot.Upstreams.Find(collectorUpstreamRef.GetNamespace(), collectorUpstreamRef.GetName()) + upstream, err := snapshot.Upstreams.Find(collectorUpstreamRef.GetNamespace(), collectorUpstreamRef.GetName()) if err != nil { return "", pluginutils.NewUpstreamNotFoundErr(collectorUpstreamRef) } - return translatorutil.UpstreamToClusterName(collectorUpstreamRef), nil + return upstreams.UpstreamToClusterName(upstream), nil } func envoySimplePercent(numerator float32) *envoy_type.Percent { diff --git a/projects/gloo/pkg/plugins/tunneling/plugin.go b/projects/gloo/pkg/plugins/tunneling/plugin.go index 8b1ecdeedec..e1934f65767 100644 --- a/projects/gloo/pkg/plugins/tunneling/plugin.go +++ b/projects/gloo/pkg/plugins/tunneling/plugin.go @@ -12,7 +12,7 @@ import ( "github.com/golang/protobuf/ptypes/wrappers" "github.com/solo-io/gloo/projects/gloo/constants" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" "k8s.io/apimachinery/pkg/util/sets" ) @@ -63,7 +63,7 @@ func (p *plugin) GeneratedResources(params plugins.Params, // we do not handle the weighted cluster or cluster header cases if cluster := rtAction.GetCluster(); cluster != "" { - ref, err := translator.ClusterToUpstreamRef(cluster) + ref, err := glooupstreams.ClusterToUpstreamRef(cluster) if err != nil { // return what we have so far, so that any modified input resources can still route // successfully to their generated targets diff --git a/projects/gloo/pkg/plugins/tunneling/plugin_test.go b/projects/gloo/pkg/plugins/tunneling/plugin_test.go index 6d7d7887552..3d77494a532 100644 --- a/projects/gloo/pkg/plugins/tunneling/plugin_test.go +++ b/projects/gloo/pkg/plugins/tunneling/plugin_test.go @@ -14,7 +14,7 @@ import ( v1snap "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/gloosnapshot" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/tunneling" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" "github.com/solo-io/skv2/test/matchers" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" @@ -68,7 +68,7 @@ var _ = Describe("Plugin", func() { Action: &envoy_config_route_v3.Route_Route{ Route: &envoy_config_route_v3.RouteAction{ ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{ - Cluster: translator.UpstreamToClusterName(us.Metadata.Ref()), + Cluster: glooupstreams.UpstreamToClusterName(us), }, }, }, @@ -80,7 +80,7 @@ var _ = Describe("Plugin", func() { } // use UpstreamToClusterName to emulate a real translation loop. - clusterName := translator.UpstreamToClusterName(us.Metadata.Ref()) + clusterName := glooupstreams.UpstreamToClusterName(us) inClusters = []*envoy_config_cluster_v3.Cluster{ { Name: clusterName, @@ -160,7 +160,7 @@ var _ = Describe("Plugin", func() { dupRoute.Action = &envoy_config_route_v3.Route_Route{ Route: &envoy_config_route_v3.RouteAction{ ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{ - Cluster: translator.UpstreamToClusterName(us.Metadata.Ref()), + Cluster: glooupstreams.UpstreamToClusterName(us), }, }, } @@ -193,7 +193,7 @@ var _ = Describe("Plugin", func() { cpRoute.Action = &envoy_config_route_v3.Route_Route{ Route: &envoy_config_route_v3.RouteAction{ ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{ - Cluster: translator.UpstreamToClusterName(usCopy.Metadata.Ref()), + Cluster: glooupstreams.UpstreamToClusterName(usCopy), }, }, } @@ -202,7 +202,7 @@ var _ = Describe("Plugin", func() { // update cluster input such that copied cluster's name matches the copied upstream inCluster := inClusters[0] cpCluster := proto.Clone(inCluster).(*envoy_config_cluster_v3.Cluster) - cpCluster.Name = translator.UpstreamToClusterName(usCopy.Metadata.Ref()) + cpCluster.Name = glooupstreams.UpstreamToClusterName(usCopy) inClusters = append(inClusters, cpCluster) }) diff --git a/projects/gloo/pkg/syncer/sanitizer/route_replacing_sanitizer.go b/projects/gloo/pkg/syncer/sanitizer/route_replacing_sanitizer.go index 0472c3b7203..858ef18adf4 100644 --- a/projects/gloo/pkg/syncer/sanitizer/route_replacing_sanitizer.go +++ b/projects/gloo/pkg/syncer/sanitizer/route_replacing_sanitizer.go @@ -24,6 +24,7 @@ import ( v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" "github.com/solo-io/gloo/projects/gloo/pkg/syncer/stats" "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" glooutils "github.com/solo-io/gloo/projects/gloo/pkg/utils" validationutils "github.com/solo-io/gloo/projects/gloo/pkg/utils/validation" "github.com/solo-io/gloo/projects/gloo/pkg/xds" @@ -242,8 +243,8 @@ func getClusters(glooSnapshot *v1snap.ApiSnapshot, xdsSnapshot envoycache.Snapsh validClusters := make(map[string]struct{}) xdsClusters := xdsSnapshot.GetResources(types.ClusterTypeV3) - for _, up := range glooSnapshot.Upstreams.AsInputResources() { - clusterName := translator.UpstreamToClusterName(up.GetMetadata().Ref()) + for _, up := range glooSnapshot.Upstreams { + clusterName := upstreams.UpstreamToClusterName(up) if xdsClusters.Items[clusterName] != nil { validClusters[clusterName] = struct{}{} } diff --git a/projects/gloo/pkg/syncer/sanitizer/route_replacing_sanitizer_test.go b/projects/gloo/pkg/syncer/sanitizer/route_replacing_sanitizer_test.go index 904db77771b..85705be2f55 100644 --- a/projects/gloo/pkg/syncer/sanitizer/route_replacing_sanitizer_test.go +++ b/projects/gloo/pkg/syncer/sanitizer/route_replacing_sanitizer_test.go @@ -15,7 +15,7 @@ import ( "github.com/rotisserie/eris" v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" v1snap "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/gloosnapshot" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" validationutils "github.com/solo-io/gloo/projects/gloo/pkg/utils/validation" "github.com/solo-io/gloo/projects/gloo/pkg/xds" @@ -35,7 +35,7 @@ var _ = Describe("RouteReplacingSanitizer", func() { Namespace: "upstream", }, } - clusterName = translator.UpstreamToClusterName(us.Metadata.Ref()) + clusterName = upstreams.UpstreamToClusterName(us) missingCluster = "missing_cluster" diff --git a/projects/gloo/pkg/syncer/sanitizer/upstream_removing_sanitizer.go b/projects/gloo/pkg/syncer/sanitizer/upstream_removing_sanitizer.go index c87d9c949f8..beac7da95ef 100644 --- a/projects/gloo/pkg/syncer/sanitizer/upstream_removing_sanitizer.go +++ b/projects/gloo/pkg/syncer/sanitizer/upstream_removing_sanitizer.go @@ -7,7 +7,7 @@ import ( "github.com/solo-io/gloo/pkg/utils/statsutils" v1snap "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/gloosnapshot" "github.com/solo-io/gloo/projects/gloo/pkg/syncer/stats" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/xds" "github.com/solo-io/go-utils/contextutils" envoycache "github.com/solo-io/solo-kit/pkg/api/v1/control-plane/cache" @@ -53,11 +53,11 @@ func (s *UpstreamRemovingSanitizer) SanitizeSnapshot( var removed int64 // Find all the errored upstreams and remove them from the xDS snapshot - for _, up := range glooSnapshot.Upstreams.AsInputResources() { + for _, up := range glooSnapshot.Upstreams { if reports[up].Errors != nil { - clusterName := translator.UpstreamToClusterName(up.GetMetadata().Ref()) + clusterName := upstreams.UpstreamToClusterName(up) if clusters.Items[clusterName] == nil { // cluster has already been removed from the snapshot contextutils.LoggerFrom(ctx).Debugf("cluster %s does not exist in the xds snapshot", clusterName) @@ -92,7 +92,7 @@ func (s *UpstreamRemovingSanitizer) SanitizeSnapshot( ) // Convert errors related to upstreams to warnings - for _, up := range glooSnapshot.Upstreams.AsInputResources() { + for _, up := range glooSnapshot.Upstreams { if upReport := reports[up]; upReport.Errors != nil { upReport.Warnings = []string{upReport.Errors.Error()} upReport.Errors = nil diff --git a/projects/gloo/pkg/syncer/sanitizer/upstream_removing_sanitizer_test.go b/projects/gloo/pkg/syncer/sanitizer/upstream_removing_sanitizer_test.go index 702abd1faae..3f09d3207b6 100644 --- a/projects/gloo/pkg/syncer/sanitizer/upstream_removing_sanitizer_test.go +++ b/projects/gloo/pkg/syncer/sanitizer/upstream_removing_sanitizer_test.go @@ -11,7 +11,7 @@ import ( . "github.com/onsi/gomega" "github.com/rotisserie/eris" v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/xds" envoycache "github.com/solo-io/solo-kit/pkg/api/v1/control-plane/cache" "github.com/solo-io/solo-kit/pkg/api/v1/control-plane/resource" @@ -33,7 +33,7 @@ var _ = Describe("UpstreamRemovingSanitizer", func() { clusterType = &envoy_config_cluster_v3.Cluster_Type{ Type: envoy_config_cluster_v3.Cluster_EDS, } - goodClusterName = translator.UpstreamToClusterName(us.Metadata.Ref()) + goodClusterName = upstreams.UpstreamToClusterName(us) goodCluster = &envoyclusterapi.Cluster{ Name: goodClusterName, ClusterDiscoveryType: clusterType, @@ -51,7 +51,7 @@ var _ = Describe("UpstreamRemovingSanitizer", func() { Namespace: "upstream", }, } - badClusterName = translator.UpstreamToClusterName(badUs.Metadata.Ref()) + badClusterName = upstreams.UpstreamToClusterName(badUs) badCluster = &envoyclusterapi.Cluster{ Name: badClusterName, ClusterDiscoveryType: clusterType, diff --git a/projects/gloo/pkg/translator/clusters.go b/projects/gloo/pkg/translator/clusters.go index 697ca6fccff..b612a203065 100644 --- a/projects/gloo/pkg/translator/clusters.go +++ b/projects/gloo/pkg/translator/clusters.go @@ -20,6 +20,7 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/ssl" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" upstream_proxy_protocol "github.com/solo-io/gloo/projects/gloo/pkg/plugins/utils/upstreamproxyprotocol" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" "github.com/solo-io/gloo/projects/gloo/pkg/xds" "github.com/solo-io/go-utils/contextutils" @@ -69,7 +70,7 @@ func (t *translatorInstance) computeClusters( } // This function is intented to be used when translating a single upstream outside of the context of a full snapshot. -// This happens in GGv2 krt implementation. +// This happens in the kube gateway krt implementation. func (t *translatorInstance) TranslateCluster( params plugins.Params, upstream *v1.Upstream, @@ -140,7 +141,7 @@ func (t *translatorInstance) initializeCluster( circuitBreakers := t.settings.GetGloo().GetCircuitBreakers() out := &envoy_config_cluster_v3.Cluster{ - Name: UpstreamToClusterName(upstream.GetMetadata().Ref()), + Name: glooupstreams.UpstreamToClusterName(upstream), Metadata: new(envoy_config_core_v3.Metadata), CircuitBreakers: getCircuitBreakers(upstream.GetCircuitBreakers(), circuitBreakers), LbSubsetConfig: createLbConfig(upstream), @@ -419,11 +420,11 @@ func validateUpstreamLambdaFunctions(proxy *v1.Proxy, upstreams v1.UpstreamList, for _, upstream := range upstreams { lambdaFuncs := upstream.GetAws().GetLambdaFunctions() for _, lambda := range lambdaFuncs { - upstreamRef := UpstreamToClusterName(upstream.GetMetadata().Ref()) - if upstreamLambdas[upstreamRef] == nil { - upstreamLambdas[upstreamRef] = make(map[string]bool) + upstreamKey := upstream.GetMetadata().Ref().Key() + if upstreamLambdas[upstreamKey] == nil { + upstreamLambdas[upstreamKey] = make(map[string]bool) } - upstreamLambdas[upstreamRef][lambda.GetLogicalName()] = true + upstreamLambdas[upstreamKey][lambda.GetLogicalName()] = true } } @@ -499,11 +500,11 @@ func validateRouteDestinationForValidLambdas( // Process destinations (upstreams) for _, dest := range destinations { - routeUpstream := dest.GetUpstream() + routeUpstreamRef := dest.GetUpstream() // Check that route is pointing to current upstream - if routeUpstream != nil { + if routeUpstreamRef != nil { // Get the lambda functions that this upstream has - lambdaFuncSet := upstreamLambdas[UpstreamToClusterName(routeUpstream)] + lambdaFuncSet := upstreamLambdas[routeUpstreamRef.Key()] routeLambda := dest.GetDestinationSpec().GetAws() routeLambdaName := routeLambda.GetLogicalName() // If route is pointing to a lambda that does not exist on this upstream, report error on the upstream diff --git a/projects/gloo/pkg/translator/endpoints.go b/projects/gloo/pkg/translator/endpoints.go index afc525804a3..90ccd6079d2 100644 --- a/projects/gloo/pkg/translator/endpoints.go +++ b/projects/gloo/pkg/translator/endpoints.go @@ -6,6 +6,7 @@ import ( structpb "github.com/golang/protobuf/ptypes/struct" "github.com/solo-io/gloo/projects/gloo/constants" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/solo-kit/pkg/api/v2/reporter" "go.opencensus.io/trace" @@ -52,7 +53,7 @@ func loadAssignmentForUpstream( clusterEndpoints []*v1.Endpoint, enableAutoMtls bool, ) *envoy_config_endpoint_v3.ClusterLoadAssignment { - clusterName := UpstreamToClusterName(upstream.GetMetadata().Ref()) + clusterName := glooupstreams.UpstreamToClusterName(upstream) var endpoints []*envoy_config_endpoint_v3.LbEndpoint for _, addr := range clusterEndpoints { // Get the metadata labels and filter metadata for the envoy load balancer based on the upstream diff --git a/projects/gloo/pkg/translator/route_config.go b/projects/gloo/pkg/translator/route_config.go index 94ed3158348..c11f1f32f0e 100644 --- a/projects/gloo/pkg/translator/route_config.go +++ b/projects/gloo/pkg/translator/route_config.go @@ -429,7 +429,17 @@ func (h *httpRouteConfigurationTranslator) setRouteAction( if err != nil { return err } - out.GetClusterSpecifier().(*envoy_config_route_v3.RouteAction_Cluster).Cluster = UpstreamToClusterName(usRef) + var clusterName string + upstream, err := params.Snapshot.Upstreams.Find(usRef.GetNamespace(), usRef.GetName()) + if err != nil { + // we don't want to return early here, as it will skip further translation and change existing behavior. + // so if there's an error, fall back to returning the "legacy" cluster name format that is based on the + // upstream ref (there won't be an actual cluster with this name, since the upstream doesn't exist). + clusterName = utils.ResourceRefToKey(usRef) + } else { + clusterName = usconversion.UpstreamToClusterName(upstream) + } + out.GetClusterSpecifier().(*envoy_config_route_v3.RouteAction_Cluster).Cluster = clusterName out.MetadataMatch = getSubsetMatch(dest.Single) @@ -489,6 +499,16 @@ func (h *httpRouteConfigurationTranslator) setWeightedClusters( if err != nil { return err } + var clusterName string + upstream, err := params.Snapshot.Upstreams.Find(usRef.GetNamespace(), usRef.GetName()) + if err != nil { + // we don't want to return early here, as it will skip further translation and change existing behavior. + // so if there's an error, fall back to returning the "legacy" cluster name format that is based on the + // upstream ref (there won't be an actual cluster with this name, since the upstream doesn't exist). + clusterName = utils.ResourceRefToKey(usRef) + } else { + clusterName = usconversion.UpstreamToClusterName(upstream) + } //Cluster weight can be nil so check if end user did not pass a weight for destination and set the default weight of 0 var clusterWeight uint32 @@ -499,7 +519,7 @@ func (h *httpRouteConfigurationTranslator) setWeightedClusters( totalWeight += weightedDest.GetWeight().GetValue() weightedCluster := &envoy_config_route_v3.WeightedCluster_ClusterWeight{ - Name: UpstreamToClusterName(usRef), + Name: clusterName, Weight: &wrappers.UInt32Value{Value: clusterWeight}, MetadataMatch: getSubsetMatch(weightedDest.GetDestination()), } diff --git a/projects/gloo/pkg/translator/translator.go b/projects/gloo/pkg/translator/translator.go index e230ad24890..f92fd153056 100644 --- a/projects/gloo/pkg/translator/translator.go +++ b/projects/gloo/pkg/translator/translator.go @@ -21,6 +21,7 @@ import ( validationapi "github.com/solo-io/gloo/projects/gloo/pkg/api/grpc/validation" v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" "github.com/solo-io/gloo/projects/gloo/pkg/plugins" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/utils" "github.com/solo-io/gloo/projects/gloo/pkg/utils/validation" "github.com/solo-io/gloo/projects/gloo/pkg/xds" @@ -28,7 +29,6 @@ import ( "github.com/solo-io/protoc-gen-ext/pkg/hasher/hashstructure" envoycache "github.com/solo-io/solo-kit/pkg/api/v1/control-plane/cache" "github.com/solo-io/solo-kit/pkg/api/v1/control-plane/resource" - "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" "github.com/solo-io/solo-kit/pkg/api/v2/reporter" "go.opencensus.io/trace" proto2 "google.golang.org/protobuf/proto" @@ -54,9 +54,7 @@ type ClusterTranslator interface { ) (*envoy_config_cluster_v3.Cluster, []error) } -var ( - _ Translator = new(translatorInstance) -) +var _ Translator = new(translatorInstance) // translatorInstance is the implementation for a Translator used during Gloo translation type translatorInstance struct { @@ -68,10 +66,6 @@ type translatorInstance struct { shouldEnforceNamespaceMatch bool } -func NewDefaultTranslator(settings *v1.Settings, pluginRegistry plugins.PluginRegistry) *translatorInstance { - return NewTranslatorWithHasher(utils.NewSslConfigTranslator(), settings, pluginRegistry, EnvoyCacheResourcesListToFnvHash) -} - func NewTranslatorWithHasher( sslConfigTranslator utils.SslConfigTranslator, settings *v1.Settings, @@ -87,6 +81,7 @@ func NewTranslatorWithHasher( // TODO: what to do here? } } + return &translatorInstance{ lock: sync.Mutex{}, pluginRegistry: pluginRegistry, @@ -179,21 +174,17 @@ func (t *translatorInstance) translateClusterSubsystemComponents(params plugins. upstreamRefKeyToEndpoints := createUpstreamToEndpointsMap(params.Snapshot.Upstreams, params.Snapshot.Endpoints) - // endpoints and listeners are shared between listeners + // endpoints and clusters are shared between listeners logger.Debugf("computing envoy clusters for proxy: %v", proxy.GetMetadata().GetName()) clusters, clusterToUpstreamMap := t.computeClusters(params, reports, upstreamRefKeyToEndpoints, proxy) logger.Debugf("computing envoy endpoints for proxy: %v", proxy.GetMetadata().GetName()) - endpoints := t.computeClusterEndpoints(params, upstreamRefKeyToEndpoints, reports) - upstreamMap := make(map[string]struct{}, len(params.Snapshot.Upstreams)) + clusterMap := make(map[string]struct{}, len(params.Snapshot.Upstreams)) // make sure to call EndpointPlugin with empty endpoint for _, upstream := range params.Snapshot.Upstreams { - key := UpstreamToClusterName(&core.ResourceRef{ - Name: upstream.GetMetadata().GetName(), - Namespace: upstream.GetMetadata().GetNamespace(), - }) - upstreamMap[key] = struct{}{} + key := upstreams.UpstreamToClusterName(upstream) + clusterMap[key] = struct{}{} } endpointMap := make(map[string][]*envoy_config_endpoint_v3.ClusterLoadAssignment, len(endpoints)) for _, ep := range endpoints { @@ -231,7 +222,7 @@ ClusterLoop: ClusterName: endpointClusterName, } // make sure to call EndpointPlugin with empty endpoint - if _, ok := upstreamMap[c.GetName()]; ok { + if _, ok := clusterMap[c.GetName()]; ok { for _, plugin := range t.pluginRegistry.GetEndpointPlugins() { if err := plugin.ProcessEndpoints(params, upstream, emptyEndpointList); err != nil { reports.AddError(upstream, err) diff --git a/projects/gloo/pkg/translator/translator_test.go b/projects/gloo/pkg/translator/translator_test.go index 62a3e934625..aa32bfc7180 100644 --- a/projects/gloo/pkg/translator/translator_test.go +++ b/projects/gloo/pkg/translator/translator_test.go @@ -78,6 +78,7 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/plugins" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/registry" . "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/projects/gloo/pkg/upstreams/consul" mock_consul "github.com/solo-io/gloo/projects/gloo/pkg/upstreams/consul/mocks" "github.com/solo-io/gloo/projects/gloo/pkg/upstreams/kubernetes" @@ -410,7 +411,7 @@ var _ = Describe("Translator", func() { ExpectWithOffset(1, report).To(Equal(validationutils.MakeReport(proxy))) clusters := snap.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster = clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) ExpectWithOffset(1, cluster).NotTo(BeNil()) @@ -1329,7 +1330,7 @@ var _ = Describe("Translator", func() { Expect(report).To(Equal(validationutils.MakeReport(proxy))) clusters := snap.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster = clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) Expect(cluster).NotTo(BeNil()) var msgList []proto.Message @@ -1735,8 +1736,8 @@ var _ = Describe("Translator", func() { Expect(clusters).ToNot(BeNil()) Expect(clusters.TotalWeight.Value).To(BeEquivalentTo(2)) Expect(clusters.Clusters).To(HaveLen(2)) - Expect(clusters.Clusters[0].Name).To(Equal(UpstreamToClusterName(upstream.Metadata.Ref()))) - Expect(clusters.Clusters[1].Name).To(Equal(UpstreamToClusterName(upstream2.Metadata.Ref()))) + Expect(clusters.Clusters[0].Name).To(Equal(glooupstreams.UpstreamToClusterName(upstream))) + Expect(clusters.Clusters[1].Name).To(Equal(glooupstreams.UpstreamToClusterName(upstream2))) }) It("should error on invalid ref in upstream groups", func() { @@ -1765,8 +1766,8 @@ var _ = Describe("Translator", func() { clusters := routeConfiguration.VirtualHosts[0].Routes[0].GetRoute().GetWeightedClusters() Expect(clusters).ToNot(BeNil()) Expect(clusters.Clusters).To(HaveLen(2)) - Expect(clusters.Clusters[0].Name).To(Equal(UpstreamToClusterName(upstream.Metadata.Ref()))) - Expect(clusters.Clusters[1].Name).To(Equal(UpstreamToClusterName(upstream2.Metadata.Ref()))) + Expect(clusters.Clusters[0].Name).To(Equal(glooupstreams.UpstreamToClusterName(upstream))) + Expect(clusters.Clusters[1].Name).To(Equal(glooupstreams.UpstreamToClusterName(upstream2))) }) }) @@ -2138,10 +2139,10 @@ var _ = Describe("Translator", func() { // Clusters have been created for the two "fake" upstreams clusters := snapshot.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(fakeUsList[0].Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(fakeUsList[0])] cluster = clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) Expect(cluster).NotTo(BeNil()) - clusterResource = clusters.Items[UpstreamToClusterName(fakeUsList[1].Metadata.Ref())] + clusterResource = clusters.Items[glooupstreams.UpstreamToClusterName(fakeUsList[1])] cluster = clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) Expect(cluster).NotTo(BeNil()) @@ -2159,7 +2160,7 @@ var _ = Describe("Translator", func() { Expect(ok).To(BeTrue()) clusterAction, ok := routeAction.Route.ClusterSpecifier.(*envoy_config_route_v3.RouteAction_Cluster) Expect(ok).To(BeTrue()) - Expect(clusterAction.Cluster).To(Equal(UpstreamToClusterName(fakeUsList[0].Metadata.Ref()))) + Expect(clusterAction.Cluster).To(Equal(glooupstreams.UpstreamToClusterName(fakeUsList[0]))) }) }) @@ -2294,7 +2295,7 @@ var _ = Describe("Translator", func() { // A cluster has been created for the "fake" upstream and has the expected subset config clusters := snapshot.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(fakeUsList[0].Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(fakeUsList[0])] cluster = clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) Expect(cluster).NotTo(BeNil()) Expect(cluster.LbSubsetConfig).NotTo(BeNil()) @@ -2327,7 +2328,7 @@ var _ = Describe("Translator", func() { clusterAction, ok := routeAction.Route.ClusterSpecifier.(*envoy_config_route_v3.RouteAction_Cluster) Expect(ok).To(BeTrue()) - Expect(clusterAction.Cluster).To(Equal(UpstreamToClusterName(fakeUsList[0].Metadata.Ref()))) + Expect(clusterAction.Cluster).To(Equal(glooupstreams.UpstreamToClusterName(fakeUsList[0]))) Expect(routeAction.Route).NotTo(BeNil()) Expect(routeAction.Route.MetadataMatch).NotTo(BeNil()) @@ -2651,7 +2652,7 @@ var _ = Describe("Translator", func() { endpointPlugin.ProcessEndpointFunc = func(params plugins.Params, in *v1.Upstream, out *envoy_config_endpoint_v3.ClusterLoadAssignment) error { Expect(out.GetEndpoints()).To(HaveLen(1)) - Expect(out.GetClusterName()).To(Equal(UpstreamToClusterName(upstream.Metadata.Ref()))) + Expect(out.GetClusterName()).To(Equal(glooupstreams.UpstreamToClusterName(upstream))) Expect(out.GetEndpoints()[0].GetLbEndpoints()).To(HaveLen(1)) out.Endpoints = append(out.Endpoints, additionalEndpoint) @@ -2900,7 +2901,7 @@ var _ = Describe("Translator", func() { tlsContext := func() *envoyauth.UpstreamTlsContext { clusters := snapshot.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster := clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) return glooutils.MustAnyToMessage(cluster.TransportSocket.GetTypedConfig()).(*envoyauth.UpstreamTlsContext) @@ -3032,7 +3033,7 @@ var _ = Describe("Translator", func() { translate() clusters := snapshot.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster := clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) transportSocketMatches := cluster.GetTransportSocketMatches() Expect(transportSocketMatches).To(HaveLen(2), "Expect 2 transport socket matches when istio auto mtls is enabled") @@ -3068,7 +3069,7 @@ var _ = Describe("Translator", func() { translate() clusters := snapshot.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster := clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) transportSocketMatches := cluster.GetTransportSocketMatches() Expect(transportSocketMatches).To(BeEmpty(), "Expect no transport socket matches when istio auto mtls is enabled") @@ -3114,7 +3115,7 @@ var _ = Describe("Translator", func() { translate() clusters := snapshot.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster := clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) transportSocketMatches := cluster.GetTransportSocketMatches() Expect(transportSocketMatches).To(HaveLen(1), "Only upstream defined transport socket match should be present") @@ -3754,7 +3755,7 @@ var _ = Describe("Translator", func() { Expect(report).To(Equal(validationutils.MakeReport(proxy))) clusters := snap.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster = clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) Expect(cluster).NotTo(BeNil()) Expect(cluster.IgnoreHealthOnHostRemoval).To(Equal(expectedClusterValue)) @@ -3779,7 +3780,7 @@ var _ = Describe("Translator", func() { Expect(errs.Validate()).To(Succeed()) clusters := snap.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster = clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) Expect(cluster).NotTo(BeNil()) @@ -3824,7 +3825,7 @@ var _ = Describe("Translator", func() { Expect(errs.ValidateStrict()).To(reportMatcher, "Ensure the reports contain the necessary errors/warnings") clusters := snap.GetResources(types.ClusterTypeV3) - clusterResource := clusters.Items[UpstreamToClusterName(upstream.Metadata.Ref())] + clusterResource := clusters.Items[glooupstreams.UpstreamToClusterName(upstream)] cluster = clusterResource.ResourceProto().(*envoy_config_cluster_v3.Cluster) Expect(cluster.GetDnsRefreshRate()).To(refreshRateMatcher) }, @@ -4018,10 +4019,10 @@ var _ = Describe("Translator", func() { }) }) -// The endpoint Cluster is now the UpstreamToClusterName- to facilitate +// The endpoint Cluster is now the glooupstreams.UpstreamToClusterName- to facilitate // gRPC EDS updates func getEndpointClusterName(upstream *v1.Upstream) string { - return fmt.Sprintf("%s-%d", UpstreamToClusterName(upstream.Metadata.Ref()), upstream.MustHash()) + return fmt.Sprintf("%s-%d", glooupstreams.UpstreamToClusterName(upstream), upstream.MustHash()) } func sv(s string) *structpb.Value { diff --git a/projects/gloo/pkg/translator/utils.go b/projects/gloo/pkg/translator/utils.go index 27a5914bff7..89e7bdef850 100644 --- a/projects/gloo/pkg/translator/utils.go +++ b/projects/gloo/pkg/translator/utils.go @@ -1,53 +1,18 @@ package translator import ( - "fmt" "net" - "strings" - - errors "github.com/rotisserie/eris" envoyal "github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v3" envoy_config_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/any" + errors "github.com/rotisserie/eris" "github.com/solo-io/gloo/projects/gloo/pkg/utils" - "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" ) -// returns the name of the cluster created for a given upstream -func UpstreamToClusterName(upstream *core.ResourceRef) string { - - // For non-namespaced resources, return only name - if upstream.GetNamespace() == "" { - return upstream.GetName() - } - - // Don't use dots in the name as it messes up prometheus stats - return fmt.Sprintf("%s_%s", upstream.GetName(), upstream.GetNamespace()) -} - -// returns the ref of the upstream for a given cluster -func ClusterToUpstreamRef(cluster string) (*core.ResourceRef, error) { - - split := strings.Split(cluster, "_") - if len(split) > 2 || len(split) < 1 { - return nil, errors.Errorf("unable to convert cluster %s back to upstream ref", cluster) - } - - ref := &core.ResourceRef{ - Name: split[0], - } - - if len(split) == 2 { - ref.Namespace = split[1] - } - return ref, nil -} - func NewFilterWithTypedConfig(name string, config proto.Message) (*envoy_config_listener_v3.Filter, error) { - s := &envoy_config_listener_v3.Filter{ Name: name, } @@ -107,14 +72,12 @@ func IsIpv4Address(bindAddress string) (validIpv4, strictIPv4 bool, err error) { if bindIP == nil { // If bindAddress is not a valid textual representation of an IP address return false, false, errors.Errorf("bindAddress %s is not a valid IP address", bindAddress) - } else if bindIP.To4() == nil { // If bindIP is not an IPv4 address, To4 returns nil. // so this is not an acceptable ipv4 return false, false, nil } return true, isPureIPv4Address(bindAddress), nil - } // isPureIPv4Address checks the string to see if it is diff --git a/projects/gloo/pkg/translator/utils_test.go b/projects/gloo/pkg/translator/utils_test.go index f89f2ec2f07..e073d0defc7 100644 --- a/projects/gloo/pkg/translator/utils_test.go +++ b/projects/gloo/pkg/translator/utils_test.go @@ -5,27 +5,10 @@ import ( . "github.com/onsi/gomega" errors "github.com/rotisserie/eris" "github.com/solo-io/gloo/projects/gloo/pkg/translator" - "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" ) var _ = Describe("Utils", func() { - It("empty namespace: should convert upstream to cluster name and back properly", func() { - ref := &core.ResourceRef{Name: "name", Namespace: ""} - clusterName := translator.UpstreamToClusterName(ref) - convertedBack, err := translator.ClusterToUpstreamRef(clusterName) - Expect(err).ToNot(HaveOccurred()) - Expect(convertedBack).To(Equal(ref)) - }) - - It("populated namespace: should convert upstream to cluster name and back properly", func() { - ref := &core.ResourceRef{Name: "name", Namespace: "namespace"} - clusterName := translator.UpstreamToClusterName(ref) - convertedBack, err := translator.ClusterToUpstreamRef(clusterName) - Expect(err).ToNot(HaveOccurred()) - Expect(convertedBack).To(Equal(ref)) - }) - DescribeTable( "IsIpv4Address", func(address string, expectedIPv4, expectedPureIPv4 bool, expectedErr error) { diff --git a/projects/gloo/pkg/upstreams/conversions.go b/projects/gloo/pkg/upstreams/conversions.go index e87d4355913..873e4fe4d00 100644 --- a/projects/gloo/pkg/upstreams/conversions.go +++ b/projects/gloo/pkg/upstreams/conversions.go @@ -1,19 +1,26 @@ package upstreams import ( - "github.com/solo-io/gloo/projects/gloo/pkg/upstreams/consul" - "github.com/solo-io/gloo/projects/gloo/pkg/upstreams/kubernetes" - "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" + "strings" "github.com/rotisserie/eris" - + "github.com/solo-io/gloo/pkg/utils/envutils" + "github.com/solo-io/gloo/projects/gloo/constants" v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams/consul" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams/kubernetes" + "github.com/solo-io/gloo/projects/gloo/pkg/utils" + "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" ) +// isRealUpstream returns true if the given upstream name refers to a "real" upstream that is +// stored in etcd (as opposed a "fake"/in-memory upstream) func isRealUpstream(upstreamName string) bool { - return !(kubernetes.IsKubeUpstream(upstreamName) || consul.IsConsulUpstream(upstreamName)) + return !(kubernetes.IsFakeKubeUpstream(upstreamName) || consul.IsConsulUpstream(upstreamName)) } +// DestinationToUpstreamRef converts a route destination to an upstream ref. The upstream ref may +// refer to either a real or in-memory upstream, depending on the destination type. func DestinationToUpstreamRef(dest *v1.Destination) (*core.ResourceRef, error) { var ref *core.ResourceRef switch d := dest.GetDestinationType().(type) { @@ -28,3 +35,54 @@ func DestinationToUpstreamRef(dest *v1.Destination) (*core.ResourceRef, error) { } return ref, nil } + +// UpstreamToClusterName converts an Upstream to a cluster name to be used in envoy. +func UpstreamToClusterName(upstream *v1.Upstream) string { + // when kube gateway is enabled, we use a new cluster name format that is more easily parseable + if envutils.IsEnvTruthy(constants.GlooGatewayEnableK8sGwControllerEnv) { + // currently only kube-type upstreams are handled, and the rest will fall back to the old cluster format + switch upstreamType := upstream.GetUpstreamType().(type) { + case *v1.Upstream_Kube: + return kubernetes.UpstreamToClusterName( + upstream.GetMetadata().GetName(), + upstream.GetMetadata().GetNamespace(), + upstreamType.Kube, + ) + + // TODO: other upstream types can be handled here later + } + } + + // fall back to "legacy" format + return utils.ResourceRefToKey(upstream.GetMetadata().Ref()) +} + +// ClusterToUpstreamRef converts an envoy cluster name back to an upstream ref. +// (this is currently only used in the tunneling plugin and the old UI) +// This does the inverse of UpstreamToClusterName +func ClusterToUpstreamRef(cluster string) (*core.ResourceRef, error) { + // if kube gateway is enabled and it's a kube-type cluster name, use the new parsing logic + if envutils.IsEnvTruthy(constants.GlooGatewayEnableK8sGwControllerEnv) && + kubernetes.IsKubeCluster(cluster) { + return kubernetes.ClusterToUpstreamRef(cluster) + } + + // TODO: if we add support for more cluster name formats based on upstream type + // (in UpstreamToClusterName), add the reverse conversion logic here + + // otherwise fall back to old logic: + // legacy and non-kube cluster names consist of `upstreamName_upstreamNamespace` + split := strings.Split(cluster, "_") + if len(split) > 2 || len(split) < 1 { + return nil, eris.Errorf("unable to convert cluster %s back to upstream ref", cluster) + } + + ref := &core.ResourceRef{ + Name: split[0], + } + + if len(split) == 2 { + ref.Namespace = split[1] + } + return ref, nil +} diff --git a/projects/gloo/pkg/upstreams/conversions_test.go b/projects/gloo/pkg/upstreams/conversions_test.go new file mode 100644 index 00000000000..9c7e38c096d --- /dev/null +++ b/projects/gloo/pkg/upstreams/conversions_test.go @@ -0,0 +1,79 @@ +package upstreams_test + +import ( + "os" + "strconv" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/solo-io/gloo/projects/gloo/constants" + gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" + "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/kubernetes" + "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/static" + "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" + upstreams_kube "github.com/solo-io/gloo/projects/gloo/pkg/upstreams/kubernetes" + "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" +) + +var _ = Describe("Conversions", func() { + + AfterEach(func() { + err := os.Unsetenv(constants.GlooGatewayEnableK8sGwControllerEnv) + Expect(err).NotTo(HaveOccurred()) + }) + + DescribeTable("converting upstream to cluster and back", + func(kubeGatewayEnabled bool, us *gloov1.Upstream, expectedCluster string) { + err := os.Setenv(constants.GlooGatewayEnableK8sGwControllerEnv, + strconv.FormatBool(kubeGatewayEnabled)) + Expect(err).NotTo(HaveOccurred()) + + // make sure the upstream converts to the expected cluster name + clusterName := upstreams.UpstreamToClusterName(us) + Expect(clusterName).To(Equal(expectedCluster)) + + // convert it back and make sure the ref is the same as the original upstream ref + usRef, err := upstreams.ClusterToUpstreamRef(clusterName) + Expect(err).ToNot(HaveOccurred()) + Expect(usRef).To(Equal(us.GetMetadata().Ref())) + }, + Entry("kubeGateway enabled, real kube upstream", true, createKubeUpstream(true, "name", "ns", "svcName", "svcNs", 123), "kube-upstream:name_ns_svcNs_svcName_123"), + Entry("kubeGateway enabled, fake kube upstream", true, createKubeUpstream(false, "name", "ns", "svcName", "svcNs", 123), "kube-svc:name_ns_svcNs_svcName_123"), + Entry("kubeGateway enabled, non-kube upstream", true, createStaticUpstream("name", "ns"), "name_ns"), + Entry("kubeGateway disabled, real kube upstream", false, createKubeUpstream(true, "name", "ns", "svcName", "svcNs", 123), "name_ns"), + Entry("kubeGateway disabled, fake kube upstream", false, createKubeUpstream(false, "name", "ns", "svcName", "svcNs", 123), "kube-svc:name_ns"), + Entry("kubeGateway disabled, non-kube upstream", false, createStaticUpstream("name", "ns"), "name_ns"), + ) +}) + +func createKubeUpstream(isReal bool, name string, namespace string, + svcName string, svcNamespace string, svcPort uint32) *gloov1.Upstream { + if !isReal { + name = upstreams_kube.FakeUpstreamNamePrefix + name + } + return &gloov1.Upstream{ + Metadata: &core.Metadata{ + Name: name, + Namespace: namespace, + }, + UpstreamType: &gloov1.Upstream_Kube{ + Kube: &kubernetes.UpstreamSpec{ + ServiceName: svcName, + ServiceNamespace: svcNamespace, + ServicePort: svcPort, + }, + }, + } +} + +func createStaticUpstream(name string, namespace string) *gloov1.Upstream { + return &gloov1.Upstream{ + Metadata: &core.Metadata{ + Name: name, + Namespace: namespace, + }, + UpstreamType: &gloov1.Upstream_Static{ + Static: &static.UpstreamSpec{}, + }, + } +} diff --git a/projects/gloo/pkg/upstreams/kubernetes/conversions.go b/projects/gloo/pkg/upstreams/kubernetes/conversions.go index fb15b9730c9..f6812800e14 100644 --- a/projects/gloo/pkg/upstreams/kubernetes/conversions.go +++ b/projects/gloo/pkg/upstreams/kubernetes/conversions.go @@ -2,35 +2,106 @@ package kubernetes import ( "context" + "fmt" "strings" + "github.com/rotisserie/eris" gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" - v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" + "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/kubernetes" kubeplugin "github.com/solo-io/gloo/projects/gloo/pkg/plugins/kubernetes" skkube "github.com/solo-io/solo-kit/pkg/api/v1/resources/common/kubernetes" "github.com/solo-io/solo-kit/pkg/api/v1/resources/core" corev1 "k8s.io/api/core/v1" ) -func IsKubeUpstream(upstreamName string) bool { - return strings.HasPrefix(upstreamName, UpstreamNamePrefix) +// FakeUpstreamNamePrefix is a prefix used to create/identify in-memory Upstreams for Kubernetes Services. +// It contains an invalid character so any accidental attempt to write to storage fails. +// Clusters created from these in-memory upstreams will also contain this prefix. +const FakeUpstreamNamePrefix = "kube-svc:" + +// KubeUpstreamClusterPrefix is a prefix added to clusters created from "real" Upstreams of `kube` type. +// This prefix only appears in the cluster name and not in the actual name of the Upstream from which +// the cluster was created (since it contains an invalid character). +const KubeUpstreamClusterPrefix = "kube-upstream:" + +// IsFakeKubeUpstream returns true if the given upstream is a "fake"/in-memory upstream representing +// a kubernetes service. An in-memory upstream is used when a routing destination is a Kubernetes +// Service (as opposed to an Upstream). +func IsFakeKubeUpstream(upstreamName string) bool { + return strings.HasPrefix(upstreamName, FakeUpstreamNamePrefix) +} + +// IsKubeCluster returns true if the given envoy cluster was created from an Upstream of `kube` type +// (which may be either "real" or "fake"). +func IsKubeCluster(cluster string) bool { + return strings.HasPrefix(cluster, FakeUpstreamNamePrefix) || strings.HasPrefix(cluster, KubeUpstreamClusterPrefix) } -func DestinationToUpstreamRef(svcDest *v1.KubernetesServiceDestination) *core.ResourceRef { +// DestinationToUpstreamRef converts a k8s service Destination to an in-memory upstream ref. +// This is called by the generic upstream DestinationToUpstreamRef. +func DestinationToUpstreamRef(svcDest *gloov1.KubernetesServiceDestination) *core.ResourceRef { return &core.ResourceRef{ Namespace: svcDest.GetRef().GetNamespace(), Name: fakeUpstreamName(svcDest.GetRef().GetName(), svcDest.GetRef().GetNamespace(), int32(svcDest.GetPort())), } } +// UpstreamToClusterName converts a kube upstream (which may be either "real" or "fake") to a cluster name. +// This is called by the generic upstream UpstreamToClusterName. +// This should only be called if kube gateway is enabled. +func UpstreamToClusterName(upstreamName string, upstreamNamespace string, kubeSpec *kubernetes.UpstreamSpec) string { + // Add an identifying prefix if it's a "real" upstream (fake upstreams already have such a prefix). + if !IsFakeKubeUpstream(upstreamName) { + upstreamName = fmt.Sprintf("%s%s", KubeUpstreamClusterPrefix, upstreamName) + } + return fmt.Sprintf("%s_%s_%s_%s_%v", + upstreamName, + upstreamNamespace, + kubeSpec.GetServiceNamespace(), + kubeSpec.GetServiceName(), + kubeSpec.GetServicePort(), + ) +} + +// ClusterToUpstreamRef converts an envoy cluster name to a kube upstream ref (the upstream may be either "real" or "fake"). +// This does the inverse of UpstreamToClusterName. +// This is called by the generic ClusterToUpstreamRef. +// This should only be called if kube gateway is enabled. +func ClusterToUpstreamRef(cluster string) (*core.ResourceRef, error) { + if !IsKubeCluster(cluster) { + return nil, eris.Errorf("cluster %s does not refer to a kubernetes service", cluster) + } + + // split cluster name into component parts (see UpstreamToClusterName for format) + parts := strings.Split(cluster, "_") + if len(parts) != 5 { + return nil, eris.Errorf("unable to convert cluster %s back to upstream ref", cluster) + } + upstreamName := parts[0] + upstreamNamespace := parts[1] + + // if it's a "real" upstream, remove the special cluster prefix, as that's not part of the actual upstream name + if strings.HasPrefix(cluster, KubeUpstreamClusterPrefix) { + upstreamName = upstreamName[len(KubeUpstreamClusterPrefix):] + } + + return &core.ResourceRef{ + Name: upstreamName, + Namespace: upstreamNamespace, + }, nil +} + +// fakeUpstreamName generates a name for an in-memory upstream, based on the given service spec func fakeUpstreamName(serviceName, serviceNamespace string, port int32) string { regularServiceName := kubeplugin.UpstreamName(serviceNamespace, serviceName, port) - return UpstreamNamePrefix + regularServiceName + return FakeUpstreamNamePrefix + regularServiceName } +// KubeServicesToUpstreams converts a list of k8s Services to a list of in-memory Upstreams. // Public because it's needed in the translator test -func KubeServicesToUpstreams(ctx context.Context, services skkube.ServiceList) v1.UpstreamList { - var result v1.UpstreamList +// Also used by k8s upstream client (List/Watch) +func KubeServicesToUpstreams(ctx context.Context, services skkube.ServiceList) gloov1.UpstreamList { + var result gloov1.UpstreamList for _, svc := range services { for _, port := range svc.Spec.Ports { kubeSvc := svc.Service.GetKubeService() @@ -40,11 +111,14 @@ func KubeServicesToUpstreams(ctx context.Context, services skkube.ServiceList) v return result } +// ServiceToUpstream converts a k8s Service to an in-memory Upstream (with the kube-svc prefix). +// Called by KubeServicesToUpstreams (above) and kube gateway proxy syncer when initializing +// in-memory upstreams from k8s services. func ServiceToUpstream(ctx context.Context, svc *corev1.Service, port corev1.ServicePort) *gloov1.Upstream { us := kubeplugin.DefaultUpstreamConverter().CreateUpstream(ctx, svc, port) - us.GetMetadata().Name = fakeUpstreamName(svc.Name, svc.Namespace, port.Port) - us.GetMetadata().Namespace = svc.Namespace + us.GetMetadata().Name = fakeUpstreamName(svc.GetName(), svc.GetNamespace(), port.Port) + us.GetMetadata().Namespace = svc.GetNamespace() us.GetMetadata().ResourceVersion = "" return us diff --git a/projects/gloo/pkg/upstreams/kubernetes/conversions_test.go b/projects/gloo/pkg/upstreams/kubernetes/conversions_test.go index 2cd30b5e517..85d8680b94b 100644 --- a/projects/gloo/pkg/upstreams/kubernetes/conversions_test.go +++ b/projects/gloo/pkg/upstreams/kubernetes/conversions_test.go @@ -14,13 +14,13 @@ var _ = Describe("Conversions", func() { It("correctly builds service-derived upstream name", func() { name := fakeUpstreamName("my-service", "ns", 8080) - Expect(name).To(Equal(UpstreamNamePrefix + "ns-my-service-8080")) + Expect(name).To(Equal(FakeUpstreamNamePrefix + "ns-my-service-8080")) }) It("correctly detects upstreams derived from Kubernetes services", func() { - Expect(IsKubeUpstream(UpstreamNamePrefix + "my-service-8080")).To(BeTrue()) - Expect(IsKubeUpstream("my-" + UpstreamNamePrefix + "service-8080")).To(BeFalse()) - Expect(IsKubeUpstream("svc:my-service-8080")).To(BeFalse()) + Expect(IsFakeKubeUpstream(FakeUpstreamNamePrefix + "my-service-8080")).To(BeTrue()) + Expect(IsFakeKubeUpstream("my-" + FakeUpstreamNamePrefix + "service-8080")).To(BeFalse()) + Expect(IsFakeKubeUpstream("svc:my-service-8080")).To(BeFalse()) }) It("correctly converts a list of services to upstreams", func() { @@ -42,14 +42,14 @@ var _ = Describe("Conversions", func() { usList := KubeServicesToUpstreams(context.TODO(), skkube.ServiceList{svc}) usList.Sort() Expect(usList).To(HaveLen(2)) - Expect(usList[0].Metadata.Name).To(Equal(UpstreamNamePrefix + "ns-1-svc-1-8080")) + Expect(usList[0].Metadata.Name).To(Equal(FakeUpstreamNamePrefix + "ns-1-svc-1-8080")) Expect(usList[0].Metadata.Namespace).To(Equal("ns-1")) Expect(usList[0].GetKube()).NotTo(BeNil()) Expect(usList[0].GetKube().ServiceName).To(Equal("svc-1")) Expect(usList[0].GetKube().ServiceNamespace).To(Equal("ns-1")) Expect(usList[0].GetKube().ServicePort).To(BeEquivalentTo(8080)) - Expect(usList[1].Metadata.Name).To(Equal(UpstreamNamePrefix + "ns-1-svc-1-8081")) + Expect(usList[1].Metadata.Name).To(Equal(FakeUpstreamNamePrefix + "ns-1-svc-1-8081")) Expect(usList[1].Metadata.Namespace).To(Equal("ns-1")) Expect(usList[1].GetKube()).NotTo(BeNil()) Expect(usList[1].GetKube().ServiceName).To(Equal("svc-1")) diff --git a/projects/gloo/pkg/upstreams/kubernetes/upstream_client.go b/projects/gloo/pkg/upstreams/kubernetes/upstream_client.go index 9632aff8de6..241bf7d93b2 100644 --- a/projects/gloo/pkg/upstreams/kubernetes/upstream_client.go +++ b/projects/gloo/pkg/upstreams/kubernetes/upstream_client.go @@ -12,10 +12,6 @@ import ( skkube "github.com/solo-io/solo-kit/pkg/api/v1/resources/common/kubernetes" ) -// UpstreamNamePrefix is a prefix used to create/identify in-memory Upstreams for Kubernetes Services -// It contains an invalid character so any accidental attempt to write to storage fails -const UpstreamNamePrefix = "kube-svc:" - const notImplementedErrMsg = "this operation is not supported by this client" func NewKubernetesUpstreamClient(serviceClient skkube.ServiceClient) v1.UpstreamClient { diff --git a/projects/gloo/pkg/utils/gloo_resources.go b/projects/gloo/pkg/utils/gloo_resources.go index 53a9cc994d7..dcf855b3059 100644 --- a/projects/gloo/pkg/utils/gloo_resources.go +++ b/projects/gloo/pkg/utils/gloo_resources.go @@ -1,6 +1,7 @@ package utils import ( + "fmt" "sort" gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" @@ -9,6 +10,17 @@ import ( "k8s.io/apimachinery/pkg/util/sets" ) +// ResourceRefToKey generates a (prometheus-safe) unique resource key from the given resource ref. +func ResourceRefToKey(ref *core.ResourceRef) string { + // For non-namespaced resources, return only name + if ref.GetNamespace() == "" { + return ref.GetName() + } + + // Don't use dots in the name as it messes up prometheus stats + return fmt.Sprintf("%s_%s", ref.GetName(), ref.GetNamespace()) +} + // Merges the modified resources into the existing resources, overwriting any existing values, // and returns the new list func MergeResourceLists(existingResources sk_resources.ResourceList, modifiedResources sk_resources.ResourceList) sk_resources.ResourceList { diff --git a/projects/gloo/pkg/validation/server.go b/projects/gloo/pkg/validation/server.go index be8a0721c20..0e68306c31d 100644 --- a/projects/gloo/pkg/validation/server.go +++ b/projects/gloo/pkg/validation/server.go @@ -246,7 +246,7 @@ func (s *validator) ValidateGloo(ctx context.Context, proxy *v1.Proxy, resource kubeSvcUs := &v1.Upstream{ Metadata: &core.Metadata{ Namespace: resource.GetMetadata().GetNamespace(), - Name: fmt.Sprintf("%s%s", kubernetes.UpstreamNamePrefix, resource.GetMetadata().GetName()), + Name: fmt.Sprintf("%s%s", kubernetes.FakeUpstreamNamePrefix, resource.GetMetadata().GetName()), }, } if err := snapCopy.RemoveFromResourceList(kubeSvcUs); err != nil { @@ -283,7 +283,7 @@ func applyRequestToSnapshot(snap *v1snap.ApiSnapshot, req *validation.GlooValida for _, ref := range req.GetDeletedResources().GetUpstreamRefs() { deletedUpstreamRefs = append(deletedUpstreamRefs, &core.ResourceRef{ Namespace: ref.GetNamespace(), - Name: fmt.Sprintf("%s%s", kubernetes.UpstreamNamePrefix, ref.GetName()), + Name: fmt.Sprintf("%s%s", kubernetes.FakeUpstreamNamePrefix, ref.GetName()), }) } finalUpstreams := utils.DeleteResources(existingUpstreams, deletedUpstreamRefs) diff --git a/projects/gloo/pkg/validation/server_test.go b/projects/gloo/pkg/validation/server_test.go index f283f6ec11a..f41c40b141e 100644 --- a/projects/gloo/pkg/validation/server_test.go +++ b/projects/gloo/pkg/validation/server_test.go @@ -349,7 +349,7 @@ var _ = Describe("Validation Server", func() { } kubeSvcUpstream = v1.Upstream{ Metadata: &core.Metadata{ - Name: fmt.Sprintf("%s%s", upstreams_kubernetes.UpstreamNamePrefix, upstream.GetMetadata().GetName()), + Name: fmt.Sprintf("%s%s", upstreams_kubernetes.FakeUpstreamNamePrefix, upstream.GetMetadata().GetName()), Namespace: upstream.GetMetadata().GetNamespace(), }, UpstreamType: usType, diff --git a/test/e2e/access_log_test.go b/test/e2e/access_log_test.go index b2c163b73ce..711948417a0 100644 --- a/test/e2e/access_log_test.go +++ b/test/e2e/access_log_test.go @@ -26,7 +26,7 @@ import ( gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1" "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/als" alsplugin "github.com/solo-io/gloo/projects/gloo/pkg/plugins/als" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" ) var _ = Describe("Access Log", func() { @@ -106,7 +106,7 @@ var _ = Describe("Access Log", func() { var entry *envoy_data_accesslog_v3.HTTPAccessLogEntry g.Eventually(msgChan, 2*time.Second).Should(Receive(&entry)) - g.Expect(entry.CommonProperties.UpstreamCluster).To(Equal(translator.UpstreamToClusterName(testContext.TestUpstream().Upstream.Metadata.Ref()))) + g.Expect(entry.CommonProperties.UpstreamCluster).To(Equal(glooupstreams.UpstreamToClusterName(testContext.TestUpstream().Upstream))) }, time.Second*21, time.Second*2).Should(Succeed()) }) diff --git a/test/e2e/gateway_test.go b/test/e2e/gateway_test.go index b2ab369a5ac..e822eb3be3f 100644 --- a/test/e2e/gateway_test.go +++ b/test/e2e/gateway_test.go @@ -23,7 +23,7 @@ import ( extauthv1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/enterprise/options/extauth/v1" "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/ssl" "github.com/solo-io/gloo/projects/gloo/pkg/defaults" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" gloohelpers "github.com/solo-io/gloo/test/helpers" "github.com/solo-io/gloo/test/services" "github.com/solo-io/gloo/test/v1helpers" @@ -459,7 +459,7 @@ var _ = Describe("Gateway", func() { }) It("should direct requests that use cluster_header to the proper upstream", func() { - upstreamName := translator.UpstreamToClusterName(testUpstream.Upstream.Metadata.Ref()) + upstreamName := glooupstreams.UpstreamToClusterName(testUpstream.Upstream) vs := getTrivialVirtualService(writeNamespace) // Create route that uses cluster header destination @@ -1039,7 +1039,7 @@ var _ = Describe("Gateway", func() { }) It("should direct requests that use cluster_header to the proper upstream", func() { - upstreamName := translator.UpstreamToClusterName(testUpstream.Upstream.Metadata.Ref()) + upstreamName := glooupstreams.UpstreamToClusterName(testUpstream.Upstream) // Create route that uses cluster header destination virtualService.GetVirtualHost().Routes = []*gatewayv1.Route{{ diff --git a/test/e2e/zipkin_test.go b/test/e2e/zipkin_test.go index 2b52f1cd880..a4d7409a1eb 100644 --- a/test/e2e/zipkin_test.go +++ b/test/e2e/zipkin_test.go @@ -15,7 +15,7 @@ import ( "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/gloosnapshot" "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/options/hcm" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/solo-kit/pkg/api/v1/resources" gatewayv1 "github.com/solo-io/gloo/projects/gateway/pkg/api/v1" @@ -102,8 +102,9 @@ var _ = Describe("Tracing config loading", Serial, func() { Context("Tracing defined on Gloo resources", func() { var ( - testClients services.TestClients - testUpstream *v1helpers.TestUpstream + testClients services.TestClients + testUpstream *v1helpers.TestUpstream + tracingCollectorUs *gloov1.Upstream resourcesToCreate *gloosnapshot.ApiSnapshot ) @@ -136,7 +137,7 @@ var _ = Describe("Tracing config loading", Serial, func() { Build() // create tracing collector upstream - tracingCollectorUs := &gloov1.Upstream{ + tracingCollectorUs = &gloov1.Upstream{ Metadata: &core.Metadata{ Name: tracingCollectorUpstreamName, Namespace: writeNamespace, @@ -268,10 +269,7 @@ var _ = Describe("Tracing config loading", Serial, func() { ProviderConfig: &tracing.ListenerTracingSettings_OpenTelemetryConfig{ OpenTelemetryConfig: &envoytrace_gloo.OpenTelemetryConfig{ CollectorCluster: &envoytrace_gloo.OpenTelemetryConfig_ClusterName{ - ClusterName: translator.UpstreamToClusterName(&core.ResourceRef{ - Name: tracingCollectorUpstreamName, - Namespace: writeNamespace, - }), + ClusterName: glooupstreams.UpstreamToClusterName(tracingCollectorUs), }, }, }, @@ -382,10 +380,7 @@ var _ = Describe("Tracing config loading", Serial, func() { ProviderConfig: &tracing.ListenerTracingSettings_ZipkinConfig{ ZipkinConfig: &envoytrace_gloo.ZipkinConfig{ CollectorCluster: &envoytrace_gloo.ZipkinConfig_ClusterName{ - ClusterName: translator.UpstreamToClusterName(&core.ResourceRef{ - Name: tracingCollectorUpstreamName, - Namespace: writeNamespace, - }), + ClusterName: glooupstreams.UpstreamToClusterName(tracingCollectorUs), }, CollectorEndpoint: zipkinCollectionPath, CollectorEndpointVersion: envoytrace_gloo.ZipkinConfig_HTTP_JSON, diff --git a/test/kube2e/gateway/gateway_test.go b/test/kube2e/gateway/gateway_test.go index faba896171f..7ebcc6ea5cc 100644 --- a/test/kube2e/gateway/gateway_test.go +++ b/test/kube2e/gateway/gateway_test.go @@ -44,7 +44,7 @@ import ( defaults2 "github.com/solo-io/gloo/projects/gloo/pkg/defaults" kubernetesplugin "github.com/solo-io/gloo/projects/gloo/pkg/plugins/kubernetes" "github.com/solo-io/gloo/projects/gloo/pkg/plugins/linkerd" - "github.com/solo-io/gloo/projects/gloo/pkg/translator" + glooupstreams "github.com/solo-io/gloo/projects/gloo/pkg/upstreams" "github.com/solo-io/gloo/test/helpers" "github.com/solo-io/gloo/test/kube2e" "github.com/solo-io/gloo/test/kube2e/helper" @@ -1107,10 +1107,14 @@ var _ = Describe("Kube2e: gateway", func() { _, err = resourceClientset.KubeClients().CoreV1().Services(testHelper.InstallNamespace).Update(ctx, gwSvc, metav1.UpdateOptions{}) Expect(err).NotTo(HaveOccurred()) - httpEchoClusterName = translator.UpstreamToClusterName(&core.ResourceRef{ - Namespace: testHelper.InstallNamespace, - Name: kubernetesplugin.UpstreamName(testHelper.InstallNamespace, helper.HttpEchoName, helper.HttpEchoPort), - }) + httpEchoClusterName = glooupstreams.UpstreamToClusterName( + &gloov1.Upstream{ + Metadata: &core.Metadata{ + Name: kubernetesplugin.UpstreamName(testHelper.InstallNamespace, helper.HttpEchoName, helper.HttpEchoPort), + Namespace: testHelper.InstallNamespace, + }, + }) + }) AfterEach(func() {