mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
Feature/network (#2622)
* Feature: Add in the clear bindings * wip: Working on network * fix: Make it so the config gives the url * chore: Remove the repeated types * chore: Add in the todo's here * chore: UPdate and remove some poorly name var * chore: Remove the clear-bindings impl * chore: Remove the wrapper * handle HostnameInfo for Host bindings Co-authored-by: Jade <Blu-J@users.noreply.github.com> * ?? * chore: Make the install work * Fix: Url's not being created * chore: Fix the local onion in url * include port in hostname * Chore of adding a comment just to modify. --------- Co-authored-by: Aiden McClelland <me@drbonez.dev> Co-authored-by: Jade <Blu-J@users.noreply.github.com>
This commit is contained in:
16
container-runtime/package-lock.json
generated
16
container-runtime/package-lock.json
generated
@@ -14,7 +14,7 @@
|
|||||||
"filebrowser": "^1.0.0",
|
"filebrowser": "^1.0.0",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"node-fetch": "^3.1.0",
|
"node-fetch": "^3.1.0",
|
||||||
"ts-matches": "^5.4.1",
|
"ts-matches": "^5.5.1",
|
||||||
"tslib": "^2.5.3",
|
"tslib": "^2.5.3",
|
||||||
"typescript": "^5.1.3",
|
"typescript": "^5.1.3",
|
||||||
"yaml": "^2.3.1"
|
"yaml": "^2.3.1"
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"../sdk/dist": {
|
"../sdk/dist": {
|
||||||
"name": "@start9labs/start-sdk",
|
"name": "@start9labs/start-sdk",
|
||||||
"version": "0.4.0-rev0.lib0.rc8.beta10",
|
"version": "0.3.6-alpha1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
@@ -2428,9 +2428,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ts-matches": {
|
"node_modules/ts-matches": {
|
||||||
"version": "5.4.1",
|
"version": "5.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-matches/-/ts-matches-5.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/ts-matches/-/ts-matches-5.5.1.tgz",
|
||||||
"integrity": "sha512-kXrY75F0s0WD15N2bWKDScKlKgwnusN6dTRzGs1N7LlxQRnazrsBISC1HL4sy2adsyk65Zbx3Ui3IGN8leAFOQ=="
|
"integrity": "sha512-UFYaKgfqlg9FROK7bdpYqFwG1CJvP4kOJdjXuWoqxo9jCmANoDw1GxkSCpJgoTeIiSTaTH5Qr1klSspb8c+ydg=="
|
||||||
},
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
@@ -4195,9 +4195,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ts-matches": {
|
"ts-matches": {
|
||||||
"version": "5.4.1",
|
"version": "5.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-matches/-/ts-matches-5.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/ts-matches/-/ts-matches-5.5.1.tgz",
|
||||||
"integrity": "sha512-kXrY75F0s0WD15N2bWKDScKlKgwnusN6dTRzGs1N7LlxQRnazrsBISC1HL4sy2adsyk65Zbx3Ui3IGN8leAFOQ=="
|
"integrity": "sha512-UFYaKgfqlg9FROK7bdpYqFwG1CJvP4kOJdjXuWoqxo9jCmANoDw1GxkSCpJgoTeIiSTaTH5Qr1klSspb8c+ydg=="
|
||||||
},
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"filebrowser": "^1.0.0",
|
"filebrowser": "^1.0.0",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"node-fetch": "^3.1.0",
|
"node-fetch": "^3.1.0",
|
||||||
"ts-matches": "^5.4.1",
|
"ts-matches": "^5.5.1",
|
||||||
"tslib": "^2.5.3",
|
"tslib": "^2.5.3",
|
||||||
"typescript": "^5.1.3",
|
"typescript": "^5.1.3",
|
||||||
"yaml": "^2.3.1"
|
"yaml": "^2.3.1"
|
||||||
|
|||||||
@@ -96,7 +96,10 @@ export class HostSystemStartOs implements Effects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bind(...[options]: Parameters<T.Effects["bind"]>) {
|
bind(...[options]: Parameters<T.Effects["bind"]>) {
|
||||||
return this.rpcRound("bind", options) as ReturnType<T.Effects["bind"]>
|
return this.rpcRound("bind", {
|
||||||
|
...options,
|
||||||
|
stack: new Error().stack,
|
||||||
|
}) as ReturnType<T.Effects["bind"]>
|
||||||
}
|
}
|
||||||
clearBindings(...[]: Parameters<T.Effects["clearBindings"]>) {
|
clearBindings(...[]: Parameters<T.Effects["clearBindings"]>) {
|
||||||
return this.rpcRound("clearBindings", null) as ReturnType<
|
return this.rpcRound("clearBindings", null) as ReturnType<
|
||||||
@@ -228,11 +231,6 @@ export class HostSystemStartOs implements Effects {
|
|||||||
restart(...[]: Parameters<T.Effects["restart"]>) {
|
restart(...[]: Parameters<T.Effects["restart"]>) {
|
||||||
return this.rpcRound("restart", null)
|
return this.rpcRound("restart", null)
|
||||||
}
|
}
|
||||||
reverseProxy(...[options]: Parameters<T.Effects["reverseProxy"]>) {
|
|
||||||
return this.rpcRound("reverseProxy", options) as ReturnType<
|
|
||||||
T.Effects["reverseProxy"]
|
|
||||||
>
|
|
||||||
}
|
|
||||||
running(...[packageId]: Parameters<T.Effects["running"]>) {
|
running(...[packageId]: Parameters<T.Effects["running"]>) {
|
||||||
return this.rpcRound("running", { packageId }) as ReturnType<
|
return this.rpcRound("running", { packageId }) as ReturnType<
|
||||||
T.Effects["running"]
|
T.Effects["running"]
|
||||||
|
|||||||
@@ -97,11 +97,9 @@ export class MainLoop {
|
|||||||
id: interfaceId,
|
id: interfaceId,
|
||||||
internalPort,
|
internalPort,
|
||||||
preferredExternalPort: torConf?.external || internalPort,
|
preferredExternalPort: torConf?.external || internalPort,
|
||||||
scheme: "http",
|
|
||||||
secure: null,
|
secure: null,
|
||||||
addSsl: lanConf?.ssl
|
addSsl: lanConf?.ssl
|
||||||
? {
|
? {
|
||||||
scheme: "https",
|
|
||||||
preferredExternalPort: lanConf.external,
|
preferredExternalPort: lanConf.external,
|
||||||
alpn: { specified: ["http/1.1"] },
|
alpn: { specified: ["http/1.1"] },
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,16 @@ import { HostSystemStartOs } from "../../HostSystemStartOs"
|
|||||||
import { JsonPath, unNestPath } from "../../../Models/JsonPath"
|
import { JsonPath, unNestPath } from "../../../Models/JsonPath"
|
||||||
import { RpcResult, matchRpcResult } from "../../RpcListener"
|
import { RpcResult, matchRpcResult } from "../../RpcListener"
|
||||||
import { CT } from "@start9labs/start-sdk"
|
import { CT } from "@start9labs/start-sdk"
|
||||||
|
import {
|
||||||
|
AddSslOptions,
|
||||||
|
BindOptions,
|
||||||
|
} from "@start9labs/start-sdk/cjs/lib/osBindings"
|
||||||
|
import {
|
||||||
|
BindOptionsByProtocol,
|
||||||
|
Host,
|
||||||
|
MultiHost,
|
||||||
|
} from "@start9labs/start-sdk/cjs/lib/interfaces/Host"
|
||||||
|
import { ServiceInterfaceBuilder } from "@start9labs/start-sdk/cjs/lib/interfaces/ServiceInterfaceBuilder"
|
||||||
|
|
||||||
type Optional<A> = A | undefined | null
|
type Optional<A> = A | undefined | null
|
||||||
function todo(): never {
|
function todo(): never {
|
||||||
@@ -335,6 +345,85 @@ export class SystemForEmbassy implements System {
|
|||||||
await this.migration(effects, previousVersion, timeoutMs)
|
await this.migration(effects, previousVersion, timeoutMs)
|
||||||
await effects.setMainStatus({ status: "stopped" })
|
await effects.setMainStatus({ status: "stopped" })
|
||||||
await this.exportActions(effects)
|
await this.exportActions(effects)
|
||||||
|
await this.exportNetwork(effects)
|
||||||
|
}
|
||||||
|
async exportNetwork(effects: HostSystemStartOs) {
|
||||||
|
for (const [id, interfaceValue] of Object.entries(
|
||||||
|
this.manifest.interfaces,
|
||||||
|
)) {
|
||||||
|
const host = new MultiHost({ effects, id })
|
||||||
|
const internalPorts = new Set(
|
||||||
|
Object.values(interfaceValue["tor-config"]?.["port-mapping"] ?? {})
|
||||||
|
.map(Number.parseInt)
|
||||||
|
.concat(
|
||||||
|
...Object.values(interfaceValue["lan-config"] ?? {}).map(
|
||||||
|
(c) => c.internal,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.filter(Boolean),
|
||||||
|
)
|
||||||
|
const bindings = Array.from(internalPorts).map<
|
||||||
|
[number, BindOptionsByProtocol]
|
||||||
|
>((port) => {
|
||||||
|
const lanPort = Object.entries(interfaceValue["lan-config"] ?? {}).find(
|
||||||
|
([external, internal]) => internal.internal === port,
|
||||||
|
)?.[0]
|
||||||
|
const torPort = Object.entries(
|
||||||
|
interfaceValue["tor-config"]?.["port-mapping"] ?? {},
|
||||||
|
).find(
|
||||||
|
([external, internal]) => Number.parseInt(internal) === port,
|
||||||
|
)?.[0]
|
||||||
|
let addSsl: AddSslOptions | null = null
|
||||||
|
if (lanPort) {
|
||||||
|
const lanPortNum = Number.parseInt(lanPort)
|
||||||
|
if (lanPortNum === 443) {
|
||||||
|
return [port, { protocol: "http", preferredExternalPort: 80 }]
|
||||||
|
}
|
||||||
|
addSsl = {
|
||||||
|
preferredExternalPort: lanPortNum,
|
||||||
|
alpn: { specified: [] },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
port,
|
||||||
|
{
|
||||||
|
secure: null,
|
||||||
|
preferredExternalPort: Number.parseInt(
|
||||||
|
torPort || lanPort || String(port),
|
||||||
|
),
|
||||||
|
addSsl,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
bindings.map(async ([internal, options]) => {
|
||||||
|
if (internal == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (options?.preferredExternalPort == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const origin = await host.bindPort(internal, options)
|
||||||
|
await origin.export([
|
||||||
|
new ServiceInterfaceBuilder({
|
||||||
|
effects,
|
||||||
|
name: interfaceValue.name,
|
||||||
|
id: `${id}-${internal}`,
|
||||||
|
description: interfaceValue.description,
|
||||||
|
hasPrimary: false,
|
||||||
|
disabled: false,
|
||||||
|
type: "api",
|
||||||
|
masked: false,
|
||||||
|
path: "",
|
||||||
|
schemeOverride: null,
|
||||||
|
search: {},
|
||||||
|
username: null,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async exportActions(effects: HostSystemStartOs) {
|
async exportActions(effects: HostSystemStartOs) {
|
||||||
const manifest = this.manifest
|
const manifest = this.manifest
|
||||||
@@ -486,6 +575,7 @@ export class SystemForEmbassy implements System {
|
|||||||
const newConfig = structuredClone(newConfigWithoutPointers)
|
const newConfig = structuredClone(newConfigWithoutPointers)
|
||||||
await updateConfig(
|
await updateConfig(
|
||||||
effects,
|
effects,
|
||||||
|
this.manifest,
|
||||||
await this.getConfigUncleaned(effects, timeoutMs).then((x) => x.spec),
|
await this.getConfigUncleaned(effects, timeoutMs).then((x) => x.spec),
|
||||||
newConfig,
|
newConfig,
|
||||||
)
|
)
|
||||||
@@ -866,6 +956,7 @@ function cleanConfigFromPointers<C, S>(
|
|||||||
|
|
||||||
async function updateConfig(
|
async function updateConfig(
|
||||||
effects: HostSystemStartOs,
|
effects: HostSystemStartOs,
|
||||||
|
manifest: Manifest,
|
||||||
spec: unknown,
|
spec: unknown,
|
||||||
mutConfigValue: unknown,
|
mutConfigValue: unknown,
|
||||||
) {
|
) {
|
||||||
@@ -877,7 +968,12 @@ async function updateConfig(
|
|||||||
const newConfigValue = mutConfigValue[key]
|
const newConfigValue = mutConfigValue[key]
|
||||||
if (matchSpec.test(specValue)) {
|
if (matchSpec.test(specValue)) {
|
||||||
const updateObject = { spec: null }
|
const updateObject = { spec: null }
|
||||||
await updateConfig(effects, { spec: specValue.spec }, updateObject)
|
await updateConfig(
|
||||||
|
effects,
|
||||||
|
manifest,
|
||||||
|
{ spec: specValue.spec },
|
||||||
|
updateObject,
|
||||||
|
)
|
||||||
mutConfigValue[key] = updateObject.spec
|
mutConfigValue[key] = updateObject.spec
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -899,20 +995,48 @@ async function updateConfig(
|
|||||||
if (matchPointerPackage.test(specValue)) {
|
if (matchPointerPackage.test(specValue)) {
|
||||||
if (specValue.target === "tor-key")
|
if (specValue.target === "tor-key")
|
||||||
throw new Error("This service uses an unsupported target TorKey")
|
throw new Error("This service uses an unsupported target TorKey")
|
||||||
|
|
||||||
|
const specInterface = specValue.interface
|
||||||
|
const serviceInterfaceId = extractServiceInterfaceId(
|
||||||
|
manifest,
|
||||||
|
specInterface,
|
||||||
|
)
|
||||||
const filled = await utils
|
const filled = await utils
|
||||||
.getServiceInterface(effects, {
|
.getServiceInterface(effects, {
|
||||||
packageId: specValue["package-id"],
|
packageId: specValue["package-id"],
|
||||||
id: specValue.interface,
|
id: serviceInterfaceId,
|
||||||
})
|
})
|
||||||
.once()
|
.once()
|
||||||
.catch(() => null)
|
.catch((x) => {
|
||||||
|
console.error("Could not get the service interface", x)
|
||||||
mutConfigValue[key] =
|
return null
|
||||||
|
})
|
||||||
|
const catchFn = <X>(fn: () => X) => {
|
||||||
|
try {
|
||||||
|
return fn()
|
||||||
|
} catch (e) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const url: string =
|
||||||
filled === null
|
filled === null
|
||||||
? ""
|
? ""
|
||||||
: specValue.target === "lan-address"
|
: catchFn(() =>
|
||||||
? filled.addressInfo.localHostnames[0]
|
utils.hostnameInfoToAddress(
|
||||||
: filled.addressInfo.onionHostnames[0]
|
specValue.target === "lan-address"
|
||||||
|
? filled.addressInfo.localHostnames[0] ||
|
||||||
|
filled.addressInfo.onionHostnames[0]
|
||||||
|
: filled.addressInfo.onionHostnames[0] ||
|
||||||
|
filled.addressInfo.localHostnames[0],
|
||||||
|
),
|
||||||
|
) || ""
|
||||||
|
mutConfigValue[key] = url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function extractServiceInterfaceId(manifest: Manifest, specInterface: string) {
|
||||||
|
let serviceInterfaceId
|
||||||
|
const lanConfig = manifest.interfaces[specInterface]?.["lan-config"] || {}
|
||||||
|
serviceInterfaceId = `${specInterface}-${Object.entries(lanConfig)[0]?.[1]?.internal}`
|
||||||
|
return serviceInterfaceId
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ export const matchManifest = object(
|
|||||||
object(
|
object(
|
||||||
{
|
{
|
||||||
name: string,
|
name: string,
|
||||||
|
description: string,
|
||||||
"tor-config": object({
|
"tor-config": object({
|
||||||
"port-mapping": dictionary([string, string]),
|
"port-mapping": dictionary([string, string]),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ export type Effects = {
|
|||||||
/** Sandbox mode lets us read but not write */
|
/** Sandbox mode lets us read but not write */
|
||||||
is_sandboxed(): boolean
|
is_sandboxed(): boolean
|
||||||
|
|
||||||
|
// Does a volume and path exist?
|
||||||
exists(input: { volumeId: string; path: string }): Promise<boolean>
|
exists(input: { volumeId: string; path: string }): Promise<boolean>
|
||||||
|
|
||||||
fetch(
|
fetch(
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ pub use service_interface::ServiceInterfaceId;
|
|||||||
pub use volume::VolumeId;
|
pub use volume::VolumeId;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref ID_REGEX: Regex = Regex::new("^[a-z]+(-[a-z]+)*$").unwrap();
|
static ref ID_REGEX: Regex = Regex::new("^[a-z]+(-[a-z0-9]+)*$").unwrap();
|
||||||
pub static ref SYSTEM_ID: Id = Id(InternedString::intern("x_system"));
|
pub static ref SYSTEM_ID: Id = Id(InternedString::intern("x_system"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use reqwest::Url;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
use crate::net::host::HostInfo;
|
use crate::net::host::Hosts;
|
||||||
use crate::net::service_interface::ServiceInterfaceWithHostInfo;
|
use crate::net::service_interface::ServiceInterface;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::progress::FullProgress;
|
use crate::progress::FullProgress;
|
||||||
use crate::s9pk::manifest::Manifest;
|
use crate::s9pk::manifest::Manifest;
|
||||||
@@ -333,8 +333,8 @@ pub struct PackageDataEntry {
|
|||||||
pub last_backup: Option<DateTime<Utc>>,
|
pub last_backup: Option<DateTime<Utc>>,
|
||||||
pub current_dependencies: CurrentDependencies,
|
pub current_dependencies: CurrentDependencies,
|
||||||
pub actions: BTreeMap<ActionId, ActionMetadata>,
|
pub actions: BTreeMap<ActionId, ActionMetadata>,
|
||||||
pub service_interfaces: BTreeMap<ServiceInterfaceId, ServiceInterfaceWithHostInfo>,
|
pub service_interfaces: BTreeMap<ServiceInterfaceId, ServiceInterface>,
|
||||||
pub hosts: HostInfo,
|
pub hosts: Hosts,
|
||||||
#[ts(type = "string[]")]
|
#[ts(type = "string[]")]
|
||||||
pub store_exposed_dependents: Vec<JsonPointer>,
|
pub store_exposed_dependents: Vec<JsonPointer>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rpc_toolkit::{
|
use rpc_toolkit::{from_fn_async, CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler};
|
||||||
from_fn_async, CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::context::{CliContext, RpcContext};
|
use crate::context::{CliContext, RpcContext};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::net::IpAddr;
|
|||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
|
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use imbl_value::InternedString;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
@@ -11,17 +10,31 @@ use crate::prelude::*;
|
|||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct BindInfo {
|
pub struct BindInfo {
|
||||||
pub options: BindOptions,
|
pub options: BindOptions,
|
||||||
pub assigned_lan_port: Option<u16>,
|
pub lan: LanInfo,
|
||||||
|
}
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize, TS, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export)]
|
||||||
|
pub struct LanInfo {
|
||||||
|
pub assigned_port: Option<u16>,
|
||||||
|
pub assigned_ssl_port: Option<u16>,
|
||||||
}
|
}
|
||||||
impl BindInfo {
|
impl BindInfo {
|
||||||
pub fn new(available_ports: &mut AvailablePorts, options: BindOptions) -> Result<Self, Error> {
|
pub fn new(available_ports: &mut AvailablePorts, options: BindOptions) -> Result<Self, Error> {
|
||||||
let mut assigned_lan_port = None;
|
let mut assigned_port = None;
|
||||||
if options.add_ssl.is_some() || options.secure.is_some() {
|
let mut assigned_ssl_port = None;
|
||||||
assigned_lan_port = Some(available_ports.alloc()?);
|
if options.secure.is_some() {
|
||||||
|
assigned_port = Some(available_ports.alloc()?);
|
||||||
|
}
|
||||||
|
if options.add_ssl.is_some() {
|
||||||
|
assigned_ssl_port = Some(available_ports.alloc()?);
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
options,
|
options,
|
||||||
assigned_lan_port,
|
lan: LanInfo {
|
||||||
|
assigned_port,
|
||||||
|
assigned_ssl_port,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn update(
|
pub fn update(
|
||||||
@@ -29,29 +42,38 @@ impl BindInfo {
|
|||||||
available_ports: &mut AvailablePorts,
|
available_ports: &mut AvailablePorts,
|
||||||
options: BindOptions,
|
options: BindOptions,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let Self {
|
let Self { mut lan, .. } = self;
|
||||||
mut assigned_lan_port,
|
if options
|
||||||
..
|
.secure
|
||||||
} = self;
|
.map_or(false, |s| !(s.ssl && options.add_ssl.is_some()))
|
||||||
if options.add_ssl.is_some() || options.secure.is_some() {
|
// doesn't make sense to have 2 listening ports, both with ssl
|
||||||
assigned_lan_port = if let Some(port) = assigned_lan_port.take() {
|
{
|
||||||
|
lan.assigned_port = if let Some(port) = lan.assigned_port.take() {
|
||||||
Some(port)
|
Some(port)
|
||||||
} else {
|
} else {
|
||||||
Some(available_ports.alloc()?)
|
Some(available_ports.alloc()?)
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if let Some(port) = assigned_lan_port.take() {
|
if let Some(port) = lan.assigned_port.take() {
|
||||||
available_ports.free([port]);
|
available_ports.free([port]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Self {
|
if options.add_ssl.is_some() {
|
||||||
options,
|
lan.assigned_ssl_port = if let Some(port) = lan.assigned_ssl_port.take() {
|
||||||
assigned_lan_port,
|
Some(port)
|
||||||
})
|
} else {
|
||||||
|
Some(available_ports.alloc()?)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
if let Some(port) = lan.assigned_ssl_port.take() {
|
||||||
|
available_ports.free([port]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Self { options, lan })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Security {
|
pub struct Security {
|
||||||
@@ -62,8 +84,6 @@ pub struct Security {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct BindOptions {
|
pub struct BindOptions {
|
||||||
#[ts(type = "string | null")]
|
|
||||||
pub scheme: Option<InternedString>,
|
|
||||||
pub preferred_external_port: u16,
|
pub preferred_external_port: u16,
|
||||||
pub add_ssl: Option<AddSslOptions>,
|
pub add_ssl: Option<AddSslOptions>,
|
||||||
pub secure: Option<Security>,
|
pub secure: Option<Security>,
|
||||||
@@ -73,11 +93,8 @@ pub struct BindOptions {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct AddSslOptions {
|
pub struct AddSslOptions {
|
||||||
#[ts(type = "string | null")]
|
|
||||||
pub scheme: Option<InternedString>,
|
|
||||||
pub preferred_external_port: u16,
|
pub preferred_external_port: u16,
|
||||||
// #[serde(default)]
|
// #[serde(default)]
|
||||||
// pub add_x_forwarded_headers: bool, // TODO
|
// pub add_x_forwarded_headers: bool, // TODO
|
||||||
#[serde(default)]
|
pub alpn: Option<AlpnInfo>,
|
||||||
pub alpn: AlpnInfo,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ use std::collections::{BTreeMap, BTreeSet};
|
|||||||
use imbl_value::InternedString;
|
use imbl_value::InternedString;
|
||||||
use models::{HostId, PackageId};
|
use models::{HostId, PackageId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use torut::onion::{OnionAddressV3, TorSecretKeyV3};
|
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
use crate::db::model::DatabaseModel;
|
use crate::db::model::DatabaseModel;
|
||||||
use crate::net::forward::AvailablePorts;
|
use crate::net::forward::AvailablePorts;
|
||||||
use crate::net::host::address::HostAddress;
|
use crate::net::host::address::HostAddress;
|
||||||
use crate::net::host::binding::{BindInfo, BindOptions};
|
use crate::net::host::binding::{BindInfo, BindOptions};
|
||||||
|
use crate::net::service_interface::HostnameInfo;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub mod address;
|
pub mod address;
|
||||||
@@ -23,7 +23,8 @@ pub struct Host {
|
|||||||
pub kind: HostKind,
|
pub kind: HostKind,
|
||||||
pub bindings: BTreeMap<u16, BindInfo>,
|
pub bindings: BTreeMap<u16, BindInfo>,
|
||||||
pub addresses: BTreeSet<HostAddress>,
|
pub addresses: BTreeSet<HostAddress>,
|
||||||
pub primary: Option<HostAddress>,
|
/// COMPUTED: NetService::update
|
||||||
|
pub hostname_info: BTreeMap<u16, Vec<HostnameInfo>>, // internal port -> Hostnames
|
||||||
}
|
}
|
||||||
impl AsRef<Host> for Host {
|
impl AsRef<Host> for Host {
|
||||||
fn as_ref(&self) -> &Host {
|
fn as_ref(&self) -> &Host {
|
||||||
@@ -36,7 +37,7 @@ impl Host {
|
|||||||
kind,
|
kind,
|
||||||
bindings: BTreeMap::new(),
|
bindings: BTreeMap::new(),
|
||||||
addresses: BTreeSet::new(),
|
addresses: BTreeSet::new(),
|
||||||
primary: None,
|
hostname_info: BTreeMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,9 +54,9 @@ pub enum HostKind {
|
|||||||
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
|
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
|
||||||
#[model = "Model<Self>"]
|
#[model = "Model<Self>"]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct HostInfo(BTreeMap<HostId, Host>);
|
pub struct Hosts(pub BTreeMap<HostId, Host>);
|
||||||
|
|
||||||
impl Map for HostInfo {
|
impl Map for Hosts {
|
||||||
type Key = HostId;
|
type Key = HostId;
|
||||||
type Value = Host;
|
type Value = Host;
|
||||||
fn key_str(key: &Self::Key) -> Result<impl AsRef<str>, Error> {
|
fn key_str(key: &Self::Key) -> Result<impl AsRef<str>, Error> {
|
||||||
@@ -75,7 +76,7 @@ pub fn host_for<'a>(
|
|||||||
fn host_info<'a>(
|
fn host_info<'a>(
|
||||||
db: &'a mut DatabaseModel,
|
db: &'a mut DatabaseModel,
|
||||||
package_id: &PackageId,
|
package_id: &PackageId,
|
||||||
) -> Result<&'a mut Model<HostInfo>, Error> {
|
) -> Result<&'a mut Model<Hosts>, Error> {
|
||||||
Ok::<_, Error>(
|
Ok::<_, Error>(
|
||||||
db.as_public_mut()
|
db.as_public_mut()
|
||||||
.as_package_data_mut()
|
.as_package_data_mut()
|
||||||
@@ -129,9 +130,3 @@ impl Model<Host> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HostInfo {
|
|
||||||
pub fn get_host_primary(&self, host_id: &HostId) -> Option<HostAddress> {
|
|
||||||
self.0.get(&host_id).and_then(|h| h.primary.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use std::sync::{Arc, Weak};
|
|||||||
|
|
||||||
use color_eyre::eyre::eyre;
|
use color_eyre::eyre::eyre;
|
||||||
use imbl::OrdMap;
|
use imbl::OrdMap;
|
||||||
use lazy_format::lazy_format;
|
|
||||||
use models::{HostId, OptionExt, PackageId};
|
use models::{HostId, OptionExt, PackageId};
|
||||||
use torut::onion::{OnionAddressV3, TorSecretKeyV3};
|
use torut::onion::{OnionAddressV3, TorSecretKeyV3};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -15,8 +14,9 @@ use crate::hostname::Hostname;
|
|||||||
use crate::net::dns::DnsController;
|
use crate::net::dns::DnsController;
|
||||||
use crate::net::forward::LanPortForwardController;
|
use crate::net::forward::LanPortForwardController;
|
||||||
use crate::net::host::address::HostAddress;
|
use crate::net::host::address::HostAddress;
|
||||||
use crate::net::host::binding::{AddSslOptions, BindOptions};
|
use crate::net::host::binding::{AddSslOptions, BindOptions, LanInfo};
|
||||||
use crate::net::host::{host_for, Host, HostKind};
|
use crate::net::host::{host_for, Host, HostKind};
|
||||||
|
use crate::net::service_interface::{HostnameInfo, IpHostname, OnionHostname};
|
||||||
use crate::net::tor::TorController;
|
use crate::net::tor::TorController;
|
||||||
use crate::net::vhost::{AlpnInfo, VHostController};
|
use crate::net::vhost::{AlpnInfo, VHostController};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
@@ -164,7 +164,7 @@ impl NetController {
|
|||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
struct HostBinds {
|
struct HostBinds {
|
||||||
lan: BTreeMap<u16, (u16, Option<AddSslOptions>, Arc<()>)>,
|
lan: BTreeMap<u16, (LanInfo, Option<AddSslOptions>, Vec<Arc<()>>)>,
|
||||||
tor: BTreeMap<OnionAddressV3, (OrdMap<u16, SocketAddr>, Vec<Arc<()>>)>,
|
tor: BTreeMap<OnionAddressV3, (OrdMap<u16, SocketAddr>, Vec<Arc<()>>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,105 +209,173 @@ impl NetService {
|
|||||||
.await?;
|
.await?;
|
||||||
self.update(id, host).await
|
self.update(id, host).await
|
||||||
}
|
}
|
||||||
|
pub async fn clear_bindings(&mut self) -> Result<(), Error> {
|
||||||
|
// TODO BLUJ
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn update(&mut self, id: HostId, host: Host) -> Result<(), Error> {
|
async fn update(&mut self, id: HostId, host: Host) -> Result<(), Error> {
|
||||||
dbg!(&host);
|
|
||||||
dbg!(&self.binds);
|
|
||||||
let ctrl = self.net_controller()?;
|
let ctrl = self.net_controller()?;
|
||||||
|
let mut hostname_info = BTreeMap::new();
|
||||||
let binds = {
|
let binds = {
|
||||||
if !self.binds.contains_key(&id) {
|
if !self.binds.contains_key(&id) {
|
||||||
self.binds.insert(id.clone(), Default::default());
|
self.binds.insert(id.clone(), Default::default());
|
||||||
}
|
}
|
||||||
self.binds.get_mut(&id).unwrap()
|
self.binds.get_mut(&id).unwrap()
|
||||||
};
|
};
|
||||||
if true
|
let peek = ctrl.db.peek().await;
|
||||||
// TODO: if should listen lan
|
|
||||||
{
|
// LAN
|
||||||
for (port, bind) in &host.bindings {
|
let server_info = peek.as_public().as_server_info();
|
||||||
let old_lan_bind = binds.lan.remove(port);
|
let ip_info = server_info.as_ip_info().de()?;
|
||||||
let old_lan_port = old_lan_bind.as_ref().map(|(external, _, _)| *external);
|
let hostname = server_info.as_hostname().de()?;
|
||||||
let lan_bind = old_lan_bind.filter(|(external, ssl, _)| {
|
for (port, bind) in &host.bindings {
|
||||||
ssl == &bind.options.add_ssl
|
let old_lan_bind = binds.lan.remove(port);
|
||||||
&& bind.assigned_lan_port.as_ref() == Some(external)
|
let old_lan_port = old_lan_bind.as_ref().map(|(external, _, _)| *external);
|
||||||
}); // only keep existing binding if relevant details match
|
let lan_bind = old_lan_bind
|
||||||
if let Some(external) = bind.assigned_lan_port {
|
.filter(|(external, ssl, _)| ssl == &bind.options.add_ssl && bind.lan == *external); // only keep existing binding if relevant details match
|
||||||
let new_lan_bind = if let Some(b) = lan_bind {
|
if bind.lan.assigned_port.is_some() || bind.lan.assigned_ssl_port.is_some() {
|
||||||
b
|
let new_lan_bind = if let Some(b) = lan_bind {
|
||||||
} else {
|
b
|
||||||
if let Some(ssl) = &bind.options.add_ssl {
|
} else {
|
||||||
let rc = ctrl
|
let mut rcs = Vec::with_capacity(2);
|
||||||
.vhost
|
if let Some(ssl) = &bind.options.add_ssl {
|
||||||
|
let external = bind
|
||||||
|
.lan
|
||||||
|
.assigned_ssl_port
|
||||||
|
.or_not_found("assigned ssl port")?;
|
||||||
|
rcs.push(
|
||||||
|
ctrl.vhost
|
||||||
.add(
|
.add(
|
||||||
None,
|
None,
|
||||||
external,
|
external,
|
||||||
(self.ip, *port).into(),
|
(self.ip, *port).into(),
|
||||||
if bind.options.secure.as_ref().map_or(false, |s| s.ssl) {
|
if let Some(alpn) = ssl.alpn.clone() {
|
||||||
Ok(())
|
Err(alpn)
|
||||||
} else {
|
} else {
|
||||||
Err(ssl.alpn.clone())
|
if bind.options.secure.as_ref().map_or(false, |s| s.ssl) {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(AlpnInfo::Reflect)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?,
|
||||||
(*port, Some(ssl.clone()), rc)
|
);
|
||||||
|
}
|
||||||
|
if let Some(security) = bind.options.secure {
|
||||||
|
if bind.options.add_ssl.is_some() && security.ssl {
|
||||||
|
// doesn't make sense to have 2 listening ports, both with ssl
|
||||||
} else {
|
} else {
|
||||||
let rc = ctrl.forward.add(external, (self.ip, *port).into()).await?;
|
let external =
|
||||||
(*port, None, rc)
|
bind.lan.assigned_port.or_not_found("assigned lan port")?;
|
||||||
|
rcs.push(ctrl.forward.add(external, (self.ip, *port).into()).await?);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
binds.lan.insert(*port, new_lan_bind);
|
(bind.lan, bind.options.add_ssl.clone(), rcs)
|
||||||
|
};
|
||||||
|
let mut bind_hostname_info: Vec<HostnameInfo> =
|
||||||
|
hostname_info.remove(port).unwrap_or_default();
|
||||||
|
for (interface, ip_info) in &ip_info {
|
||||||
|
bind_hostname_info.push(HostnameInfo::Ip {
|
||||||
|
network_interface_id: interface.clone(),
|
||||||
|
public: false,
|
||||||
|
hostname: IpHostname::Local {
|
||||||
|
value: format!("{hostname}.local"),
|
||||||
|
port: new_lan_bind.0.assigned_port,
|
||||||
|
ssl_port: new_lan_bind.0.assigned_ssl_port,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if let Some(ipv4) = ip_info.ipv4 {
|
||||||
|
bind_hostname_info.push(HostnameInfo::Ip {
|
||||||
|
network_interface_id: interface.clone(),
|
||||||
|
public: false,
|
||||||
|
hostname: IpHostname::Ipv4 {
|
||||||
|
value: ipv4,
|
||||||
|
port: new_lan_bind.0.assigned_port,
|
||||||
|
ssl_port: new_lan_bind.0.assigned_ssl_port,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(ipv6) = ip_info.ipv6 {
|
||||||
|
bind_hostname_info.push(HostnameInfo::Ip {
|
||||||
|
network_interface_id: interface.clone(),
|
||||||
|
public: false,
|
||||||
|
hostname: IpHostname::Ipv6 {
|
||||||
|
value: ipv6,
|
||||||
|
port: new_lan_bind.0.assigned_port,
|
||||||
|
ssl_port: new_lan_bind.0.assigned_ssl_port,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(external) = old_lan_port {
|
hostname_info.insert(*port, bind_hostname_info);
|
||||||
|
binds.lan.insert(*port, new_lan_bind);
|
||||||
|
}
|
||||||
|
if let Some(lan) = old_lan_port {
|
||||||
|
if let Some(external) = lan.assigned_ssl_port {
|
||||||
ctrl.vhost.gc(None, external).await?;
|
ctrl.vhost.gc(None, external).await?;
|
||||||
|
}
|
||||||
|
if let Some(external) = lan.assigned_port {
|
||||||
ctrl.forward.gc(external).await?;
|
ctrl.forward.gc(external).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut removed = BTreeSet::new();
|
}
|
||||||
let mut removed_ssl = BTreeSet::new();
|
let mut removed = BTreeSet::new();
|
||||||
binds.lan.retain(|internal, (external, ssl, _)| {
|
binds.lan.retain(|internal, (external, _, _)| {
|
||||||
if host.bindings.contains_key(internal) {
|
if host.bindings.contains_key(internal) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
if ssl.is_some() {
|
removed.insert(*external);
|
||||||
removed_ssl.insert(*external);
|
|
||||||
} else {
|
false
|
||||||
removed.insert(*external);
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for external in removed {
|
|
||||||
ctrl.forward.gc(external).await?;
|
|
||||||
}
|
}
|
||||||
for external in removed_ssl {
|
});
|
||||||
|
for lan in removed {
|
||||||
|
if let Some(external) = lan.assigned_ssl_port {
|
||||||
ctrl.vhost.gc(None, external).await?;
|
ctrl.vhost.gc(None, external).await?;
|
||||||
}
|
}
|
||||||
|
if let Some(external) = lan.assigned_port {
|
||||||
|
ctrl.forward.gc(external).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let tor_binds: OrdMap<u16, SocketAddr> = host
|
|
||||||
.bindings
|
struct TorHostnamePorts {
|
||||||
.iter()
|
non_ssl: Option<u16>,
|
||||||
.flat_map(|(internal, info)| {
|
ssl: Option<u16>,
|
||||||
let non_ssl = (
|
}
|
||||||
info.options.preferred_external_port,
|
let mut tor_hostname_ports = BTreeMap::<u16, TorHostnamePorts>::new();
|
||||||
SocketAddr::from((self.ip, *internal)),
|
let mut tor_binds = OrdMap::<u16, SocketAddr>::new();
|
||||||
|
for (internal, info) in &host.bindings {
|
||||||
|
tor_binds.insert(
|
||||||
|
info.options.preferred_external_port,
|
||||||
|
SocketAddr::from((self.ip, *internal)),
|
||||||
|
);
|
||||||
|
if let (Some(ssl), Some(ssl_internal)) =
|
||||||
|
(&info.options.add_ssl, info.lan.assigned_ssl_port)
|
||||||
|
{
|
||||||
|
tor_binds.insert(
|
||||||
|
ssl.preferred_external_port,
|
||||||
|
SocketAddr::from(([127, 0, 0, 1], ssl_internal)),
|
||||||
);
|
);
|
||||||
if let (Some(ssl), Some(ssl_internal)) =
|
tor_hostname_ports.insert(
|
||||||
(&info.options.add_ssl, info.assigned_lan_port)
|
*internal,
|
||||||
{
|
TorHostnamePorts {
|
||||||
itertools::Either::Left(
|
non_ssl: Some(info.options.preferred_external_port)
|
||||||
[
|
.filter(|p| *p != ssl.preferred_external_port),
|
||||||
(
|
ssl: Some(ssl.preferred_external_port),
|
||||||
ssl.preferred_external_port,
|
},
|
||||||
SocketAddr::from(([127, 0, 0, 1], ssl_internal)),
|
);
|
||||||
),
|
} else {
|
||||||
non_ssl,
|
tor_hostname_ports.insert(
|
||||||
]
|
*internal,
|
||||||
.into_iter(),
|
TorHostnamePorts {
|
||||||
)
|
non_ssl: Some(info.options.preferred_external_port),
|
||||||
} else {
|
ssl: None,
|
||||||
itertools::Either::Right([non_ssl].into_iter())
|
},
|
||||||
}
|
);
|
||||||
})
|
}
|
||||||
.collect();
|
}
|
||||||
let mut keep_tor_addrs = BTreeSet::new();
|
let mut keep_tor_addrs = BTreeSet::new();
|
||||||
for addr in match host.kind {
|
for addr in match host.kind {
|
||||||
HostKind::Multi => {
|
HostKind::Multi => {
|
||||||
@@ -324,13 +392,10 @@ impl NetService {
|
|||||||
let new_tor_bind = if let Some(tor_bind) = tor_bind {
|
let new_tor_bind = if let Some(tor_bind) = tor_bind {
|
||||||
tor_bind
|
tor_bind
|
||||||
} else {
|
} else {
|
||||||
let key = ctrl
|
let key = peek
|
||||||
.db
|
.as_private()
|
||||||
.peek()
|
.as_key_store()
|
||||||
.await
|
.as_onion()
|
||||||
.into_private()
|
|
||||||
.into_key_store()
|
|
||||||
.into_onion()
|
|
||||||
.get_key(address)?;
|
.get_key(address)?;
|
||||||
let rcs = ctrl
|
let rcs = ctrl
|
||||||
.tor
|
.tor
|
||||||
@@ -338,6 +403,18 @@ impl NetService {
|
|||||||
.await?;
|
.await?;
|
||||||
(tor_binds.clone(), rcs)
|
(tor_binds.clone(), rcs)
|
||||||
};
|
};
|
||||||
|
for (internal, ports) in &tor_hostname_ports {
|
||||||
|
let mut bind_hostname_info =
|
||||||
|
hostname_info.remove(internal).unwrap_or_default();
|
||||||
|
bind_hostname_info.push(HostnameInfo::Onion {
|
||||||
|
hostname: OnionHostname {
|
||||||
|
value: address.to_string(),
|
||||||
|
port: ports.non_ssl,
|
||||||
|
ssl_port: ports.ssl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
hostname_info.insert(*internal, bind_hostname_info);
|
||||||
|
}
|
||||||
binds.tor.insert(address.clone(), new_tor_bind);
|
binds.tor.insert(address.clone(), new_tor_bind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,6 +424,14 @@ impl NetService {
|
|||||||
ctrl.tor.gc(Some(addr.clone()), None).await?;
|
ctrl.tor.gc(Some(addr.clone()), None).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.net_controller()?
|
||||||
|
.db
|
||||||
|
.mutate(|db| {
|
||||||
|
host_for(db, &self.id, &id, host.kind)?
|
||||||
|
.as_hostname_info_mut()
|
||||||
|
.ser(&hostname_info)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,12 +440,13 @@ impl NetService {
|
|||||||
let mut errors = ErrorCollection::new();
|
let mut errors = ErrorCollection::new();
|
||||||
if let Some(ctrl) = Weak::upgrade(&self.controller) {
|
if let Some(ctrl) = Weak::upgrade(&self.controller) {
|
||||||
for (_, binds) in std::mem::take(&mut self.binds) {
|
for (_, binds) in std::mem::take(&mut self.binds) {
|
||||||
for (_, (external, ssl, rc)) in binds.lan {
|
for (_, (lan, _, rc)) in binds.lan {
|
||||||
drop(rc);
|
drop(rc);
|
||||||
if ssl.is_some() {
|
if let Some(external) = lan.assigned_ssl_port {
|
||||||
errors.handle(ctrl.vhost.gc(None, external).await);
|
ctrl.vhost.gc(None, external).await?;
|
||||||
} else {
|
}
|
||||||
errors.handle(ctrl.forward.gc(external).await);
|
if let Some(external) = lan.assigned_port {
|
||||||
|
ctrl.forward.gc(external).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (addr, (_, rcs)) in binds.tor {
|
for (addr, (_, rcs)) in binds.tor {
|
||||||
@@ -384,12 +470,12 @@ impl NetService {
|
|||||||
self.ip
|
self.ip
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ext_port(&self, host_id: HostId, internal_port: u16) -> Result<u16, Error> {
|
pub fn get_ext_port(&self, host_id: HostId, internal_port: u16) -> Result<LanInfo, Error> {
|
||||||
let host_id_binds = self.binds.get_key_value(&host_id);
|
let host_id_binds = self.binds.get_key_value(&host_id);
|
||||||
match host_id_binds {
|
match host_id_binds {
|
||||||
Some((_, binds)) => {
|
Some((_, binds)) => {
|
||||||
if let Some(ext_port_info) = binds.lan.get(&internal_port) {
|
if let Some((lan, _, _)) = binds.lan.get(&internal_port) {
|
||||||
Ok(ext_port_info.0)
|
Ok(*lan)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::new(
|
Err(Error::new(
|
||||||
eyre!(
|
eyre!(
|
||||||
|
|||||||
@@ -1,51 +1,32 @@
|
|||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
|
|
||||||
|
use imbl_value::InternedString;
|
||||||
use models::{HostId, ServiceInterfaceId};
|
use models::{HostId, ServiceInterfaceId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
use crate::net::host::binding::BindOptions;
|
use crate::net::host::address::HostAddress;
|
||||||
use crate::net::host::HostKind;
|
|
||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
|
||||||
#[ts(export)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct ServiceInterfaceWithHostInfo {
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub service_interface: ServiceInterface,
|
|
||||||
pub host_info: ExportedHostInfo,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
|
||||||
#[ts(export)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct ExportedHostInfo {
|
|
||||||
pub id: HostId,
|
|
||||||
pub kind: HostKind,
|
|
||||||
pub hostnames: Vec<ExportedHostnameInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[serde(rename_all_fields = "camelCase")]
|
#[serde(rename_all_fields = "camelCase")]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
pub enum ExportedHostnameInfo {
|
pub enum HostnameInfo {
|
||||||
Ip {
|
Ip {
|
||||||
network_interface_id: String,
|
network_interface_id: String,
|
||||||
public: bool,
|
public: bool,
|
||||||
hostname: ExportedIpHostname,
|
hostname: IpHostname,
|
||||||
},
|
},
|
||||||
Onion {
|
Onion {
|
||||||
hostname: ExportedOnionHostname,
|
hostname: OnionHostname,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ExportedOnionHostname {
|
pub struct OnionHostname {
|
||||||
pub value: String,
|
pub value: String,
|
||||||
pub port: Option<u16>,
|
pub port: Option<u16>,
|
||||||
pub ssl_port: Option<u16>,
|
pub ssl_port: Option<u16>,
|
||||||
@@ -56,7 +37,7 @@ pub struct ExportedOnionHostname {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[serde(rename_all_fields = "camelCase")]
|
#[serde(rename_all_fields = "camelCase")]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
pub enum ExportedIpHostname {
|
pub enum IpHostname {
|
||||||
Ipv4 {
|
Ipv4 {
|
||||||
value: Ipv4Addr,
|
value: Ipv4Addr,
|
||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
@@ -110,6 +91,10 @@ pub enum ServiceInterfaceType {
|
|||||||
pub struct AddressInfo {
|
pub struct AddressInfo {
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
pub host_id: HostId,
|
pub host_id: HostId,
|
||||||
pub bind_options: BindOptions,
|
pub internal_port: u16,
|
||||||
|
#[ts(type = "string | null")]
|
||||||
|
pub scheme: Option<InternedString>,
|
||||||
|
#[ts(type = "string | null")]
|
||||||
|
pub ssl_scheme: Option<InternedString>,
|
||||||
pub suffix: String,
|
pub suffix: String,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,6 @@ impl Middleware<RegistryContext> for Auth {
|
|||||||
if request.headers().contains_key(AUTH_SIG_HEADER) {
|
if request.headers().contains_key(AUTH_SIG_HEADER) {
|
||||||
self.signer = Some(
|
self.signer = Some(
|
||||||
async {
|
async {
|
||||||
let request = request;
|
|
||||||
let SignatureHeader {
|
let SignatureHeader {
|
||||||
commitment,
|
commitment,
|
||||||
signer,
|
signer,
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ use persistent_container::PersistentContainer;
|
|||||||
use rpc_toolkit::{from_fn_async, CallRemoteHandler, Empty, HandlerArgs, HandlerFor};
|
use rpc_toolkit::{from_fn_async, CallRemoteHandler, Empty, HandlerArgs, HandlerFor};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use start_stop::StartStop;
|
use start_stop::StartStop;
|
||||||
use tokio::{fs::File, sync::Notify};
|
use tokio::fs::File;
|
||||||
|
use tokio::sync::Notify;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
use crate::context::{CliContext, RpcContext};
|
use crate::context::{CliContext, RpcContext};
|
||||||
@@ -308,7 +309,7 @@ impl Service {
|
|||||||
.send(transition::restore::Restore {
|
.send(transition::restore::Restore {
|
||||||
path: backup_source.path().to_path_buf(),
|
path: backup_source.path().to_path_buf(),
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
Ok(service)
|
Ok(service)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +371,7 @@ impl Service {
|
|||||||
.send(transition::backup::Backup {
|
.send(transition::backup::Backup {
|
||||||
path: guard.path().to_path_buf(),
|
path: guard.path().to_path_buf(),
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use imbl_value::InternedString;
|
|||||||
use models::{ProcedureName, VolumeId};
|
use models::{ProcedureName, VolumeId};
|
||||||
use rpc_toolkit::{Empty, Server, ShutdownHandle};
|
use rpc_toolkit::{Empty, Server, ShutdownHandle};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use tokio::fs::{ File};
|
use tokio::fs::File;
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
use tokio::sync::{oneshot, watch, Mutex, OnceCell};
|
use tokio::sync::{oneshot, watch, Mutex, OnceCell};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use std::sync::{Arc, Weak};
|
|||||||
use clap::builder::ValueParserFactory;
|
use clap::builder::ValueParserFactory;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use emver::VersionRange;
|
use emver::VersionRange;
|
||||||
use imbl::OrdMap;
|
|
||||||
use imbl_value::{json, InternedString};
|
use imbl_value::{json, InternedString};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use models::{
|
use models::{
|
||||||
@@ -30,12 +29,9 @@ use crate::disk::mount::filesystem::idmapped::IdMapped;
|
|||||||
use crate::disk::mount::filesystem::loop_dev::LoopDev;
|
use crate::disk::mount::filesystem::loop_dev::LoopDev;
|
||||||
use crate::disk::mount::filesystem::overlayfs::OverlayGuard;
|
use crate::disk::mount::filesystem::overlayfs::OverlayGuard;
|
||||||
use crate::net::host::address::HostAddress;
|
use crate::net::host::address::HostAddress;
|
||||||
use crate::net::host::binding::BindOptions;
|
use crate::net::host::binding::{BindOptions, LanInfo};
|
||||||
use crate::net::host::{self, HostKind};
|
use crate::net::host::{Host, HostKind};
|
||||||
use crate::net::service_interface::{
|
use crate::net::service_interface::{AddressInfo, ServiceInterface, ServiceInterfaceType};
|
||||||
AddressInfo, ExportedHostInfo, ExportedHostnameInfo, ServiceInterface, ServiceInterfaceType,
|
|
||||||
ServiceInterfaceWithHostInfo,
|
|
||||||
};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::s9pk::merkle_archive::source::http::HttpSource;
|
use crate::s9pk::merkle_archive::source::http::HttpSource;
|
||||||
use crate::s9pk::rpc::SKIP_ENV;
|
use crate::s9pk::rpc::SKIP_ENV;
|
||||||
@@ -193,7 +189,6 @@ pub fn service_effect_handler<C: Context>() -> ParentHandler<C> {
|
|||||||
.subcommand("removeAddress", from_fn_async(remove_address).no_cli())
|
.subcommand("removeAddress", from_fn_async(remove_address).no_cli())
|
||||||
.subcommand("exportAction", from_fn_async(export_action).no_cli())
|
.subcommand("exportAction", from_fn_async(export_action).no_cli())
|
||||||
.subcommand("removeAction", from_fn_async(remove_action).no_cli())
|
.subcommand("removeAction", from_fn_async(remove_action).no_cli())
|
||||||
.subcommand("reverseProxy", from_fn_async(reverse_proxy).no_cli())
|
|
||||||
.subcommand("mount", from_fn_async(mount).no_cli())
|
.subcommand("mount", from_fn_async(mount).no_cli())
|
||||||
|
|
||||||
// TODO Callbacks
|
// TODO Callbacks
|
||||||
@@ -233,8 +228,6 @@ struct ExportServiceInterfaceParams {
|
|||||||
masked: bool,
|
masked: bool,
|
||||||
address_info: AddressInfo,
|
address_info: AddressInfo,
|
||||||
r#type: ServiceInterfaceType,
|
r#type: ServiceInterfaceType,
|
||||||
host_kind: HostKind,
|
|
||||||
hostnames: Vec<ExportedHostnameInfo>,
|
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
@@ -242,9 +235,8 @@ struct ExportServiceInterfaceParams {
|
|||||||
struct GetPrimaryUrlParams {
|
struct GetPrimaryUrlParams {
|
||||||
#[ts(type = "string | null")]
|
#[ts(type = "string | null")]
|
||||||
package_id: Option<PackageId>,
|
package_id: Option<PackageId>,
|
||||||
service_interface_id: String,
|
service_interface_id: ServiceInterfaceId,
|
||||||
callback: Callback,
|
callback: Callback,
|
||||||
host_id: HostId,
|
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
@@ -276,37 +268,7 @@ struct RemoveActionParams {
|
|||||||
#[ts(type = "string")]
|
#[ts(type = "string")]
|
||||||
id: ActionId,
|
id: ActionId,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
|
||||||
#[ts(export)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
struct ReverseProxyBind {
|
|
||||||
ip: Option<String>,
|
|
||||||
port: u32,
|
|
||||||
ssl: bool,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
|
||||||
#[ts(export)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
struct ReverseProxyDestination {
|
|
||||||
ip: Option<String>,
|
|
||||||
port: u32,
|
|
||||||
ssl: bool,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
|
||||||
#[ts(export)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
struct ReverseProxyHttp {
|
|
||||||
#[ts(type = "null | {[key: string]: string}")]
|
|
||||||
headers: Option<OrdMap<String, String>>,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
|
||||||
#[ts(export)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
struct ReverseProxyParams {
|
|
||||||
bind: ReverseProxyBind,
|
|
||||||
dst: ReverseProxyDestination,
|
|
||||||
http: ReverseProxyHttp,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@@ -367,7 +329,7 @@ async fn get_container_ip(context: EffectContext, _: Empty) -> Result<Ipv4Addr,
|
|||||||
async fn get_service_port_forward(
|
async fn get_service_port_forward(
|
||||||
context: EffectContext,
|
context: EffectContext,
|
||||||
data: GetServicePortForwardParams,
|
data: GetServicePortForwardParams,
|
||||||
) -> Result<u16, Error> {
|
) -> Result<LanInfo, Error> {
|
||||||
let internal_port = data.internal_port as u16;
|
let internal_port = data.internal_port as u16;
|
||||||
|
|
||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
@@ -404,13 +366,10 @@ async fn export_service_interface(
|
|||||||
masked,
|
masked,
|
||||||
address_info,
|
address_info,
|
||||||
r#type,
|
r#type,
|
||||||
host_kind,
|
|
||||||
hostnames,
|
|
||||||
}: ExportServiceInterfaceParams,
|
}: ExportServiceInterfaceParams,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
let package_id = context.id.clone();
|
let package_id = context.id.clone();
|
||||||
let host_id = address_info.host_id.clone();
|
|
||||||
|
|
||||||
let service_interface = ServiceInterface {
|
let service_interface = ServiceInterface {
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
@@ -422,15 +381,7 @@ async fn export_service_interface(
|
|||||||
address_info,
|
address_info,
|
||||||
interface_type: r#type,
|
interface_type: r#type,
|
||||||
};
|
};
|
||||||
let host_info = ExportedHostInfo {
|
let svc_interface_with_host_info = service_interface;
|
||||||
id: host_id,
|
|
||||||
kind: host_kind,
|
|
||||||
hostnames,
|
|
||||||
};
|
|
||||||
let svc_interface_with_host_info = ServiceInterfaceWithHostInfo {
|
|
||||||
service_interface,
|
|
||||||
host_info,
|
|
||||||
};
|
|
||||||
|
|
||||||
context
|
context
|
||||||
.ctx
|
.ctx
|
||||||
@@ -449,35 +400,26 @@ async fn export_service_interface(
|
|||||||
}
|
}
|
||||||
async fn get_primary_url(
|
async fn get_primary_url(
|
||||||
context: EffectContext,
|
context: EffectContext,
|
||||||
data: GetPrimaryUrlParams,
|
GetPrimaryUrlParams {
|
||||||
) -> Result<HostAddress, Error> {
|
package_id,
|
||||||
|
service_interface_id,
|
||||||
|
callback,
|
||||||
|
}: GetPrimaryUrlParams,
|
||||||
|
) -> Result<Option<HostAddress>, Error> {
|
||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
let package_id = context.id.clone();
|
let package_id = package_id.unwrap_or_else(|| context.id.clone());
|
||||||
|
|
||||||
let db_model = context.ctx.db.peek().await;
|
Ok(None) // TODO
|
||||||
|
|
||||||
let pkg_data_model = db_model
|
|
||||||
.as_public()
|
|
||||||
.as_package_data()
|
|
||||||
.as_idx(&package_id)
|
|
||||||
.or_not_found(&package_id)?;
|
|
||||||
|
|
||||||
let host = pkg_data_model.de()?.hosts.get_host_primary(&data.host_id);
|
|
||||||
|
|
||||||
match host {
|
|
||||||
Some(host_address) => Ok(host_address),
|
|
||||||
None => Err(Error::new(
|
|
||||||
eyre!("Primary Url not found for {}", data.host_id),
|
|
||||||
crate::ErrorKind::NotFound,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async fn list_service_interfaces(
|
async fn list_service_interfaces(
|
||||||
context: EffectContext,
|
context: EffectContext,
|
||||||
data: ListServiceInterfacesParams,
|
ListServiceInterfacesParams {
|
||||||
) -> Result<BTreeMap<ServiceInterfaceId, ServiceInterfaceWithHostInfo>, Error> {
|
package_id,
|
||||||
|
callback,
|
||||||
|
}: ListServiceInterfacesParams,
|
||||||
|
) -> Result<BTreeMap<ServiceInterfaceId, ServiceInterface>, Error> {
|
||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
let package_id = context.id.clone();
|
let package_id = package_id.unwrap_or_else(|| context.id.clone());
|
||||||
|
|
||||||
context
|
context
|
||||||
.ctx
|
.ctx
|
||||||
@@ -553,10 +495,8 @@ async fn remove_action(context: EffectContext, data: RemoveActionParams) -> Resu
|
|||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn reverse_proxy(context: EffectContext, data: ReverseProxyParams) -> Result<Value, Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
async fn mount(context: EffectContext, data: MountParams) -> Result<Value, Error> {
|
async fn mount(context: EffectContext, data: MountParams) -> Result<Value, Error> {
|
||||||
|
// TODO
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,49 +504,42 @@ async fn mount(context: EffectContext, data: MountParams) -> Result<Value, Error
|
|||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
struct Callback(#[ts(type = "() => void")] i64);
|
struct Callback(#[ts(type = "() => void")] i64);
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
#[ts(export)]
|
|
||||||
enum GetHostInfoParamsKind {
|
|
||||||
Multi,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
struct GetHostInfoParams {
|
struct GetHostInfoParams {
|
||||||
kind: Option<GetHostInfoParamsKind>,
|
host_id: HostId,
|
||||||
service_interface_id: String,
|
|
||||||
#[ts(type = "string | null")]
|
#[ts(type = "string | null")]
|
||||||
package_id: Option<PackageId>,
|
package_id: Option<PackageId>,
|
||||||
callback: Callback,
|
callback: Callback,
|
||||||
}
|
}
|
||||||
async fn get_host_info(
|
async fn get_host_info(
|
||||||
ctx: EffectContext,
|
ctx: EffectContext,
|
||||||
GetHostInfoParams { .. }: GetHostInfoParams,
|
GetHostInfoParams {
|
||||||
) -> Result<Value, Error> {
|
callback,
|
||||||
|
package_id,
|
||||||
|
host_id,
|
||||||
|
}: GetHostInfoParams,
|
||||||
|
) -> Result<Host, Error> {
|
||||||
let ctx = ctx.deref()?;
|
let ctx = ctx.deref()?;
|
||||||
Ok(json!({
|
let db = ctx.ctx.db.peek().await;
|
||||||
"id": "fakeId1",
|
let package_id = package_id.unwrap_or_else(|| ctx.id.clone());
|
||||||
"kind": "multi",
|
|
||||||
"hostnames": [{
|
|
||||||
"kind": "ip",
|
|
||||||
"networkInterfaceId": "fakeNetworkInterfaceId1",
|
|
||||||
"public": true,
|
|
||||||
"hostname":{
|
|
||||||
"kind": "domain",
|
|
||||||
"domain": format!("{}", ctx.id),
|
|
||||||
"subdomain": (),
|
|
||||||
"port": (),
|
|
||||||
"sslPort": ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
db.as_public()
|
||||||
}))
|
.as_package_data()
|
||||||
|
.as_idx(&package_id)
|
||||||
|
.or_not_found(&package_id)?
|
||||||
|
.as_hosts()
|
||||||
|
.as_idx(&host_id)
|
||||||
|
.or_not_found(&host_id)?
|
||||||
|
.de()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn clear_bindings(context: EffectContext, _: Empty) -> Result<Value, Error> {
|
async fn clear_bindings(context: EffectContext, _: Empty) -> Result<(), Error> {
|
||||||
todo!()
|
let ctx = context.deref()?;
|
||||||
|
let mut svc = ctx.persistent_container.net_service.lock().await;
|
||||||
|
svc.clear_bindings().await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||||
@@ -619,15 +552,13 @@ struct BindParams {
|
|||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
options: BindOptions,
|
options: BindOptions,
|
||||||
}
|
}
|
||||||
async fn bind(
|
async fn bind(context: EffectContext, bind_params: Value) -> Result<(), Error> {
|
||||||
context: EffectContext,
|
let BindParams {
|
||||||
BindParams {
|
|
||||||
kind,
|
kind,
|
||||||
id,
|
id,
|
||||||
internal_port,
|
internal_port,
|
||||||
options,
|
options,
|
||||||
}: BindParams,
|
} = from_value(bind_params)?;
|
||||||
) -> Result<(), Error> {
|
|
||||||
let ctx = context.deref()?;
|
let ctx = context.deref()?;
|
||||||
let mut svc = ctx.persistent_container.net_service.lock().await;
|
let mut svc = ctx.persistent_container.net_service.lock().await;
|
||||||
svc.bind(kind, id, internal_port, options).await
|
svc.bind(kind, id, internal_port, options).await
|
||||||
@@ -639,39 +570,32 @@ async fn bind(
|
|||||||
struct GetServiceInterfaceParams {
|
struct GetServiceInterfaceParams {
|
||||||
#[ts(type = "string | null")]
|
#[ts(type = "string | null")]
|
||||||
package_id: Option<PackageId>,
|
package_id: Option<PackageId>,
|
||||||
service_interface_id: String,
|
service_interface_id: ServiceInterfaceId,
|
||||||
callback: Callback,
|
callback: Callback,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_service_interface(
|
async fn get_service_interface(
|
||||||
_: EffectContext,
|
ctx: EffectContext,
|
||||||
GetServiceInterfaceParams {
|
GetServiceInterfaceParams {
|
||||||
callback,
|
callback,
|
||||||
package_id,
|
package_id,
|
||||||
service_interface_id,
|
service_interface_id,
|
||||||
}: GetServiceInterfaceParams,
|
}: GetServiceInterfaceParams,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<ServiceInterface, Error> {
|
||||||
// TODO @Dr_Bonez
|
let ctx = ctx.deref()?;
|
||||||
Ok(json!({
|
let package_id = package_id.unwrap_or_else(|| ctx.id.clone());
|
||||||
"id": service_interface_id,
|
let db = ctx.ctx.db.peek().await;
|
||||||
"name": service_interface_id,
|
|
||||||
"description": "This is a fake",
|
let interface = db
|
||||||
"hasPrimary": true,
|
.as_public()
|
||||||
"disabled": false,
|
.as_package_data()
|
||||||
"masked": false,
|
.as_idx(&package_id)
|
||||||
"addressInfo": json!({
|
.or_not_found(&package_id)?
|
||||||
"username": Value::Null,
|
.as_service_interfaces()
|
||||||
"hostId": "HostId?",
|
.as_idx(&service_interface_id)
|
||||||
"options": json!({
|
.or_not_found(&service_interface_id)?
|
||||||
"scheme": Value::Null,
|
.de()?;
|
||||||
"preferredExternalPort": 80,
|
Ok(interface)
|
||||||
"addSsl":Value::Null,
|
|
||||||
"secure": false,
|
|
||||||
"ssl": false
|
|
||||||
}),
|
|
||||||
"suffix": "http"
|
|
||||||
}),
|
|
||||||
"type": "api"
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Parser, TS)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Parser, TS)]
|
||||||
@@ -764,6 +688,7 @@ async fn get_ssl_certificate(
|
|||||||
host_id,
|
host_id,
|
||||||
}: GetSslCertificateParams,
|
}: GetSslCertificateParams,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
|
// TODO
|
||||||
let fake = include_str!("./fake.cert.pem");
|
let fake = include_str!("./fake.cert.pem");
|
||||||
Ok(json!([fake, fake, fake]))
|
Ok(json!([fake, fake, fake]))
|
||||||
}
|
}
|
||||||
@@ -785,6 +710,7 @@ async fn get_ssl_key(
|
|||||||
algorithm,
|
algorithm,
|
||||||
}: GetSslKeyParams,
|
}: GetSslKeyParams,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
|
// TODO
|
||||||
let fake = include_str!("./fake.cert.key");
|
let fake = include_str!("./fake.cert.key");
|
||||||
Ok(json!(fake))
|
Ok(json!(fake))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ import {
|
|||||||
} from "./interfaces/setupInterfaces"
|
} from "./interfaces/setupInterfaces"
|
||||||
import { successFailure } from "./trigger/successFailure"
|
import { successFailure } from "./trigger/successFailure"
|
||||||
import { HealthReceipt } from "./health/HealthReceipt"
|
import { HealthReceipt } from "./health/HealthReceipt"
|
||||||
import { MultiHost, Scheme, SingleHost, StaticHost } from "./interfaces/Host"
|
import { MultiHost, Scheme } from "./interfaces/Host"
|
||||||
import { ServiceInterfaceBuilder } from "./interfaces/ServiceInterfaceBuilder"
|
import { ServiceInterfaceBuilder } from "./interfaces/ServiceInterfaceBuilder"
|
||||||
import { GetSystemSmtp } from "./util/GetSystemSmtp"
|
import { GetSystemSmtp } from "./util/GetSystemSmtp"
|
||||||
import nullIfEmpty from "./util/nullIfEmpty"
|
import nullIfEmpty from "./util/nullIfEmpty"
|
||||||
@@ -178,10 +178,10 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
|||||||
},
|
},
|
||||||
|
|
||||||
host: {
|
host: {
|
||||||
static: (effects: Effects, id: string) =>
|
// static: (effects: Effects, id: string) =>
|
||||||
new StaticHost({ id, effects }),
|
// new StaticHost({ id, effects }),
|
||||||
single: (effects: Effects, id: string) =>
|
// single: (effects: Effects, id: string) =>
|
||||||
new SingleHost({ id, effects }),
|
// new SingleHost({ id, effects }),
|
||||||
multi: (effects: Effects, id: string) => new MultiHost({ id, effects }),
|
multi: (effects: Effects, id: string) => new MultiHost({ id, effects }),
|
||||||
},
|
},
|
||||||
nullIfEmpty,
|
nullIfEmpty,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { object, string } from "ts-matches"
|
import { number, object, string } from "ts-matches"
|
||||||
import { Effects } from "../types"
|
import { Effects } from "../types"
|
||||||
import { Origin } from "./Origin"
|
import { Origin } from "./Origin"
|
||||||
import { AddSslOptions } from ".././osBindings"
|
import { AddSslOptions, BindParams } from ".././osBindings"
|
||||||
import { Security } from ".././osBindings"
|
import { Security } from ".././osBindings"
|
||||||
import { BindOptions } from ".././osBindings"
|
import { BindOptions } from ".././osBindings"
|
||||||
import { AlpnInfo } from ".././osBindings"
|
import { AlpnInfo } from ".././osBindings"
|
||||||
|
|
||||||
export { AddSslOptions, Security, BindOptions }
|
export { AddSslOptions, Security, BindOptions }
|
||||||
|
|
||||||
const knownProtocols = {
|
export const knownProtocols = {
|
||||||
http: {
|
http: {
|
||||||
secure: null,
|
secure: null,
|
||||||
defaultPort: 80,
|
defaultPort: 80,
|
||||||
@@ -69,19 +69,17 @@ type NotProtocolsWithSslVariants = Exclude<
|
|||||||
type BindOptionsByKnownProtocol =
|
type BindOptionsByKnownProtocol =
|
||||||
| {
|
| {
|
||||||
protocol: ProtocolsWithSslVariants
|
protocol: ProtocolsWithSslVariants
|
||||||
preferredExternalPort?: number
|
preferredExternalPort: number
|
||||||
scheme?: Scheme
|
|
||||||
addSsl?: Partial<AddSslOptions>
|
addSsl?: Partial<AddSslOptions>
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
protocol: NotProtocolsWithSslVariants
|
protocol: NotProtocolsWithSslVariants
|
||||||
preferredExternalPort?: number
|
preferredExternalPort: number
|
||||||
scheme?: Scheme
|
|
||||||
addSsl?: AddSslOptions
|
addSsl?: AddSslOptions
|
||||||
}
|
}
|
||||||
type BindOptionsByProtocol = BindOptionsByKnownProtocol | BindOptions
|
export type BindOptionsByProtocol = BindOptionsByKnownProtocol | BindOptions
|
||||||
|
|
||||||
export type HostKind = "static" | "single" | "multi"
|
export type HostKind = BindParams["kind"]
|
||||||
|
|
||||||
const hasStringProtocol = object({
|
const hasStringProtocol = object({
|
||||||
protocol: string,
|
protocol: string,
|
||||||
@@ -110,66 +108,62 @@ export class Host {
|
|||||||
private async bindPortForUnknown(
|
private async bindPortForUnknown(
|
||||||
internalPort: number,
|
internalPort: number,
|
||||||
options: {
|
options: {
|
||||||
scheme: Scheme
|
|
||||||
preferredExternalPort: number
|
preferredExternalPort: number
|
||||||
addSsl: AddSslOptions | null
|
addSsl: AddSslOptions | null
|
||||||
secure: { ssl: boolean } | null
|
secure: { ssl: boolean } | null
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
await this.options.effects.bind({
|
const binderOptions = {
|
||||||
kind: this.options.kind,
|
kind: this.options.kind,
|
||||||
id: this.options.id,
|
id: this.options.id,
|
||||||
internalPort: internalPort,
|
internalPort,
|
||||||
...options,
|
...options,
|
||||||
})
|
}
|
||||||
|
await this.options.effects.bind(binderOptions)
|
||||||
|
|
||||||
return new Origin(this, options)
|
return new Origin(this, internalPort, null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async bindPortForKnown(
|
private async bindPortForKnown(
|
||||||
options: BindOptionsByKnownProtocol,
|
options: BindOptionsByKnownProtocol,
|
||||||
internalPort: number,
|
internalPort: number,
|
||||||
) {
|
) {
|
||||||
const scheme =
|
|
||||||
options.scheme === undefined ? options.protocol : options.scheme
|
|
||||||
const protoInfo = knownProtocols[options.protocol]
|
const protoInfo = knownProtocols[options.protocol]
|
||||||
const preferredExternalPort =
|
const preferredExternalPort =
|
||||||
options.preferredExternalPort ||
|
options.preferredExternalPort ||
|
||||||
knownProtocols[options.protocol].defaultPort
|
knownProtocols[options.protocol].defaultPort
|
||||||
const addSsl = this.getAddSsl(options, protoInfo)
|
const sslProto = this.getSslProto(options, protoInfo)
|
||||||
|
const addSsl =
|
||||||
|
sslProto && "alpn" in protoInfo
|
||||||
|
? {
|
||||||
|
// addXForwardedHeaders: null,
|
||||||
|
preferredExternalPort: knownProtocols[sslProto].defaultPort,
|
||||||
|
scheme: sslProto,
|
||||||
|
alpn: protoInfo.alpn,
|
||||||
|
...("addSsl" in options ? options.addSsl : null),
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
|
||||||
const secure: Security | null = !protoInfo.secure ? null : { ssl: false }
|
const secure: Security | null = !protoInfo.secure ? null : { ssl: false }
|
||||||
|
|
||||||
const newOptions = {
|
|
||||||
scheme,
|
|
||||||
preferredExternalPort,
|
|
||||||
addSsl,
|
|
||||||
secure,
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.options.effects.bind({
|
await this.options.effects.bind({
|
||||||
kind: this.options.kind,
|
kind: this.options.kind,
|
||||||
id: this.options.id,
|
id: this.options.id,
|
||||||
internalPort,
|
internalPort,
|
||||||
...newOptions,
|
preferredExternalPort,
|
||||||
|
addSsl,
|
||||||
|
secure,
|
||||||
})
|
})
|
||||||
|
|
||||||
return new Origin(this, newOptions)
|
return new Origin(this, internalPort, options.protocol, sslProto)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAddSsl(
|
private getSslProto(
|
||||||
options: BindOptionsByKnownProtocol,
|
options: BindOptionsByKnownProtocol,
|
||||||
protoInfo: KnownProtocols[keyof KnownProtocols],
|
protoInfo: KnownProtocols[keyof KnownProtocols],
|
||||||
): AddSslOptions | null {
|
) {
|
||||||
if (inObject("noAddSsl", options) && options.noAddSsl) return null
|
if (inObject("noAddSsl", options) && options.noAddSsl) return null
|
||||||
if ("withSsl" in protoInfo && protoInfo.withSsl)
|
if ("withSsl" in protoInfo && protoInfo.withSsl) return protoInfo.withSsl
|
||||||
return {
|
|
||||||
// addXForwardedHeaders: null,
|
|
||||||
preferredExternalPort: knownProtocols[protoInfo.withSsl].defaultPort,
|
|
||||||
scheme: protoInfo.withSsl,
|
|
||||||
alpn: protoInfo.alpn,
|
|
||||||
...("addSsl" in options ? options.addSsl : null),
|
|
||||||
}
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,17 +175,17 @@ function inObject<Key extends string>(
|
|||||||
return key in obj
|
return key in obj
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StaticHost extends Host {
|
// export class StaticHost extends Host {
|
||||||
constructor(options: { effects: Effects; id: string }) {
|
// constructor(options: { effects: Effects; id: string }) {
|
||||||
super({ ...options, kind: "static" })
|
// super({ ...options, kind: "static" })
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
export class SingleHost extends Host {
|
// export class SingleHost extends Host {
|
||||||
constructor(options: { effects: Effects; id: string }) {
|
// constructor(options: { effects: Effects; id: string }) {
|
||||||
super({ ...options, kind: "single" })
|
// super({ ...options, kind: "single" })
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
export class MultiHost extends Host {
|
export class MultiHost extends Host {
|
||||||
constructor(options: { effects: Effects; id: string }) {
|
constructor(options: { effects: Effects; id: string }) {
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import { ServiceInterfaceBuilder } from "./ServiceInterfaceBuilder"
|
|||||||
export class Origin<T extends Host> {
|
export class Origin<T extends Host> {
|
||||||
constructor(
|
constructor(
|
||||||
readonly host: T,
|
readonly host: T,
|
||||||
readonly options: BindOptions,
|
readonly internalPort: number,
|
||||||
|
readonly scheme: string | null,
|
||||||
|
readonly sslScheme: string | null,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
build({ username, path, search, schemeOverride }: BuildOptions): AddressInfo {
|
build({ username, path, search, schemeOverride }: BuildOptions): AddressInfo {
|
||||||
@@ -20,18 +22,9 @@ export class Origin<T extends Host> {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
hostId: this.host.options.id,
|
hostId: this.host.options.id,
|
||||||
bindOptions: {
|
internalPort: this.internalPort,
|
||||||
...this.options,
|
scheme: schemeOverride ? schemeOverride.noSsl : this.scheme,
|
||||||
scheme: schemeOverride ? schemeOverride.noSsl : this.options.scheme,
|
sslScheme: schemeOverride ? schemeOverride.ssl : this.sslScheme,
|
||||||
addSsl: this.options.addSsl
|
|
||||||
? {
|
|
||||||
...this.options.addSsl,
|
|
||||||
scheme: schemeOverride
|
|
||||||
? schemeOverride.ssl
|
|
||||||
: this.options.addSsl.scheme,
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
},
|
|
||||||
suffix: `${path}${qp}`,
|
suffix: `${path}${qp}`,
|
||||||
username,
|
username,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import type { Version } from "./Version"
|
|||||||
export type AddAssetParams = {
|
export type AddAssetParams = {
|
||||||
version: Version
|
version: Version
|
||||||
platform: string
|
platform: string
|
||||||
upload: boolean
|
|
||||||
url: string
|
url: string
|
||||||
signature: AnySignature
|
signature: AnySignature
|
||||||
commitment: Blake3Commitment
|
commitment: Blake3Commitment
|
||||||
|
|||||||
9
sdk/lib/osBindings/AddPackageParams.ts
Normal file
9
sdk/lib/osBindings/AddPackageParams.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
import type { AnySignature } from "./AnySignature"
|
||||||
|
import type { MerkleArchiveCommitment } from "./MerkleArchiveCommitment"
|
||||||
|
|
||||||
|
export type AddPackageParams = {
|
||||||
|
url: string
|
||||||
|
commitment: MerkleArchiveCommitment
|
||||||
|
signature: AnySignature
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
import type { AlpnInfo } from "./AlpnInfo"
|
import type { AlpnInfo } from "./AlpnInfo"
|
||||||
|
|
||||||
export type AddSslOptions = {
|
export type AddSslOptions = {
|
||||||
scheme: string | null
|
|
||||||
preferredExternalPort: number
|
preferredExternalPort: number
|
||||||
alpn: AlpnInfo
|
alpn: AlpnInfo | null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { BindOptions } from "./BindOptions"
|
|
||||||
import type { HostId } from "./HostId"
|
import type { HostId } from "./HostId"
|
||||||
|
|
||||||
export type AddressInfo = {
|
export type AddressInfo = {
|
||||||
username: string | null
|
username: string | null
|
||||||
hostId: HostId
|
hostId: HostId
|
||||||
bindOptions: BindOptions
|
internalPort: number
|
||||||
|
scheme: string | null
|
||||||
|
sslScheme: string | null
|
||||||
suffix: string
|
suffix: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { BindOptions } from "./BindOptions"
|
import type { BindOptions } from "./BindOptions"
|
||||||
|
import type { LanInfo } from "./LanInfo"
|
||||||
|
|
||||||
export type BindInfo = { options: BindOptions; assignedLanPort: number | null }
|
export type BindInfo = { options: BindOptions; lan: LanInfo }
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import type { AddSslOptions } from "./AddSslOptions"
|
|||||||
import type { Security } from "./Security"
|
import type { Security } from "./Security"
|
||||||
|
|
||||||
export type BindOptions = {
|
export type BindOptions = {
|
||||||
scheme: string | null
|
|
||||||
preferredExternalPort: number
|
preferredExternalPort: number
|
||||||
addSsl: AddSslOptions | null
|
addSsl: AddSslOptions | null
|
||||||
secure: Security | null
|
secure: Security | null
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ export type BindParams = {
|
|||||||
kind: HostKind
|
kind: HostKind
|
||||||
id: HostId
|
id: HostId
|
||||||
internalPort: number
|
internalPort: number
|
||||||
scheme: string | null
|
|
||||||
preferredExternalPort: number
|
preferredExternalPort: number
|
||||||
addSsl: AddSslOptions | null
|
addSsl: AddSslOptions | null
|
||||||
secure: Security | null
|
secure: Security | null
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { AddressInfo } from "./AddressInfo"
|
import type { AddressInfo } from "./AddressInfo"
|
||||||
import type { ExportedHostnameInfo } from "./ExportedHostnameInfo"
|
|
||||||
import type { HostKind } from "./HostKind"
|
|
||||||
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
|
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
|
||||||
import type { ServiceInterfaceType } from "./ServiceInterfaceType"
|
import type { ServiceInterfaceType } from "./ServiceInterfaceType"
|
||||||
|
|
||||||
@@ -14,6 +12,4 @@ export type ExportServiceInterfaceParams = {
|
|||||||
masked: boolean
|
masked: boolean
|
||||||
addressInfo: AddressInfo
|
addressInfo: AddressInfo
|
||||||
type: ServiceInterfaceType
|
type: ServiceInterfaceType
|
||||||
hostKind: HostKind
|
|
||||||
hostnames: Array<ExportedHostnameInfo>
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
import type { ExportedHostnameInfo } from "./ExportedHostnameInfo"
|
|
||||||
import type { HostId } from "./HostId"
|
|
||||||
import type { HostKind } from "./HostKind"
|
|
||||||
|
|
||||||
export type ExportedHostInfo = {
|
|
||||||
id: HostId
|
|
||||||
kind: HostKind
|
|
||||||
hostnames: Array<ExportedHostnameInfo>
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
import type { ExportedIpHostname } from "./ExportedIpHostname"
|
|
||||||
import type { ExportedOnionHostname } from "./ExportedOnionHostname"
|
|
||||||
|
|
||||||
export type ExportedHostnameInfo =
|
|
||||||
| {
|
|
||||||
kind: "ip"
|
|
||||||
networkInterfaceId: string
|
|
||||||
public: boolean
|
|
||||||
hostname: ExportedIpHostname
|
|
||||||
}
|
|
||||||
| { kind: "onion"; hostname: ExportedOnionHostname }
|
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { Callback } from "./Callback"
|
import type { Callback } from "./Callback"
|
||||||
import type { GetHostInfoParamsKind } from "./GetHostInfoParamsKind"
|
import type { HostId } from "./HostId"
|
||||||
|
|
||||||
export type GetHostInfoParams = {
|
export type GetHostInfoParams = {
|
||||||
kind: GetHostInfoParamsKind | null
|
hostId: HostId
|
||||||
serviceInterfaceId: string
|
|
||||||
packageId: string | null
|
packageId: string | null
|
||||||
callback: Callback
|
callback: Callback
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
|
|
||||||
export type GetHostInfoParamsKind = "multi"
|
|
||||||
@@ -4,6 +4,7 @@ import type { PackageVersionInfo } from "./PackageVersionInfo"
|
|||||||
import type { Version } from "./Version"
|
import type { Version } from "./Version"
|
||||||
|
|
||||||
export type GetPackageResponse = {
|
export type GetPackageResponse = {
|
||||||
|
categories: string[]
|
||||||
best: { [key: Version]: PackageVersionInfo }
|
best: { [key: Version]: PackageVersionInfo }
|
||||||
otherVersions?: { [key: Version]: PackageInfoShort }
|
otherVersions?: { [key: Version]: PackageInfoShort }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { PackageVersionInfo } from "./PackageVersionInfo"
|
|||||||
import type { Version } from "./Version"
|
import type { Version } from "./Version"
|
||||||
|
|
||||||
export type GetPackageResponseFull = {
|
export type GetPackageResponseFull = {
|
||||||
|
categories: string[]
|
||||||
best: { [key: Version]: PackageVersionInfo }
|
best: { [key: Version]: PackageVersionInfo }
|
||||||
otherVersions: { [key: Version]: PackageVersionInfo }
|
otherVersions: { [key: Version]: PackageVersionInfo }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { Callback } from "./Callback"
|
import type { Callback } from "./Callback"
|
||||||
import type { HostId } from "./HostId"
|
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
|
||||||
|
|
||||||
export type GetPrimaryUrlParams = {
|
export type GetPrimaryUrlParams = {
|
||||||
packageId: string | null
|
packageId: string | null
|
||||||
serviceInterfaceId: string
|
serviceInterfaceId: ServiceInterfaceId
|
||||||
callback: Callback
|
callback: Callback
|
||||||
hostId: HostId
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { Callback } from "./Callback"
|
import type { Callback } from "./Callback"
|
||||||
|
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
|
||||||
|
|
||||||
export type GetServiceInterfaceParams = {
|
export type GetServiceInterfaceParams = {
|
||||||
packageId: string | null
|
packageId: string | null
|
||||||
serviceInterfaceId: string
|
serviceInterfaceId: ServiceInterfaceId
|
||||||
callback: Callback
|
callback: Callback
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
export type HardwareRequirements = {
|
export type HardwareRequirements = {
|
||||||
device: { [key: string]: string }
|
device: { [key: string]: string }
|
||||||
ram: number | null
|
ram: number | null
|
||||||
arch: Array<string> | null
|
arch: string[] | null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,14 @@
|
|||||||
import type { BindInfo } from "./BindInfo"
|
import type { BindInfo } from "./BindInfo"
|
||||||
import type { HostAddress } from "./HostAddress"
|
import type { HostAddress } from "./HostAddress"
|
||||||
import type { HostKind } from "./HostKind"
|
import type { HostKind } from "./HostKind"
|
||||||
|
import type { HostnameInfo } from "./HostnameInfo"
|
||||||
|
|
||||||
export type Host = {
|
export type Host = {
|
||||||
kind: HostKind
|
kind: HostKind
|
||||||
bindings: { [key: number]: BindInfo }
|
bindings: { [key: number]: BindInfo }
|
||||||
addresses: Array<HostAddress>
|
addresses: Array<HostAddress>
|
||||||
primary: HostAddress | null
|
/**
|
||||||
|
* COMPUTED: NetService::update
|
||||||
|
*/
|
||||||
|
hostnameInfo: { [key: number]: Array<HostnameInfo> }
|
||||||
}
|
}
|
||||||
|
|||||||
12
sdk/lib/osBindings/HostnameInfo.ts
Normal file
12
sdk/lib/osBindings/HostnameInfo.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
import type { IpHostname } from "./IpHostname"
|
||||||
|
import type { OnionHostname } from "./OnionHostname"
|
||||||
|
|
||||||
|
export type HostnameInfo =
|
||||||
|
| {
|
||||||
|
kind: "ip"
|
||||||
|
networkInterfaceId: string
|
||||||
|
public: boolean
|
||||||
|
hostname: IpHostname
|
||||||
|
}
|
||||||
|
| { kind: "onion"; hostname: OnionHostname }
|
||||||
@@ -2,4 +2,4 @@
|
|||||||
import type { Host } from "./Host"
|
import type { Host } from "./Host"
|
||||||
import type { HostId } from "./HostId"
|
import type { HostId } from "./HostId"
|
||||||
|
|
||||||
export type HostInfo = { [key: HostId]: Host }
|
export type Hosts = { [key: HostId]: Host }
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
export type ExportedIpHostname =
|
export type IpHostname =
|
||||||
| { kind: "ipv4"; value: string; port: number | null; sslPort: number | null }
|
| { kind: "ipv4"; value: string; port: number | null; sslPort: number | null }
|
||||||
| { kind: "ipv6"; value: string; port: number | null; sslPort: number | null }
|
| { kind: "ipv6"; value: string; port: number | null; sslPort: number | null }
|
||||||
| {
|
| {
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
export type ReverseProxyDestination = {
|
export type LanInfo = {
|
||||||
ip: string | null
|
assignedPort: number | null
|
||||||
port: number
|
assignedSslPort: number | null
|
||||||
ssl: boolean
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
export type ExportedOnionHostname = {
|
export type OnionHostname = {
|
||||||
value: string
|
value: string
|
||||||
port: number | null
|
port: number | null
|
||||||
sslPort: number | null
|
sslPort: number | null
|
||||||
@@ -7,7 +7,7 @@ export type OsVersionInfo = {
|
|||||||
headline: string
|
headline: string
|
||||||
releaseNotes: string
|
releaseNotes: string
|
||||||
sourceVersion: string
|
sourceVersion: string
|
||||||
signers: Array<Guid>
|
authorized: Array<Guid>
|
||||||
iso: { [key: string]: RegistryAsset<Blake3Commitment> }
|
iso: { [key: string]: RegistryAsset<Blake3Commitment> }
|
||||||
squashfs: { [key: string]: RegistryAsset<Blake3Commitment> }
|
squashfs: { [key: string]: RegistryAsset<Blake3Commitment> }
|
||||||
img: { [key: string]: RegistryAsset<Blake3Commitment> }
|
img: { [key: string]: RegistryAsset<Blake3Commitment> }
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import type { ActionId } from "./ActionId"
|
|||||||
import type { ActionMetadata } from "./ActionMetadata"
|
import type { ActionMetadata } from "./ActionMetadata"
|
||||||
import type { CurrentDependencies } from "./CurrentDependencies"
|
import type { CurrentDependencies } from "./CurrentDependencies"
|
||||||
import type { DataUrl } from "./DataUrl"
|
import type { DataUrl } from "./DataUrl"
|
||||||
import type { HostInfo } from "./HostInfo"
|
import type { Hosts } from "./Hosts"
|
||||||
import type { PackageState } from "./PackageState"
|
import type { PackageState } from "./PackageState"
|
||||||
|
import type { ServiceInterface } from "./ServiceInterface"
|
||||||
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
|
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
|
||||||
import type { ServiceInterfaceWithHostInfo } from "./ServiceInterfaceWithHostInfo"
|
|
||||||
import type { Status } from "./Status"
|
import type { Status } from "./Status"
|
||||||
|
|
||||||
export type PackageDataEntry = {
|
export type PackageDataEntry = {
|
||||||
@@ -18,7 +18,7 @@ export type PackageDataEntry = {
|
|||||||
lastBackup: string | null
|
lastBackup: string | null
|
||||||
currentDependencies: CurrentDependencies
|
currentDependencies: CurrentDependencies
|
||||||
actions: { [key: ActionId]: ActionMetadata }
|
actions: { [key: ActionId]: ActionMetadata }
|
||||||
serviceInterfaces: { [key: ServiceInterfaceId]: ServiceInterfaceWithHostInfo }
|
serviceInterfaces: { [key: ServiceInterfaceId]: ServiceInterface }
|
||||||
hosts: HostInfo
|
hosts: Hosts
|
||||||
storeExposedDependents: string[]
|
storeExposedDependents: string[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { PackageVersionInfo } from "./PackageVersionInfo"
|
|||||||
import type { Version } from "./Version"
|
import type { Version } from "./Version"
|
||||||
|
|
||||||
export type PackageInfo = {
|
export type PackageInfo = {
|
||||||
signers: Array<Guid>
|
authorized: Array<Guid>
|
||||||
versions: { [key: Version]: PackageVersionInfo }
|
versions: { [key: Version]: PackageVersionInfo }
|
||||||
|
categories: string[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export type PackageVersionInfo = {
|
|||||||
upstreamRepo: string
|
upstreamRepo: string
|
||||||
supportSite: string
|
supportSite: string
|
||||||
marketingSite: string
|
marketingSite: string
|
||||||
categories: string[]
|
|
||||||
osVersion: Version
|
osVersion: Version
|
||||||
hardwareRequirements: HardwareRequirements
|
hardwareRequirements: HardwareRequirements
|
||||||
sourceVersion: string | null
|
sourceVersion: string | null
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
|
|
||||||
export type ReverseProxyBind = { ip: string | null; port: number; ssl: boolean }
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
|
|
||||||
export type ReverseProxyHttp = { headers: null | { [key: string]: string } }
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
import type { ReverseProxyBind } from "./ReverseProxyBind"
|
|
||||||
import type { ReverseProxyDestination } from "./ReverseProxyDestination"
|
|
||||||
import type { ReverseProxyHttp } from "./ReverseProxyHttp"
|
|
||||||
|
|
||||||
export type ReverseProxyParams = {
|
|
||||||
bind: ReverseProxyBind
|
|
||||||
dst: ReverseProxyDestination
|
|
||||||
http: ReverseProxyHttp
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
||||||
import type { AddressInfo } from "./AddressInfo"
|
|
||||||
import type { ExportedHostInfo } from "./ExportedHostInfo"
|
|
||||||
import type { ServiceInterfaceId } from "./ServiceInterfaceId"
|
|
||||||
import type { ServiceInterfaceType } from "./ServiceInterfaceType"
|
|
||||||
|
|
||||||
export type ServiceInterfaceWithHostInfo = {
|
|
||||||
hostInfo: ExportedHostInfo
|
|
||||||
id: ServiceInterfaceId
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
hasPrimary: boolean
|
|
||||||
disabled: boolean
|
|
||||||
masked: boolean
|
|
||||||
addressInfo: AddressInfo
|
|
||||||
type: ServiceInterfaceType
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ export { ActionId } from "./ActionId"
|
|||||||
export { ActionMetadata } from "./ActionMetadata"
|
export { ActionMetadata } from "./ActionMetadata"
|
||||||
export { AddAdminParams } from "./AddAdminParams"
|
export { AddAdminParams } from "./AddAdminParams"
|
||||||
export { AddAssetParams } from "./AddAssetParams"
|
export { AddAssetParams } from "./AddAssetParams"
|
||||||
|
export { AddPackageParams } from "./AddPackageParams"
|
||||||
export { AddressInfo } from "./AddressInfo"
|
export { AddressInfo } from "./AddressInfo"
|
||||||
export { AddSslOptions } from "./AddSslOptions"
|
export { AddSslOptions } from "./AddSslOptions"
|
||||||
export { AddVersionParams } from "./AddVersionParams"
|
export { AddVersionParams } from "./AddVersionParams"
|
||||||
@@ -40,15 +41,10 @@ export { Duration } from "./Duration"
|
|||||||
export { EncryptedWire } from "./EncryptedWire"
|
export { EncryptedWire } from "./EncryptedWire"
|
||||||
export { ExecuteAction } from "./ExecuteAction"
|
export { ExecuteAction } from "./ExecuteAction"
|
||||||
export { ExportActionParams } from "./ExportActionParams"
|
export { ExportActionParams } from "./ExportActionParams"
|
||||||
export { ExportedHostInfo } from "./ExportedHostInfo"
|
|
||||||
export { ExportedHostnameInfo } from "./ExportedHostnameInfo"
|
|
||||||
export { ExportedIpHostname } from "./ExportedIpHostname"
|
|
||||||
export { ExportedOnionHostname } from "./ExportedOnionHostname"
|
|
||||||
export { ExportServiceInterfaceParams } from "./ExportServiceInterfaceParams"
|
export { ExportServiceInterfaceParams } from "./ExportServiceInterfaceParams"
|
||||||
export { ExposeForDependentsParams } from "./ExposeForDependentsParams"
|
export { ExposeForDependentsParams } from "./ExposeForDependentsParams"
|
||||||
export { FullIndex } from "./FullIndex"
|
export { FullIndex } from "./FullIndex"
|
||||||
export { FullProgress } from "./FullProgress"
|
export { FullProgress } from "./FullProgress"
|
||||||
export { GetHostInfoParamsKind } from "./GetHostInfoParamsKind"
|
|
||||||
export { GetHostInfoParams } from "./GetHostInfoParams"
|
export { GetHostInfoParams } from "./GetHostInfoParams"
|
||||||
export { GetOsAssetParams } from "./GetOsAssetParams"
|
export { GetOsAssetParams } from "./GetOsAssetParams"
|
||||||
export { GetPackageParams } from "./GetPackageParams"
|
export { GetPackageParams } from "./GetPackageParams"
|
||||||
@@ -69,14 +65,17 @@ export { HealthCheckId } from "./HealthCheckId"
|
|||||||
export { HealthCheckResult } from "./HealthCheckResult"
|
export { HealthCheckResult } from "./HealthCheckResult"
|
||||||
export { HostAddress } from "./HostAddress"
|
export { HostAddress } from "./HostAddress"
|
||||||
export { HostId } from "./HostId"
|
export { HostId } from "./HostId"
|
||||||
export { HostInfo } from "./HostInfo"
|
|
||||||
export { HostKind } from "./HostKind"
|
export { HostKind } from "./HostKind"
|
||||||
|
export { HostnameInfo } from "./HostnameInfo"
|
||||||
|
export { Hosts } from "./Hosts"
|
||||||
export { Host } from "./Host"
|
export { Host } from "./Host"
|
||||||
export { ImageId } from "./ImageId"
|
export { ImageId } from "./ImageId"
|
||||||
export { InstalledState } from "./InstalledState"
|
export { InstalledState } from "./InstalledState"
|
||||||
export { InstallingInfo } from "./InstallingInfo"
|
export { InstallingInfo } from "./InstallingInfo"
|
||||||
export { InstallingState } from "./InstallingState"
|
export { InstallingState } from "./InstallingState"
|
||||||
|
export { IpHostname } from "./IpHostname"
|
||||||
export { IpInfo } from "./IpInfo"
|
export { IpInfo } from "./IpInfo"
|
||||||
|
export { LanInfo } from "./LanInfo"
|
||||||
export { ListServiceInterfacesParams } from "./ListServiceInterfacesParams"
|
export { ListServiceInterfacesParams } from "./ListServiceInterfacesParams"
|
||||||
export { ListVersionSignersParams } from "./ListVersionSignersParams"
|
export { ListVersionSignersParams } from "./ListVersionSignersParams"
|
||||||
export { MainStatus } from "./MainStatus"
|
export { MainStatus } from "./MainStatus"
|
||||||
@@ -86,6 +85,7 @@ export { MerkleArchiveCommitment } from "./MerkleArchiveCommitment"
|
|||||||
export { MountParams } from "./MountParams"
|
export { MountParams } from "./MountParams"
|
||||||
export { MountTarget } from "./MountTarget"
|
export { MountTarget } from "./MountTarget"
|
||||||
export { NamedProgress } from "./NamedProgress"
|
export { NamedProgress } from "./NamedProgress"
|
||||||
|
export { OnionHostname } from "./OnionHostname"
|
||||||
export { OsIndex } from "./OsIndex"
|
export { OsIndex } from "./OsIndex"
|
||||||
export { OsVersionInfo } from "./OsVersionInfo"
|
export { OsVersionInfo } from "./OsVersionInfo"
|
||||||
export { PackageDataEntry } from "./PackageDataEntry"
|
export { PackageDataEntry } from "./PackageDataEntry"
|
||||||
@@ -106,10 +106,6 @@ export { RemoveActionParams } from "./RemoveActionParams"
|
|||||||
export { RemoveAddressParams } from "./RemoveAddressParams"
|
export { RemoveAddressParams } from "./RemoveAddressParams"
|
||||||
export { RemoveVersionParams } from "./RemoveVersionParams"
|
export { RemoveVersionParams } from "./RemoveVersionParams"
|
||||||
export { RequestCommitment } from "./RequestCommitment"
|
export { RequestCommitment } from "./RequestCommitment"
|
||||||
export { ReverseProxyBind } from "./ReverseProxyBind"
|
|
||||||
export { ReverseProxyDestination } from "./ReverseProxyDestination"
|
|
||||||
export { ReverseProxyHttp } from "./ReverseProxyHttp"
|
|
||||||
export { ReverseProxyParams } from "./ReverseProxyParams"
|
|
||||||
export { Security } from "./Security"
|
export { Security } from "./Security"
|
||||||
export { ServerInfo } from "./ServerInfo"
|
export { ServerInfo } from "./ServerInfo"
|
||||||
export { ServerSpecs } from "./ServerSpecs"
|
export { ServerSpecs } from "./ServerSpecs"
|
||||||
@@ -117,7 +113,6 @@ export { ServerStatus } from "./ServerStatus"
|
|||||||
export { ServiceInterfaceId } from "./ServiceInterfaceId"
|
export { ServiceInterfaceId } from "./ServiceInterfaceId"
|
||||||
export { ServiceInterface } from "./ServiceInterface"
|
export { ServiceInterface } from "./ServiceInterface"
|
||||||
export { ServiceInterfaceType } from "./ServiceInterfaceType"
|
export { ServiceInterfaceType } from "./ServiceInterfaceType"
|
||||||
export { ServiceInterfaceWithHostInfo } from "./ServiceInterfaceWithHostInfo"
|
|
||||||
export { SessionList } from "./SessionList"
|
export { SessionList } from "./SessionList"
|
||||||
export { Sessions } from "./Sessions"
|
export { Sessions } from "./Sessions"
|
||||||
export { Session } from "./Session"
|
export { Session } from "./Session"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ describe("host", () => {
|
|||||||
const foo = sdk.host.multi(effects, "foo")
|
const foo = sdk.host.multi(effects, "foo")
|
||||||
const fooOrigin = await foo.bindPort(80, {
|
const fooOrigin = await foo.bindPort(80, {
|
||||||
protocol: "http" as const,
|
protocol: "http" as const,
|
||||||
|
preferredExternalPort: 80,
|
||||||
})
|
})
|
||||||
const fooInterface = new ServiceInterfaceBuilder({
|
const fooInterface = new ServiceInterfaceBuilder({
|
||||||
effects,
|
effects,
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import { ListServiceInterfacesParams } from ".././osBindings"
|
|||||||
import { RemoveAddressParams } from ".././osBindings"
|
import { RemoveAddressParams } from ".././osBindings"
|
||||||
import { ExportActionParams } from ".././osBindings"
|
import { ExportActionParams } from ".././osBindings"
|
||||||
import { RemoveActionParams } from ".././osBindings"
|
import { RemoveActionParams } from ".././osBindings"
|
||||||
import { ReverseProxyParams } from ".././osBindings"
|
|
||||||
import { MountParams } from ".././osBindings"
|
import { MountParams } from ".././osBindings"
|
||||||
function typeEquality<ExpectedType>(_a: ExpectedType) {}
|
function typeEquality<ExpectedType>(_a: ExpectedType) {}
|
||||||
describe("startosTypeValidation ", () => {
|
describe("startosTypeValidation ", () => {
|
||||||
@@ -66,7 +65,6 @@ describe("startosTypeValidation ", () => {
|
|||||||
removeAddress: {} as RemoveAddressParams,
|
removeAddress: {} as RemoveAddressParams,
|
||||||
exportAction: {} as ExportActionParams,
|
exportAction: {} as ExportActionParams,
|
||||||
removeAction: {} as RemoveActionParams,
|
removeAction: {} as RemoveActionParams,
|
||||||
reverseProxy: {} as ReverseProxyParams,
|
|
||||||
mount: {} as MountParams,
|
mount: {} as MountParams,
|
||||||
checkDependencies: {} as CheckDependenciesParam,
|
checkDependencies: {} as CheckDependenciesParam,
|
||||||
getDependencies: undefined,
|
getDependencies: undefined,
|
||||||
|
|||||||
@@ -5,6 +5,12 @@ import {
|
|||||||
SetHealth,
|
SetHealth,
|
||||||
HealthCheckResult,
|
HealthCheckResult,
|
||||||
SetMainStatus,
|
SetMainStatus,
|
||||||
|
ServiceInterface,
|
||||||
|
Host,
|
||||||
|
ExportServiceInterfaceParams,
|
||||||
|
GetPrimaryUrlParams,
|
||||||
|
LanInfo,
|
||||||
|
BindParams,
|
||||||
} from "./osBindings"
|
} from "./osBindings"
|
||||||
|
|
||||||
import { MainEffects, ServiceInterfaceType, Signals } from "./StartSdk"
|
import { MainEffects, ServiceInterfaceType, Signals } from "./StartSdk"
|
||||||
@@ -12,7 +18,7 @@ import { InputSpec } from "./config/configTypes"
|
|||||||
import { DependenciesReceipt } from "./config/setupConfig"
|
import { DependenciesReceipt } from "./config/setupConfig"
|
||||||
import { BindOptions, Scheme } from "./interfaces/Host"
|
import { BindOptions, Scheme } from "./interfaces/Host"
|
||||||
import { Daemons } from "./mainFn/Daemons"
|
import { Daemons } from "./mainFn/Daemons"
|
||||||
import { PathBuilder, StorePath } from "./store/PathBuilder"
|
import { StorePath } from "./store/PathBuilder"
|
||||||
import { ExposedStorePaths } from "./store/setupExposeStore"
|
import { ExposedStorePaths } from "./store/setupExposeStore"
|
||||||
import { UrlString } from "./util/getServiceInterface"
|
import { UrlString } from "./util/getServiceInterface"
|
||||||
export * from "./osBindings"
|
export * from "./osBindings"
|
||||||
@@ -184,14 +190,6 @@ export declare const hostName: unique symbol
|
|||||||
// asdflkjadsf.onion | 1.2.3.4
|
// asdflkjadsf.onion | 1.2.3.4
|
||||||
export type Hostname = string & { [hostName]: never }
|
export type Hostname = string & { [hostName]: never }
|
||||||
|
|
||||||
/** ${scheme}://${username}@${host}:${externalPort}${suffix} */
|
|
||||||
export type AddressInfo = {
|
|
||||||
username: string | null
|
|
||||||
hostId: string
|
|
||||||
bindOptions: BindOptions
|
|
||||||
suffix: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type HostnameInfoIp = {
|
export type HostnameInfoIp = {
|
||||||
kind: "ip"
|
kind: "ip"
|
||||||
networkInterfaceId: string
|
networkInterfaceId: string
|
||||||
@@ -219,44 +217,9 @@ export type HostnameInfoOnion = {
|
|||||||
|
|
||||||
export type HostnameInfo = HostnameInfoIp | HostnameInfoOnion
|
export type HostnameInfo = HostnameInfoIp | HostnameInfoOnion
|
||||||
|
|
||||||
export type SingleHost = {
|
|
||||||
id: string
|
|
||||||
kind: "single" | "static"
|
|
||||||
hostname: HostnameInfo | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type MultiHost = {
|
|
||||||
id: string
|
|
||||||
kind: "multi"
|
|
||||||
hostnames: HostnameInfo[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export type HostInfo = SingleHost | MultiHost
|
|
||||||
|
|
||||||
export type ServiceInterfaceId = string
|
export type ServiceInterfaceId = string
|
||||||
|
|
||||||
export type ServiceInterface = {
|
export { ServiceInterface }
|
||||||
id: ServiceInterfaceId
|
|
||||||
/** The title of this field to be displayed */
|
|
||||||
name: string
|
|
||||||
/** Human readable description, used as tooltip usually */
|
|
||||||
description: string
|
|
||||||
/** Whether or not one address must be the primary address */
|
|
||||||
hasPrimary: boolean
|
|
||||||
/** Disabled interfaces do not serve, but they retain their metadata and addresses */
|
|
||||||
disabled: boolean
|
|
||||||
/** Whether or not to mask the URIs for this interface. Useful if the URIs contain sensitive information, such as a password, macaroon, or API key */
|
|
||||||
masked: boolean
|
|
||||||
/** URI Information */
|
|
||||||
addressInfo: AddressInfo
|
|
||||||
/** The network interface could be several types, something like ui, p2p, or network */
|
|
||||||
type: ServiceInterfaceType
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ServiceInterfaceWithHostInfo = ServiceInterface & {
|
|
||||||
hostInfo: HostInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ExposeServicePaths<Store = never> = {
|
export type ExposeServicePaths<Store = never> = {
|
||||||
/** The path to the value in the Store. [JsonPath](https://jsonpath.com/) */
|
/** The path to the value in the Store. [JsonPath](https://jsonpath.com/) */
|
||||||
paths: ExposedStorePaths
|
paths: ExposedStorePaths
|
||||||
@@ -326,13 +289,7 @@ export type Effects = {
|
|||||||
/** Removes all network bindings */
|
/** Removes all network bindings */
|
||||||
clearBindings(): Promise<void>
|
clearBindings(): Promise<void>
|
||||||
/** Creates a host connected to the specified port with the provided options */
|
/** Creates a host connected to the specified port with the provided options */
|
||||||
bind(
|
bind(options: BindParams): Promise<void>
|
||||||
options: {
|
|
||||||
kind: "static" | "single" | "multi"
|
|
||||||
id: string
|
|
||||||
internalPort: number
|
|
||||||
} & BindOptions,
|
|
||||||
): Promise<void>
|
|
||||||
/** Retrieves the current hostname(s) associated with a host id */
|
/** Retrieves the current hostname(s) associated with a host id */
|
||||||
// getHostInfo(options: {
|
// getHostInfo(options: {
|
||||||
// kind: "static" | "single"
|
// kind: "static" | "single"
|
||||||
@@ -341,11 +298,10 @@ export type Effects = {
|
|||||||
// callback: () => void
|
// callback: () => void
|
||||||
// }): Promise<SingleHost>
|
// }): Promise<SingleHost>
|
||||||
getHostInfo(options: {
|
getHostInfo(options: {
|
||||||
kind: "multi" | null
|
hostId: string
|
||||||
serviceInterfaceId: string
|
|
||||||
packageId: string | null
|
packageId: string | null
|
||||||
callback: () => void
|
callback: () => void
|
||||||
}): Promise<MultiHost>
|
}): Promise<Host>
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Run rsync between two volumes. This is used to backup data between volumes.
|
// * Run rsync between two volumes. This is used to backup data between volumes.
|
||||||
@@ -395,14 +351,14 @@ export type Effects = {
|
|||||||
getServicePortForward(options: {
|
getServicePortForward(options: {
|
||||||
internalPort: number
|
internalPort: number
|
||||||
packageId: string | null
|
packageId: string | null
|
||||||
}): Promise<number>
|
}): Promise<LanInfo>
|
||||||
|
|
||||||
/** Removes all network interfaces */
|
/** Removes all network interfaces */
|
||||||
clearServiceInterfaces(): Promise<void>
|
clearServiceInterfaces(): Promise<void>
|
||||||
/** When we want to create a link in the front end interfaces, and example is
|
/** When we want to create a link in the front end interfaces, and example is
|
||||||
* exposing a url to view a web service
|
* exposing a url to view a web service
|
||||||
*/
|
*/
|
||||||
exportServiceInterface(options: ServiceInterface): Promise<string>
|
exportServiceInterface(options: ExportServiceInterfaceParams): Promise<string>
|
||||||
|
|
||||||
exposeForDependents(options: { paths: string[] }): Promise<void>
|
exposeForDependents(options: { paths: string[] }): Promise<void>
|
||||||
|
|
||||||
@@ -422,11 +378,7 @@ export type Effects = {
|
|||||||
* The user sets the primary url for a interface
|
* The user sets the primary url for a interface
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
getPrimaryUrl(options: {
|
getPrimaryUrl(options: GetPrimaryUrlParams): Promise<UrlString | null>
|
||||||
packageId: PackageId | null
|
|
||||||
serviceInterfaceId: ServiceInterfaceId
|
|
||||||
callback: () => void
|
|
||||||
}): Promise<UrlString | null>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There are times that we want to see the addresses that where exported
|
* There are times that we want to see the addresses that where exported
|
||||||
@@ -437,7 +389,7 @@ export type Effects = {
|
|||||||
listServiceInterfaces(options: {
|
listServiceInterfaces(options: {
|
||||||
packageId: PackageId | null
|
packageId: PackageId | null
|
||||||
callback: () => void
|
callback: () => void
|
||||||
}): Promise<ServiceInterface[]>
|
}): Promise<Record<ServiceInterfaceId, ServiceInterface>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Remove an address that was exported. Used problably during main or during setConfig.
|
*Remove an address that was exported. Used problably during main or during setConfig.
|
||||||
@@ -501,25 +453,6 @@ export type Effects = {
|
|||||||
/** Exists could be useful during the runtime to know if some service is running, option dep */
|
/** Exists could be useful during the runtime to know if some service is running, option dep */
|
||||||
running(options: { packageId: PackageId }): Promise<boolean>
|
running(options: { packageId: PackageId }): Promise<boolean>
|
||||||
|
|
||||||
/** Instead of creating proxies with nginx, we have a utility to create and maintain a proxy in the lifetime of this running. */
|
|
||||||
reverseProxy(options: {
|
|
||||||
bind: {
|
|
||||||
/** Optional, default is 0.0.0.0 */
|
|
||||||
ip: string | null
|
|
||||||
port: number
|
|
||||||
ssl: boolean
|
|
||||||
}
|
|
||||||
dst: {
|
|
||||||
/** Optional: default is 127.0.0.1 */
|
|
||||||
ip: string | null // optional, default 127.0.0.1
|
|
||||||
port: number
|
|
||||||
ssl: boolean
|
|
||||||
}
|
|
||||||
http: {
|
|
||||||
// optional, will do TCP layer proxy only if not present
|
|
||||||
headers: Record<string, string> | null
|
|
||||||
} | null
|
|
||||||
}): Promise<{ stop(): Promise<void> }>
|
|
||||||
restart(): void
|
restart(): void
|
||||||
shutdown(): void
|
shutdown(): void
|
||||||
|
|
||||||
|
|||||||
25
sdk/lib/util/Hostname.ts
Normal file
25
sdk/lib/util/Hostname.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { HostnameInfo } from "../types"
|
||||||
|
|
||||||
|
export function hostnameInfoToAddress(hostInfo: HostnameInfo): string {
|
||||||
|
if (hostInfo.kind === "onion") {
|
||||||
|
return `${hostInfo.hostname.value}`
|
||||||
|
}
|
||||||
|
if (hostInfo.kind !== "ip") {
|
||||||
|
throw Error("Expecting that the kind is ip.")
|
||||||
|
}
|
||||||
|
const hostname = hostInfo.hostname
|
||||||
|
if (hostname.kind === "domain") {
|
||||||
|
return `${hostname.subdomain ? `${hostname.subdomain}.` : ""}${hostname.domain}`
|
||||||
|
}
|
||||||
|
const port = hostname.sslPort || hostname.port
|
||||||
|
const portString = port ? `:${port}` : ""
|
||||||
|
if ("ipv4" === hostname.kind || "ipv6" === hostname.kind) {
|
||||||
|
return `${hostname.value}${portString}`
|
||||||
|
}
|
||||||
|
if ("local" === hostname.kind) {
|
||||||
|
return `${hostname.value}${portString}`
|
||||||
|
}
|
||||||
|
throw Error(
|
||||||
|
"Expecting to have a valid hostname kind." + JSON.stringify(hostname),
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
import { ServiceInterfaceType } from "../StartSdk"
|
import { ServiceInterfaceType } from "../StartSdk"
|
||||||
|
import { knownProtocols } from "../interfaces/Host"
|
||||||
import {
|
import {
|
||||||
AddressInfo,
|
AddressInfo,
|
||||||
Effects,
|
Effects,
|
||||||
HostInfo,
|
Host,
|
||||||
|
HostAddress,
|
||||||
Hostname,
|
Hostname,
|
||||||
HostnameInfo,
|
HostnameInfo,
|
||||||
|
HostnameInfoIp,
|
||||||
|
HostnameInfoOnion,
|
||||||
|
IpInfo,
|
||||||
} from "../types"
|
} from "../types"
|
||||||
|
|
||||||
export type UrlString = string
|
export type UrlString = string
|
||||||
@@ -20,13 +25,13 @@ export const getHostname = (url: string): Hostname | null => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type Filled = {
|
export type Filled = {
|
||||||
hostnames: Hostname[]
|
hostnames: HostnameInfo[]
|
||||||
onionHostnames: Hostname[]
|
onionHostnames: HostnameInfo[]
|
||||||
localHostnames: Hostname[]
|
localHostnames: HostnameInfo[]
|
||||||
ipHostnames: Hostname[]
|
ipHostnames: HostnameInfo[]
|
||||||
ipv4Hostnames: Hostname[]
|
ipv4Hostnames: HostnameInfo[]
|
||||||
ipv6Hostnames: Hostname[]
|
ipv6Hostnames: HostnameInfo[]
|
||||||
nonIpHostnames: Hostname[]
|
nonIpHostnames: HostnameInfo[]
|
||||||
|
|
||||||
urls: UrlString[]
|
urls: UrlString[]
|
||||||
onionUrls: UrlString[]
|
onionUrls: UrlString[]
|
||||||
@@ -50,7 +55,7 @@ export type ServiceInterfaceFilled = {
|
|||||||
/** Whether or not to mask the URIs for this interface. Useful if the URIs contain sensitive information, such as a password, macaroon, or API key */
|
/** Whether or not to mask the URIs for this interface. Useful if the URIs contain sensitive information, such as a password, macaroon, or API key */
|
||||||
masked: boolean
|
masked: boolean
|
||||||
/** Information about the host for this binding */
|
/** Information about the host for this binding */
|
||||||
hostInfo: HostInfo
|
host: Host
|
||||||
/** URI information */
|
/** URI information */
|
||||||
addressInfo: FilledAddressInfo
|
addressInfo: FilledAddressInfo
|
||||||
/** Indicates if we are a ui/p2p/api for the kind of interface that this is representing */
|
/** Indicates if we are a ui/p2p/api for the kind of interface that this is representing */
|
||||||
@@ -69,110 +74,103 @@ const negate =
|
|||||||
(a: A) =>
|
(a: A) =>
|
||||||
!fn(a)
|
!fn(a)
|
||||||
const unique = <A>(values: A[]) => Array.from(new Set(values))
|
const unique = <A>(values: A[]) => Array.from(new Set(values))
|
||||||
function stringifyHostname(info: HostnameInfo): Hostname {
|
export const addressHostToUrl = (
|
||||||
let base: string
|
{ scheme, sslScheme, username, suffix }: AddressInfo,
|
||||||
if ("kind" in info.hostname && info.hostname.kind === "domain") {
|
host: HostnameInfo,
|
||||||
base = info.hostname.subdomain
|
): UrlString[] => {
|
||||||
? `${info.hostname.subdomain}.${info.hostname.domain}`
|
const res = []
|
||||||
: info.hostname.domain
|
const fmt = (scheme: string | null, host: HostnameInfo, port: number) => {
|
||||||
} else {
|
const includePort =
|
||||||
base = info.hostname.value
|
scheme &&
|
||||||
|
scheme in knownProtocols &&
|
||||||
|
port === knownProtocols[scheme as keyof typeof knownProtocols].defaultPort
|
||||||
|
let hostname
|
||||||
|
if (host.kind === "onion") {
|
||||||
|
hostname = host.hostname.value
|
||||||
|
} else if (host.kind === "ip") {
|
||||||
|
if (host.hostname.kind === "domain") {
|
||||||
|
hostname = `${host.hostname.subdomain ? `${host.hostname.subdomain}.` : ""}${host.hostname.domain}`
|
||||||
|
} else {
|
||||||
|
hostname = host.hostname.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `${scheme ? `${scheme}://` : ""}${
|
||||||
|
username ? `${username}@` : ""
|
||||||
|
}${hostname}${includePort ? `:${port}` : ""}${suffix}`
|
||||||
}
|
}
|
||||||
if (info.hostname.port && info.hostname.sslPort) {
|
if (host.hostname.sslPort !== null) {
|
||||||
return `${base}:${info.hostname.port}` as Hostname
|
res.push(fmt(sslScheme, host, host.hostname.sslPort))
|
||||||
} else if (info.hostname.sslPort) {
|
|
||||||
return `${base}:${info.hostname.sslPort}` as Hostname
|
|
||||||
} else if (info.hostname.port) {
|
|
||||||
return `${base}:${info.hostname.port}` as Hostname
|
|
||||||
}
|
}
|
||||||
return base as Hostname
|
if (host.hostname.port !== null) {
|
||||||
}
|
res.push(fmt(scheme, host, host.hostname.port))
|
||||||
const addressHostToUrl = (
|
}
|
||||||
{ bindOptions, username, suffix }: AddressInfo,
|
|
||||||
host: Hostname,
|
return res
|
||||||
): UrlString => {
|
|
||||||
const scheme = host.endsWith(".onion")
|
|
||||||
? bindOptions.scheme
|
|
||||||
: bindOptions.addSsl
|
|
||||||
? bindOptions.addSsl.scheme
|
|
||||||
: bindOptions.scheme // TODO: encode whether hostname transport is "secure"?
|
|
||||||
return `${scheme ? `${scheme}//` : ""}${
|
|
||||||
username ? `${username}@` : ""
|
|
||||||
}${host}${suffix}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const filledAddress = (
|
export const filledAddress = (
|
||||||
hostInfo: HostInfo,
|
host: Host,
|
||||||
addressInfo: AddressInfo,
|
addressInfo: AddressInfo,
|
||||||
): FilledAddressInfo => {
|
): FilledAddressInfo => {
|
||||||
const toUrl = addressHostToUrl.bind(null, addressInfo)
|
const toUrl = addressHostToUrl.bind(null, addressInfo)
|
||||||
const hostnameInfo =
|
const hostnames = host.hostnameInfo[addressInfo.internalPort]
|
||||||
hostInfo.kind == "multi"
|
|
||||||
? hostInfo.hostnames
|
|
||||||
: hostInfo.hostname
|
|
||||||
? [hostInfo.hostname]
|
|
||||||
: []
|
|
||||||
return {
|
return {
|
||||||
...addressInfo,
|
...addressInfo,
|
||||||
hostnames: hostnameInfo.flatMap((h) => stringifyHostname(h)),
|
hostnames,
|
||||||
get onionHostnames() {
|
get onionHostnames() {
|
||||||
return hostnameInfo
|
return hostnames.filter((h) => h.kind === "onion")
|
||||||
.filter((h) => h.kind === "onion")
|
|
||||||
.map((h) => stringifyHostname(h))
|
|
||||||
},
|
},
|
||||||
get localHostnames() {
|
get localHostnames() {
|
||||||
return hostnameInfo
|
return hostnames.filter(
|
||||||
.filter((h) => h.kind === "ip" && h.hostname.kind === "local")
|
(h) => h.kind === "ip" && h.hostname.kind === "local",
|
||||||
.map((h) => stringifyHostname(h))
|
)
|
||||||
},
|
},
|
||||||
get ipHostnames() {
|
get ipHostnames() {
|
||||||
return hostnameInfo
|
return hostnames.filter(
|
||||||
.filter(
|
(h) =>
|
||||||
(h) =>
|
h.kind === "ip" &&
|
||||||
h.kind === "ip" &&
|
(h.hostname.kind === "ipv4" || h.hostname.kind === "ipv6"),
|
||||||
(h.hostname.kind === "ipv4" || h.hostname.kind === "ipv6"),
|
)
|
||||||
)
|
|
||||||
.map((h) => stringifyHostname(h))
|
|
||||||
},
|
},
|
||||||
get ipv4Hostnames() {
|
get ipv4Hostnames() {
|
||||||
return hostnameInfo
|
return hostnames.filter(
|
||||||
.filter((h) => h.kind === "ip" && h.hostname.kind === "ipv4")
|
(h) => h.kind === "ip" && h.hostname.kind === "ipv4",
|
||||||
.map((h) => stringifyHostname(h))
|
)
|
||||||
},
|
},
|
||||||
get ipv6Hostnames() {
|
get ipv6Hostnames() {
|
||||||
return hostnameInfo
|
return hostnames.filter(
|
||||||
.filter((h) => h.kind === "ip" && h.hostname.kind === "ipv6")
|
(h) => h.kind === "ip" && h.hostname.kind === "ipv6",
|
||||||
.map((h) => stringifyHostname(h))
|
)
|
||||||
},
|
},
|
||||||
get nonIpHostnames() {
|
get nonIpHostnames() {
|
||||||
return hostnameInfo
|
return hostnames.filter(
|
||||||
.filter(
|
(h) =>
|
||||||
(h) =>
|
h.kind === "ip" &&
|
||||||
h.kind === "ip" &&
|
h.hostname.kind !== "ipv4" &&
|
||||||
h.hostname.kind !== "ipv4" &&
|
h.hostname.kind !== "ipv6",
|
||||||
h.hostname.kind !== "ipv6",
|
)
|
||||||
)
|
|
||||||
.map((h) => stringifyHostname(h))
|
|
||||||
},
|
},
|
||||||
get urls() {
|
get urls() {
|
||||||
return this.hostnames.map(toUrl)
|
return this.hostnames.flatMap(toUrl)
|
||||||
},
|
},
|
||||||
get onionUrls() {
|
get onionUrls() {
|
||||||
return this.onionHostnames.map(toUrl)
|
return this.onionHostnames.flatMap(toUrl)
|
||||||
},
|
},
|
||||||
get localUrls() {
|
get localUrls() {
|
||||||
return this.localHostnames.map(toUrl)
|
return this.localHostnames.flatMap(toUrl)
|
||||||
},
|
},
|
||||||
get ipUrls() {
|
get ipUrls() {
|
||||||
return this.ipHostnames.map(toUrl)
|
return this.ipHostnames.flatMap(toUrl)
|
||||||
},
|
},
|
||||||
get ipv4Urls() {
|
get ipv4Urls() {
|
||||||
return this.ipv4Hostnames.map(toUrl)
|
return this.ipv4Hostnames.flatMap(toUrl)
|
||||||
},
|
},
|
||||||
get ipv6Urls() {
|
get ipv6Urls() {
|
||||||
return this.ipv6Hostnames.map(toUrl)
|
return this.ipv6Hostnames.flatMap(toUrl)
|
||||||
},
|
},
|
||||||
get nonIpUrls() {
|
get nonIpUrls() {
|
||||||
return this.nonIpHostnames.map(toUrl)
|
return this.nonIpHostnames.flatMap(toUrl)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,23 +191,25 @@ const makeInterfaceFilled = async ({
|
|||||||
packageId,
|
packageId,
|
||||||
callback,
|
callback,
|
||||||
})
|
})
|
||||||
const hostInfo = await effects.getHostInfo({
|
const hostId = serviceInterfaceValue.addressInfo.hostId
|
||||||
packageId,
|
const host = await effects.getHostInfo({
|
||||||
kind: null,
|
|
||||||
serviceInterfaceId: serviceInterfaceValue.id,
|
|
||||||
callback,
|
|
||||||
})
|
|
||||||
const primaryUrl = await effects.getPrimaryUrl({
|
|
||||||
serviceInterfaceId: id,
|
|
||||||
packageId,
|
packageId,
|
||||||
|
hostId,
|
||||||
callback,
|
callback,
|
||||||
})
|
})
|
||||||
|
const primaryUrl = await effects
|
||||||
|
.getPrimaryUrl({
|
||||||
|
serviceInterfaceId: id,
|
||||||
|
packageId,
|
||||||
|
callback,
|
||||||
|
})
|
||||||
|
.catch((e) => null)
|
||||||
|
|
||||||
const interfaceFilled: ServiceInterfaceFilled = {
|
const interfaceFilled: ServiceInterfaceFilled = {
|
||||||
...serviceInterfaceValue,
|
...serviceInterfaceValue,
|
||||||
primaryUrl: primaryUrl,
|
primaryUrl: primaryUrl,
|
||||||
hostInfo,
|
host,
|
||||||
addressInfo: filledAddress(hostInfo, serviceInterfaceValue.addressInfo),
|
addressInfo: filledAddress(host, serviceInterfaceValue.addressInfo),
|
||||||
get primaryHostname() {
|
get primaryHostname() {
|
||||||
if (primaryUrl == null) return null
|
if (primaryUrl == null) return null
|
||||||
return getHostname(primaryUrl)
|
return getHostname(primaryUrl)
|
||||||
|
|||||||
@@ -18,41 +18,27 @@ const makeManyInterfaceFilled = async ({
|
|||||||
packageId,
|
packageId,
|
||||||
callback,
|
callback,
|
||||||
})
|
})
|
||||||
const hostIdsRecord = Object.fromEntries(
|
|
||||||
await Promise.all(
|
|
||||||
Array.from(new Set(serviceInterfaceValues.map((x) => x.id))).map(
|
|
||||||
async (id) =>
|
|
||||||
[
|
|
||||||
id,
|
|
||||||
await effects.getHostInfo({
|
|
||||||
kind: null,
|
|
||||||
packageId,
|
|
||||||
serviceInterfaceId: id,
|
|
||||||
callback,
|
|
||||||
}),
|
|
||||||
] as const,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
const serviceInterfacesFilled: ServiceInterfaceFilled[] = await Promise.all(
|
const serviceInterfacesFilled: ServiceInterfaceFilled[] = await Promise.all(
|
||||||
serviceInterfaceValues.map(async (serviceInterfaceValue) => {
|
Object.values(serviceInterfaceValues).map(async (serviceInterfaceValue) => {
|
||||||
const hostInfo = await effects.getHostInfo({
|
const hostId = serviceInterfaceValue.addressInfo.hostId
|
||||||
kind: null,
|
const host = await effects.getHostInfo({
|
||||||
packageId,
|
|
||||||
serviceInterfaceId: serviceInterfaceValue.id,
|
|
||||||
callback,
|
|
||||||
})
|
|
||||||
const primaryUrl = await effects.getPrimaryUrl({
|
|
||||||
serviceInterfaceId: serviceInterfaceValue.id,
|
|
||||||
packageId,
|
packageId,
|
||||||
|
hostId,
|
||||||
callback,
|
callback,
|
||||||
})
|
})
|
||||||
|
const primaryUrl = await effects
|
||||||
|
.getPrimaryUrl({
|
||||||
|
serviceInterfaceId: serviceInterfaceValue.id,
|
||||||
|
packageId,
|
||||||
|
callback,
|
||||||
|
})
|
||||||
|
.catch(() => null)
|
||||||
return {
|
return {
|
||||||
...serviceInterfaceValue,
|
...serviceInterfaceValue,
|
||||||
primaryUrl: primaryUrl,
|
primaryUrl: primaryUrl,
|
||||||
hostInfo,
|
host,
|
||||||
addressInfo: filledAddress(hostInfo, serviceInterfaceValue.addressInfo),
|
addressInfo: filledAddress(host, serviceInterfaceValue.addressInfo),
|
||||||
get primaryHostname() {
|
get primaryHostname() {
|
||||||
if (primaryUrl == null) return null
|
if (primaryUrl == null) return null
|
||||||
return getHostname(primaryUrl)
|
return getHostname(primaryUrl)
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import "./once"
|
|||||||
|
|
||||||
export { GetServiceInterface, getServiceInterface } from "./getServiceInterface"
|
export { GetServiceInterface, getServiceInterface } from "./getServiceInterface"
|
||||||
export { getServiceInterfaces } from "./getServiceInterfaces"
|
export { getServiceInterfaces } from "./getServiceInterfaces"
|
||||||
|
export { addressHostToUrl } from "./getServiceInterface"
|
||||||
|
export { hostnameInfoToAddress } from "./Hostname"
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
export type FlattenIntersection<T> =
|
export type FlattenIntersection<T> =
|
||||||
T extends ArrayLike<any> ? T :
|
T extends ArrayLike<any> ? T :
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { PatchDB } from 'patch-db-client'
|
|||||||
import { QRComponent } from 'src/app/components/qr/qr.component'
|
import { QRComponent } from 'src/app/components/qr/qr.component'
|
||||||
import { map } from 'rxjs'
|
import { map } from 'rxjs'
|
||||||
import { T } from '@start9labs/start-sdk'
|
import { T } from '@start9labs/start-sdk'
|
||||||
|
import { addressHostToUrl } from '@start9labs/start-sdk/cjs/lib/util/getServiceInterface'
|
||||||
|
|
||||||
type MappedInterface = T.ServiceInterface & {
|
type MappedInterface = T.ServiceInterface & {
|
||||||
addresses: MappedAddress[]
|
addresses: MappedAddress[]
|
||||||
@@ -33,10 +34,14 @@ export class AppInterfacesPage {
|
|||||||
.sort(iface =>
|
.sort(iface =>
|
||||||
iface.name.toLowerCase() > iface.name.toLowerCase() ? -1 : 1,
|
iface.name.toLowerCase() > iface.name.toLowerCase() ? -1 : 1,
|
||||||
)
|
)
|
||||||
.map(iface => ({
|
.map(iface => {
|
||||||
...iface,
|
// TODO @Matt
|
||||||
addresses: getAddresses(iface),
|
const host = {} as any
|
||||||
}))
|
return {
|
||||||
|
...iface,
|
||||||
|
addresses: getAddresses(iface, host),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ui: sorted.filter(val => val.type === 'ui'),
|
ui: sorted.filter(val => val.type === 'ui'),
|
||||||
@@ -99,66 +104,40 @@ export class AppInterfacesItemComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getAddresses(
|
function getAddresses(
|
||||||
serviceInterface: T.ServiceInterfaceWithHostInfo,
|
serviceInterface: T.ServiceInterface,
|
||||||
|
host: T.Host,
|
||||||
): MappedAddress[] {
|
): MappedAddress[] {
|
||||||
const host = serviceInterface.hostInfo
|
|
||||||
const addressInfo = serviceInterface.addressInfo
|
const addressInfo = serviceInterface.addressInfo
|
||||||
const username = addressInfo.username ? addressInfo.username + '@' : ''
|
const username = addressInfo.username ? addressInfo.username + '@' : ''
|
||||||
const suffix = addressInfo.suffix || ''
|
const suffix = addressInfo.suffix || ''
|
||||||
|
|
||||||
const hostnames = host.kind === 'multi' ? host.hostnames : [] // TODO: non-multi
|
const hostnames =
|
||||||
|
host.kind === 'multi' ? host.hostnameInfo[addressInfo.internalPort] : [] // TODO: non-multi
|
||||||
/* host.hostname
|
/* host.hostname
|
||||||
? [host.hostname]
|
? [host.hostname]
|
||||||
: [] */
|
: [] */
|
||||||
|
|
||||||
const addresses: MappedAddress[] = []
|
return hostnames.flatMap(h => {
|
||||||
|
|
||||||
hostnames.forEach(h => {
|
|
||||||
let name = ''
|
let name = ''
|
||||||
let hostname = ''
|
|
||||||
|
|
||||||
if (h.kind === 'onion') {
|
if (h.kind === 'onion') {
|
||||||
name = 'Tor'
|
name = 'Tor'
|
||||||
hostname = h.hostname.value
|
|
||||||
} else {
|
} else {
|
||||||
const hostnameKind = h.hostname.kind
|
const hostnameKind = h.hostname.kind
|
||||||
|
|
||||||
if (hostnameKind === 'domain') {
|
if (hostnameKind === 'domain') {
|
||||||
name = 'Domain'
|
name = 'Domain'
|
||||||
hostname = `${h.hostname.subdomain}.${h.hostname.domain}`
|
|
||||||
} else {
|
} else {
|
||||||
name =
|
name =
|
||||||
hostnameKind === 'local'
|
hostnameKind === 'local'
|
||||||
? 'Local'
|
? 'Local'
|
||||||
: `${h.networkInterfaceId} (${hostnameKind})`
|
: `${h.networkInterfaceId} (${hostnameKind})`
|
||||||
hostname = h.hostname.value
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h.hostname.sslPort) {
|
return addressHostToUrl(addressInfo, h).map(url => ({
|
||||||
const port = h.hostname.sslPort === 443 ? '' : `:${h.hostname.sslPort}`
|
name,
|
||||||
const scheme = addressInfo.bindOptions.addSsl?.scheme
|
url,
|
||||||
? `${addressInfo.bindOptions.addSsl.scheme}://`
|
}))
|
||||||
: ''
|
|
||||||
|
|
||||||
addresses.push({
|
|
||||||
name: name === 'Tor' ? 'Tor (HTTPS)' : name,
|
|
||||||
url: `${scheme}${username}${hostname}${port}${suffix}`,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h.hostname.port) {
|
|
||||||
const port = h.hostname.port === 80 ? '' : `:${h.hostname.port}`
|
|
||||||
const scheme = addressInfo.bindOptions.scheme
|
|
||||||
? `${addressInfo.bindOptions.scheme}://`
|
|
||||||
: ''
|
|
||||||
|
|
||||||
addresses.push({
|
|
||||||
name: name === 'Tor' ? 'Tor (HTTP)' : name,
|
|
||||||
url: `${scheme}${username}${hostname}${port}${suffix}`,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return addresses
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1422,66 +1422,11 @@ export module Mock {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'abcdefg',
|
hostId: 'abcdefg',
|
||||||
bindOptions: {
|
internalPort: 80,
|
||||||
scheme: 'http',
|
scheme: 'http',
|
||||||
preferredExternalPort: 80,
|
sslScheme: 'https',
|
||||||
addSsl: {
|
|
||||||
// addXForwardedHeaders: false,
|
|
||||||
preferredExternalPort: 443,
|
|
||||||
scheme: 'https',
|
|
||||||
alpn: { specified: ['http/1.1', 'h2'] },
|
|
||||||
},
|
|
||||||
secure: null,
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'abcdefg',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: null,
|
|
||||||
sslPort: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'bitcoin-ui-address.onion',
|
|
||||||
port: 80,
|
|
||||||
sslPort: 443,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: null,
|
|
||||||
sslPort: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: null,
|
|
||||||
sslPort: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
rpc: {
|
rpc: {
|
||||||
id: 'rpc',
|
id: 'rpc',
|
||||||
@@ -1495,66 +1440,11 @@ export module Mock {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'bcdefgh',
|
hostId: 'bcdefgh',
|
||||||
bindOptions: {
|
internalPort: 8332,
|
||||||
scheme: 'http',
|
scheme: 'http',
|
||||||
preferredExternalPort: 80,
|
sslScheme: 'https',
|
||||||
addSsl: {
|
|
||||||
// addXForwardedHeaders: false,
|
|
||||||
preferredExternalPort: 443,
|
|
||||||
scheme: 'https',
|
|
||||||
alpn: { specified: ['http/1.1'] },
|
|
||||||
},
|
|
||||||
secure: null,
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'bcdefgh',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: null,
|
|
||||||
sslPort: 2345,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'bitcoin-rpc-address.onion',
|
|
||||||
port: 80,
|
|
||||||
sslPort: 443,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: null,
|
|
||||||
sslPort: 2345,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: null,
|
|
||||||
sslPort: 2345,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
p2p: {
|
p2p: {
|
||||||
id: 'p2p',
|
id: 'p2p',
|
||||||
@@ -1568,63 +1458,11 @@ export module Mock {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'cdefghi',
|
hostId: 'cdefghi',
|
||||||
bindOptions: {
|
internalPort: 8333,
|
||||||
scheme: 'bitcoin',
|
scheme: 'bitcoin',
|
||||||
preferredExternalPort: 8333,
|
sslScheme: null,
|
||||||
addSsl: null,
|
|
||||||
secure: {
|
|
||||||
ssl: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'cdefghi',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: 3456,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'bitcoin-p2p-address.onion',
|
|
||||||
port: 8333,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: 3456,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: 3456,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
currentDependencies: {},
|
currentDependencies: {},
|
||||||
@@ -1660,101 +1498,11 @@ export module Mock {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'hijklmnop',
|
hostId: 'hijklmnop',
|
||||||
bindOptions: {
|
internalPort: 80,
|
||||||
scheme: 'http',
|
scheme: 'http',
|
||||||
preferredExternalPort: 80,
|
sslScheme: 'https',
|
||||||
addSsl: {
|
|
||||||
// addXForwardedHeaders: false,
|
|
||||||
preferredExternalPort: 443,
|
|
||||||
scheme: 'https',
|
|
||||||
alpn: { specified: ['http/1.1', 'h2'] },
|
|
||||||
},
|
|
||||||
secure: {
|
|
||||||
ssl: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'hijklmnop',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: null,
|
|
||||||
sslPort: 4567,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'proxy-ui-address.onion',
|
|
||||||
port: 80,
|
|
||||||
sslPort: 443,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: null,
|
|
||||||
sslPort: 4567,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: null,
|
|
||||||
sslPort: 4567,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'wlan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: null,
|
|
||||||
sslPort: 4567,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'wlan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.7',
|
|
||||||
port: null,
|
|
||||||
sslPort: 4567,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'wlan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: null,
|
|
||||||
sslPort: 4567,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
currentDependencies: {
|
currentDependencies: {
|
||||||
@@ -1801,63 +1549,11 @@ export module Mock {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'qrstuv',
|
hostId: 'qrstuv',
|
||||||
bindOptions: {
|
internalPort: 10009,
|
||||||
scheme: 'grpc',
|
scheme: null,
|
||||||
preferredExternalPort: 10009,
|
sslScheme: 'grpc',
|
||||||
addSsl: null,
|
|
||||||
secure: {
|
|
||||||
ssl: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'qrstuv',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'lnd-grpc-address.onion',
|
|
||||||
port: 10009,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
lndconnect: {
|
lndconnect: {
|
||||||
id: 'lndconnect',
|
id: 'lndconnect',
|
||||||
@@ -1871,63 +1567,11 @@ export module Mock {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'qrstuv',
|
hostId: 'qrstuv',
|
||||||
bindOptions: {
|
internalPort: 10009,
|
||||||
scheme: 'lndconnect',
|
scheme: null,
|
||||||
preferredExternalPort: 10009,
|
sslScheme: 'lndconnect',
|
||||||
addSsl: null,
|
|
||||||
secure: {
|
|
||||||
ssl: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
suffix: 'cert=askjdfbjadnaskjnd&macaroon=ksjbdfnhjasbndjksand',
|
suffix: 'cert=askjdfbjadnaskjnd&macaroon=ksjbdfnhjasbndjksand',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'qrstuv',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'lnd-grpc-address.onion',
|
|
||||||
port: 10009,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
p2p: {
|
p2p: {
|
||||||
id: 'p2p',
|
id: 'p2p',
|
||||||
@@ -1941,63 +1585,11 @@ export module Mock {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'rstuvw',
|
hostId: 'rstuvw',
|
||||||
bindOptions: {
|
internalPort: 9735,
|
||||||
scheme: null,
|
scheme: 'lightning',
|
||||||
preferredExternalPort: 9735,
|
sslScheme: null,
|
||||||
addSsl: null,
|
|
||||||
secure: {
|
|
||||||
ssl: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'rstuvw',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: 6789,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'lnd-p2p-address.onion',
|
|
||||||
port: 9735,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: 6789,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: 6789,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
currentDependencies: {
|
currentDependencies: {
|
||||||
|
|||||||
@@ -141,66 +141,11 @@ export const mockPatchData: DataModel = {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'abcdefg',
|
hostId: 'abcdefg',
|
||||||
bindOptions: {
|
internalPort: 80,
|
||||||
scheme: 'http',
|
scheme: 'http',
|
||||||
preferredExternalPort: 80,
|
sslScheme: 'https',
|
||||||
addSsl: {
|
|
||||||
// addXForwardedHeaders: false,
|
|
||||||
preferredExternalPort: 443,
|
|
||||||
scheme: 'https',
|
|
||||||
alpn: { specified: ['http/1.1', 'h2'] },
|
|
||||||
},
|
|
||||||
secure: null,
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'abcdefg',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: null,
|
|
||||||
sslPort: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'bitcoin-ui-address.onion',
|
|
||||||
port: 80,
|
|
||||||
sslPort: 443,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: null,
|
|
||||||
sslPort: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: null,
|
|
||||||
sslPort: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
rpc: {
|
rpc: {
|
||||||
id: 'rpc',
|
id: 'rpc',
|
||||||
@@ -214,66 +159,11 @@ export const mockPatchData: DataModel = {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'bcdefgh',
|
hostId: 'bcdefgh',
|
||||||
bindOptions: {
|
internalPort: 8332,
|
||||||
scheme: 'http',
|
scheme: 'http',
|
||||||
preferredExternalPort: 80,
|
sslScheme: 'https',
|
||||||
addSsl: {
|
|
||||||
// addXForwardedHeaders: false,
|
|
||||||
preferredExternalPort: 443,
|
|
||||||
scheme: 'https',
|
|
||||||
alpn: { specified: ['http/1.1'] },
|
|
||||||
},
|
|
||||||
secure: null,
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'bcdefgh',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: null,
|
|
||||||
sslPort: 2345,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'bitcoin-rpc-address.onion',
|
|
||||||
port: 80,
|
|
||||||
sslPort: 443,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: null,
|
|
||||||
sslPort: 2345,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: null,
|
|
||||||
sslPort: 2345,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
p2p: {
|
p2p: {
|
||||||
id: 'p2p',
|
id: 'p2p',
|
||||||
@@ -287,63 +177,11 @@ export const mockPatchData: DataModel = {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'cdefghi',
|
hostId: 'cdefghi',
|
||||||
bindOptions: {
|
internalPort: 8333,
|
||||||
scheme: 'bitcoin',
|
scheme: 'bitcoin',
|
||||||
preferredExternalPort: 8333,
|
sslScheme: null,
|
||||||
addSsl: null,
|
|
||||||
secure: {
|
|
||||||
ssl: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'cdefghi',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: 3456,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'bitcoin-p2p-address.onion',
|
|
||||||
port: 8333,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: 3456,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: 3456,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
currentDependencies: {},
|
currentDependencies: {},
|
||||||
@@ -382,63 +220,11 @@ export const mockPatchData: DataModel = {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'qrstuv',
|
hostId: 'qrstuv',
|
||||||
bindOptions: {
|
internalPort: 10009,
|
||||||
scheme: 'grpc',
|
scheme: null,
|
||||||
preferredExternalPort: 10009,
|
sslScheme: 'grpc',
|
||||||
addSsl: null,
|
|
||||||
secure: {
|
|
||||||
ssl: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'qrstuv',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'lnd-grpc-address.onion',
|
|
||||||
port: 10009,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
lndconnect: {
|
lndconnect: {
|
||||||
id: 'lndconnect',
|
id: 'lndconnect',
|
||||||
@@ -452,63 +238,11 @@ export const mockPatchData: DataModel = {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'qrstuv',
|
hostId: 'qrstuv',
|
||||||
bindOptions: {
|
internalPort: 10009,
|
||||||
scheme: 'lndconnect',
|
scheme: null,
|
||||||
preferredExternalPort: 10009,
|
sslScheme: 'lndconnect',
|
||||||
addSsl: null,
|
|
||||||
secure: {
|
|
||||||
ssl: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
suffix: 'cert=askjdfbjadnaskjnd&macaroon=ksjbdfnhjasbndjksand',
|
suffix: 'cert=askjdfbjadnaskjnd&macaroon=ksjbdfnhjasbndjksand',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'qrstuv',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'lnd-grpc-address.onion',
|
|
||||||
port: 10009,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: 5678,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
p2p: {
|
p2p: {
|
||||||
id: 'p2p',
|
id: 'p2p',
|
||||||
@@ -522,61 +256,11 @@ export const mockPatchData: DataModel = {
|
|||||||
addressInfo: {
|
addressInfo: {
|
||||||
username: null,
|
username: null,
|
||||||
hostId: 'rstuvw',
|
hostId: 'rstuvw',
|
||||||
bindOptions: {
|
internalPort: 8333,
|
||||||
scheme: null,
|
scheme: 'bitcoin',
|
||||||
preferredExternalPort: 9735,
|
sslScheme: null,
|
||||||
addSsl: null,
|
|
||||||
secure: { ssl: true },
|
|
||||||
},
|
|
||||||
suffix: '',
|
suffix: '',
|
||||||
},
|
},
|
||||||
hostInfo: {
|
|
||||||
id: 'rstuvw',
|
|
||||||
kind: 'multi',
|
|
||||||
hostnames: [
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'local',
|
|
||||||
value: 'adjective-noun.local',
|
|
||||||
port: 6789,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'onion',
|
|
||||||
hostname: {
|
|
||||||
value: 'lnd-p2p-address.onion',
|
|
||||||
port: 9735,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv4',
|
|
||||||
value: '192.168.1.5',
|
|
||||||
port: 6789,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'ip',
|
|
||||||
networkInterfaceId: 'elan0',
|
|
||||||
public: false,
|
|
||||||
hostname: {
|
|
||||||
kind: 'ipv6',
|
|
||||||
value: '[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
|
||||||
port: 6789,
|
|
||||||
sslPort: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
currentDependencies: {
|
currentDependencies: {
|
||||||
|
|||||||
@@ -57,12 +57,14 @@ export class ConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** ${scheme}://${username}@${host}:${externalPort}${suffix} */
|
/** ${scheme}://${username}@${host}:${externalPort}${suffix} */
|
||||||
launchableAddress(interfaces: PackageDataEntry['serviceInterfaces']): string {
|
launchableAddress(
|
||||||
|
interfaces: PackageDataEntry['serviceInterfaces'],
|
||||||
|
host: T.Host,
|
||||||
|
): string {
|
||||||
const ui = Object.values(interfaces).find(i => i.type === 'ui')
|
const ui = Object.values(interfaces).find(i => i.type === 'ui')
|
||||||
|
|
||||||
if (!ui) return ''
|
if (!ui) return ''
|
||||||
|
|
||||||
const host = ui.hostInfo
|
|
||||||
const addressInfo = ui.addressInfo
|
const addressInfo = ui.addressInfo
|
||||||
const scheme = this.isHttps() ? 'https' : 'http'
|
const scheme = this.isHttps() ? 'https' : 'http'
|
||||||
const username = addressInfo.username ? addressInfo.username + '@' : ''
|
const username = addressInfo.username ? addressInfo.username + '@' : ''
|
||||||
@@ -70,20 +72,25 @@ export class ConfigService {
|
|||||||
const url = new URL(`${scheme}://${username}placeholder${suffix}`)
|
const url = new URL(`${scheme}://${username}placeholder${suffix}`)
|
||||||
|
|
||||||
if (host.kind === 'multi') {
|
if (host.kind === 'multi') {
|
||||||
const onionHostname = host.hostnames.find(h => h.kind === 'onion')
|
const onionHostname = host.addresses.find(h => h.kind === 'onion')
|
||||||
?.hostname as T.ExportedOnionHostname
|
?.address as T.OnionHostname | undefined
|
||||||
|
|
||||||
|
if (!onionHostname)
|
||||||
|
throw new Error('Expecting that there is an onion hostname')
|
||||||
|
|
||||||
if (this.isTor() && onionHostname) {
|
if (this.isTor() && onionHostname) {
|
||||||
url.hostname = onionHostname.value
|
url.hostname = onionHostname.value
|
||||||
} else {
|
|
||||||
const ipHostname = host.hostnames.find(h => h.kind === 'ip')
|
|
||||||
?.hostname as T.ExportedIpHostname
|
|
||||||
|
|
||||||
if (!ipHostname) return ''
|
|
||||||
|
|
||||||
url.hostname = this.hostname
|
|
||||||
url.port = String(ipHostname.sslPort || ipHostname.port)
|
|
||||||
}
|
}
|
||||||
|
// TODO Handle single
|
||||||
|
// else {
|
||||||
|
// const ipHostname = host.addresses.find(h => h.kind === 'ip')
|
||||||
|
// ?.hostname as T.ExportedIpHostname
|
||||||
|
|
||||||
|
// if (!ipHostname) return ''
|
||||||
|
|
||||||
|
// url.hostname = this.hostname
|
||||||
|
// url.port = String(ipHostname.sslPort || ipHostname.port)
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
throw new Error('unimplemented')
|
throw new Error('unimplemented')
|
||||||
// const hostname = {} as T.ExportedHostnameInfo // host.hostname
|
// const hostname = {} as T.ExportedHostnameInfo // host.hostname
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Inject, Injectable } from '@angular/core'
|
|||||||
import { WINDOW } from '@ng-web-apis/common'
|
import { WINDOW } from '@ng-web-apis/common'
|
||||||
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
import { PackageDataEntry } from 'src/app/services/patch-db/data-model'
|
||||||
import { ConfigService } from './config.service'
|
import { ConfigService } from './config.service'
|
||||||
|
import { T } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@@ -13,8 +14,10 @@ export class UiLauncherService {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
launch(interfaces: PackageDataEntry['serviceInterfaces']): void {
|
launch(interfaces: PackageDataEntry['serviceInterfaces']): void {
|
||||||
|
// TODO @Matt
|
||||||
|
const host = {} as any
|
||||||
this.windowRef.open(
|
this.windowRef.open(
|
||||||
this.config.launchableAddress(interfaces),
|
this.config.launchableAddress(interfaces, host),
|
||||||
'_blank',
|
'_blank',
|
||||||
'noreferrer',
|
'noreferrer',
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user