Compare commits

..

16 Commits

81 changed files with 2109 additions and 824 deletions

@ -6,8 +6,8 @@ on:
- '**' - '**'
env: env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}} NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}} NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}} NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
@ -27,7 +27,7 @@ jobs:
- name: Install pnpm and npmci - name: Install pnpm and npmci
run: | run: |
pnpm install -g pnpm pnpm install -g pnpm
pnpm install -g @shipzone/npmci pnpm install -g @ship.zone/npmci
npmci npm prepare npmci npm prepare
- name: Audit production dependencies - name: Audit production dependencies
@ -54,7 +54,7 @@ jobs:
- name: Prepare - name: Prepare
run: | run: |
pnpm install -g pnpm pnpm install -g pnpm
pnpm install -g @shipzone/npmci pnpm install -g @ship.zone/npmci
npmci npm prepare npmci npm prepare
- name: Test stable - name: Test stable

@ -6,8 +6,8 @@ on:
- '*' - '*'
env: env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci IMAGE: code.foss.global/hosttoday/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}} NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}} NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}} NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
@ -27,7 +27,7 @@ jobs:
- name: Prepare - name: Prepare
run: | run: |
pnpm install -g pnpm pnpm install -g pnpm
pnpm install -g @shipzone/npmci pnpm install -g @ship.zone/npmci
npmci npm prepare npmci npm prepare
- name: Audit production dependencies - name: Audit production dependencies
@ -54,7 +54,7 @@ jobs:
- name: Prepare - name: Prepare
run: | run: |
pnpm install -g pnpm pnpm install -g pnpm
pnpm install -g @shipzone/npmci pnpm install -g @ship.zone/npmci
npmci npm prepare npmci npm prepare
- name: Test stable - name: Test stable
@ -74,7 +74,7 @@ jobs:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: registry.gitlab.com/hosttoday/ht-docker-dbase:npmci image: code.foss.global/hosttoday/ht-docker-dbase:npmci
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -82,15 +82,15 @@ jobs:
- name: Prepare - name: Prepare
run: | run: |
pnpm install -g pnpm pnpm install -g pnpm
pnpm install -g @shipzone/npmci pnpm install -g @ship.zone/npmci
- name: Release - name: Release
run: | run: |
npmci docker login npmci docker login
npmci docker build npmci docker build
npmci docker test npmci docker test
# npmci docker push gitea.lossless.digital # npmci docker push
npmci docker push dockerregistry.lossless.digital npmci docker push
metadata: metadata:
needs: test needs: test

@ -1,6 +1,6 @@
# gitzone dockerfile_service # gitzone dockerfile_service
## STAGE 1 // BUILD ## STAGE 1 // BUILD
FROM registry.gitlab.com/hosttoday/ht-docker-node:npmci as node1 FROM code.foss.global/hosttoday/ht-docker-node:npmci as node1
COPY ./ /app COPY ./ /app
WORKDIR /app WORKDIR /app
ARG NPMCI_TOKEN_NPM2 ARG NPMCI_TOKEN_NPM2
@ -12,7 +12,7 @@ RUN pnpm run build
# gitzone dockerfile_service # gitzone dockerfile_service
## STAGE 2 // install production ## STAGE 2 // install production
FROM registry.gitlab.com/hosttoday/ht-docker-node:npmci as node2 FROM code.foss.global/hosttoday/ht-docker-node:npmci as node2
WORKDIR /app WORKDIR /app
COPY --from=node1 /app /app COPY --from=node1 /app /app
RUN rm -rf .pnpm-store RUN rm -rf .pnpm-store
@ -24,7 +24,7 @@ RUN rm -rf node_modules/ && pnpm install --prod
## STAGE 3 // rebuild dependencies for alpine ## STAGE 3 // rebuild dependencies for alpine
FROM registry.gitlab.com/hosttoday/ht-docker-node:alpinenpmci as node3 FROM code.foss.global/hosttoday/ht-docker-node:alpinenpmci as node3
WORKDIR /app WORKDIR /app
COPY --from=node2 /app /app COPY --from=node2 /app /app
ARG NPMCI_TOKEN_NPM2 ARG NPMCI_TOKEN_NPM2
@ -34,7 +34,7 @@ RUN pnpm config set store-dir .pnpm-store
RUN pnpm rebuild -r RUN pnpm rebuild -r
## STAGE 4 // the final production image with all dependencies in place ## STAGE 4 // the final production image with all dependencies in place
FROM registry.gitlab.com/hosttoday/ht-docker-node:alpine as node4 FROM code.foss.global/hosttoday/ht-docker-node:alpine as node4
WORKDIR /app WORKDIR /app
COPY --from=node3 /app /app COPY --from=node3 /app /app

@ -1,5 +1,54 @@
# Changelog # Changelog
## 2024-10-28 - 4.1.1 - fix(core)
Fixed syntax issues in commitinfo data and package.json file.
- Added a missing newline at the end of the package.json file.
- Corrected a trailing comma and added proper syntax in the commitinfo data.
## 2024-10-28 - 4.1.0 - feat(core)
Enhance core functionality for cloud management and orchestration
- Improved initialization and management of cloud environments with Docker Swarmkit.
- Added capability to manage DNS records via Cloudflare.
- Introduced integration support for DigitalOcean resources.
## 2024-10-28 - 4.0.1 - fix(package_manager)
Update @git.zone/tspublish dependency version
- Bump @git.zone/tspublish version from 1.5.4 to 1.5.5.
## 2024-10-28 - 4.0.0 - BREAKING CHANGE(core)
Significant overhaul with potential breaking changes, update to version 3.0.0
- Updated project version from 1.2.5 to 3.0.0 in package.json
## 2024-10-28 - 1.2.5 - fix(build)
Updated devDependencies for tspublish and removed buildDocs script
- devDependencies updated: @git.zone/tspublish to version ^1.5.4
- Removed: buildDocs script from the scripts section
## 2024-10-27 - 1.2.4 - fix(ci)
Fix Docker images and npm registry URL in CI workflows
- Updated Docker image registry URL from 'registry.gitlab.com' to 'code.foss.global'.
- Fixed npmci package installation path from '@shipzone/npmci' to '@ship.zone/npmci'.
## 2024-10-23 - 1.2.3 - fix(cli)
Set up CLI client definition and registry configuration
- Added a console log message for CLI identification.
- Defined package name for CLI client.
- Configured npm registries for package distribution.
## 2024-10-23 - 1.2.2 - fix(docs)
Updated documentation with clearer usage instructions and examples.
- Refined setup guides in README.
- Added more detailed examples in code snippets.
- Clarified cloud service integration instructions.
## 2024-10-23 - 1.2.1 - fix(core) ## 2024-10-23 - 1.2.1 - fix(core)
Fixed startup issue for the Cloudly instance Fixed startup issue for the Cloudly instance

@ -1,6 +1,6 @@
{ {
"name": "@serve.zone/cloudly", "name": "@serve.zone/cloudly",
"version": "1.2.1", "version": "4.1.1",
"private": false, "private": false,
"description": "A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.", "description": "A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.",
"type": "module", "type": "module",
@ -18,19 +18,21 @@
"start": "node cli.js", "start": "node cli.js",
"startTs": "node cli.ts.js", "startTs": "node cli.ts.js",
"watch": "tswatch website", "watch": "tswatch website",
"publish": "tspublish" "publish": "tspublish",
"buildDocs": "tsdoc"
}, },
"devDependencies": { "devDependencies": {
"@git.zone/tsbuild": "^2.1.84", "@git.zone/tsbuild": "^2.1.85",
"@git.zone/tsbundle": "^2.0.15", "@git.zone/tsbundle": "^2.1.0",
"@git.zone/tspublish": "^1.3.0", "@git.zone/tspublish": "^1.5.5",
"@git.zone/tstest": "^1.0.90", "@git.zone/tstest": "^1.0.90",
"@git.zone/tswatch": "^2.0.23", "@git.zone/tswatch": "^2.0.25",
"@push.rocks/tapbundle": "^5.3.0", "@push.rocks/tapbundle": "^5.3.0",
"@types/node": "^22.7.7" "@types/node": "^22.8.1"
}, },
"dependencies": { "dependencies": {
"@api.global/typedrequest": "3.1.10", "@api.global/typedrequest": "3.1.10",
"@api.global/typedrequest-interfaces": "^3.0.19",
"@api.global/typedserver": "^3.0.51", "@api.global/typedserver": "^3.0.51",
"@api.global/typedsocket": "^3.0.1", "@api.global/typedsocket": "^3.0.1",
"@apiclient.xyz/cloudflare": "^6.0.1", "@apiclient.xyz/cloudflare": "^6.0.1",
@ -40,7 +42,7 @@
"@design.estate/dees-catalog": "^1.2.0", "@design.estate/dees-catalog": "^1.2.0",
"@design.estate/dees-domtools": "^2.0.64", "@design.estate/dees-domtools": "^2.0.64",
"@design.estate/dees-element": "^2.0.39", "@design.estate/dees-element": "^2.0.39",
"@git.zone/tsrun": "^1.2.49", "@git.zone/tsrun": "^1.3.3",
"@push.rocks/early": "^4.0.3", "@push.rocks/early": "^4.0.3",
"@push.rocks/npmextra": "^5.0.23", "@push.rocks/npmextra": "^5.0.23",
"@push.rocks/projectinfo": "^5.0.1", "@push.rocks/projectinfo": "^5.0.1",
@ -59,6 +61,7 @@
"@push.rocks/smartjwt": "^2.2.1", "@push.rocks/smartjwt": "^2.2.1",
"@push.rocks/smartlog": "^3.0.7", "@push.rocks/smartlog": "^3.0.7",
"@push.rocks/smartlog-destination-clickhouse": "^1.0.13", "@push.rocks/smartlog-destination-clickhouse": "^1.0.13",
"@push.rocks/smartlog-interfaces": "^3.0.2",
"@push.rocks/smartpath": "^5.0.18", "@push.rocks/smartpath": "^5.0.18",
"@push.rocks/smartpromise": "^4.0.4", "@push.rocks/smartpromise": "^4.0.4",
"@push.rocks/smartrequest": "^2.0.22", "@push.rocks/smartrequest": "^2.0.22",
@ -70,7 +73,6 @@
"@push.rocks/smartunique": "^3.0.9", "@push.rocks/smartunique": "^3.0.9",
"@push.rocks/taskbuffer": "^3.0.2", "@push.rocks/taskbuffer": "^3.0.2",
"@push.rocks/webjwt": "^1.0.9", "@push.rocks/webjwt": "^1.0.9",
"@serve.zone/interfaces": "^1.1.2",
"@tsclass/tsclass": "^4.1.2" "@tsclass/tsclass": "^4.1.2"
}, },
"files": [ "files": [

1295
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/cloudly', name: '@serve.zone/cloudly',
version: '1.2.1', version: '4.1.1',
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.' description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.'
} }

@ -17,7 +17,7 @@ import { MongodbConnector } from './connector.mongodb/connector.js';
import { CloudlyCoreflowManager } from './manager.coreflow/coreflowmanager.js'; import { CloudlyCoreflowManager } from './manager.coreflow/coreflowmanager.js';
import { ClusterManager } from './manager.cluster/classes.clustermanager.js'; import { ClusterManager } from './manager.cluster/classes.clustermanager.js';
import { CloudlyTaskmanager } from './manager.task/taskmanager.js'; import { CloudlyTaskmanager } from './manager.task/taskmanager.js';
import { CloudlySecretManager } from './manager.secret/classes.secretmanager.js' import { CloudlySecretManager } from './manager.secret/classes.secretmanager.js';
import { CloudlyServerManager } from './manager.server/classes.servermanager.js'; import { CloudlyServerManager } from './manager.server/classes.servermanager.js';
import { ExternalApiManager } from './manager.status/statusmanager.js'; import { ExternalApiManager } from './manager.status/statusmanager.js';
import { ImageManager } from './manager.image/classes.imagemanager.js'; import { ImageManager } from './manager.image/classes.imagemanager.js';

@ -9,15 +9,16 @@ import type { Cloudly } from './classes.cloudly.js';
export class CloudlyConfig { export class CloudlyConfig {
public cloudlyRef: Cloudly; public cloudlyRef: Cloudly;
public appData: plugins.npmextra.AppData<plugins.servezoneInterfaces.data.ICloudlyConfig>; public appData: plugins.npmextra.AppData<plugins.servezoneInterfaces.data.ICloudlyConfig>;
public data: plugins.servezoneInterfaces.data.ICloudlyConfig public data: plugins.servezoneInterfaces.data.ICloudlyConfig;
constructor(cloudlyRefArg: Cloudly) { constructor(cloudlyRefArg: Cloudly) {
this.cloudlyRef = cloudlyRefArg; this.cloudlyRef = cloudlyRefArg;
} }
public async init() { public async init() {
this.appData = await plugins.npmextra.AppData.createAndInit<plugins.servezoneInterfaces.data.ICloudlyConfig>({ this.appData =
await plugins.npmextra.AppData.createAndInit<plugins.servezoneInterfaces.data.ICloudlyConfig>(
{
envMapping: { envMapping: {
cfToken: 'CF_TOKEN', cfToken: 'CF_TOKEN',
environment: 'SERVEZONE_ENVIRONMENT' as 'production' | 'integration', environment: 'SERVEZONE_ENVIRONMENT' as 'production' | 'integration',
@ -39,7 +40,8 @@ export class CloudlyConfig {
port: 'S3_PORT', // Note: This will remain as a string. Ensure to parse it to an integer where it's used. port: 'S3_PORT', // Note: This will remain as a string. Ensure to parse it to an integer where it's used.
useSsl: true, useSsl: true,
}, },
sslMode: 'SERVEZONE_SSLMODE' as plugins.servezoneInterfaces.data.ICloudlyConfig['sslMode'], sslMode:
'SERVEZONE_SSLMODE' as plugins.servezoneInterfaces.data.ICloudlyConfig['sslMode'],
servezoneAdminaccount: 'SERVEZONE_ADMINACCOUNT', servezoneAdminaccount: 'SERVEZONE_ADMINACCOUNT',
}, },
requiredKeys: [ requiredKeys: [
@ -52,7 +54,8 @@ export class CloudlyConfig {
'environment', 'environment',
'mongoDescriptor', 'mongoDescriptor',
], ],
}); },
);
const kvStore = await this.appData.getKvStore(); const kvStore = await this.appData.getKvStore();

@ -45,16 +45,16 @@ export class CloudlyServer {
logger.log('info', `Using letsencrypt for ssl mode. Trying to obtain a certificate...`); logger.log('info', `Using letsencrypt for ssl mode. Trying to obtain a certificate...`);
logger.log('info', `This might take 10 minutes...`); logger.log('info', `This might take 10 minutes...`);
sslCert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain( sslCert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
this.cloudlyRef.config.data.publicUrl this.cloudlyRef.config.data.publicUrl,
); );
logger.log( logger.log(
'success', 'success',
`Successfully obtained certificate for cloudly domain ${this.cloudlyRef.config.data.publicUrl}` `Successfully obtained certificate for cloudly domain ${this.cloudlyRef.config.data.publicUrl}`,
); );
} else if (this.cloudlyRef.config.data.sslMode === 'external') { } else if (this.cloudlyRef.config.data.sslMode === 'external') {
logger.log( logger.log(
'info', 'info',
`Using external certificate for ssl mode, meaning cloudly is not in charge of ssl termination.` `Using external certificate for ssl mode, meaning cloudly is not in charge of ssl termination.`,
); );
} }
@ -95,7 +95,7 @@ export class CloudlyServer {
this.typedServer.typedrouter.addTypedRouter(this.typedrouter); this.typedServer.typedrouter.addTypedRouter(this.typedrouter);
this.typedServer.server.addRoute( this.typedServer.server.addRoute(
'/curlfresh/:scriptname', '/curlfresh/:scriptname',
this.cloudlyRef.serverManager.curlfreshInstance.handler this.cloudlyRef.serverManager.curlfreshInstance.handler,
); );
await this.typedServer.start(); await this.typedServer.start();
} }

@ -24,19 +24,19 @@ export class LetsencryptConnector {
environment: this.cloudlyRef.config.data.environment, environment: this.cloudlyRef.config.data.environment,
setChallenge: async (dnsChallenge) => { setChallenge: async (dnsChallenge) => {
await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeSetDnsChallenge( await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeSetDnsChallenge(
dnsChallenge dnsChallenge,
); );
}, },
removeChallenge: async (dnsChallenge) => { removeChallenge: async (dnsChallenge) => {
await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeRemoveDnsChallenge( await this.cloudlyRef.cloudflareConnector.cloudflare.convenience.acmeRemoveDnsChallenge(
dnsChallenge dnsChallenge,
); );
}, },
mongoDescriptor: this.cloudlyRef.config.data.mongoDescriptor, mongoDescriptor: this.cloudlyRef.config.data.mongoDescriptor,
}); });
await this.smartacme.start().catch(err => { await this.smartacme.start().catch((err) => {
console.error('error in init', err); console.error('error in init', err);
console.log(`trying again in a few minutes`) console.log(`trying again in a few minutes`);
}); });
} }

@ -11,7 +11,9 @@ export class MongodbConnector {
} }
public async init() { public async init() {
this.smartdataDb = new plugins.smartdata.SmartdataDb(this.cloudlyRef.config.data.mongoDescriptor); this.smartdataDb = new plugins.smartdata.SmartdataDb(
this.cloudlyRef.config.data.mongoDescriptor,
);
await this.smartdataDb.init(); await this.smartdataDb.init();
} }

@ -7,7 +7,6 @@ import { logger } from './logger.js';
const cloudlyQenv = new plugins.qenv.Qenv(paths.packageDir, paths.nogitDir, true); const cloudlyQenv = new plugins.qenv.Qenv(paths.packageDir, paths.nogitDir, true);
early.stop(); early.stop();
/** /**
* starts the cloudly instance * starts the cloudly instance
*/ */
@ -17,7 +16,7 @@ const runCli = async () => {
logger.log( logger.log(
'info', 'info',
`running in environment ${await cloudlyQenv.getEnvVarOnDemand('SERVEZONE_ENVIRONMENT')}` `running in environment ${await cloudlyQenv.getEnvVarOnDemand('SERVEZONE_ENVIRONMENT')}`,
); );
await cloudlyInstance.start(); await cloudlyInstance.start();
@ -27,4 +26,4 @@ const runCli = async () => {
export { runCli, Cloudly }; export { runCli, Cloudly };
type ICloudlyConfig = plugins.servezoneInterfaces.data.ICloudlyConfig; type ICloudlyConfig = plugins.servezoneInterfaces.data.ICloudlyConfig;
export { type ICloudlyConfig } export { type ICloudlyConfig };

@ -9,8 +9,8 @@ export const logger = new plugins.smartlog.Smartlog({
zone: null, zone: null,
companyunit: null, companyunit: null,
containerName: null, containerName: null,
} },
}); });
logger.enableConsole({ logger.enableConsole({
captureAll: false captureAll: false,
}); });

@ -5,7 +5,6 @@ import { logger } from '../logger.js';
import { Authorization } from './classes.authorization.js'; import { Authorization } from './classes.authorization.js';
import { User } from './classes.user.js'; import { User } from './classes.user.js';
export interface IJwtData { export interface IJwtData {
userId: string; userId: string;
status: 'loggedIn' | 'loggedOut'; status: 'loggedIn' | 'loggedOut';
@ -13,7 +12,7 @@ export interface IJwtData {
} }
export class CloudlyAuthManager { export class CloudlyAuthManager {
cloudlyRef: Cloudly cloudlyRef: Cloudly;
public get db() { public get db() {
return this.cloudlyRef.mongodbConnector.smartdataDb; return this.cloudlyRef.mongodbConnector.smartdataDb;
} }
@ -38,7 +37,9 @@ export class CloudlyAuthManager {
await this.smartjwtInstance.init(); await this.smartjwtInstance.init();
const kvStore = await this.cloudlyRef.config.appData.getKvStore(); const kvStore = await this.cloudlyRef.config.appData.getKvStore();
const existingJwtKeys: plugins.tsclass.network.IJwtKeypair = (await kvStore.readKey('jwtKeypair')) as plugins.tsclass.network.IJwtKeypair; const existingJwtKeys: plugins.tsclass.network.IJwtKeypair = (await kvStore.readKey(
'jwtKeypair',
)) as plugins.tsclass.network.IJwtKeypair;
if (!existingJwtKeys) { if (!existingJwtKeys) {
await this.smartjwtInstance.createNewKeyPair(); await this.smartjwtInstance.createNewKeyPair();
@ -76,31 +77,50 @@ export class CloudlyAuthManager {
type: user.data.type, type: user.data.type,
}, },
}; };
} },
) ),
); );
} }
public async stop() {} public async stop() {}
public validIdentityGuard = new plugins.smartguard.Guard<{identity: plugins.servezoneInterfaces.data.IIdentity}>(async (dataArg) => { public validIdentityGuard = new plugins.smartguard.Guard<{
identity: plugins.servezoneInterfaces.data.IIdentity;
}>(
async (dataArg) => {
const jwt = dataArg.identity.jwt; const jwt = dataArg.identity.jwt;
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt); const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
const expired = jwtData.expiresAt < Date.now(); const expired = jwtData.expiresAt < Date.now();
plugins.smartexpect.expect(jwtData.status).setFailMessage('user not logged in').toEqual('loggedIn'); plugins.smartexpect
.expect(jwtData.status)
.setFailMessage('user not logged in')
.toEqual('loggedIn');
plugins.smartexpect.expect(expired).setFailMessage(`jwt expired`).toBeFalse(); plugins.smartexpect.expect(expired).setFailMessage(`jwt expired`).toBeFalse();
plugins.smartexpect.expect(dataArg.identity.expiresAt).setFailMessage(`expiresAt >>identity valid until:${dataArg.identity.expiresAt}, but jwt says: ${jwtData.expiresAt}<< has been tampered with`).toEqual(jwtData.expiresAt); plugins.smartexpect
plugins.smartexpect.expect(dataArg.identity.userId).setFailMessage('userId has been tampered with').toEqual(jwtData.userId); .expect(dataArg.identity.expiresAt)
.setFailMessage(
`expiresAt >>identity valid until:${dataArg.identity.expiresAt}, but jwt says: ${jwtData.expiresAt}<< has been tampered with`,
)
.toEqual(jwtData.expiresAt);
plugins.smartexpect
.expect(dataArg.identity.userId)
.setFailMessage('userId has been tampered with')
.toEqual(jwtData.userId);
if (expired) { if (expired) {
throw new Error('identity is expired'); throw new Error('identity is expired');
} }
return true; return true;
}, { },
{
failedHint: 'identity is not valid.', failedHint: 'identity is not valid.',
name: 'validIdentityGuard', name: 'validIdentityGuard',
}); },
);
public adminIdentityGuard = new plugins.smartguard.Guard<{identity: plugins.servezoneInterfaces.data.IIdentity}>(async (dataArg) => { public adminIdentityGuard = new plugins.smartguard.Guard<{
identity: plugins.servezoneInterfaces.data.IIdentity;
}>(
async (dataArg) => {
await plugins.smartguard.passGuardsOrReject(dataArg, [this.validIdentityGuard]); await plugins.smartguard.passGuardsOrReject(dataArg, [this.validIdentityGuard]);
const jwt = dataArg.identity.jwt; const jwt = dataArg.identity.jwt;
const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt); const jwtData: IJwtData = await this.smartjwtInstance.verifyJWTAndGetData(jwt);
@ -108,8 +128,10 @@ export class CloudlyAuthManager {
const isAdminBool = user.data.role === 'admin'; const isAdminBool = user.data.role === 'admin';
console.log(`user is admin: ${isAdminBool}`); console.log(`user is admin: ${isAdminBool}`);
return isAdminBool; return isAdminBool;
}, { },
{
failedHint: 'user is not admin.', failedHint: 'user is not admin.',
name: 'adminIdentityGuard', name: 'adminIdentityGuard',
}) },
);
} }

@ -1,6 +1,4 @@
import * as plugins from '../plugins.js'; import * as plugins from '../plugins.js';
@plugins.smartdata.managed() @plugins.smartdata.managed()
export class Authorization extends plugins.smartdata.SmartDataDbDoc<Authorization, Authorization> { export class Authorization extends plugins.smartdata.SmartDataDbDoc<Authorization, Authorization> {}
}

@ -14,11 +14,13 @@ export class User extends plugins.smartdata.SmartDataDbDoc<
user.data = { user.data = {
type: 'machine', type: 'machine',
username: userNameArg, username: userNameArg,
tokens: [{ tokens: [
{
token: 'machineUser', token: 'machineUser',
expiresAt: Date.now() + 3600 * 1000 * 24 * 365, expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
assignedRoles: ['admin'], assignedRoles: ['admin'],
}], },
],
role: 'api', role: 'api',
}; };
await user.save(); await user.save();

@ -1,5 +1,3 @@
import * as plugins from '../plugins.js'; import * as plugins from '../plugins.js';
export class Cert extends plugins.smartdata.SmartDataDbDoc<Cert, Cert> { export class Cert extends plugins.smartdata.SmartDataDbDoc<Cert, Cert> {}
}

@ -4,11 +4,12 @@ import * as plugins from '../plugins.js';
* cluster defines a swarmkit cluster * cluster defines a swarmkit cluster
*/ */
@plugins.smartdata.managed() @plugins.smartdata.managed()
export class Cluster extends plugins.smartdata.SmartDataDbDoc<Cluster, plugins.servezoneInterfaces.data.ICluster> { export class Cluster extends plugins.smartdata.SmartDataDbDoc<
Cluster,
plugins.servezoneInterfaces.data.ICluster
> {
// STATIC // STATIC
public static async fromConfigObject( public static async fromConfigObject(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
configObjectArg: plugins.servezoneInterfaces.data.ICluster
) {
const newCluster = new Cluster(); const newCluster = new Cluster();
Object.assign(newCluster, configObjectArg); Object.assign(newCluster, configObjectArg);
return newCluster; return newCluster;

@ -40,7 +40,7 @@ export class ClusterManager {
return { return {
clusterConfig: await cluster.createSavableObject(), clusterConfig: await cluster.createSavableObject(),
}; };
}) }),
); );
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_GetAllClusters>( this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_GetAllClusters>(
@ -49,10 +49,10 @@ export class ClusterManager {
const clusters = await this.getAllClusters(); const clusters = await this.getAllClusters();
return { return {
clusters: await Promise.all( clusters: await Promise.all(
clusters.map((clusterArg) => clusterArg.createSavableObject()) clusters.map((clusterArg) => clusterArg.createSavableObject()),
), ),
}; };
}) }),
); );
// delete cluster // delete cluster
@ -63,7 +63,7 @@ export class ClusterManager {
return { return {
success: true, success: true,
}; };
}) }),
); );
} }

@ -18,17 +18,23 @@ export class CloudlyCoreflowManager {
new plugins.typedrequest.TypedHandler('getIdentityByToken', async (requestData) => { new plugins.typedrequest.TypedHandler('getIdentityByToken', async (requestData) => {
const user = await this.cloudlyRef.authManager.CUser.getInstance({ const user = await this.cloudlyRef.authManager.CUser.getInstance({
data: { data: {
tokens: [{ tokens: [
{
token: requestData.token, token: requestData.token,
}] // find the proper user here. },
} as any ], // find the proper user here.
} as any,
}); });
if (!user) { if (!user) {
throw new plugins.typedrequest.TypedResponseError('The supplied token is not valid. No matching user found.'); throw new plugins.typedrequest.TypedResponseError(
'The supplied token is not valid. No matching user found.',
);
} }
if (user.data.type !== 'machine') { if (user.data.type !== 'machine') {
throw new plugins.typedrequest.TypedResponseError('The supplied token is not valid. The user is not a machine.'); throw new plugins.typedrequest.TypedResponseError(
'The supplied token is not valid. The user is not a machine.',
);
} }
let cluster: Cluster; let cluster: Cluster;
if (user.data.role === 'cluster') { if (user.data.role === 'cluster') {
@ -42,18 +48,20 @@ export class CloudlyCoreflowManager {
type: 'machine', // if someone authenticates by token, they are a machine, no matter what. type: 'machine', // if someone authenticates by token, they are a machine, no matter what.
userId: user.id, userId: user.id,
expiresAt: expiryTimestamp, expiresAt: expiryTimestamp,
...(cluster ? { ...(cluster
? {
clusterId: cluster.id, clusterId: cluster.id,
clusterName: cluster.data.name, clusterName: cluster.data.name,
} : {}), }
: {}),
jwt: await this.cloudlyRef.authManager.smartjwtInstance.createJWT({ jwt: await this.cloudlyRef.authManager.smartjwtInstance.createJWT({
status: 'loggedIn', status: 'loggedIn',
userId: user.id, userId: user.id,
expiresAt: expiryTimestamp, expiresAt: expiryTimestamp,
}) }),
}, },
}; };
}) }),
); );
// lets enable the getting of cluster configs // lets enable the getting of cluster configs
@ -64,17 +72,14 @@ export class CloudlyCoreflowManager {
const identity = dataArg.identity; const identity = dataArg.identity;
console.log('trying to get clusterConfigSet'); console.log('trying to get clusterConfigSet');
console.log(dataArg); console.log(dataArg);
const cluster = const cluster = await this.cloudlyRef.clusterManager.getClusterBy_Identity(identity);
await this.cloudlyRef.clusterManager.getClusterBy_Identity(
identity
);
console.log('got cluster config and sending it back to coreflow'); console.log('got cluster config and sending it back to coreflow');
return { return {
configData: await cluster.createSavableObject(), configData: await cluster.createSavableObject(),
deploymentDirectives: [], deploymentDirectives: [],
}; };
} },
) ),
); );
// lets enable getting of certificates // lets enable getting of certificates
@ -84,14 +89,14 @@ export class CloudlyCoreflowManager {
async (dataArg) => { async (dataArg) => {
console.log(`incoming API request for certificate ${dataArg.domainName}`); console.log(`incoming API request for certificate ${dataArg.domainName}`);
const cert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain( const cert = await this.cloudlyRef.letsencryptConnector.getCertificateForDomain(
dataArg.domainName dataArg.domainName,
); );
console.log(`got certificate ready for reponse ${dataArg.domainName}`); console.log(`got certificate ready for reponse ${dataArg.domainName}`);
return { return {
certificate: await cert.createSavableObject(), certificate: await cert.createSavableObject(),
}; };
} },
) ),
); );
} }
} }

@ -2,8 +2,14 @@ import * as plugins from '../plugins.js';
import type { ImageManager } from './classes.imagemanager.js'; import type { ImageManager } from './classes.imagemanager.js';
@plugins.smartdata.managed() @plugins.smartdata.managed()
export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.servezoneInterfaces.data.IImage, ImageManager> { export class Image extends plugins.smartdata.SmartDataDbDoc<
public static async create(imageDataArg: Partial<plugins.servezoneInterfaces.data.IImage['data']>) { Image,
plugins.servezoneInterfaces.data.IImage,
ImageManager
> {
public static async create(
imageDataArg: Partial<plugins.servezoneInterfaces.data.IImage['data']>,
) {
const image = new Image(); const image = new Image();
image.id = await this.getNewId(); image.id = await this.getNewId();
console.log(imageDataArg); console.log(imageDataArg);
@ -14,7 +20,7 @@ export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.serve
versions: [], versions: [],
}, },
}); });
console.log((Image as any).saveableProperties) console.log((Image as any).saveableProperties);
await image.save(); await image.save();
return image; return image;
} }
@ -32,14 +38,10 @@ export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.serve
* note: this is relative to the storage method defined by the imageManager * note: this is relative to the storage method defined by the imageManager
*/ */
public async getStoragePath(versionStringArg: string) { public async getStoragePath(versionStringArg: string) {
return `${this.data.name}:${versionStringArg}`.replace('/', '__') return `${this.data.name}:${versionStringArg}`.replace('/', '__');
} }
public async getWriteStream() { public async getWriteStream() {}
} public async getReadStream() {}
public async getReadStream() {
}
} }

@ -35,8 +35,8 @@ export class ImageManager {
return { return {
image: await image.createSavableObject(), image: await image.createSavableObject(),
}; };
} },
) ),
); );
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_GetImage>( this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_GetImage>(
@ -48,7 +48,7 @@ export class ImageManager {
return { return {
image: await image.createSavableObject(), image: await image.createSavableObject(),
}; };
}) }),
); );
this.typedrouter.addTypedHandler( this.typedrouter.addTypedHandler(
@ -61,8 +61,8 @@ export class ImageManager {
}); });
await image.delete(); await image.delete();
return {}; return {};
} },
) ),
); );
this.typedrouter.addTypedHandler( this.typedrouter.addTypedHandler(
@ -75,11 +75,11 @@ export class ImageManager {
images: await Promise.all( images: await Promise.all(
images.map((image) => { images.map((image) => {
return image.createSavableObject(); return image.createSavableObject();
}) }),
), ),
}; };
} },
) ),
); );
this.typedrouter.addTypedHandler( this.typedrouter.addTypedHandler(
@ -97,7 +97,7 @@ export class ImageManager {
} }
const imageVersion = reqArg.versionString; const imageVersion = reqArg.versionString;
console.log( console.log(
`got request to push image version ${imageVersion} for image ${refImage.data.name}` `got request to push image version ${imageVersion} for image ${refImage.data.name}`,
); );
const imagePushStream = reqArg.imageStream; const imagePushStream = reqArg.imageStream;
(async () => { (async () => {
@ -111,13 +111,16 @@ export class ImageManager {
}, },
}); });
imagePushStream.writeToWebstream(smartWebDuplex.writable); imagePushStream.writeToWebstream(smartWebDuplex.writable);
await this.dockerImageStore.storeImage(refImage.id, plugins.smartstream.SmartDuplex.fromWebReadableStream(smartWebDuplex.readable)); await this.dockerImageStore.storeImage(
refImage.id,
plugins.smartstream.SmartDuplex.fromWebReadableStream(smartWebDuplex.readable),
);
})(); })();
return { return {
allowed: true, allowed: true,
}; };
} },
) ),
); );
this.typedrouter.addTypedHandler( this.typedrouter.addTypedHandler(
@ -128,20 +131,20 @@ export class ImageManager {
id: reqArg.imageId, id: reqArg.imageId,
}); });
const imageVersion = image.data.versions.find( const imageVersion = image.data.versions.find(
(version) => version.versionString === reqArg.versionString (version) => version.versionString === reqArg.versionString,
); );
const readable = this.imageDir.fastGetStream( const readable = this.imageDir.fastGetStream(
{ {
path: await image.getStoragePath(reqArg.versionString), path: await image.getStoragePath(reqArg.versionString),
}, },
'webstream' 'webstream',
); );
const imageVirtualStream = new plugins.typedrequest.VirtualStream(); const imageVirtualStream = new plugins.typedrequest.VirtualStream();
return { return {
imageStream: imageVirtualStream, imageStream: imageVirtualStream,
}; };
} },
) ),
); );
} }
@ -151,7 +154,7 @@ export class ImageManager {
await this.cloudlyRef.config.appData.waitForAndGetKey('s3Descriptor'); await this.cloudlyRef.config.appData.waitForAndGetKey('s3Descriptor');
console.log(this.cloudlyRef.config.data.s3Descriptor); console.log(this.cloudlyRef.config.data.s3Descriptor);
this.smartbucketInstance = new plugins.smartbucket.SmartBucket( this.smartbucketInstance = new plugins.smartbucket.SmartBucket(
this.cloudlyRef.config.data.s3Descriptor this.cloudlyRef.config.data.s3Descriptor,
); );
const bucket = await this.smartbucketInstance.getBucketByName('cloudly-test'); const bucket = await this.smartbucketInstance.getBucketByName('cloudly-test');
await bucket.fastPut({ path: 'images/00init', contents: 'init' }); await bucket.fastPut({ path: 'images/00init', contents: 'init' });

@ -23,7 +23,7 @@ export class SecretBundle extends plugins.smartdata.SmartDataDbDoc<
secretGroups.push( secretGroups.push(
await SecretGroup.getInstance({ await SecretGroup.getInstance({
id: secretGroupId, id: secretGroupId,
}) }),
); );
} }
return secretGroups; return secretGroups;

@ -40,23 +40,23 @@ export class CloudlySecretManager {
'adminGetConfigBundlesAndSecretGroups', 'adminGetConfigBundlesAndSecretGroups',
async (dataArg, toolsArg) => { async (dataArg, toolsArg) => {
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg); await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
dataArg.identity.jwt dataArg.identity.jwt;
const secretBundles = await SecretBundle.getInstances({}); const secretBundles = await SecretBundle.getInstances({});
const secretGroups = await SecretGroup.getInstances({}); const secretGroups = await SecretGroup.getInstances({});
return { return {
secretBundles: [ secretBundles: [
...(await Promise.all( ...(await Promise.all(
secretBundles.map((configBundle) => configBundle.createSavableObject()) secretBundles.map((configBundle) => configBundle.createSavableObject()),
)), )),
], ],
secretGroups: [ secretGroups: [
...(await Promise.all( ...(await Promise.all(
secretGroups.map((secretGroup) => secretGroup.createSavableObject()) secretGroups.map((secretGroup) => secretGroup.createSavableObject()),
)), )),
], ],
}; };
} },
) ),
); );
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_CreateConfigBundlesAndSecretGroups>( this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_CreateConfigBundlesAndSecretGroups>(
@ -72,8 +72,8 @@ export class CloudlySecretManager {
return { return {
ok: true, ok: true,
}; };
} },
) ),
); );
this.typedrouter.addTypedHandler( this.typedrouter.addTypedHandler(
@ -96,8 +96,8 @@ export class CloudlySecretManager {
return { return {
ok: true, ok: true,
}; };
} },
) ),
); );
// lets add typedrouter routes for accessing the configvailt from apps // lets add typedrouter routes for accessing the configvailt from apps
@ -116,19 +116,19 @@ export class CloudlySecretManager {
}, },
}); });
const authorization = await wantedBundle.getAuthorizationFromAuthKey( const authorization = await wantedBundle.getAuthorizationFromAuthKey(
dataArg.authorization dataArg.authorization,
); );
return { return {
envBundle: { envBundle: {
configKeyValueObject: await wantedBundle.getKeyValueObjectForEnvironment( configKeyValueObject: await wantedBundle.getKeyValueObjectForEnvironment(
authorization.environment authorization.environment,
), ),
environment: authorization.environment, environment: authorization.environment,
timeSensitive: false, timeSensitive: false,
}, },
}; };
} },
) ),
); );
} }

@ -5,7 +5,7 @@ import type { CloudlyServerManager } from './classes.servermanager.js';
export class CurlFresh { export class CurlFresh {
public optionsArg = { public optionsArg = {
npmRegistry: 'https://registry.npmjs.org', npmRegistry: 'https://registry.npmjs.org',
} };
public scripts = { public scripts = {
'setup.sh': `#!/bin/bash 'setup.sh': `#!/bin/bash
@ -66,7 +66,8 @@ bash -c "spark installdaemon"
this.serverManagerRef = serverManagerRefArg; this.serverManagerRef = serverManagerRefArg;
} }
public async getServerUserData(): Promise<string> { public async getServerUserData(): Promise<string> {
const sslMode = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('sslMode'); const sslMode =
await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('sslMode');
let protocol: 'http' | 'https'; let protocol: 'http' | 'https';
if (sslMode === 'none') { if (sslMode === 'none') {
protocol = 'http'; protocol = 'http';
@ -74,14 +75,16 @@ bash -c "spark installdaemon"
protocol = 'https'; protocol = 'https';
} }
const domain = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicUrl'); const domain =
const port = await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicPort'); await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicUrl');
const port =
await this.serverManagerRef.cloudlyRef.config.appData.waitForAndGetKey('publicPort');
const serverUserData = `#cloud-config const serverUserData = `#cloud-config
runcmd: runcmd:
- curl -o- ${protocol}://${domain}:${port}/curlfresh/setup.sh | sh - curl -o- ${protocol}://${domain}:${port}/curlfresh/setup.sh | sh
` `;
console.log(serverUserData); console.log(serverUserData);
return serverUserData; return serverUserData;
}; }
} }

@ -4,10 +4,13 @@ import * as plugins from '../plugins.js';
* cluster defines a swarmkit cluster * cluster defines a swarmkit cluster
*/ */
@plugins.smartdata.Manager() @plugins.smartdata.Manager()
export class Server extends plugins.smartdata.SmartDataDbDoc<Server, plugins.servezoneInterfaces.data.IServer> { export class Server extends plugins.smartdata.SmartDataDbDoc<
Server,
plugins.servezoneInterfaces.data.IServer
> {
// STATIC // STATIC
public static async createFromHetznerServer( public static async createFromHetznerServer(
hetznerServerArg: plugins.hetznercloud.HetznerServer hetznerServerArg: plugins.hetznercloud.HetznerServer,
) { ) {
const newServer = new Server(); const newServer = new Server();
newServer.id = plugins.smartunique.shortId(8); newServer.id = plugins.smartunique.shortId(8);
@ -16,7 +19,7 @@ export class Server extends plugins.smartdata.SmartDataDbDoc<Server, plugins.ser
requiredDebianPackages: [], requiredDebianPackages: [],
sshKeys: [], sshKeys: [],
type: 'hetzner', type: 'hetzner',
} };
Object.assign(newServer, { data }); Object.assign(newServer, { data });
await newServer.save(); await newServer.save();
return newServer; return newServer;

@ -29,17 +29,19 @@ export class CloudlyServerManager {
const serverId = requestData.serverId; const serverId = requestData.serverId;
const server = await this.CServer.getInstance({ const server = await this.CServer.getInstance({
id: serverId, id: serverId,
}) });
return { return {
configData: await server.createSavableObject(), configData: await server.createSavableObject(),
}; };
} },
) ),
); );
} }
public async start() { public async start() {
this.hetznerAccount = new plugins.hetznercloud.HetznerAccount(this.cloudlyRef.config.data.hetznerToken); this.hetznerAccount = new plugins.hetznercloud.HetznerAccount(
this.cloudlyRef.config.data.hetznerToken,
);
} }
public async stop() {} public async stop() {}
@ -66,16 +68,18 @@ export class CloudlyServerManager {
clusterId: cluster.id, clusterId: cluster.id,
priority: '1', priority: '1',
}, },
userData: await this.curlfreshInstance.getServerUserData() userData: await this.curlfreshInstance.getServerUserData(),
}); });
const newServer = await Server.createFromHetznerServer(server); const newServer = await Server.createFromHetznerServer(server);
console.log(`cluster created new server for cluster ${cluster.id}`); console.log(`cluster created new server for cluster ${cluster.id}`);
} else { } else {
console.log(`cluster ${cluster.id} already has servers. Making sure that they actually exist in the real world...`); console.log(
`cluster ${cluster.id} already has servers. Making sure that they actually exist in the real world...`,
);
// if there is a server, make sure that it exists // if there is a server, make sure that it exists
for (const server of servers) { for (const server of servers) {
const hetznerServer = await this.hetznerAccount.getServersByLabel({ const hetznerServer = await this.hetznerAccount.getServersByLabel({
'clusterId': cluster.id clusterId: cluster.id,
}); });
if (!hetznerServer) { if (!hetznerServer) {
console.log(`server ${server.id} does not exist in the real world. Creating it now...`); console.log(`server ${server.id} does not exist in the real world. Creating it now...`);
@ -86,7 +90,7 @@ export class CloudlyServerManager {
labels: { labels: {
clusterId: cluster.id, clusterId: cluster.id,
priority: '1', priority: '1',
} },
}); });
const newServer = await Server.createFromHetznerServer(hetznerServer); const newServer = await Server.createFromHetznerServer(hetznerServer);
} }
@ -99,7 +103,7 @@ export class CloudlyServerManager {
const results = await this.CServer.getInstances({ const results = await this.CServer.getInstances({
data: { data: {
assignedClusterId: clusterArg.id, assignedClusterId: clusterArg.id,
} },
}); });
return results; return results;
} }

@ -1,13 +1,14 @@
import * as plugins from '../plugins.js'; import * as plugins from '../plugins.js';
import { ServiceManager } from './classes.servicemanager.js'; import { ServiceManager } from './classes.servicemanager.js';
export class Service extends plugins.smartdata.SmartDataDbDoc<Service, plugins.servezoneInterfaces.data.IService, ServiceManager> { export class Service extends plugins.smartdata.SmartDataDbDoc<
Service,
plugins.servezoneInterfaces.data.IService,
ServiceManager
> {
@plugins.smartdata.svDb() @plugins.smartdata.svDb()
public id: string; public id: string;
@plugins.smartdata.svDb() @plugins.smartdata.svDb()
public data: plugins.servezoneInterfaces.data.IService['data']; public data: plugins.servezoneInterfaces.data.IService['data'];
} }

@ -16,7 +16,7 @@ export class ExternalApiManager {
return { return {
networkNodes, networkNodes,
}; };
}) }),
); );
} }
} }

@ -1,6 +1,9 @@
import * as plugins from './plugins.js'; import * as plugins from './plugins.js';
export const packageDir = plugins.path.join(plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url), '../'); export const packageDir = plugins.path.join(
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
'../',
);
export const nogitDir = plugins.path.join(packageDir, '.nogit/'); export const nogitDir = plugins.path.join(packageDir, '.nogit/');
export const dockerImageStoreDir = plugins.path.join(nogitDir, './dockerimagestore/'); export const dockerImageStoreDir = plugins.path.join(nogitDir, './dockerimagestore/');
export const distServeDir = plugins.path.join(packageDir, './dist_serve'); export const distServeDir = plugins.path.join(packageDir, './dist_serve');

@ -0,0 +1 @@
console.log('this is the cli client.');

@ -1,3 +1,8 @@
{ {
"name": "@serve.zone/cli" "name": "@serve.zone/cli",
"dependencies": [],
"registries": [
"registry.npmjs.org:public",
"verdaccio.lossless.digital:public"
]
} }

@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @push.rocks/commitinfo
*/
export const commitinfo = {
name: '@serve.zone/interfaces',
version: '1.1.2',
description: 'interfaces for working with containers'
}

@ -0,0 +1,16 @@
import * as plugins from '../plugins.js';
export interface ICloudlyConfig {
cfToken?: string;
hetznerToken?: string;
environment?: 'production' | 'integration';
letsEncryptEmail?: string;
letsEncryptPrivateKey?: string;
jwtKeypair?: plugins.tsclass.network.IJwtKeypair;
mongoDescriptor?: plugins.tsclass.database.IMongoDescriptor;
s3Descriptor?: plugins.tsclass.storage.IS3Descriptor;
publicUrl?: string;
publicPort?: string;
sslMode?: 'none' | 'letsencrypt' | 'external';
servezoneAdminaccount?: string;
}

@ -0,0 +1,36 @@
import * as plugins from '../plugins.js';
import { type IDockerRegistryInfo } from '../data/docker.js';
import type { IServer } from './server.js';
export interface ICluster {
id: string;
data: {
name: string;
/**
* a cluster has a machine user that governs access rights.
*/
userId: string;
/**
* how can the cluster reach cloudly
*/
cloudlyUrl?: string;
/**
* what servers are expected to be part of the cluster
*/
servers: IServer[];
/**
* ACME info. This is used to get SSL certificates.
*/
acmeInfo: {
serverAddress: string;
serverSecret: string;
};
sshKeys: plugins.tsclass.network.ISshKey[];
};
}

@ -0,0 +1 @@
export type TConfigType = 'server' | 'cluster' | 'coreflow' | 'service';

@ -0,0 +1,14 @@
import * as plugins from '../plugins.js';
/**
* results from a DeploymentDirective
* tracks the status of a deployment
*/
export interface IDeployment {
id: string;
deploymentDirectiveId: string;
affectedServiceIds: string[];
usedImageId: string;
deploymentLog: string[];
status: 'scheduled' | 'running' | 'deployed' | 'failed';
}

@ -0,0 +1,14 @@
import type { IServiceRessources } from "./docker.js";
/**
* used for tellilng a cluster about a disired deployment
* and specifies its configuration
*/
export interface IDeploymentDirective {
id: string;
name: string;
imageClaim: string;
ports: { hostPort: number; containerPort: number }[];
environment: { [key: string]: string };
resources?: IServiceRessources;
}

@ -0,0 +1,15 @@
import * as plugins from '../plugins.js';
export interface IDockerRegistryInfo {
serveraddress: string;
username: string;
password: string;
}
export interface IServiceRessources {
cpuLimit?: number;
cpuReservation?: number;
memorySizeLimitMB?: number;
memorySizeReservationMB?: number;
volumeMounts?: plugins.tsclass.container.IVolumeMount[];
}

@ -0,0 +1,6 @@
export interface IEnvBundle {
environment: string;
timeSensitive: boolean;
configKeyValueObject: {[key: string]: string};
}

@ -0,0 +1,11 @@
import * as plugins from '../plugins.js';
export interface IEvent_Cloudly_ContainerVersionNotification
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedEvent<plugins.tsclass.container.IContainer>,
IEvent_Cloudly_ContainerVersionNotification
> {
name: 'newContainerVersion';
uniqueEventId: string;
payload: plugins.tsclass.container.IContainer;
}

@ -0,0 +1,15 @@
import * as plugins from '../plugins.js';
export interface IImage {
id: string;
data: {
name: string;
description: string;
versions: Array<{
versionString: string;
storagePath?: string;
size: number;
createdAt: number;
}>;
};
}

@ -0,0 +1,17 @@
export * from './cloudlyconfig.js';
export * from './cluster.js';
export * from './config.js';
export * from './deployment.js';
export * from './deploymentdirective.js';
export * from './docker.js';
export * from './env.js';
export * from './event.js';
export * from './image.js';
export * from './secretbundle.js';
export * from './secretgroup.js'
export * from './server.js';
export * from './service.js';
export * from './status.js';
export * from './traffic.js';
export * from './user.js';
export * from './version.js';

@ -0,0 +1,42 @@
export interface ISecretBundle {
id: string;
data: {
name: string;
description: string;
/**
* determines if the secret is a service or an external secret
* if external secret additional checks are put in place to protect the secret
*/
type: 'service' | 'npmci' | 'gitzone' | 'external';
/**
* You can add specific secret groups using this
*/
includedSecretGroupIds: string[];
/**
* You can add specific tags using this
*/
includedTags: {
key: string;
value?: string;
}[];
/**
* add images
*/
includedImages: {
imageId: string;
permissions: ('read' | 'write')[];
}[];
/**
* authrozations select a specific environment of a config bundle
*/
authorizations: Array<{
secretAccessKey: string;
environment: string;
}>;
};
}

@ -0,0 +1,54 @@
export interface ISecretGroup {
/**
* the insatnce id. This should be a random id, except for default
*/
id: string;
data: {
name: string;
description: string;
/**
* the key of the secretgroup like CI_RUNNER_TOKEN
*/
key: string;
/**
* the priority of the secretgroup
* will be used to determine which secretgroup will be used
* when there are multiple secretgroups with the same key
*/
priority?: number;
/**
* any tags that can be used to filter the secretgroup
* can be used for putting secrets into projects
*/
tags: {
key: string;
value: string;
}[];
/**
* the values for this secretGroup
*/
environments: {
[key: string]: {
value: string;
/**
* can be used to update the value
*/
updateToken?: string;
/**
* the linux timestamp of the last update
*/
lastUpdated: number;
history: {
timestamp: string;
value: string;
}[];
};
};
};
}

@ -0,0 +1,36 @@
import * as plugins from '../plugins.js';
import { type IDockerRegistryInfo } from './docker.js';
export interface IServerMetrics {
serverId: string;
cpuUsageInPercent: number;
memoryUsageinMB: number;
memoryAvailableInMB: number;
containerCount: number;
containerMetrics: Array<{
containerId: string;
containerName: string;
cpuUsageInPercent: number;
memoryUsageInMB: number;
}>;
}
export interface IServer {
id: string;
data: {
type: 'baremetal' | 'hetzner';
assignedClusterId: string;
/**
* a list of debian packages to be installed
*/
requiredDebianPackages: string[];
/**
* a list of SSH keys to deploy
*/
sshKeys: plugins.tsclass.network.ISshKey[];
};
}

@ -0,0 +1,26 @@
import type { IServiceRessources } from './docker.js';
export interface IService {
id: string;
data: {
name: string;
imageId: string;
imageVersion: string;
environment: { [key: string]: string };
secretBundleId: string;
scaleFactor: number;
balancingStrategy: 'round-robin' | 'least-connections';
ports: {
web: number;
custom?: { [domain: string]: string };
};
resources?: IServiceRessources;
domains: {
name: string;
port?: number;
protocol?: 'http' | 'https' | 'ssh';
}[];
deploymentIds: string[];
deploymentDirectiveIds: string[];
};
}

@ -0,0 +1,20 @@
import * as plugins from '../plugins.js';
export interface IClusterStatus {
name: string;
ip: string;
nodesCount: number;
containersUnderManagementCount: number;
nodeStatusId: string;
containerStatusArray: IContainerStatus[];
}
export interface INodeStatus {
nodeId: string;
}
export interface IContainerStatus {
serviceName: string;
dockerImageUrl: string;
dockerImageVersion: string;
}

@ -0,0 +1,5 @@
import * as plugins from '../plugins.js';
interface IReverseProxyConfig extends plugins.tsclass.network.IReverseProxyConfig {}
export { type IReverseProxyConfig };

@ -0,0 +1,30 @@
export interface IToken {
token: string;
expiresAt: number;
assignedRoles: string[];
}
/**
* an identity is assumed by authentication as a user
* an identity is ephemeral and has to be renewed regularly
*/
export interface IIdentity {
name: string;
userId: string;
type: 'machine' | 'human';
role: 'admin' | 'user' | 'api' | 'cluster';
expiresAt: number;
/** the jwt token should contain above data for verification */
jwt: string;
}
export interface IUser {
id: string;
data: {
type: 'machine' | 'human';
role: 'admin' | 'user' | 'api' | 'cluster';
username?: string;
password?: string;
tokens?: IToken[];
}
}

@ -0,0 +1,11 @@
export interface IContainerVersionData {
/**
* the docker image url
* example: registry.gitlab.com/hosttoday/ht-docker-node:latest
*/
dockerImageUrl: string;
/**
* the docker image version. Note: This is different from docker tags that are often used for versions.
*/
dockerImageVersion: string;
}

9
ts_interfaces/index.ts Normal file

@ -0,0 +1,9 @@
import * as data from './data/index.js';
import * as platformservice from './platformservice/index.js';
import * as requests from './requests/index.js';
export {
data,
platformservice,
requests
}

@ -0,0 +1 @@
The platform folder contains types that can be used for talking with the underlying platform by apps running on serve.zone.

@ -0,0 +1,23 @@
import * as plugins from '../plugins.js';
export interface IChat {
systemMessage: string;
messages: {
role: 'assistant' | 'user';
content: string;
}[];
}
export interface IReq_Chat extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_Chat
> {
method: 'chat',
request: {
chat: IChat;
};
response: {
chat: IChat;
latestMessage: string;
}
}

@ -0,0 +1,13 @@
import * as aibridge from './aibridge.js';
import * as letter from './letter.js';
import * as mta from './mta.js';
import * as pushnotification from './pushnotification.js';
import * as sms from './sms.js';
export {
aibridge,
letter,
mta,
pushnotification,
sms,
}

@ -0,0 +1,34 @@
import * as plugins from '../plugins.js';
export interface IRequest_SendLetter extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_SendLetter
> {
method: 'sendLetter';
request: {
/**
* will be used in logs
*/
description: string;
/**
* if you send any PDF / invoice that you have not made sure to be letterxpress compliant
* we strongly recommend using a cover page
*/
needsCover: boolean;
title?: string;
from?: plugins.tsclass.business.IAddress;
to?: plugins.tsclass.business.IAddress;
coverBody?: string;
service: ('Einschreiben')[];
pdfAttachments?: Array<{
name: string;
binaryAttachmentString: string;
}>
};
response: {
/**
* this process id allows status retrieval of the letter
*/
processId: string;
};
}

@ -0,0 +1,39 @@
import * as plugins from '../plugins.js';
export type TTemplates = 'default' | 'linkaction' | 'notification';
export interface IRequest_SendEmail extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_SendEmail
> {
method: 'sendEmail';
request: {
title: string;
from: string;
to: string;
body: string;
attachments?: Array<{
name: string;
binaryAttachmentString: string;
}>
};
response: {
/**
* the response id allows for handling of responses to that email
*/
responseId: string;
};
}
export interface IRequestRegisterRecipient extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequestRegisterRecipient
> {
method: 'registerRecepient';
request: {
emailAddress: string;
};
response: {
status: 'ok' | 'not ok';
};
}

@ -0,0 +1,16 @@
import * as plugins from '../plugins.js';
export interface IRequest_SendPushNotification extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_SendPushNotification
> {
method: 'sendPushNotification';
request: {
deviceToken: string;
message: string;
}
response: {
ok: boolean;
status: string;
}
}

@ -0,0 +1,33 @@
import * as plugins from '../plugins.js';
export interface IRequest_SendSms
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_SendSms
> {
method: 'sendSms';
request: {
toNumber: number;
fromName: string;
messageText: string;
};
response: {
status: 'ok' | 'not ok';
}
}
export interface IRequest_SendVerificationCode
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_SendVerificationCode
> {
method: 'sendVerificationCode';
request: {
toNumber: number;
fromName: string;
};
response: {
status: 'ok' | 'not ok';
verificationCode: string;
}
}

20
ts_interfaces/plugins.ts Normal file

@ -0,0 +1,20 @@
// @apiglobal scope
import * as typedrequestInterfaces from '@api.global/typedrequest-interfaces';
export {
typedrequestInterfaces
}
// @push.rocks scope
import * as smartlogInterfaces from '@push.rocks/smartlog-interfaces';
export {
smartlogInterfaces,
}
// tsclass scope
import * as tsclass from '@tsclass/tsclass';
export {
tsclass
}

@ -0,0 +1,18 @@
import * as plugins from '../plugins.js';
import * as userInterfaces from '../data/user.js';
export interface IRequest_Any_Cloudly_GetCertificateForDomain
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_GetCertificateForDomain
> {
method: 'getCertificateForDomain';
request: {
identity: userInterfaces.IIdentity;
domainName: string;
type: 'ssl';
};
response: {
certificate: plugins.tsclass.network.ICert;
};
}

@ -0,0 +1,67 @@
import * as userInterfaces from '../data/user.js';
import * as clusterInterfaces from '../data/cluster.js';
import * as plugins from '../plugins.js';
/**
* get all clusters
*/
export interface IRequest_GetAllClusters extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_GetAllClusters
> {
method: 'getAllClusters';
request: {
identity: userInterfaces.IIdentity;
};
response: {
clusters: clusterInterfaces.ICluster[];
};
}
export interface IRequest_CreateCluster extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_CreateCluster
> {
method: 'createCluster';
request: {
identity: userInterfaces.IIdentity;
clusterName: string;
};
response: {
clusterConfig: clusterInterfaces.ICluster;
};
}
/**
* updates a cluster
*/
export interface IRequest_UpdateCluster extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_UpdateCluster
> {
method: 'updateCluster';
request: {
identity: userInterfaces.IIdentity;
clusterConfig: clusterInterfaces.ICluster;
};
response: {
clusterConfig: clusterInterfaces.ICluster;
};
}
/**
* deletes a cluster
*/
export interface IRequest_DeleteCluster extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_DeleteCluster
> {
method: 'deleteCluster';
request: {
identity: userInterfaces.IIdentity;
clusterId: string;
};
response: {
success: boolean;
};
}

@ -0,0 +1,49 @@
import * as plugins from '../plugins.js';
import * as clusterInterfaces from '../data/cluster.js';
import * as serverInterfaces from '../data/server.js';
import * as userInterfaces from '../data/user.js';
import type { IService } from '../data/service.js';
import type { IDeploymentDirective } from '../data/deploymentdirective.js';
export interface IRequest_Any_Cloudly_GetServerConfig
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_GetServerConfig
> {
method: 'getServerConfig';
request: {
identity: userInterfaces.IIdentity;
serverId: string;
};
response: {
configData: serverInterfaces.IServer;
};
}
export interface IRequest_Any_Cloudly_GetClusterConfig
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_GetClusterConfig
> {
method: 'getClusterConfig';
request: {
identity: userInterfaces.IIdentity;
};
response: {
configData: clusterInterfaces.ICluster;
deploymentDirectives: IDeploymentDirective[];
};
}
export interface IRequest_Cloudly_Coreflow_PushClusterConfig
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Cloudly_Coreflow_PushClusterConfig
> {
method: 'pushClusterConfig';
request: {
configData: clusterInterfaces.ICluster;
deploymentDirectives: IDeploymentDirective[];
};
response: {};
}

@ -0,0 +1,23 @@
import * as plugins from '../plugins.js';
import * as userInterfaces from '../data/user.js'
// ========
// IDENTITY
// ========
/**
* get the identity that then will be used to get the config
*/
export interface IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken
> {
method: 'getIdentityByToken';
request: {
token: string;
};
response: {
identity: userInterfaces.IIdentity;
};
}

@ -0,0 +1,94 @@
import * as plugins from '../plugins.js';
import * as userInterfaces from '../data/user.js';
import type { IImage } from '../data/index.js';
export interface IRequest_GetAllImages extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_GetAllImages
> {
method: 'getAllImages';
request: {
identity: userInterfaces.IIdentity;
};
response: {
images: IImage[];
};
}
/**
* gets a single image
*/
export interface IRequest_GetImage extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_GetImage
> {
method: 'getImage';
request: {
identity: userInterfaces.IIdentity;
imageId: string;
};
response: {
image: IImage;
};
}
export interface IRequest_CreateImage extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_CreateImage
> {
method: 'createImage';
request: {
identity: userInterfaces.IIdentity;
name: string;
description: string;
};
response: {
image: IImage;
};
}
export interface IRequest_PushImageVersion extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_PushImageVersion
> {
method: 'pushImageVersion';
request: {
identity: userInterfaces.IIdentity;
imageId: string;
versionString: string;
imageStream: plugins.typedrequestInterfaces.IVirtualStream;
};
response: {
allowed: boolean;
};
}
export interface IRequest_PullImageVersion extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_PullImageVersion
> {
method: 'pullImageVersion';
request: {
identity: userInterfaces.IIdentity;
imageId: string;
versionString: string;
};
response: {
imageStream: plugins.typedrequestInterfaces.IVirtualStream;
};
}
export interface IRequest_DeleteImage extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_DeleteImage
> {
method: 'deleteImage';
request: {
identity: userInterfaces.IIdentity;
imageId: string;
};
response: {
};
}

@ -0,0 +1,33 @@
import * as plugins from '../plugins.js';
import * as certificateRequests from './certificate.js';
import * as clusterRequests from './cluster.js';
import * as configRequests from './config.js';
import * as identityRequests from './identity.js';
import * as imageRequests from './image.js';
import * as informRequests from './inform.js';
import * as logRequests from './log.js';
import * as networkRequests from './network.js';
import * as routingRequests from './routing.js';
import * as secretRequests from './secret.js';
import * as serverRequests from './server.js';
import * as statusRequests from './status.js';
import * as versionRequests from './version.js';
export {
certificateRequests as certificate,
clusterRequests as cluster,
configRequests as config,
identityRequests as identity,
imageRequests as image,
informRequests as inform,
logRequests as log,
networkRequests as network,
routingRequests as routing,
secretRequests as secret,
serverRequests as server,
statusRequests as status,
versionRequests as version,
};
export * from './inform.js';

@ -0,0 +1,12 @@
import * as plugins from '../plugins.js';
export interface IRequest_InformAboutNewContainerImage extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_InformAboutNewContainerImage
> {
method: 'servezonestandard_InformAboutNewContainerVersion';
request: {
containerImageInfo: plugins.tsclass.container.IContainer
};
response: {};
}

@ -0,0 +1,13 @@
import * as plugins from '../plugins.js';
export interface IRequest_Log extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Log
> {
method: 'log';
request: {
authToken: string;
logPackages: plugins.smartlogInterfaces.ILogPackage[];
},
response: {};
}

@ -0,0 +1,9 @@
import * as plugins from '../plugins.js';
export interface IRequest_Any_Cloudly_GetNetworkNodes {
method: 'getNetworkNodes';
request: {};
response: {
networkNodes: plugins.tsclass.network.INetworkNode[];
};
}

@ -0,0 +1,12 @@
import { type IReverseProxyConfig } from '../data/traffic.js';
export interface IRequest_Coreflow_Coretraffic_RoutingUpdate {
method: 'updateRouting';
request: {
reverseConfigs: IReverseProxyConfig[];
};
response: {
status: 'ok' | 'error';
errorText: string;
};
}

@ -0,0 +1,94 @@
import * as plugins from '../plugins.js';
import * as data from '../data/index.js';
import * as userInterfaces from '../data/user.js';
export interface IReq_GetEnvBundle extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetEnvBundle
> {
method: 'getEnvBundle';
request: {
authorization: string;
/**
* specify this if you want to get a warning, if the envBundle is for an unexpected environment
*/
environment?: string;
};
response: {
envBundle: data.IEnvBundle;
};
}
export interface IReq_Admin_LoginWithUsernameAndPassword extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_Admin_LoginWithUsernameAndPassword
> {
method: 'adminLoginWithUsernameAndPassword';
request: {
username: string;
password: string;
};
response: {
identity: userInterfaces.IIdentity;
}
}
export interface IReq_Admin_GetConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_Admin_GetConfigBundlesAndSecretGroups
> {
method: 'adminGetConfigBundlesAndSecretGroups';
request: {
identity: userInterfaces.IIdentity;
};
response: {
secretBundles: data.ISecretBundle[];
secretGroups: data.ISecretGroup[];
};
}
export interface IReq_Admin_CreateConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_Admin_CreateConfigBundlesAndSecretGroups
> {
method: 'adminCreateConfigBundlesAndSecretGroups';
request: {
identity: userInterfaces.IIdentity;
secretBundles: data.ISecretBundle[];
secretGroups: data.ISecretGroup[];
};
response: {
ok: boolean;
};
}
export interface IReq_Admin_UpdateConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_Admin_UpdateConfigBundlesAndSecretGroups
> {
method: 'adminUpdateConfigBundlesAndSecretGroups';
request: {
identity: userInterfaces.IIdentity;
configBundles: data.ISecretBundle[];
secretGroups: data.ISecretGroup[];
};
response: {
ok: boolean;
};
}
export interface IReq_Admin_DeleteConfigBundlesAndSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_Admin_DeleteConfigBundlesAndSecretGroups
> {
method: 'adminDeleteConfigBundlesAndSecretGroups';
request: {
identity: userInterfaces.IIdentity;
secretBundleIds: string[];
secretGroupIds: string[];
};
response: {
ok: boolean;
};
}

@ -0,0 +1,47 @@
import type { IServerMetrics } from '../data/server.js';
import * as plugins from '../plugins.js';
/**
* This request can be used between any two players
* Examples:
* WebApp -> Cloudly (get metrics)
* Cloudly -> Webapp (send metrics)
* Cloudly -> Coreflow (get metrics)
* Coreflow -> Cloudly (send metrics)
*/
export interface IRequest_Any_Cloudly_ServerStatus
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_ServerStatus
> {
method: 'getOrSendServerMetrics',
request: {
getOrSend: 'get' | 'send';
serverMetrics?: IServerMetrics;
},
response: {
serverMetrics?: IServerMetrics;
},
}
/**
* this request can be used between any two players
* Examples:
* WebApp -> Cloudly
* Cloudly -> Coreflow
* Cloudly -> HostingProvider
*/
export interface IRequest_TriggerServerAction
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_TriggerServerAction
> {
method: 'triggerServerAction';
request: {
actionName: 'reboot' | 'rebuild';
payload: any;
};
response: {
actionConfirmed: boolean;
};
}

@ -0,0 +1,12 @@
import * as userInterfaces from '../data/user.js';
/**
* a status update dashboard
*/
export interface IRequest_Coreflow_Cloudly_CoreflowManagerStatusupdate {
method: 'cloudlyStatus';
request: {
identity: userInterfaces.IIdentity;
};
response: {};
}

@ -0,0 +1,8 @@
import * as versionInterfaces from '../data/version.js';
// Containers
export interface IRequest_Any_Cloudly_VersionManager_InformCloudlyAboutNewContainerVersion {
method: 'informCloudlyAboutNewContainerVersion';
request: versionInterfaces.IContainerVersionData;
response: {};
}

@ -1,6 +1,8 @@
{ {
"name": "@serve.zone/interfaces", "name": "@serve.zone/interfaces",
"dependencies": [ "dependencies": [
"@api.global/typedrequest-interfaces",
"@push.rocks/smartlog-interfaces",
"@tsclass/tsclass" "@tsclass/tsclass"
], ],
"registries": [ "registries": [

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/cloudly', name: '@serve.zone/cloudly',
version: '1.2.1', version: '4.1.1',
description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.' description: 'A comprehensive multi-cloud manager leveraging Docker Swarmkit to orchestrate containerized applications across various cloud services and provide robust configuration and API integration.'
} }

@ -6,7 +6,19 @@
"module": "NodeNext", "module": "NodeNext",
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
"esModuleInterop": true, "esModuleInterop": true,
"verbatimModuleSyntax": true "verbatimModuleSyntax": true,
"baseUrl": ".",
"paths": {
"@serve.zone/api": [
"./ts_apiclient/index.ts"
],
"@serve.zone/cli": [
"./ts_cliclient/index.ts"
],
"@serve.zone/interfaces": [
"./ts_interfaces/index.ts"
]
}
}, },
"exclude": [ "exclude": [
"dist_*/**/*.d.ts" "dist_*/**/*.d.ts"