diff --git a/core/src/plugins/kubernetes/kubernetes-type/common.ts b/core/src/plugins/kubernetes/kubernetes-type/common.ts index 68435593d6..30bce1620f 100644 --- a/core/src/plugins/kubernetes/kubernetes-type/common.ts +++ b/core/src/plugins/kubernetes/kubernetes-type/common.ts @@ -8,7 +8,7 @@ import { basename, dirname, join, resolve } from "path" import { pathExists, readFile } from "fs-extra" -import { flatten, keyBy, set } from "lodash" +import { flatten, isEmpty, keyBy, set } from "lodash" import { KubernetesModule } from "./module-config" import { KubernetesResource } from "../types" @@ -497,12 +497,37 @@ export function convertServiceResource( return null } - return { - kind: s.kind, - name: s.name || module.name, - podSelector: s.podSelector, - containerName: s.containerName, + return convertServiceResourceSpec(s, module.name) +} + +/** + * Converts 0.12 {@link ServiceResourceSpec} to 0.13 {@link KubernetesTargetResourceSpec}. + * + * NOTE! In 0.13 {@link KubernetesTargetResourceSpec} has stricter schema validation rules + * than {@link ServiceResourceSpec} in 0.12. + * + * The resulting {@link KubernetesTargetResourceSpec} can contain either a pair of {@code (kind, name)} + * or a {@code podSelector}. + * The {@code podSelector} takes precedence over the {@code (kind, name)}, see {@link getTargetResource}. + * + * @param module the current module + * @param serviceResourceSpec the input service resource spec in 0.12 format + * @return the 0.13 compatible kubernetes service resource spec + * @see targetResourceSpecSchema + * @see getTargetResource + */ +export function convertServiceResourceSpec(s: ServiceResourceSpec, moduleName: string): KubernetesTargetResourceSpec { + // Set only the necessary fields to satisfy the schema restrictions defined for KubernetesTargetResourceSpec. + const result: KubernetesTargetResourceSpec = + s.podSelector && !isEmpty(s.podSelector) + ? { podSelector: s.podSelector } + : { kind: s.kind, name: s.name || moduleName } + + if (s.containerName) { + result.containerName = s.containerName } + + return result } export async function runOrTestWithPod( diff --git a/core/test/integ/src/plugins/kubernetes/sync-mode.ts b/core/test/integ/src/plugins/kubernetes/sync-mode.ts index 323f905f28..5dd7d96d90 100644 --- a/core/test/integ/src/plugins/kubernetes/sync-mode.ts +++ b/core/test/integ/src/plugins/kubernetes/sync-mode.ts @@ -265,8 +265,6 @@ describe("sync mode deployments and sync behavior", () => { target: { kind: "Deployment", name: "some-deployment", - containerName: undefined, - podSelector: undefined, }, mode: "two-way", sourcePath: join(module.path, "src"), @@ -323,8 +321,6 @@ describe("sync mode deployments and sync behavior", () => { target: { kind: "Deployment", name: "some-deployment", - containerName: undefined, - podSelector: undefined, }, mode: "two-way", exclude: ["bad/things"], diff --git a/core/test/unit/src/plugins/kubernetes/kubernetes-type/common.ts b/core/test/unit/src/plugins/kubernetes/kubernetes-type/common.ts new file mode 100644 index 0000000000..55daf01853 --- /dev/null +++ b/core/test/unit/src/plugins/kubernetes/kubernetes-type/common.ts @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018-2023 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import { KubernetesTargetResourceSpec, ServiceResourceSpec } from "../../../../../../src/plugins/kubernetes/config" +import { convertServiceResourceSpec } from "../../../../../../src/plugins/kubernetes/kubernetes-type/common" +import { expect } from "chai" + +describe("convertServiceResource", () => { + const moduleName = "module-a" + + it("picks kind and name if podSelector is not defined", async () => { + const serviceResourceSpec: ServiceResourceSpec = { + kind: "Deployment", + name: "service-a", + } + + const kubernetesResourceSpec = convertServiceResourceSpec(serviceResourceSpec, moduleName) + const expectedKubernetesResourceSpec: KubernetesTargetResourceSpec = { + kind: "Deployment", + name: "service-a", + } + expect(kubernetesResourceSpec).to.eql(expectedKubernetesResourceSpec) + }) + + it("picks kind and name if podSelector is empty", async () => { + const serviceResourceSpec: ServiceResourceSpec = { + kind: "Deployment", + name: "service-a", + podSelector: {}, + } + + const kubernetesResourceSpec = convertServiceResourceSpec(serviceResourceSpec, moduleName) + const expectedKubernetesResourceSpec: KubernetesTargetResourceSpec = { + kind: "Deployment", + name: "service-a", + } + expect(kubernetesResourceSpec).to.eql(expectedKubernetesResourceSpec) + }) + + it("picks podSelector instead of kind and name if podSelector is not empty", async () => { + const serviceResourceSpec: ServiceResourceSpec = { + kind: "Deployment", + name: "service-a", + podSelector: { + app: "app-service-a", + }, + } + + const kubernetesResourceSpec = convertServiceResourceSpec(serviceResourceSpec, moduleName) + const expectedKubernetesResourceSpec: KubernetesTargetResourceSpec = { + podSelector: { + app: "app-service-a", + }, + } + expect(kubernetesResourceSpec).to.eql(expectedKubernetesResourceSpec) + }) +})