@heynixie/pulumi-k8s 0.0.0 → 0.42.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 +68 -45
- package/dist/build-backup-pod-spec.d.ts +10 -0
- package/dist/build-nixie-spec.d.ts +22 -0
- package/dist/build-nixie-web-spec.d.ts +11 -0
- package/dist/build-service-args.d.ts +9 -0
- package/dist/create-nixie.d.ts +11 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +363 -0
- package/dist/types.d.ts +28 -0
- package/package.json +31 -7
package/README.md
CHANGED
|
@@ -1,45 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>@heynixie/pulumi-k8s</h1>
|
|
3
|
+
|
|
4
|
+
<p>
|
|
5
|
+
<a href="https://www.npmjs.com/package/@heynixie/pulumi-k8s"><img src="https://img.shields.io/npm/v/@heynixie/pulumi-k8s" alt="npm version"></a>
|
|
6
|
+
<a href="../../LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT license"></a>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p>
|
|
10
|
+
<a href="../../docs/architecture/deployment/kubernetes.md#the-pulumi-component">Kubernetes</a> •
|
|
11
|
+
<a href="../../docs/architecture/deployment/release-pipeline.md">Release pipeline</a>
|
|
12
|
+
</p>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
A Pulumi component that runs nixie on Kubernetes.
|
|
16
|
+
|
|
17
|
+
The component registers nixie's StatefulSet, the web client and the backup job in one namespace, in
|
|
18
|
+
the shape each nixie release ships. Each release of nixie publishes the component at its own
|
|
19
|
+
version, so a deployment takes a change to that shape with a version bump. To start, install the
|
|
20
|
+
package beside your Pulumi SDKs, call `createNixie` with your namespace and images, and point your
|
|
21
|
+
ingress at the two Services it returns.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
The package ships an ES module with its type declarations, so a Pulumi program on Node or on Bun
|
|
26
|
+
loads it. It takes `@pulumi/pulumi` 3 and `@pulumi/kubernetes` 4 as peer dependencies, which your
|
|
27
|
+
program installs.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bun add @heynixie/pulumi-k8s
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **nixie's pod.** One replica on a `ReadWriteOnce` claim, with the configuration, the encrypted
|
|
36
|
+
secrets and a git-sync container that follows your definitions repo on GitHub.
|
|
37
|
+
- **The web client.** A Deployment that rolls out after nixie and calls its API by the Service.
|
|
38
|
+
- **The backup.** A CronJob that runs your backup script on nixie's volume, on your schedule.
|
|
39
|
+
- **Moving onto it.** Each resource keeps its own Pulumi name and an alias to the stack, so a stack
|
|
40
|
+
that declared the same resources itself moves onto the component with no replacement.
|
|
41
|
+
|
|
42
|
+
## Configuration
|
|
43
|
+
|
|
44
|
+
`createNixie(name, args, opts)` takes the per-deployment values in `args`, and their types in
|
|
45
|
+
[`src/types.ts`](src/types.ts) describe each one. Pass your Kubernetes provider in `opts`.
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { createNixie, nixieAPIPort, nixieWebPort } from '@heynixie/pulumi-k8s';
|
|
49
|
+
|
|
50
|
+
const nixie = createNixie(
|
|
51
|
+
'nixie',
|
|
52
|
+
{
|
|
53
|
+
namespace: 'assistant',
|
|
54
|
+
image: 'ghcr.io/zgeoff/nixie:<version>@sha256:<digest>',
|
|
55
|
+
web: { image: 'ghcr.io/zgeoff/nixie-web:<version>@sha256:<digest>' },
|
|
56
|
+
config: configText,
|
|
57
|
+
secretsFile: sopsFileText,
|
|
58
|
+
ageKey: ageKeySecret,
|
|
59
|
+
definitions: { repository: '<owner>/<repo>', ref: 'live', deployKey: deployKeySecret },
|
|
60
|
+
storageClassName: 'local-path',
|
|
61
|
+
},
|
|
62
|
+
{ provider: cluster },
|
|
63
|
+
);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Documentation
|
|
67
|
+
|
|
68
|
+
The [Kubernetes architecture](../../docs/architecture/deployment/kubernetes.md) covers the shape.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { types } from '@pulumi/kubernetes';
|
|
2
|
+
import type { Input } from '@pulumi/pulumi';
|
|
3
|
+
export interface BackupPodInputs {
|
|
4
|
+
readonly image: Input<string>;
|
|
5
|
+
readonly claim: string;
|
|
6
|
+
readonly scriptConfigMap: string;
|
|
7
|
+
readonly envSecret: string;
|
|
8
|
+
readonly pullSecret: Input<string>;
|
|
9
|
+
}
|
|
10
|
+
export declare function buildBackupPodSpec(inputs: BackupPodInputs): types.input.core.v1.PodSpec;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { types } from '@pulumi/kubernetes';
|
|
2
|
+
import type { Input } from '@pulumi/pulumi';
|
|
3
|
+
export declare const nixieLabels: {
|
|
4
|
+
app: string;
|
|
5
|
+
};
|
|
6
|
+
export interface NixieSpecInputs {
|
|
7
|
+
readonly image: Input<string>;
|
|
8
|
+
readonly serviceName: Input<string>;
|
|
9
|
+
readonly configMap: Input<string>;
|
|
10
|
+
readonly secret: Input<string>;
|
|
11
|
+
readonly definitionsSecret: Input<string>;
|
|
12
|
+
readonly definitionsRepository: string;
|
|
13
|
+
readonly definitionsRef: Input<string>;
|
|
14
|
+
readonly storageClassName: Input<string>;
|
|
15
|
+
}
|
|
16
|
+
export declare function buildNixieSpec(inputs: NixieSpecInputs): types.input.apps.v1.StatefulSetSpec;
|
|
17
|
+
export declare const nixieAPIPort = 8080;
|
|
18
|
+
export declare const nixieSecretsFileKey = "secrets.yaml";
|
|
19
|
+
export declare const nixieAgeKeyKey = "age-key.txt";
|
|
20
|
+
export declare const nixieConfigKey = "config.yaml";
|
|
21
|
+
export declare const definitionsDeployKeyKey = "ssh";
|
|
22
|
+
export declare const definitionsKnownHostsKey = "known_hosts";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { types } from '@pulumi/kubernetes';
|
|
2
|
+
import type { Input } from '@pulumi/pulumi';
|
|
3
|
+
export declare const nixieWebLabels: {
|
|
4
|
+
app: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const nixieWebPort = 3000;
|
|
7
|
+
export interface NixieWebSpecInputs {
|
|
8
|
+
readonly image: Input<string>;
|
|
9
|
+
readonly apiURL: Input<string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function buildNixieWebSpec(inputs: NixieWebSpecInputs): types.input.apps.v1.DeploymentSpec;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { core } from '@pulumi/kubernetes';
|
|
2
|
+
import type { Input } from '@pulumi/pulumi';
|
|
3
|
+
export interface ServiceShape {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly namespace: Input<string>;
|
|
6
|
+
readonly labels: Record<string, string>;
|
|
7
|
+
readonly port: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildServiceArgs(shape: ServiceShape): core.v1.ServiceArgs;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { apps, core } from '@pulumi/kubernetes';
|
|
2
|
+
import type { ComponentResourceOptions } from '@pulumi/pulumi';
|
|
3
|
+
import { ComponentResource } from '@pulumi/pulumi';
|
|
4
|
+
import type { NixieArgs } from './types.js';
|
|
5
|
+
export interface Nixie {
|
|
6
|
+
readonly component: ComponentResource;
|
|
7
|
+
readonly api: core.v1.Service;
|
|
8
|
+
readonly web: core.v1.Service;
|
|
9
|
+
readonly statefulSet: apps.v1.StatefulSet;
|
|
10
|
+
}
|
|
11
|
+
export declare function createNixie(name: string, args: NixieArgs, opts?: ComponentResourceOptions): Nixie;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { nixieAPIPort } from './build-nixie-spec.js';
|
|
2
|
+
export { nixieWebPort } from './build-nixie-web-spec.js';
|
|
3
|
+
export { createNixie } from './create-nixie.js';
|
|
4
|
+
export type { Nixie } from './create-nixie.js';
|
|
5
|
+
export type { NixieArgs, NixieBackupArgs, NixieDefinitionsArgs, NixieWebArgs } from './types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
// src/build-nixie-spec.ts
|
|
2
|
+
var nixieLabels = { app: "nixie" };
|
|
3
|
+
function buildNixieSpec(inputs) {
|
|
4
|
+
return {
|
|
5
|
+
replicas: 1,
|
|
6
|
+
updateStrategy: { type: "RollingUpdate" },
|
|
7
|
+
podManagementPolicy: "Parallel",
|
|
8
|
+
serviceName: inputs.serviceName,
|
|
9
|
+
selector: { matchLabels: nixieLabels },
|
|
10
|
+
template: {
|
|
11
|
+
metadata: { labels: nixieLabels },
|
|
12
|
+
spec: {
|
|
13
|
+
terminationGracePeriodSeconds: 60,
|
|
14
|
+
securityContext: {
|
|
15
|
+
fsGroup: 10001,
|
|
16
|
+
runAsNonRoot: true,
|
|
17
|
+
seccompProfile: { type: "RuntimeDefault" }
|
|
18
|
+
},
|
|
19
|
+
volumes: [
|
|
20
|
+
{ name: "config", configMap: { name: inputs.configMap } },
|
|
21
|
+
{ name: "secrets", secret: { secretName: inputs.secret, defaultMode: 288 } },
|
|
22
|
+
{
|
|
23
|
+
name: "definitions-key",
|
|
24
|
+
secret: { secretName: inputs.definitionsSecret, defaultMode: 288 }
|
|
25
|
+
},
|
|
26
|
+
{ name: "definitions", emptyDir: {} },
|
|
27
|
+
{ name: "tmp", emptyDir: {} },
|
|
28
|
+
{ name: "git-sync-tmp", emptyDir: {} }
|
|
29
|
+
],
|
|
30
|
+
containers: [
|
|
31
|
+
buildNixieContainer(inputs.image),
|
|
32
|
+
buildGitSyncContainer(inputs.definitionsRepository, inputs.definitionsRef)
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
volumeClaimTemplates: [
|
|
37
|
+
{
|
|
38
|
+
metadata: { name: "data" },
|
|
39
|
+
spec: {
|
|
40
|
+
accessModes: ["ReadWriteOnce"],
|
|
41
|
+
storageClassName: inputs.storageClassName,
|
|
42
|
+
resources: { requests: { storage: "10Gi" } }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
var lockedDown = {
|
|
49
|
+
allowPrivilegeEscalation: false,
|
|
50
|
+
readOnlyRootFilesystem: true,
|
|
51
|
+
capabilities: { drop: ["ALL"] }
|
|
52
|
+
};
|
|
53
|
+
var nixieAPIPort = 8080;
|
|
54
|
+
var nixieSecretsFileKey = "secrets.yaml";
|
|
55
|
+
var nixieAgeKeyKey = "age-key.txt";
|
|
56
|
+
var nixieConfigKey = "config.yaml";
|
|
57
|
+
var definitionsRoot = "/etc/nixie/definitions";
|
|
58
|
+
function buildNixieContainer(image) {
|
|
59
|
+
return {
|
|
60
|
+
name: "nixie",
|
|
61
|
+
image,
|
|
62
|
+
ports: [{ name: "http", containerPort: nixieAPIPort }],
|
|
63
|
+
env: [{ name: "SOPS_AGE_KEY_FILE", value: `/etc/nixie/age/${nixieAgeKeyKey}` }],
|
|
64
|
+
startupProbe: {
|
|
65
|
+
httpGet: { path: "/health/live", port: nixieAPIPort },
|
|
66
|
+
periodSeconds: 5,
|
|
67
|
+
failureThreshold: 60
|
|
68
|
+
},
|
|
69
|
+
livenessProbe: {
|
|
70
|
+
httpGet: { path: "/health/live", port: nixieAPIPort },
|
|
71
|
+
periodSeconds: 30,
|
|
72
|
+
failureThreshold: 3
|
|
73
|
+
},
|
|
74
|
+
readinessProbe: {
|
|
75
|
+
httpGet: { path: "/health/ready", port: nixieAPIPort },
|
|
76
|
+
periodSeconds: 10,
|
|
77
|
+
timeoutSeconds: 5,
|
|
78
|
+
failureThreshold: 3
|
|
79
|
+
},
|
|
80
|
+
volumeMounts: [
|
|
81
|
+
{ name: "data", mountPath: "/data" },
|
|
82
|
+
{
|
|
83
|
+
name: "config",
|
|
84
|
+
mountPath: `/etc/nixie/${nixieConfigKey}`,
|
|
85
|
+
subPath: nixieConfigKey,
|
|
86
|
+
readOnly: true
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "secrets",
|
|
90
|
+
mountPath: `/etc/nixie/${nixieSecretsFileKey}`,
|
|
91
|
+
subPath: nixieSecretsFileKey,
|
|
92
|
+
readOnly: true
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "secrets",
|
|
96
|
+
mountPath: `/etc/nixie/age/${nixieAgeKeyKey}`,
|
|
97
|
+
subPath: nixieAgeKeyKey,
|
|
98
|
+
readOnly: true
|
|
99
|
+
},
|
|
100
|
+
{ name: "definitions", mountPath: definitionsRoot, readOnly: true },
|
|
101
|
+
{ name: "tmp", mountPath: "/tmp" }
|
|
102
|
+
],
|
|
103
|
+
securityContext: { ...lockedDown, runAsUser: 10001, runAsGroup: 10001 },
|
|
104
|
+
resources: { requests: { cpu: "100m", memory: "256Mi" }, limits: { memory: "1Gi" } }
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
var definitionsDeployKeyKey = "ssh";
|
|
108
|
+
var definitionsKnownHostsKey = "known_hosts";
|
|
109
|
+
var gitSyncImage = "registry.k8s.io/git-sync/git-sync:v4.7.1@sha256:c5e1976da735bf0b53979f079a07475d77174c51863cd084e928ff6074480717";
|
|
110
|
+
function buildGitSyncContainer(repository, ref) {
|
|
111
|
+
return {
|
|
112
|
+
name: "git-sync",
|
|
113
|
+
image: gitSyncImage,
|
|
114
|
+
env: [
|
|
115
|
+
{ name: "GITSYNC_REPO", value: `ssh://git@ssh.github.com:443/${repository}.git` },
|
|
116
|
+
{ name: "GITSYNC_REF", value: ref },
|
|
117
|
+
{ name: "GITSYNC_ROOT", value: definitionsRoot },
|
|
118
|
+
{ name: "GITSYNC_LINK", value: "current" },
|
|
119
|
+
{ name: "GITSYNC_PERIOD", value: "60s" },
|
|
120
|
+
{ name: "GITSYNC_DEPTH", value: "1" },
|
|
121
|
+
{ name: "GITSYNC_SSH_KEY_FILE", value: `/etc/git-secret/${definitionsDeployKeyKey}` },
|
|
122
|
+
{ name: "GITSYNC_SSH_KNOWN_HOSTS", value: "true" },
|
|
123
|
+
{
|
|
124
|
+
name: "GITSYNC_SSH_KNOWN_HOSTS_FILE",
|
|
125
|
+
value: `/etc/git-secret/${definitionsKnownHostsKey}`
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
volumeMounts: [
|
|
129
|
+
{ name: "definitions", mountPath: definitionsRoot },
|
|
130
|
+
{ name: "definitions-key", mountPath: "/etc/git-secret", readOnly: true },
|
|
131
|
+
{ name: "git-sync-tmp", mountPath: "/tmp" }
|
|
132
|
+
],
|
|
133
|
+
securityContext: { ...lockedDown, runAsUser: 65533, runAsGroup: 65533 },
|
|
134
|
+
resources: { requests: { cpu: "10m", memory: "32Mi" }, limits: { memory: "128Mi" } }
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// src/build-nixie-web-spec.ts
|
|
138
|
+
var nixieWebLabels = { app: "nixie-web" };
|
|
139
|
+
var nixieWebPort = 3000;
|
|
140
|
+
function buildNixieWebSpec(inputs) {
|
|
141
|
+
return {
|
|
142
|
+
replicas: 1,
|
|
143
|
+
selector: { matchLabels: nixieWebLabels },
|
|
144
|
+
template: {
|
|
145
|
+
metadata: { labels: nixieWebLabels },
|
|
146
|
+
spec: {
|
|
147
|
+
securityContext: {
|
|
148
|
+
runAsNonRoot: true,
|
|
149
|
+
seccompProfile: { type: "RuntimeDefault" }
|
|
150
|
+
},
|
|
151
|
+
volumes: [{ name: "tmp", emptyDir: {} }],
|
|
152
|
+
containers: [
|
|
153
|
+
{
|
|
154
|
+
name: "web",
|
|
155
|
+
image: inputs.image,
|
|
156
|
+
ports: [{ name: "http", containerPort: nixieWebPort }],
|
|
157
|
+
env: [
|
|
158
|
+
{ name: "NIXIE_API_URL", value: inputs.apiURL },
|
|
159
|
+
{ name: "PORT", value: String(nixieWebPort) }
|
|
160
|
+
],
|
|
161
|
+
livenessProbe: {
|
|
162
|
+
httpGet: { path: "/health/live", port: nixieWebPort },
|
|
163
|
+
periodSeconds: 30,
|
|
164
|
+
failureThreshold: 3
|
|
165
|
+
},
|
|
166
|
+
readinessProbe: {
|
|
167
|
+
httpGet: { path: "/health/ready", port: nixieWebPort },
|
|
168
|
+
periodSeconds: 10
|
|
169
|
+
},
|
|
170
|
+
volumeMounts: [{ name: "tmp", mountPath: "/tmp" }],
|
|
171
|
+
securityContext: {
|
|
172
|
+
allowPrivilegeEscalation: false,
|
|
173
|
+
readOnlyRootFilesystem: true,
|
|
174
|
+
capabilities: { drop: ["ALL"] },
|
|
175
|
+
runAsUser: 1000,
|
|
176
|
+
runAsGroup: 1000
|
|
177
|
+
},
|
|
178
|
+
resources: { requests: { cpu: "20m", memory: "96Mi" }, limits: { memory: "512Mi" } }
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// src/create-nixie.ts
|
|
186
|
+
import { apps, batch, core } from "@pulumi/kubernetes";
|
|
187
|
+
import { ComponentResource, interpolate, rootStackResource, secret } from "@pulumi/pulumi";
|
|
188
|
+
|
|
189
|
+
// src/build-backup-pod-spec.ts
|
|
190
|
+
function buildBackupPodSpec(inputs) {
|
|
191
|
+
return {
|
|
192
|
+
restartPolicy: "OnFailure",
|
|
193
|
+
securityContext: {
|
|
194
|
+
runAsNonRoot: true,
|
|
195
|
+
runAsUser: 10001,
|
|
196
|
+
runAsGroup: 10001,
|
|
197
|
+
fsGroup: 10001,
|
|
198
|
+
seccompProfile: { type: "RuntimeDefault" }
|
|
199
|
+
},
|
|
200
|
+
automountServiceAccountToken: false,
|
|
201
|
+
imagePullSecrets: [{ name: inputs.pullSecret }],
|
|
202
|
+
containers: [
|
|
203
|
+
{
|
|
204
|
+
name: "backup",
|
|
205
|
+
image: inputs.image,
|
|
206
|
+
command: ["/bin/sh", "/opt/nixie-backup/backup.sh"],
|
|
207
|
+
args: ["backup"],
|
|
208
|
+
env: [
|
|
209
|
+
{ name: "STATE_DIR", value: "/state" },
|
|
210
|
+
{ name: "HOME", value: "/tmp" }
|
|
211
|
+
],
|
|
212
|
+
envFrom: [{ secretRef: { name: inputs.envSecret } }],
|
|
213
|
+
volumeMounts: [
|
|
214
|
+
{ name: "state", mountPath: "/state" },
|
|
215
|
+
{ name: "script", mountPath: "/opt/nixie-backup", readOnly: true },
|
|
216
|
+
{ name: "tmp", mountPath: "/tmp" }
|
|
217
|
+
],
|
|
218
|
+
resources: { requests: { cpu: "50m", memory: "64Mi" }, limits: { memory: "256Mi" } },
|
|
219
|
+
securityContext: { allowPrivilegeEscalation: false, capabilities: { drop: ["ALL"] } }
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
volumes: [
|
|
223
|
+
{ name: "state", persistentVolumeClaim: { claimName: inputs.claim } },
|
|
224
|
+
{ name: "script", configMap: { name: inputs.scriptConfigMap } },
|
|
225
|
+
{ name: "tmp", emptyDir: {} }
|
|
226
|
+
]
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/build-service-args.ts
|
|
231
|
+
function buildServiceArgs(shape) {
|
|
232
|
+
return {
|
|
233
|
+
metadata: {
|
|
234
|
+
name: shape.name,
|
|
235
|
+
namespace: shape.namespace,
|
|
236
|
+
annotations: { "pulumi.com/skipAwait": "true" }
|
|
237
|
+
},
|
|
238
|
+
spec: {
|
|
239
|
+
selector: shape.labels,
|
|
240
|
+
ports: [{ name: "http", port: shape.port, targetPort: "http" }]
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/create-nixie.ts
|
|
246
|
+
var rolloutTimeouts = { create: "30m", update: "30m" };
|
|
247
|
+
function createNixie(name, args, opts = {}) {
|
|
248
|
+
const component = new ComponentResource("heynixie:k8s:Nixie", name, {}, opts);
|
|
249
|
+
const childOptions = {
|
|
250
|
+
parent: component,
|
|
251
|
+
aliases: [{ parent: rootStackResource }]
|
|
252
|
+
};
|
|
253
|
+
const api = new core.v1.Service("nixie", buildServiceArgs({
|
|
254
|
+
name: "nixie",
|
|
255
|
+
namespace: args.namespace,
|
|
256
|
+
labels: nixieLabels,
|
|
257
|
+
port: nixieAPIPort
|
|
258
|
+
}), childOptions);
|
|
259
|
+
const statefulSet = new apps.v1.StatefulSet("nixie", {
|
|
260
|
+
metadata: { name: "nixie", namespace: args.namespace },
|
|
261
|
+
spec: buildNixieSpec({
|
|
262
|
+
image: args.image,
|
|
263
|
+
serviceName: api.metadata.name,
|
|
264
|
+
configMap: createConfig(args, childOptions),
|
|
265
|
+
secret: createSecrets(args, childOptions),
|
|
266
|
+
definitionsSecret: createDefinitionsKey(args, childOptions),
|
|
267
|
+
definitionsRepository: args.definitions.repository,
|
|
268
|
+
definitionsRef: args.definitions.ref,
|
|
269
|
+
storageClassName: args.storageClassName
|
|
270
|
+
})
|
|
271
|
+
}, { ...childOptions, customTimeouts: rolloutTimeouts });
|
|
272
|
+
const web = new core.v1.Service("nixie-web", buildServiceArgs({
|
|
273
|
+
name: "nixie-web",
|
|
274
|
+
namespace: args.namespace,
|
|
275
|
+
labels: nixieWebLabels,
|
|
276
|
+
port: nixieWebPort
|
|
277
|
+
}), childOptions);
|
|
278
|
+
createWebDeployment(args, api, {
|
|
279
|
+
...childOptions,
|
|
280
|
+
dependsOn: [statefulSet],
|
|
281
|
+
customTimeouts: rolloutTimeouts
|
|
282
|
+
});
|
|
283
|
+
if (args.backup !== undefined) {
|
|
284
|
+
createBackupJob(args.namespace, args.backup, statefulSet, childOptions);
|
|
285
|
+
}
|
|
286
|
+
return { component, api, web, statefulSet };
|
|
287
|
+
}
|
|
288
|
+
function createConfig(args, opts) {
|
|
289
|
+
const config = new core.v1.ConfigMap("nixie-config", { metadata: { namespace: args.namespace }, data: { [nixieConfigKey]: args.config } }, opts);
|
|
290
|
+
return config.metadata.name;
|
|
291
|
+
}
|
|
292
|
+
function createSecrets(args, opts) {
|
|
293
|
+
const secrets = new core.v1.Secret("nixie-secrets", {
|
|
294
|
+
metadata: { namespace: args.namespace },
|
|
295
|
+
stringData: {
|
|
296
|
+
[nixieSecretsFileKey]: args.secretsFile,
|
|
297
|
+
[nixieAgeKeyKey]: secret(args.ageKey)
|
|
298
|
+
}
|
|
299
|
+
}, opts);
|
|
300
|
+
return secrets.metadata.name;
|
|
301
|
+
}
|
|
302
|
+
var githubKnownHosts = `[ssh.github.com]:443 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
|
303
|
+
`;
|
|
304
|
+
function createDefinitionsKey(args, opts) {
|
|
305
|
+
const key = new core.v1.Secret("nixie-definitions-key", {
|
|
306
|
+
metadata: { namespace: args.namespace },
|
|
307
|
+
stringData: {
|
|
308
|
+
[definitionsDeployKeyKey]: secret(args.definitions.deployKey).apply((value) => `${value.trimEnd()}
|
|
309
|
+
`),
|
|
310
|
+
[definitionsKnownHostsKey]: githubKnownHosts
|
|
311
|
+
}
|
|
312
|
+
}, opts);
|
|
313
|
+
return key.metadata.name;
|
|
314
|
+
}
|
|
315
|
+
function createWebDeployment(args, api, opts) {
|
|
316
|
+
return new apps.v1.Deployment("nixie-web", {
|
|
317
|
+
metadata: { name: "nixie-web", namespace: args.namespace },
|
|
318
|
+
spec: buildNixieWebSpec({
|
|
319
|
+
image: args.web.image,
|
|
320
|
+
apiURL: interpolate`http://${api.metadata.name}.${args.namespace}.svc.cluster.local:${nixieAPIPort}`
|
|
321
|
+
})
|
|
322
|
+
}, opts);
|
|
323
|
+
}
|
|
324
|
+
var backupScriptConfigMap = "nixie-backup-script";
|
|
325
|
+
var backupEnvSecret = "nixie-backup";
|
|
326
|
+
function createBackupJob(namespace, backup, statefulSet, opts) {
|
|
327
|
+
const env = new core.v1.Secret("nixie-backup", {
|
|
328
|
+
metadata: { name: backupEnvSecret, namespace },
|
|
329
|
+
stringData: backup.environment
|
|
330
|
+
}, opts);
|
|
331
|
+
const script = new core.v1.ConfigMap("nixie-backup-script", {
|
|
332
|
+
metadata: { name: backupScriptConfigMap, namespace },
|
|
333
|
+
data: { "backup.sh": backup.script }
|
|
334
|
+
}, opts);
|
|
335
|
+
return new batch.v1.CronJob("nixie-backup", {
|
|
336
|
+
metadata: { name: "nixie-backup", namespace },
|
|
337
|
+
spec: {
|
|
338
|
+
schedule: backup.schedule,
|
|
339
|
+
timeZone: backup.timeZone,
|
|
340
|
+
suspend: false,
|
|
341
|
+
concurrencyPolicy: "Forbid",
|
|
342
|
+
jobTemplate: {
|
|
343
|
+
spec: {
|
|
344
|
+
backoffLimit: 2,
|
|
345
|
+
template: {
|
|
346
|
+
spec: buildBackupPodSpec({
|
|
347
|
+
image: backup.image,
|
|
348
|
+
claim: "data-nixie-0",
|
|
349
|
+
scriptConfigMap: backupScriptConfigMap,
|
|
350
|
+
envSecret: backupEnvSecret,
|
|
351
|
+
pullSecret: backup.pullSecret
|
|
352
|
+
})
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}, { ...opts, dependsOn: [env, script, statefulSet] });
|
|
358
|
+
}
|
|
359
|
+
export {
|
|
360
|
+
createNixie,
|
|
361
|
+
nixieAPIPort,
|
|
362
|
+
nixieWebPort
|
|
363
|
+
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Input } from '@pulumi/pulumi';
|
|
2
|
+
export interface NixieArgs {
|
|
3
|
+
readonly namespace: Input<string>;
|
|
4
|
+
readonly image: Input<string>;
|
|
5
|
+
readonly config: Input<string>;
|
|
6
|
+
readonly secretsFile: Input<string>;
|
|
7
|
+
readonly ageKey: Input<string>;
|
|
8
|
+
readonly definitions: NixieDefinitionsArgs;
|
|
9
|
+
readonly storageClassName: Input<string>;
|
|
10
|
+
readonly web: NixieWebArgs;
|
|
11
|
+
readonly backup?: NixieBackupArgs;
|
|
12
|
+
}
|
|
13
|
+
export interface NixieWebArgs {
|
|
14
|
+
readonly image: Input<string>;
|
|
15
|
+
}
|
|
16
|
+
export interface NixieBackupArgs {
|
|
17
|
+
readonly image: Input<string>;
|
|
18
|
+
readonly pullSecret: Input<string>;
|
|
19
|
+
readonly script: Input<string>;
|
|
20
|
+
readonly schedule: Input<string>;
|
|
21
|
+
readonly timeZone: Input<string>;
|
|
22
|
+
readonly environment: Record<string, Input<string>>;
|
|
23
|
+
}
|
|
24
|
+
export interface NixieDefinitionsArgs {
|
|
25
|
+
readonly repository: string;
|
|
26
|
+
readonly ref: Input<string>;
|
|
27
|
+
readonly deployKey: Input<string>;
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heynixie/pulumi-k8s",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
3
|
+
"version": "0.42.0",
|
|
4
|
+
"description": "A Pulumi component that runs nixie on Kubernetes",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/zgeoff/nixie.git",
|
|
9
|
+
"directory": "deploy/pulumi-k8s"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"README.md",
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"type": "module",
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"typecheck": "tsrs --noEmit"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@pulumi/kubernetes": "4.34.2",
|
|
28
|
+
"@pulumi/pulumi": "3.269.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@pulumi/kubernetes": ">=4.34.2 <5",
|
|
32
|
+
"@pulumi/pulumi": ">=3.268.0 <4"
|
|
33
|
+
}
|
|
10
34
|
}
|