From 73f48bf62c13937313a5cfeb33ba73a86a6707f4 Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Thu, 7 Mar 2019 22:49:39 +0100 Subject: [PATCH] fix(k8s): handle CRDs properly --- garden-service/package-lock.json | 85 ++++++++++++++----- garden-service/package.json | 2 + garden-service/src/plugins/kubernetes/api.ts | 21 +++-- .../src/plugins/kubernetes/helm/common.ts | 24 +++--- .../src/plugins/kubernetes/helm/status.ts | 1 + .../src/plugins/kubernetes/status.ts | 2 +- 6 files changed, 94 insertions(+), 41 deletions(-) diff --git a/garden-service/package-lock.json b/garden-service/package-lock.json index ad75f6219d..8c5f4e9065 100644 --- a/garden-service/package-lock.json +++ b/garden-service/package-lock.json @@ -439,6 +439,12 @@ "@types/node": "*" } }, + "@types/caseless": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz", + "integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A==", + "dev": true + }, "@types/chai": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", @@ -565,6 +571,15 @@ "integrity": "sha512-mQjDxyOM1Cpocd+vm1kZBP7smwKZ4TNokFeds9LV7OZibmPJFEzY3+xZMrKfUdNT71lv8GoCPD6upKwHxubClw==", "dev": true }, + "@types/form-data": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", + "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/fs-extra": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", @@ -843,6 +858,18 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz", "integrity": "sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw==" }, + "@types/request": { + "version": "2.48.1", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.1.tgz", + "integrity": "sha512-ZgEZ1TiD+KGA9LiAAPPJL68Id2UWfeSO62ijSXZjFJArVV+2pKcsVHmrcu+1oiE3q6eDGiFiSolRc4JHoerBBg==", + "dev": true, + "requires": { + "@types/caseless": "*", + "@types/form-data": "*", + "@types/node": "*", + "@types/tough-cookie": "*" + } + }, "@types/rx": { "version": "4.1.1", "resolved": "http://registry.npmjs.org/@types/rx/-/rx-4.1.1.tgz", @@ -1036,6 +1063,12 @@ "@types/node": "*" } }, + "@types/tough-cookie": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz", + "integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==", + "dev": true + }, "@types/undertaker": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.0.tgz", @@ -1163,14 +1196,14 @@ } }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "amdefine": { @@ -3527,9 +3560,9 @@ } }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -5104,11 +5137,11 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "requires": { - "ajv": "^5.3.0", + "ajv": "^6.5.5", "har-schema": "^2.0.0" } }, @@ -5967,9 +6000,9 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify": { "version": "1.0.1", @@ -9329,9 +9362,9 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" }, "pump": { "version": "1.0.3", @@ -10780,9 +10813,9 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -11792,6 +11825,14 @@ "xdg-basedir": "^3.0.0" } }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, "urijs": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.1.tgz", diff --git a/garden-service/package.json b/garden-service/package.json index cc121dc468..ef36e78526 100644 --- a/garden-service/package.json +++ b/garden-service/package.json @@ -73,6 +73,7 @@ "normalize-url": "^4.1.0", "p-queue": "^3.0.0", "path-is-inside": "^1.0.2", + "request": "^2.88.0", "split": "^1.0.1", "string-width": "^3.0.0", "strip-ansi": "^5.0.0", @@ -129,6 +130,7 @@ "@types/p-queue": "^3.0.0", "@types/path-is-inside": "^1.0.0", "@types/prettyjson": "0.0.28", + "@types/request": "^2.48.1", "@types/string-width": "^2.0.0", "@types/supertest": "^2.0.7", "@types/tar": "^4.0.0", diff --git a/garden-service/src/plugins/kubernetes/api.ts b/garden-service/src/plugins/kubernetes/api.ts index 7865fbfa6e..222f679ba8 100644 --- a/garden-service/src/plugins/kubernetes/api.ts +++ b/garden-service/src/plugins/kubernetes/api.ts @@ -17,10 +17,11 @@ import { Policy_v1beta1Api, } from "@kubernetes/client-node" import { join } from "path" +import request = require("request") import { readFileSync, pathExistsSync } from "fs-extra" import { safeLoad } from "js-yaml" import { zip, omitBy, isObject } from "lodash" -import { GardenBaseError, ConfigurationError } from "../../exceptions" +import { GardenBaseError } from "../../exceptions" import { homedir } from "os" import { KubernetesProvider } from "./kubernetes" import { KubernetesResource } from "./types" @@ -72,6 +73,7 @@ export class KubernetesError extends GardenBaseError { export class KubeApi { public context: string + private config: KubeConfig public apiExtensions: Apiextensions_v1beta1Api public apps: Apps_v1Api @@ -82,11 +84,11 @@ export class KubeApi { constructor(public provider: KubernetesProvider) { this.context = provider.config.context - const config = getConfig(this.context) + this.config = getConfig(this.context) for (const [name, cls] of Object.entries(apiTypes)) { - const api = new cls(config.getCurrentCluster()!.server) - this[name] = this.proxyApi(api, config) + const api = new cls(this.config.getCurrentCluster()!.server) + this[name] = this.proxyApi(api, this.config) } } @@ -140,9 +142,14 @@ export class KubeApi { case "PodDisruptionBudget": return this.policy.readNamespacedPodDisruptionBudget(name, namespace) default: - throw new ConfigurationError(`Unsupported Kubernetes spec kind: ${spec.kind}`, { - spec, - }) + const apiVersion = spec.apiVersion + const url = `${this.config.getCurrentCluster()!.server}/apis/${apiVersion}` + + `/namespaces/${namespace}/${spec.kind.toLowerCase()}/${name || spec.metadata.name}` + + const opts: request.Options = { method: "get", url, json: true } + this.config.applyToRequest(opts) + + return request(opts) } } diff --git a/garden-service/src/plugins/kubernetes/helm/common.ts b/garden-service/src/plugins/kubernetes/helm/common.ts index 8a4c46eb5b..6222663784 100644 --- a/garden-service/src/plugins/kubernetes/helm/common.ts +++ b/garden-service/src/plugins/kubernetes/helm/common.ts @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { find, isEmpty } from "lodash" +import { find, isEmpty, isPlainObject } from "lodash" import { join } from "path" import { pathExists, writeFile, remove } from "fs-extra" import cryptoRandomString = require("crypto-random-string") @@ -54,10 +54,6 @@ export async function getChartResources(ctx: PluginContext, module: Module, log: return objects .filter(obj => { - if (obj === null) { - return false - } - const helmHook = getAnnotation(obj, "helm.sh/hook") if (helmHook && helmHook.startsWith("test-")) { return false @@ -65,12 +61,6 @@ export async function getChartResources(ctx: PluginContext, module: Module, log: return true }) - .map((obj) => { - if (!obj.metadata.annotations) { - obj.metadata.annotations = {} - } - return obj - }) } /** @@ -310,4 +300,16 @@ async function renderHelmTemplateString( */ function loadTemplate(template: string) { return loadAll(template, undefined, { json: true }) + .filter(obj => obj !== null) + .map((obj) => { + if (isPlainObject(obj)) { + if (!obj.metadata) { + obj.metadata = {} + } + if (!obj.metadata.annotations) { + obj.metadata.annotations = {} + } + } + return obj + }) } diff --git a/garden-service/src/plugins/kubernetes/helm/status.ts b/garden-service/src/plugins/kubernetes/helm/status.ts index d22bbf3850..0e3641cefb 100644 --- a/garden-service/src/plugins/kubernetes/helm/status.ts +++ b/garden-service/src/plugins/kubernetes/helm/status.ts @@ -74,6 +74,7 @@ export async function getReleaseStatus( namespace: string, context: string, releaseName: string, log: LogEntry, ): Promise { try { + log.silly(`Getting the release status for ${releaseName}`) const res = JSON.parse(await helm(namespace, context, log, "status", releaseName, "--output", "json")) const statusCode = res.info.status.code return { diff --git a/garden-service/src/plugins/kubernetes/status.ts b/garden-service/src/plugins/kubernetes/status.ts index 9be2890f5e..48226caf2b 100644 --- a/garden-service/src/plugins/kubernetes/status.ts +++ b/garden-service/src/plugins/kubernetes/status.ts @@ -526,7 +526,7 @@ async function getDeployedObject( try { const res = await api.readBySpec(namespace, obj) - return res.body + return res.body } catch (err) { if (err.code === 404) { return null