diff --git a/pkg/plugins/runtime/k8s/controllers/inbound_converter.go b/pkg/plugins/runtime/k8s/controllers/inbound_converter.go index c181b6ce5231..489ef1d43d76 100644 --- a/pkg/plugins/runtime/k8s/controllers/inbound_converter.go +++ b/pkg/plugins/runtime/k8s/controllers/inbound_converter.go @@ -131,7 +131,29 @@ func inboundForServiceless(zone string, pod *kube_core.Pod, name string, nodeLab } } +// Deprecated: LegacyInboundInterfacesFor is currently only used for delegated gateway and Mesh without MeshService exclusive +// to not change order of inbounds. +// For gateway we pick first inbound to take tags from. Delegated gateway identity relies on this. +// For Dataplanes when MeshService is disabled we base identity and routing +// TODO: We should revisit this when we rework identity. More in https://github.com/kumahq/kuma/issues/3339 +func (i *InboundConverter) LegacyInboundInterfacesFor(ctx context.Context, zone string, pod *kube_core.Pod, services []*kube_core.Service) ([]*mesh_proto.Dataplane_Networking_Inbound, error) { + return i.inboundInterfacesFor(ctx, zone, pod, services) +} + +// InboundInterfacesFor should be used when MeshService mode is Exclusive func (i *InboundConverter) InboundInterfacesFor(ctx context.Context, zone string, pod *kube_core.Pod, services []*kube_core.Service) ([]*mesh_proto.Dataplane_Networking_Inbound, error) { + inbounds, err := i.inboundInterfacesFor(ctx, zone, pod, services) + if err != nil { + return inbounds, err + } + + // Right now we will build multiple inbounds for each service selecting port, but later on + // we will only create one listener for last inbound. Ignoring other inbounds from dataplane. + // Because of this we can safely deduplicate them here. This needs to change when we get rid of kuma.io/service + return deduplicateInboundsByAddressAndPort(inbounds), nil +} + +func (i *InboundConverter) inboundInterfacesFor(ctx context.Context, zone string, pod *kube_core.Pod, services []*kube_core.Service) ([]*mesh_proto.Dataplane_Networking_Inbound, error) { nodeLabels, err := i.getNodeLabelsToCopy(ctx, pod.Spec.NodeName) if err != nil { return nil, err @@ -161,6 +183,23 @@ func (i *InboundConverter) InboundInterfacesFor(ctx context.Context, zone string return ifaces, nil } +func deduplicateInboundsByAddressAndPort(ifaces []*mesh_proto.Dataplane_Networking_Inbound) []*mesh_proto.Dataplane_Networking_Inbound { + inboundKey := func(iface *mesh_proto.Dataplane_Networking_Inbound) string { + return fmt.Sprintf("%s:%d", iface.Address, iface.Port) + } + + var deduplicatedInbounds []*mesh_proto.Dataplane_Networking_Inbound + inboundsPerAddressPort := map[string]*mesh_proto.Dataplane_Networking_Inbound{} + for _, iface := range ifaces { + if inboundsPerAddressPort[inboundKey(iface)] == nil { + inboundsPerAddressPort[inboundKey(iface)] = iface + deduplicatedInbounds = append(deduplicatedInbounds, iface) + } + } + + return deduplicatedInbounds +} + func (i *InboundConverter) getNodeLabelsToCopy(ctx context.Context, nodeName string) (map[string]string, error) { if len(i.NodeLabelsToCopy) == 0 || nodeName == "" { return map[string]string{}, nil diff --git a/pkg/plugins/runtime/k8s/controllers/pod_controller.go b/pkg/plugins/runtime/k8s/controllers/pod_controller.go index d033deccf9ca..fcaaf8f067de 100644 --- a/pkg/plugins/runtime/k8s/controllers/pod_controller.go +++ b/pkg/plugins/runtime/k8s/controllers/pod_controller.go @@ -22,6 +22,7 @@ import ( core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh" "github.com/kumahq/kuma/pkg/core/resources/model" k8s_common "github.com/kumahq/kuma/pkg/plugins/common/k8s" + "github.com/kumahq/kuma/pkg/plugins/resources/k8s/native/api/v1alpha1" mesh_k8s "github.com/kumahq/kuma/pkg/plugins/resources/k8s/native/api/v1alpha1" k8s_model "github.com/kumahq/kuma/pkg/plugins/resources/k8s/native/pkg/model" "github.com/kumahq/kuma/pkg/plugins/runtime/k8s/metadata" @@ -317,6 +318,16 @@ func (r *PodReconciler) createOrUpdateDataplane( services []*kube_core.Service, others []*mesh_k8s.Dataplane, ) error { + meshName := util_k8s.MeshOfByLabelOrAnnotation(r.Log, pod, ns) + k8sMesh := v1alpha1.Mesh{} + if err := r.Client.Get(ctx, kube_types.NamespacedName{Name: meshName}, &k8sMesh); err != nil { + return err + } + mesh := core_mesh.NewMeshResource() + if err := r.ResourceConverter.ToCoreResource(&k8sMesh, mesh); err != nil { + return err + } + dataplane := &mesh_k8s.Dataplane{ ObjectMeta: kube_meta.ObjectMeta{ Namespace: pod.Namespace, @@ -324,7 +335,7 @@ func (r *PodReconciler) createOrUpdateDataplane( }, } operationResult, err := kube_controllerutil.CreateOrUpdate(ctx, r.Client, dataplane, func() error { - if err := r.PodConverter.PodToDataplane(ctx, dataplane, pod, ns, services, others); err != nil { + if err := r.PodConverter.PodToDataplane(ctx, dataplane, pod, ns, services, others, mesh.Spec.MeshServicesMode()); err != nil { return errors.Wrap(err, "unable to translate a Pod into a Dataplane") } if err := kube_controllerutil.SetControllerReference(pod, dataplane, r.Scheme); err != nil { diff --git a/pkg/plugins/runtime/k8s/controllers/pod_controller_test.go b/pkg/plugins/runtime/k8s/controllers/pod_controller_test.go index db99a1e5c2e3..91d34913492f 100644 --- a/pkg/plugins/runtime/k8s/controllers/pod_controller_test.go +++ b/pkg/plugins/runtime/k8s/controllers/pod_controller_test.go @@ -8,6 +8,7 @@ import ( . "github.com/onsi/gomega" kube_core "k8s.io/api/core/v1" kube_discovery "k8s.io/api/discovery/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" kube_meta "k8s.io/apimachinery/pkg/apis/meta/v1" kube_types "k8s.io/apimachinery/pkg/types" kube_intstr "k8s.io/apimachinery/pkg/util/intstr" @@ -98,6 +99,99 @@ var _ = Describe("PodReconciler", func() { }, }, }, + &kube_core.Pod{ + ObjectMeta: kube_meta.ObjectMeta{ + Namespace: "demo", + Name: "pod-with-duplicated-inbound", + Annotations: map[string]string{ + "kuma.io/mesh": "poc-ms", + "kuma.io/sidecar-injected": "true", + }, + Labels: map[string]string{ + "app": "sample-ms", + }, + UID: "pod-with-duplicated-inbound-demo", + }, + Spec: kube_core.PodSpec{ + Containers: []kube_core.Container{ + { + Ports: []kube_core.ContainerPort{ + {ContainerPort: 8080}, + }, + }, + { + Ports: []kube_core.ContainerPort{ + {ContainerPort: 6060, Name: "metrics"}, + }, + }, + { + Ports: []kube_core.ContainerPort{ + {ContainerPort: 9090}, + }, + }, + }, + }, + Status: kube_core.PodStatus{ + PodIP: "192.168.0.1", + ContainerStatuses: []kube_core.ContainerStatus{ + { + State: kube_core.ContainerState{}, + }, + }, + }, + }, + &kube_core.Service{ + ObjectMeta: kube_meta.ObjectMeta{ + Namespace: "demo", + Name: "example-ms-1", + }, + Spec: kube_core.ServiceSpec{ + ClusterIP: "192.168.0.1", + Ports: []kube_core.ServicePort{ + { + Port: 80, + TargetPort: kube_intstr.IntOrString{ + Type: kube_intstr.Int, + IntVal: 8080, + }, + AppProtocol: pointer.To("http"), + }, + { + Protocol: "TCP", + Port: 6061, + TargetPort: kube_intstr.IntOrString{ + Type: kube_intstr.String, + StrVal: "metrics", + }, + }, + }, + Selector: map[string]string{ + "app": "sample-ms", + }, + }, + }, + &kube_core.Service{ + ObjectMeta: kube_meta.ObjectMeta{ + Namespace: "demo", + Name: "example-ms-2", + }, + Spec: kube_core.ServiceSpec{ + ClusterIP: "192.168.0.1", + Ports: []kube_core.ServicePort{ + { + Port: 80, + TargetPort: kube_intstr.IntOrString{ + Type: kube_intstr.Int, + IntVal: 8080, + }, + AppProtocol: pointer.To("http"), + }, + }, + Selector: map[string]string{ + "app": "sample-ms", + }, + }, + }, &kube_core.Pod{ ObjectMeta: kube_meta.ObjectMeta{ Namespace: "demo", @@ -443,6 +537,19 @@ var _ = Describe("PodReconciler", func() { "app": "sample", }, }, + }, + &mesh_k8s.Mesh{ + ObjectMeta: kube_meta.ObjectMeta{ + Name: "poc", + }, + }, + &mesh_k8s.Mesh{ + ObjectMeta: kube_meta.ObjectMeta{ + Name: "poc-ms", + }, + Spec: &apiextensionsv1.JSON{ + Raw: []byte(`{"meshServices":{"mode":"Exclusive"}}`), + }, }).Build() reconciler = &PodReconciler{ @@ -635,64 +742,143 @@ var _ = Describe("PodReconciler", func() { Expect(err).ToNot(HaveOccurred()) // and Expect(actual).To(MatchYAML(` - mesh: poc - metadata: - creationTimestamp: null - labels: - app: sample - k8s.kuma.io/namespace: demo - kuma.io/env: kubernetes - kuma.io/mesh: poc - kuma.io/origin: zone - kuma.io/proxy-type: sidecar - kuma.io/zone: zone-1 - name: pod-with-kuma-sidecar-and-ip - namespace: demo - ownerReferences: - - apiVersion: v1 - blockOwnerDeletion: true - controller: true - kind: Pod - name: pod-with-kuma-sidecar-and-ip - uid: pod-with-kuma-sidecar-and-ip-demo - resourceVersion: "1" - spec: - networking: - address: 192.168.0.1 - inbound: - - state: NotReady - health: {} +mesh: poc +metadata: + creationTimestamp: null + labels: + app: sample + k8s.kuma.io/namespace: demo + kuma.io/env: kubernetes + kuma.io/mesh: poc + kuma.io/origin: zone + kuma.io/proxy-type: sidecar + kuma.io/zone: zone-1 + name: pod-with-kuma-sidecar-and-ip + namespace: demo + ownerReferences: + - apiVersion: v1 + blockOwnerDeletion: true + controller: true + kind: Pod + name: pod-with-kuma-sidecar-and-ip + uid: pod-with-kuma-sidecar-and-ip-demo + resourceVersion: "1" +spec: + networking: + address: 192.168.0.1 + inbound: + - health: {} port: 8080 + state: NotReady tags: app: sample - kuma.io/protocol: http - kuma.io/service: example_demo_svc_80 + k8s.kuma.io/namespace: demo k8s.kuma.io/service-name: example k8s.kuma.io/service-port: "80" - k8s.kuma.io/namespace: demo + kuma.io/protocol: http + kuma.io/service: example_demo_svc_80 kuma.io/zone: zone-1 - - state: NotReady - health: {} - port: 6060 + - health: {} name: metrics + port: 6060 + state: NotReady tags: app: sample - kuma.io/service: example_demo_svc_6061 - kuma.io/protocol: tcp + k8s.kuma.io/namespace: demo k8s.kuma.io/service-name: example k8s.kuma.io/service-port: "6061" - k8s.kuma.io/namespace: demo + kuma.io/protocol: tcp + kuma.io/service: example_demo_svc_6061 kuma.io/zone: zone-1 - - state: NotReady - health: {} + - health: {} port: 9090 + state: NotReady tags: app: sample - kuma.io/service: manual-example_demo_svc_90 - kuma.io/protocol: http + k8s.kuma.io/namespace: demo k8s.kuma.io/service-name: manual-example k8s.kuma.io/service-port: "90" + kuma.io/protocol: http + kuma.io/service: manual-example_demo_svc_90 + kuma.io/zone: zone-1 +`)) + }) + + It("should generate Dataplane resource for every Pod that has Kuma sidecar injected when MeshService enabled", func() { + // given + req := kube_ctrl.Request{ + NamespacedName: kube_types.NamespacedName{Namespace: "demo", Name: "pod-with-duplicated-inbound"}, + } + + // when + result, err := reconciler.Reconcile(context.Background(), req) + + // then + Expect(err).ToNot(HaveOccurred()) + // and + Expect(result).To(BeZero()) + + // when + dataplanes := &mesh_k8s.DataplaneList{} + err = kubeClient.List(context.Background(), dataplanes) + // then + Expect(err).ToNot(HaveOccurred()) + // and + Expect(dataplanes.Items).To(HaveLen(1)) + + // when + actual, err := json.Marshal(dataplanes.Items[0]) + // then + Expect(err).ToNot(HaveOccurred()) + // and + Expect(actual).To(MatchYAML(` +mesh: poc-ms +metadata: + creationTimestamp: null + labels: + app: sample-ms + k8s.kuma.io/namespace: demo + kuma.io/env: kubernetes + kuma.io/mesh: poc-ms + kuma.io/origin: zone + kuma.io/proxy-type: sidecar + kuma.io/zone: zone-1 + name: pod-with-duplicated-inbound + namespace: demo + ownerReferences: + - apiVersion: v1 + blockOwnerDeletion: true + controller: true + kind: Pod + name: pod-with-duplicated-inbound + uid: pod-with-duplicated-inbound-demo + resourceVersion: "1" +spec: + networking: + address: 192.168.0.1 + inbound: + - health: {} + port: 8080 + state: NotReady + tags: + app: sample-ms + k8s.kuma.io/namespace: demo + k8s.kuma.io/service-name: example-ms-1 + k8s.kuma.io/service-port: "80" + kuma.io/protocol: http + kuma.io/service: example-ms-1_demo_svc_80 + kuma.io/zone: zone-1 + - health: {} + name: metrics + port: 6060 + state: NotReady + tags: + app: sample-ms k8s.kuma.io/namespace: demo + k8s.kuma.io/service-name: example-ms-1 + k8s.kuma.io/service-port: "6061" + kuma.io/protocol: tcp + kuma.io/service: example-ms-1_demo_svc_6061 kuma.io/zone: zone-1 `)) }) @@ -737,64 +923,64 @@ var _ = Describe("PodReconciler", func() { Expect(err).ToNot(HaveOccurred()) // and Expect(actual).To(MatchYAML(` - mesh: poc - metadata: - creationTimestamp: null - labels: - app: sample - k8s.kuma.io/namespace: demo - kuma.io/env: kubernetes - kuma.io/mesh: poc - kuma.io/origin: zone - kuma.io/proxy-type: sidecar - kuma.io/zone: zone-1 +mesh: poc +metadata: + creationTimestamp: null + labels: + app: sample + k8s.kuma.io/namespace: demo + kuma.io/env: kubernetes + kuma.io/mesh: poc + kuma.io/origin: zone + kuma.io/proxy-type: sidecar + kuma.io/zone: zone-1 + name: pod-with-kuma-sidecar-and-ip + namespace: demo + ownerReferences: + - apiVersion: v1 + blockOwnerDeletion: true + controller: true + kind: Pod name: pod-with-kuma-sidecar-and-ip - namespace: demo - ownerReferences: - - apiVersion: v1 - blockOwnerDeletion: true - controller: true - kind: Pod - name: pod-with-kuma-sidecar-and-ip - uid: "pod-with-kuma-sidecar-and-ip-demo" - resourceVersion: "2" - spec: - networking: - address: 192.168.0.1 - inbound: - - state: NotReady - health: {} + uid: pod-with-kuma-sidecar-and-ip-demo + resourceVersion: "2" +spec: + networking: + address: 192.168.0.1 + inbound: + - health: {} port: 8080 + state: NotReady tags: app: sample - kuma.io/protocol: http - kuma.io/service: example_demo_svc_80 + k8s.kuma.io/namespace: demo k8s.kuma.io/service-name: example k8s.kuma.io/service-port: "80" - k8s.kuma.io/namespace: demo + kuma.io/protocol: http + kuma.io/service: example_demo_svc_80 kuma.io/zone: zone-1 - - state: NotReady - health: {} - port: 6060 + - health: {} name: metrics + port: 6060 + state: NotReady tags: app: sample - kuma.io/service: example_demo_svc_6061 - kuma.io/protocol: tcp + k8s.kuma.io/namespace: demo k8s.kuma.io/service-name: example k8s.kuma.io/service-port: "6061" - k8s.kuma.io/namespace: demo + kuma.io/protocol: tcp + kuma.io/service: example_demo_svc_6061 kuma.io/zone: zone-1 - - state: NotReady - health: {} + - health: {} port: 9090 + state: NotReady tags: app: sample - kuma.io/service: manual-example_demo_svc_90 - kuma.io/protocol: http + k8s.kuma.io/namespace: demo k8s.kuma.io/service-name: manual-example k8s.kuma.io/service-port: "90" - k8s.kuma.io/namespace: demo + kuma.io/protocol: http + kuma.io/service: manual-example_demo_svc_90 kuma.io/zone: zone-1 `)) }) diff --git a/pkg/plugins/runtime/k8s/controllers/pod_converter.go b/pkg/plugins/runtime/k8s/controllers/pod_converter.go index 0d99e730f0dd..9a6a4c3e5b43 100644 --- a/pkg/plugins/runtime/k8s/controllers/pod_converter.go +++ b/pkg/plugins/runtime/k8s/controllers/pod_converter.go @@ -48,11 +48,12 @@ func (p *PodConverter) PodToDataplane( ns *kube_core.Namespace, services []*kube_core.Service, others []*mesh_k8s.Dataplane, + msMode mesh_proto.Mesh_MeshServices_Mode, ) error { logger := converterLog.WithValues("Dataplane.name", dataplane.Name, "Pod.name", pod.Name) previousMesh := dataplane.Mesh dataplane.Mesh = util_k8s.MeshOfByLabelOrAnnotation(logger, pod, ns) - dataplaneProto, err := p.dataplaneFor(ctx, pod, services, others) + dataplaneProto, err := p.dataplaneFor(ctx, pod, services, others, msMode) if err != nil { return err } @@ -169,6 +170,7 @@ func (p *PodConverter) dataplaneFor( pod *kube_core.Pod, services []*kube_core.Service, others []*mesh_k8s.Dataplane, + msMode mesh_proto.Mesh_MeshServices_Mode, ) (*mesh_proto.Dataplane, error) { dataplane := &mesh_proto.Dataplane{ Networking: &mesh_proto.Dataplane_Networking{}, @@ -270,9 +272,20 @@ func (p *PodConverter) dataplaneFor( return nil, errors.Errorf("invalid delegated gateway type '%s'", gwType) } } else { - ifaces, err := p.InboundConverter.InboundInterfacesFor(ctx, p.Zone, pod, services) - if err != nil { - return nil, err + var ifaces []*mesh_proto.Dataplane_Networking_Inbound + var err error + // deduplicate inbounds only when MeshService mode is exclusive. Without MeshServices we need duplicated inbounds + // for identity and traffic routing + if msMode == mesh_proto.Mesh_MeshServices_Exclusive { + ifaces, err = p.InboundConverter.InboundInterfacesFor(ctx, p.Zone, pod, services) + if err != nil { + return nil, err + } + } else { + ifaces, err = p.InboundConverter.LegacyInboundInterfacesFor(ctx, p.Zone, pod, services) + if err != nil { + return nil, err + } } dataplane.Networking.Inbound = ifaces } @@ -309,13 +322,13 @@ func (p *PodConverter) dataplaneFor( } func (p *PodConverter) GatewayByServiceFor(ctx context.Context, clusterName string, pod *kube_core.Pod, services []*kube_core.Service) (*mesh_proto.Dataplane_Networking_Gateway, error) { - interfaces, err := p.InboundConverter.InboundInterfacesFor(ctx, clusterName, pod, services) + interfaces, err := p.InboundConverter.LegacyInboundInterfacesFor(ctx, clusterName, pod, services) if err != nil { return nil, err } return &mesh_proto.Dataplane_Networking_Gateway{ Type: mesh_proto.Dataplane_Networking_Gateway_DELEGATED, - Tags: interfaces[0].Tags, // InboundInterfacesFor() returns either a non-empty list or an error + Tags: interfaces[0].Tags, }, nil } diff --git a/pkg/plugins/runtime/k8s/controllers/pod_converter_test.go b/pkg/plugins/runtime/k8s/controllers/pod_converter_test.go index 4af991eb294c..88c841cb8c57 100644 --- a/pkg/plugins/runtime/k8s/controllers/pod_converter_test.go +++ b/pkg/plugins/runtime/k8s/controllers/pod_converter_test.go @@ -144,7 +144,7 @@ var _ = Describe("PodToDataplane(..)", func() { } // when - err = converter.PodToDataplane(context.Background(), existingDataplane, pod, &namespace, services, otherDataplanes) + err = converter.PodToDataplane(context.Background(), existingDataplane, pod, &namespace, services, otherDataplanes, mesh_proto.Mesh_MeshServices_Exclusive) // then Expect(err).ToNot(HaveOccurred()) @@ -327,6 +327,11 @@ var _ = Describe("PodToDataplane(..)", func() { otherServices: "update-dataplane.other-services.yaml", dataplane: "update-dataplane.dataplane.yaml", }), + Entry("Multiples services selecting single port", testCase{ + pod: "duplicated-inbounds.pod.yaml", + servicesForPod: "duplicated-inbounds.services-for-pod.yaml", + dataplane: "duplicated-inbounds.dataplane.yaml", + }), ) DescribeTable("should convert Ingress Pod into an Ingress Dataplane YAML version", diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/18.services-for-pod.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/18.services-for-pod.yaml index aad5d137c15d..f2bf8bed8138 100644 --- a/pkg/plugins/runtime/k8s/controllers/testdata/18.services-for-pod.yaml +++ b/pkg/plugins/runtime/k8s/controllers/testdata/18.services-for-pod.yaml @@ -8,3 +8,7 @@ spec: appProtocol: http port: 443 targetPort: 8443 + - protocol: TCP + appProtocol: http + port: 80 + targetPort: 8000 diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.dataplane.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.dataplane.yaml new file mode 100644 index 000000000000..cb76b4cf4982 --- /dev/null +++ b/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.dataplane.yaml @@ -0,0 +1,40 @@ +mesh: default +metadata: + creationTimestamp: null + labels: + app: example + k8s.kuma.io/namespace: demo + kuma.io/mesh: default + kuma.io/proxy-type: sidecar + kuma.io/sidecar-injection: enabled + version: "0.1" +spec: + networking: + address: 192.168.0.1 + inbound: + - health: + ready: true + name: main-port + port: 7070 + tags: + app: example + k8s.kuma.io/namespace: demo + k8s.kuma.io/service-name: example + k8s.kuma.io/service-port: "7000" + kuma.io/protocol: tcp + kuma.io/service: example_demo_svc_7000 + kuma.io/zone: zone-1 + version: "0.1" + - health: + ready: true + name: metrics + port: 6060 + tags: + app: example + k8s.kuma.io/namespace: demo + k8s.kuma.io/service-name: example + k8s.kuma.io/service-port: "6000" + kuma.io/protocol: tcp + kuma.io/service: example_demo_svc_6000 + kuma.io/zone: zone-1 + version: "0.1" diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.pod.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.pod.yaml new file mode 100644 index 000000000000..ac454c095a16 --- /dev/null +++ b/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.pod.yaml @@ -0,0 +1,25 @@ +metadata: + namespace: demo + name: example + labels: + app: example + version: "0.1" + kuma.io/sidecar-injection: enabled +spec: + containers: + - ports: [] + # when a 'targetPort' in a ServicePort is a number, + # it should not be mandatory to list container ports explicitly + # + # containerPort: 8080 + # containerPort: 8443 + - ports: + - containerPort: 7070 + name: main-port + - containerPort: 6060 + name: metrics +status: + podIP: 192.168.0.1 + containerStatuses: + - ready: true + started: true diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.services-for-pod.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.services-for-pod.yaml new file mode 100644 index 000000000000..eb5397399c59 --- /dev/null +++ b/pkg/plugins/runtime/k8s/controllers/testdata/duplicated-inbounds.services-for-pod.yaml @@ -0,0 +1,28 @@ +--- +metadata: + namespace: demo + name: example +spec: + clusterIP: 192.168.0.1 + ports: + - protocol: TCP + appProtocol: MONGO + port: 7000 + targetPort: 7070 + - protocol: TCP + port: 6000 + targetPort: metrics +--- +metadata: + namespace: playground + name: sample +spec: + clusterIP: 192.168.0.1 + ports: + - protocol: TCP + appProtocol: MONGO + port: 7001 + targetPort: 7070 + - protocol: TCP + port: 6001 + targetPort: metrics