Skip to content

Commit

Permalink
Merge branch 'master' into private-registry-auth
Browse files Browse the repository at this point in the history
  • Loading branch information
eysi09 authored Dec 5, 2019
2 parents cb91079 + a44ebf1 commit b3f8d64
Show file tree
Hide file tree
Showing 14 changed files with 179 additions and 46 deletions.
3 changes: 3 additions & 0 deletions garden-service/src/commands/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type DeleteSecretArgs = typeof deleteSecretArgs
export class DeleteSecretCommand extends Command<typeof deleteSecretArgs> {
name = "secret"
help = "Delete a secret from the environment."
protected = true

description = dedent`
Returns with an error if the provided key could not be found by the provider.
Expand Down Expand Up @@ -79,6 +80,7 @@ export class DeleteEnvironmentCommand extends Command {
name = "environment"
alias = "env"
help = "Deletes a running environment."
protected = true

description = dedent`
This will delete all services in the specified environment, and trigger providers to clear up any other resources
Expand Down Expand Up @@ -111,6 +113,7 @@ export class DeleteServiceCommand extends Command {
alias = "services"
help = "Deletes running services."
arguments = deleteServiceArgs
protected = true

description = dedent`
Deletes (i.e. un-deploys) the specified services. Note that this command does not take into account any
Expand Down
40 changes: 29 additions & 11 deletions garden-service/src/config/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { sep, resolve, relative, basename } from "path"
import { sep, resolve, relative, basename, dirname } from "path"
import yaml from "js-yaml"
import { readFile } from "fs-extra"
import { omit, flatten, isPlainObject, find } from "lodash"
import { ModuleResource, moduleConfigSchema } from "./module"
import { ModuleResource, moduleConfigSchema, coreModuleSpecSchema } from "./module"
import { ConfigurationError } from "../exceptions"
import { DEFAULT_API_VERSION } from "../constants"
import { ProjectResource } from "../config/project"
import { getConfigFilePath } from "../util/fs"
import { validateWithPath } from "./common"

export interface GardenResource {
apiVersion: string
Expand Down Expand Up @@ -82,10 +83,11 @@ function prepareResources(spec: any, path: string, configPath: string, projectRo
})
}

if (spec.kind) {
return [prepareFlatConfigDoc(spec, path, configPath, projectRoot)]
// TODO: remove support for the older scoped config style in 0.11
if (spec.project || spec.module) {
return prepareScopedConfigDoc(spec, path, configPath, projectRoot)
} else {
return prepareScopedConfigDoc(spec, path, configPath)
return [prepareFlatConfigDoc(spec, path, configPath, projectRoot)]
}
}

Expand All @@ -96,13 +98,18 @@ function prepareResources(spec: any, path: string, configPath: string, projectRo
*/
function prepareFlatConfigDoc(spec: any, path: string, configPath: string, projectRoot: string): GardenResource {
const kind = spec.kind
const relPath = `${relative(projectRoot, path)}/garden.yml`

if (kind === "Project") {
return prepareProjectConfig(spec, path, configPath)
} else if (kind === "Module") {
return prepareModuleResource(spec, path, configPath)
return prepareModuleResource(spec, path, configPath, projectRoot)
} else if (!kind) {
throw new ConfigurationError(`Missing \`kind\` field in config at ${relPath}`, {
kind,
path: relPath,
})
} else {
const relPath = `${relative(projectRoot, path)}/garden.yml`
throw new ConfigurationError(`Unknown config kind ${kind} in ${relPath}`, {
kind,
path: relPath,
Expand All @@ -116,15 +123,15 @@ function prepareFlatConfigDoc(spec: any, path: string, configPath: string, proje
* The spec defines a project and/or a module, with the config for each nested under the "project" / "module" field,
* respectively.
*/
function prepareScopedConfigDoc(spec: any, path: string, configPath: string): GardenResource[] {
function prepareScopedConfigDoc(spec: any, path: string, configPath: string, projectRoot: string): GardenResource[] {
const resources: GardenResource[] = []

if (spec.project) {
resources.push(prepareProjectConfig(spec.project, path, configPath))
}

if (spec.module) {
resources.push(prepareModuleResource(spec.module, path, configPath))
resources.push(prepareModuleResource(spec.module, path, configPath, projectRoot))
}

return resources
Expand All @@ -142,7 +149,7 @@ function prepareProjectConfig(spec: any, path: string, configPath: string): Proj
return spec
}

function prepareModuleResource(spec: any, path: string, configPath: string): ModuleResource {
function prepareModuleResource(spec: any, path: string, configPath: string, projectRoot: string): ModuleResource {
/**
* We allow specifying modules by name only as a shorthand:
* dependencies:
Expand All @@ -155,7 +162,7 @@ function prepareModuleResource(spec: any, path: string, configPath: string): Mod
: []

// Built-in keys are validated here and the rest are put into the `spec` field
return {
const config: ModuleResource = {
apiVersion: spec.apiVersion || DEFAULT_API_VERSION,
kind: "Module",
allowPublish: spec.allowPublish,
Expand All @@ -179,6 +186,17 @@ function prepareModuleResource(spec: any, path: string, configPath: string): Mod
type: spec.type,
taskConfigs: [],
}

validateWithPath({
config,
schema: coreModuleSpecSchema,
path: dirname(configPath),
projectRoot,
configType: "module",
ErrorClass: ConfigurationError,
})

return config
}

export async function findProjectConfig(path: string, allowInvalid = false): Promise<ProjectResource | undefined> {
Expand Down
63 changes: 34 additions & 29 deletions garden-service/src/config/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ export const baseBuildSpecSchema = joi
.default(() => ({ dependencies: [] }), "{}")
.description("Specify how to build the module. Note that plugins may define additional keys on this object.")

export const baseModuleSpecSchema = joi
// These fields are validated immediately when loading the config file
export const coreModuleSpecSchema = joi
.object()
.keys({
apiVersion: joi
Expand All @@ -117,12 +118,20 @@ export const baseModuleSpecSchema = joi
.required()
.description("The name of this module.")
.example("my-sweet-module"),
description: joi.string(),
include: joi
.array()
.items(joi.string().posixPath({ allowGlobs: true, subPathOnly: true }))
.description(
dedent`Specify a list of POSIX-style paths or globs that should be regarded as the source files for this
})
.required()
.unknown(true)
.description("Configure a module whose sources are located in this directory.")
.meta({ extendable: true })

// These fields may be resolved later in the process, and allow for usage of template strings
export const baseModuleSpecSchema = coreModuleSpecSchema.keys({
description: joi.string(),
include: joi
.array()
.items(joi.string().posixPath({ allowGlobs: true, subPathOnly: true }))
.description(
dedent`Specify a list of POSIX-style paths or globs that should be regarded as the source files for this
module. Files that do *not* match these paths or globs are excluded when computing the version of the module,
when responding to filesystem watch events, and when staging builds.
Expand All @@ -131,13 +140,13 @@ export const baseModuleSpecSchema = joi
[Configuration Files guide](${includeGuideLink}) for details.
Also note that specifying an empty list here means _no sources_ should be included.`
)
.example([["Dockerfile", "my-app.js"], {}]),
exclude: joi
.array()
.items(joi.string().posixPath({ allowGlobs: true, subPathOnly: true }))
.description(
dedent`Specify a list of POSIX-style paths or glob patterns that should be excluded from the module. Files that
)
.example([["Dockerfile", "my-app.js"], {}]),
exclude: joi
.array()
.items(joi.string().posixPath({ allowGlobs: true, subPathOnly: true }))
.description(
dedent`Specify a list of POSIX-style paths or glob patterns that should be excluded from the module. Files that
match these paths or globs are excluded when computing the version of the module, when responding to filesystem
watch events, and when staging builds.
Expand All @@ -149,24 +158,20 @@ export const baseModuleSpecSchema = joi
and directories are watched for changes. Use the project \`modules.exclude\` field to affect those, if you have
large directories that should not be watched for changes.
`
)
.example([["tmp/**/*", "*.log"], {}]),
repositoryUrl: joiRepositoryUrl().description(
dedent`${joiRepositoryUrl().describe().description}
)
.example([["tmp/**/*", "*.log"], {}]),
repositoryUrl: joiRepositoryUrl().description(
dedent`${joiRepositoryUrl().describe().description}
Garden will import the repository source code into this module, but read the module's
config from the local garden.yml file.`
),
allowPublish: joi
.boolean()
.default(true)
.description("When false, disables pushing this module to remote registries."),
build: baseBuildSpecSchema.unknown(true),
})
.required()
.unknown(true)
.description("Configure a module whose sources are located in this directory.")
.meta({ extendable: true })
),
allowPublish: joi
.boolean()
.default(true)
.description("When false, disables pushing this module to remote registries."),
build: baseBuildSpecSchema.unknown(true),
})

export interface ModuleConfig<
M extends ModuleSpec = any,
Expand Down
32 changes: 26 additions & 6 deletions garden-service/src/plugins/openfaas/openfaas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ConfigurationError } from "../../exceptions"
import { ServiceStatus, ServiceIngress, ServiceProtocol } from "../../types/service"
import { testExecModule } from "../exec"
import { getNamespace } from "../kubernetes/namespace"
import { findByName } from "../../util/util"
import { findByName, sleep } from "../../util/util"
import { KubeApi } from "../kubernetes/api"
import { waitForResources } from "../kubernetes/status/status"
import { checkWorkloadStatus } from "../kubernetes/status/workload"
Expand Down Expand Up @@ -242,6 +242,9 @@ async function getServiceLogs(params: GetServiceLogsParams<OpenFaasModule>) {
return getAllLogs({ ...params, provider: k8sProvider, defaultNamespace: namespace, resources })
}

const faasNetesInitTimeout = 10000
const retryWait = 1000

async function deployService(params: DeployServiceParams<OpenFaasModule>): Promise<ServiceStatus> {
const { ctx, module, service, log, runtimeContext } = params
const k8sProvider = getK8sProvider(ctx.provider.dependencies)
Expand All @@ -251,11 +254,28 @@ async function deployService(params: DeployServiceParams<OpenFaasModule>): Promi
await writeStackFile(<OpenFaasProvider>ctx.provider, k8sProvider, module, envVars)

// use faas-cli to do the deployment
await faasCli.stdout({
log,
cwd: module.buildPath,
args: ["deploy", "-f", stackFilename],
})
const start = new Date().getTime()

while (true) {
try {
await faasCli.stdout({
log,
cwd: module.buildPath,
args: ["deploy", "-f", stackFilename],
})
break
} catch (err) {
const now = new Date().getTime()

// Retry a few times in case faas-netes is still initializing
if (err.all.includes("failed to deploy with status code: 503") && now - start < faasNetesInitTimeout * 1000) {
await sleep(retryWait)
continue
} else {
throw err
}
}
}

// wait until deployment is ready
const namespace = await getFunctionNamespace(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
type: foo
name: bla
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kind: Module
type: foo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kind: Module
name: foo
5 changes: 5 additions & 0 deletions garden-service/test/unit/src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,9 @@ describe("commands.build", () => {
"stage-build.module-b": {},
})
})

it("should be protected", async () => {
const command = new BuildCommand()
expect(command.protected).to.be.true
})
})
13 changes: 13 additions & 0 deletions garden-service/test/unit/src/commands/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ describe("DeleteSecretCommand", () => {
"not-found"
)
})

it("should be protected", async () => {
const command = new DeleteSecretCommand()
expect(command.protected).to.be.true
})
})

const getServiceStatus = async (): Promise<ServiceStatus> => {
Expand Down Expand Up @@ -134,6 +139,10 @@ describe("DeleteEnvironmentCommand", () => {
})
expect(deletedServices.sort()).to.eql(["service-a", "service-b", "service-c", "service-d"])
})

it("should be protected", async () => {
expect(command.protected).to.be.true
})
})

describe("DeleteServiceCommand", () => {
Expand Down Expand Up @@ -211,4 +220,8 @@ describe("DeleteServiceCommand", () => {
"service-b": { forwardablePorts: [], state: "unknown", ingresses: [], detail: {} },
})
})

it("should be protected", async () => {
expect(command.protected).to.be.true
})
})
5 changes: 5 additions & 0 deletions garden-service/test/unit/src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,9 @@ describe("DeployCommand", () => {
"deploy.service-b": { forwardablePorts: [], version: "1", state: "ready", detail: {} },
})
})

it("should be protected", async () => {
const command = new DeployCommand()
expect(command.protected).to.be.true
})
})
9 changes: 9 additions & 0 deletions garden-service/test/unit/src/commands/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { expect } from "chai"
import { DevCommand } from "../../../../src/commands/dev"

describe("DevCommand", () => {
it("should be protected", async () => {
const command = new DevCommand()
expect(command.protected).to.be.true
})
})
9 changes: 9 additions & 0 deletions garden-service/test/unit/src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { expect } from "chai"
import { InitCommand } from "../../../../src/commands/init"

describe("DevCommand", () => {
it("should be protected", async () => {
const command = new InitCommand()
expect(command.protected).to.be.true
})
})
5 changes: 5 additions & 0 deletions garden-service/test/unit/src/commands/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,9 @@ describe("commands.test", () => {
})
).to.be.false
})

it("should be protected", async () => {
const command = new TestCommand()
expect(command.protected).to.be.true
})
})
Loading

0 comments on commit b3f8d64

Please sign in to comment.