mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 04:01:58 +00:00
Bugfix/ssl proxy to ssl (#2956)
* fix registry rm command * fix bind with addSsl on ssl proto * fix bind with addSsl on ssl proto * Add pre-release version migrations * fix os build * add mime to package deps * update lockfile * more ssl fixes * add waitFor * improve restart lockup * beta.26 * fix dependency health check logic * handle missing health check * fix port forwards --------- Co-authored-by: Aiden McClelland <me@drbonez.dev>
This commit is contained in:
@@ -81,9 +81,13 @@ export async function checkDependencies<
|
||||
) {
|
||||
throw new Error(`Unknown HealthCheckId ${healthCheckId}`)
|
||||
}
|
||||
const errors = Object.entries(dep.result.healthChecks)
|
||||
.filter(([id, _]) => (healthCheckId ? id === healthCheckId : true))
|
||||
.filter(([_, res]) => res.result !== "success")
|
||||
const errors =
|
||||
dep.requirement.kind === "running"
|
||||
? dep.requirement.healthChecks
|
||||
.map((id) => [id, dep.result.healthChecks[id] ?? null] as const)
|
||||
.filter(([id, _]) => (healthCheckId ? id === healthCheckId : true))
|
||||
.filter(([_, res]) => res?.result !== "success")
|
||||
: []
|
||||
return errors.length === 0
|
||||
}
|
||||
const pkgSatisfied = (packageId: DependencyId) =>
|
||||
@@ -153,15 +157,20 @@ export async function checkDependencies<
|
||||
) {
|
||||
throw new Error(`Unknown HealthCheckId ${healthCheckId}`)
|
||||
}
|
||||
const errors = Object.entries(dep.result.healthChecks)
|
||||
.filter(([id, _]) => (healthCheckId ? id === healthCheckId : true))
|
||||
.filter(([_, res]) => res.result !== "success")
|
||||
const errors =
|
||||
dep.requirement.kind === "running"
|
||||
? dep.requirement.healthChecks
|
||||
.map((id) => [id, dep.result.healthChecks[id] ?? null] as const)
|
||||
.filter(([id, _]) => (healthCheckId ? id === healthCheckId : true))
|
||||
.filter(([_, res]) => res?.result !== "success")
|
||||
: []
|
||||
if (errors.length) {
|
||||
throw new Error(
|
||||
errors
|
||||
.map(
|
||||
([_, e]) =>
|
||||
`Health Check ${e.name} of ${dep.result.title || packageId} failed with status ${e.result}${e.message ? `: ${e.message}` : ""}`,
|
||||
.map(([id, e]) =>
|
||||
e
|
||||
? `Health Check ${e.name} of ${dep.result.title || packageId} failed with status ${e.result}${e.message ? `: ${e.message}` : ""}`
|
||||
: `Health Check ${id} of ${dep.result.title} does not exist`,
|
||||
)
|
||||
.join("; "),
|
||||
)
|
||||
|
||||
@@ -134,19 +134,26 @@ export class MultiHost {
|
||||
const preferredExternalPort =
|
||||
options.preferredExternalPort ||
|
||||
knownProtocols[options.protocol].defaultPort
|
||||
const sslProto = this.getSslProto(options, protoInfo)
|
||||
const addSsl =
|
||||
sslProto && "alpn" in protoInfo
|
||||
const sslProto = this.getSslProto(options)
|
||||
const addSsl = sslProto
|
||||
? {
|
||||
// addXForwardedHeaders: null,
|
||||
preferredExternalPort: knownProtocols[sslProto].defaultPort,
|
||||
scheme: sslProto,
|
||||
alpn: "alpn" in protoInfo ? protoInfo.alpn : null,
|
||||
...("addSsl" in options ? options.addSsl : null),
|
||||
}
|
||||
: options.addSsl
|
||||
? {
|
||||
// addXForwardedHeaders: null,
|
||||
preferredExternalPort: knownProtocols[sslProto].defaultPort,
|
||||
preferredExternalPort: 443,
|
||||
scheme: sslProto,
|
||||
alpn: protoInfo.alpn,
|
||||
alpn: null,
|
||||
...("addSsl" in options ? options.addSsl : null),
|
||||
}
|
||||
: null
|
||||
|
||||
const secure: Security | null = !protoInfo.secure ? null : { ssl: false }
|
||||
const secure: Security | null = protoInfo.secure ?? null
|
||||
|
||||
await this.options.effects.bind({
|
||||
id: this.options.id,
|
||||
@@ -159,12 +166,12 @@ export class MultiHost {
|
||||
return new Origin(this, internalPort, options.protocol, sslProto)
|
||||
}
|
||||
|
||||
private getSslProto(
|
||||
options: BindOptionsByKnownProtocol,
|
||||
protoInfo: KnownProtocols[keyof KnownProtocols],
|
||||
) {
|
||||
private getSslProto(options: BindOptionsByKnownProtocol) {
|
||||
const proto = options.protocol
|
||||
const protoInfo = knownProtocols[proto]
|
||||
if (inObject("noAddSsl", options) && options.noAddSsl) return null
|
||||
if ("withSsl" in protoInfo && protoInfo.withSsl) return protoInfo.withSsl
|
||||
if (protoInfo.secure?.ssl) return proto
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,4 +71,30 @@ export class GetSystemSmtp {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches the system SMTP credentials. Returns when the predicate is true
|
||||
*/
|
||||
async waitFor(pred: (value: T.SmtpValue | null) => boolean) {
|
||||
const resolveCell = { resolve: () => {} }
|
||||
this.effects.onLeaveContext(() => {
|
||||
resolveCell.resolve()
|
||||
})
|
||||
while (this.effects.isInContext) {
|
||||
let callback: () => void = () => {}
|
||||
const waitForNext = new Promise<void>((resolve) => {
|
||||
callback = resolve
|
||||
resolveCell.resolve = resolve
|
||||
})
|
||||
const res = await this.effects.getSystemSmtp({
|
||||
callback: () => callback(),
|
||||
})
|
||||
if (pred(res)) {
|
||||
resolveCell.resolve()
|
||||
return res
|
||||
}
|
||||
await waitForNext
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,6 +366,36 @@ export class GetServiceInterface {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches the requested service interface. Returns when the predicate is true
|
||||
*/
|
||||
async waitFor(pred: (value: ServiceInterfaceFilled | null) => boolean) {
|
||||
const { id, packageId } = this.opts
|
||||
const resolveCell = { resolve: () => {} }
|
||||
this.effects.onLeaveContext(() => {
|
||||
resolveCell.resolve()
|
||||
})
|
||||
while (this.effects.isInContext) {
|
||||
let callback: () => void = () => {}
|
||||
const waitForNext = new Promise<void>((resolve) => {
|
||||
callback = resolve
|
||||
resolveCell.resolve = resolve
|
||||
})
|
||||
const res = await makeInterfaceFilled({
|
||||
effects: this.effects,
|
||||
id,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
if (pred(res)) {
|
||||
resolveCell.resolve()
|
||||
return res
|
||||
}
|
||||
await waitForNext
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
export function getServiceInterface(
|
||||
effects: Effects,
|
||||
|
||||
@@ -130,6 +130,35 @@ export class GetServiceInterfaces {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches the service interfaces for the package. Returns when the predicate is true
|
||||
*/
|
||||
async waitFor(pred: (value: ServiceInterfaceFilled[] | null) => boolean) {
|
||||
const { packageId } = this.opts
|
||||
const resolveCell = { resolve: () => {} }
|
||||
this.effects.onLeaveContext(() => {
|
||||
resolveCell.resolve()
|
||||
})
|
||||
while (this.effects.isInContext) {
|
||||
let callback: () => void = () => {}
|
||||
const waitForNext = new Promise<void>((resolve) => {
|
||||
callback = resolve
|
||||
resolveCell.resolve = resolve
|
||||
})
|
||||
const res = await makeManyInterfaceFilled({
|
||||
effects: this.effects,
|
||||
packageId,
|
||||
callback,
|
||||
})
|
||||
if (pred(res)) {
|
||||
resolveCell.resolve()
|
||||
return res
|
||||
}
|
||||
await waitForNext
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
export function getServiceInterfaces(
|
||||
effects: Effects,
|
||||
|
||||
Reference in New Issue
Block a user