redkite 0.1.13 → 0.1.14
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 +50 -3
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +3 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/proxy.d.ts +5 -0
- package/dist/services/proxy.d.ts.map +1 -1
- package/dist/services/proxy.js +56 -2
- package/dist/services/proxy.js.map +1 -1
- package/dist/topology.d.ts.map +1 -1
- package/dist/topology.js +8 -1
- package/dist/topology.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/services/index.ts +3 -0
- package/src/services/proxy.ts +71 -3
- package/src/topology.ts +9 -1
- package/src/types.ts +18 -0
package/README.md
CHANGED
|
@@ -571,15 +571,62 @@ proxy: nginx({
|
|
|
571
571
|
`server` lines go inside the server block above the locations, `location` lines
|
|
572
572
|
inside every location. Both are written as nginx sees them, semicolons and all.
|
|
573
573
|
|
|
574
|
+
`locations` is for one app's location alone, keyed by the app's name:
|
|
575
|
+
|
|
576
|
+
```ts
|
|
577
|
+
proxy: nginx({
|
|
578
|
+
location: ["proxy_buffering off;"],
|
|
579
|
+
locations: {
|
|
580
|
+
backend: ["proxy_read_timeout 300s;", "proxy_buffering on;"],
|
|
581
|
+
},
|
|
582
|
+
}),
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
Those lines come after the ones every location gets, so `proxy_buffering on;`
|
|
586
|
+
replaces `off` in the backend's location and the frontend's keeps `off`. A name
|
|
587
|
+
that is not one of the deployment's apps is refused, and so is `proxy_pass` in
|
|
588
|
+
any location: where a location sends a request is its app's route.
|
|
589
|
+
|
|
590
|
+
#### Logging
|
|
591
|
+
|
|
592
|
+
Without `logs`, nginx logs the way its image does, to the container's own output.
|
|
593
|
+
`logs` says where instead, or that there is nothing to log:
|
|
594
|
+
|
|
595
|
+
```ts
|
|
596
|
+
proxy: nginx({
|
|
597
|
+
logs: { directory: "/var/log/acme", errors: "warn" },
|
|
598
|
+
}),
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
| `logs` | What nginx writes |
|
|
602
|
+
| --- | --- |
|
|
603
|
+
| absent | Whatever the image does, which for `nginx:stable` is `docker logs` |
|
|
604
|
+
| `false` | No access log, and errors nowhere: `error_log` has no off, so they go to `/dev/null` at `emerg` |
|
|
605
|
+
| `{}` | Access and errors on the container's output, stated rather than left to the image |
|
|
606
|
+
| `{ directory }` | Files in that directory on the deploy host |
|
|
607
|
+
|
|
608
|
+
`directory` is mounted where nginx writes, and each environment writes files of
|
|
609
|
+
its own into it, `staging.access.log` and `staging.error.log`, so two
|
|
610
|
+
environments on one host can share it. It has to be an absolute path: docker
|
|
611
|
+
reads anything else as the name of a volume. `access: false` turns off only the
|
|
612
|
+
access log. `errors` is how severe something has to be to reach the error log,
|
|
613
|
+
`error` unless it says otherwise.
|
|
614
|
+
|
|
615
|
+
The logging lines go at the top of the server block, so an `access_log` written
|
|
616
|
+
in `server` still replaces them, and an `access_log off;` in one app's
|
|
617
|
+
`locations` quiets just that route. Changing any of it recreates the proxy
|
|
618
|
+
container on the next deploy, since the mount and the config are what it was
|
|
619
|
+
created from.
|
|
620
|
+
|
|
574
621
|
**A line replaces rather than repeats.** nginx refuses a second
|
|
575
622
|
`proxy_read_timeout` outright instead of letting the later one win, so
|
|
576
623
|
`proxy_read_timeout 300s;` takes the place of the 30s redkite would have set. A
|
|
577
624
|
header keeps its own name as part of that, so `proxy_set_header Host $host;`
|
|
578
625
|
replaces only the Host header and leaves the other three alone.
|
|
579
626
|
|
|
580
|
-
The upstreams, the location per route, the failover
|
|
581
|
-
A `listen` in the server block is refused: the published port maps
|
|
582
|
-
inside the container, so only one side of that may say it.
|
|
627
|
+
The upstreams, the location per route, the failover, `listen` and `proxy_pass`
|
|
628
|
+
stay derived. A `listen` in the server block is refused: the published port maps
|
|
629
|
+
onto the one inside the container, so only one side of that may say it.
|
|
583
630
|
|
|
584
631
|
### Services
|
|
585
632
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAKtE,wBAAgB,KAAK,CAAC,OAAO,GAAE,SAAc,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAKtE,wBAAgB,KAAK,CAAC,OAAO,GAAE,SAAc,GAAG,SAAS,CAUxD;AAED,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,WAAW,CAW7D;AAED,KAAK,eAAe,GAAG;IAGrB,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,WAAW,CAa9D"}
|
package/dist/services/index.js
CHANGED
|
@@ -7,6 +7,9 @@ export function nginx(options = {}) {
|
|
|
7
7
|
maxBodySize: options.maxBodySize ?? "1M",
|
|
8
8
|
server: options.server ?? [],
|
|
9
9
|
location: options.location ?? [],
|
|
10
|
+
locations: options.locations ?? {},
|
|
11
|
+
// Carried as given: absent and false mean different things
|
|
12
|
+
logs: options.logs,
|
|
10
13
|
};
|
|
11
14
|
}
|
|
12
15
|
export function redis(options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAEA,6EAA6E;AAC7E,4EAA4E;AAC5E,kEAAkE;AAClE,MAAM,UAAU,KAAK,CAAC,UAAqB,EAAE;IAC3C,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,cAAc;QACtC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAEA,6EAA6E;AAC7E,4EAA4E;AAC5E,kEAAkE;AAClE,MAAM,UAAU,KAAK,CAAC,UAAqB,EAAE;IAC3C,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,cAAc;QACtC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;QAChC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;QAClC,2DAA2D;QAC3D,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC;AACJ,CAAC;AASD,MAAM,UAAU,KAAK,CAAC,UAAwB,EAAE;IAC9C,OAAO;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;QACjC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO;QAC/B,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,wEAAwE;QACxE,oEAAoE;QACpE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;KAC9C,CAAC;AACJ,CAAC;AAcD,MAAM,UAAU,QAAQ,CAAC,OAAwB;IAC/C,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,oBAAoB;QAC5C,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,UAAU;QAClC,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,wEAAwE;QACxE,yEAAyE;QACzE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,IAAI,EAAE,0BAA0B,EAAE;KACjE,CAAC;AACJ,CAAC"}
|
package/dist/services/proxy.d.ts
CHANGED
|
@@ -2,6 +2,11 @@ import type { Topology } from "../topology.js";
|
|
|
2
2
|
import type { Deployment, ProxySpec, ServiceSpec } from "../types.js";
|
|
3
3
|
export declare const LISTEN_PORT = 3000;
|
|
4
4
|
export declare const PROXY = "nginx";
|
|
5
|
+
export declare const LOG_DIRECTORY = "/var/log/nginx";
|
|
5
6
|
export declare function proxyService(config: Deployment): ServiceSpec;
|
|
6
7
|
export declare function renderProxy(topology: Topology, proxy?: ProxySpec): string;
|
|
8
|
+
export declare function logMount(proxy: ProxySpec | undefined): {
|
|
9
|
+
volume: string;
|
|
10
|
+
mountPath: string;
|
|
11
|
+
} | undefined;
|
|
7
12
|
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/services/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/services/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAa,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAyBjF,eAAO,MAAM,WAAW,OAAO,CAAC;AAIhC,eAAO,MAAM,KAAK,UAAU,CAAC;AAG7B,eAAO,MAAM,aAAa,mBAAmB,CAAC;AAI9C,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,CAM5D;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,GAAE,SAAc,UA8BpE;AA0DD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;;;cAYpD"}
|
package/dist/services/proxy.js
CHANGED
|
@@ -22,6 +22,8 @@ export const LISTEN_PORT = 3000;
|
|
|
22
22
|
// What the derived proxy is called. A service by this name would be a second
|
|
23
23
|
// container claiming the first one's, so the config surface refuses it
|
|
24
24
|
export const PROXY = "nginx";
|
|
25
|
+
// Where nginx writes inside its container. A log directory is mounted here
|
|
26
|
+
export const LOG_DIRECTORY = "/var/log/nginx";
|
|
25
27
|
// Not something a deployment lists. Apps carry routes, routes need something
|
|
26
28
|
// to resolve them, and this says what that something is
|
|
27
29
|
export function proxyService(config) {
|
|
@@ -32,14 +34,19 @@ export function proxyService(config) {
|
|
|
32
34
|
};
|
|
33
35
|
}
|
|
34
36
|
export function renderProxy(topology, proxy = {}) {
|
|
37
|
+
assertNotDerived(proxy.server ?? []);
|
|
38
|
+
assertLocations(topology, proxy);
|
|
35
39
|
const upstreams = topology.apps.map((app) => upstream(app)).join("\n\n");
|
|
36
40
|
// Longest route first, so "/api/" is not shadowed by the "/" catch-all
|
|
37
41
|
const ordered = [...topology.apps].sort((a, b) => b.route.length - a.route.length);
|
|
38
|
-
const locations = ordered
|
|
39
|
-
|
|
42
|
+
const locations = ordered
|
|
43
|
+
.map((app) => location(app, [...(proxy.location ?? []), ...(proxy.locations?.[app.name] ?? [])]))
|
|
44
|
+
.join("\n\n");
|
|
45
|
+
// Logging leads the lines written by hand, so an access_log there replaces it
|
|
40
46
|
const server = settled([
|
|
41
47
|
`merge_slashes off;`,
|
|
42
48
|
`client_max_body_size ${proxy.maxBodySize ?? "1M"};`,
|
|
49
|
+
...logging(proxy.logs, topology.environment),
|
|
43
50
|
...(proxy.server ?? []),
|
|
44
51
|
]);
|
|
45
52
|
return `resolver 127.0.0.1 valid=5s;
|
|
@@ -81,6 +88,53 @@ function assertNotDerived(lines) {
|
|
|
81
88
|
throw new Error(`The proxy's server block says ${listening.trim()}, and the port it listens ` +
|
|
82
89
|
"on inside its container is what publicPort is published onto");
|
|
83
90
|
}
|
|
91
|
+
// Nothing for a deployment that says nothing, so a proxy it already runs is not
|
|
92
|
+
// recreated for a config that means the same. error_log has no off: the
|
|
93
|
+
// quietest it gets is emerg, written nowhere
|
|
94
|
+
function logging(logs, environment) {
|
|
95
|
+
if (logs === undefined)
|
|
96
|
+
return [];
|
|
97
|
+
if (logs === false)
|
|
98
|
+
return ["access_log off;", "error_log /dev/null emerg;"];
|
|
99
|
+
// Named for the environment, since two environments on one host may be given
|
|
100
|
+
// the same directory
|
|
101
|
+
const access = logs.directory ? `${LOG_DIRECTORY}/${environment}.access.log` : "/dev/stdout";
|
|
102
|
+
const error = logs.directory ? `${LOG_DIRECTORY}/${environment}.error.log` : "/dev/stderr";
|
|
103
|
+
return [
|
|
104
|
+
logs.access === false ? "access_log off;" : `access_log ${access};`,
|
|
105
|
+
`error_log ${error} ${logs.errors ?? "error"};`,
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
// The host directory a deployment's logs land in, mounted where nginx writes.
|
|
109
|
+
// Absolute, because docker reads anything else as the name of a volume and the
|
|
110
|
+
// logs would go somewhere nobody asked for
|
|
111
|
+
export function logMount(proxy) {
|
|
112
|
+
const directory = proxy?.logs ? proxy.logs.directory : undefined;
|
|
113
|
+
if (directory === undefined)
|
|
114
|
+
return undefined;
|
|
115
|
+
if (!directory.startsWith("/") || /[:,]/.test(directory)) {
|
|
116
|
+
throw new Error(`The proxy logs to ${directory}, which has to be an absolute path on the deploy ` +
|
|
117
|
+
"host with no colon or comma in it: docker reads anything else as a volume name");
|
|
118
|
+
}
|
|
119
|
+
return { volume: directory, mountPath: LOG_DIRECTORY };
|
|
120
|
+
}
|
|
121
|
+
// An app name nobody has is a typo, and a location it named would otherwise be
|
|
122
|
+
// settings nothing reads. proxy_pass is what routes the location to its app, so
|
|
123
|
+
// replacing it is not a setting but a broken route
|
|
124
|
+
function assertLocations(topology, proxy) {
|
|
125
|
+
const apps = new Set(topology.apps.map((app) => app.name));
|
|
126
|
+
const unknown = Object.keys(proxy.locations ?? {}).filter((name) => !apps.has(name));
|
|
127
|
+
if (unknown.length > 0) {
|
|
128
|
+
throw new Error(`The proxy sets locations for ${unknown.join(", ")}, which this deployment has ` +
|
|
129
|
+
`no app by that name for. Its apps are ${[...apps].join(", ")}`);
|
|
130
|
+
}
|
|
131
|
+
const lines = [...(proxy.location ?? []), ...Object.values(proxy.locations ?? {}).flat()];
|
|
132
|
+
const routing = lines.find((line) => directive(line) === "proxy_pass");
|
|
133
|
+
if (!routing)
|
|
134
|
+
return;
|
|
135
|
+
throw new Error(`A proxy location says ${routing.trim()}, and where a location sends a request ` +
|
|
136
|
+
"is its app's route, which redkite derives");
|
|
137
|
+
}
|
|
84
138
|
function indented(lines, by) {
|
|
85
139
|
return lines.map((line) => " ".repeat(by) + line).join("\n");
|
|
86
140
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/services/proxy.ts"],"names":[],"mappings":"AAGA,6EAA6E;AAC7E,8EAA8E;AAC9E,sDAAsD;AACtD,EAAE;AACF,gFAAgF;AAChF,8DAA8D;AAE9D,MAAM,UAAU,GAAG;IACjB,mCAAmC;IACnC,8DAA8D;IAC9D,+CAA+C;IAC/C,6CAA6C;CAC9C,CAAC;AAEF,MAAM,QAAQ,GAAG;IACf,2BAA2B;IAC3B,yBAAyB;IACzB,sDAAsD;IACtD,8BAA8B;CAC/B,CAAC;AAEF,8EAA8E;AAC9E,6EAA6E;AAC7E,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC;AAEhC,6EAA6E;AAC7E,uEAAuE;AACvE,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC;AAE7B,6EAA6E;AAC7E,wDAAwD;AACxD,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,OAAO;QACL,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,IAAI,cAAc;QAC5C,OAAO,EAAE,QAAQ;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAkB,EAAE,QAAmB,EAAE;IACnE,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzE,uEAAuE;IACvE,MAAM,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/services/proxy.ts"],"names":[],"mappings":"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"}
|
package/dist/topology.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,UAAU,EAAe,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,UAAU,EAAe,MAAM,YAAY,CAAC;AAenE,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IAEb,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAE5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC,CAAC;AAEF,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,QAAQ,CAkD7E"}
|
package/dist/topology.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { environmentOf } from "./config.js";
|
|
2
2
|
import { mountFor } from "./layout.js";
|
|
3
|
+
import { logMount } from "./services/proxy.js";
|
|
3
4
|
// Every name and address the deployment uses, derived from the app list. This
|
|
4
5
|
// is the file that replaces the constants block: nothing is chosen by hand, so
|
|
5
6
|
// adding an app cannot collide with an address somebody already picked.
|
|
@@ -34,7 +35,9 @@ export function topologyFor(config, environment) {
|
|
|
34
35
|
name: "nginx",
|
|
35
36
|
container: `${prefix}-nginx`,
|
|
36
37
|
address: address(NGINX_OCTET),
|
|
37
|
-
|
|
38
|
+
// Only a directory the deployment named. Nothing mounted otherwise, so a
|
|
39
|
+
// proxy that says nothing about its logs is the container it always was
|
|
40
|
+
volumes: routerVolumes(config),
|
|
38
41
|
},
|
|
39
42
|
apps,
|
|
40
43
|
services,
|
|
@@ -88,6 +91,10 @@ function serviceTopology(service, prefix, address, index) {
|
|
|
88
91
|
})),
|
|
89
92
|
};
|
|
90
93
|
}
|
|
94
|
+
function routerVolumes(config) {
|
|
95
|
+
const logs = logMount(config.proxy);
|
|
96
|
+
return logs ? [logs] : [];
|
|
97
|
+
}
|
|
91
98
|
// Nginx resolves upstreams by container name, apps reach services by alias
|
|
92
99
|
function extraHosts(apps, services, declared = {}) {
|
|
93
100
|
const hosts = {};
|
package/dist/topology.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topology.js","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"topology.js","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -30,6 +30,13 @@ export type ProxySpec = {
|
|
|
30
30
|
maxBodySize?: string;
|
|
31
31
|
server?: string[];
|
|
32
32
|
location?: string[];
|
|
33
|
+
locations?: Record<string, string[]>;
|
|
34
|
+
logs?: false | ProxyLogs;
|
|
35
|
+
};
|
|
36
|
+
export type ProxyLogs = {
|
|
37
|
+
directory?: string;
|
|
38
|
+
access?: boolean;
|
|
39
|
+
errors?: "debug" | "info" | "notice" | "warn" | "error" | "crit" | "alert" | "emerg";
|
|
33
40
|
};
|
|
34
41
|
export type ServiceSpec = {
|
|
35
42
|
name: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAM1C,MAAM,MAAM,WAAW,GAAG;IAKxB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAE3B,MAAM,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,MAAM,CAAC;IAIf,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,IAAI,CAAC,EAAE,UAAU,CAAC;IAIlB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAIpC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAErC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAIlD,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC;AAMF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAI7E,MAAM,MAAM,QAAQ,GAGhB,YAAY,GAGZ,QAAQ,GAGR,KAAK,CAAC;AAEV,MAAM,MAAM,UAAU,GAAG;IAEvB,OAAO,EAAE,MAAM,CAAC;IAEhB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAIF,MAAM,MAAM,SAAS,GAAG;IAEtB,QAAQ,EAAE,MAAM,CAAC;IAEjB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAGF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;AAKjD,MAAM,MAAM,SAAS,GAAG;IAEtB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAGlB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/services/index.ts
CHANGED
|
@@ -9,6 +9,9 @@ export function nginx(options: ProxySpec = {}): ProxySpec {
|
|
|
9
9
|
maxBodySize: options.maxBodySize ?? "1M",
|
|
10
10
|
server: options.server ?? [],
|
|
11
11
|
location: options.location ?? [],
|
|
12
|
+
locations: options.locations ?? {},
|
|
13
|
+
// Carried as given: absent and false mean different things
|
|
14
|
+
logs: options.logs,
|
|
12
15
|
};
|
|
13
16
|
}
|
|
14
17
|
|
package/src/services/proxy.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AppTopology, Topology } from "../topology.js";
|
|
2
|
-
import type { Deployment, ProxySpec, ServiceSpec } from "../types.js";
|
|
2
|
+
import type { Deployment, ProxyLogs, ProxySpec, ServiceSpec } from "../types.js";
|
|
3
3
|
|
|
4
4
|
// The proxy every route is resolved by: what it is, and the configuration it
|
|
5
5
|
// runs. Both halves here, because a deployment does not list this service and
|
|
@@ -30,6 +30,9 @@ export const LISTEN_PORT = 3000;
|
|
|
30
30
|
// container claiming the first one's, so the config surface refuses it
|
|
31
31
|
export const PROXY = "nginx";
|
|
32
32
|
|
|
33
|
+
// Where nginx writes inside its container. A log directory is mounted here
|
|
34
|
+
export const LOG_DIRECTORY = "/var/log/nginx";
|
|
35
|
+
|
|
33
36
|
// Not something a deployment lists. Apps carry routes, routes need something
|
|
34
37
|
// to resolve them, and this says what that something is
|
|
35
38
|
export function proxyService(config: Deployment): ServiceSpec {
|
|
@@ -41,16 +44,22 @@ export function proxyService(config: Deployment): ServiceSpec {
|
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export function renderProxy(topology: Topology, proxy: ProxySpec = {}) {
|
|
47
|
+
assertNotDerived(proxy.server ?? []);
|
|
48
|
+
assertLocations(topology, proxy);
|
|
49
|
+
|
|
44
50
|
const upstreams = topology.apps.map((app) => upstream(app)).join("\n\n");
|
|
45
51
|
// Longest route first, so "/api/" is not shadowed by the "/" catch-all
|
|
46
52
|
const ordered = [...topology.apps].sort((a, b) => b.route.length - a.route.length);
|
|
47
|
-
const locations = ordered.map((app) => location(app, proxy.location ?? [])).join("\n\n");
|
|
48
53
|
|
|
49
|
-
|
|
54
|
+
const locations = ordered
|
|
55
|
+
.map((app) => location(app, [...(proxy.location ?? []), ...(proxy.locations?.[app.name] ?? [])]))
|
|
56
|
+
.join("\n\n");
|
|
50
57
|
|
|
58
|
+
// Logging leads the lines written by hand, so an access_log there replaces it
|
|
51
59
|
const server = settled([
|
|
52
60
|
`merge_slashes off;`,
|
|
53
61
|
`client_max_body_size ${proxy.maxBodySize ?? "1M"};`,
|
|
62
|
+
...logging(proxy.logs, topology.environment),
|
|
54
63
|
...(proxy.server ?? []),
|
|
55
64
|
]);
|
|
56
65
|
|
|
@@ -101,6 +110,65 @@ function assertNotDerived(lines: string[]) {
|
|
|
101
110
|
);
|
|
102
111
|
}
|
|
103
112
|
|
|
113
|
+
// Nothing for a deployment that says nothing, so a proxy it already runs is not
|
|
114
|
+
// recreated for a config that means the same. error_log has no off: the
|
|
115
|
+
// quietest it gets is emerg, written nowhere
|
|
116
|
+
function logging(logs: false | ProxyLogs | undefined, environment: string) {
|
|
117
|
+
if (logs === undefined) return [];
|
|
118
|
+
if (logs === false) return ["access_log off;", "error_log /dev/null emerg;"];
|
|
119
|
+
|
|
120
|
+
// Named for the environment, since two environments on one host may be given
|
|
121
|
+
// the same directory
|
|
122
|
+
const access = logs.directory ? `${LOG_DIRECTORY}/${environment}.access.log` : "/dev/stdout";
|
|
123
|
+
const error = logs.directory ? `${LOG_DIRECTORY}/${environment}.error.log` : "/dev/stderr";
|
|
124
|
+
|
|
125
|
+
return [
|
|
126
|
+
logs.access === false ? "access_log off;" : `access_log ${access};`,
|
|
127
|
+
`error_log ${error} ${logs.errors ?? "error"};`,
|
|
128
|
+
];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// The host directory a deployment's logs land in, mounted where nginx writes.
|
|
132
|
+
// Absolute, because docker reads anything else as the name of a volume and the
|
|
133
|
+
// logs would go somewhere nobody asked for
|
|
134
|
+
export function logMount(proxy: ProxySpec | undefined) {
|
|
135
|
+
const directory = proxy?.logs ? proxy.logs.directory : undefined;
|
|
136
|
+
if (directory === undefined) return undefined;
|
|
137
|
+
|
|
138
|
+
if (!directory.startsWith("/") || /[:,]/.test(directory)) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`The proxy logs to ${directory}, which has to be an absolute path on the deploy ` +
|
|
141
|
+
"host with no colon or comma in it: docker reads anything else as a volume name",
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return { volume: directory, mountPath: LOG_DIRECTORY };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// An app name nobody has is a typo, and a location it named would otherwise be
|
|
149
|
+
// settings nothing reads. proxy_pass is what routes the location to its app, so
|
|
150
|
+
// replacing it is not a setting but a broken route
|
|
151
|
+
function assertLocations(topology: Topology, proxy: ProxySpec) {
|
|
152
|
+
const apps = new Set(topology.apps.map((app) => app.name));
|
|
153
|
+
const unknown = Object.keys(proxy.locations ?? {}).filter((name) => !apps.has(name));
|
|
154
|
+
|
|
155
|
+
if (unknown.length > 0) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`The proxy sets locations for ${unknown.join(", ")}, which this deployment has ` +
|
|
158
|
+
`no app by that name for. Its apps are ${[...apps].join(", ")}`,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const lines = [...(proxy.location ?? []), ...Object.values(proxy.locations ?? {}).flat()];
|
|
163
|
+
const routing = lines.find((line) => directive(line) === "proxy_pass");
|
|
164
|
+
if (!routing) return;
|
|
165
|
+
|
|
166
|
+
throw new Error(
|
|
167
|
+
`A proxy location says ${routing.trim()}, and where a location sends a request ` +
|
|
168
|
+
"is its app's route, which redkite derives",
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
104
172
|
function indented(lines: string[], by: number) {
|
|
105
173
|
return lines.map((line) => " ".repeat(by) + line).join("\n");
|
|
106
174
|
}
|
package/src/topology.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { AppSpec, Deployment, ServiceSpec } from "./types.js";
|
|
|
2
2
|
|
|
3
3
|
import { environmentOf } from "./config.js";
|
|
4
4
|
import { mountFor } from "./layout.js";
|
|
5
|
+
import { logMount } from "./services/proxy.js";
|
|
5
6
|
|
|
6
7
|
// Every name and address the deployment uses, derived from the app list. This
|
|
7
8
|
// is the file that replaces the constants block: nothing is chosen by hand, so
|
|
@@ -92,7 +93,9 @@ export function topologyFor(config: Deployment, environment: string): Topology {
|
|
|
92
93
|
name: "nginx",
|
|
93
94
|
container: `${prefix}-nginx`,
|
|
94
95
|
address: address(NGINX_OCTET),
|
|
95
|
-
|
|
96
|
+
// Only a directory the deployment named. Nothing mounted otherwise, so a
|
|
97
|
+
// proxy that says nothing about its logs is the container it always was
|
|
98
|
+
volumes: routerVolumes(config),
|
|
96
99
|
},
|
|
97
100
|
apps,
|
|
98
101
|
services,
|
|
@@ -165,6 +168,11 @@ function serviceTopology(
|
|
|
165
168
|
};
|
|
166
169
|
}
|
|
167
170
|
|
|
171
|
+
function routerVolumes(config: Deployment) {
|
|
172
|
+
const logs = logMount(config.proxy);
|
|
173
|
+
return logs ? [logs] : [];
|
|
174
|
+
}
|
|
175
|
+
|
|
168
176
|
// Nginx resolves upstreams by container name, apps reach services by alias
|
|
169
177
|
function extraHosts(
|
|
170
178
|
apps: AppTopology[],
|
package/src/types.ts
CHANGED
|
@@ -92,6 +92,24 @@ export type ProxySpec = {
|
|
|
92
92
|
// Lines put inside every location, below what redkite sets, so one of these
|
|
93
93
|
// replaces a header rather than being replaced by it
|
|
94
94
|
location?: string[];
|
|
95
|
+
// Lines for one app's location alone, keyed by the app's name. Below the lines
|
|
96
|
+
// every location gets, so one of these replaces those for that app only
|
|
97
|
+
locations?: Record<string, string[]>;
|
|
98
|
+
// Where the proxy writes what it logs, and whether it logs at all. Absent
|
|
99
|
+
// leaves it to the image, which writes to the container's own output
|
|
100
|
+
logs?: false | ProxyLogs;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export type ProxyLogs = {
|
|
104
|
+
// A directory on the deploy host, mounted where nginx writes its logs. Each
|
|
105
|
+
// environment writes files of its own into it. Absent keeps them on the
|
|
106
|
+
// container's output, where docker logs reads them
|
|
107
|
+
directory?: string;
|
|
108
|
+
// One line per request. On unless this says false
|
|
109
|
+
access?: boolean;
|
|
110
|
+
// How severe something has to be to reach the error log. nginx's own default
|
|
111
|
+
// is error
|
|
112
|
+
errors?: "debug" | "info" | "notice" | "warn" | "error" | "crit" | "alert" | "emerg";
|
|
95
113
|
};
|
|
96
114
|
|
|
97
115
|
export type ServiceSpec = {
|