From 8d3f366fa8df9b8f71c5bbc57119da6aa9fff597 Mon Sep 17 00:00:00 2001 From: Thorarinn Sigurdsson Date: Tue, 18 Sep 2018 18:53:00 +0200 Subject: [PATCH] fix: incl. ingresses & services in delete command. When deleting a container service via the delete command, also delete its k8s service and ingress. This fixes problems previously caused by dangling k8s ingresses/services. --- garden-cli/package-lock.json | 2 +- garden-cli/src/plugins/kubernetes/actions.ts | 4 ++- .../src/plugins/kubernetes/deployment.ts | 20 ++++++------- garden-cli/src/plugins/kubernetes/kubectl.ts | 30 +++++++++++++++++++ garden-cli/src/plugins/openfaas.ts | 5 +++- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/garden-cli/package-lock.json b/garden-cli/package-lock.json index 751977726c..13cbea06fd 100644 --- a/garden-cli/package-lock.json +++ b/garden-cli/package-lock.json @@ -1,6 +1,6 @@ { "name": "garden-cli", - "version": "0.5.0", + "version": "0.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/garden-cli/src/plugins/kubernetes/actions.ts b/garden-cli/src/plugins/kubernetes/actions.ts index 5baf534074..4ab287206c 100644 --- a/garden-cli/src/plugins/kubernetes/actions.ts +++ b/garden-cli/src/plugins/kubernetes/actions.ts @@ -160,8 +160,10 @@ export async function cleanupEnvironment({ ctx, logEntry }: CleanupEnvironmentPa export async function deleteService(params: DeleteServiceParams): Promise { const { ctx, logEntry, service } = params const namespace = await getAppNamespace(ctx, ctx.provider) + const provider = ctx.provider - await deleteContainerService({ provider: ctx.provider, logEntry, namespace, serviceName: service.name }) + await deleteContainerService( + { provider, namespace, serviceName: service.name, deploymentOnly: false, logEntry }) return getContainerServiceStatus(params) } diff --git a/garden-cli/src/plugins/kubernetes/deployment.ts b/garden-cli/src/plugins/kubernetes/deployment.ts index 5a06f5aecb..6266124869 100644 --- a/garden-cli/src/plugins/kubernetes/deployment.ts +++ b/garden-cli/src/plugins/kubernetes/deployment.ts @@ -22,14 +22,12 @@ import { RuntimeContext, ServiceStatus } from "../../types/service" import { createIngresses, getIngresses } from "./ingress" import { createServices } from "./service" import { waitForObjects, compareDeployedObjects } from "./status" -import { applyMany } from "./kubectl" +import { applyMany, deleteObjectsByLabel } from "./kubectl" import { getAppNamespace } from "./namespace" import { KubernetesObject } from "./helm" import { PluginContext } from "../../plugin-context" -import { KubernetesProvider } from "./kubernetes" import { GARDEN_ANNOTATION_KEYS_VERSION } from "../../constants" import { KubeApi } from "./api" -import { LogEntry } from "../../logger/log-entry" export const DEFAULT_CPU_REQUEST = "10m" export const DEFAULT_CPU_LIMIT = "500m" @@ -324,17 +322,19 @@ export async function createDeployment( return deployment } -export async function deleteContainerService({ namespace, provider, serviceName, logEntry }: { - namespace: string, - provider: KubernetesProvider, - serviceName: string, - logEntry?: LogEntry, -}) { - const api = new KubeApi(provider) +export async function deleteContainerService( + { namespace, provider, serviceName, deploymentOnly, logEntry }, +) { + let found = true + const context = provider.config.context + const api = new KubeApi(provider) try { await api.extensions.deleteNamespacedDeployment(serviceName, namespace, {}) + if (!deploymentOnly) { + await deleteObjectsByLabel(context, namespace, "service", serviceName) + } } catch (err) { if (err.code === 404) { found = false diff --git a/garden-cli/src/plugins/kubernetes/kubectl.ts b/garden-cli/src/plugins/kubernetes/kubectl.ts index 8484da38be..91d429bdfe 100644 --- a/garden-cli/src/plugins/kubernetes/kubectl.ts +++ b/garden-cli/src/plugins/kubernetes/kubectl.ts @@ -37,6 +37,11 @@ export interface ApplyOptions { namespace?: string, } +export interface DeleteOptions { + includeUninitialized?: boolean, + objectTypes?: string[] +} + export const KUBECTL_DEFAULT_TIMEOUT = 300 export class Kubectl { @@ -193,3 +198,28 @@ export async function applyMany( return result.output } } + +const defaultObjectTypesForDelete = ["deployment", "service", "ingress"] + +export async function deleteObjectsByLabel( + context: string, namespace: string, labelKey: string, labelValue: string, + { includeUninitialized = false, objectTypes = defaultObjectTypesForDelete }: DeleteOptions = {}, +) { + + let args = [ + "delete", + objectTypes.join(","), + "-l", + `${labelKey}=${labelValue}`, + ] + + includeUninitialized && args.push("--include-uninitialized") + + const result = await kubectl(context, namespace).call(args) + + try { + return JSON.parse(result.output) + } catch (_) { + return result.output + } +} diff --git a/garden-cli/src/plugins/openfaas.ts b/garden-cli/src/plugins/openfaas.ts index 4193eb7c48..ce9249b599 100644 --- a/garden-cli/src/plugins/openfaas.ts +++ b/garden-cli/src/plugins/openfaas.ts @@ -244,7 +244,10 @@ export function gardenPlugin({ config }: { config: OpenFaasConfig }): GardenPlug const provider = getK8sProvider(ctx) const namespace = await getAppNamespace(ctx, provider) - await deleteContainerService({ provider, logEntry, namespace, serviceName: service.name }) + await deleteContainerService({ + namespace, provider, serviceName: service.name, + deploymentOnly: true, logEntry, + }) return await getServiceStatus(params) },