|
6 | 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
7 | 7 | */ |
8 | 8 |
|
9 | | -import * as execa from "execa" |
10 | | -import { safeLoad } from "js-yaml" |
11 | | -import * as Joi from "joi" |
12 | | -import { join } from "path" |
13 | | -import { GardenPlugin, PluginFactoryParams } from "../../../types/plugin/plugin" |
14 | | -import { |
15 | | - gardenPlugin as k8sPlugin, |
16 | | - KubernetesBaseConfig, |
17 | | - kubernetesConfigBase, |
18 | | -} from "../kubernetes" |
19 | | -import { readFile } from "fs-extra" |
20 | | -import { homedir } from "os" |
| 9 | +import { GardenPlugin } from "../../../types/plugin/plugin" |
| 10 | +import { gardenPlugin as k8sPlugin } from "../kubernetes" |
21 | 11 | import { getLocalEnvironmentStatus, prepareLocalEnvironment } from "../init" |
22 | | -import { ConfigureProviderParams } from "../../../types/plugin/params" |
23 | | - |
24 | | -// TODO: split this into separate plugins to handle Docker for Mac and Minikube |
25 | | - |
26 | | -// note: this is in order of preference, in case neither is set as the current kubectl context |
27 | | -// and none is explicitly configured in the garden.yml |
28 | | -const supportedContexts = ["docker-for-desktop", "minikube"] |
29 | | -const kubeConfigPath = join(homedir(), ".kube", "config") |
30 | | - |
31 | | -async function getKubeConfig(): Promise<any> { |
32 | | - try { |
33 | | - return safeLoad((await readFile(kubeConfigPath)).toString()) |
34 | | - } catch { |
35 | | - return {} |
36 | | - } |
37 | | -} |
38 | | - |
39 | | -/** |
40 | | - * Automatically set docker environment variables for minikube |
41 | | - * TODO: it would be better to explicitly provide those to docker instead of using process.env |
42 | | - */ |
43 | | -async function setMinikubeDockerEnv() { |
44 | | - const minikubeEnv = await execa.stdout("minikube", ["docker-env", "--shell=bash"]) |
45 | | - for (const line of minikubeEnv.split("\n")) { |
46 | | - const matched = line.match(/^export (\w+)="(.+)"$/) |
47 | | - if (matched) { |
48 | | - process.env[matched[1]] = matched[2] |
49 | | - } |
50 | | - } |
51 | | -} |
52 | | - |
53 | | -export interface LocalKubernetesConfig extends KubernetesBaseConfig { |
54 | | - _system?: Symbol |
55 | | - setupIngressController: string | boolean | null |
56 | | -} |
57 | | - |
58 | | -export const configSchema = kubernetesConfigBase |
59 | | - .keys({ |
60 | | - namespace: Joi.string() |
61 | | - .default(undefined, "<project name>") |
62 | | - .description( |
63 | | - "Specify which namespace to deploy services to (defaults to the project name). " + |
64 | | - "Note that the framework generates other namespaces as well with this name as a prefix.", |
65 | | - ), |
66 | | - setupIngressController: Joi.string() |
67 | | - .allow("nginx", false, null) |
68 | | - .default("nginx") |
69 | | - .description("Set this to null or false to skip installing/enabling the `nginx` ingress controller."), |
70 | | - _system: Joi.any().meta({ internal: true }), |
71 | | - }) |
72 | | - .description("The provider configuration for the local-kubernetes plugin.") |
| 12 | +import { configureProvider, configSchema } from "./config" |
73 | 13 |
|
74 | 14 | export const name = "local-kubernetes" |
75 | 15 |
|
76 | | -export function gardenPlugin({ projectName, log }: PluginFactoryParams): GardenPlugin { |
| 16 | +export function gardenPlugin(): GardenPlugin { |
77 | 17 | const plugin = k8sPlugin() |
78 | 18 |
|
79 | 19 | plugin.configSchema = configSchema |
80 | 20 |
|
81 | | - plugin.actions!.configureProvider = async ({ config }: ConfigureProviderParams<LocalKubernetesConfig>) => { |
82 | | - let context = config.context |
83 | | - let defaultHostname = config.defaultHostname |
84 | | - let setupIngressController = config.setupIngressController |
85 | | - |
86 | | - if (!context) { |
87 | | - // automatically detect supported kubectl context if not explicitly configured |
88 | | - const kubeConfig = await getKubeConfig() |
89 | | - const currentContext = kubeConfig["current-context"] |
90 | | - |
91 | | - if (currentContext && supportedContexts.includes(currentContext)) { |
92 | | - // prefer current context if set and supported |
93 | | - context = currentContext |
94 | | - log.debug({ section: name, msg: `Using current context: ${context}` }) |
95 | | - } else if (kubeConfig.contexts) { |
96 | | - const availableContexts = kubeConfig.contexts.map(c => c.name) |
97 | | - |
98 | | - for (const supportedContext of supportedContexts) { |
99 | | - if (availableContexts.includes(supportedContext)) { |
100 | | - context = supportedContext |
101 | | - log.debug({ section: name, msg: `Using detected context: ${context}` }) |
102 | | - break |
103 | | - } |
104 | | - } |
105 | | - } |
106 | | - } |
107 | | - |
108 | | - if (!context) { |
109 | | - context = supportedContexts[0] |
110 | | - log.debug({ section: name, msg: `No kubectl context auto-detected, using default: ${context}` }) |
111 | | - } |
112 | | - |
113 | | - if (context === "minikube") { |
114 | | - await execa("minikube", ["config", "set", "WantUpdateNotification", "false"]) |
115 | | - |
116 | | - if (!defaultHostname) { |
117 | | - // use the nip.io service to give a hostname to the instance, if none is explicitly configured |
118 | | - const minikubeIp = await execa.stdout("minikube", ["ip"]) |
119 | | - defaultHostname = `${projectName}.${minikubeIp}.nip.io` |
120 | | - } |
121 | | - |
122 | | - if (config.setupIngressController === "nginx") { |
123 | | - log.silly("Using minikube's ingress addon") |
124 | | - await execa("minikube", ["addons", "enable", "ingress"]) |
125 | | - // make sure the prepare handler doesn't also set up the ingress controller |
126 | | - setupIngressController = false |
127 | | - } |
128 | | - |
129 | | - await setMinikubeDockerEnv() |
130 | | - |
131 | | - } else { |
132 | | - if (!defaultHostname) { |
133 | | - defaultHostname = `${projectName}.local.app.garden` |
134 | | - } |
135 | | - } |
136 | | - |
137 | | - config = { |
138 | | - name: config.name, |
139 | | - context, |
140 | | - defaultHostname, |
141 | | - deploymentRegistry: { |
142 | | - hostname: "foo.garden", // this is not used by this plugin, but required by the base plugin |
143 | | - namespace: "_", |
144 | | - }, |
145 | | - forceSsl: false, |
146 | | - imagePullSecrets: config.imagePullSecrets, |
147 | | - ingressHttpPort: 80, |
148 | | - ingressHttpsPort: 443, |
149 | | - ingressClass: "nginx", |
150 | | - namespace: config.namespace || projectName, |
151 | | - setupIngressController, |
152 | | - tlsCertificates: config.tlsCertificates, |
153 | | - _system: config._system, |
154 | | - } |
155 | | - |
156 | | - return { name: config.name, config } |
157 | | - } |
| 21 | + plugin.actions!.configureProvider = configureProvider |
158 | 22 |
|
159 | 23 | // override the environment configuration steps |
160 | 24 | plugin.actions!.getEnvironmentStatus = getLocalEnvironmentStatus |
|
0 commit comments