-
Notifications
You must be signed in to change notification settings - Fork 273
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(k8s): provider-level defaults for dev mode
Excludes and permission/owner/group settings can now be set on the provider level for `kubernetes` and `local-kubernetes`. Defaults specified there will be extended/overridden by corresponding settings on individual sync specs. This helps reduce clutter when the same excludes and permission settings are commonly applied across services/modules.
- test-circleci
- edge-bonsai
- edge-acorn
- edge
- 0.13.50
- 0.13.49
- 0.13.48
- 0.13.47
- 0.13.46
- 0.13.45
- 0.13.44
- 0.13.43
- 0.13.42
- 0.13.41
- 0.13.40
- 0.13.39
- 0.13.38
- 0.13.37
- 0.13.36
- 0.13.35
- 0.13.34
- 0.13.33
- 0.13.32
- 0.13.31
- 0.13.30
- 0.13.29
- 0.13.28
- 0.13.27
- 0.13.26
- 0.13.25
- 0.13.24
- 0.13.23
- 0.13.22
- 0.13.21
- 0.13.20
- 0.13.19
- 0.13.18
- 0.13.17
- 0.13.16
- 0.13.15
- 0.13.14
- 0.13.13
- 0.13.12
- 0.13.11
- 0.13.10
- 0.13.9
- 0.13.8
- 0.13.7
- 0.13.6
- 0.13.5
- 0.13.4
- 0.13.3
- 0.13.2
- 0.13.1
- 0.13.0
- 0.13.0-1
- 0.13.0-0
- 0.12.71
- 0.12.70
- 0.12.69
- 0.12.68
- 0.12.67
- 0.12.66
- 0.12.65
- 0.12.64
- 0.12.63
- 0.12.62
- 0.12.61
- 0.12.60
- 0.12.59
- 0.12.58
- 0.12.57
- 0.12.56
- 0.12.56-1
- 0.12.56-0
- 0.12.55
- 0.12.55-0
- 0.12.54
- 0.12.54-0
- 0.12.53
- 0.12.53-0
- 0.12.52
- 0.12.52-0
- 0.12.51
- 0.12.51-0
- 0.12.50
- 0.12.49
- 0.12.49-0
- 0.12.48
- 0.12.48-0
- 0.12.47
- 0.12.47-0
- 0.12.46
- 0.12.46-0
- 0.12.45
- 0.12.45-0
- 0.12.44
- 0.12.44-0
- 0.12.43
- 0.12.43-0
- 0.12.42
- 0.12.42-0
- 0.12.41
- 0.12.41-0
- 0.12.40
- 0.12.40-0
- 0.12.39
- 0.12.39-0
- 0.12.38
- 0.12.38-0
- 0.12.37
- 0.12.37-0
- 0.12.36
- 0.12.36-1
- 0.12.36-0
- 0.12.35
- 0.12.35-0
- 0.12.34
- 0.12.34-0
- 0.12.33
- 0.12.33-777
- 0.12.33-0
- 0.12.32
- 0.12.31
- 0.12.31-2
- 0.12.31-1
- 0.12.31-0
- 0.12.30
- 0.12.30-0
- 0.12.29
- 0.12.28
- 0.12.28-1
- 0.12.28-0
- 0.12.27
- 0.12.27-0
Showing
16 changed files
with
770 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
/* | ||
* Copyright (C) 2018-2021 Garden Technologies, Inc. <info@garden.io> | ||
* | ||
* 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 { expect } from "chai" | ||
import { mkdirp, pathExists, readFile, remove, writeFile } from "fs-extra" | ||
import { join } from "path" | ||
import { ConfigGraph } from "../../../../../src/config-graph" | ||
import { Garden } from "../../../../../src/garden" | ||
import { LogEntry } from "../../../../../src/logger/log-entry" | ||
import { ContainerService } from "../../../../../src/plugins/container/config" | ||
import { KubernetesPluginContext, KubernetesProvider } from "../../../../../src/plugins/kubernetes/config" | ||
import { getContainerServiceStatus } from "../../../../../src/plugins/kubernetes/container/status" | ||
import { KubernetesWorkload } from "../../../../../src/plugins/kubernetes/types" | ||
import { execInWorkload } from "../../../../../src/plugins/kubernetes/util" | ||
import { emptyRuntimeContext } from "../../../../../src/runtime-context" | ||
import { DeployTask } from "../../../../../src/tasks/deploy" | ||
import { dedent } from "../../../../../src/util/string" | ||
import { sleep } from "../../../../../src/util/util" | ||
import { getContainerTestGarden } from "./container/container" | ||
|
||
describe("dev mode deployments and sync behavior", () => { | ||
let garden: Garden | ||
let graph: ConfigGraph | ||
let ctx: KubernetesPluginContext | ||
let provider: KubernetesProvider | ||
|
||
const execInPod = async (command: string[], log: LogEntry, workload: KubernetesWorkload) => { | ||
const execRes = await execInWorkload({ | ||
command, | ||
ctx, | ||
provider, | ||
log, | ||
namespace: provider.config.namespace!.name!, | ||
workload, | ||
interactive: false, | ||
}) | ||
return execRes | ||
} | ||
|
||
before(async () => { | ||
await init("local") | ||
}) | ||
|
||
beforeEach(async () => { | ||
graph = await garden.getConfigGraph({ log: garden.log, emit: false }) | ||
}) | ||
|
||
afterEach(async () => { | ||
if (garden) { | ||
await garden.close() | ||
} | ||
}) | ||
|
||
const init = async (environmentName: string) => { | ||
garden = await getContainerTestGarden(environmentName) | ||
provider = <KubernetesProvider>await garden.resolveProvider(garden.log, "local-kubernetes") | ||
ctx = <KubernetesPluginContext>await garden.getPluginContext(provider) | ||
} | ||
|
||
it("should deploy a service in dev mode and successfully set a two-way sync", async () => { | ||
await init("local") | ||
const service = graph.getService("dev-mode") | ||
const module = service.module | ||
const log = garden.log | ||
const deployTask = new DeployTask({ | ||
garden, | ||
graph, | ||
log, | ||
service, | ||
force: true, | ||
forceBuild: false, | ||
devModeServiceNames: [service.name], | ||
hotReloadServiceNames: [], | ||
}) | ||
|
||
await garden.processTasks([deployTask], { throwOnError: true }) | ||
const status = await getContainerServiceStatus({ | ||
ctx, | ||
module, | ||
service, | ||
runtimeContext: emptyRuntimeContext, | ||
log, | ||
devMode: true, | ||
hotReload: false, | ||
}) | ||
|
||
const workload = status.detail.workload! | ||
|
||
// First, we create a file locally and verify that it gets synced into the pod | ||
await writeFile(join(module.path, "made_locally"), "foo") | ||
await sleep(300) | ||
const execRes = await execInPod(["/bin/sh", "-c", "cat /tmp/made_locally"], log, workload) | ||
expect(execRes.output.trim()).to.eql("foo") | ||
|
||
// Then, we create a file in the pod and verify that it gets synced back | ||
await execInPod(["/bin/sh", "-c", "echo bar > /tmp/made_in_pod"], log, workload) | ||
await sleep(500) | ||
const localPath = join(module.path, "made_in_pod") | ||
expect(await pathExists(localPath)).to.eql(true) | ||
expect((await readFile(localPath)).toString().trim()).to.eql("bar") | ||
|
||
// This is to make sure that the two-way sync doesn't recreate the local files we're about to delete here. | ||
const actions = await garden.getActionRouter() | ||
await actions.deleteService({ graph, log: garden.log, service }) | ||
|
||
// Clean up the files we created locally | ||
for (const filename of ["made_locally", "made_in_pod"]) { | ||
try { | ||
await remove(join(module.path, filename)) | ||
} catch {} | ||
} | ||
}) | ||
|
||
it("should apply ignore rules from the sync spec and the provider-level dev mode defaults", async () => { | ||
await init("local") | ||
const service: ContainerService = graph.getService("dev-mode") | ||
|
||
// We want to ignore the following directories (all at module root) | ||
// somedir | ||
// prefix-a <--- matched by provider-level default excludes | ||
// nested/prefix-b <--- matched by provider-level default excludes | ||
|
||
service.spec.devMode!.sync[0].mode = "one-way-replica" | ||
service.spec.devMode!.sync[0].exclude = ["somedir"] | ||
const module = service.module | ||
const log = garden.log | ||
const deployTask = new DeployTask({ | ||
garden, | ||
graph, | ||
log, | ||
service, | ||
force: true, | ||
forceBuild: false, | ||
devModeServiceNames: [service.name], | ||
hotReloadServiceNames: [], | ||
}) | ||
|
||
await garden.processTasks([deployTask], { throwOnError: true }) | ||
const status = await getContainerServiceStatus({ | ||
ctx, | ||
module, | ||
service, | ||
runtimeContext: emptyRuntimeContext, | ||
log, | ||
devMode: true, | ||
hotReload: false, | ||
}) | ||
|
||
const workload = status.detail.workload! | ||
|
||
// First, we create a non-ignored file locally | ||
await writeFile(join(module.path, "made_locally"), "foo") | ||
|
||
// Then, we create files in each of the directories we intended to ignore in the `exclude` spec above, and | ||
// verify that they didn't get synced into the pod. | ||
await mkdirp(join(module.path, "somedir")) | ||
await writeFile(join(module.path, "somedir", "file"), "foo") | ||
await mkdirp(join(module.path, "prefix-a")) | ||
await writeFile(join(module.path, "prefix-a", "file"), "foo") | ||
await mkdirp(join(module.path, "nested", "prefix-b")) | ||
await writeFile(join(module.path, "nested", "prefix-b", "file"), "foo") | ||
await sleep(500) | ||
const ignoreExecRes = await execInPod(["/bin/sh", "-c", "ls -a /tmp /tmp/nested"], log, workload) | ||
// Clean up the files we created locally | ||
for (const filename of ["made_locally", "somedir", "prefix-a", "nested"]) { | ||
try { | ||
await remove(join(module.path, filename)) | ||
} catch {} | ||
} | ||
|
||
expect(ignoreExecRes.output.trim()).to.eql(dedent` | ||
/tmp: | ||
. | ||
.. | ||
Dockerfile | ||
garden.yml | ||
made_locally | ||
nested | ||
/tmp/nested: | ||
. | ||
.. | ||
`) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* Copyright (C) 2018-2021 Garden Technologies, Inc. <info@garden.io> | ||
* | ||
* 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 { expect } from "chai" | ||
import { builtInExcludes, makeSyncConfig } from "../../../../../src/plugins/kubernetes/dev-mode" | ||
|
||
describe("k8s dev mode helpers", () => { | ||
const localPath = "/path/to/module/src" | ||
const remoteDestination = "exec:'various fun connection parameters'" | ||
const source = "src" | ||
const target = "/app/src" | ||
describe("makeSyncConfig", () => { | ||
it("should generate a simple sync config", () => { | ||
const config = makeSyncConfig({ | ||
localPath, | ||
remoteDestination, | ||
defaults: {}, | ||
spec: { | ||
source, | ||
target, | ||
mode: "one-way", | ||
}, | ||
}) | ||
|
||
expect(config).to.eql({ | ||
alpha: localPath, | ||
beta: remoteDestination, | ||
ignore: [...builtInExcludes], | ||
mode: "one-way", | ||
defaultOwner: undefined, | ||
defaultGroup: undefined, | ||
defaultDirectoryMode: undefined, | ||
defaultFileMode: undefined, | ||
}) | ||
}) | ||
|
||
it("should apply provider-level defaults", () => { | ||
const config = makeSyncConfig({ | ||
localPath, | ||
remoteDestination, | ||
defaults: { | ||
exclude: ["**/*.log"], | ||
owner: "node", | ||
group: "admin", | ||
fileMode: 600, | ||
directoryMode: 700, | ||
}, | ||
spec: { | ||
source, | ||
target, | ||
mode: "one-way", | ||
}, | ||
}) | ||
|
||
expect(config).to.eql({ | ||
alpha: localPath, | ||
beta: remoteDestination, | ||
ignore: [...builtInExcludes, "**/*.log"], | ||
mode: "one-way", | ||
defaultOwner: "node", | ||
defaultGroup: "admin", | ||
defaultFileMode: 600, | ||
defaultDirectoryMode: 700, | ||
}) | ||
}) | ||
|
||
it("should override/extend provider-level defaults with settings on the sync spec", () => { | ||
const config = makeSyncConfig({ | ||
localPath, | ||
remoteDestination, | ||
defaults: { | ||
exclude: ["**/*.log"], | ||
owner: "node", | ||
group: "admin", | ||
fileMode: 600, | ||
directoryMode: 700, | ||
}, | ||
spec: { | ||
source, | ||
target, | ||
mode: "one-way", | ||
exclude: ["node_modules"], | ||
defaultOwner: "owner_from_spec", | ||
defaultGroup: "group_from_spec", | ||
defaultFileMode: 700, | ||
defaultDirectoryMode: 777, | ||
}, | ||
}) | ||
|
||
expect(config).to.eql({ | ||
alpha: localPath, | ||
beta: remoteDestination, | ||
ignore: [...builtInExcludes, "**/*.log", "node_modules"], | ||
mode: "one-way", | ||
defaultOwner: "owner_from_spec", | ||
defaultGroup: "group_from_spec", | ||
defaultFileMode: 700, | ||
defaultDirectoryMode: 777, | ||
}) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters