diff --git a/charts/spark-operator-chart/Chart.yaml b/charts/spark-operator-chart/Chart.yaml
index d41ef4b0e6..45fc7de437 100644
--- a/charts/spark-operator-chart/Chart.yaml
+++ b/charts/spark-operator-chart/Chart.yaml
@@ -1,7 +1,7 @@
apiVersion: v2
name: spark-operator
description: A Helm chart for Spark on Kubernetes operator
-version: 1.1.29
+version: 1.1.30
appVersion: v1beta2-1.3.8-3.1.1
keywords:
- spark
diff --git a/charts/spark-operator-chart/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml b/charts/spark-operator-chart/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml
index 20e1e00126..9f04e1dba3 100644
--- a/charts/spark-operator-chart/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml
+++ b/charts/spark-operator-chart/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml
@@ -3750,6 +3750,10 @@ spec:
additionalProperties:
type: string
type: object
+ serviceLabels:
+ additionalProperties:
+ type: string
+ type: object
ingressAnnotations:
additionalProperties:
type: string
diff --git a/charts/spark-operator-chart/crds/sparkoperator.k8s.io_sparkapplications.yaml b/charts/spark-operator-chart/crds/sparkoperator.k8s.io_sparkapplications.yaml
index 63e70b276e..fb71683a8b 100644
--- a/charts/spark-operator-chart/crds/sparkoperator.k8s.io_sparkapplications.yaml
+++ b/charts/spark-operator-chart/crds/sparkoperator.k8s.io_sparkapplications.yaml
@@ -3736,6 +3736,10 @@ spec:
additionalProperties:
type: string
type: object
+ serviceLabels:
+ additionalProperties:
+ type: string
+ type: object
ingressAnnotations:
additionalProperties:
type: string
diff --git a/docs/api-docs.md b/docs/api-docs.md
index 0403b6e587..fbedbb8fbd 100644
--- a/docs/api-docs.md
+++ b/docs/api-docs.md
@@ -3120,6 +3120,18 @@ map[string]string
+
ingressAnnotations
map[string]string
diff --git a/examples/spark-pi.yaml b/examples/spark-pi.yaml
index 1f7fafae43..986fe505ff 100644
--- a/examples/spark-pi.yaml
+++ b/examples/spark-pi.yaml
@@ -26,6 +26,9 @@ spec:
mainClass: org.apache.spark.examples.SparkPi
mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.12-3.1.1.jar"
sparkVersion: "3.1.1"
+ sparkUIOptions:
+ serviceLabels:
+ test-label/v1: 'true'
restartPolicy:
type: Never
volumes:
diff --git a/go.sum b/go.sum
index f4d211cf11..fc7758ecd8 100644
--- a/go.sum
+++ b/go.sum
@@ -2427,6 +2427,7 @@ k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/heapster v1.2.0-beta.1/go.mod h1:h1uhptVXMwC8xtZBYsPXKVi8fpdlYkTs6k949KozGrM=
+k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
diff --git a/manifest/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml b/manifest/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml
index 20e1e00126..9f04e1dba3 100644
--- a/manifest/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml
+++ b/manifest/crds/sparkoperator.k8s.io_scheduledsparkapplications.yaml
@@ -3750,6 +3750,10 @@ spec:
additionalProperties:
type: string
type: object
+ serviceLabels:
+ additionalProperties:
+ type: string
+ type: object
ingressAnnotations:
additionalProperties:
type: string
diff --git a/manifest/crds/sparkoperator.k8s.io_sparkapplications.yaml b/manifest/crds/sparkoperator.k8s.io_sparkapplications.yaml
index 63e70b276e..fb71683a8b 100644
--- a/manifest/crds/sparkoperator.k8s.io_sparkapplications.yaml
+++ b/manifest/crds/sparkoperator.k8s.io_sparkapplications.yaml
@@ -3736,6 +3736,10 @@ spec:
additionalProperties:
type: string
type: object
+ serviceLabels:
+ additionalProperties:
+ type: string
+ type: object
ingressAnnotations:
additionalProperties:
type: string
diff --git a/pkg/apis/sparkoperator.k8s.io/v1beta2/types.go b/pkg/apis/sparkoperator.k8s.io/v1beta2/types.go
index 2c89fe9482..616c2fc681 100644
--- a/pkg/apis/sparkoperator.k8s.io/v1beta2/types.go
+++ b/pkg/apis/sparkoperator.k8s.io/v1beta2/types.go
@@ -317,6 +317,9 @@ type SparkUIConfiguration struct {
// ServiceAnnotations is a map of key,value pairs of annotations that might be added to the service object.
// +optional
ServiceAnnotations map[string]string `json:"serviceAnnotations,omitempty"`
+ // ServiceLables is a map of key,value pairs of labels that might be added to the service object.
+ // +optional
+ ServiceLabels map[string]string `json:"serviceLabels,omitempty"`
// IngressAnnotations is a map of key,value pairs of annotations that might be added to the ingress object. i.e. specify nginx as ingress.class
// +optional
IngressAnnotations map[string]string `json:"ingressAnnotations,omitempty"`
diff --git a/pkg/controller/sparkapplication/sparkapp_util.go b/pkg/controller/sparkapplication/sparkapp_util.go
index ef41ade98c..30cce2c1c7 100644
--- a/pkg/controller/sparkapplication/sparkapp_util.go
+++ b/pkg/controller/sparkapplication/sparkapp_util.go
@@ -90,6 +90,16 @@ func getServiceAnnotations(app *v1beta2.SparkApplication) map[string]string {
return serviceAnnotations
}
+func getServiceLabels(app *v1beta2.SparkApplication) map[string]string {
+ serviceLabels := map[string]string{}
+ if app.Spec.SparkUIOptions != nil && app.Spec.SparkUIOptions.ServiceLabels != nil {
+ for key, value := range app.Spec.SparkUIOptions.ServiceLabels {
+ serviceLabels[key] = value
+ }
+ }
+ return serviceLabels
+}
+
func getIngressResourceAnnotations(app *v1beta2.SparkApplication) map[string]string {
ingressAnnotations := map[string]string{}
if app.Spec.SparkUIOptions != nil && app.Spec.SparkUIOptions.IngressAnnotations != nil {
diff --git a/pkg/controller/sparkapplication/sparkui.go b/pkg/controller/sparkapplication/sparkui.go
index c3c856aafa..533c3e953d 100644
--- a/pkg/controller/sparkapplication/sparkui.go
+++ b/pkg/controller/sparkapplication/sparkui.go
@@ -71,6 +71,7 @@ type SparkService struct {
targetPort intstr.IntOrString
serviceIP string
serviceAnnotations map[string]string
+ serviceLabels map[string]string
}
// SparkIngress encapsulates information about the driver UI ingress.
@@ -285,6 +286,12 @@ func createSparkUIService(
service.ObjectMeta.Annotations = serviceAnnotations
}
+ serviceLabels := getServiceLabels(app)
+ if len(serviceLabels) != 0 {
+ glog.Infof("Creating a service labels %s for the Spark UI: %v", service.Name, &serviceLabels)
+ service.ObjectMeta.Labels = serviceLabels
+ }
+
glog.Infof("Creating a service %s for the Spark UI for application %s", service.Name, app.Name)
service, err = kubeClient.CoreV1().Services(app.Namespace).Create(context.TODO(), service, metav1.CreateOptions{})
if err != nil {
@@ -299,6 +306,7 @@ func createSparkUIService(
targetPort: service.Spec.Ports[0].TargetPort,
serviceIP: service.Spec.ClusterIP,
serviceAnnotations: serviceAnnotations,
+ serviceLabels: serviceLabels,
}, nil
}
diff --git a/pkg/controller/sparkapplication/sparkui_test.go b/pkg/controller/sparkapplication/sparkui_test.go
index acec9b7afc..80d8e1075e 100644
--- a/pkg/controller/sparkapplication/sparkui_test.go
+++ b/pkg/controller/sparkapplication/sparkui_test.go
@@ -87,6 +87,10 @@ func TestCreateSparkUIService(t *testing.T) {
if !reflect.DeepEqual(serviceAnnotations, test.expectedService.serviceAnnotations) {
t.Errorf("%s: unexpected annotations wanted %s got %s", test.name, test.expectedService.serviceAnnotations, serviceAnnotations)
}
+ serviceLabels := service.ObjectMeta.Labels
+ if !reflect.DeepEqual(serviceLabels, test.expectedService.serviceLabels) {
+ t.Errorf("%s: unexpected labels wanted %s got %s", test.name, test.expectedService.serviceLabels, serviceLabels)
+ }
}
defaultPort := defaultSparkWebUIPort
defaultPortName := defaultSparkWebUIPortName
@@ -205,6 +209,25 @@ func TestCreateSparkUIService(t *testing.T) {
ExecutionAttempts: 1,
},
}
+ app8 := &v1beta2.SparkApplication{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "foo8",
+ Namespace: "default",
+ UID: "foo-123",
+ },
+ Spec: v1beta2.SparkApplicationSpec{
+ SparkUIOptions: &v1beta2.SparkUIConfiguration{
+ ServiceLabels: map[string]string{
+ "sparkoperator.k8s.io/app-name": "foo8",
+ "key": "value",
+ },
+ },
+ },
+ Status: v1beta2.SparkApplicationStatus{
+ SparkApplicationID: "foo-8",
+ ExecutionAttempts: 1,
+ },
+ }
testcases := []testcase{
{
name: "service with custom serviceport and serviceport and target port are same",
@@ -214,6 +237,9 @@ func TestCreateSparkUIService(t *testing.T) {
serviceType: apiv1.ServiceTypeClusterIP,
servicePortName: defaultPortName,
servicePort: 4041,
+ serviceLabels: map[string]string{
+ "sparkoperator.k8s.io/app-name": "foo1",
+ },
targetPort: intstr.IntOrString{
Type: intstr.Int,
IntVal: int32(4041),
@@ -233,6 +259,9 @@ func TestCreateSparkUIService(t *testing.T) {
serviceType: apiv1.ServiceTypeClusterIP,
servicePortName: defaultPortName,
servicePort: int32(defaultPort),
+ serviceLabels: map[string]string{
+ "sparkoperator.k8s.io/app-name": "foo2",
+ },
},
expectedSelector: map[string]string{
config.SparkAppNameLabel: "foo2",
@@ -248,6 +277,9 @@ func TestCreateSparkUIService(t *testing.T) {
serviceType: apiv1.ServiceTypeClusterIP,
servicePortName: defaultPortName,
servicePort: 80,
+ serviceLabels: map[string]string{
+ "sparkoperator.k8s.io/app-name": "foo4",
+ },
targetPort: intstr.IntOrString{
Type: intstr.Int,
IntVal: int32(4041),
@@ -267,6 +299,9 @@ func TestCreateSparkUIService(t *testing.T) {
serviceType: apiv1.ServiceTypeNodePort,
servicePortName: defaultPortName,
servicePort: int32(defaultPort),
+ serviceLabels: map[string]string{
+ "sparkoperator.k8s.io/app-name": "foo5",
+ },
},
expectedSelector: map[string]string{
config.SparkAppNameLabel: "foo5",
@@ -282,6 +317,9 @@ func TestCreateSparkUIService(t *testing.T) {
serviceType: apiv1.ServiceTypeClusterIP,
servicePortName: "http-spark-test",
servicePort: int32(80),
+ serviceLabels: map[string]string{
+ "sparkoperator.k8s.io/app-name": "foo6",
+ },
},
expectedSelector: map[string]string{
config.SparkAppNameLabel: "foo6",
@@ -300,6 +338,9 @@ func TestCreateSparkUIService(t *testing.T) {
serviceAnnotations: map[string]string{
"key": "value",
},
+ serviceLabels: map[string]string{
+ "sparkoperator.k8s.io/app-name": "foo7",
+ },
targetPort: intstr.IntOrString{
Type: intstr.Int,
IntVal: int32(4041),
@@ -311,6 +352,29 @@ func TestCreateSparkUIService(t *testing.T) {
},
expectError: false,
},
+ {
+ name: "service with custom labels",
+ app: app8,
+ expectedService: SparkService{
+ serviceName: fmt.Sprintf("%s-ui-svc", app8.GetName()),
+ serviceType: apiv1.ServiceTypeClusterIP,
+ servicePortName: defaultPortName,
+ servicePort: defaultPort,
+ serviceLabels: map[string]string{
+ "sparkoperator.k8s.io/app-name": "foo8",
+ "key": "value",
+ },
+ targetPort: intstr.IntOrString{
+ Type: intstr.Int,
+ IntVal: int32(4041),
+ },
+ },
+ expectedSelector: map[string]string{
+ config.SparkAppNameLabel: "foo8",
+ config.SparkRoleLabel: config.SparkDriverRole,
+ },
+ expectError: false,
+ },
{
name: "service with bad port configurations",
app: app3,
diff --git a/test/e2e/basic_test.go b/test/e2e/basic_test.go
index 15c72e8e72..db6c703b1a 100644
--- a/test/e2e/basic_test.go
+++ b/test/e2e/basic_test.go
@@ -18,6 +18,7 @@ package e2e
import (
"context"
+ "log"
"strings"
"testing"
@@ -64,6 +65,7 @@ func TestSubmitSparkPiYaml(t *testing.T) {
app, _ := appFramework.GetSparkApplication(framework.SparkApplicationClient, appFramework.SparkTestNamespace, appName)
podName := app.Status.DriverInfo.PodName
+ log.Printf("LABELS: %v", app.ObjectMeta.GetLabels())
rawLogs, err := framework.KubeClient.CoreV1().Pods(appFramework.SparkTestNamespace).GetLogs(podName, &v1.PodLogOptions{}).Do(context.TODO()).Raw()
assert.Equal(t, nil, err)
assert.NotEqual(t, -1, strings.Index(string(rawLogs), "Pi is roughly 3"))
|