chore(deps): modernize coreflow tooling

This commit is contained in:
2026-04-28 12:02:22 +00:00
parent 9cce79f040
commit 6ba5e36f4f
20 changed files with 6311 additions and 6166 deletions
+84 -123
View File
@@ -4,9 +4,7 @@ import { Coreflow } from './coreflow.classes.coreflow.js';
export class ClusterManager {
public coreflowRef: Coreflow;
public configSubscription: plugins.smartrx.rxjs.Subscription;
public containerSubscription: plugins.smartrx.rxjs.Subscription;
public containerVersionSubscription: plugins.smartrx.rxjs.Subscription;
public configSubscription?: plugins.smartrx.rxjs.Subscription;
public readyDeferred = plugins.smartpromise.defer();
@@ -51,42 +49,34 @@ export class ClusterManager {
public async provisionBaseServices() {
// swarm should be enabled by lower level serverconfig package
// get current situation
const networks = await this.coreflowRef.dockerHost.getNetworks();
const networks = await this.coreflowRef.dockerHost.listNetworks();
logger.log('info', 'There are currently ' + networks.length + ' networks');
for (const network of networks) {
logger.log('info', 'Network: ' + network.Name);
}
// make sure there is a network for the webgateway
let sznWebgatewayNetwork = await plugins.docker.DockerNetwork.getNetworkByName(
this.coreflowRef.dockerHost,
let sznWebgatewayNetwork = await this.coreflowRef.dockerHost.getNetworkByName(
this.commonDockerData.networkNames.sznWebgateway,
);
if (!sznWebgatewayNetwork) {
logger.log('info', 'Creating network: ' + this.commonDockerData.networkNames.sznWebgateway);
sznWebgatewayNetwork = await plugins.docker.DockerNetwork.createNetwork(
this.coreflowRef.dockerHost,
{
Name: this.commonDockerData.networkNames.sznWebgateway,
},
);
sznWebgatewayNetwork = await this.coreflowRef.dockerHost.createNetwork({
Name: this.commonDockerData.networkNames.sznWebgateway,
});
} else {
logger.log('ok', 'sznWebgateway is already present');
}
// corechat network so base services can talk to each other
let sznCorechatNetwork = await plugins.docker.DockerNetwork.getNetworkByName(
this.coreflowRef.dockerHost,
let sznCorechatNetwork = await this.coreflowRef.dockerHost.getNetworkByName(
this.commonDockerData.networkNames.sznCorechat,
);
if (!sznCorechatNetwork) {
sznCorechatNetwork = await plugins.docker.DockerNetwork.createNetwork(
this.coreflowRef.dockerHost,
{
Name: this.commonDockerData.networkNames.sznCorechat,
},
);
sznCorechatNetwork = await this.coreflowRef.dockerHost.createNetwork({
Name: this.commonDockerData.networkNames.sznCorechat,
});
} else {
logger.log('ok', 'sznCorechat is already present');
}
@@ -99,30 +89,19 @@ export class ClusterManager {
// Images
logger.log('info', `now updating docker images of base services...`);
const coretrafficImage = await plugins.docker.DockerImage.createFromRegistry(
this.coreflowRef.dockerHost,
{
creationObject: {
imageUrl: 'code.foss.global/serve.zone/coretraffic',
},
},
);
const coretrafficImage = await this.coreflowRef.dockerHost.createImageFromRegistry({
imageUrl: 'code.foss.global/serve.zone/coretraffic',
});
const corelogImage = await plugins.docker.DockerImage.createFromRegistry(
this.coreflowRef.dockerHost,
{
creationObject: {
imageUrl: 'code.foss.global/serve.zone/corelog',
},
},
);
const corelogImage = await this.coreflowRef.dockerHost.createImageFromRegistry({
imageUrl: 'code.foss.global/serve.zone/corelog',
});
// SERVICES
// lets deploy the base services
// coretraffic
let coretrafficService: plugins.docker.DockerService;
coretrafficService = await plugins.docker.DockerService.getServiceByName(
this.coreflowRef.dockerHost,
let coretrafficService: plugins.docker.DockerService | null;
coretrafficService = await this.coreflowRef.dockerHost.getServiceByName(
'coretraffic',
);
@@ -135,22 +114,19 @@ export class ClusterManager {
}
if (!coretrafficService) {
coretrafficService = await plugins.docker.DockerService.createService(
this.coreflowRef.dockerHost,
{
image: coretrafficImage,
labels: {},
name: 'coretraffic',
networks: [sznCorechatNetwork, sznWebgatewayNetwork],
networkAlias: 'coretraffic',
ports: ['80:7999', '443:8000'],
secrets: [],
resources: {
memorySizeMB: 1100,
volumeMounts: [],
},
coretrafficService = await this.coreflowRef.dockerHost.createService({
image: coretrafficImage,
labels: {},
name: 'coretraffic',
networks: [sznCorechatNetwork, sznWebgatewayNetwork],
networkAlias: 'coretraffic',
ports: ['80:7999', '443:8000'],
secrets: [],
resources: {
memorySizeMB: 1100,
volumeMounts: [],
},
);
});
} else {
logger.log('ok', 'coretraffic service is already present');
}
@@ -158,9 +134,8 @@ export class ClusterManager {
await plugins.smartdelay.delayFor(10000);
// corelog
let corelogService: plugins.docker.DockerService;
corelogService = await plugins.docker.DockerService.getServiceByName(
this.coreflowRef.dockerHost,
let corelogService: plugins.docker.DockerService | null;
corelogService = await this.coreflowRef.dockerHost.getServiceByName(
'corelog',
);
@@ -172,22 +147,19 @@ export class ClusterManager {
}
if (!corelogService) {
corelogService = await plugins.docker.DockerService.createService(
this.coreflowRef.dockerHost,
{
image: corelogImage,
labels: {},
name: 'corelog',
networks: [sznCorechatNetwork],
networkAlias: 'corelog',
ports: [],
secrets: [],
resources: {
memorySizeMB: 120,
volumeMounts: [],
},
corelogService = await this.coreflowRef.dockerHost.createService({
image: corelogImage,
labels: {},
name: 'corelog',
networks: [sznCorechatNetwork],
networkAlias: 'corelog',
ports: [],
secrets: [],
resources: {
memorySizeMB: 120,
volumeMounts: [],
},
);
});
} else {
logger.log('ok', 'corelog service is already present');
}
@@ -219,15 +191,11 @@ export class ClusterManager {
const imageStream = await containerImageFromCloudly.pullImageVersion(
serviceArgFromCloudly.data.imageVersion,
);
localDockerImage = await plugins.docker.DockerImage.createFromTarStream(
this.coreflowRef.dockerHost,
localDockerImage = await this.coreflowRef.dockerHost.createImageFromTarStream(
plugins.smartstream.nodewebhelpers.convertWebReadableToNodeReadable(imageStream),
{
creationObject: {
imageUrl: containerImageFromCloudly.id,
imageTag: serviceArgFromCloudly.data.imageVersion,
},
tarStream:
plugins.smartstream.nodewebhelpers.convertWebReadableToNodeReadable(imageStream),
imageUrl: containerImageFromCloudly.id,
imageTag: serviceArgFromCloudly.data.imageVersion,
},
);
} else if (
@@ -240,42 +208,40 @@ export class ClusterManager {
);
// Lets authenticate against the external registry
// TODO: deduplicate this, check wether we are already authenticated
if (!externalRegistry.data.username || !externalRegistry.data.password) {
throw new Error(`External registry ${externalRegistry.id} is missing credentials`);
}
await this.coreflowRef.dockerHost.auth({
username: externalRegistry.data.username,
password: externalRegistry.data.password,
serveraddress: externalRegistry.data.url,
});
localDockerImage = await plugins.docker.DockerImage.createFromRegistry(
this.coreflowRef.dockerHost,
{
creationObject: {
imageUrl: containerImageFromCloudly.id,
imageTag: serviceArgFromCloudly.data.imageVersion,
},
},
);
localDockerImage = await this.coreflowRef.dockerHost.createImageFromRegistry({
imageUrl: containerImageFromCloudly.id,
imageTag: serviceArgFromCloudly.data.imageVersion,
});
await localDockerImage.pullLatestImageFromRegistry();
} else {
throw new Error('Invalid image location');
}
let containerService = await plugins.docker.DockerService.getServiceByName(
this.coreflowRef.dockerHost,
let containerService: plugins.docker.DockerService | null = await this.coreflowRef.dockerHost.getServiceByName(
serviceArgFromCloudly.data.name,
);
this.coreflowRef.cloudlyConnector.cloudlyApiClient;
const dockerSecretName = `${serviceArgFromCloudly.id}_${serviceArgFromCloudly.data.name}_Secret`;
let containerSecret = await plugins.docker.DockerSecret.getSecretByName(
this.coreflowRef.dockerHost,
let containerSecret: plugins.docker.DockerSecret | undefined | null = await this.coreflowRef.dockerHost.getSecretByName(
dockerSecretName,
);
// existing network to connect to
const webGatewayNetwork = await plugins.docker.DockerNetwork.getNetworkByName(
this.coreflowRef.dockerHost,
const webGatewayNetwork = await this.coreflowRef.dockerHost.getNetworkByName(
this.commonDockerData.networkNames.sznWebgateway,
);
if (!webGatewayNetwork) {
throw new Error(`Missing required Docker network ${this.commonDockerData.networkNames.sznWebgateway}`);
}
if (containerService && (await containerService.needsUpdate())) {
await containerService.remove();
@@ -287,8 +253,7 @@ export class ClusterManager {
}
if (!containerService) {
containerSecret = await plugins.docker.DockerSecret.getSecretByName(
this.coreflowRef.dockerHost,
containerSecret = await this.coreflowRef.dockerHost.getSecretByName(
dockerSecretName,
);
if (containerSecret) {
@@ -301,29 +266,23 @@ export class ClusterManager {
);
// lets create the relevant stuff on the docker side
containerSecret = await plugins.docker.DockerSecret.createSecret(
this.coreflowRef.dockerHost,
{
name: dockerSecretName,
contentArg: JSON.stringify(await secretBundle.getFlatKeyValueObjectForEnvironment()),
labels: {},
version: serviceArgFromCloudly.data.imageVersion,
},
);
containerService = await plugins.docker.DockerService.createService(
this.coreflowRef.dockerHost,
{
name: serviceArgFromCloudly.data.name,
image: localDockerImage,
networks: [webGatewayNetwork],
secrets: [containerSecret],
ports: [],
labels: {},
resources: serviceArgFromCloudly.data.resources,
// TODO: introduce a clean name here, that is guaranteed to work with APIs.
networkAlias: serviceArgFromCloudly.data.name,
},
);
containerSecret = await this.coreflowRef.dockerHost.createSecret({
name: dockerSecretName,
contentArg: JSON.stringify(await secretBundle.getFlatKeyValueObjectForEnvironment()),
labels: {},
version: serviceArgFromCloudly.data.imageVersion,
});
containerService = await this.coreflowRef.dockerHost.createService({
name: serviceArgFromCloudly.data.name,
image: localDockerImage,
networks: [webGatewayNetwork],
secrets: [containerSecret],
ports: [],
labels: {},
resources: serviceArgFromCloudly.data.resources,
// TODO: introduce a clean name here, that is guaranteed to work with APIs.
networkAlias: serviceArgFromCloudly.data.name,
});
}
}
@@ -346,11 +305,13 @@ export class ClusterManager {
public async updateTrafficRouting(
_clusterConfigArg: plugins.servezoneInterfaces.data.ICluster,
) {
const services = await this.coreflowRef.dockerHost.getServices();
const webGatewayNetwork = await plugins.docker.DockerNetwork.getNetworkByName(
this.coreflowRef.dockerHost,
const services = await this.coreflowRef.dockerHost.listServices();
const webGatewayNetwork = await this.coreflowRef.dockerHost.getNetworkByName(
this.commonDockerData.networkNames.sznWebgateway,
);
if (!webGatewayNetwork) {
throw new Error(`Missing required Docker network ${this.commonDockerData.networkNames.sznWebgateway}`);
}
const reverseProxyConfigs: plugins.servezoneInterfaces.data.IReverseProxyConfig[] = [];
const pushProxyConfig = async (
+1 -1
View File
@@ -11,7 +11,7 @@ import { PlatformManager } from './coreflow.classes.platformmanager.js';
* the main Coreflow class
*/
export class Coreflow {
public typedrouter = new plugins.typedrequest.TypedRouter();
public typedrouter: plugins.typedrequest.TypedRouter = new plugins.typedrequest.TypedRouter();
public internalServer: InternalServer;
public serviceQenv: plugins.qenv.Qenv;
+12 -2
View File
@@ -3,19 +3,29 @@ import * as plugins from './coreflow.plugins.js';
export class InternalServer {
public coreflowRef: Coreflow;
public typedsocketServer: plugins.typedsocket.TypedSocket;
public smartServe: plugins.smartserve.SmartServe;
public typedsocketServer!: plugins.typedsocket.TypedSocket;
constructor(coreflowRefArg: Coreflow) {
this.coreflowRef = coreflowRefArg;
this.smartServe = new plugins.smartserve.SmartServe({
port: 3000,
websocket: {
typedRouter: this.coreflowRef.typedrouter,
},
});
}
public async start() {
this.typedsocketServer = await plugins.typedsocket.TypedSocket.createServer(
await this.smartServe.start();
this.typedsocketServer = plugins.typedsocket.TypedSocket.fromSmartServe(
this.smartServe,
this.coreflowRef.typedrouter,
);
}
public async stop() {
await this.typedsocketServer.stop();
await this.smartServe.stop();
}
}
-5
View File
@@ -6,9 +6,6 @@ export class CoreflowTaskmanager {
public coreflowRef: Coreflow;
public taskmanager: plugins.taskbuffer.TaskManager;
// checkin tasks
public checkinTask: plugins.taskbuffer.Task;
// event based tasks
/**
* updates baseservices
@@ -19,8 +16,6 @@ export class CoreflowTaskmanager {
// timed
public updateTrafficRoutingTask: plugins.taskbuffer.Task;
public updateConfigTask: plugins.taskbuffer.Task;
constructor(coreflowRefArg: Coreflow) {
this.coreflowRef = coreflowRefArg;
this.taskmanager = new plugins.taskbuffer.TaskManager();
+13 -5
View File
@@ -7,21 +7,29 @@ import { Coreflow } from './coreflow.classes.coreflow.js';
export class CloudlyConnector {
public coreflowRef: Coreflow;
public cloudlyApiClient: plugins.servezoneApi.CloudlyApiClient;
public coreflowJumpCode: string;
public identity: plugins.servezoneInterfaces.data.IIdentity;
public cloudlyApiClient!: plugins.servezoneApi.CloudlyApiClient;
public coreflowJumpCode!: string;
public identity!: plugins.servezoneInterfaces.data.IIdentity;
constructor(coreflowRefArg: Coreflow) {
this.coreflowRef = coreflowRefArg;
}
public async start() {
const cloudlyUrl = await this.coreflowRef.serviceQenv.getEnvVarOnDemand('CLOUDLY_URL');
if (!cloudlyUrl) {
throw new Error('Missing required CLOUDLY_URL environment variable');
}
this.cloudlyApiClient = new plugins.servezoneApi.CloudlyApiClient({
registerAs: 'coreflow',
cloudlyUrl: await this.coreflowRef.serviceQenv.getEnvVarOnDemand('CLOUDLY_URL'),
cloudlyUrl,
});
await this.cloudlyApiClient.start();
this.coreflowJumpCode = await this.coreflowRef.serviceQenv.getEnvVarOnDemand('JUMPCODE');
const coreflowJumpCode = await this.coreflowRef.serviceQenv.getEnvVarOnDemand('JUMPCODE');
if (!coreflowJumpCode) {
throw new Error('Missing required JUMPCODE environment variable');
}
this.coreflowJumpCode = coreflowJumpCode;
// get identity and tag connection (second parameter is true -> tags the connection)
this.identity = await this.cloudlyApiClient.getIdentityByToken(this.coreflowJumpCode, {
@@ -22,8 +22,8 @@ export class CoretrafficConnector {
const reactionRequest =
this.coreflowRef.internalServer.typedsocketServer.createTypedRequest<plugins.servezoneInterfaces.requests.routing.IRequest_Coreflow_Coretraffic_RoutingUpdate>(
'updateRouting',
await this.coreflowRef.internalServer.typedsocketServer.findTargetConnection(
async (targetConnection) => targetConnection.alias === 'coretraffic',
await this.coreflowRef.internalServer.typedsocketServer.findTargetConnectionByTag(
'coretraffic',
),
);
const response = await reactionRequest.fire({
+1 -1
View File
@@ -1,4 +1,4 @@
import * as plugins from './coreflow.plugins.js';
import * as paths from './coreflow.paths.js';
export const projectInfoNpm = new plugins.projectinfo.ProjectinfoNpm(paths.packageDir);
export const projectInfoNpm = await plugins.projectinfo.ProjectinfoNpm.create(paths.packageDir);
-1
View File
@@ -1,5 +1,4 @@
import * as plugins from './coreflow.plugins.js';
import { projectInfoNpm } from './coreflow.info.js';
export const logger = new plugins.smartlog.Smartlog({
logContext: {
+3 -1
View File
@@ -15,7 +15,7 @@ import * as typedsocket from '@api.global/typedsocket';
export { typedrequest, typedsocket };
// @pushrocks scope
// @push.rocks scope
import * as lik from '@push.rocks/lik';
import * as projectinfo from '@push.rocks/projectinfo';
import * as qenv from '@push.rocks/qenv';
@@ -26,6 +26,7 @@ import * as smartnetwork from '@push.rocks/smartnetwork';
import * as smartpath from '@push.rocks/smartpath';
import * as smartpromise from '@push.rocks/smartpromise';
import * as smartrequest from '@push.rocks/smartrequest';
import * as smartserve from '@push.rocks/smartserve';
import * as smartrx from '@push.rocks/smartrx';
import * as smartstate from '@push.rocks/smartstate';
import * as smartstream from '@push.rocks/smartstream';
@@ -43,6 +44,7 @@ export {
smartpath,
smartpromise,
smartrequest,
smartserve,
smartrx,
smartstate,
smartstream,