From bdc9f7d4ed04aa9888585f1f1bc963ea3aea1bf4 Mon Sep 17 00:00:00 2001 From: Nick Hale <4175918+njhale@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:43:55 -0400 Subject: [PATCH 1/3] Add path to port spec and endpoint status Add a path field to container ports so that users can specify an optional path to append to container's endpoint URL. The path field supports interpolation which, for example, enables the use of runtime generated tokens. Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com> --- pkg/apis/internal.acorn.io/v1/appinstance.go | 1 + pkg/apis/internal.acorn.io/v1/appspec.go | 1 + pkg/apis/internal.acorn.io/v1/service.go | 1 + pkg/appdefinition/app.acorn | 1 + pkg/controller/appstatus/cli_status.go | 9 ++- pkg/controller/appstatus/endpoints.go | 1 + pkg/openapi/generated/openapi_generated.go | 18 +++++ pkg/publish/ingress.go | 16 ++-- pkg/services/acorn.go | 78 +++++++++++++++++++- pkg/services/services.go | 3 + 10 files changed, 119 insertions(+), 10 deletions(-) diff --git a/pkg/apis/internal.acorn.io/v1/appinstance.go b/pkg/apis/internal.acorn.io/v1/appinstance.go index b230cc63d..9ce6612de 100644 --- a/pkg/apis/internal.acorn.io/v1/appinstance.go +++ b/pkg/apis/internal.acorn.io/v1/appinstance.go @@ -255,6 +255,7 @@ type Endpoint struct { Address string `json:"address,omitempty"` Protocol Protocol `json:"protocol,omitempty"` PublishProtocol PublishProtocol `json:"publishProtocol,omitempty"` + Path string `json:"path,omitempty"` Pending bool `json:"pending,omitempty"` } diff --git a/pkg/apis/internal.acorn.io/v1/appspec.go b/pkg/apis/internal.acorn.io/v1/appspec.go index 6eba0055e..9d3c265b5 100644 --- a/pkg/apis/internal.acorn.io/v1/appspec.go +++ b/pkg/apis/internal.acorn.io/v1/appspec.go @@ -129,6 +129,7 @@ func (in PortDef) FormatString(serviceName string) string { type PortDef struct { Hostname string `json:"hostname,omitempty"` + Path string `json:"path,omitempty"` Protocol Protocol `json:"protocol,omitempty"` Publish bool `json:"publish,omitempty"` Dev bool `json:"dev,omitempty"` diff --git a/pkg/apis/internal.acorn.io/v1/service.go b/pkg/apis/internal.acorn.io/v1/service.go index 11663fd51..a3ed58e37 100644 --- a/pkg/apis/internal.acorn.io/v1/service.go +++ b/pkg/apis/internal.acorn.io/v1/service.go @@ -72,6 +72,7 @@ type PortPublish struct { Port int32 `json:"port,omitempty"` Protocol Protocol `json:"protocol,omitempty"` Hostname string `json:"hostname,omitempty"` + Path string `json:"path,omitempty"` TargetPort int32 `json:"targetPort,omitempty"` } diff --git a/pkg/appdefinition/app.acorn b/pkg/appdefinition/app.acorn index b259be2a4..36b3a27c6 100644 --- a/pkg/appdefinition/app.acorn +++ b/pkg/appdefinition/app.acorn @@ -240,6 +240,7 @@ port?: int targetPort?: int protocol?: enum("tcp", "udp", "http", "http2") + path?: string =~ "^/.*" } Metrics: { diff --git a/pkg/controller/appstatus/cli_status.go b/pkg/controller/appstatus/cli_status.go index 5e05f2843..3a38a331a 100644 --- a/pkg/controller/appstatus/cli_status.go +++ b/pkg/controller/appstatus/cli_status.go @@ -142,9 +142,7 @@ func endpoints(req router.Request, app *v1.AppInstance) (string, error) { var endpointStrings []string for _, endpoints := range typed.SortedValues(endpointTarget) { - var ( - publicStrings []string - ) + var publicStrings []string for _, endpoint := range endpoints { buf := &strings.Builder{} @@ -177,7 +175,12 @@ func endpoints(req router.Request, app *v1.AppInstance) (string, error) { } } else { buf.WriteString(endpoint.Address) + if len(endpoint.Path) > 0 { + // TODO(njhale): Sanitize address and path if necessary + buf.WriteString(endpoint.Path) + } } + publicStrings = append(publicStrings, buf.String()) } diff --git a/pkg/controller/appstatus/endpoints.go b/pkg/controller/appstatus/endpoints.go index c1a68b584..f48d537ff 100644 --- a/pkg/controller/appstatus/endpoints.go +++ b/pkg/controller/appstatus/endpoints.go @@ -126,6 +126,7 @@ func ingressEndpoints(ctx context.Context, c kclient.Client, app *v1.AppInstance endpoints = append(endpoints, v1.Endpoint{ Target: target.Service, TargetPort: target.Port, + Path: target.Path, Address: hostname, Protocol: v1.ProtocolHTTP, Pending: len(ingress.Status.LoadBalancer.Ingress) == 0, diff --git a/pkg/openapi/generated/openapi_generated.go b/pkg/openapi/generated/openapi_generated.go index 42862ce84..f78a31a8e 100644 --- a/pkg/openapi/generated/openapi_generated.go +++ b/pkg/openapi/generated/openapi_generated.go @@ -9025,6 +9025,12 @@ func schema_pkg_apis_internalacornio_v1_Endpoint(ref common.ReferenceCallback) c Format: "", }, }, + "path": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, "pending": { SchemaProps: spec.SchemaProps{ Type: []string{"boolean"}, @@ -10606,6 +10612,12 @@ func schema_pkg_apis_internalacornio_v1_PortDef(ref common.ReferenceCallback) co Format: "", }, }, + "path": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, "protocol": { SchemaProps: spec.SchemaProps{ Type: []string{"string"}, @@ -10666,6 +10678,12 @@ func schema_pkg_apis_internalacornio_v1_PortPublish(ref common.ReferenceCallback Format: "", }, }, + "path": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, "targetPort": { SchemaProps: spec.SchemaProps{ Type: []string{"integer"}, diff --git a/pkg/publish/ingress.go b/pkg/publish/ingress.go index a7002d2e0..8d22f4b40 100644 --- a/pkg/publish/ingress.go +++ b/pkg/publish/ingress.go @@ -156,6 +156,7 @@ func hash(limit int, s string) string { type Target struct { Port int32 `json:"port,omitempty"` + Path string `json:"path,omitempty"` Service string `json:"service,omitempty"` } @@ -222,12 +223,16 @@ func Ingress(req router.Request, svc *v1.ServiceInstance) (result []kclient.Obje if err != nil { return nil, err } + + target := Target{Port: port.TargetPort, Path: port.Path, Service: svc.Name} + rule := getIngressRule(svc, hostname, port.Port) + if domain == acornDNSDomain || strings.HasSuffix(domain, profiles.ClusterDomainDefault) { - acornDomainTargets[hostname] = Target{Port: port.TargetPort, Service: svc.Name} - acornDomainRules = append(acornDomainRules, getIngressRule(svc, hostname, port.Port)) + acornDomainTargets[hostname] = target + acornDomainRules = append(acornDomainRules, rule) } else { - customDomainTargets[hostname] = Target{Port: port.TargetPort, Service: svc.Name} - customDomainRules = append(customDomainRules, getIngressRule(svc, hostname, port.Port)) + customDomainTargets[hostname] = target + customDomainRules = append(customDomainRules, rule) } } } @@ -235,7 +240,7 @@ func Ingress(req router.Request, svc *v1.ServiceInstance) (result []kclient.Obje if len(ports) > 1 { return nil, fmt.Errorf("multiple ports bound to the same hostname [%s]", hostname) } - customDomainTargets[hostname] = Target{Port: ports[0].TargetPort, Service: svc.Name} + customDomainTargets[hostname] = Target{Port: ports[0].TargetPort, Path: ports[0].Path, Service: svc.Name} customDomainRules = append(customDomainRules, getIngressRule(svc, hostname, ports[0].Port)) } } @@ -276,6 +281,7 @@ func Ingress(req router.Request, svc *v1.ServiceInstance) (result []kclient.Obje svc.Status.Endpoints = append(svc.Status.Endpoints, v1.Endpoint{ Address: rule.Host, PublishProtocol: proto, + Path: rules.target[rule.Host].Path, }) } diff --git a/pkg/services/acorn.go b/pkg/services/acorn.go index 9646e962d..e495c1f1f 100644 --- a/pkg/services/acorn.go +++ b/pkg/services/acorn.go @@ -123,6 +123,10 @@ func serviceNames(appInstance *v1.AppInstance) sets.Set[string] { for k := range appInstance.Status.AppSpec.Containers { result.Insert(k) } + // TODO(njhale): Uncomment me when supporting job ports + //for k := range appInstance.Status.AppSpec.Jobs { + // result.Insert(k) + //} for k := range appInstance.Status.AppSpec.Routers { result.Insert(k) } @@ -237,7 +241,7 @@ func selfScope(scopedLabels v1.ScopedLabels) map[string]string { return labelMap } -func forContainers(appInstance *v1.AppInstance) (result []kclient.Object) { +func forContainers(interpolator *secrets.Interpolator, appInstance *v1.AppInstance) (result []kclient.Object) { for _, entry := range typed.Sorted(appInstance.Status.AppSpec.Containers) { containerName, container := entry.Key, entry.Value @@ -250,6 +254,23 @@ func forContainers(appInstance *v1.AppInstance) (result []kclient.Object) { continue } + var failed bool + interp := interpolator.ForContainer(containerName) + for i, p := range ports { + replacement, err := interp.Replace(p.Path) + if err != nil { + interp.AddError(err) + failed = true + continue + } + + ports[i].Path = replacement + } + + if failed { + continue + } + result = append(result, &v1.ServiceInstance{ ObjectMeta: metav1.ObjectMeta{ Name: containerName, @@ -281,6 +302,57 @@ func forContainers(appInstance *v1.AppInstance) (result []kclient.Object) { return } +func forJobs(appInstance *v1.AppInstance) (result []kclient.Object) { + for _, entry := range typed.Sorted(appInstance.Status.AppSpec.Jobs) { + jobName, job := entry.Key, entry.Value + + if ports2.IsLinked(appInstance, jobName) { + continue + } + + ports := ports2.CollectContainerPorts(&job, appInstance.Status.GetDevMode()) + if len(ports) == 0 { + continue + } + + result = append(result, &v1.ServiceInstance{ + ObjectMeta: metav1.ObjectMeta{ + Name: jobName, + Namespace: appInstance.Status.Namespace, + Labels: labels.Managed(appInstance, + labels.AcornPublicName, publicname.ForChild(appInstance, jobName), + // TODO(njhale): Should this be AcornJobName? + //labels.AcornContainerName, jobName), + labels.AcornJobName, jobName), + Annotations: map[string]string{ + labels.AcornAppGeneration: strconv.FormatInt(appInstance.Generation, 10), + labels.AcornConfigHashAnnotation: appInstance.Status.AppStatus.Jobs[jobName].ConfigHash, + }, + }, + Spec: v1.ServiceInstanceSpec{ + AppName: appInstance.Name, + AppNamespace: appInstance.Namespace, + PublishMode: publishMode(appInstance), + Publish: ports2.PortPublishForService(jobName, appInstance.Spec.Publish), + Labels: labels.Merge(labels.Managed(appInstance, labels.AcornJobName, jobName), + labels.GatherScoped(jobName, v1.LabelTypeJob, + appInstance.Status.AppSpec.Labels, job.Labels, appInstance.Spec.Labels)), + Annotations: labels.GatherScoped(jobName, v1.LabelTypeJob, + appInstance.Status.AppSpec.Annotations, job.Annotations, appInstance.Spec.Annotations), + //Labels: labels.Merge(labels.Managed(appInstance, labels.AcornContainerName, containerName), + // labels.GatherScoped(containerName, v1.LabelTypeContainer, + // appInstance.Status.AppSpec.Labels, container.Labels, appInstance.Spec.Labels)), + //Annotations: labels.GatherScoped(containerName, v1.LabelTypeContainer, + // appInstance.Status.AppSpec.Annotations, container.Annotations, appInstance.Spec.Annotations), + Ports: ports, + Job: jobName, + }, + }) + } + + return +} + func forLinkedServices(app *v1.AppInstance) (result []kclient.Object) { for _, link := range app.Spec.Links { newService := &v1.ServiceInstance{ @@ -369,7 +441,9 @@ func ToAcornServices(ctx context.Context, c kclient.Client, interpolator *secret } result = append(result, objs...) result = append(result, forAcorns(appInstance)...) - result = append(result, forContainers(appInstance)...) + result = append(result, forContainers(interpolator, appInstance)...) + // TODO(njhale): add services for jobs + //result = append(result, forJobs(appInstance)...) routers, err := forRouters(appInstance) if err != nil { diff --git a/pkg/services/services.go b/pkg/services/services.go index dddaac061..d6df7a4de 100644 --- a/pkg/services/services.go +++ b/pkg/services/services.go @@ -250,6 +250,9 @@ func ToK8sService(req router.Request, service *v1.ServiceInstance) (result []kcl return toAddressService(service), nil, nil } else if service.Spec.Container != "" { return toContainerService(service), nil, nil + // TODO(njhale): Flip this on when generating job services + //} else if service.Spec.Job != "" { + // return toJobService(service), nil, nil } else if len(service.Spec.ContainerLabels) > 0 { return toContainerLabelsService(service), nil, nil } From 8a0ba088f2dd3d6bc85e832338b39ecb451067b3 Mon Sep 17 00:00:00 2001 From: Nick Hale <4175918+njhale@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:24:15 -0400 Subject: [PATCH 2/3] Allow jobs to publish ports Deploy ServiceInstances and Ingresses for job ports. This allows jobs to serve traffic and expose things like temporary web pages for collecting user credentials. Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com> --- pkg/controller/appstatus/cli_status.go | 25 ++++++------ pkg/publish/servicelb.go | 8 +++- pkg/services/acorn.go | 55 +++++++++++++++++--------- pkg/services/services.go | 27 +++++++++++-- 4 files changed, 82 insertions(+), 33 deletions(-) diff --git a/pkg/controller/appstatus/cli_status.go b/pkg/controller/appstatus/cli_status.go index 3a38a331a..3b84f39fd 100644 --- a/pkg/controller/appstatus/cli_status.go +++ b/pkg/controller/appstatus/cli_status.go @@ -162,22 +162,25 @@ func endpoints(req router.Request, app *v1.AppInstance) (string, error) { buf.WriteString("http://") } } + + if endpoint.Pending { + buf.WriteString("") + } else { + buf.WriteString(endpoint.Address) + + // Append the path if provided + if len(endpoint.Path) > 0 { + buf.WriteString(endpoint.Path) + } + } default: buf.WriteString(strings.ToLower(string(endpoint.Protocol))) buf.WriteString("://") - } - if endpoint.Pending { - if endpoint.Protocol == "http" { - buf.WriteString("") - } else { + if endpoint.Pending { buf.WriteString("") - } - } else { - buf.WriteString(endpoint.Address) - if len(endpoint.Path) > 0 { - // TODO(njhale): Sanitize address and path if necessary - buf.WriteString(endpoint.Path) + } else { + buf.WriteString(endpoint.Address) } } diff --git a/pkg/publish/servicelb.go b/pkg/publish/servicelb.go index 2f203fca0..12fe7bed1 100644 --- a/pkg/publish/servicelb.go +++ b/pkg/publish/servicelb.go @@ -30,8 +30,14 @@ func ServiceLoadBalancer(req router.Request, svc *v1.ServiceInstance) (result [] selectorLabels := svc.Spec.ContainerLabels if svc.Spec.Container != "" { + selectorLabel := labels.AcornContainerName + if svc.Labels[labels.AcornJobName] != "" { + // Service targets a job, so we need to selector for containers matching the job name. + // Which will be marked as the Container on the spec. + selectorLabel = labels.AcornJobName + } selectorLabels = map[string]string{ - labels.AcornContainerName: svc.Spec.Container, + selectorLabel: svc.Spec.Container, } } diff --git a/pkg/services/acorn.go b/pkg/services/acorn.go index e495c1f1f..21a7d1b4d 100644 --- a/pkg/services/acorn.go +++ b/pkg/services/acorn.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/acorn-io/baaah/pkg/apply" + "github.com/acorn-io/baaah/pkg/name" "github.com/acorn-io/baaah/pkg/typed" v1 "github.com/acorn-io/runtime/pkg/apis/internal.acorn.io/v1" "github.com/acorn-io/runtime/pkg/jobs" @@ -123,10 +124,9 @@ func serviceNames(appInstance *v1.AppInstance) sets.Set[string] { for k := range appInstance.Status.AppSpec.Containers { result.Insert(k) } - // TODO(njhale): Uncomment me when supporting job ports - //for k := range appInstance.Status.AppSpec.Jobs { - // result.Insert(k) - //} + for k := range appInstance.Status.AppSpec.Jobs { + result.Insert(jobServiceName(k)) + } for k := range appInstance.Status.AppSpec.Routers { result.Insert(k) } @@ -302,7 +302,7 @@ func forContainers(interpolator *secrets.Interpolator, appInstance *v1.AppInstan return } -func forJobs(appInstance *v1.AppInstance) (result []kclient.Object) { +func forJobs(interpolator *secrets.Interpolator, appInstance *v1.AppInstance) (result []kclient.Object) { for _, entry := range typed.Sorted(appInstance.Status.AppSpec.Jobs) { jobName, job := entry.Key, entry.Value @@ -315,14 +315,35 @@ func forJobs(appInstance *v1.AppInstance) (result []kclient.Object) { continue } + var failed bool + interp := interpolator.ForJob(jobName) + for i, p := range ports { + replacement, err := interp.Replace(p.Path) + if err != nil { + interp.AddError(err) + failed = true + continue + } + + ports[i].Path = replacement + } + + if failed { + continue + } + + publish := publishMode(appInstance) + if appInstance.Status.AppStatus.Jobs[jobName].State == "completed" { + // Don't publish endpoints for jobs that are completed + publish = v1.PublishModeNone + } + result = append(result, &v1.ServiceInstance{ ObjectMeta: metav1.ObjectMeta{ - Name: jobName, + Name: jobServiceName(jobName), Namespace: appInstance.Status.Namespace, Labels: labels.Managed(appInstance, labels.AcornPublicName, publicname.ForChild(appInstance, jobName), - // TODO(njhale): Should this be AcornJobName? - //labels.AcornContainerName, jobName), labels.AcornJobName, jobName), Annotations: map[string]string{ labels.AcornAppGeneration: strconv.FormatInt(appInstance.Generation, 10), @@ -332,20 +353,15 @@ func forJobs(appInstance *v1.AppInstance) (result []kclient.Object) { Spec: v1.ServiceInstanceSpec{ AppName: appInstance.Name, AppNamespace: appInstance.Namespace, - PublishMode: publishMode(appInstance), + PublishMode: publish, Publish: ports2.PortPublishForService(jobName, appInstance.Spec.Publish), Labels: labels.Merge(labels.Managed(appInstance, labels.AcornJobName, jobName), labels.GatherScoped(jobName, v1.LabelTypeJob, appInstance.Status.AppSpec.Labels, job.Labels, appInstance.Spec.Labels)), Annotations: labels.GatherScoped(jobName, v1.LabelTypeJob, appInstance.Status.AppSpec.Annotations, job.Annotations, appInstance.Spec.Annotations), - //Labels: labels.Merge(labels.Managed(appInstance, labels.AcornContainerName, containerName), - // labels.GatherScoped(containerName, v1.LabelTypeContainer, - // appInstance.Status.AppSpec.Labels, container.Labels, appInstance.Spec.Labels)), - //Annotations: labels.GatherScoped(containerName, v1.LabelTypeContainer, - // appInstance.Status.AppSpec.Annotations, container.Annotations, appInstance.Spec.Annotations), - Ports: ports, - Job: jobName, + Ports: ports, + Container: jobName, }, }) } @@ -442,8 +458,7 @@ func ToAcornServices(ctx context.Context, c kclient.Client, interpolator *secret result = append(result, objs...) result = append(result, forAcorns(appInstance)...) result = append(result, forContainers(interpolator, appInstance)...) - // TODO(njhale): add services for jobs - //result = append(result, forJobs(appInstance)...) + result = append(result, forJobs(interpolator, appInstance)...) routers, err := forRouters(appInstance) if err != nil { @@ -526,3 +541,7 @@ func getUngranted(appInstance *v1.AppInstance, service *v1.ServiceInstance) []v1 return ungranted } + +func jobServiceName(jobName string) string { + return name.SafeConcatName(jobName, "job") +} diff --git a/pkg/services/services.go b/pkg/services/services.go index d6df7a4de..9a896b48f 100644 --- a/pkg/services/services.go +++ b/pkg/services/services.go @@ -64,6 +64,27 @@ func toContainerService(service *v1.ServiceInstance) (result []kclient.Object) { return } +func toJobService(service *v1.ServiceInstance) (result []kclient.Object) { + newService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: service.Name, + Namespace: service.Namespace, + Labels: service.Spec.Labels, + Annotations: typed.Concat(service.Spec.Annotations, map[string]string{ + labels.AcornConfigHashAnnotation: service.Annotations[labels.AcornConfigHashAnnotation], + }), + }, + Spec: corev1.ServiceSpec{ + Ports: ports.ToServicePorts(service.Spec.Ports), + Type: corev1.ServiceTypeClusterIP, + Selector: labels.ManagedByApp(service.Spec.AppNamespace, + service.Spec.AppName, labels.AcornJobName, service.Spec.Container), + }, + } + result = append(result, newService) + return +} + func toAddressService(service *v1.ServiceInstance) (result []kclient.Object) { newService := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ @@ -249,10 +270,10 @@ func ToK8sService(req router.Request, service *v1.ServiceInstance) (result []kcl } else if service.Spec.Address != "" { return toAddressService(service), nil, nil } else if service.Spec.Container != "" { + if service.Labels[labels.AcornJobName] != "" { + return toJobService(service), nil, nil + } return toContainerService(service), nil, nil - // TODO(njhale): Flip this on when generating job services - //} else if service.Spec.Job != "" { - // return toJobService(service), nil, nil } else if len(service.Spec.ContainerLabels) > 0 { return toContainerLabelsService(service), nil, nil } From ef0ed60cdb836b861a5e3ccc2334704e5f08452c Mon Sep 17 00:00:00 2001 From: Nick Hale <4175918+njhale@users.noreply.github.com> Date: Fri, 3 Nov 2023 15:21:10 -0400 Subject: [PATCH 3/3] Update test fixtures Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com> --- .../testdata/computeclass/job/expected.golden | 35 ++++++++++ .../filter-user-labels/expected.golden | 41 +++++++++++ .../deployspec/labels/expected.golden | 39 +++++++++++ .../deployspec/no-user-labels/expected.golden | 32 +++++++++ .../deployspec/pre-stop/job/expected.golden | 35 ++++++++++ .../testdata/job/basic/expected.golden | 35 ++++++++++ .../testdata/job/labels/expected.golden | 43 ++++++++++++ .../testdata/memory/job/expected.golden | 35 ++++++++++ .../testdata/permissions/both/expected.golden | 35 ++++++++++ .../bothwithnopermissions/expected.golden | 35 ++++++++++ .../testdata/permissions/job/expected.golden | 35 ++++++++++ .../permissions/multiplejobs/expected.golden | 70 +++++++++++++++++++ 12 files changed, 470 insertions(+) diff --git a/pkg/controller/appdefinition/testdata/computeclass/job/expected.golden b/pkg/controller/appdefinition/testdata/computeclass/job/expected.golden index c7a9ff68d..0787f0a97 100644 --- a/pkg/controller/appdefinition/testdata/computeclass/job/expected.golden +++ b/pkg/controller/appdefinition/testdata/computeclass/job/expected.golden @@ -139,6 +139,41 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.oneimage + name: oneimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: oneimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance diff --git a/pkg/controller/appdefinition/testdata/deployspec/filter-user-labels/expected.golden b/pkg/controller/appdefinition/testdata/deployspec/filter-user-labels/expected.golden index 8de67c590..7b9352f44 100644 --- a/pkg/controller/appdefinition/testdata/deployspec/filter-user-labels/expected.golden +++ b/pkg/controller/appdefinition/testdata/deployspec/filter-user-labels/expected.golden @@ -289,6 +289,47 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: job-name + acorn.io/managed: "true" + acorn.io/public-name: app-name.job-name + name: job-name-job + namespace: app-created-namespace +spec: + annotations: + admit-job.io: test-admit-job-ann + admit.io: test-admit-app-spec-ann + allowed-global.io: test-global + allowed.io: test-allowed-app-spec-ann + appName: app-name + appNamespace: app-namespace + container: job-name + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: job-name + acorn.io/managed: "true" + allowed-global.io: test-global + allowed-job.io: test-allowed-job-label + allowed.io: test-allowed-app-spec-label + permit.io: test-permit-app-spec-label + ports: + - port: 80 + protocol: http + targetPort: 81 +status: {} + --- apiVersion: v1 kind: PersistentVolumeClaim diff --git a/pkg/controller/appdefinition/testdata/deployspec/labels/expected.golden b/pkg/controller/appdefinition/testdata/deployspec/labels/expected.golden index f5da0fbdf..0c3e5d5f8 100644 --- a/pkg/controller/appdefinition/testdata/deployspec/labels/expected.golden +++ b/pkg/controller/appdefinition/testdata/deployspec/labels/expected.golden @@ -283,6 +283,45 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: job-name + acorn.io/managed: "true" + acorn.io/public-name: app-name.job-name + name: job-name-job + namespace: app-created-namespace +spec: + annotations: + appSpecAnn: test-app-spec-ann + global-scoped-ann: test-global + jobAnn: test-job-ann + appName: app-name + appNamespace: app-namespace + container: job-name + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: job-name + acorn.io/managed: "true" + appSpecLabel: test-app-spec-label + global-scoped-label: test-global + jobLabel: test-job-label + ports: + - port: 80 + protocol: http + targetPort: 81 +status: {} + --- apiVersion: v1 kind: PersistentVolumeClaim diff --git a/pkg/controller/appdefinition/testdata/deployspec/no-user-labels/expected.golden b/pkg/controller/appdefinition/testdata/deployspec/no-user-labels/expected.golden index 30f9740a7..24b143307 100644 --- a/pkg/controller/appdefinition/testdata/deployspec/no-user-labels/expected.golden +++ b/pkg/controller/appdefinition/testdata/deployspec/no-user-labels/expected.golden @@ -225,6 +225,38 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: job-name + acorn.io/managed: "true" + acorn.io/public-name: app-name.job-name + name: job-name-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: job-name + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: job-name + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 +status: {} + --- apiVersion: v1 kind: PersistentVolumeClaim diff --git a/pkg/controller/appdefinition/testdata/deployspec/pre-stop/job/expected.golden b/pkg/controller/appdefinition/testdata/deployspec/pre-stop/job/expected.golden index 874abbb62..ebdd8be9e 100644 --- a/pkg/controller/appdefinition/testdata/deployspec/pre-stop/job/expected.golden +++ b/pkg/controller/appdefinition/testdata/deployspec/pre-stop/job/expected.golden @@ -120,6 +120,41 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.oneimage + name: oneimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: oneimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance diff --git a/pkg/controller/appdefinition/testdata/job/basic/expected.golden b/pkg/controller/appdefinition/testdata/job/basic/expected.golden index 874abbb62..ebdd8be9e 100644 --- a/pkg/controller/appdefinition/testdata/job/basic/expected.golden +++ b/pkg/controller/appdefinition/testdata/job/basic/expected.golden @@ -120,6 +120,41 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.oneimage + name: oneimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: oneimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance diff --git a/pkg/controller/appdefinition/testdata/job/labels/expected.golden b/pkg/controller/appdefinition/testdata/job/labels/expected.golden index fb1057488..6adeef91b 100644 --- a/pkg/controller/appdefinition/testdata/job/labels/expected.golden +++ b/pkg/controller/appdefinition/testdata/job/labels/expected.golden @@ -135,6 +135,49 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: job1 + acorn.io/managed: "true" + acorn.io/public-name: app-name.job1 + name: job1-job + namespace: app-created-namespace +spec: + annotations: + alljobsa: value + global2a: value + globala: value + job1a: value + job3a: value + appName: app-name + appNamespace: app-namespace + container: job1 + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: job1 + acorn.io/managed: "true" + alljobs: value + global: value + global2: value + job1: value + job3: value + ports: + - port: 80 + protocol: http + targetPort: 81 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance diff --git a/pkg/controller/appdefinition/testdata/memory/job/expected.golden b/pkg/controller/appdefinition/testdata/memory/job/expected.golden index f9fc3194d..241fac53b 100644 --- a/pkg/controller/appdefinition/testdata/memory/job/expected.golden +++ b/pkg/controller/appdefinition/testdata/memory/job/expected.golden @@ -124,6 +124,41 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.oneimage + name: oneimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: oneimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance diff --git a/pkg/controller/appdefinition/testdata/permissions/both/expected.golden b/pkg/controller/appdefinition/testdata/permissions/both/expected.golden index 95370d56b..b00628858 100644 --- a/pkg/controller/appdefinition/testdata/permissions/both/expected.golden +++ b/pkg/controller/appdefinition/testdata/permissions/both/expected.golden @@ -479,6 +479,41 @@ spec: targetPort: 91 status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.oneimage + name: oneimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: oneimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance diff --git a/pkg/controller/appdefinition/testdata/permissions/bothwithnopermissions/expected.golden b/pkg/controller/appdefinition/testdata/permissions/bothwithnopermissions/expected.golden index 8e15389a9..027ae0a5f 100644 --- a/pkg/controller/appdefinition/testdata/permissions/bothwithnopermissions/expected.golden +++ b/pkg/controller/appdefinition/testdata/permissions/bothwithnopermissions/expected.golden @@ -281,6 +281,41 @@ spec: targetPort: 91 status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.oneimage + name: oneimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: oneimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance diff --git a/pkg/controller/appdefinition/testdata/permissions/job/expected.golden b/pkg/controller/appdefinition/testdata/permissions/job/expected.golden index e00c1d058..cf2cfa129 100644 --- a/pkg/controller/appdefinition/testdata/permissions/job/expected.golden +++ b/pkg/controller/appdefinition/testdata/permissions/job/expected.golden @@ -221,6 +221,41 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.oneimage + name: oneimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: oneimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance diff --git a/pkg/controller/appdefinition/testdata/permissions/multiplejobs/expected.golden b/pkg/controller/appdefinition/testdata/permissions/multiplejobs/expected.golden index 559b19768..d4d847100 100644 --- a/pkg/controller/appdefinition/testdata/permissions/multiplejobs/expected.golden +++ b/pkg/controller/appdefinition/testdata/permissions/multiplejobs/expected.golden @@ -445,6 +445,76 @@ spec: name: acorn-job-output-helper status: {} +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.oneimage + name: oneimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: oneimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: oneimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + +--- +apiVersion: internal.acorn.io/v1 +kind: ServiceInstance +metadata: + annotations: + acorn.io/app-generation: "0" + acorn.io/config-hash: "" + creationTimestamp: null + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: twoimage + acorn.io/managed: "true" + acorn.io/public-name: app-name.twoimage + name: twoimage-job + namespace: app-created-namespace +spec: + appName: app-name + appNamespace: app-namespace + container: twoimage + default: false + labels: + acorn.io/app-name: app-name + acorn.io/app-namespace: app-namespace + acorn.io/job-name: twoimage + acorn.io/managed: "true" + ports: + - port: 80 + protocol: http + targetPort: 81 + - port: 90 + protocol: tcp + targetPort: 91 +status: {} + --- apiVersion: internal.acorn.io/v1 kind: AppInstance