@alchemy.run/kubernetes 0.0.0 → 2.0.0-beta.85
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/LICENSE +201 -0
- package/README.md +41 -4
- package/lib/BuiltinAdapters.d.ts +43 -0
- package/lib/BuiltinAdapters.d.ts.map +1 -0
- package/lib/BuiltinAdapters.js +129 -0
- package/lib/BuiltinAdapters.js.map +1 -0
- package/lib/Client.d.ts +97 -0
- package/lib/Client.d.ts.map +1 -0
- package/lib/Client.js +312 -0
- package/lib/Client.js.map +1 -0
- package/lib/ClusterAdapter.d.ts +324 -0
- package/lib/ClusterAdapter.d.ts.map +1 -0
- package/lib/ClusterAdapter.js +65 -0
- package/lib/ClusterAdapter.js.map +1 -0
- package/lib/Connection.d.ts +210 -0
- package/lib/Connection.d.ts.map +1 -0
- package/lib/Connection.js +58 -0
- package/lib/Connection.js.map +1 -0
- package/lib/Deployment.d.ts +401 -0
- package/lib/Deployment.d.ts.map +1 -0
- package/lib/Deployment.js +550 -0
- package/lib/Deployment.js.map +1 -0
- package/lib/HelmChart.d.ts +147 -0
- package/lib/HelmChart.d.ts.map +1 -0
- package/lib/HelmChart.js +248 -0
- package/lib/HelmChart.js.map +1 -0
- package/lib/Job.d.ts +333 -0
- package/lib/Job.d.ts.map +1 -0
- package/lib/Job.js +443 -0
- package/lib/Job.js.map +1 -0
- package/lib/LocalCluster.d.ts +243 -0
- package/lib/LocalCluster.d.ts.map +1 -0
- package/lib/LocalCluster.js +359 -0
- package/lib/LocalCluster.js.map +1 -0
- package/lib/Manifest.d.ts +157 -0
- package/lib/Manifest.d.ts.map +1 -0
- package/lib/Manifest.js +205 -0
- package/lib/Manifest.js.map +1 -0
- package/lib/Objects.d.ts +60 -0
- package/lib/Objects.d.ts.map +1 -0
- package/lib/Objects.js +132 -0
- package/lib/Objects.js.map +1 -0
- package/lib/Providers.d.ts +24 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +36 -0
- package/lib/Providers.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +10 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/declared.d.ts +19 -0
- package/lib/internal/declared.d.ts.map +1 -0
- package/lib/internal/declared.js +435 -0
- package/lib/internal/declared.js.map +1 -0
- package/lib/internal/helm.d.ts +65 -0
- package/lib/internal/helm.d.ts.map +1 -0
- package/lib/internal/helm.js +173 -0
- package/lib/internal/helm.js.map +1 -0
- package/lib/internal/kind.d.ts +17 -0
- package/lib/internal/kind.d.ts.map +1 -0
- package/lib/internal/kind.js +31 -0
- package/lib/internal/kind.js.map +1 -0
- package/lib/internal/kubeconfig.d.ts +79 -0
- package/lib/internal/kubeconfig.d.ts.map +1 -0
- package/lib/internal/kubeconfig.js +222 -0
- package/lib/internal/kubeconfig.js.map +1 -0
- package/lib/internal/registry.d.ts +44 -0
- package/lib/internal/registry.d.ts.map +1 -0
- package/lib/internal/registry.js +72 -0
- package/lib/internal/registry.js.map +1 -0
- package/lib/internal/workload.d.ts +127 -0
- package/lib/internal/workload.d.ts.map +1 -0
- package/lib/internal/workload.js +411 -0
- package/lib/internal/workload.js.map +1 -0
- package/package.json +55 -3
- package/src/BuiltinAdapters.ts +202 -0
- package/src/Client.ts +496 -0
- package/src/ClusterAdapter.ts +373 -0
- package/src/Connection.ts +234 -0
- package/src/Deployment.ts +872 -0
- package/src/HelmChart.ts +388 -0
- package/src/Job.ts +709 -0
- package/src/LocalCluster.ts +631 -0
- package/src/Manifest.ts +301 -0
- package/src/Objects.ts +213 -0
- package/src/Providers.ts +52 -0
- package/src/globals.d.ts +2 -0
- package/src/index.ts +9 -0
- package/src/internal/declared.ts +471 -0
- package/src/internal/helm.ts +245 -0
- package/src/internal/kind.ts +43 -0
- package/src/internal/kubeconfig.ts +364 -0
- package/src/internal/registry.ts +108 -0
- package/src/internal/workload.ts +504 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import * as Provider from "alchemy/Provider";
|
|
2
|
+
import { Resource } from "alchemy/Resource";
|
|
3
|
+
import * as FileSystem from "effect/FileSystem";
|
|
4
|
+
import { type ClusterLike, type Connection } from "./Connection.ts";
|
|
5
|
+
import { type KubernetesObjectRef } from "./Objects.ts";
|
|
6
|
+
import type { Providers } from "./Providers.ts";
|
|
7
|
+
export interface HelmChartProps {
|
|
8
|
+
/**
|
|
9
|
+
* Target cluster the chart's objects are applied onto. Pass a managed
|
|
10
|
+
* cluster resource (e.g. `AWS.EKS.Cluster`), a
|
|
11
|
+
* `Kubernetes.KubeConfig(...)`, or a raw `Kubernetes.Connection`.
|
|
12
|
+
*/
|
|
13
|
+
cluster: ClusterLike;
|
|
14
|
+
/**
|
|
15
|
+
* Chart reference: a repository chart name (used with {@link repo}, e.g.
|
|
16
|
+
* `"ingress-nginx"`), an `oci://` registry reference, or a local chart
|
|
17
|
+
* directory path.
|
|
18
|
+
*/
|
|
19
|
+
chart: string;
|
|
20
|
+
/**
|
|
21
|
+
* Classic chart repository URL, e.g.
|
|
22
|
+
* `https://kubernetes.github.io/ingress-nginx`. Not needed for `oci://`
|
|
23
|
+
* references or local chart directories.
|
|
24
|
+
*/
|
|
25
|
+
repo?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Chart version to render. Pin this for repository/OCI charts — without
|
|
28
|
+
* it, helm resolves the latest version at each deploy and the rendered
|
|
29
|
+
* objects can drift between runs. Ignored for local chart directories.
|
|
30
|
+
*/
|
|
31
|
+
version?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Helm release name the chart's templates render with
|
|
34
|
+
* (`.Release.Name`). If omitted, a deterministic name is derived from
|
|
35
|
+
* the stack, stage, and logical ID.
|
|
36
|
+
*/
|
|
37
|
+
releaseName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Kubernetes namespace the objects are rendered into
|
|
40
|
+
* (`.Release.Namespace`; also injected as `metadata.namespace` on
|
|
41
|
+
* namespaced objects the chart leaves namespace-less). The namespace
|
|
42
|
+
* must already exist unless {@link createNamespace} is set.
|
|
43
|
+
* @default "default"
|
|
44
|
+
*/
|
|
45
|
+
namespace?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Values passed to the chart — a literal object, the same shape as a
|
|
48
|
+
* `values.yaml` file.
|
|
49
|
+
*/
|
|
50
|
+
values?: Record<string, unknown>;
|
|
51
|
+
/**
|
|
52
|
+
* Render objects from the chart's `crds/` directory too.
|
|
53
|
+
* @default true
|
|
54
|
+
*/
|
|
55
|
+
includeCrds?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Create the target Namespace and track it while this flag stays on.
|
|
58
|
+
* Turning it off leaves the Namespace in the cluster.
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
createNamespace?: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface HelmChart extends Resource<"Kubernetes.HelmChart", HelmChartProps, {
|
|
64
|
+
/** The connection of the cluster the chart is applied to. */
|
|
65
|
+
connection: Connection;
|
|
66
|
+
/** The Helm release name the chart rendered with. */
|
|
67
|
+
releaseName: string;
|
|
68
|
+
/** The namespace the chart rendered into. */
|
|
69
|
+
namespace: string;
|
|
70
|
+
/** The chart reference that was rendered. */
|
|
71
|
+
chart: string;
|
|
72
|
+
/** The pinned chart version, when one was declared. */
|
|
73
|
+
version: string | undefined;
|
|
74
|
+
/** References to the applied Kubernetes objects. */
|
|
75
|
+
objects: KubernetesObjectRef[];
|
|
76
|
+
/** Content hash of the chart inputs (and local chart files). */
|
|
77
|
+
code: {
|
|
78
|
+
hash: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Set by `read` when an applied object is missing or its fingerprint
|
|
82
|
+
* changed. Reconcile does not persist it; the extra field is what
|
|
83
|
+
* `alchemy drift` compares.
|
|
84
|
+
*/
|
|
85
|
+
observedHash?: string;
|
|
86
|
+
}, {}, Providers> {
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Renders a Helm chart and converges its objects onto any Kubernetes
|
|
90
|
+
* cluster via server-side apply.
|
|
91
|
+
*
|
|
92
|
+
* The chart is rendered locally with the `helm` CLI (`helm template` —
|
|
93
|
+
* install helm on the deploying machine, like Docker for image builds);
|
|
94
|
+
* the rendered objects then flow through the same apply machinery as
|
|
95
|
+
* `Kubernetes.Manifest`: Alchemy owns the object lifecycle, re-applies the
|
|
96
|
+
* full render whenever the chart's inputs change, prunes objects that drop
|
|
97
|
+
* out of the render, and deletes everything on destroy. There is no
|
|
98
|
+
* in-cluster Helm release record; the target `cluster` can be a managed
|
|
99
|
+
* cluster resource (e.g. `AWS.EKS.Cluster`) or any cluster your kubeconfig
|
|
100
|
+
* can reach.
|
|
101
|
+
*
|
|
102
|
+
* Helm lifecycle hooks (`helm.sh/hook`-annotated objects: install/upgrade/
|
|
103
|
+
* delete hooks, tests) are neither executed nor applied — the chart is
|
|
104
|
+
* rendered with `--no-hooks`, so they never enter the managed-object graph.
|
|
105
|
+
* Charts that depend on hooks for correctness should be installed with Helm
|
|
106
|
+
* directly.
|
|
107
|
+
* ### Installing a Chart
|
|
108
|
+
* **Example:** Chart from a repository
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const ingress = yield* Kubernetes.HelmChart("IngressNginx", {
|
|
111
|
+
* cluster,
|
|
112
|
+
* chart: "ingress-nginx",
|
|
113
|
+
* repo: "https://kubernetes.github.io/ingress-nginx",
|
|
114
|
+
* version: "4.11.2",
|
|
115
|
+
* namespace: "ingress-nginx",
|
|
116
|
+
* createNamespace: true,
|
|
117
|
+
* values: {
|
|
118
|
+
* controller: { replicaCount: 2 },
|
|
119
|
+
* },
|
|
120
|
+
* });
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* **Example:** OCI chart
|
|
124
|
+
* ```typescript
|
|
125
|
+
* const karpenter = yield* Kubernetes.HelmChart("Karpenter", {
|
|
126
|
+
* cluster,
|
|
127
|
+
* chart: "oci://public.ecr.aws/karpenter/karpenter",
|
|
128
|
+
* version: "1.0.6",
|
|
129
|
+
* namespace: "kube-system",
|
|
130
|
+
* });
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* **Example:** Local chart directory
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const app = yield* Kubernetes.HelmChart("App", {
|
|
136
|
+
* cluster,
|
|
137
|
+
* chart: "./charts/app",
|
|
138
|
+
* values: { image: { tag: "v1.2.3" } },
|
|
139
|
+
* });
|
|
140
|
+
* ```
|
|
141
|
+
*
|
|
142
|
+
* @resource
|
|
143
|
+
* @product Helm
|
|
144
|
+
*/
|
|
145
|
+
export declare const HelmChart: import("alchemy/Resource").ResourceClass<HelmChart>;
|
|
146
|
+
export declare const HelmChartProvider: () => import("effect/Layer").Layer<Provider.Provider<HelmChart>, never, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | import("effect/Path").Path | import("alchemy/Stack").Stack | import("alchemy/Stage").Stage>;
|
|
147
|
+
//# sourceMappingURL=HelmChart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HelmChart.d.ts","sourceRoot":"","sources":["../src/HelmChart.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAI5C,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAUhD,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAIlF,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,OAAO,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ,CACzC,sBAAsB,EACtB,cAAc,EACd;IACE,6DAA6D;IAC7D,UAAU,EAAE,UAAU,CAAC;IACvB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,oDAAoD;IACpD,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,gEAAgE;IAChE,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,EACD,EAAE,EACF,SAAS,CACV;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,eAAO,MAAM,SAAS,qDAEpB,CAAC;AA0FH,eAAO,MAAM,iBAAiB,gQAyH3B,CAAC"}
|
package/lib/HelmChart.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { hashDirectory } from "alchemy/Command/Memo";
|
|
2
|
+
import { isResolved } from "alchemy/Diff";
|
|
3
|
+
import { createPhysicalName } from "alchemy/PhysicalName";
|
|
4
|
+
import * as Provider from "alchemy/Provider";
|
|
5
|
+
import { Resource } from "alchemy/Resource";
|
|
6
|
+
import { collectRedactedSecrets } from "alchemy/Util/Redaction";
|
|
7
|
+
import { sha256Object } from "alchemy/Util/sha256";
|
|
8
|
+
import * as Effect from "effect/Effect";
|
|
9
|
+
import * as FileSystem from "effect/FileSystem";
|
|
10
|
+
import { connectCluster, deleteObjects, ifClusterExists, readObject, reconcileObjects, resolveKindSpec, } from "./Client.js";
|
|
11
|
+
import { toConnection } from "./Connection.js";
|
|
12
|
+
import { hashDriftSelection } from "./internal/declared.js";
|
|
13
|
+
import { renderHelmChart } from "./internal/helm.js";
|
|
14
|
+
import { connectionIdentity, connectionOfOutput, tryConnectionOf } from "./internal/workload.js";
|
|
15
|
+
import { kubernetesObjectKey, } from "./Objects.js";
|
|
16
|
+
/**
|
|
17
|
+
* Renders a Helm chart and converges its objects onto any Kubernetes
|
|
18
|
+
* cluster via server-side apply.
|
|
19
|
+
*
|
|
20
|
+
* The chart is rendered locally with the `helm` CLI (`helm template` —
|
|
21
|
+
* install helm on the deploying machine, like Docker for image builds);
|
|
22
|
+
* the rendered objects then flow through the same apply machinery as
|
|
23
|
+
* `Kubernetes.Manifest`: Alchemy owns the object lifecycle, re-applies the
|
|
24
|
+
* full render whenever the chart's inputs change, prunes objects that drop
|
|
25
|
+
* out of the render, and deletes everything on destroy. There is no
|
|
26
|
+
* in-cluster Helm release record; the target `cluster` can be a managed
|
|
27
|
+
* cluster resource (e.g. `AWS.EKS.Cluster`) or any cluster your kubeconfig
|
|
28
|
+
* can reach.
|
|
29
|
+
*
|
|
30
|
+
* Helm lifecycle hooks (`helm.sh/hook`-annotated objects: install/upgrade/
|
|
31
|
+
* delete hooks, tests) are neither executed nor applied — the chart is
|
|
32
|
+
* rendered with `--no-hooks`, so they never enter the managed-object graph.
|
|
33
|
+
* Charts that depend on hooks for correctness should be installed with Helm
|
|
34
|
+
* directly.
|
|
35
|
+
* ### Installing a Chart
|
|
36
|
+
* **Example:** Chart from a repository
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const ingress = yield* Kubernetes.HelmChart("IngressNginx", {
|
|
39
|
+
* cluster,
|
|
40
|
+
* chart: "ingress-nginx",
|
|
41
|
+
* repo: "https://kubernetes.github.io/ingress-nginx",
|
|
42
|
+
* version: "4.11.2",
|
|
43
|
+
* namespace: "ingress-nginx",
|
|
44
|
+
* createNamespace: true,
|
|
45
|
+
* values: {
|
|
46
|
+
* controller: { replicaCount: 2 },
|
|
47
|
+
* },
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* **Example:** OCI chart
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const karpenter = yield* Kubernetes.HelmChart("Karpenter", {
|
|
54
|
+
* cluster,
|
|
55
|
+
* chart: "oci://public.ecr.aws/karpenter/karpenter",
|
|
56
|
+
* version: "1.0.6",
|
|
57
|
+
* namespace: "kube-system",
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* **Example:** Local chart directory
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const app = yield* Kubernetes.HelmChart("App", {
|
|
64
|
+
* cluster,
|
|
65
|
+
* chart: "./charts/app",
|
|
66
|
+
* values: { image: { tag: "v1.2.3" } },
|
|
67
|
+
* });
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @resource
|
|
71
|
+
* @product Helm
|
|
72
|
+
*/
|
|
73
|
+
export const HelmChart = Resource("Kubernetes.HelmChart", {
|
|
74
|
+
aliases: ["AWS.EKS.HelmChart"],
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* Hash the chart identity: every render input, plus the chart directory's
|
|
78
|
+
* content hash when `chart` is a local path (so editing a local chart is
|
|
79
|
+
* visible to `diff` even though no prop changed).
|
|
80
|
+
*/
|
|
81
|
+
const computeChartHash = Effect.fn(function* (news, releaseName) {
|
|
82
|
+
const fs = yield* FileSystem.FileSystem;
|
|
83
|
+
const isLocalDir = !news.chart.startsWith("oci://") && (yield* fs.exists(news.chart));
|
|
84
|
+
return yield* sha256Object({
|
|
85
|
+
chart: news.chart,
|
|
86
|
+
repo: news.repo,
|
|
87
|
+
version: news.version,
|
|
88
|
+
releaseName,
|
|
89
|
+
namespace: news.namespace ?? "default",
|
|
90
|
+
values: news.values,
|
|
91
|
+
includeCrds: news.includeCrds ?? true,
|
|
92
|
+
createNamespace: news.createNamespace ?? false,
|
|
93
|
+
localChart: isLocalDir ? yield* hashDirectory({ cwd: news.chart }) : undefined,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
const resolveReleaseName = (id, news, output) => Effect.suspend(() => {
|
|
97
|
+
if (news.releaseName)
|
|
98
|
+
return Effect.succeed(news.releaseName);
|
|
99
|
+
if (output?.releaseName)
|
|
100
|
+
return Effect.succeed(output.releaseName);
|
|
101
|
+
// Helm rejects release names longer than 53 characters.
|
|
102
|
+
return createPhysicalName({ id, maxLength: 53, lowercase: true });
|
|
103
|
+
});
|
|
104
|
+
/**
|
|
105
|
+
* Charts commonly omit `metadata.namespace` and rely on the install
|
|
106
|
+
* namespace. Server-side apply addresses objects by explicit path, so
|
|
107
|
+
* inject the target namespace into namespaced objects that omit it
|
|
108
|
+
* (resolving each kind's scope; cluster-scoped objects pass through).
|
|
109
|
+
*/
|
|
110
|
+
const injectNamespace = Effect.fn(function* (transport, objects, namespace) {
|
|
111
|
+
return yield* Effect.forEach(objects, (object) => Effect.gen(function* () {
|
|
112
|
+
if (object.metadata.namespace !== undefined)
|
|
113
|
+
return object;
|
|
114
|
+
const spec = yield* resolveKindSpec({ transport, input: object });
|
|
115
|
+
if (spec.scope === "Cluster")
|
|
116
|
+
return object;
|
|
117
|
+
return {
|
|
118
|
+
...object,
|
|
119
|
+
metadata: { ...object.metadata, namespace },
|
|
120
|
+
};
|
|
121
|
+
}));
|
|
122
|
+
});
|
|
123
|
+
const chartObjects = Effect.fn(function* (transport, props, releaseName) {
|
|
124
|
+
const namespace = props.namespace ?? "default";
|
|
125
|
+
const redactions = props.values === undefined ? [] : collectRedactedSecrets(props.values);
|
|
126
|
+
const rendered = yield* renderHelmChart({
|
|
127
|
+
chart: props.chart,
|
|
128
|
+
repo: props.repo,
|
|
129
|
+
version: props.version,
|
|
130
|
+
releaseName,
|
|
131
|
+
namespace,
|
|
132
|
+
values: props.values,
|
|
133
|
+
includeCrds: props.includeCrds,
|
|
134
|
+
});
|
|
135
|
+
const placed = yield* injectNamespace(transport, rendered, namespace);
|
|
136
|
+
const objects = props.createNamespace && namespace !== "default"
|
|
137
|
+
? [
|
|
138
|
+
{
|
|
139
|
+
apiVersion: "v1",
|
|
140
|
+
kind: "Namespace",
|
|
141
|
+
metadata: { name: namespace },
|
|
142
|
+
},
|
|
143
|
+
...placed,
|
|
144
|
+
]
|
|
145
|
+
: placed;
|
|
146
|
+
return { objects, redactions };
|
|
147
|
+
});
|
|
148
|
+
export const HelmChartProvider = () => Provider.effect(HelmChart, Effect.gen(function* () {
|
|
149
|
+
return {
|
|
150
|
+
stables: ["connection", "releaseName", "namespace"],
|
|
151
|
+
// In-cluster objects have no cloud-side enumeration that attributes
|
|
152
|
+
// them to alchemy; refresh happens per-instance through `read`.
|
|
153
|
+
list: () => Effect.succeed([]),
|
|
154
|
+
diff: Effect.fn(function* ({ id, olds, news, output }) {
|
|
155
|
+
if (!isResolved(news))
|
|
156
|
+
return;
|
|
157
|
+
const releaseName = yield* resolveReleaseName(id, news, output);
|
|
158
|
+
const oldCluster = connectionIdentity(tryConnectionOf(olds?.cluster));
|
|
159
|
+
const newCluster = connectionIdentity(tryConnectionOf(news.cluster));
|
|
160
|
+
// Object identity is the (cluster, release, namespace) triple —
|
|
161
|
+
// moving any of it means a different set of objects.
|
|
162
|
+
if (output &&
|
|
163
|
+
((oldCluster !== undefined && newCluster !== undefined && oldCluster !== newCluster) ||
|
|
164
|
+
output.releaseName !== releaseName ||
|
|
165
|
+
output.namespace !== (news.namespace ?? "default"))) {
|
|
166
|
+
return { action: "replace" };
|
|
167
|
+
}
|
|
168
|
+
if (output) {
|
|
169
|
+
const hash = yield* computeChartHash(news, releaseName);
|
|
170
|
+
if (hash !== output.code.hash) {
|
|
171
|
+
return { action: "update" };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}),
|
|
175
|
+
reconcile: Effect.fn(function* ({ id, news, olds, output, session }) {
|
|
176
|
+
const releaseName = yield* resolveReleaseName(id, news, output);
|
|
177
|
+
const namespace = news.namespace ?? "default";
|
|
178
|
+
const connection = toConnection(news.cluster);
|
|
179
|
+
const transport = yield* connectCluster(connection);
|
|
180
|
+
const hash = yield* computeChartHash(news, releaseName);
|
|
181
|
+
yield* session.note(`Rendering Helm chart ${news.chart}${news.version ? `@${news.version}` : ""}...`);
|
|
182
|
+
const { objects: desiredObjects, redactions } = yield* chartObjects(transport, news, releaseName);
|
|
183
|
+
yield* session.note(`Applying ${String(desiredObjects.length)} objects from ${news.chart}...`);
|
|
184
|
+
// Turning createNamespace off releases the Namespace. It stays in the cluster.
|
|
185
|
+
const previousObjects = (output?.objects ?? []).filter((object) => !(olds?.createNamespace === true &&
|
|
186
|
+
news.createNamespace !== true &&
|
|
187
|
+
object.kind === "Namespace" &&
|
|
188
|
+
object.name === namespace));
|
|
189
|
+
const objects = yield* reconcileObjects({
|
|
190
|
+
transport,
|
|
191
|
+
previousObjects,
|
|
192
|
+
desiredObjects,
|
|
193
|
+
redactions,
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
connection,
|
|
197
|
+
releaseName,
|
|
198
|
+
namespace,
|
|
199
|
+
chart: news.chart,
|
|
200
|
+
version: news.version,
|
|
201
|
+
objects: [...objects],
|
|
202
|
+
code: { hash },
|
|
203
|
+
};
|
|
204
|
+
}),
|
|
205
|
+
read: Effect.fn(function* ({ output }) {
|
|
206
|
+
if (!output)
|
|
207
|
+
return undefined;
|
|
208
|
+
const connection = connectionOfOutput(output);
|
|
209
|
+
if (!connection)
|
|
210
|
+
return undefined;
|
|
211
|
+
// ClusterNotFound fails the drift row. undefined means an object is gone.
|
|
212
|
+
// GETs only: a dry-run PATCH needs `patch`, and re-rendering a chart
|
|
213
|
+
// rerolls randAlphaNum into a false drift.
|
|
214
|
+
const transport = yield* connectCluster(connection);
|
|
215
|
+
const notes = yield* Effect.forEach(output.objects, (object) => Effect.gen(function* () {
|
|
216
|
+
const key = kubernetesObjectKey(object);
|
|
217
|
+
const observed = yield* readObject({ transport, object }).pipe(Effect.catchTag("KubernetesNotFound", () => Effect.undefined));
|
|
218
|
+
if (!observed)
|
|
219
|
+
return `missing:${key}`;
|
|
220
|
+
// Older rows stored no selection. Re-rendering the chart is
|
|
221
|
+
// not a read, so only a missing object is drift until apply
|
|
222
|
+
// writes a mask.
|
|
223
|
+
if (object.driftMask === undefined || object.baselineHash === undefined) {
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
const liveHash = yield* hashDriftSelection(object.driftMask, observed);
|
|
227
|
+
return liveHash === object.baselineHash ? undefined : liveHash;
|
|
228
|
+
}), { concurrency: 8 });
|
|
229
|
+
const drifted = notes.filter((note) => note !== undefined);
|
|
230
|
+
if (drifted.length === 0)
|
|
231
|
+
return output;
|
|
232
|
+
return {
|
|
233
|
+
...output,
|
|
234
|
+
observedHash: yield* sha256Object({ notes: drifted }),
|
|
235
|
+
};
|
|
236
|
+
}),
|
|
237
|
+
delete: Effect.fn(function* ({ output }) {
|
|
238
|
+
const connection = connectionOfOutput(output);
|
|
239
|
+
if (!connection)
|
|
240
|
+
return;
|
|
241
|
+
const transport = yield* ifClusterExists(connectCluster(connection));
|
|
242
|
+
if (!transport)
|
|
243
|
+
return;
|
|
244
|
+
yield* deleteObjects({ transport, objects: output.objects });
|
|
245
|
+
}),
|
|
246
|
+
};
|
|
247
|
+
}));
|
|
248
|
+
//# sourceMappingURL=HelmChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HelmChart.js","sourceRoot":"","sources":["../src/HelmChart.ts"],"names":[],"mappings":"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"}
|