@backstage-community/plugin-scaffolder-backend-module-kubernetes 2.8.1 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ### Dependencies
2
2
 
3
+ ## 2.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - da12da9: Backstage version bump to v1.42.5
8
+
9
+ ## 2.9.0
10
+
11
+ ### Minor Changes
12
+
13
+ - f9a8eec: Backstage version bump to v1.41.1
14
+
3
15
  ## 2.8.1
4
16
 
5
17
  ### Patch Changes
@@ -2,7 +2,6 @@
2
2
 
3
3
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
4
4
  var clientNode = require('@kubernetes/client-node');
5
- var zod = require('zod');
6
5
  var createKubernetesNamespace_examples = require('./createKubernetesNamespace.examples.cjs.js');
7
6
 
8
7
  const KUBERNETES_API_URL_ANNOTATION = "kubernetes.io/api-server";
@@ -69,27 +68,19 @@ function createKubernetesNamespaceAction(catalogClient) {
69
68
  description: "Creates a kubernetes namespace",
70
69
  examples: createKubernetesNamespace_examples.examples,
71
70
  schema: {
72
- input: zod.z.object({
73
- namespace: zod.z.string().describe("Name of the namespace to be created"),
74
- token: zod.z.string().describe("Bearer token to authenticate with"),
75
- clusterRef: zod.z.string().optional().describe("Cluster resource entity reference from the catalog"),
76
- url: zod.z.string().optional().describe(
71
+ input: {
72
+ namespace: (z) => z.string().describe("Name of the namespace to be created"),
73
+ token: (z) => z.string().describe("Bearer token to authenticate with"),
74
+ clusterRef: (z) => z.string().optional().describe("Cluster resource entity reference from the catalog"),
75
+ url: (z) => z.string().optional().describe(
77
76
  "Url of the kubernetes API, will be used if clusterRef is not provided"
78
77
  ),
79
- skipTLSVerify: zod.z.boolean().optional().default(false).describe(
78
+ skipTLSVerify: (z) => z.boolean().optional().default(false).describe(
80
79
  "Skip TLS certificate verification, not recommended to use in production environment, defaults to false"
81
80
  ),
82
- caData: zod.z.string().optional().describe("Certificate Authority base64 encoded certificate"),
83
- labels: zod.z.string().optional().describe("Labels that will be applied to the namespace.")
84
- }).superRefine((data, ctx) => {
85
- if (!data.clusterRef && !data.url) {
86
- ctx.addIssue({
87
- code: zod.z.ZodIssueCode.custom,
88
- message: "Either clusterRef or url must be provided",
89
- path: ["clusterRef", "url"]
90
- });
91
- }
92
- })
81
+ caData: (z) => z.string().optional().describe("Certificate Authority base64 encoded certificate"),
82
+ labels: (z) => z.string().optional().describe("Labels that will be applied to the namespace.")
83
+ }
93
84
  },
94
85
  async handler(ctx) {
95
86
  const {
@@ -1 +1 @@
1
- {"version":3,"file":"createKubernetesNamespace.cjs.js","sources":["../../src/actions/createKubernetesNamespace.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { CatalogClient } from '@backstage/catalog-client';\nimport type { Entity } from '@backstage/catalog-model';\nimport {\n createTemplateAction,\n type ActionContext,\n} from '@backstage/plugin-scaffolder-node';\n\nimport {\n CoreV1Api,\n CoreV1ApiCreateNamespaceRequest,\n KubeConfig,\n} from '@kubernetes/client-node';\nimport { z } from 'zod';\nimport { examples } from './createKubernetesNamespace.examples';\n\nconst KUBERNETES_API_URL_ANNOTATION = 'kubernetes.io/api-server';\nconst KUBERNETES_CLUSTER_TYPE = 'kubernetes-cluster';\n\nexport interface HttpErrorBody {\n kind: string;\n apiVersion: string;\n metadata: Object;\n status: string;\n message: string;\n reason: string;\n details: { name: string; kind: string };\n code: number;\n}\n\ntype TemplateActionParameters = {\n namespace: string;\n clusterRef?: string;\n url?: string;\n token: string;\n skipTLSVerify?: boolean;\n caData?: string;\n labels?: string;\n};\n\nconst getUrlFromClusterRef = async (\n ctx: ActionContext<TemplateActionParameters>,\n catalogClient: CatalogClient,\n clusterRef: string,\n): Promise<string> => {\n const isResource = clusterRef.startsWith('resource:');\n if (!isResource) {\n ctx.logger.warn(\n 'Cluster reference in the wrong format, attempting to fix it',\n );\n }\n const catalogEntity: Entity | undefined = await catalogClient.getEntityByRef(\n isResource ? clusterRef : `resource:${clusterRef}`,\n );\n if (!catalogEntity) {\n throw new Error('Resource not found');\n }\n if (catalogEntity.spec?.type !== KUBERNETES_CLUSTER_TYPE) {\n ctx.logger.warn(`Resource is not of ${KUBERNETES_CLUSTER_TYPE} type`);\n }\n const apiUrl =\n catalogEntity.metadata?.annotations?.[KUBERNETES_API_URL_ANNOTATION];\n if (!apiUrl) {\n throw new Error(\n `Cluster resource is missing ${KUBERNETES_API_URL_ANNOTATION} annotation`,\n );\n }\n return apiUrl;\n};\n\nconst validateUrl = (url: string | undefined = '') => {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n } catch (error) {\n throw new Error(`\"${url}\" is an invalid url`);\n }\n};\n\nexport const convertLabelsToObject = (\n labelsString: string | undefined,\n): { [key: string]: string } => {\n const result: { [key: string]: string } = {};\n\n if (!labelsString || labelsString.indexOf('=') === -1) {\n console.error(\n \"Invalid label string. Label string must contain at least one label separated by '=' character.\",\n );\n return result;\n }\n\n const labelsArray = labelsString.split(';');\n\n labelsArray.forEach(label => {\n const separatorIndex = label.indexOf('=');\n if (separatorIndex !== -1) {\n const key = label.slice(0, separatorIndex).trim();\n const value = label.slice(separatorIndex + 1).trim();\n if (key && value) {\n result[key] = value;\n }\n } else {\n console.error(\n `Invalid label: '${label}'. Label must contain at least one '=' character.`,\n );\n }\n });\n\n return result;\n};\n\n/**\n * @public\n */\nexport function createKubernetesNamespaceAction(catalogClient: CatalogClient) {\n return createTemplateAction<TemplateActionParameters>({\n id: 'kubernetes:create-namespace',\n description: 'Creates a kubernetes namespace',\n examples,\n schema: {\n input: z\n .object({\n namespace: z.string().describe('Name of the namespace to be created'),\n token: z.string().describe('Bearer token to authenticate with'),\n clusterRef: z\n .string()\n .optional()\n .describe('Cluster resource entity reference from the catalog'),\n url: z\n .string()\n .optional()\n .describe(\n 'Url of the kubernetes API, will be used if clusterRef is not provided',\n ),\n skipTLSVerify: z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'Skip TLS certificate verification, not recommended to use in production environment, defaults to false',\n ),\n caData: z\n .string()\n .optional()\n .describe('Certificate Authority base64 encoded certificate'),\n labels: z\n .string()\n .optional()\n .describe('Labels that will be applied to the namespace.'),\n })\n .superRefine((data, ctx) => {\n if (!data.clusterRef && !data.url) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Either clusterRef or url must be provided',\n path: ['clusterRef', 'url'],\n });\n }\n }),\n },\n async handler(ctx) {\n const {\n namespace,\n clusterRef,\n token,\n url,\n skipTLSVerify,\n caData,\n labels,\n } = ctx.input;\n const kubeConfig = new KubeConfig();\n const name = 'backstage';\n const cluster = {\n server: '',\n name,\n serviceAccountToken: token,\n skipTLSVerify: skipTLSVerify || false,\n caData,\n };\n\n if (clusterRef && url) {\n throw new Error(\n \"Cluster reference and url can't be specified at the same time\",\n );\n }\n\n if (!clusterRef && !url) {\n throw new Error('Cluster reference or url are required');\n }\n\n if (clusterRef) {\n cluster.server = await getUrlFromClusterRef(\n ctx,\n catalogClient,\n clusterRef,\n );\n } else {\n validateUrl(url);\n cluster.server = url!;\n }\n\n kubeConfig.loadFromOptions({\n clusters: [cluster],\n users: [{ name, token }],\n contexts: [\n {\n name,\n user: name,\n cluster: name,\n },\n ],\n currentContext: name,\n });\n\n const namespaceLabels = convertLabelsToObject(labels);\n\n const api = kubeConfig.makeApiClient(CoreV1Api);\n const k8sNamespace: CoreV1ApiCreateNamespaceRequest = {\n body: {\n metadata: {\n name: namespace,\n labels: namespaceLabels,\n },\n },\n };\n await api.createNamespace(k8sNamespace).catch((e: Error) => {\n // e.body should be string or blob binary\n if ('body' in e && typeof e.body === 'string') {\n let body: HttpErrorBody | undefined;\n try {\n body = JSON.parse(e.body);\n } catch (error) {\n /* eslint-disable-line no-empty */\n }\n if (body) {\n throw new Error(\n `Failed to create kubernetes namespace, API code: ${body.code} -- ${body.message}`,\n );\n }\n }\n\n throw new Error(`Failed to create kubernetes namespace, ${e.message}`);\n });\n },\n });\n}\n"],"names":["createTemplateAction","examples","z","KubeConfig","CoreV1Api"],"mappings":"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"}
1
+ {"version":3,"file":"createKubernetesNamespace.cjs.js","sources":["../../src/actions/createKubernetesNamespace.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { CatalogClient } from '@backstage/catalog-client';\nimport type { Entity } from '@backstage/catalog-model';\nimport {\n createTemplateAction,\n type ActionContext,\n} from '@backstage/plugin-scaffolder-node';\n\nimport {\n CoreV1Api,\n CoreV1ApiCreateNamespaceRequest,\n KubeConfig,\n} from '@kubernetes/client-node';\nimport { examples } from './createKubernetesNamespace.examples';\n\nconst KUBERNETES_API_URL_ANNOTATION = 'kubernetes.io/api-server';\nconst KUBERNETES_CLUSTER_TYPE = 'kubernetes-cluster';\n\nexport interface HttpErrorBody {\n kind: string;\n apiVersion: string;\n metadata: Object;\n status: string;\n message: string;\n reason: string;\n details: { name: string; kind: string };\n code: number;\n}\n\ntype TemplateActionParameters = {\n namespace: string;\n clusterRef?: string;\n url?: string;\n token: string;\n skipTLSVerify: boolean;\n caData?: string;\n labels?: string;\n};\n\nconst getUrlFromClusterRef = async (\n ctx: ActionContext<TemplateActionParameters>,\n catalogClient: CatalogClient,\n clusterRef: string,\n): Promise<string> => {\n const isResource = clusterRef.startsWith('resource:');\n if (!isResource) {\n ctx.logger.warn(\n 'Cluster reference in the wrong format, attempting to fix it',\n );\n }\n const catalogEntity: Entity | undefined = await catalogClient.getEntityByRef(\n isResource ? clusterRef : `resource:${clusterRef}`,\n );\n if (!catalogEntity) {\n throw new Error('Resource not found');\n }\n if (catalogEntity.spec?.type !== KUBERNETES_CLUSTER_TYPE) {\n ctx.logger.warn(`Resource is not of ${KUBERNETES_CLUSTER_TYPE} type`);\n }\n const apiUrl =\n catalogEntity.metadata?.annotations?.[KUBERNETES_API_URL_ANNOTATION];\n if (!apiUrl) {\n throw new Error(\n `Cluster resource is missing ${KUBERNETES_API_URL_ANNOTATION} annotation`,\n );\n }\n return apiUrl;\n};\n\nconst validateUrl = (url: string | undefined = '') => {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n } catch (error) {\n throw new Error(`\"${url}\" is an invalid url`);\n }\n};\n\nexport const convertLabelsToObject = (\n labelsString: string | undefined,\n): { [key: string]: string } => {\n const result: { [key: string]: string } = {};\n\n if (!labelsString || labelsString.indexOf('=') === -1) {\n console.error(\n \"Invalid label string. Label string must contain at least one label separated by '=' character.\",\n );\n return result;\n }\n\n const labelsArray = labelsString.split(';');\n\n labelsArray.forEach(label => {\n const separatorIndex = label.indexOf('=');\n if (separatorIndex !== -1) {\n const key = label.slice(0, separatorIndex).trim();\n const value = label.slice(separatorIndex + 1).trim();\n if (key && value) {\n result[key] = value;\n }\n } else {\n console.error(\n `Invalid label: '${label}'. Label must contain at least one '=' character.`,\n );\n }\n });\n\n return result;\n};\n\n/**\n * @public\n */\nexport function createKubernetesNamespaceAction(catalogClient: CatalogClient) {\n return createTemplateAction({\n id: 'kubernetes:create-namespace',\n description: 'Creates a kubernetes namespace',\n examples,\n schema: {\n input: {\n namespace: z =>\n z.string().describe('Name of the namespace to be created'),\n token: z => z.string().describe('Bearer token to authenticate with'),\n clusterRef: z =>\n z\n .string()\n .optional()\n .describe('Cluster resource entity reference from the catalog'),\n url: z =>\n z\n .string()\n .optional()\n .describe(\n 'Url of the kubernetes API, will be used if clusterRef is not provided',\n ),\n skipTLSVerify: z =>\n z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'Skip TLS certificate verification, not recommended to use in production environment, defaults to false',\n ),\n caData: z =>\n z\n .string()\n .optional()\n .describe('Certificate Authority base64 encoded certificate'),\n labels: z =>\n z\n .string()\n .optional()\n .describe('Labels that will be applied to the namespace.'),\n },\n },\n async handler(ctx) {\n const {\n namespace,\n clusterRef,\n token,\n url,\n skipTLSVerify,\n caData,\n labels,\n } = ctx.input;\n const kubeConfig = new KubeConfig();\n const name = 'backstage';\n const cluster = {\n server: '',\n name,\n serviceAccountToken: token,\n skipTLSVerify: skipTLSVerify || false,\n caData,\n };\n\n if (clusterRef && url) {\n throw new Error(\n \"Cluster reference and url can't be specified at the same time\",\n );\n }\n\n if (!clusterRef && !url) {\n throw new Error('Cluster reference or url are required');\n }\n\n if (clusterRef) {\n cluster.server = await getUrlFromClusterRef(\n ctx,\n catalogClient,\n clusterRef,\n );\n } else {\n validateUrl(url);\n cluster.server = url!;\n }\n\n kubeConfig.loadFromOptions({\n clusters: [cluster],\n users: [{ name, token }],\n contexts: [\n {\n name,\n user: name,\n cluster: name,\n },\n ],\n currentContext: name,\n });\n\n const namespaceLabels = convertLabelsToObject(labels);\n\n const api = kubeConfig.makeApiClient(CoreV1Api);\n const k8sNamespace: CoreV1ApiCreateNamespaceRequest = {\n body: {\n metadata: {\n name: namespace,\n labels: namespaceLabels,\n },\n },\n };\n await api.createNamespace(k8sNamespace).catch((e: Error) => {\n // e.body should be string or blob binary\n if ('body' in e && typeof e.body === 'string') {\n let body: HttpErrorBody | undefined;\n try {\n body = JSON.parse(e.body);\n } catch (error) {\n /* eslint-disable-line no-empty */\n }\n if (body) {\n throw new Error(\n `Failed to create kubernetes namespace, API code: ${body.code} -- ${body.message}`,\n );\n }\n }\n\n throw new Error(`Failed to create kubernetes namespace, ${e.message}`);\n });\n },\n });\n}\n"],"names":["createTemplateAction","examples","KubeConfig","CoreV1Api"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,7 +5,17 @@ import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
5
5
  /**
6
6
  * @public
7
7
  */
8
- declare function createKubernetesNamespaceAction(catalogClient: CatalogClient): _backstage_plugin_scaffolder_node.TemplateAction<any, any, "v1">;
8
+ declare function createKubernetesNamespaceAction(catalogClient: CatalogClient): _backstage_plugin_scaffolder_node.TemplateAction<{
9
+ namespace: string;
10
+ token: string;
11
+ skipTLSVerify: boolean;
12
+ clusterRef?: string | undefined;
13
+ url?: string | undefined;
14
+ caData?: string | undefined;
15
+ labels?: string | undefined;
16
+ }, {
17
+ [x: string]: any;
18
+ }, "v2">;
9
19
 
10
20
  /**
11
21
  * @public
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage-community/plugin-scaffolder-backend-module-kubernetes",
3
3
  "description": "The kubernetes module for @backstage/plugin-scaffolder-backend",
4
- "version": "2.8.1",
4
+ "version": "2.10.0",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -46,17 +46,16 @@
46
46
  "postpack": "backstage-cli package postpack"
47
47
  },
48
48
  "dependencies": {
49
- "@backstage/backend-plugin-api": "^1.3.1",
50
- "@backstage/catalog-client": "^1.10.0",
51
- "@backstage/plugin-scaffolder-node": "^0.8.2",
49
+ "@backstage/backend-plugin-api": "^1.4.2",
50
+ "@backstage/catalog-client": "^1.11.0",
51
+ "@backstage/plugin-scaffolder-node": "^0.11.0",
52
52
  "@kubernetes/client-node": "1.0.0-rc7",
53
- "yaml": "^2.0.0",
54
- "zod": "^3.22.4"
53
+ "yaml": "^2.0.0"
55
54
  },
56
55
  "devDependencies": {
57
- "@backstage/catalog-model": "^1.7.4",
58
- "@backstage/cli": "^0.32.1",
59
- "@backstage/plugin-scaffolder-node-test-utils": "^0.2.2",
56
+ "@backstage/catalog-model": "^1.7.5",
57
+ "@backstage/cli": "^0.34.1",
58
+ "@backstage/plugin-scaffolder-node-test-utils": "^0.3.2",
60
59
  "msw": "1.3.5"
61
60
  },
62
61
  "files": [