This is an automated email from the ASF dual-hosted git repository.

ricardozanini pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-serverless-operator.git


The following commit(s) were added to refs/heads/main by this push:
     new 162f3693 kie-issues-308: Operator driven service discovery API Phase2 
(#309)
162f3693 is described below

commit 162f3693844de04e94b447b29253eb3ed38057ad
Author: Walter Medvedeo <[email protected]>
AuthorDate: Fri Nov 24 15:03:59 2023 +0100

    kie-issues-308: Operator driven service discovery API Phase2 (#309)
    
    * kie-issues-308: Operator driven service discovery API Phase2
        - Add the discovery of kubernetes Deployment, StatefulSet, and Ingress 
objects to the service discovery API.
    
    * kie-issues-308: Operator driven service discovery API Phase2
        - Code review suggestions 1, simplify the Deployment and StatefulSet 
discovery
---
 controllers/discovery/discovery.go                 |  93 +++++---
 controllers/discovery/discovery_test.go            | 218 +++++++++++++++---
 controllers/discovery/knative_catalog.go           |  31 +--
 controllers/discovery/kubernetes_catalog.go        | 116 +++++++---
 controllers/discovery/kubernetes_constants.go      |  29 +++
 controllers/discovery/port_utils.go                |  57 +++--
 controllers/discovery/port_utils_test.go           |  77 ++++---
 controllers/discovery/queries.go                   | 110 +++++++---
 controllers/discovery/queries_test.go              | 244 +++++++++++++--------
 controllers/discovery/test_utils.go                | 157 ++++++++++---
 controllers/discovery/uri_parser.go                |  42 ++--
 controllers/discovery/uri_parser_test.go           |  54 +++--
 controllers/discovery/uri_utils.go                 |  41 ++--
 controllers/discovery/uri_utils_test.go            |  83 +++----
 controllers/profiles/common/app_properties.go      |  31 +--
 controllers/profiles/common/app_properties_test.go |  31 +--
 16 files changed, 965 insertions(+), 449 deletions(-)

diff --git a/controllers/discovery/discovery.go 
b/controllers/discovery/discovery.go
index 06c4709f..4b170b9f 100644
--- a/controllers/discovery/discovery.go
+++ b/controllers/discovery/discovery.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -27,8 +32,9 @@ const (
        KubernetesScheme = "kubernetes"
        OpenshiftScheme  = "openshift"
 
-       // PortLabel well known label name to select a particular target port
-       PortLabel = "port"
+       // PortQueryParam well known query param to select a particular target 
port, for example when a service is being
+       // discovered and there are many ports to select.
+       PortQueryParam = "port"
 
        // KubernetesDNSAddress use this output format with kubernetes services 
and pods to resolve to the corresponding
        // kubernetes DNS name. see: 
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
@@ -53,11 +59,11 @@ const (
 )
 
 type ResourceUri struct {
-       Scheme       string
-       GVK          v1.GroupVersionKind
-       Namespace    string
-       Name         string
-       CustomLabels map[string]string
+       Scheme      string
+       GVK         v1.GroupVersionKind
+       Namespace   string
+       Name        string
+       QueryParams map[string]string
 }
 
 // ServiceCatalog is the entry point to resolve resource addresses given a 
ResourceUri.
@@ -105,9 +111,9 @@ type ResourceUriBuilder struct {
 func NewResourceUriBuilder(scheme string) ResourceUriBuilder {
        return ResourceUriBuilder{
                uri: &ResourceUri{
-                       Scheme:       scheme,
-                       GVK:          v1.GroupVersionKind{},
-                       CustomLabels: map[string]string{},
+                       Scheme:      scheme,
+                       GVK:         v1.GroupVersionKind{},
+                       QueryParams: map[string]string{},
                },
        }
 }
@@ -137,13 +143,13 @@ func (b ResourceUriBuilder) Name(name string) 
ResourceUriBuilder {
        return b
 }
 
-func (b ResourceUriBuilder) Port(customPort string) ResourceUriBuilder {
+func (b ResourceUriBuilder) WithPort(customPort string) ResourceUriBuilder {
        b.uri.SetPort(customPort)
        return b
 }
 
-func (b ResourceUriBuilder) WithLabel(labelName string, labelValue string) 
ResourceUriBuilder {
-       b.uri.CustomLabels[labelName] = labelValue
+func (b ResourceUriBuilder) WithQueryParam(param string, value string) 
ResourceUriBuilder {
+       b.uri.AddQueryParam(param, value)
        return b
 }
 
@@ -151,26 +157,43 @@ func (b ResourceUriBuilder) Build() *ResourceUri {
        return b.uri
 }
 
-func (r *ResourceUri) AddLabel(name string, value string) *ResourceUri {
+func (r *ResourceUri) AddQueryParam(name string, value string) {
        if len(value) > 0 {
-               r.CustomLabels[name] = value
+               r.QueryParams[name] = value
        }
-       return r
 }
 
-func (r *ResourceUri) GetLabel(name string) string {
+func (r *ResourceUri) GetQueryParam(name string) string {
        if len(name) > 0 {
-               return r.CustomLabels[name]
+               return r.QueryParams[name]
        }
        return ""
 }
 
-func (r *ResourceUri) SetPort(value string) *ResourceUri {
-       return r.AddLabel(PortLabel, value)
+func (r *ResourceUri) SetPort(value string) {
+       r.AddQueryParam(PortQueryParam, value)
 }
 
 func (r *ResourceUri) GetPort() string {
-       return r.GetLabel(PortLabel)
+       return r.GetQueryParam(PortQueryParam)
+}
+
+// GetCustomLabels returns all the query parameters that not considered well 
known query parameters, and thus, has no
+// particular semantic during the discovery. These arbitrary parameters are 
normally considered as labels, and when
+// present, and the service discovery must give a preference over a set of 
resources, they can be used to do a filtering.
+// by labels.
+func (r *ResourceUri) GetCustomLabels() map[string]string {
+       customQueryParams := make(map[string]string)
+       for k, v := range r.QueryParams {
+               if !isWellKnownQueryParam(k) && len(v) > 0 {
+                       customQueryParams[k] = v
+               }
+       }
+       return customQueryParams
+}
+
+func isWellKnownQueryParam(k string) bool {
+       return k == PortQueryParam
 }
 
 func (r *ResourceUri) String() string {
@@ -184,7 +207,7 @@ func (r *ResourceUri) String() string {
        uri = appendWithDelimiter(uri, r.Namespace, "/")
        uri = appendWithDelimiter(uri, r.Name, "/")
 
-       return appendWithDelimiter(uri, buildLabelsString(r.CustomLabels, "&"), 
"?")
+       return appendWithDelimiter(uri, buildLabelsString(r.QueryParams, "&"), 
"?")
 }
 
 func appendWithDelimiter(value string, toAppend string, delimiter string) 
string {
diff --git a/controllers/discovery/discovery_test.go 
b/controllers/discovery/discovery_test.go
index e54b4685..e03fcb01 100644
--- a/controllers/discovery/discovery_test.go
+++ b/controllers/discovery/discovery_test.go
@@ -1,25 +1,32 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
 import (
        "context"
+       "fmt"
        "testing"
 
        "github.com/stretchr/testify/assert"
        corev1 "k8s.io/api/core/v1"
+       v1 "k8s.io/api/networking/v1"
        "sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
@@ -29,22 +36,24 @@ func Test_NewResourceUriBuilder(t *testing.T) {
                Group("apps").
                Version("v1").
                Namespace(namespace1).
-               Name(service1).
-               Port("custom-port").
-               WithLabel(label1, valueLabel1).Build()
+               Name(service1Name).
+               WithPort("custom-port-value").
+               WithQueryParam(label1, valueLabel1).Build()
 
        assert.Equal(t, "deployments", resourceUri.GVK.Kind)
        assert.Equal(t, "apps", resourceUri.GVK.Group)
        assert.Equal(t, "v1", resourceUri.GVK.Version)
        assert.Equal(t, namespace1, resourceUri.Namespace)
-       assert.Equal(t, service1, resourceUri.Name)
-       assert.Equal(t, 2, len(resourceUri.CustomLabels))
-       assert.Equal(t, "custom-port", resourceUri.CustomLabels["port"])
-       assert.Equal(t, valueLabel1, resourceUri.CustomLabels[label1])
+       assert.Equal(t, service1Name, resourceUri.Name)
+       assert.Equal(t, 2, len(resourceUri.QueryParams))
+       assert.Equal(t, "custom-port-value", resourceUri.GetPort())
+       assert.Equal(t, valueLabel1, resourceUri.QueryParams[label1])
+       assert.Equal(t, 1, len(resourceUri.GetCustomLabels()))
+       assert.Equal(t, valueLabel1, resourceUri.GetCustomLabels()[label1])
 }
 
 func Test_QueryKubernetesServiceDNSMode(t *testing.T) {
-       doTestQueryKubernetesService(t, KubernetesDNSAddress, 
"http://service1.namespace1.svc:80";)
+       doTestQueryKubernetesService(t, KubernetesDNSAddress, 
"http://service1Name.namespace1.svc:80";)
 }
 
 func Test_QueryKubernetesServiceIPAddressMode(t *testing.T) {
@@ -52,7 +61,7 @@ func Test_QueryKubernetesServiceIPAddressMode(t *testing.T) {
 }
 
 func doTestQueryKubernetesService(t *testing.T, outputFormat string, 
expectedUri string) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort(httpProtocolName, tcp, defaultHttp))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
        service.Spec.Type = corev1.ServiceTypeNodePort
        service.Spec.ClusterIP = "10.1.5.18"
        cli := fake.NewClientBuilder().WithRuntimeObjects(service).Build()
@@ -61,7 +70,7 @@ func doTestQueryKubernetesService(t *testing.T, outputFormat 
string, expectedUri
                Kind("services").
                Version("v1").
                Namespace(namespace1).
-               Name(service1).Build(), outputFormat, expectedUri)
+               Name(service1Name).Build(), outputFormat, expectedUri)
 }
 
 func Test_QueryKubernetesPodDNSMode(t *testing.T) {
@@ -73,8 +82,8 @@ func Test_QueryKubernetesPodIPAddressMode(t *testing.T) {
 }
 
 func doTestQueryKubernetesPod(t *testing.T, outputFormat string, expectedUri 
string) {
-       pod := mockPodWithContainers(namespace1, pod1,
-               *mockContainerWithPorts("container1", 
mockContainerPort(httpProtocolName, tcp, defaultHttp)))
+       pod := mockPodWithContainers(namespace1, pod1Name,
+               *mockContainerWithPorts("container1Name", 
mockContainerPort(httpProtocol, tcp, defaultHttpPort)))
        pod.Status.PodIP = "10.1.12.13"
        cli := fake.NewClientBuilder().WithRuntimeObjects(pod).Build()
        ctg := NewServiceCatalog(cli)
@@ -82,7 +91,159 @@ func doTestQueryKubernetesPod(t *testing.T, outputFormat 
string, expectedUri str
                Kind("pods").
                Version("v1").
                Namespace(namespace1).
-               Name(pod1).Build(), outputFormat, expectedUri)
+               Name(pod1Name).Build(), outputFormat, expectedUri)
+}
+
+func Test_QueryKubernetesDeploymentWithServiceDNSMode(t *testing.T) {
+       doTesQueryKubernetesDeploymentWithService(t, KubernetesDNSAddress, 
"http://service1Name.namespace1.svc:80";)
+}
+
+func Test_QueryKubernetesDeploymentWithServiceIPAddressMode(t *testing.T) {
+       doTesQueryKubernetesDeploymentWithService(t, KubernetesIPAddress, 
"http://10.1.15.16:80";)
+}
+
+func doTesQueryKubernetesDeploymentWithService(t *testing.T, outputFormat 
string, expectedUri string) {
+       selector := map[string]string{
+               label1: valueLabel1,
+               label2: valueLabel2,
+       }
+
+       deployment := mockDeployment(namespace1, deployment1Name, nil, 
&selector)
+
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
+       service.Spec.Selector = selector
+       service.Spec.ClusterIP = "10.1.15.16"
+       service.Spec.Type = corev1.ServiceTypeNodePort
+
+       cli := fake.NewClientBuilder().WithRuntimeObjects(deployment, 
service).Build()
+       ctg := NewServiceCatalog(cli)
+
+       doTestQuery(t, ctg, *NewResourceUriBuilder(KubernetesScheme).
+               Group("apps").
+               Version("v1").
+               Kind("deployments").
+               Namespace(namespace1).
+               Name(deployment1Name).Build(),
+               outputFormat, expectedUri)
+}
+
+func Test_QueryKubernetesDeploymentWithoutServiceDNSMode(t *testing.T) {
+       doTestQueryKubernetesDeploymentWithoutService(t, KubernetesDNSAddress)
+}
+
+func Test_QueryKubernetesDeploymentWithoutServiceIPAddressMode(t *testing.T) {
+       doTestQueryKubernetesDeploymentWithoutService(t, KubernetesIPAddress)
+}
+
+func doTestQueryKubernetesDeploymentWithoutService(t *testing.T, outputFormat 
string) {
+       selector := map[string]string{
+               label1: valueLabel1,
+               label2: valueLabel2,
+       }
+
+       deployment := mockDeployment(namespace1, deployment1Name, nil, 
&selector)
+       ctg := 
NewServiceCatalog(fake.NewClientBuilder().WithRuntimeObjects(deployment).Build())
+
+       uri := *NewResourceUriBuilder(KubernetesScheme).
+               Group("apps").
+               Version("v1").
+               Kind("deployments").
+               Namespace(namespace1).
+               Name(deployment1Name).Build()
+
+       doTestQueryWithError(t, ctg, uri, outputFormat, fmt.Sprintf("no service 
was found for the deployment: %s", uri.Name))
+}
+
+func Test_QueryKubernetesStatefulSetWithServiceDNSMode(t *testing.T) {
+       doTestQueryKubernetesStatefulSetWithService(t, KubernetesDNSAddress, 
"http://service1Name.namespace1.svc:80";)
+}
+
+func Test_QueryKubernetesStatefulSetWithServiceIPAddressMode(t *testing.T) {
+       doTestQueryKubernetesStatefulSetWithService(t, KubernetesIPAddress, 
"http://10.1.18.19:80";)
+}
+
+func doTestQueryKubernetesStatefulSetWithService(t *testing.T, outputFormat 
string, expectedUri string) {
+       selector := map[string]string{
+               label1: valueLabel1,
+               label2: valueLabel2,
+       }
+
+       statefulSet := mockStatefulSet(namespace1, statefulSet1Name, nil, 
&selector)
+
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
+       service.Spec.Selector = selector
+       service.Spec.ClusterIP = "10.1.18.19"
+       service.Spec.Type = corev1.ServiceTypeNodePort
+
+       cli := fake.NewClientBuilder().WithRuntimeObjects(statefulSet, 
service).Build()
+       ctg := NewServiceCatalog(cli)
+
+       doTestQuery(t, ctg, *NewResourceUriBuilder(KubernetesScheme).
+               Group("apps").
+               Version("v1").
+               Kind("statefulsets").
+               Namespace(namespace1).
+               Name(statefulSet1Name).Build(),
+               outputFormat, expectedUri)
+}
+
+func Test_QueryKubernetesStatefulSetWithoutServiceDNSMode(t *testing.T) {
+       doTestQueryKubernetesStatefulSetWithoutService(t, KubernetesDNSAddress)
+}
+
+func Test_QueryKubernetesStatefulSetWithoutServiceIPAddressMode(t *testing.T) {
+       doTestQueryKubernetesStatefulSetWithoutService(t, KubernetesIPAddress)
+}
+
+func doTestQueryKubernetesStatefulSetWithoutService(t *testing.T, outputFormat 
string) {
+       selector := map[string]string{
+               label1: valueLabel1,
+               label2: valueLabel2,
+       }
+
+       statefulSet := mockStatefulSet(namespace1, statefulSet1Name, nil, 
&selector)
+       ctg := 
NewServiceCatalog(fake.NewClientBuilder().WithRuntimeObjects(statefulSet).Build())
+
+       uri := *NewResourceUriBuilder(KubernetesScheme).
+               Group("apps").
+               Version("v1").
+               Kind("statefulsets").
+               Namespace(namespace1).
+               Name(statefulSet1Name).Build()
+       doTestQueryWithError(t, ctg, uri, outputFormat, fmt.Sprintf("no service 
was found for the statefulset: %s", uri.Name))
+}
+
+func Test_QueryKubernetesIngressHostNoTLS(t *testing.T) {
+       doTestQueryKubernetesIngress(t, "myingresshost.com.uy", "", false, 
KubernetesIPAddress, "http://myingresshost.com.uy:80";)
+}
+
+func Test_QueryKubernetesIngressHostWithTLS(t *testing.T) {
+       doTestQueryKubernetesIngress(t, "myingresshost.com.uy", "", true, 
KubernetesIPAddress, "https://myingresshost.com.uy:443";)
+}
+
+func Test_QueryKubernetesIngressIPNoTLS(t *testing.T) {
+       doTestQueryKubernetesIngress(t, "", "142.250.184.174", false, 
KubernetesIPAddress, "http://142.250.184.174:80";)
+}
+
+func Test_QueryKubernetesIngressIPWithTLS(t *testing.T) {
+       doTestQueryKubernetesIngress(t, "", "142.250.184.174", true, 
KubernetesIPAddress, "https://142.250.184.174:443";)
+}
+
+func doTestQueryKubernetesIngress(t *testing.T, hostName string, ip string, 
tls bool, outputFormat string, expectedUri string) {
+       ingress := mockIngress(namespace1, ingress1Name)
+
+       ingress.Status.LoadBalancer.Ingress = 
[]v1.IngressLoadBalancerIngress{{Hostname: hostName, IP: ip}}
+       if tls {
+               ingress.Spec.TLS = []v1.IngressTLS{{}}
+       }
+       cli := fake.NewClientBuilder().WithRuntimeObjects(ingress).Build()
+       ctg := NewServiceCatalog(cli)
+       doTestQuery(t, ctg, *NewResourceUriBuilder(KubernetesScheme).
+               Kind("ingresses").
+               Group("networking.k8s.io").
+               Version("v1").
+               Namespace(namespace1).
+               Name(ingress1Name).Build(), outputFormat, expectedUri)
 }
 
 func doTestQuery(t *testing.T, ctg ServiceCatalog, resourceUri ResourceUri, 
outputFormat, expectedUri string) {
@@ -90,3 +251,8 @@ func doTestQuery(t *testing.T, ctg ServiceCatalog, 
resourceUri ResourceUri, outp
        assert.NoError(t, err)
        assert.Equal(t, expectedUri, uri)
 }
+
+func doTestQueryWithError(t *testing.T, ctg ServiceCatalog, resourceUri 
ResourceUri, outputFormat string, expectedErrorMessage string) {
+       _, err := ctg.Query(context.TODO(), resourceUri, outputFormat)
+       assert.ErrorContains(t, err, expectedErrorMessage)
+}
diff --git a/controllers/discovery/knative_catalog.go 
b/controllers/discovery/knative_catalog.go
index ad7fb011..77760015 100644
--- a/controllers/discovery/knative_catalog.go
+++ b/controllers/discovery/knative_catalog.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
diff --git a/controllers/discovery/kubernetes_catalog.go 
b/controllers/discovery/kubernetes_catalog.go
index eb526e75..324a798e 100644
--- a/controllers/discovery/kubernetes_catalog.go
+++ b/controllers/discovery/kubernetes_catalog.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -22,8 +27,11 @@ import (
 )
 
 const (
-       serviceKind = "services"
-       podKind     = "pods"
+       serviceKind     = "services"
+       podKind         = "pods"
+       deploymentKind  = "deployments"
+       statefulSetKind = "statefulsets"
+       ingressKind     = "ingresses"
 )
 
 type k8sServiceCatalog struct {
@@ -42,8 +50,14 @@ func (c k8sServiceCatalog) Query(ctx context.Context, uri 
ResourceUri, outputFor
                return c.resolveServiceQuery(ctx, uri, outputFormat)
        case podKind:
                return c.resolvePodQuery(ctx, uri, outputFormat)
+       case deploymentKind:
+               return c.resolveDeploymentQuery(ctx, uri, outputFormat)
+       case statefulSetKind:
+               return c.resolveStatefulSetQuery(ctx, uri, outputFormat)
+       case ingressKind:
+               return c.resolveIngressQuery(ctx, uri)
        default:
-               return "", fmt.Errorf("resolution of kind: %s is not yet 
implemented", uri.GVK.Kind)
+               return "", fmt.Errorf("resolution of kind: %s is not 
implemented", uri.GVK.Kind)
        }
 }
 
@@ -58,21 +72,67 @@ func (c k8sServiceCatalog) resolveServiceQuery(ctx 
context.Context, uri Resource
 }
 
 func (c k8sServiceCatalog) resolvePodQuery(ctx context.Context, uri 
ResourceUri, outputFormat string) (string, error) {
-       if pod, service, err := findPodAndReferenceServiceByPodLabels(ctx, 
c.Client, uri.Namespace, uri.Name); err != nil {
+       if pod, serviceList, err := findPodAndReferenceServices(ctx, c.Client, 
uri.Namespace, uri.Name); err != nil {
                return "", err
        } else {
-               if service != nil {
-                       if serviceUri, err := resolveServiceUri(service, 
uri.GetPort(), outputFormat); err != nil {
-                               return "", err
-                       } else {
-                               return serviceUri, nil
-                       }
+               if serviceList != nil && len(serviceList.Items) > 0 {
+                       referenceService := 
selectBestSuitedServiceByCustomLabels(serviceList, uri.GetCustomLabels())
+                       return resolveServiceUri(referenceService, 
uri.GetPort(), outputFormat)
                } else {
-                       if podUri, err := resolvePodUri(pod, "", uri.GetPort(), 
outputFormat); err != nil {
-                               return "", err
-                       } else {
-                               return podUri, nil
-                       }
+                       return resolvePodUri(pod, "", uri.GetPort(), 
outputFormat)
                }
        }
 }
+
+func (c k8sServiceCatalog) resolveDeploymentQuery(ctx context.Context, uri 
ResourceUri, outputFormat string) (string, error) {
+       if deployment, err := findDeployment(ctx, c.Client, uri.Namespace, 
uri.Name); err != nil {
+               return "", err
+       } else {
+               if serviceList, err := findServicesBySelectorTarget(ctx, 
c.Client, uri.Namespace, deployment.Spec.Selector.MatchLabels); err != nil {
+                       return "", err
+               } else if len(serviceList.Items) == 0 {
+                       return "", fmt.Errorf("no service was found for the 
deployment: %s in namespace: %s", uri.Name, uri.Namespace)
+               } else {
+                       referenceService := 
selectBestSuitedServiceByCustomLabels(serviceList, uri.GetCustomLabels())
+                       return resolveServiceUri(referenceService, 
uri.GetPort(), outputFormat)
+               }
+       }
+}
+
+func (c k8sServiceCatalog) resolveStatefulSetQuery(ctx context.Context, uri 
ResourceUri, outputFormat string) (string, error) {
+       if statefulSet, err := findStatefulSet(ctx, c.Client, uri.Namespace, 
uri.Name); err != nil {
+               return "", err
+       } else {
+               if serviceList, err := findServicesBySelectorTarget(ctx, 
c.Client, uri.Namespace, statefulSet.Spec.Selector.MatchLabels); err != nil {
+                       return "", err
+               } else if len(serviceList.Items) == 0 {
+                       return "", fmt.Errorf("no service was found for the 
statefulset: %s in namespace: %s", uri.Name, uri.Namespace)
+               } else {
+                       referenceService := 
selectBestSuitedServiceByCustomLabels(serviceList, uri.GetCustomLabels())
+                       return resolveServiceUri(referenceService, 
uri.GetPort(), outputFormat)
+               }
+       }
+}
+
+func (c k8sServiceCatalog) resolveIngressQuery(ctx context.Context, uri 
ResourceUri) (string, error) {
+       if ingress, err := findIngress(ctx, c.Client, uri.Namespace, uri.Name); 
err != nil {
+               return "", err
+       } else {
+               // for now stick with the first ip or hostname.
+               loadBalancer := ingress.Status.LoadBalancer.Ingress[0]
+               var scheme = httpProtocol
+               var host string
+               var port = defaultHttpPort
+               if len(loadBalancer.Hostname) > 0 {
+                       host = loadBalancer.Hostname
+               } else {
+                       host = loadBalancer.IP
+               }
+               // An Ingress does not expose arbitrary ports or protocols 
other than HTTP and HTTPS
+               if len(ingress.Spec.TLS) >= 1 {
+                       scheme = httpsProtocol
+                       port = defaultHttpsPort
+               }
+               return buildURI(scheme, host, port), nil
+       }
+}
diff --git a/controllers/discovery/kubernetes_constants.go 
b/controllers/discovery/kubernetes_constants.go
new file mode 100644
index 00000000..78d472d1
--- /dev/null
+++ b/controllers/discovery/kubernetes_constants.go
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package discovery
+
+const (
+       httpProtocol         = "http"
+       httpsProtocol        = "https"
+       webProtocol          = "web"
+       defaultHttpPort      = 80
+       defaultHttpsPort     = 443
+       defaultAppSecurePort = 8443
+)
diff --git a/controllers/discovery/port_utils.go 
b/controllers/discovery/port_utils.go
index 891995c6..207d7c6b 100644
--- a/controllers/discovery/port_utils.go
+++ b/controllers/discovery/port_utils.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -19,16 +24,8 @@ import (
        corev1 "k8s.io/api/core/v1"
 )
 
-const (
-       httpProtocolName  = "http"
-       httpsProtocolName = "https"
-       webProtocolName   = "web"
-       securePort        = 443
-       appSecurePort     = 8443
-)
-
 func isSecurePort(port int) bool {
-       return port == securePort || port == appSecurePort
+       return port == defaultHttpsPort || port == defaultAppSecurePort
 }
 
 // findBestSuitedServicePort returns the best suited ServicePort to connect to 
a service.
@@ -42,15 +39,15 @@ func findBestSuitedServicePort(service *corev1.Service, 
customPort string) *core
                }
        }
        // has ssl port?
-       if result, _ := kubernetes.GetServicePortByName(httpsProtocolName, 
service); result != nil {
+       if result, _ := kubernetes.GetServicePortByName(httpsProtocol, 
service); result != nil {
                return result
        }
        // has http port?
-       if result, _ := kubernetes.GetServicePortByName(httpProtocolName, 
service); result != nil {
+       if result, _ := kubernetes.GetServicePortByName(httpProtocol, service); 
result != nil {
                return result
        }
        // has web port?
-       if result, _ := kubernetes.GetServicePortByName(webProtocolName, 
service); result != nil {
+       if result, _ := kubernetes.GetServicePortByName(webProtocol, service); 
result != nil {
                return result
        }
        // by definition a service must always have at least one port, get the 
first port.
@@ -58,7 +55,7 @@ func findBestSuitedServicePort(service *corev1.Service, 
customPort string) *core
 }
 
 func isSecureServicePort(servicePort *corev1.ServicePort) bool {
-       return servicePort.Name == httpsProtocolName || 
isSecurePort(int(servicePort.Port))
+       return servicePort.Name == httpsProtocol || 
isSecurePort(int(servicePort.Port))
 }
 
 // findBestSuitedContainerPort returns the best suited PortPort to connect to 
a pod, or nil if the pod has no ports at all.
@@ -76,15 +73,15 @@ func findBestSuitedContainerPort(container 
*corev1.Container, customPort string)
                }
        }
        // has ssl port?
-       if result, _ := kubernetes.GetContainerPortByName(httpsProtocolName, 
container); result != nil {
+       if result, _ := kubernetes.GetContainerPortByName(httpsProtocol, 
container); result != nil {
                return result
        }
        // has http port?
-       if result, _ := kubernetes.GetContainerPortByName(httpProtocolName, 
container); result != nil {
+       if result, _ := kubernetes.GetContainerPortByName(httpProtocol, 
container); result != nil {
                return result
        }
        // has web port?
-       if result, _ := kubernetes.GetContainerPortByName(webProtocolName, 
container); result != nil {
+       if result, _ := kubernetes.GetContainerPortByName(webProtocol, 
container); result != nil {
                return result
        }
        // when defined, a ContainerPort must always have containerPort 
(Required value)
@@ -92,5 +89,5 @@ func findBestSuitedContainerPort(container *corev1.Container, 
customPort string)
 }
 
 func isSecureContainerPort(containerPort *corev1.ContainerPort) bool {
-       return containerPort.Name == httpsProtocolName || 
isSecurePort(int(containerPort.ContainerPort))
+       return containerPort.Name == httpsProtocol || 
isSecurePort(int(containerPort.ContainerPort))
 }
diff --git a/controllers/discovery/port_utils_test.go 
b/controllers/discovery/port_utils_test.go
index 367dc428..9e01b9bc 100644
--- a/controllers/discovery/port_utils_test.go
+++ b/controllers/discovery/port_utils_test.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -29,44 +34,44 @@ func TestIsSecurePort(t *testing.T) {
 }
 
 func TestBestSuitedServicePort_BestIsCustomPort(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort("not-wanted", tcp, 8282),
-               mockServicePort(httpsProtocolName, tcp, defaultHttps),
-               mockServicePort(customPortName, tcp, defaultHttp))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort("not-wanted", tcp, 8282),
+               mockServicePort(httpsProtocol, tcp, defaultHttpsPort),
+               mockServicePort(customPortName, tcp, defaultHttpPort))
        doTestBestSuitedServicePort(t, service, customPortName, 
&service.Spec.Ports[2])
 }
 
 func TestBestSuitedServicePort_BestIsHttpsPort(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort("not-wanted", tcp, 8282),
-               mockServicePort(httpProtocolName, tcp, defaultHttp),
-               mockServicePort(httpsProtocolName, tcp, defaultHttps))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort("not-wanted", tcp, 8282),
+               mockServicePort(httpProtocol, tcp, defaultHttpPort),
+               mockServicePort(httpsProtocol, tcp, defaultHttpsPort))
        doTestBestSuitedServicePort(t, service, "", &service.Spec.Ports[2])
 }
 
 func TestBestSuitedServicePort_BestIsHttpPort(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort("not-wanted", tcp, 8282),
-               mockServicePort(webProtocolName, tcp, 81),
-               mockServicePort(httpProtocolName, tcp, defaultHttp))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort("not-wanted", tcp, 8282),
+               mockServicePort(webProtocol, tcp, 81),
+               mockServicePort(httpProtocol, tcp, defaultHttpPort))
        doTestBestSuitedServicePort(t, service, "", &service.Spec.Ports[2])
 }
 
 func TestBestSuitedServicePort_BestWebPort(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort("not-wanted", tcp, 8282),
-               mockServicePort(webProtocolName, tcp, 81))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort("not-wanted", tcp, 8282),
+               mockServicePort(webProtocol, tcp, 81))
        doTestBestSuitedServicePort(t, service, "", &service.Spec.Ports[1])
 }
 
 func TestBestSuitedServicePort_BestIsFirst(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort("first-port", tcp, 8282),
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort("first-port", tcp, 8282),
                mockServicePort("second-port", tcp, 8383))
        doTestBestSuitedServicePort(t, service, "", &service.Spec.Ports[0])
 }
 
 func TestIsSecureServicePort(t *testing.T) {
-       servicePort := mockServicePort(httpsProtocolName, tcp, 443)
+       servicePort := mockServicePort(httpsProtocol, tcp, 443)
        assert.True(t, isSecureServicePort(&servicePort))
        servicePort = mockServicePort("other-secure-port", tcp, 443)
        assert.True(t, isSecureServicePort(&servicePort))
-       servicePort = mockServicePort(httpProtocolName, tcp, 80)
+       servicePort = mockServicePort(httpProtocol, tcp, 80)
        assert.False(t, isSecureServicePort(&servicePort))
 }
 
@@ -81,28 +86,28 @@ func TestBestSuitedContainerPort_ContainerWithNoPorts(t 
*testing.T) {
 
 func TestBestSuitedContainerPort_BestIsCustomPort(t *testing.T) {
        container := mockContainerWithPorts("", mockContainerPort("not-wanted", 
tcp, 8282),
-               mockContainerPort(httpsProtocolName, tcp, defaultHttps),
-               mockContainerPort(customPortName, tcp, defaultHttp))
+               mockContainerPort(httpsProtocol, tcp, defaultHttpsPort),
+               mockContainerPort(customPortName, tcp, defaultHttpPort))
        doTestBestSuitedContainerPort(t, container, customPortName, 
&container.Ports[2])
 }
 
 func TestBestSuitedContainerPort_BestIsHttpsPort(t *testing.T) {
        container := mockContainerWithPorts("", mockContainerPort("not-wanted", 
tcp, 8282),
-               mockContainerPort(httpProtocolName, tcp, defaultHttp),
-               mockContainerPort(httpsProtocolName, tcp, defaultHttps))
+               mockContainerPort(httpProtocol, tcp, defaultHttpPort),
+               mockContainerPort(httpsProtocol, tcp, defaultHttpsPort))
        doTestBestSuitedContainerPort(t, container, "", &container.Ports[2])
 }
 
 func TestBestSuitedContainerPort_BestIsHttpPort(t *testing.T) {
        container := mockContainerWithPorts("", mockContainerPort("not-wanted", 
tcp, 8282),
-               mockContainerPort(webProtocolName, tcp, 81),
-               mockContainerPort(httpProtocolName, tcp, defaultHttp))
+               mockContainerPort(webProtocol, tcp, 81),
+               mockContainerPort(httpProtocol, tcp, defaultHttpsPort))
        doTestBestSuitedContainerPort(t, container, "", &container.Ports[2])
 }
 
 func TestBestSuitedContainerPort_BestWebPort(t *testing.T) {
        container := mockContainerWithPorts("", mockContainerPort("not-wanted", 
tcp, 8282),
-               mockContainerPort(webProtocolName, tcp, 81))
+               mockContainerPort(webProtocol, tcp, 81))
        doTestBestSuitedContainerPort(t, container, "", &container.Ports[1])
 }
 
@@ -118,10 +123,10 @@ func doTestBestSuitedContainerPort(t *testing.T, 
container *corev1.Container, cu
 }
 
 func TestIsSecureContainerPort(t *testing.T) {
-       containerPort := mockContainerPort(httpsProtocolName, tcp, 443)
+       containerPort := mockContainerPort(httpsProtocol, tcp, 443)
        assert.True(t, isSecureContainerPort(&containerPort))
        containerPort = mockContainerPort("other-secure-port", tcp, 443)
        assert.True(t, isSecureContainerPort(&containerPort))
-       containerPort = mockContainerPort(httpProtocolName, tcp, 80)
+       containerPort = mockContainerPort(httpProtocol, tcp, 80)
        assert.False(t, isSecureContainerPort(&containerPort))
 }
diff --git a/controllers/discovery/queries.go b/controllers/discovery/queries.go
index 5710201d..37a7e1a6 100644
--- a/controllers/discovery/queries.go
+++ b/controllers/discovery/queries.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -24,8 +29,6 @@ import (
        "sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-const podTemplateHashLabel = "pod-template-hash"
-
 // findService finds a service by name in the given namespace.
 func findService(ctx context.Context, cli client.Client, namespace string, 
name string) (*corev1.Service, error) {
        service := &corev1.Service{}
@@ -35,13 +38,65 @@ func findService(ctx context.Context, cli client.Client, 
namespace string, name
        return service, nil
 }
 
-// findServiceByLabels finds a service by a set of matching labels in the 
given namespace.
-func findServiceByLabels(ctx context.Context, cli client.Client, namespace 
string, labels map[string]string) (*corev1.ServiceList, error) {
+// findServicesBySelectorTarget finds the services for which all the 
configured selector labels are present in the
+// selection target map.
+func findServicesBySelectorTarget(ctx context.Context, cli client.Client, 
namespace string, selectorTarget map[string]string) (*corev1.ServiceList, 
error) {
        serviceList := &corev1.ServiceList{}
-       if err := cli.List(ctx, serviceList, client.InNamespace(namespace), 
client.MatchingLabels(labels)); err != nil {
+       items := make([]corev1.Service, 0)
+       if err := cli.List(ctx, serviceList, client.InNamespace(namespace)); 
err != nil {
                return nil, err
+       } else {
+               for _, service := range serviceList.Items {
+                       if len(service.Spec.Selector) > 0 && 
containsSubset(selectorTarget, service.Spec.Selector) {
+                               items = append(items, service)
+                       }
+               }
+       }
+       return &corev1.ServiceList{Items: items}, nil
+}
+
+// selectBestSuitedServiceByCustomLabels In situations where a previous query 
returned many Services, for example, to
+// access a set of pods, or a deployment, we can filter them by a set of 
customLabels, to determine which one is the best suited.
+func selectBestSuitedServiceByCustomLabels(serviceList *corev1.ServiceList, 
customLabels map[string]string) *corev1.Service {
+       var filteredService *corev1.Service = nil
+       if len(serviceList.Items) > 0 {
+               if len(serviceList.Items) == 1 {
+                       filteredService = &serviceList.Items[0]
+               } else {
+                       filteredService = &serviceList.Items[0]
+                       if len(customLabels) > 0 {
+                               if filteredServiceList := 
filterServiceListByLabelsSubset(serviceList, customLabels); 
len(filteredServiceList.Items) > 0 {
+                                       filteredService = 
&filteredServiceList.Items[0]
+                               }
+                       }
+               }
+       }
+       return filteredService
+}
+
+func filterServiceListByLabelsSubset(serviceList *corev1.ServiceList, labels 
map[string]string) *corev1.ServiceList {
+       var items = make([]corev1.Service, 0)
+       for _, service := range serviceList.Items {
+               if containsSubset(service.Labels, labels) {
+                       items = append(items, service)
+               }
+       }
+       return &corev1.ServiceList{Items: items}
+}
+
+func containsSubset(container map[string]string, subset map[string]string) 
bool {
+       if container == nil {
+               return subset == nil
+       } else if subset == nil {
+               return true
+       } else {
+               for k, v := range subset {
+                       if cv := container[k]; cv != v {
+                               return false
+                       }
+               }
        }
-       return serviceList, nil
+       return true
 }
 
 // findPod finds a pod by name in the given namespace.
@@ -53,21 +108,18 @@ func findPod(ctx context.Context, cli client.Client, 
namespace string, name stri
        return pod, nil
 }
 
-// findPodAndReferenceServiceByPodLabels finds a pod by name in the given 
namespace at the same time it piggybacks it's
-// reference service if any. The reference service is determined by using the 
same set of labels as the pod.
-func findPodAndReferenceServiceByPodLabels(ctx context.Context, cli 
client.Client, namespace string, name string) (*corev1.Pod, *corev1.Service, 
error) {
+// findPodAndReferenceServices finds a pod by name in the given namespace, at 
the same time it piggybacks potential
+// reference services if any. The reference services are determined by looking 
if the corresponding selector labels
+// matches the pod labels.
+func findPodAndReferenceServices(ctx context.Context, cli client.Client, 
namespace string, name string) (*corev1.Pod, *corev1.ServiceList, error) {
        if pod, err := findPod(ctx, cli, namespace, name); err != nil {
                return nil, nil, err
        } else {
-               queryLabels := pod.Labels
-               // pod-template-hash is pod dependent, mustn't be considered.
-               delete(queryLabels, podTemplateHashLabel)
-               if len(queryLabels) > 0 {
-                       // check if we have a defined reference service
-                       if serviceList, err := findServiceByLabels(ctx, cli, 
namespace, queryLabels); err != nil {
+               if len(pod.Labels) > 0 {
+                       if serviceList, err := 
findServicesBySelectorTarget(ctx, cli, namespace, pod.Labels); err != nil {
                                return nil, nil, err
                        } else if len(serviceList.Items) > 0 {
-                               return pod, &serviceList.Items[0], nil
+                               return pod, serviceList, nil
                        }
                }
                return pod, nil, nil
diff --git a/controllers/discovery/queries_test.go 
b/controllers/discovery/queries_test.go
index 4c130407..b0500b78 100644
--- a/controllers/discovery/queries_test.go
+++ b/controllers/discovery/queries_test.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -22,14 +27,13 @@ import (
        appsv1 "k8s.io/api/apps/v1"
        corev1 "k8s.io/api/core/v1"
        networkingV1 "k8s.io/api/networking/v1"
-       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
 func Test_findService(t *testing.T) {
        service := mockService1(nil)
        cli := fake.NewClientBuilder().WithRuntimeObjects(service).Build()
-       result, err := findService(context.TODO(), cli, namespace1, service1)
+       result, err := findService(context.TODO(), cli, namespace1, 
service1Name)
 
        assert.NoError(t, err)
        assert.Equal(t, service, result)
@@ -37,45 +41,108 @@ func Test_findService(t *testing.T) {
 
 func Test_findServiceNotFound(t *testing.T) {
        cli := fake.NewClientBuilder().Build()
-       _, err := findService(context.TODO(), cli, namespace1, service1)
-       assert.ErrorContains(t, err, "\"service1\" not found")
+       _, err := findService(context.TODO(), cli, namespace1, service1Name)
+       assert.ErrorContains(t, err, "\"service1Name\" not found")
 }
 
-func Test_findServiceByLabels(t *testing.T) {
-       labels := &map[string]string{
+func Test_findServicesBySelectorTarget(t *testing.T) {
+       selector1Labels := &map[string]string{
+               label1: valueLabel1,
+               label2: valueLabel2,
+       }
+       selector2Labels := &map[string]string{
+               label1: valueLabel1,
+               label3: valueLabel3,
+       }
+       selector3Labels := &map[string]string{
                label1: valueLabel1,
                label2: valueLabel2,
        }
-       service := mockService1(labels)
-       cli := fake.NewClientBuilder().WithRuntimeObjects(service).Build()
-       serviceList, err := findServiceByLabels(context.TODO(), cli, 
namespace1, *labels)
+
+       service1 := mockService1(selector1Labels)
+       service2 := mockService2(selector2Labels)
+       service3 := mockService3(selector3Labels)
+       cli := fake.NewClientBuilder().WithRuntimeObjects(service1, service2, 
service3).Build()
+       serviceList, err := findServicesBySelectorTarget(context.TODO(), cli, 
namespace1, *selector1Labels)
 
        assert.NoError(t, err)
-       assert.Len(t, serviceList.Items, 1)
-       assert.Equal(t, service, &serviceList.Items[0])
+       assert.Len(t, serviceList.Items, 2)
+       assert.Equal(t, service1, &serviceList.Items[0])
+       assert.Equal(t, service3, &serviceList.Items[1])
 }
 
-func Test_findServiceByLabelsNotFound(t *testing.T) {
-       labels := &map[string]string{
+func Test_findServicesBySelectorTargetNotFound(t *testing.T) {
+       selectorLabels := &map[string]string{
                label1: valueLabel1,
                label2: valueLabel2,
        }
        queryLabels := map[string]string{
                label1: valueLabel1,
        }
-       service := mockService1(labels)
+       service := mockService1(selectorLabels)
        cli := fake.NewClientBuilder().WithRuntimeObjects(service).Build()
-       serviceList, err := findServiceByLabels(context.TODO(), cli, 
namespace1, queryLabels)
+       serviceList, err := findServicesBySelectorTarget(context.TODO(), cli, 
namespace1, queryLabels)
 
        assert.NoError(t, err)
-       assert.Len(t, serviceList.Items, 1)
-       assert.Equal(t, service, &serviceList.Items[0])
+       assert.Len(t, serviceList.Items, 0)
+}
+
+func Test_selectBestSuitedServiceByCustomLabels(t *testing.T) {
+       service1 := mockService1(nil)
+       service1.Labels = map[string]string{
+               label1: valueLabel1,
+               label2: valueLabel2,
+       }
+       service2 := mockService2(nil)
+       service2.Labels = map[string]string{
+               label1:        valueLabel1,
+               label3:        valueLabel3,
+               "environment": "dev",
+       }
+       service3 := mockService2(nil)
+       service3.Labels = map[string]string{
+               label2: valueLabel2,
+               label3: valueLabel3,
+       }
+       serviceList := &corev1.ServiceList{
+               Items: []corev1.Service{*service1, *service2, *service3},
+       }
+       bestSuitedService := selectBestSuitedServiceByCustomLabels(serviceList, 
map[string]string{"environment": "dev"})
+       assert.Equal(t, service2, bestSuitedService)
+}
+
+func Test_filterServiceListByLabelsSubset(t *testing.T) {
+       service1 := mockService1(nil)
+       service1.Labels = map[string]string{
+               label1: valueLabel1,
+       }
+       service2 := mockService2(nil)
+       service2.Labels = map[string]string{
+               label1: valueLabel1,
+               label3: valueLabel3,
+       }
+       service3 := mockService3(nil)
+       service3.Labels = map[string]string{
+               label1: valueLabel1,
+               label2: valueLabel2,
+               label3: valueLabel3,
+       }
+       serviceList := &corev1.ServiceList{
+               Items: []corev1.Service{*service1, *service2, *service3},
+       }
+       filteredServiceList := filterServiceListByLabelsSubset(serviceList, 
map[string]string{
+               label1: valueLabel1,
+               label3: valueLabel3})
+
+       assert.Len(t, filteredServiceList.Items, 2)
+       assert.Equal(t, *service2, filteredServiceList.Items[0])
+       assert.Equal(t, *service3, filteredServiceList.Items[1])
 }
 
 func Test_findPod(t *testing.T) {
        pod := mockPod1(nil)
        cli := fake.NewClientBuilder().WithRuntimeObjects(pod).Build()
-       result, err := findPod(context.TODO(), cli, namespace1, pod1)
+       result, err := findPod(context.TODO(), cli, namespace1, pod1Name)
 
        assert.NoError(t, err)
        assert.Equal(t, pod, result)
@@ -83,45 +150,51 @@ func Test_findPod(t *testing.T) {
 
 func Test_findPodNotFound(t *testing.T) {
        cli := fake.NewClientBuilder().Build()
-       _, err := findPod(context.TODO(), cli, namespace1, pod1)
-       assert.ErrorContains(t, err, "\"pod1\" not found")
+       _, err := findPod(context.TODO(), cli, namespace1, pod1Name)
+       assert.ErrorContains(t, err, "\"pod1Name\" not found")
 }
 
-func Test_findPodAndReferenceServiceByPodLabelsWithReferenceService(t 
*testing.T) {
+func Test_findPodAndReferenceServicesWithReferenceService(t *testing.T) {
        podLabels := &map[string]string{
                label1: valueLabel1,
                label2: valueLabel2,
+               label3: valueLabel3,
        }
-       service := mockService1(podLabels)
+       selectorLabels := &map[string]string{
+               label1: valueLabel1,
+               label2: valueLabel2,
+       }
+       service := mockService1(selectorLabels)
        pod := mockPod1(podLabels)
        cli := fake.NewClientBuilder().WithRuntimeObjects(service, pod).Build()
-       resultPod, resultService, err := 
findPodAndReferenceServiceByPodLabels(context.TODO(), cli, namespace1, pod1)
+       resultPod, referenceServices, err := 
findPodAndReferenceServices(context.TODO(), cli, namespace1, pod1Name)
        assert.NoError(t, err)
        assert.Equal(t, pod, resultPod)
-       assert.Equal(t, service, resultService)
+       assert.Len(t, referenceServices.Items, 1)
+       assert.Equal(t, *service, referenceServices.Items[0])
 }
 
-func Test_findPodAndReferenceServiceByPodLabelsWithoutReferenceService(t 
*testing.T) {
+func Test_findPodAndReferenceServicesWithoutReferenceService(t *testing.T) {
        podLabels := &map[string]string{
                label1: valueLabel1,
-               label2: valueLabel2,
        }
-       serviceLabels := &map[string]string{
+       selectorLabels := &map[string]string{
                label1: valueLabel1,
+               label2: valueLabel2,
        }
-       service := mockService1(serviceLabels)
+       service := mockService1(selectorLabels)
        pod := mockPod1(podLabels)
        cli := fake.NewClientBuilder().WithRuntimeObjects(service, pod).Build()
-       resultPod, resultService, err := 
findPodAndReferenceServiceByPodLabels(context.TODO(), cli, namespace1, pod1)
+       resultPod, referenceServices, err := 
findPodAndReferenceServices(context.TODO(), cli, namespace1, pod1Name)
        assert.NoError(t, err)
        assert.Equal(t, pod, resultPod)
-       assert.Nil(t, resultService)
+       assert.Nil(t, referenceServices)
 }
 
-func Test_findPodAndReferenceServiceByPodLabelsNotFound(t *testing.T) {
+func Test_findPodAndReferenceServicesNotFound(t *testing.T) {
        cli := fake.NewClientBuilder().Build()
-       resultPod, resultService, err := 
findPodAndReferenceServiceByPodLabels(context.TODO(), cli, namespace1, pod1)
-       assert.ErrorContains(t, err, "\"pod1\" not found")
+       resultPod, resultService, err := 
findPodAndReferenceServices(context.TODO(), cli, namespace1, pod1Name)
+       assert.ErrorContains(t, err, "\"pod1Name\" not found")
        assert.Nil(t, resultPod)
        assert.Nil(t, resultService)
 }
@@ -129,7 +202,7 @@ func Test_findPodAndReferenceServiceByPodLabelsNotFound(t 
*testing.T) {
 func Test_findDeployment(t *testing.T) {
        deployment := mockDeployment1(nil)
        cli := fake.NewClientBuilder().WithRuntimeObjects(deployment).Build()
-       result, err := findDeployment(context.TODO(), cli, namespace1, 
deployment1)
+       result, err := findDeployment(context.TODO(), cli, namespace1, 
deployment1Name)
 
        assert.NoError(t, err)
        assert.Equal(t, deployment, result)
@@ -137,14 +210,14 @@ func Test_findDeployment(t *testing.T) {
 
 func Test_findDeploymentNotFound(t *testing.T) {
        cli := fake.NewClientBuilder().Build()
-       _, err := findDeployment(context.TODO(), cli, namespace1, deployment1)
-       assert.ErrorContains(t, err, "\"deployment1\" not found")
+       _, err := findDeployment(context.TODO(), cli, namespace1, 
deployment1Name)
+       assert.ErrorContains(t, err, "\"deployment1Name\" not found")
 }
 
 func Test_findStatefulSet(t *testing.T) {
        statefulSet := mockStatefulSet1()
        cli := fake.NewClientBuilder().WithRuntimeObjects(statefulSet).Build()
-       result, err := findStatefulSet(context.TODO(), cli, namespace1, 
statefulSet1)
+       result, err := findStatefulSet(context.TODO(), cli, namespace1, 
statefulSet1Name)
 
        assert.NoError(t, err)
        assert.Equal(t, statefulSet, result)
@@ -152,14 +225,14 @@ func Test_findStatefulSet(t *testing.T) {
 
 func Test_findStatefulSetNotFound(t *testing.T) {
        cli := fake.NewClientBuilder().Build()
-       _, err := findStatefulSet(context.TODO(), cli, namespace1, statefulSet1)
-       assert.ErrorContains(t, err, "\"statefulSet1\" not found")
+       _, err := findStatefulSet(context.TODO(), cli, namespace1, 
statefulSet1Name)
+       assert.ErrorContains(t, err, "\"statefulSet1Name\" not found")
 }
 
 func Test_findIngress(t *testing.T) {
        ingress := mockIngress1()
        cli := fake.NewClientBuilder().WithRuntimeObjects(ingress).Build()
-       result, err := findIngress(context.TODO(), cli, namespace1, ingress1)
+       result, err := findIngress(context.TODO(), cli, namespace1, 
ingress1Name)
 
        assert.NoError(t, err)
        assert.Equal(t, ingress, result)
@@ -167,59 +240,42 @@ func Test_findIngress(t *testing.T) {
 
 func Test_findIngressNotFound(t *testing.T) {
        cli := fake.NewClientBuilder().Build()
-       _, err := findIngress(context.TODO(), cli, namespace1, ingress1)
-       assert.ErrorContains(t, err, "\"ingress1\" not found")
+       _, err := findIngress(context.TODO(), cli, namespace1, ingress1Name)
+       assert.ErrorContains(t, err, "\"ingress1Name\" not found")
 }
 
-func mockService1(labels *map[string]string) *corev1.Service {
-       return mockService(namespace1, service1, labels)
+func mockService1(selectorLabels *map[string]string) *corev1.Service {
+       return mockService(namespace1, service1Name, nil, selectorLabels)
+}
+
+func mockService2(selectorLabels *map[string]string) *corev1.Service {
+       return mockService(namespace1, service2Name, nil, selectorLabels)
+}
+
+func mockService3(selectorLabels *map[string]string) *corev1.Service {
+       return mockService(namespace1, service3Name, nil, selectorLabels)
 }
 
 func mockPod1(labels *map[string]string) *corev1.Pod {
-       return mockPod(namespace1, pod1, labels)
+       return mockPod(namespace1, pod1Name, labels)
+}
+
+func mockPod2(labels *map[string]string) *corev1.Pod {
+       return mockPod(namespace1, pod2Name, labels)
+}
+
+func mockPod3(labels *map[string]string) *corev1.Pod {
+       return mockPod(namespace1, pod3Name, labels)
 }
 
 func mockDeployment1(labels *map[string]string) *appsv1.Deployment {
-       deployment := &appsv1.Deployment{
-               TypeMeta: metav1.TypeMeta{
-                       Kind:       "Deployment",
-                       APIVersion: "apps/v1",
-               },
-               ObjectMeta: metav1.ObjectMeta{
-                       Namespace: namespace1,
-                       Name:      deployment1,
-               },
-       }
-       if labels != nil {
-               deployment.ObjectMeta.Labels = *labels
-       }
-       return deployment
+       return mockDeployment(namespace1, deployment1Name, labels, nil)
 }
 
 func mockStatefulSet1() *appsv1.StatefulSet {
-       statefulSet := &appsv1.StatefulSet{
-               TypeMeta: metav1.TypeMeta{
-                       Kind:       "StatefulSet",
-                       APIVersion: "apps/v1",
-               },
-               ObjectMeta: metav1.ObjectMeta{
-                       Namespace: namespace1,
-                       Name:      statefulSet1,
-               },
-       }
-       return statefulSet
+       return mockStatefulSet(namespace1, statefulSet1Name, nil, nil)
 }
 
 func mockIngress1() *networkingV1.Ingress {
-       ingress := &networkingV1.Ingress{
-               TypeMeta: metav1.TypeMeta{
-                       Kind:       "Ingress",
-                       APIVersion: "networking.k8s.io/v1",
-               },
-               ObjectMeta: metav1.ObjectMeta{
-                       Namespace: namespace1,
-                       Name:      ingress1,
-               },
-       }
-       return ingress
+       return mockIngress(namespace1, ingress1Name)
 }
diff --git a/controllers/discovery/test_utils.go 
b/controllers/discovery/test_utils.go
index d56bfb05..b84b932b 100644
--- a/controllers/discovery/test_utils.go
+++ b/controllers/discovery/test_utils.go
@@ -1,45 +1,63 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
 import (
+       "fmt"
+
+       appsv1 "k8s.io/api/apps/v1"
        corev1 "k8s.io/api/core/v1"
+       networkingV1 "k8s.io/api/networking/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/types"
 )
 
 const (
-       namespace1   = "namespace1"
-       service1     = "service1"
-       deployment1  = "deployment1"
-       statefulSet1 = "statefulSet1"
-       pod1         = "pod1"
-       container1   = "container1"
-       container2   = "container2"
-       ingress1     = "ingress1"
-       label1       = "label1"
-       valueLabel1  = "valueLabel1"
-       label2       = "label2"
-       valueLabel2  = "valueLabel2"
-
-       customPortName = "my-custom-port"
-       defaultHttp    = 80
-       defaultHttps   = 443
-       tcp            = "TCP"
+       namespace1       = "namespace1"
+       service1Name     = "service1Name"
+       service2Name     = "service2Name"
+       service3Name     = "service3Name"
+       deployment1Name  = "deployment1Name"
+       statefulSet1Name = "statefulSet1Name"
+       pod1Name         = "pod1Name"
+       pod2Name         = "pod2Name"
+       pod3Name         = "pod3Name"
+       container1Name   = "container1Name"
+       container2Name   = "container2Name"
+       ingress1Name     = "ingress1Name"
+       label1           = "label1"
+       valueLabel1      = "valueLabel1"
+       label2           = "label2"
+       valueLabel2      = "valueLabel2"
+       label3           = "label3"
+       valueLabel3      = "valueLabel3"
+       customPortName   = "my-custom-port"
+       tcp              = "TCP"
+       uidOwner1        = "uidOwner1"
+       uidOwner2        = "uidOwner2"
+       replicaSet1Name  = "replicaSet1Name"
+       replicaSet2Name  = "replicaSet2Name"
+       replicaSet3Name  = "replicaSet3Name"
 )
 
-func mockService(namespace string, name string, labels *map[string]string) 
*corev1.Service {
+func mockService(namespace string, name string, labels *map[string]string, 
selectorLabels *map[string]string) *corev1.Service {
        service := &corev1.Service{
                TypeMeta: metav1.TypeMeta{
                        Kind:       "Service",
@@ -53,11 +71,14 @@ func mockService(namespace string, name string, labels 
*map[string]string) *core
        if labels != nil {
                service.ObjectMeta.Labels = *labels
        }
+       if selectorLabels != nil {
+               service.Spec.Selector = *selectorLabels
+       }
        return service
 }
 
 func mockServiceWithPorts(namespace string, name string, ports 
...corev1.ServicePort) *corev1.Service {
-       service := mockService(namespace, name, &map[string]string{})
+       service := mockService(namespace, name, &map[string]string{}, nil)
        service.Spec.Ports = ports
        return service
 }
@@ -108,3 +129,75 @@ func mockContainerPort(name string, protocol string, port 
int32) corev1.Containe
                Protocol:      corev1.Protocol(protocol),
        }
 }
+
+func mockReplicaSet(namespace string, name string, ownerReferenceUID string) 
*appsv1.ReplicaSet {
+       replicaSet := &appsv1.ReplicaSet{
+               TypeMeta: metav1.TypeMeta{
+                       Kind:       "ReplicaSet",
+                       APIVersion: "apps/v1",
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace:       namespace,
+                       Name:            name,
+                       OwnerReferences: []metav1.OwnerReference{{UID: 
types.UID(ownerReferenceUID)}},
+                       UID:             
types.UID(fmt.Sprintf("%s-%s-mock-replicaset-uid", namespace, name)),
+               },
+       }
+       return replicaSet
+}
+
+func mockDeployment(namespace string, name string, labels *map[string]string, 
selector *map[string]string) *appsv1.Deployment {
+       deployment := &appsv1.Deployment{
+               TypeMeta: metav1.TypeMeta{
+                       Kind:       "Deployment",
+                       APIVersion: "apps/v1",
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: namespace,
+                       Name:      name,
+                       UID:       
types.UID(fmt.Sprintf("%s-%s-mock-deployment-uid", namespace, name)),
+               },
+       }
+       if labels != nil {
+               deployment.ObjectMeta.Labels = *labels
+       }
+       if selector != nil {
+               deployment.Spec.Selector = &metav1.LabelSelector{MatchLabels: 
*selector}
+       }
+       return deployment
+}
+
+func mockStatefulSet(namespace string, name string, labels *map[string]string, 
selector *map[string]string) *appsv1.StatefulSet {
+       statefulSet := &appsv1.StatefulSet{
+               TypeMeta: metav1.TypeMeta{
+                       Kind:       "StatefulSet",
+                       APIVersion: "apps/v1",
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: namespace,
+                       Name:      name,
+                       UID:       
types.UID(fmt.Sprintf("%s-%s-mock-statefulset-uid", namespace, name)),
+               },
+       }
+       if labels != nil {
+               statefulSet.ObjectMeta.Labels = *labels
+       }
+       if selector != nil {
+               statefulSet.Spec.Selector = &metav1.LabelSelector{MatchLabels: 
*selector}
+       }
+       return statefulSet
+}
+
+func mockIngress(namespace string, name string) *networkingV1.Ingress {
+       ingress := &networkingV1.Ingress{
+               TypeMeta: metav1.TypeMeta{
+                       Kind:       "Ingress",
+                       APIVersion: "networking.k8s.io/v1",
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: namespace,
+                       Name:      name,
+               },
+       }
+       return ingress
+}
diff --git a/controllers/discovery/uri_parser.go 
b/controllers/discovery/uri_parser.go
index 4f7425c6..1096780a 100644
--- a/controllers/discovery/uri_parser.go
+++ b/controllers/discovery/uri_parser.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -74,14 +79,13 @@ func parseKubernetesUri(uri string, schemaAndGroup string, 
after string) (*Resou
                if queryParams, err = parseQueryParams(uri, split[1]); err != 
nil {
                        return nil, err
                }
-
                gvk, _ := parseGVK(schemaAndGroup)
                return &ResourceUri{
-                       Scheme:       KubernetesScheme,
-                       GVK:          *gvk,
-                       Namespace:    namespace,
-                       Name:         name,
-                       CustomLabels: queryParams,
+                       Scheme:      KubernetesScheme,
+                       GVK:         *gvk,
+                       Namespace:   namespace,
+                       Name:        name,
+                       QueryParams: queryParams,
                }, nil
 
        } else {
diff --git a/controllers/discovery/uri_parser_test.go 
b/controllers/discovery/uri_parser_test.go
index 32cb158b..9b72d1d5 100644
--- a/controllers/discovery/uri_parser_test.go
+++ b/controllers/discovery/uri_parser_test.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -40,7 +45,7 @@ var KubernetesServicesTestValues = map[string]*ResourceUri{
                Kind("services").
                Version("v1").
                Name("my-service").
-               WithLabel("label-a", "value-a").Build(),
+               WithQueryParam("label-a", "value-a").Build(),
 
        "kubernetes:services.v1/my-service?label-a=value-a&": nil,
 
@@ -52,8 +57,8 @@ var KubernetesServicesTestValues = map[string]*ResourceUri{
                Kind("services").
                Version("v1").
                Name("my-service").
-               WithLabel("label-a", "value-a").
-               WithLabel("label-b", "value-b").Build(),
+               WithQueryParam("label-a", "value-a").
+               WithQueryParam("label-b", "value-b").Build(),
 
        "kubernetes:services.v1/my-namespace/": nil,
 
@@ -77,7 +82,7 @@ var KubernetesServicesTestValues = map[string]*ResourceUri{
                Version("v1").
                Namespace("my-namespace").
                Name("my-service").
-               WithLabel("label-a", "value-a").Build(),
+               WithQueryParam("label-a", "value-a").Build(),
 
        "kubernetes:services.v1/my-namespace/my-service?label-a=value-a&": nil,
 
@@ -85,13 +90,14 @@ var KubernetesServicesTestValues = map[string]*ResourceUri{
 
        
"kubernetes:services.v1/my-namespace/my-service?label-a=value-a&label-b=": nil,
 
-       
"kubernetes:services.v1/my-namespace/my-service?label-a=value-a&label-b=value-b":
 NewResourceUriBuilder(KubernetesScheme).
+       
"kubernetes:services.v1/my-namespace/my-service?label-a=value-a&label-b=value-b&port=custom-port-value":
 NewResourceUriBuilder(KubernetesScheme).
                Kind("services").
                Version("v1").
                Namespace("my-namespace").
                Name("my-service").
-               WithLabel("label-a", "value-a").
-               WithLabel("label-b", "value-b").Build(),
+               WithQueryParam("label-a", "value-a").
+               WithQueryParam("label-b", "value-b").
+               WithPort("custom-port-value").Build(),
 }
 
 func TestParseKubernetesServicesURI(t *testing.T) {
@@ -122,9 +128,9 @@ func assertEquals(t *testing.T, uri *ResourceUri, 
expectedUri *ResourceUri) {
        assert.Equal(t, uri.GVK.Group, expectedUri.GVK.Group)
        assert.Equal(t, uri.GVK.Version, expectedUri.GVK.Version)
        assert.Equal(t, uri.GVK.Kind, expectedUri.GVK.Kind)
-       assert.Equal(t, len(uri.CustomLabels), len(expectedUri.CustomLabels))
-       for k, v := range uri.CustomLabels {
-               assert.True(t, len(expectedUri.CustomLabels[k]) > 0, "label %s 
is not present in expectedUri: %s", k, expectedUri.String())
-               assert.Equal(t, v, expectedUri.CustomLabels[k], "value for 
label %s in expectedUri should be %s, but is %s", k, v, 
expectedUri.CustomLabels[k])
+       assert.Equal(t, len(uri.QueryParams), len(expectedUri.QueryParams))
+       for k, v := range uri.QueryParams {
+               assert.True(t, len(expectedUri.QueryParams[k]) > 0, "label %s 
is not present in expectedUri: %s", k, expectedUri.String())
+               assert.Equal(t, v, expectedUri.QueryParams[k], "value for label 
%s in expectedUri should be %s, but is %s", k, v, expectedUri.QueryParams[k])
        }
 }
diff --git a/controllers/discovery/uri_utils.go 
b/controllers/discovery/uri_utils.go
index 4c1de70e..a3092d5c 100644
--- a/controllers/discovery/uri_utils.go
+++ b/controllers/discovery/uri_utils.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -32,7 +37,7 @@ func resolveServiceUri(service *corev1.Service, customPort 
string, outputFormat
        case corev1.ServiceTypeExternalName:
                // ExternalName may not work properly with SSL:
                // 
https://kubernetes.io/docs/concepts/services-networking/service/#externalname
-               protocol = httpProtocolName
+               protocol = httpProtocol
                host = service.Spec.ExternalName
                port = 80
        case corev1.ServiceTypeClusterIP:
@@ -60,9 +65,9 @@ func resolveServiceUri(service *corev1.Service, customPort 
string, outputFormat
 func resolveClusterIPOrTypeNodeServiceUriParams(service *corev1.Service, 
customPort string) (protocol string, host string, port int) {
        servicePort := findBestSuitedServicePort(service, customPort)
        if isSecureServicePort(servicePort) {
-               protocol = httpsProtocolName
+               protocol = httpsProtocol
        } else {
-               protocol = httpProtocolName
+               protocol = httpProtocol
        }
        host = service.Spec.ClusterIP
        port = int(servicePort.Port)
@@ -83,9 +88,9 @@ func resolvePodUri(pod *corev1.Pod, customContainer string, 
customPort string, o
                if containerPort := findBestSuitedContainerPort(container, 
customPort); containerPort == nil {
                        return "", fmt.Errorf("no container port was found for 
pod: %s in namespace: %s", pod.Name, pod.Namespace)
                } else {
-                       protocol := httpProtocolName
+                       protocol := httpProtocol
                        if isSecure := isSecureContainerPort(containerPort); 
isSecure {
-                               protocol = httpsProtocolName
+                               protocol = httpsProtocol
                        }
                        if outputFormat == KubernetesDNSAddress {
                                return buildKubernetesPodDNSUri(protocol, 
pod.Namespace, podIp, int(containerPort.ContainerPort)), nil
diff --git a/controllers/discovery/uri_utils_test.go 
b/controllers/discovery/uri_utils_test.go
index 6c5fa703..3d296114 100644
--- a/controllers/discovery/uri_utils_test.go
+++ b/controllers/discovery/uri_utils_test.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package discovery
 
@@ -22,35 +27,35 @@ import (
 )
 
 func Test_resolveServiceUriClusterIPServiceDNSMode(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort(httpProtocolName, tcp, defaultHttp))
-       doTestResolveServiceUri(t, service, corev1.ServiceTypeClusterIP, 
KubernetesDNSAddress, "http://service1.namespace1.svc:80";)
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
+       doTestResolveServiceUri(t, service, corev1.ServiceTypeClusterIP, 
KubernetesDNSAddress, "http://service1Name.namespace1.svc:80";)
 }
 
 func Test_resolveServiceUriClusterIPServiceIPAddressMode(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort(httpProtocolName, tcp, defaultHttp))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
        service.Spec.ClusterIP = "10.1.15.16"
        doTestResolveServiceUri(t, service, corev1.ServiceTypeClusterIP, 
KubernetesIPAddress, "http://10.1.15.16:80";)
 }
 
 func Test_resolveServiceUriNodeTypeServiceDNSMode(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort(httpProtocolName, tcp, defaultHttp))
-       doTestResolveServiceUri(t, service, corev1.ServiceTypeNodePort, 
KubernetesDNSAddress, "http://service1.namespace1.svc:80";)
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
+       doTestResolveServiceUri(t, service, corev1.ServiceTypeNodePort, 
KubernetesDNSAddress, "http://service1Name.namespace1.svc:80";)
 }
 
 func Test_resolveServiceUriNodeTypeServiceIPAddressMode(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort(httpProtocolName, tcp, defaultHttp))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
        service.Spec.ClusterIP = "10.1.15.16"
        doTestResolveServiceUri(t, service, corev1.ServiceTypeNodePort, 
KubernetesIPAddress, "http://10.1.15.16:80";)
 }
 
 func Test_resolveServiceUriExternalNameServiceDNSMode(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort(httpProtocolName, tcp, defaultHttp))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
        service.Spec.ExternalName = "external.service.com"
        doTestResolveServiceUri(t, service, corev1.ServiceTypeExternalName, 
KubernetesIPAddress, "http://external.service.com:80";)
 }
 
 func Test_resolveServiceUriExternalNameServiceIPAddressMode(t *testing.T) {
-       service := mockServiceWithPorts(namespace1, service1, 
mockServicePort(httpProtocolName, tcp, defaultHttp))
+       service := mockServiceWithPorts(namespace1, service1Name, 
mockServicePort(httpProtocol, tcp, defaultHttpPort))
        service.Spec.ExternalName = "external.service.com"
        doTestResolveServiceUri(t, service, corev1.ServiceTypeExternalName, 
KubernetesIPAddress, "http://external.service.com:80";)
 }
@@ -63,40 +68,40 @@ func doTestResolveServiceUri(t *testing.T, service 
*corev1.Service, serviceType
 }
 
 func Test_resolvePodUriDNSMode(t *testing.T) {
-       pod := mockPodWithContainers(namespace1, pod1,
-               *mockContainerWithPorts(container1, 
mockContainerPort(httpProtocolName, tcp, defaultHttp)),
-               *mockContainerWithPorts(container2, 
mockContainerPort(httpsProtocolName, tcp, defaultHttps)))
+       pod := mockPodWithContainers(namespace1, pod1Name,
+               *mockContainerWithPorts(container1Name, 
mockContainerPort(httpProtocol, tcp, defaultHttpPort)),
+               *mockContainerWithPorts(container2Name, 
mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)))
        pod.Status.PodIP = "10.1.15.16"
        doTestResolvePodUri(t, pod, "", "", KubernetesDNSAddress, 
"http://10-1-15-16.namespace1.pod:80";)
 }
 
 func Test_resolvePodUriIPAddressMode(t *testing.T) {
-       pod := mockPodWithContainers(namespace1, pod1,
-               *mockContainerWithPorts(container1, 
mockContainerPort(httpProtocolName, tcp, defaultHttp)),
-               *mockContainerWithPorts(container2, 
mockContainerPort(httpsProtocolName, tcp, defaultHttps)))
+       pod := mockPodWithContainers(namespace1, pod1Name,
+               *mockContainerWithPorts(container1Name, 
mockContainerPort(httpProtocol, tcp, defaultHttpPort)),
+               *mockContainerWithPorts(container2Name, 
mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)))
        pod.Status.PodIP = "10.1.15.17"
        doTestResolvePodUri(t, pod, "", "", KubernetesIPAddress, 
"http://10.1.15.17:80";)
 }
 
 func Test_resolvePodUriByCustomContainerDNSMode(t *testing.T) {
-       pod := mockPodWithContainers(namespace1, pod1,
-               *mockContainerWithPorts(container1, 
mockContainerPort(httpsProtocolName, tcp, defaultHttps)),
-               *mockContainerWithPorts("custom-container", 
mockContainerPort(httpProtocolName, tcp, defaultHttp)))
+       pod := mockPodWithContainers(namespace1, pod1Name,
+               *mockContainerWithPorts(container1Name, 
mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)),
+               *mockContainerWithPorts("custom-container", 
mockContainerPort(httpProtocol, tcp, defaultHttpPort)))
        pod.Status.PodIP = "10.1.15.16"
        doTestResolvePodUri(t, pod, "custom-container", "", 
KubernetesDNSAddress, "http://10-1-15-16.namespace1.pod:80";)
 }
 
 func Test_resolvePodUriByCustomContainerIPAddressMode(t *testing.T) {
-       pod := mockPodWithContainers(namespace1, pod1,
-               *mockContainerWithPorts(container1, 
mockContainerPort(httpsProtocolName, tcp, defaultHttps)),
-               *mockContainerWithPorts("custom-container", 
mockContainerPort(httpProtocolName, tcp, defaultHttp)))
+       pod := mockPodWithContainers(namespace1, pod1Name,
+               *mockContainerWithPorts(container1Name, 
mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)),
+               *mockContainerWithPorts("custom-container", 
mockContainerPort(httpProtocol, tcp, defaultHttpPort)))
        pod.Status.PodIP = "10.1.15.17"
        doTestResolvePodUri(t, pod, "custom-container", "", 
KubernetesIPAddress, "http://10.1.15.17:80";)
 }
 
 func Test_resolvePodUriByCustomContainerAndCustomPortDNSMode(t *testing.T) {
-       pod := mockPodWithContainers(namespace1, pod1,
-               *mockContainerWithPorts(container1, 
mockContainerPort(httpsProtocolName, tcp, defaultHttps)),
+       pod := mockPodWithContainers(namespace1, pod1Name,
+               *mockContainerWithPorts(container1Name, 
mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)),
                *mockContainerWithPorts("custom-container",
                        mockContainerPort("not-wanted", tcp, 8008),
                        mockContainerPort("custom-port", tcp, 8181)))
@@ -105,8 +110,8 @@ func 
Test_resolvePodUriByCustomContainerAndCustomPortDNSMode(t *testing.T) {
 }
 
 func Test_resolvePodUriByCustomContainerAndCustomPortIPAddressMode(t 
*testing.T) {
-       pod := mockPodWithContainers(namespace1, pod1,
-               *mockContainerWithPorts(container1, 
mockContainerPort(httpsProtocolName, tcp, defaultHttps)),
+       pod := mockPodWithContainers(namespace1, pod1Name,
+               *mockContainerWithPorts(container1Name, 
mockContainerPort(httpsProtocol, tcp, defaultHttpsPort)),
                *mockContainerWithPorts("custom-container",
                        mockContainerPort("not-wanted", tcp, 8008),
                        mockContainerPort("custom-port", tcp, 8181)))
@@ -125,9 +130,9 @@ func Test_buildURI(t *testing.T) {
 }
 
 func Test_buildKubernetesServiceDNSUri(t *testing.T) {
-       assert.Equal(t, "http://service1.namespace1.svc:8383";, 
buildKubernetesServiceDNSUri("http", namespace1, service1, 8383))
+       assert.Equal(t, "http://service1Name.namespace1.svc:8383";, 
buildKubernetesServiceDNSUri("http", namespace1, service1Name, 8383))
 }
 
 func Test_buildKubernetesPodDNSUri(t *testing.T) {
-       assert.Equal(t, "http://pod1.namespace1.pod:8484";, 
buildKubernetesPodDNSUri("http", namespace1, pod1, 8484))
+       assert.Equal(t, "http://pod1Name.namespace1.pod:8484";, 
buildKubernetesPodDNSUri("http", namespace1, pod1Name, 8484))
 }
diff --git a/controllers/profiles/common/app_properties.go 
b/controllers/profiles/common/app_properties.go
index f97e9934..9564d160 100644
--- a/controllers/profiles/common/app_properties.go
+++ b/controllers/profiles/common/app_properties.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package common
 
diff --git a/controllers/profiles/common/app_properties_test.go 
b/controllers/profiles/common/app_properties_test.go
index f3d46f07..8fae160d 100644
--- a/controllers/profiles/common/app_properties_test.go
+++ b/controllers/profiles/common/app_properties_test.go
@@ -1,16 +1,21 @@
-// Copyright 2023 Red Hat, Inc. and/or its affiliates
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
 package common
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to