Skip to content

Commit

Permalink
Merge pull request #286 from garden-io/fix-delete-service
Browse files Browse the repository at this point in the history
fix: incl. ingresses & services in delete command.
  • Loading branch information
edvald authored Sep 20, 2018
2 parents 90da248 + b38113e commit 24ae2f3
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 58 deletions.
2 changes: 1 addition & 1 deletion garden-cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion garden-cli/src/plugins/kubernetes/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@ export async function cleanupEnvironment({ ctx, logEntry }: CleanupEnvironmentPa
export async function deleteService(params: DeleteServiceParams): Promise<ServiceStatus> {
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, logEntry })

return getContainerServiceStatus(params)
}
Expand Down
33 changes: 23 additions & 10 deletions garden-cli/src/plugins/kubernetes/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -324,14 +322,29 @@ 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, logEntry },
) {

const context = provider.config.context
await deleteContainerDeployment({ namespace, provider, serviceName, logEntry })
await deleteObjectsByLabel({
context,
namespace,
labelKey: "service",
labelValue: serviceName,
objectTypes: ["deployment", "service", "ingress"],
includeUninitialized: false,
})

}

export async function deleteContainerDeployment(
{ namespace, provider, serviceName, logEntry },
) {

let found = true
const api = new KubeApi(provider)

try {
await api.extensions.deleteNamespacedDeployment(serviceName, namespace, <any>{})
Expand Down
37 changes: 37 additions & 0 deletions garden-cli/src/plugins/kubernetes/kubectl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,40 @@ export async function applyMany(
return result.output
}
}

export interface DeleteObjectsParams {
context: string,
namespace: string,
labelKey: string,
labelValue: string,
objectTypes: string[],
includeUninitialized?: boolean,
}

export async function deleteObjectsByLabel(
{
context,
namespace,
labelKey,
labelValue,
objectTypes,
includeUninitialized = false,
}: DeleteObjectsParams) {

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
}
}
44 changes: 44 additions & 0 deletions garden-cli/src/plugins/openfaas/faas-cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2018 Garden Technologies, Inc. <[email protected]>
*
* 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 { builderWorkDir, stackFilename } from "./openfaas"

export interface FaasCliCmdParams {
buildPath: string,
imageId: string,
faasCmd: string,
faasOpts?: string[],
dockerOpts?: string[],
}

export function faasCliCmd(
cmdParams: FaasCliCmdParams,
): string[] {

return [
"docker",
...(faasCliDockerArgs(cmdParams)),
]

}

export function faasCliDockerArgs(
{ buildPath, imageId, faasCmd, faasOpts = [], dockerOpts = [] }: FaasCliCmdParams): string[] {

return [
"run", "-i",
"-v", `${buildPath}:${builderWorkDir}`,
"-v", "/var/run/docker.sock:/var/run/docker.sock",
"--workdir", builderWorkDir,
...dockerOpts,
imageId,
"faas-cli", faasCmd, "-f", stackFilename,
...faasOpts,
]

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,55 +9,56 @@
import * as Joi from "joi"
import { join, resolve } from "path"
import { resolve as urlResolve } from "url"
import { STATIC_DIR } from "../constants"
import { PluginError, ConfigurationError } from "../exceptions"
import { Garden } from "../garden"
import { PluginContext } from "../plugin-context"
import { joiArray, validate, PrimitiveMap } from "../config/common"
import { Module } from "../types/module"
import { ValidateModuleResult } from "../types/plugin/outputs"
import { STATIC_DIR } from "../../constants"
import { PluginError, ConfigurationError } from "../../exceptions"
import { Garden } from "../../garden"
import { PluginContext } from "../../plugin-context"
import { joiArray, validate, PrimitiveMap } from "../../config/common"
import { Module } from "../../types/module"
import { ValidateModuleResult } from "../../types/plugin/outputs"
import {
PrepareEnvironmentParams,
GetEnvironmentStatusParams,
ValidateModuleParams,
DeleteServiceParams,
} from "../types/plugin/params"
} from "../../types/plugin/params"
import {
ServiceStatus,
ServiceIngress,
Service,
} from "../types/service"
} from "../../types/service"
import {
buildGenericModule,
GenericModuleSpec,
genericModuleSpecSchema,
GenericTestSpec,
testGenericModule,
getGenericModuleBuildStatus,
} from "./generic"
import { KubernetesProvider } from "./kubernetes/kubernetes"
import { getNamespace, getAppNamespace } from "./kubernetes/namespace"
} from "../generic"
import { KubernetesProvider } from "../kubernetes/kubernetes"
import { getNamespace, getAppNamespace } from "../kubernetes/namespace"
import {
DeployServiceParams,
GetServiceStatusParams,
BuildModuleParams,
GetServiceOutputsParams,
} from "../types/plugin/params"
} from "../../types/plugin/params"
import { every, values } from "lodash"
import { dumpYaml, findByName } from "../util/util"
import { dumpYaml, findByName } from "../../util/util"
import * as execa from "execa"
import { KubeApi } from "./kubernetes/api"
import { waitForObjects, checkDeploymentStatus } from "./kubernetes/status"
import { systemSymbol } from "./kubernetes/system"
import { BaseServiceSpec } from "../config/service"
import { GardenPlugin } from "../types/plugin/plugin"
import { deleteContainerService } from "./kubernetes/deployment"
import { Provider, providerConfigBaseSchema } from "../config/project"
import { KubeApi } from "../kubernetes/api"
import { waitForObjects, checkDeploymentStatus } from "../kubernetes/status"
import { systemSymbol } from "../kubernetes/system"
import { BaseServiceSpec } from "../../config/service"
import { GardenPlugin } from "../../types/plugin/plugin"
import { Provider, providerConfigBaseSchema } from "../../config/project"
import dedent = require("dedent")
import { faasCliCmd, faasCliDockerArgs } from "./faas-cli"

const systemProjectPath = join(STATIC_DIR, "openfaas", "system")
const stackFilename = "stack.yml"
const builderWorkDir = "/wd"
export const stackFilename = "stack.yml"
export const builderWorkDir = "/wd"
export const FAAS_CLI_IMAGE_ID = "openfaas/faas-cli:0.7.3"

export interface OpenFaasModuleSpec extends GenericModuleSpec {
handler: string
Expand Down Expand Up @@ -151,14 +152,11 @@ export function gardenPlugin({ config }: { config: OpenFaasConfig }): GardenPlug
)

// FIXME: this feels too magicky and convoluted, we should make this type of flow feel more natural
moduleConfig.build.command = [
"docker", "run", "-i",
"-v", `\${modules.${moduleConfig.name}.buildPath}:${builderWorkDir}`,
"-v", "/var/run/docker.sock:/var/run/docker.sock",
"--workdir", builderWorkDir,
`openfaas--builder:\${modules.openfaas--builder.version}`,
"faas-cli", "build", "-f", stackFilename,
]
moduleConfig.build.command = faasCliCmd({
buildPath: `\${modules.${moduleConfig.name}.buildPath}`,
imageId: `openfaas--builder:\${modules.openfaas--builder.version}`,
faasCmd: "build",
})

moduleConfig.build.dependencies.push({
name: "builder",
Expand Down Expand Up @@ -216,15 +214,12 @@ export function gardenPlugin({ config }: { config: OpenFaasConfig }): GardenPlug
await writeStackFile(ctx, module, runtimeContext.envVars)

// use faas-cli to do the deployment
await execa("docker", [
"run", "-i",
"-v", `${module.buildPath}:${builderWorkDir}`,
"-v", "/var/run/docker.sock:/var/run/docker.sock",
"--workdir", builderWorkDir,
"--net", "host",
"openfaas/faas-cli:0.7.3",
"faas-cli", "deploy", "-f", stackFilename,
])
await execa("docker", faasCliDockerArgs({
buildPath: module.buildPath,
imageId: FAAS_CLI_IMAGE_ID,
faasCmd: "deploy",
dockerOpts: ["--net", "host"],
}))

// wait until deployment is ready
const k8sProvider = getK8sProvider(ctx)
Expand All @@ -240,13 +235,37 @@ export function gardenPlugin({ config }: { config: OpenFaasConfig }): GardenPlug
},

async deleteService(params: DeleteServiceParams<OpenFaasModule>): Promise<ServiceStatus> {
const { ctx, logEntry, service } = params
const provider = getK8sProvider(ctx)
const namespace = await getAppNamespace(ctx, provider)
const { ctx, logEntry, service, runtimeContext } = params
let status
let found = true

try {

status = await getServiceStatus({
ctx,
service,
runtimeContext,
module: service.module,
})

found = !!status.state

await execa("docker", faasCliDockerArgs({
buildPath: service.module.buildPath,
imageId: FAAS_CLI_IMAGE_ID,
faasCmd: "remove",
dockerOpts: ["--net", "host"],
}))

} catch (err) {
found = false
}

await deleteContainerService({ provider, logEntry, namespace, serviceName: service.name })
if (logEntry) {
found ? logEntry.setSuccess("Service deleted") : logEntry.setWarn("Service not deployed")
}

return await getServiceStatus(params)
return status
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion garden-cli/src/plugins/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const builtinPlugins: RegisterPluginParam[] = [
"./kubernetes/local",
"./npm-package",
"./google/google-app-engine",
"./openfaas",
"./openfaas/openfaas",
].map(p => resolve(__dirname, p))

// These plugins are always loaded
Expand Down

0 comments on commit 24ae2f3

Please sign in to comment.