pepr 0.13.3 → 0.14.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/README.md +23 -4
- package/dist/cli.js +455 -266
- package/dist/controller.js +1 -1
- package/dist/lib/assets/deploy.d.ts.map +1 -1
- package/dist/lib/assets/destroy.d.ts +2 -0
- package/dist/lib/assets/destroy.d.ts.map +1 -0
- package/dist/lib/assets/index.d.ts +6 -5
- package/dist/lib/assets/index.d.ts.map +1 -1
- package/dist/lib/assets/networking.d.ts +6 -5
- package/dist/lib/assets/networking.d.ts.map +1 -1
- package/dist/lib/assets/pods.d.ts +84 -4
- package/dist/lib/assets/pods.d.ts.map +1 -1
- package/dist/lib/assets/rbac.d.ts +6 -4
- package/dist/lib/assets/rbac.d.ts.map +1 -1
- package/dist/lib/assets/store.d.ts +7 -0
- package/dist/lib/assets/store.d.ts.map +1 -0
- package/dist/lib/assets/webhooks.d.ts +2 -2
- package/dist/lib/assets/webhooks.d.ts.map +1 -1
- package/dist/lib/assets/yaml.d.ts.map +1 -1
- package/dist/lib/capability.d.ts +21 -4
- package/dist/lib/capability.d.ts.map +1 -1
- package/dist/lib/controller/index.d.ts +10 -0
- package/dist/lib/controller/index.d.ts.map +1 -0
- package/dist/lib/controller/store.d.ts +7 -0
- package/dist/lib/controller/store.d.ts.map +1 -0
- package/dist/lib/filter.d.ts +2 -2
- package/dist/lib/filter.d.ts.map +1 -1
- package/dist/lib/{k8s/types.d.ts → k8s.d.ts} +14 -25
- package/dist/lib/k8s.d.ts.map +1 -0
- package/dist/lib/metrics.d.ts +12 -12
- package/dist/lib/metrics.d.ts.map +1 -1
- package/dist/lib/module.d.ts +25 -4
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/mutate-processor.d.ts +3 -3
- package/dist/lib/mutate-processor.d.ts.map +1 -1
- package/dist/lib/mutate-request.d.ts +11 -10
- package/dist/lib/mutate-request.d.ts.map +1 -1
- package/dist/lib/storage.d.ts +56 -0
- package/dist/lib/storage.d.ts.map +1 -0
- package/dist/lib/tls.d.ts.map +1 -0
- package/dist/lib/types.d.ts +28 -48
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/validate-processor.d.ts +2 -2
- package/dist/lib/validate-processor.d.ts.map +1 -1
- package/dist/lib/validate-request.d.ts +9 -8
- package/dist/lib/validate-request.d.ts.map +1 -1
- package/dist/lib/watch-processor.d.ts +3 -0
- package/dist/lib/watch-processor.d.ts.map +1 -0
- package/dist/lib.d.ts +3 -7
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +484 -807
- package/dist/lib.js.map +4 -4
- package/package.json +16 -20
- package/src/lib/assets/deploy.ts +69 -127
- package/src/lib/assets/destroy.ts +33 -0
- package/src/lib/assets/index.ts +8 -14
- package/src/lib/assets/networking.ts +28 -5
- package/src/lib/assets/pods.ts +130 -11
- package/src/lib/assets/rbac.ts +42 -4
- package/src/lib/assets/store.ts +49 -0
- package/src/lib/assets/webhooks.ts +2 -2
- package/src/lib/assets/yaml.ts +13 -3
- package/src/lib/capability.ts +69 -14
- package/src/lib/{controller.ts → controller/index.ts} +25 -23
- package/src/lib/controller/store.ts +197 -0
- package/src/lib/filter.ts +2 -2
- package/src/lib/{k8s/types.ts → k8s.ts} +15 -26
- package/src/lib/metrics.ts +22 -38
- package/src/lib/module.ts +47 -10
- package/src/lib/mutate-processor.ts +6 -6
- package/src/lib/mutate-request.ts +18 -26
- package/src/lib/storage.ts +128 -0
- package/src/lib/types.ts +30 -53
- package/src/lib/validate-processor.ts +5 -4
- package/src/lib/validate-request.ts +15 -19
- package/src/lib/watch-processor.ts +55 -0
- package/src/lib.ts +4 -8
- package/src/templates/.eslintrc.template.json +18 -0
- package/src/templates/capabilities/hello-pepr.ts +54 -5
- package/src/templates/package.json +1 -0
- package/dist/lib/controller.d.ts +0 -10
- package/dist/lib/controller.d.ts.map +0 -1
- package/dist/lib/fetch.d.ts +0 -23
- package/dist/lib/fetch.d.ts.map +0 -1
- package/dist/lib/k8s/index.d.ts +0 -7
- package/dist/lib/k8s/index.d.ts.map +0 -1
- package/dist/lib/k8s/kinds.d.ts +0 -12
- package/dist/lib/k8s/kinds.d.ts.map +0 -1
- package/dist/lib/k8s/tls.d.ts.map +0 -1
- package/dist/lib/k8s/types.d.ts.map +0 -1
- package/dist/lib/k8s/upstream.d.ts +0 -4
- package/dist/lib/k8s/upstream.d.ts.map +0 -1
- package/jest.config.json +0 -4
- package/journey/before.ts +0 -21
- package/journey/k8s.ts +0 -100
- package/journey/pepr-build.ts +0 -69
- package/journey/pepr-deploy.ts +0 -174
- package/journey/pepr-dev.ts +0 -155
- package/journey/pepr-format.ts +0 -13
- package/journey/pepr-init.ts +0 -12
- package/src/lib/fetch.ts +0 -76
- package/src/lib/k8s/index.ts +0 -14
- package/src/lib/k8s/kinds.ts +0 -531
- package/src/lib/k8s/upstream.ts +0 -53
- /package/dist/lib/{k8s/tls.d.ts → tls.d.ts} +0 -0
- /package/src/lib/{k8s/tls.ts → tls.ts} +0 -0
package/src/lib/assets/deploy.ts
CHANGED
|
@@ -1,179 +1,121 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
AdmissionregistrationV1Api as AdmissionRegV1API,
|
|
6
|
-
AppsV1Api,
|
|
7
|
-
CoreV1Api,
|
|
8
|
-
HttpError,
|
|
9
|
-
KubeConfig,
|
|
10
|
-
RbacAuthorizationV1Api,
|
|
11
|
-
} from "@kubernetes/client-node";
|
|
12
4
|
import crypto from "crypto";
|
|
13
5
|
import { promises as fs } from "fs";
|
|
6
|
+
import { K8s, kind } from "kubernetes-fluent-client";
|
|
14
7
|
|
|
15
8
|
import { Assets } from ".";
|
|
16
9
|
import Log from "../logger";
|
|
17
|
-
import { apiTokenSecret, service, tlsSecret } from "./networking";
|
|
18
|
-
import { deployment, moduleSecret, namespace } from "./pods";
|
|
19
|
-
import { clusterRole, clusterRoleBinding, serviceAccount } from "./rbac";
|
|
10
|
+
import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
|
|
11
|
+
import { deployment, moduleSecret, namespace, watcher } from "./pods";
|
|
12
|
+
import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
|
|
13
|
+
import { peprStoreCRD } from "./store";
|
|
20
14
|
import { webhookConfig } from "./webhooks";
|
|
21
15
|
|
|
22
16
|
export async function deploy(assets: Assets, webhookTimeout?: number) {
|
|
23
17
|
Log.info("Establishing connection to Kubernetes");
|
|
24
18
|
|
|
25
|
-
const peprNS = "pepr-system";
|
|
26
19
|
const { name, host, path } = assets;
|
|
27
20
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
kubeConfig.loadFromDefault();
|
|
31
|
-
|
|
32
|
-
const coreV1Api = kubeConfig.makeApiClient(CoreV1Api);
|
|
33
|
-
const admissionApi = kubeConfig.makeApiClient(AdmissionRegV1API);
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
Log.info("Checking for namespace");
|
|
37
|
-
await coreV1Api.readNamespace(peprNS);
|
|
38
|
-
} catch (e) {
|
|
39
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
40
|
-
Log.info("Creating namespace");
|
|
41
|
-
await coreV1Api.createNamespace(namespace);
|
|
42
|
-
}
|
|
21
|
+
Log.info("Applying pepr-system namespace");
|
|
22
|
+
await K8s(kind.Namespace).Apply(namespace);
|
|
43
23
|
|
|
44
24
|
// Create the mutating webhook configuration if it is needed
|
|
45
25
|
const mutateWebhook = await webhookConfig(assets, "mutate", webhookTimeout);
|
|
46
26
|
if (mutateWebhook) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Log.info("Removing and re-creating mutating webhook");
|
|
53
|
-
await admissionApi.deleteMutatingWebhookConfiguration(mutateWebhook.metadata?.name ?? "");
|
|
54
|
-
await admissionApi.createMutatingWebhookConfiguration(mutateWebhook);
|
|
55
|
-
}
|
|
27
|
+
Log.info("Applying mutating webhook");
|
|
28
|
+
await K8s(kind.MutatingWebhookConfiguration).Apply(mutateWebhook);
|
|
29
|
+
} else {
|
|
30
|
+
Log.info("Mutating webhook not needed, removing if it exists");
|
|
31
|
+
await K8s(kind.MutatingWebhookConfiguration).Delete(name);
|
|
56
32
|
}
|
|
57
33
|
|
|
58
34
|
// Create the validating webhook configuration if it is needed
|
|
59
35
|
const validateWebhook = await webhookConfig(assets, "validate", webhookTimeout);
|
|
60
36
|
if (validateWebhook) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Log.info("Removing and re-creating validating webhook");
|
|
67
|
-
await admissionApi.deleteValidatingWebhookConfiguration(validateWebhook.metadata?.name ?? "");
|
|
68
|
-
await admissionApi.createValidatingWebhookConfiguration(validateWebhook);
|
|
69
|
-
}
|
|
37
|
+
Log.info("Applying validating webhook");
|
|
38
|
+
await K8s(kind.ValidatingWebhookConfiguration).Apply(validateWebhook);
|
|
39
|
+
} else {
|
|
40
|
+
Log.info("Validating webhook not needed, removing if it exists");
|
|
41
|
+
await K8s(kind.ValidatingWebhookConfiguration).Delete(name);
|
|
70
42
|
}
|
|
71
43
|
|
|
44
|
+
Log.info("Applying the Pepr Store CRD if it doesn't exist");
|
|
45
|
+
await K8s(kind.CustomResourceDefinition).Apply(peprStoreCRD);
|
|
46
|
+
|
|
72
47
|
// If a host is specified, we don't need to deploy the rest of the resources
|
|
73
48
|
if (host) {
|
|
74
49
|
return;
|
|
75
50
|
}
|
|
76
51
|
|
|
77
|
-
if (!path) {
|
|
78
|
-
throw new Error("No code provided");
|
|
79
|
-
}
|
|
80
|
-
|
|
81
52
|
const code = await fs.readFile(path);
|
|
82
|
-
|
|
83
53
|
const hash = crypto.createHash("sha256").update(code).digest("hex");
|
|
84
54
|
|
|
85
|
-
|
|
86
|
-
|
|
55
|
+
if (code.length < 1) {
|
|
56
|
+
throw new Error("No code provided");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
await setupRBAC(name);
|
|
60
|
+
await setupController(assets, code, hash);
|
|
61
|
+
await setupWatcher(assets, hash);
|
|
62
|
+
}
|
|
87
63
|
|
|
64
|
+
async function setupRBAC(name: string) {
|
|
65
|
+
Log.info("Applying cluster role binding");
|
|
88
66
|
const crb = clusterRoleBinding(name);
|
|
89
|
-
|
|
90
|
-
Log.info("Creating cluster role binding");
|
|
91
|
-
await rbacApi.createClusterRoleBinding(crb);
|
|
92
|
-
} catch (e) {
|
|
93
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
94
|
-
Log.info("Removing and re-creating cluster role binding");
|
|
95
|
-
await rbacApi.deleteClusterRoleBinding(crb.metadata?.name ?? "");
|
|
96
|
-
await rbacApi.createClusterRoleBinding(crb);
|
|
97
|
-
}
|
|
67
|
+
await K8s(kind.ClusterRoleBinding).Apply(crb);
|
|
98
68
|
|
|
69
|
+
Log.info("Applying cluster role");
|
|
99
70
|
const cr = clusterRole(name);
|
|
100
|
-
|
|
101
|
-
Log.info("Creating cluster role");
|
|
102
|
-
await rbacApi.createClusterRole(cr);
|
|
103
|
-
} catch (e) {
|
|
104
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
105
|
-
Log.info("Removing and re-creating the cluster role");
|
|
106
|
-
try {
|
|
107
|
-
await rbacApi.deleteClusterRole(cr.metadata?.name ?? "");
|
|
108
|
-
await rbacApi.createClusterRole(cr);
|
|
109
|
-
} catch (e) {
|
|
110
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
71
|
+
await K8s(kind.ClusterRole).Apply(cr);
|
|
113
72
|
|
|
73
|
+
Log.info("Applying service account");
|
|
114
74
|
const sa = serviceAccount(name);
|
|
115
|
-
|
|
116
|
-
Log.info("Creating service account");
|
|
117
|
-
await coreV1Api.createNamespacedServiceAccount(peprNS, sa);
|
|
118
|
-
} catch (e) {
|
|
119
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
120
|
-
Log.info("Removing and re-creating service account");
|
|
121
|
-
await coreV1Api.deleteNamespacedServiceAccount(sa.metadata?.name ?? "", peprNS);
|
|
122
|
-
await coreV1Api.createNamespacedServiceAccount(peprNS, sa);
|
|
123
|
-
}
|
|
75
|
+
await K8s(kind.ServiceAccount).Apply(sa);
|
|
124
76
|
|
|
77
|
+
Log.info("Applying store role");
|
|
78
|
+
const role = storeRole(name);
|
|
79
|
+
await K8s(kind.Role).Apply(role);
|
|
80
|
+
|
|
81
|
+
Log.info("Applying store role binding");
|
|
82
|
+
const roleBinding = storeRoleBinding(name);
|
|
83
|
+
await K8s(kind.RoleBinding).Apply(roleBinding);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function setupController(assets: Assets, code: Buffer, hash: string) {
|
|
87
|
+
const { name } = assets;
|
|
88
|
+
|
|
89
|
+
Log.info("Applying module secret");
|
|
125
90
|
const mod = moduleSecret(name, code, hash);
|
|
126
|
-
|
|
127
|
-
Log.info("Creating module secret");
|
|
128
|
-
await coreV1Api.createNamespacedSecret(peprNS, mod);
|
|
129
|
-
} catch (e) {
|
|
130
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
131
|
-
Log.info("Removing and re-creating module secret");
|
|
132
|
-
await coreV1Api.deleteNamespacedSecret(mod.metadata?.name ?? "", peprNS);
|
|
133
|
-
await coreV1Api.createNamespacedSecret(peprNS, mod);
|
|
134
|
-
}
|
|
91
|
+
await K8s(kind.Secret).Apply(mod);
|
|
135
92
|
|
|
93
|
+
Log.info("Applying controller service");
|
|
136
94
|
const svc = service(name);
|
|
137
|
-
|
|
138
|
-
Log.info("Creating service");
|
|
139
|
-
await coreV1Api.createNamespacedService(peprNS, svc);
|
|
140
|
-
} catch (e) {
|
|
141
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
142
|
-
Log.info("Removing and re-creating service");
|
|
143
|
-
await coreV1Api.deleteNamespacedService(svc.metadata?.name ?? "", peprNS);
|
|
144
|
-
await coreV1Api.createNamespacedService(peprNS, svc);
|
|
145
|
-
}
|
|
95
|
+
await K8s(kind.Service).Apply(svc);
|
|
146
96
|
|
|
97
|
+
Log.info("Applying TLS secret");
|
|
147
98
|
const tls = tlsSecret(name, assets.tls);
|
|
148
|
-
|
|
149
|
-
Log.info("Creating TLS secret");
|
|
150
|
-
await coreV1Api.createNamespacedSecret(peprNS, tls);
|
|
151
|
-
} catch (e) {
|
|
152
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
153
|
-
Log.info("Removing and re-creating TLS secret");
|
|
154
|
-
await coreV1Api.deleteNamespacedSecret(tls.metadata?.name ?? "", peprNS);
|
|
155
|
-
await coreV1Api.createNamespacedSecret(peprNS, tls);
|
|
156
|
-
}
|
|
99
|
+
await K8s(kind.Secret).Apply(tls);
|
|
157
100
|
|
|
101
|
+
Log.info("Applying API token secret");
|
|
158
102
|
const apiToken = apiTokenSecret(name, assets.apiToken);
|
|
159
|
-
|
|
160
|
-
Log.info("Creating API token secret");
|
|
161
|
-
await coreV1Api.createNamespacedSecret(peprNS, apiToken);
|
|
162
|
-
} catch (e) {
|
|
163
|
-
Log.debug(e instanceof HttpError ? e.body : e);
|
|
164
|
-
Log.info("Removing and re-creating API token secret");
|
|
165
|
-
await coreV1Api.deleteNamespacedSecret(apiToken.metadata?.name ?? "", peprNS);
|
|
166
|
-
await coreV1Api.createNamespacedSecret(peprNS, apiToken);
|
|
167
|
-
}
|
|
103
|
+
await K8s(kind.Secret).Apply(apiToken);
|
|
168
104
|
|
|
105
|
+
Log.info("Applying deployment");
|
|
169
106
|
const dep = deployment(assets, hash);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
107
|
+
await K8s(kind.Deployment).Apply(dep);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function setupWatcher(assets: Assets, hash: string) {
|
|
111
|
+
// If the module has a watcher, deploy it
|
|
112
|
+
const watchDeployment = watcher(assets, hash);
|
|
113
|
+
if (watchDeployment) {
|
|
114
|
+
Log.info("Applying watcher deployment");
|
|
115
|
+
await K8s(kind.Deployment).Apply(watchDeployment);
|
|
116
|
+
|
|
117
|
+
Log.info("Applying watcher service");
|
|
118
|
+
const watchSvc = watcherService(assets.name);
|
|
119
|
+
await K8s(kind.Service).Apply(watchSvc);
|
|
178
120
|
}
|
|
179
121
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
|
|
4
|
+
import { K8s, kind } from "kubernetes-fluent-client";
|
|
5
|
+
|
|
6
|
+
import Log from "../logger";
|
|
7
|
+
import { peprStoreCRD } from "./store";
|
|
8
|
+
|
|
9
|
+
export async function destroyModule(name: string) {
|
|
10
|
+
const namespace = "pepr-system";
|
|
11
|
+
|
|
12
|
+
Log.info("Destroying Pepr module");
|
|
13
|
+
|
|
14
|
+
await Promise.all([
|
|
15
|
+
K8s(kind.MutatingWebhookConfiguration).Delete(name),
|
|
16
|
+
K8s(kind.ValidatingWebhookConfiguration).Delete(name),
|
|
17
|
+
|
|
18
|
+
K8s(kind.CustomResourceDefinition).Delete(peprStoreCRD),
|
|
19
|
+
K8s(kind.ClusterRoleBinding).Delete(name),
|
|
20
|
+
K8s(kind.ClusterRole).Delete(name),
|
|
21
|
+
K8s(kind.ServiceAccount, { namespace }).Delete(name),
|
|
22
|
+
K8s(kind.Role, { namespace }).Delete(name),
|
|
23
|
+
K8s(kind.RoleBinding, { namespace }).Delete(`${name}-store`),
|
|
24
|
+
|
|
25
|
+
K8s(kind.Secret, { namespace }).Delete(`${name}-module`),
|
|
26
|
+
K8s(kind.Service, { namespace }).Delete(name),
|
|
27
|
+
K8s(kind.Secret, { namespace }).Delete(`${name}-tls`),
|
|
28
|
+
K8s(kind.Secret, { namespace }).Delete(`${name}-api-token`),
|
|
29
|
+
K8s(kind.Deployment, { namespace }).Delete(name),
|
|
30
|
+
K8s(kind.Deployment, { namespace }).Delete(`${name}-watcher`),
|
|
31
|
+
K8s(kind.Service, { namespace }).Delete(`${name}-watcher`),
|
|
32
|
+
]);
|
|
33
|
+
}
|
package/src/lib/assets/index.ts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
import crypto from "crypto";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { ModuleConfig } from "../module";
|
|
7
|
+
import { TLSOut, genTLS } from "../tls";
|
|
8
|
+
import { CapabilityExport } from "../types";
|
|
8
9
|
import { deploy } from "./deploy";
|
|
9
10
|
import { loadCapabilities } from "./loader";
|
|
10
11
|
import { allYaml, zarfYaml } from "./yaml";
|
|
@@ -21,11 +22,6 @@ export class Assets {
|
|
|
21
22
|
readonly path: string,
|
|
22
23
|
readonly host?: string,
|
|
23
24
|
) {
|
|
24
|
-
// Bind public methods
|
|
25
|
-
this.deploy = this.deploy.bind(this);
|
|
26
|
-
this.zarfYaml = this.zarfYaml.bind(this);
|
|
27
|
-
this.allYaml = this.allYaml.bind(this);
|
|
28
|
-
|
|
29
25
|
this.name = `pepr-${config.uuid}`;
|
|
30
26
|
|
|
31
27
|
this.image = `ghcr.io/defenseunicorns/pepr/controller:v${config.peprVersion}`;
|
|
@@ -37,17 +33,15 @@ export class Assets {
|
|
|
37
33
|
this.apiToken = crypto.randomBytes(32).toString("hex");
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
async
|
|
36
|
+
deploy = async (webhookTimeout?: number) => {
|
|
41
37
|
this.capabilities = await loadCapabilities(this.path);
|
|
42
38
|
await deploy(this, webhookTimeout);
|
|
43
|
-
}
|
|
39
|
+
};
|
|
44
40
|
|
|
45
|
-
zarfYaml(path: string)
|
|
46
|
-
return zarfYaml(this, path);
|
|
47
|
-
}
|
|
41
|
+
zarfYaml = (path: string) => zarfYaml(this, path);
|
|
48
42
|
|
|
49
|
-
async
|
|
43
|
+
allYaml = async () => {
|
|
50
44
|
this.capabilities = await loadCapabilities(this.path);
|
|
51
45
|
return allYaml(this);
|
|
52
|
-
}
|
|
46
|
+
};
|
|
53
47
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { Secret, Service } from "../k8s/upstream";
|
|
4
|
+
import { kind } from "kubernetes-fluent-client";
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
import { TLSOut } from "../tls";
|
|
7
|
+
|
|
8
|
+
export function apiTokenSecret(name: string, apiToken: string): kind.Secret {
|
|
8
9
|
return {
|
|
9
10
|
apiVersion: "v1",
|
|
10
11
|
kind: "Secret",
|
|
@@ -19,7 +20,7 @@ export function apiTokenSecret(name: string, apiToken: string): Secret {
|
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export function tlsSecret(name: string, tls: TLSOut): Secret {
|
|
23
|
+
export function tlsSecret(name: string, tls: TLSOut): kind.Secret {
|
|
23
24
|
return {
|
|
24
25
|
apiVersion: "v1",
|
|
25
26
|
kind: "Secret",
|
|
@@ -35,7 +36,7 @@ export function tlsSecret(name: string, tls: TLSOut): Secret {
|
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
export function service(name: string): Service {
|
|
39
|
+
export function service(name: string): kind.Service {
|
|
39
40
|
return {
|
|
40
41
|
apiVersion: "v1",
|
|
41
42
|
kind: "Service",
|
|
@@ -56,3 +57,25 @@ export function service(name: string): Service {
|
|
|
56
57
|
},
|
|
57
58
|
};
|
|
58
59
|
}
|
|
60
|
+
|
|
61
|
+
export function watcherService(name: string): kind.Service {
|
|
62
|
+
return {
|
|
63
|
+
apiVersion: "v1",
|
|
64
|
+
kind: "Service",
|
|
65
|
+
metadata: {
|
|
66
|
+
name: `${name}-watcher`,
|
|
67
|
+
namespace: "pepr-system",
|
|
68
|
+
},
|
|
69
|
+
spec: {
|
|
70
|
+
selector: {
|
|
71
|
+
app: `${name}-watcher`,
|
|
72
|
+
},
|
|
73
|
+
ports: [
|
|
74
|
+
{
|
|
75
|
+
port: 443,
|
|
76
|
+
targetPort: 3000,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
package/src/lib/assets/pods.ts
CHANGED
|
@@ -1,20 +1,141 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
|
+
import { kind } from "kubernetes-fluent-client";
|
|
4
5
|
import { gzipSync } from "zlib";
|
|
5
6
|
|
|
6
7
|
import { Assets } from ".";
|
|
7
|
-
import {
|
|
8
|
+
import { Binding } from "../types";
|
|
8
9
|
|
|
9
10
|
/** Generate the pepr-system namespace */
|
|
10
|
-
export const namespace: Namespace = {
|
|
11
|
+
export const namespace: kind.Namespace = {
|
|
11
12
|
apiVersion: "v1",
|
|
12
13
|
kind: "Namespace",
|
|
13
14
|
metadata: { name: "pepr-system" },
|
|
14
15
|
};
|
|
15
16
|
|
|
16
|
-
export function
|
|
17
|
-
const { name, image } = assets;
|
|
17
|
+
export function watcher(assets: Assets, hash: string) {
|
|
18
|
+
const { name, image, capabilities, config } = assets;
|
|
19
|
+
|
|
20
|
+
// Append the watcher suffix
|
|
21
|
+
const app = `${name}-watcher`;
|
|
22
|
+
const bindings: Binding[] = [];
|
|
23
|
+
|
|
24
|
+
// Loop through the capabilities and find any Watch Actions
|
|
25
|
+
for (const capability of capabilities) {
|
|
26
|
+
const watchers = capability.bindings.filter(binding => binding.isWatch);
|
|
27
|
+
bindings.push(...watchers);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// If there are no watchers, don't deploy the watcher
|
|
31
|
+
if (bindings.length < 1) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
apiVersion: "apps/v1",
|
|
37
|
+
kind: "Deployment",
|
|
38
|
+
metadata: {
|
|
39
|
+
name: app,
|
|
40
|
+
namespace: "pepr-system",
|
|
41
|
+
labels: {
|
|
42
|
+
app,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
spec: {
|
|
46
|
+
replicas: 1,
|
|
47
|
+
strategy: {
|
|
48
|
+
type: "Recreate",
|
|
49
|
+
},
|
|
50
|
+
selector: {
|
|
51
|
+
matchLabels: {
|
|
52
|
+
app,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
template: {
|
|
56
|
+
metadata: {
|
|
57
|
+
labels: {
|
|
58
|
+
app,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
spec: {
|
|
62
|
+
serviceAccountName: name,
|
|
63
|
+
containers: [
|
|
64
|
+
{
|
|
65
|
+
name: "watcher",
|
|
66
|
+
image,
|
|
67
|
+
imagePullPolicy: "IfNotPresent",
|
|
68
|
+
command: ["node", "/app/node_modules/pepr/dist/controller.js", hash],
|
|
69
|
+
readinessProbe: {
|
|
70
|
+
httpGet: {
|
|
71
|
+
path: "/healthz",
|
|
72
|
+
port: 3000,
|
|
73
|
+
scheme: "HTTPS",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
livenessProbe: {
|
|
77
|
+
httpGet: {
|
|
78
|
+
path: "/healthz",
|
|
79
|
+
port: 3000,
|
|
80
|
+
scheme: "HTTPS",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
ports: [
|
|
84
|
+
{
|
|
85
|
+
containerPort: 3000,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
resources: {
|
|
89
|
+
requests: {
|
|
90
|
+
memory: "64Mi",
|
|
91
|
+
cpu: "100m",
|
|
92
|
+
},
|
|
93
|
+
limits: {
|
|
94
|
+
memory: "256Mi",
|
|
95
|
+
cpu: "500m",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
volumeMounts: [
|
|
99
|
+
{
|
|
100
|
+
name: "tls-certs",
|
|
101
|
+
mountPath: "/etc/certs",
|
|
102
|
+
readOnly: true,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "module",
|
|
106
|
+
mountPath: `/app/load`,
|
|
107
|
+
readOnly: true,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
env: [
|
|
111
|
+
{ name: "PEPR_WATCH_MODE", value: "true" },
|
|
112
|
+
{ name: "PEPR_PRETTY_LOG", value: "false" },
|
|
113
|
+
{ name: "LOG_LEVEL", value: config.logLevel || "debug" },
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
volumes: [
|
|
118
|
+
{
|
|
119
|
+
name: "tls-certs",
|
|
120
|
+
secret: {
|
|
121
|
+
secretName: `${name}-tls`,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "module",
|
|
126
|
+
secret: {
|
|
127
|
+
secretName: `${name}-module`,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function deployment(assets: Assets, hash: string): kind.Deployment {
|
|
138
|
+
const { name, image, config } = assets;
|
|
18
139
|
const app = name;
|
|
19
140
|
|
|
20
141
|
return {
|
|
@@ -68,12 +189,6 @@ export function deployment(assets: Assets, hash: string): Deployment {
|
|
|
68
189
|
containerPort: 3000,
|
|
69
190
|
},
|
|
70
191
|
],
|
|
71
|
-
env: [
|
|
72
|
-
{
|
|
73
|
-
name: "PEPR_PRETTY_LOG",
|
|
74
|
-
value: "false",
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
192
|
resources: {
|
|
78
193
|
requests: {
|
|
79
194
|
memory: "64Mi",
|
|
@@ -84,6 +199,10 @@ export function deployment(assets: Assets, hash: string): Deployment {
|
|
|
84
199
|
cpu: "500m",
|
|
85
200
|
},
|
|
86
201
|
},
|
|
202
|
+
env: [
|
|
203
|
+
{ name: "PEPR_PRETTY_LOG", value: "false" },
|
|
204
|
+
{ name: "LOG_LEVEL", value: config.logLevel || "debug" },
|
|
205
|
+
],
|
|
87
206
|
volumeMounts: [
|
|
88
207
|
{
|
|
89
208
|
name: "tls-certs",
|
|
@@ -129,7 +248,7 @@ export function deployment(assets: Assets, hash: string): Deployment {
|
|
|
129
248
|
};
|
|
130
249
|
}
|
|
131
250
|
|
|
132
|
-
export function moduleSecret(name: string, data: Buffer, hash: string): Secret {
|
|
251
|
+
export function moduleSecret(name: string, data: Buffer, hash: string): kind.Secret {
|
|
133
252
|
// Compress the data
|
|
134
253
|
const compressed = gzipSync(data);
|
|
135
254
|
const path = `module-${hash}.js.gz`;
|
package/src/lib/assets/rbac.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { kind } from "kubernetes-fluent-client";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Grants the controller access to cluster resources beyond the mutating webhook.
|
|
@@ -9,7 +9,7 @@ import { ClusterRole, ClusterRoleBinding, ServiceAccount } from "../k8s/upstream
|
|
|
9
9
|
* @todo: should dynamically generate this based on resources used by the module. will also need to explore how this should work for multiple modules.
|
|
10
10
|
* @returns
|
|
11
11
|
*/
|
|
12
|
-
export function clusterRole(name: string): ClusterRole {
|
|
12
|
+
export function clusterRole(name: string): kind.ClusterRole {
|
|
13
13
|
return {
|
|
14
14
|
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
15
15
|
kind: "ClusterRole",
|
|
@@ -25,7 +25,7 @@ export function clusterRole(name: string): ClusterRole {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export function clusterRoleBinding(name: string): ClusterRoleBinding {
|
|
28
|
+
export function clusterRoleBinding(name: string): kind.ClusterRoleBinding {
|
|
29
29
|
return {
|
|
30
30
|
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
31
31
|
kind: "ClusterRoleBinding",
|
|
@@ -45,7 +45,7 @@ export function clusterRoleBinding(name: string): ClusterRoleBinding {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export function serviceAccount(name: string): ServiceAccount {
|
|
48
|
+
export function serviceAccount(name: string): kind.ServiceAccount {
|
|
49
49
|
return {
|
|
50
50
|
apiVersion: "v1",
|
|
51
51
|
kind: "ServiceAccount",
|
|
@@ -55,3 +55,41 @@ export function serviceAccount(name: string): ServiceAccount {
|
|
|
55
55
|
},
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
export function storeRole(name: string): kind.Role {
|
|
60
|
+
name = `${name}-store`;
|
|
61
|
+
return {
|
|
62
|
+
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
63
|
+
kind: "Role",
|
|
64
|
+
metadata: { name, namespace: "pepr-system" },
|
|
65
|
+
rules: [
|
|
66
|
+
{
|
|
67
|
+
apiGroups: ["pepr.dev/*"],
|
|
68
|
+
resources: ["peprstores"],
|
|
69
|
+
resourceNames: [""],
|
|
70
|
+
verbs: ["create", "get", "patch", "watch"],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function storeRoleBinding(name: string): kind.RoleBinding {
|
|
77
|
+
name = `${name}-store`;
|
|
78
|
+
return {
|
|
79
|
+
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
80
|
+
kind: "RoleBinding",
|
|
81
|
+
metadata: { name, namespace: "pepr-system" },
|
|
82
|
+
roleRef: {
|
|
83
|
+
apiGroup: "rbac.authorization.k8s.io",
|
|
84
|
+
kind: "Role",
|
|
85
|
+
name,
|
|
86
|
+
},
|
|
87
|
+
subjects: [
|
|
88
|
+
{
|
|
89
|
+
kind: "ServiceAccount",
|
|
90
|
+
name,
|
|
91
|
+
namespace: "pepr-system",
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
|
|
4
|
+
import { kind as k } from "kubernetes-fluent-client";
|
|
5
|
+
|
|
6
|
+
import { peprStoreGVK } from "../k8s";
|
|
7
|
+
|
|
8
|
+
export const { group, version, kind } = peprStoreGVK;
|
|
9
|
+
export const singular = kind.toLocaleLowerCase();
|
|
10
|
+
export const plural = `${singular}s`;
|
|
11
|
+
export const name = `${plural}.${group}`;
|
|
12
|
+
|
|
13
|
+
export const peprStoreCRD: k.CustomResourceDefinition = {
|
|
14
|
+
apiVersion: "apiextensions.k8s.io/v1",
|
|
15
|
+
kind: "CustomResourceDefinition",
|
|
16
|
+
metadata: {
|
|
17
|
+
name,
|
|
18
|
+
},
|
|
19
|
+
spec: {
|
|
20
|
+
group,
|
|
21
|
+
versions: [
|
|
22
|
+
{
|
|
23
|
+
// typescript doesn't know this is really already set, which is kind of annoying
|
|
24
|
+
name: version || "v1",
|
|
25
|
+
served: true,
|
|
26
|
+
storage: true,
|
|
27
|
+
schema: {
|
|
28
|
+
openAPIV3Schema: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
data: {
|
|
32
|
+
type: "object",
|
|
33
|
+
additionalProperties: {
|
|
34
|
+
type: "string",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
scope: "Namespaced",
|
|
43
|
+
names: {
|
|
44
|
+
plural,
|
|
45
|
+
singular,
|
|
46
|
+
kind,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
};
|