diff --git a/operators/config/all-in-one.yaml b/operators/config/all-in-one.yaml index 77a361cbd1..261754000f 100644 --- a/operators/config/all-in-one.yaml +++ b/operators/config/all-in-one.yaml @@ -58,29 +58,12 @@ spec: description: Service is a template for the Kubernetes Service properties: metadata: - description: Metadata is metadata for the HTTP Service. - properties: - annotations: - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations' - type: object + description: ObjectMeta is metadata for the service. The name + and namespace provided here is managed by ECK and will be + ignored. type: object spec: - description: Spec contains user-provided settings for the HTTP - Service. - properties: - type: - description: 'Type determines which service type to use - for this workload. The options are: `ClusterIP|LoadBalancer|NodePort`. - Defaults to ClusterIP.' - enum: - - ClusterIP - - LoadBalancer - - NodePort - type: string + description: Spec defines the behavior of the service. type: object type: object tls: @@ -263,29 +246,12 @@ spec: description: Service is a template for the Kubernetes Service properties: metadata: - description: Metadata is metadata for the HTTP Service. - properties: - annotations: - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations' - type: object + description: ObjectMeta is metadata for the service. The name + and namespace provided here is managed by ECK and will be + ignored. type: object spec: - description: Spec contains user-provided settings for the HTTP - Service. - properties: - type: - description: 'Type determines which service type to use - for this workload. The options are: `ClusterIP|LoadBalancer|NodePort`. - Defaults to ClusterIP.' - enum: - - ClusterIP - - LoadBalancer - - NodePort - type: string + description: Spec defines the behavior of the service. type: object type: object tls: @@ -864,29 +830,12 @@ spec: description: Service is a template for the Kubernetes Service properties: metadata: - description: Metadata is metadata for the HTTP Service. - properties: - annotations: - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations' - type: object + description: ObjectMeta is metadata for the service. The name + and namespace provided here is managed by ECK and will be + ignored. type: object spec: - description: Spec contains user-provided settings for the HTTP - Service. - properties: - type: - description: 'Type determines which service type to use - for this workload. The options are: `ClusterIP|LoadBalancer|NodePort`. - Defaults to ClusterIP.' - enum: - - ClusterIP - - LoadBalancer - - NodePort - type: string + description: Spec defines the behavior of the service. type: object type: object tls: diff --git a/operators/config/crds/apm_v1alpha1_apmserver.yaml b/operators/config/crds/apm_v1alpha1_apmserver.yaml index 4e36fda111..5765d02805 100644 --- a/operators/config/crds/apm_v1alpha1_apmserver.yaml +++ b/operators/config/crds/apm_v1alpha1_apmserver.yaml @@ -58,29 +58,12 @@ spec: description: Service is a template for the Kubernetes Service properties: metadata: - description: Metadata is metadata for the HTTP Service. - properties: - annotations: - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations' - type: object + description: ObjectMeta is metadata for the service. The name + and namespace provided here is managed by ECK and will be + ignored. type: object spec: - description: Spec contains user-provided settings for the HTTP - Service. - properties: - type: - description: 'Type determines which service type to use - for this workload. The options are: `ClusterIP|LoadBalancer|NodePort`. - Defaults to ClusterIP.' - enum: - - ClusterIP - - LoadBalancer - - NodePort - type: string + description: Spec defines the behavior of the service. type: object type: object tls: diff --git a/operators/config/crds/elasticsearch_v1alpha1_elasticsearch.yaml b/operators/config/crds/elasticsearch_v1alpha1_elasticsearch.yaml index b6b03e06cd..8a89f936ec 100644 --- a/operators/config/crds/elasticsearch_v1alpha1_elasticsearch.yaml +++ b/operators/config/crds/elasticsearch_v1alpha1_elasticsearch.yaml @@ -63,29 +63,12 @@ spec: description: Service is a template for the Kubernetes Service properties: metadata: - description: Metadata is metadata for the HTTP Service. - properties: - annotations: - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations' - type: object + description: ObjectMeta is metadata for the service. The name + and namespace provided here is managed by ECK and will be + ignored. type: object spec: - description: Spec contains user-provided settings for the HTTP - Service. - properties: - type: - description: 'Type determines which service type to use - for this workload. The options are: `ClusterIP|LoadBalancer|NodePort`. - Defaults to ClusterIP.' - enum: - - ClusterIP - - LoadBalancer - - NodePort - type: string + description: Spec defines the behavior of the service. type: object type: object tls: diff --git a/operators/config/crds/kibana_v1alpha1_kibana.yaml b/operators/config/crds/kibana_v1alpha1_kibana.yaml index e3f7e7c1a6..13a64f4b8f 100644 --- a/operators/config/crds/kibana_v1alpha1_kibana.yaml +++ b/operators/config/crds/kibana_v1alpha1_kibana.yaml @@ -104,29 +104,12 @@ spec: description: Service is a template for the Kubernetes Service properties: metadata: - description: Metadata is metadata for the HTTP Service. - properties: - annotations: - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations' - type: object + description: ObjectMeta is metadata for the service. The name + and namespace provided here is managed by ECK and will be + ignored. type: object spec: - description: Spec contains user-provided settings for the HTTP - Service. - properties: - type: - description: 'Type determines which service type to use - for this workload. The options are: `ClusterIP|LoadBalancer|NodePort`. - Defaults to ClusterIP.' - enum: - - ClusterIP - - LoadBalancer - - NodePort - type: string + description: Spec defines the behavior of the service. type: object type: object tls: diff --git a/operators/pkg/apis/common/v1alpha1/common.go b/operators/pkg/apis/common/v1alpha1/common.go index 16c9a38d91..be4c4cba0b 100644 --- a/operators/pkg/apis/common/v1alpha1/common.go +++ b/operators/pkg/apis/common/v1alpha1/common.go @@ -5,6 +5,8 @@ package v1alpha1 import ( + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) @@ -35,7 +37,7 @@ func (s ObjectSelector) NamespacedName() types.NamespacedName { // HTTPConfig configures a HTTP-based service. type HTTPConfig struct { // Service is a template for the Kubernetes Service - Service HTTPService `json:"service,omitempty"` + Service ServiceTemplate `json:"service,omitempty"` // TLS describe additional options to consider when generating HTTP TLS certificates. TLS TLSOptions `json:"tls,omitempty"` } @@ -57,29 +59,14 @@ type SubjectAlternativeName struct { IP string `json:"ip,omitempty"` } -// HTTPService contains defaults for a HTTP service. -type HTTPService struct { - // Metadata is metadata for the HTTP Service. - Metadata HTTPServiceObjectMeta `json:"metadata,omitempty"` - - // Spec contains user-provided settings for the HTTP Service. - Spec HTTPServiceSpec `json:"spec,omitempty"` -} - -// HTTPServiceObjectMeta is metadata for HTTP Service. -type HTTPServiceObjectMeta struct { - // Annotations is an unstructured key value map stored with a resource that may be - // set by external tools to store and retrieve arbitrary metadata. They are not - // queryable and should be preserved when modifying objects. - // More info: http://kubernetes.io/docs/user-guide/annotations +// ServiceTemplate describes the data a service should have when created from a template +type ServiceTemplate struct { + // ObjectMeta is metadata for the service. + // The name and namespace provided here is managed by ECK and will be ignored. // +optional - Annotations map[string]string `json:"annotations,omitempty"` -} + ObjectMeta metav1.ObjectMeta `json:"metadata,omitempty"` -// HTTPServiceSpec contains a subset of overridable settings for the HTTP Service -type HTTPServiceSpec struct { - // Type determines which service type to use for this workload. The - // options are: `ClusterIP|LoadBalancer|NodePort`. Defaults to ClusterIP. - // +kubebuilder:validation:Enum=ClusterIP,LoadBalancer,NodePort - Type string `json:"type,omitempty"` + // Spec defines the behavior of the service. + // +optional + Spec v1.ServiceSpec `json:"spec,omitempty"` } diff --git a/operators/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go b/operators/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go index 3dabd4ac57..a1f5a38d6b 100644 --- a/operators/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go +++ b/operators/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go @@ -64,63 +64,6 @@ func (in *HTTPConfig) DeepCopy() *HTTPConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPService) DeepCopyInto(out *HTTPService) { - *out = *in - in.Metadata.DeepCopyInto(&out.Metadata) - out.Spec = in.Spec - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPService. -func (in *HTTPService) DeepCopy() *HTTPService { - if in == nil { - return nil - } - out := new(HTTPService) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPServiceObjectMeta) DeepCopyInto(out *HTTPServiceObjectMeta) { - *out = *in - if in.Annotations != nil { - in, out := &in.Annotations, &out.Annotations - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPServiceObjectMeta. -func (in *HTTPServiceObjectMeta) DeepCopy() *HTTPServiceObjectMeta { - if in == nil { - return nil - } - out := new(HTTPServiceObjectMeta) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPServiceSpec) DeepCopyInto(out *HTTPServiceSpec) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPServiceSpec. -func (in *HTTPServiceSpec) DeepCopy() *HTTPServiceSpec { - if in == nil { - return nil - } - out := new(HTTPServiceSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectSelector) DeepCopyInto(out *ObjectSelector) { *out = *in @@ -190,6 +133,24 @@ func (in *SelfSignedCertificate) DeepCopy() *SelfSignedCertificate { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceTemplate) DeepCopyInto(out *ServiceTemplate) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceTemplate. +func (in *ServiceTemplate) DeepCopy() *ServiceTemplate { + if in == nil { + return nil + } + out := new(ServiceTemplate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SubjectAlternativeName) DeepCopyInto(out *SubjectAlternativeName) { *out = *in diff --git a/operators/pkg/controller/apmserver/services.go b/operators/pkg/controller/apmserver/services.go index 2337133eab..b3b9510223 100644 --- a/operators/pkg/controller/apmserver/services.go +++ b/operators/pkg/controller/apmserver/services.go @@ -5,34 +5,27 @@ package apmserver import ( - v1alpha1 "github.com/elastic/cloud-on-k8s/operators/pkg/apis/apm/v1alpha1" + "github.com/elastic/cloud-on-k8s/operators/pkg/apis/apm/v1alpha1" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/common" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func NewService(as v1alpha1.ApmServer) *corev1.Service { - var svc = corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: as.Namespace, - Name: PseudoNamespacedResourceName(as), - Labels: NewLabels(as.Name), - Annotations: as.Spec.HTTP.Service.Metadata.Annotations, - }, - Spec: corev1.ServiceSpec{ - Selector: NewLabels(as.Name), - Ports: []corev1.ServicePort{ - { - Protocol: corev1.ProtocolTCP, - Port: HTTPPort, - }, - }, - SessionAffinity: corev1.ServiceAffinityNone, - Type: common.GetServiceType(as.Spec.HTTP.Service.Spec.Type), - }, + svc := corev1.Service{ + ObjectMeta: as.Spec.HTTP.Service.ObjectMeta, + Spec: as.Spec.HTTP.Service.Spec, } - if svc.Spec.Type != corev1.ServiceTypeClusterIP { - svc.Spec.ExternalTrafficPolicy = corev1.ServiceExternalTrafficPolicyTypeCluster + + svc.ObjectMeta.Namespace = as.Namespace + svc.ObjectMeta.Name = PseudoNamespacedResourceName(as) + + labels := NewLabels(as.Name) + ports := []corev1.ServicePort{ + { + Protocol: corev1.ProtocolTCP, + Port: HTTPPort, + }, } - return &svc + + return common.SetServiceDefaults(&svc, labels, labels, ports) } diff --git a/operators/pkg/controller/common/service.go b/operators/pkg/controller/common/service.go index 8c3afb21d7..526ddbbbbf 100644 --- a/operators/pkg/controller/common/service.go +++ b/operators/pkg/controller/common/service.go @@ -5,28 +5,34 @@ package common import ( - corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" ) -const ( - // DefaultServiceType is used when the stack spec is empty or not valid. - DefaultServiceType = corev1.ServiceTypeClusterIP -) +// SetServiceDefaults updates the service with the provided defaults if they are not already set. +func SetServiceDefaults( + svc *v1.Service, + defaultLabels map[string]string, + defaultSelector map[string]string, + defaultPorts []v1.ServicePort, +) *v1.Service { + if svc.ObjectMeta.Labels == nil { + svc.ObjectMeta.Labels = defaultLabels + } else { + // add our labels, but don't overwrite user labels + for k, v := range defaultLabels { + if _, ok := svc.ObjectMeta.Labels[k]; !ok { + svc.ObjectMeta.Labels[k] = v + } + } + } -// GetServiceType obtains the service type from a string. -// There's no validation here since it is assumed to happen at the API level. -func GetServiceType(s string) corev1.ServiceType { - switch corev1.ServiceType(s) { - case corev1.ServiceTypeNodePort: - return corev1.ServiceTypeNodePort - case corev1.ServiceTypeLoadBalancer: - return corev1.ServiceTypeLoadBalancer - default: - return DefaultServiceType + if svc.Spec.Selector == nil { + svc.Spec.Selector = defaultSelector + } + + if svc.Spec.Ports == nil { + svc.Spec.Ports = defaultPorts } -} -// hasNodePort returns for a given service type, if the service ports have a NodePort or not. -func hasNodePort(svcType corev1.ServiceType) bool { - return svcType == corev1.ServiceTypeNodePort || svcType == corev1.ServiceTypeLoadBalancer + return svc } diff --git a/operators/pkg/controller/common/service_control.go b/operators/pkg/controller/common/service_control.go index 55fe84d289..19b1bb8c79 100644 --- a/operators/pkg/controller/common/service_control.go +++ b/operators/pkg/controller/common/service_control.go @@ -18,7 +18,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" ) -var log = logf.Log.WithName("stack-controller") +var log = logf.Log.WithName("common") func ReconcileService( c k8s.Client, @@ -64,3 +64,8 @@ func needsUpdate(expected *corev1.Service, reconciled *corev1.Service) bool { } return !reflect.DeepEqual(expected.Spec, reconciled.Spec) } + +// hasNodePort returns for a given service type, if the service ports have a NodePort or not. +func hasNodePort(svcType corev1.ServiceType) bool { + return svcType == corev1.ServiceTypeNodePort || svcType == corev1.ServiceTypeLoadBalancer +} diff --git a/operators/pkg/controller/common/service_test.go b/operators/pkg/controller/common/service_test.go index dd74d9e42f..ca743e7516 100644 --- a/operators/pkg/controller/common/service_test.go +++ b/operators/pkg/controller/common/service_test.go @@ -5,47 +5,102 @@ package common import ( - "reflect" "testing" - corev1 "k8s.io/api/core/v1" + "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" + v12 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func TestGetServiceType(t *testing.T) { +func TestSetServiceDefaults(t *testing.T) { + sampleSvc := v1.Service{ + ObjectMeta: v12.ObjectMeta{ + Labels: map[string]string{ + "foo": "bar", + }, + }, + Spec: v1.ServiceSpec{ + Selector: map[string]string{ + "foo": "bar", + }, + Ports: []v1.ServicePort{ + {Name: "foo"}, + }, + }, + } + + sampleSvcWith := func(setter func(svc *v1.Service)) *v1.Service { + svc := sampleSvc.DeepCopy() + setter(svc) + return svc + } + type args struct { - s string + svc *v1.Service + defaultLabels map[string]string + defaultSelector map[string]string + defaultPorts []v1.ServicePort } tests := []struct { name string args args - want corev1.ServiceType + want *v1.Service }{ { - name: "Empty Type means ClusterIP service type", - args: args{s: ""}, - want: corev1.ServiceTypeClusterIP, + name: "with empty defaults", + args: args{ + svc: sampleSvc.DeepCopy(), + }, + want: &sampleSvc, }, { - name: "Type with a correct value returns it", - args: args{s: "NodePort"}, - want: corev1.ServiceTypeNodePort, + name: "should not overwrite, but add labels", + args: args{ + svc: sampleSvc.DeepCopy(), + defaultLabels: map[string]string{ + // this should be ignored + "foo": "foo", + // this should be added + "bar": "baz", + }, + }, + want: sampleSvcWith(func(svc *v1.Service) { + svc.Labels["bar"] = "baz" + }), }, { - name: "Type with a correct value returns it", - args: args{s: "LoadBalancer"}, - want: corev1.ServiceTypeLoadBalancer, + name: "should use default selector", + args: args{ + svc: &v1.Service{}, + defaultSelector: map[string]string{"foo": "foo"}, + }, + want: &v1.Service{ + Spec: v1.ServiceSpec{ + Selector: map[string]string{"foo": "foo"}, + }, + }, }, { - name: "Type with a correct value returns it", - args: args{s: "ClusterIP"}, - want: corev1.ServiceTypeClusterIP, + name: "should use default ports", + args: args{ + svc: &v1.Service{}, + defaultPorts: []v1.ServicePort{ + {Name: "bar"}, + }, + }, + want: &v1.Service{ + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{ + {Name: "bar"}, + }, + }, + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := GetServiceType(tt.args.s); !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetServiceType() = %v, want %v", got, tt.want) - } + got := SetServiceDefaults(tt.args.svc, tt.args.defaultLabels, tt.args.defaultSelector, tt.args.defaultPorts) + assert.Equal(t, tt.want, got) }) } } diff --git a/operators/pkg/controller/elasticsearch/services/services.go b/operators/pkg/controller/elasticsearch/services/services.go index 11cb490b65..cf71c5b1f4 100644 --- a/operators/pkg/controller/elasticsearch/services/services.go +++ b/operators/pkg/controller/elasticsearch/services/services.go @@ -15,7 +15,6 @@ import ( "github.com/elastic/cloud-on-k8s/operators/pkg/utils/k8s" "github.com/elastic/cloud-on-k8s/operators/pkg/utils/stringsutil" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) @@ -38,30 +37,25 @@ func ExternalServiceURL(es v1alpha1.Elasticsearch) string { // It is used by users to perform requests against one of the cluster nodes. func NewExternalService(es v1alpha1.Elasticsearch) *corev1.Service { nsn := k8s.ExtractNamespacedName(&es) - var svc = corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: es.Namespace, - Name: ExternalServiceName(es.Name), - Labels: label.NewLabels(nsn), - Annotations: es.Spec.HTTP.Service.Metadata.Annotations, - }, - Spec: corev1.ServiceSpec{ - Selector: label.NewLabels(nsn), - Ports: []corev1.ServicePort{ - { - Name: "https", - Protocol: corev1.ProtocolTCP, - Port: network.HTTPPort, - }, - }, - SessionAffinity: corev1.ServiceAffinityNone, - Type: common.GetServiceType(es.Spec.HTTP.Service.Spec.Type), - }, + + svc := corev1.Service{ + ObjectMeta: es.Spec.HTTP.Service.ObjectMeta, + Spec: es.Spec.HTTP.Service.Spec, } - if svc.Spec.Type != corev1.ServiceTypeClusterIP { - svc.Spec.ExternalTrafficPolicy = corev1.ServiceExternalTrafficPolicyTypeCluster + + svc.ObjectMeta.Namespace = es.Namespace + svc.ObjectMeta.Name = ExternalServiceName(es.Name) + + labels := label.NewLabels(nsn) + ports := []corev1.ServicePort{ + { + Name: "https", + Protocol: corev1.ProtocolTCP, + Port: network.HTTPPort, + }, } - return &svc + + return common.SetServiceDefaults(&svc, labels, labels, ports) } // IsServiceReady checks if a service has one or more ready endpoints. diff --git a/operators/pkg/controller/kibana/services.go b/operators/pkg/controller/kibana/services.go index 4b886993e7..75c4fa1b94 100644 --- a/operators/pkg/controller/kibana/services.go +++ b/operators/pkg/controller/kibana/services.go @@ -11,32 +11,24 @@ import ( kbname "github.com/elastic/cloud-on-k8s/operators/pkg/controller/kibana/name" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/kibana/pod" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func NewService(kb kibanav1alpha1.Kibana) *corev1.Service { - var svc = corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: kb.Namespace, - Name: kbname.HTTPService(kb.Name), - Labels: label.NewLabels(kb.Name), - Annotations: kb.Spec.HTTP.Service.Metadata.Annotations, - }, - Spec: corev1.ServiceSpec{ - Selector: label.NewLabels(kb.Name), - Ports: []corev1.ServicePort{ - corev1.ServicePort{ - Protocol: corev1.ProtocolTCP, - Port: pod.HTTPPort, - }, - }, - SessionAffinity: corev1.ServiceAffinityNone, - // TODO: proper ingress forwarding - Type: common.GetServiceType(kb.Spec.HTTP.Service.Spec.Type), - }, + svc := corev1.Service{ + ObjectMeta: kb.Spec.HTTP.Service.ObjectMeta, + Spec: kb.Spec.HTTP.Service.Spec, } - if svc.Spec.Type != corev1.ServiceTypeClusterIP { - svc.Spec.ExternalTrafficPolicy = corev1.ServiceExternalTrafficPolicyTypeCluster + + svc.ObjectMeta.Namespace = kb.Namespace + svc.ObjectMeta.Name = kbname.HTTPService(kb.Name) + + labels := label.NewLabels(kb.Name) + ports := []corev1.ServicePort{ + { + Protocol: corev1.ProtocolTCP, + Port: pod.HTTPPort, + }, } - return &svc + + return common.SetServiceDefaults(&svc, labels, labels, ports) }