Compare commits

..

18 Commits

Author SHA1 Message Date
7654d780b1 4.7.1
Some checks failed
Docker (tags) / security (push) Successful in 1m10s
Docker (tags) / test (push) Successful in 3m1s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 23s
2024-12-28 19:50:30 +01:00
dbd9b661c6 fix(secretmanagement): Refactor secret bundle actions and improve authorization handling 2024-12-28 19:50:29 +01:00
e19d0b4deb 4.7.0
Some checks failed
Docker (tags) / security (push) Successful in 53s
Docker (tags) / test (push) Successful in 3m3s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 22s
2024-12-22 20:09:23 +01:00
f0ebb719f7 feat(apiclient): Add method to flatten secret bundles into key-value objects. 2024-12-22 20:09:23 +01:00
c8e0666bc6 4.6.0
Some checks failed
Docker (tags) / security (push) Successful in 54s
Docker (tags) / test (push) Successful in 3m0s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 23s
2024-12-22 20:03:11 +01:00
0d0b106f90 feat(cloudlyapiclient): Extend CloudlyApiClient with cluster, secretbundle, and secretgroup methods 2024-12-22 20:03:11 +01:00
c9073df7cd 4.5.5
Some checks failed
Docker (tags) / security (push) Successful in 1m4s
Docker (tags) / test (push) Successful in 3m0s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 23s
2024-12-22 19:55:56 +01:00
f65200703d fix(apiclient): Fixed image creation method in cloudlyApiClient 2024-12-22 19:55:56 +01:00
57970b3d10 4.5.4
Some checks failed
Docker (tags) / security (push) Successful in 1m6s
Docker (tags) / test (push) Successful in 2m58s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 23s
2024-12-21 22:14:45 +01:00
b4d9f40c41 fix(ts_web): Fix action type and data fields in appstate for CRUD operations 2024-12-21 22:14:45 +01:00
a219725ff6 4.5.3
Some checks failed
Docker (tags) / security (push) Successful in 1m6s
Docker (tags) / test (push) Successful in 2m58s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 23m54s
2024-12-21 20:21:54 +01:00
4b993fc6b3 fix(secret-management): Refactor secret management to use distinct secret bundle and group APIs. Introduce API client classes for secret bundles and groups. 2024-12-21 20:21:54 +01:00
d453da709f 4.5.2
Some checks failed
Docker (tags) / security (push) Successful in 1m4s
Docker (tags) / test (push) Successful in 2m58s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 23m21s
2024-12-20 02:13:50 +01:00
50fac41c95 fix(apiclient): Implemented IService interface in Service class and improved secret bundle documentation. 2024-12-20 02:13:50 +01:00
affce1fcd1 4.5.1
Some checks failed
Docker (tags) / security (push) Successful in 1m4s
Docker (tags) / test (push) Successful in 3m4s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 16s
2024-12-17 19:51:11 +01:00
df67ebd27a fix(core): Updated dependencies in package.json to latest versions. 2024-12-17 19:51:10 +01:00
ef5bfd435a 4.5.0
Some checks failed
Docker (tags) / security (push) Successful in 1m8s
Docker (tags) / test (push) Successful in 3m5s
Docker (tags) / metadata (push) Successful in 7s
Docker (tags) / release (push) Failing after 23m36s
2024-12-14 20:32:17 +01:00
db07db930c feat(services): Add service management functionalities 2024-12-14 20:32:17 +01:00
28 changed files with 8343 additions and 5048 deletions

View File

@ -1,5 +1,70 @@
# Changelog # Changelog
## 2024-12-28 - 4.7.1 - fix(secretmanagement)
Refactor secret bundle actions and improve authorization handling
- Refactored secret bundle handling by renaming methods and reorganizing static and instance methods in SecretBundle class.
- Added getSecretBundleByAuthorization method to SecretBundle.
- Improved getFlatKeyValueObjectForEnvironment to accurately retrieve key-value pairs for specified environments.
- Removed deprecated IEnvBundle interface and related request handler for better clarity and code usage.
- Updated request interfaces related to secret bundles for consistent method naming and arguments.
## 2024-12-22 - 4.7.0 - feat(apiclient)
Add method to flatten secret bundles into key-value objects.
- SecretBundle: Implemented toFlatKeyValueObject method to flatten secret groups into key-value pairs.
- Removed stale SecretManager class from apiclient.
## 2024-12-22 - 4.6.0 - feat(cloudlyapiclient)
Extend CloudlyApiClient with cluster, secretbundle, and secretgroup methods
- Added methods to CloudlyApiClient for managing clusters: getClusterById, getClusters, createCluster.
- Added methods to CloudlyApiClient for managing secret bundles: getSecretBundleById, getSecretBundles, createSecretBundle.
- Added methods to CloudlyApiClient for managing secret groups: getSecretGroupById, getSecretGroups, createSecretGroup.
## 2024-12-22 - 4.5.5 - fix(apiclient)
Fixed image creation method in cloudlyApiClient
- Corrected method call from 'images.createImage' to 'image.createImage' to ensure proper image creation.
- Updated cluster retrieval methods and ensured proper API routes are being called.
## 2024-12-21 - 4.5.4 - fix(ts_web)
Fix action type and data fields in appstate for CRUD operations
- Correct request method in createSecretGroupAction to accurately reflect the purpose.
- Align the deleteSecretGroupAction and deleteSecretBundleAction request types with proper interfaces.
- Ensure data payload matches backend requirements for secret group and secret bundle operations.
## 2024-12-21 - 4.5.3 - fix(secret-management)
Refactor secret management to use distinct secret bundle and group APIs. Introduce API client classes for secret bundles and groups.
- Updated secret management logic to separate secret bundle and group APIs.
- Implemented new API client classes for managing secret bundles and groups.
- Fixed incorrect method usages for secret-related actions.
## 2024-12-20 - 4.5.2 - fix(apiclient)
Implemented IService interface in Service class and improved secret bundle documentation.
- Implemented plugins.servezoneInterfaces.data.IService interface in the Service class within ts_apiclient.
- Updated documentation comments for the type property in the ISecretBundle interface.
## 2024-12-17 - 4.5.1 - fix(core)
Updated dependencies in package.json to latest versions.
- Bumped @git.zone/tswatch to version ^2.0.37
- Bumped @types/node to version ^22.10.2
- Bumped @design.estate/dees-catalog to version ^1.3.2
- Bumped @push.rocks/smartfile to version ^11.0.23
- Bumped @tsclass/tsclass to version ^4.2.0
## 2024-12-14 - 4.5.0 - feat(services)
Add service management functionalities
- Integrated service-related API client methods including getServices, getServiceById, and createService.
- Updated the deployment data structure in the service manager.
- Enhanced service interface to incorporate additional fields for comprehensive data handling.
- Ensured secure token generation for Cloudly authentication processes.
## 2024-11-18 - 4.4.0 - feat(api-client) ## 2024-11-18 - 4.4.0 - feat(api-client)
Add static method getImageById for Image class in api-client Add static method getImageById for Image class in api-client

View File

@ -1,6 +1,6 @@
{ {
"name": "@serve.zone/cloudly", "name": "@serve.zone/cloudly",
"version": "4.4.0", "version": "4.7.1",
"private": false, "private": false,
"description": "A comprehensive tool for managing containerized applications across multiple cloud providers using Docker Swarmkit, featuring web, CLI, and API interfaces.", "description": "A comprehensive tool for managing containerized applications across multiple cloud providers using Docker Swarmkit, featuring web, CLI, and API interfaces.",
"type": "module", "type": "module",
@ -27,9 +27,9 @@
"@git.zone/tsdoc": "^1.4.2", "@git.zone/tsdoc": "^1.4.2",
"@git.zone/tspublish": "^1.7.7", "@git.zone/tspublish": "^1.7.7",
"@git.zone/tstest": "^1.0.90", "@git.zone/tstest": "^1.0.90",
"@git.zone/tswatch": "^2.0.25", "@git.zone/tswatch": "^2.0.37",
"@push.rocks/tapbundle": "^5.5.0", "@push.rocks/tapbundle": "^5.5.3",
"@types/node": "^22.9.0" "@types/node": "^22.10.2"
}, },
"dependencies": { "dependencies": {
"@api.global/typedrequest": "3.1.10", "@api.global/typedrequest": "3.1.10",
@ -40,23 +40,23 @@
"@apiclient.xyz/docker": "^1.2.7", "@apiclient.xyz/docker": "^1.2.7",
"@apiclient.xyz/hetznercloud": "^1.2.0", "@apiclient.xyz/hetznercloud": "^1.2.0",
"@apiclient.xyz/slack": "^3.0.9", "@apiclient.xyz/slack": "^3.0.9",
"@design.estate/dees-catalog": "^1.3.1", "@design.estate/dees-catalog": "^1.3.2",
"@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.3.3", "@git.zone/tsrun": "^1.3.3",
"@push.rocks/early": "^4.0.3", "@push.rocks/early": "^4.0.3",
"@push.rocks/npmextra": "^5.1.2", "@push.rocks/npmextra": "^5.1.2",
"@push.rocks/projectinfo": "^5.0.1", "@push.rocks/projectinfo": "^5.0.1",
"@push.rocks/qenv": "^6.0.5", "@push.rocks/qenv": "^6.1.0",
"@push.rocks/smartacme": "^5.0.0", "@push.rocks/smartacme": "^5.0.0",
"@push.rocks/smartbucket": "^3.0.23", "@push.rocks/smartbucket": "^3.3.7",
"@push.rocks/smartcli": "^4.0.11", "@push.rocks/smartcli": "^4.0.11",
"@push.rocks/smartclickhouse": "^2.0.17", "@push.rocks/smartclickhouse": "^2.0.17",
"@push.rocks/smartdata": "^5.2.10", "@push.rocks/smartdata": "^5.2.10",
"@push.rocks/smartdelay": "^3.0.5", "@push.rocks/smartdelay": "^3.0.5",
"@push.rocks/smartexit": "^1.0.23", "@push.rocks/smartexit": "^1.0.23",
"@push.rocks/smartexpect": "^1.2.1", "@push.rocks/smartexpect": "^1.2.1",
"@push.rocks/smartfile": "^11.0.21", "@push.rocks/smartfile": "^11.0.23",
"@push.rocks/smartguard": "^3.1.0", "@push.rocks/smartguard": "^3.1.0",
"@push.rocks/smartjson": "^5.0.19", "@push.rocks/smartjson": "^5.0.19",
"@push.rocks/smartjwt": "^2.2.1", "@push.rocks/smartjwt": "^2.2.1",
@ -69,12 +69,12 @@
"@push.rocks/smartrx": "^3.0.7", "@push.rocks/smartrx": "^3.0.7",
"@push.rocks/smartssh": "^2.0.1", "@push.rocks/smartssh": "^2.0.1",
"@push.rocks/smartstate": "^2.0.19", "@push.rocks/smartstate": "^2.0.19",
"@push.rocks/smartstream": "^3.2.4", "@push.rocks/smartstream": "^3.2.5",
"@push.rocks/smartstring": "^4.0.15", "@push.rocks/smartstring": "^4.0.15",
"@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",
"@tsclass/tsclass": "^4.1.2" "@tsclass/tsclass": "^4.2.0"
}, },
"files": [ "files": [
"ts/**/*", "ts/**/*",

12129
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -57,7 +57,7 @@ tap.test('should get an identity', async () => {
let image: Image; let image: Image;
tap.test('should create and upload an image', async () => { tap.test('should create and upload an image', async () => {
image = await testClient.images.createImage({ image = await testClient.image.createImage({
name: 'test', name: 'test',
description: 'test' description: 'test'
}); });

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/cloudly', name: '@serve.zone/cloudly',
version: '4.4.0', version: '4.7.1',
description: 'A comprehensive tool for managing containerized applications across multiple cloud providers using Docker Swarmkit, featuring web, CLI, and API interfaces.' description: 'A comprehensive tool for managing containerized applications across multiple cloud providers using Docker Swarmkit, featuring web, CLI, and API interfaces.'
} }

View File

@ -38,12 +38,12 @@ export class ClusterManager {
console.log(await cluster.createSavableObject()); console.log(await cluster.createSavableObject());
this.cloudlyRef.serverManager.ensureServerInfrastructure(); this.cloudlyRef.serverManager.ensureServerInfrastructure();
return { return {
clusterConfig: await cluster.createSavableObject(), cluster: await cluster.createSavableObject(),
}; };
}), }),
); );
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_GetAllClusters>( this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_GetClusters>(
new plugins.typedrequest.TypedHandler('getAllClusters', async (dataArg) => { new plugins.typedrequest.TypedHandler('getAllClusters', async (dataArg) => {
// TODO: do authentication here // TODO: do authentication here
const clusters = await this.getAllClusters(); const clusters = await this.getAllClusters();
@ -56,7 +56,7 @@ export class ClusterManager {
); );
// delete cluster // delete cluster
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IRequest_DeleteCluster>( this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_DeleteClusterById>(
new plugins.typedrequest.TypedHandler('deleteCluster', async (reqDataArg, toolsArg) => { new plugins.typedrequest.TypedHandler('deleteCluster', async (reqDataArg, toolsArg) => {
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqDataArg); await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqDataArg);
await this.deleteCluster(reqDataArg.clusterId); await this.deleteCluster(reqDataArg.clusterId);

View File

@ -35,20 +35,71 @@ export class CloudlySecretManager {
this.typedrouter = new plugins.typedrequest.TypedRouter(); this.typedrouter = new plugins.typedrequest.TypedRouter();
this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter); this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter);
this.typedrouter.addTypedHandler( // secretbundle routes
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_GetConfigBundlesAndSecretGroups>( this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_GetSecretBundles>(
'adminGetConfigBundlesAndSecretGroups', new plugins.typedrequest.TypedHandler(
'getSecretBundles',
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({});
return { return {
secretBundles: [ secretBundles: [
...(await Promise.all( ...(await Promise.all(
secretBundles.map((configBundle) => configBundle.createSavableObject()), secretBundles.map((configBundle) => configBundle.createSavableObject()),
)), )),
], ],
};
},
),
);
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_CreateSecretBundle>(
new plugins.typedrequest.TypedHandler('createSecretBundle', async (dataArg) => {
const secretBundle = new SecretBundle();
secretBundle.id = plugins.smartunique.shortId(8);
secretBundle.data = dataArg.secretBundle.data;
await secretBundle.save();
return {
resultSecretBundle: await secretBundle.createSavableObject(),
};
}),
);
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_UpdateSecretBundle>(
new plugins.typedrequest.TypedHandler('updateSecretBundle', async (dataArg) => {
const secretBundle = await SecretBundle.getInstance({
id: dataArg.secretBundle.id,
});
secretBundle.data = dataArg.secretBundle.data;
await secretBundle.save();
return {
resultSecretBundle: await secretBundle.createSavableObject(),
};
}),
);
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_DeleteSecretBundleById>(
new plugins.typedrequest.TypedHandler('deleteSecretBundleById', async (dataArg) => {
const secretBundle = await SecretBundle.getInstance({
id: dataArg.secretBundleId,
});
await secretBundle.delete();
return {
ok: true,
};
}),
);
// secretgroup routes
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretgroup.IReq_GetSecretGroups>(
new plugins.typedrequest.TypedHandler(
'getSecretGroups',
async (dataArg, toolsArg) => {
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
dataArg.identity.jwt;
const secretGroups = await SecretGroup.getInstances({});
return {
secretGroups: [ secretGroups: [
...(await Promise.all( ...(await Promise.all(
secretGroups.map((secretGroup) => secretGroup.createSavableObject()), secretGroups.map((secretGroup) => secretGroup.createSavableObject()),
@ -59,73 +110,64 @@ export class CloudlySecretManager {
), ),
); );
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_CreateConfigBundlesAndSecretGroups>( this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretgroup.IReq_CreateSecretGroup>(
new plugins.typedrequest.TypedHandler( new plugins.typedrequest.TypedHandler('createSecretGroup', async (dataArg) => {
'adminCreateConfigBundlesAndSecretGroups', const secretGroup = new SecretGroup();
async (dataArg) => { secretGroup.id = plugins.smartunique.shortId(8);
for (const secretGroupObject of dataArg.secretGroups) { secretGroup.data = dataArg.secretGroup.data;
const secretGroup = new SecretGroup(); await secretGroup.save();
secretGroup.id = plugins.smartunique.shortId(8); return {
secretGroup.data = secretGroupObject.data; resultSecretGroup: await secretGroup.createSavableObject(),
await secretGroup.save(); };
} }),
return { );
ok: true,
}; this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretgroup.IReq_UpdateSecretGroup>(
}, new plugins.typedrequest.TypedHandler('updateSecretGroup', async (dataArg) => {
), const secretGroup = await SecretGroup.getInstance({
id: dataArg.secretGroup.id,
});
secretGroup.data = dataArg.secretGroup.data;
await secretGroup.save();
return {
resultSecretGroup: await secretGroup.createSavableObject(),
};
}),
);
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretgroup.IReq_DeleteSecretGroupById>(
new plugins.typedrequest.TypedHandler('deleteSecretGroupById', async (dataArg) => {
const secretGroup = await SecretGroup.getInstance({
id: dataArg.secretGroupId,
});
await secretGroup.delete();
return {
ok: true,
};
}),
); );
this.typedrouter.addTypedHandler( this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_DeleteConfigBundlesAndSecretGroups>( new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_GetFlatKeyValueObject>(
'adminDeleteConfigBundlesAndSecretGroups', 'getFlatKeyValueObject',
async (dataArg) => {
for (const secretGroupId of dataArg.secretGroupIds) {
const secretGroup = await SecretGroup.getInstance({
id: secretGroupId,
});
await secretGroup.delete();
}
for (const secretBundleId of dataArg.secretBundleIds) {
const configBundle = await SecretBundle.getInstance({
id: secretBundleId,
});
await configBundle.delete();
console.log(`deleted configbundle ${secretBundleId}`);
}
return {
ok: true,
};
},
),
);
// lets add typedrouter routes for accessing the configvailt from apps
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_GetEnvBundle>(
'getEnvBundle',
async (dataArg) => { async (dataArg) => {
const wantedBundle = await SecretBundle.getInstance({ const wantedBundle = await SecretBundle.getInstance({
data: { data: {
authorizations: { authorizations: {
// @ts-ignore // @ts-ignore
$elemMatch: { $elemMatch: {
secretAccessKey: dataArg.authorization, secretAccessKey: dataArg.secretBundleAuthorization.secretAccessKey,
}, },
}, },
}, },
}); });
const authorization = await wantedBundle.getAuthorizationFromAuthKey( const authorization = await wantedBundle.getAuthorizationFromAuthKey(
dataArg.authorization, dataArg.secretBundleAuthorization.secretAccessKey,
); );
return { return {
envBundle: { flatKeyValueObject: await wantedBundle.getKeyValueObjectForEnvironment(
configKeyValueObject: await wantedBundle.getKeyValueObjectForEnvironment( authorization.environment,
authorization.environment, ),
),
environment: authorization.environment,
timeSensitive: false,
},
}; };
}, },
), ),

View File

@ -14,5 +14,26 @@ export class ServiceManager {
constructor(cloudlyRef: Cloudly) { constructor(cloudlyRef: Cloudly) {
this.cloudlyRef = cloudlyRef; this.cloudlyRef = cloudlyRef;
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.service.IRequest_Any_Cloudly_GetServices>(
'getServices',
async (reqArg) => {
await plugins.smartguard.passGuardsOrReject(reqArg, [
this.cloudlyRef.authManager.validIdentityGuard,
]);
const services = await this.CService.getInstances({});
return {
services: await Promise.all(
services.map((service) => {
return service.createSavableObject();
})
),
};
}
)
);
} }
} }

View File

@ -3,6 +3,10 @@ import * as plugins from './plugins.js';
export type TClientType = 'api' | 'ci' | 'coreflow' | 'cli' | 'serverconfig'; export type TClientType = 'api' | 'ci' | 'coreflow' | 'cli' | 'serverconfig';
import { Image } from './classes.image.js'; import { Image } from './classes.image.js';
import { Service } from './classes.service.js';
import { Cluster } from './classes.cluster.js';
import { SecretBundle } from './classes.secretbundle.js';
import { SecretGroup } from './classes.secretgroup.js';
export class CloudlyApiClient { export class CloudlyApiClient {
private cloudlyUrl: string; private cloudlyUrl: string;
@ -155,7 +159,7 @@ export class CloudlyApiClient {
return typedResponse.certificate; return typedResponse.certificate;
} }
public images = { public image = {
// Images // Images
getImageById: async (imageIdArg: string) => { getImageById: async (imageIdArg: string) => {
return Image.getImageById(this, imageIdArg); return Image.getImageById(this, imageIdArg);
@ -167,4 +171,56 @@ export class CloudlyApiClient {
return Image.createImage(this, optionsArg); return Image.createImage(this, optionsArg);
} }
} }
public services = {
// Services
getServiceById: async (serviceIdArg: string) => {
return Service.getServiceById(this, serviceIdArg);
},
getServices: async () => {
return Service.getServices(this);
},
createService: async (optionsArg: Parameters<typeof Service.createService>[1]) => {
return Service.createService(this, optionsArg);
}
}
public cluster = {
// Clusters
getClusterById: async (clusterIdArg: string) => {
return Cluster.getClusterById(this, clusterIdArg);
},
getClusters: async () => {
return Cluster.getClusters(this);
},
createCluster: async (optionsArg: Parameters<typeof Cluster.createCluster>[1]) => {
return Cluster.createCluster(this, optionsArg);
}
}
public secretbundle = {
// SecretBundles
getSecretBundleById: async (secretBundleIdArg: string) => {
return SecretBundle.getSecretBundleById(this, secretBundleIdArg);
},
getSecretBundles: async () => {
return SecretBundle.getSecretBundles(this);
},
createSecretBundle: async (optionsArg: Parameters<typeof SecretBundle.createSecretBundle>[1]) => {
return SecretBundle.createSecretBundle(this, optionsArg);
}
}
public secretgroup = {
// SecretGroups
getSecretGroupById: async (secretGroupIdArg: string) => {
return SecretGroup.getSecretGroupById(this, secretGroupIdArg);
},
getSecretGroups: async () => {
return SecretGroup.getSecretGroups(this);
},
createSecretGroup: async (optionsArg: Parameters<typeof SecretGroup.createSecretGroup>[1]) => {
return SecretGroup.createSecretGroup(this, optionsArg);
}
}
} }

View File

@ -1,6 +1,84 @@
import { CloudlyApiClient } from './classes.cloudlyapiclient.js';
import * as plugins from './plugins.js'; import * as plugins from './plugins.js';
export class Cluster { export class Cluster implements plugins.servezoneInterfaces.data.ICluster {
public getServers() {} // STATIC
public static async getClusterById(cloudlyClientRef: CloudlyApiClient, clusterIdArg: string) {
const getClusterByIdTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_GetClusterById>(
'getClusterById'
);
const response = await getClusterByIdTR.fire({
identity: cloudlyClientRef.identity,
clusterId: clusterIdArg,
});
const newCluster = new Cluster(cloudlyClientRef);
Object.assign(newCluster, response.cluster);
return newCluster;
}
public static async getClusters(cloudlyClientRef: CloudlyApiClient) {
const getClustersTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_GetClusters>(
'getClusters'
);
const response = await getClustersTR.fire({
identity: cloudlyClientRef.identity,
});
const clusterConfigs: Cluster[] = [];
for (const clusterConfig of response.clusters) {
const newCluster = new Cluster(cloudlyClientRef);
Object.assign(newCluster, clusterConfig);
clusterConfigs.push(newCluster);
}
return clusterConfigs;
}
public static async createCluster(cloudlyClientRef: CloudlyApiClient, clusterNameArg: string) {
const createClusterTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.cluster.IRequest_CreateCluster>(
'createCluster'
);
const response = await createClusterTR.fire({
identity: cloudlyClientRef.identity,
clusterName: clusterNameArg,
});
const newCluster = new Cluster(cloudlyClientRef);
Object.assign(newCluster, response.cluster);
return newCluster;
}
// INSTANCE
public id: string;
public data: plugins.servezoneInterfaces.data.ICluster['data'];
public cloudlyClientRef: CloudlyApiClient;
constructor(cloudlyClientRef: CloudlyApiClient) {
this.cloudlyClientRef = cloudlyClientRef;
}
public async update() {
const updateClusterTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_UpdateCluster>(
'updateCluster'
);
const response = await updateClusterTR.fire({
identity: this.cloudlyClientRef.identity,
clusterData: this.data,
});
const resultClusterData = response.resultCluster.data;
plugins.smartexpect.expect(resultClusterData).toEqual(this.data);
return this;
}
public async delete(cloudlyClientRef: CloudlyApiClient, clusterIdArg: string) {
const deleteClusterTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.cluster.IReq_Any_Cloudly_DeleteClusterById>(
'deleteClusterById'
);
const response = await deleteClusterTR.fire({
identity: cloudlyClientRef.identity,
clusterId: this.id,
});
plugins.smartexpect.expect(response.ok).toBeTrue();
return null;
}
} }

View File

@ -0,0 +1,135 @@
import * as plugins from './plugins.js';
import type { CloudlyApiClient } from './classes.cloudlyapiclient.js';
import { SecretGroup } from './classes.secretgroup.js';
export class SecretBundle implements plugins.servezoneInterfaces.data.ISecretBundle {
// STATIC
public static async getSecretBundleById(cloudlyClientRef: CloudlyApiClient, secretBundleIdArg: string) {
const getSecretBundleByIdTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretbundle.IReq_GetSecretBundleById>(
'getSecretBundleById'
);
const response = await getSecretBundleByIdTR.fire({
identity: cloudlyClientRef.identity,
secretBundleId: secretBundleIdArg,
});
const newSecretBundle = new SecretBundle(cloudlyClientRef);
Object.assign(newSecretBundle, response.secretBundle);
return newSecretBundle;
}
public static async getSecretBundleByAuthorization(cloudlyClientRef: CloudlyApiClient, secretBundleAuthorizationArg: plugins.servezoneInterfaces.data.ISecretBundleAuthorization) {
const getSecretBundleByAuthorizationTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretbundle.IReq_GetSecretBundleByAuthorization>(
'getSecretBundleByAuthorization'
);
const response = await getSecretBundleByAuthorizationTR.fire({
identity: cloudlyClientRef.identity,
secretBundleAuthorization: secretBundleAuthorizationArg,
});
const newSecretBundle = new SecretBundle(cloudlyClientRef);
Object.assign(newSecretBundle, response.secretBundle);
return newSecretBundle;
}
public static async getSecretBundles(cloudlyClientRef: CloudlyApiClient) {
const getSecretBundlesTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretbundle.IReq_GetSecretBundles>(
'getSecretBundles'
);
const response = await getSecretBundlesTR.fire({
identity: cloudlyClientRef.identity,
});
const secretBundles: SecretBundle[] = [];
for (const secretBundle of response.secretBundles) {
const newSecretBundle = new SecretBundle(cloudlyClientRef);
Object.assign(newSecretBundle, secretBundle);
secretBundles.push(newSecretBundle);
}
return secretBundles;
}
public static async createSecretBundle(cloudlyClientRef: CloudlyApiClient, secretBundleDataArg: Partial<plugins.servezoneInterfaces.data.ISecretBundle['data']>) {
const createSecretBundleTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretbundle.IReq_CreateSecretBundle>(
'createSecretBundle'
);
const response = await createSecretBundleTR.fire({
identity: cloudlyClientRef.identity,
secretBundle: {
id: null,
data: {
name: secretBundleDataArg.name,
description: secretBundleDataArg.description,
type: secretBundleDataArg.type,
authorizations: secretBundleDataArg.authorizations,
includedImages: secretBundleDataArg.includedImages,
includedSecretGroupIds: secretBundleDataArg.includedSecretGroupIds,
includedTags: secretBundleDataArg.includedTags,
},
},
});
const newSecretBundle = new SecretBundle(cloudlyClientRef);
Object.assign(newSecretBundle, response.resultSecretBundle);
return newSecretBundle;
}
// INSTANCE
public cloudlyClientRef: CloudlyApiClient;
public id: string;
public data: plugins.servezoneInterfaces.data.ISecretBundle['data'];
constructor(cloudlyClientRef: CloudlyApiClient) {
this.cloudlyClientRef = cloudlyClientRef;
}
public async update() {
const updateSecretBundleTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretbundle.IReq_UpdateSecretBundle>(
'updateSecretBundle'
);
const response = await updateSecretBundleTR.fire({
identity: this.cloudlyClientRef.identity,
secretBundle: {
id: this.id,
data: this.data,
},
});
const resultSecretBundleData = response.resultSecretBundle.data;
plugins.smartexpect.expect(resultSecretBundleData).toEqual(this.data);
return this;
}
public async delete(cloudlyClientRef: CloudlyApiClient, secretBundleIdArg: string) {
const deleteSecretBundleTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretbundle.IReq_DeleteSecretBundleById>(
'deleteSecretBundleById'
);
const response = await deleteSecretBundleTR.fire({
identity: cloudlyClientRef.identity,
secretBundleId: this.id,
});
plugins.smartexpect.expect(response.ok).toBeTrue();
return null;
}
public async getFlatKeyValueObjectForEnvironment(environmentArg: string = 'production') {
const bundleAuthorization = this.data.authorizations.find(authorization => {
return authorization.environment === environmentArg;
});
if (bundleAuthorization) {
throw new Error(`no matching environment >>${environmentArg} found in secret bundle`);
}
const getFlatKeyValueObjectTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretbundle.IReq_GetFlatKeyValueObject>(
'getFlatKeyValueObject'
);
const response = await getFlatKeyValueObjectTR.fire({
identity: this.cloudlyClientRef.identity,
seccretBundleId: this.id,
secretBundleAuthorization: bundleAuthorization,
});
const flatKeyValueObject: {[key: string]: string} = response.flatKeyValueObject;
return flatKeyValueObject;
}
}

View File

@ -0,0 +1,96 @@
import * as plugins from './plugins.js';
import type { CloudlyApiClient } from './classes.cloudlyapiclient.js';
export class SecretGroup implements plugins.servezoneInterfaces.data.ISecretGroup {
public cloudlyClientRef: CloudlyApiClient;
public id: string;
public data: plugins.servezoneInterfaces.data.ISecretGroup['data'];
constructor(cloudlyClientRef: CloudlyApiClient) {
this.cloudlyClientRef = cloudlyClientRef;
}
public static async getSecretGroupById(cloudlyClientRef: CloudlyApiClient, secretGroupIdArg: string) {
const getSecretGroupByIdTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretgroup.IReq_GetSecretGroupById>(
'getSecretGroupById'
);
const response = await getSecretGroupByIdTR.fire({
identity: cloudlyClientRef.identity,
secretGroupId: secretGroupIdArg,
});
const newSecretGroup = new SecretGroup(cloudlyClientRef);
Object.assign(newSecretGroup, response.secretGroup);
return newSecretGroup;
}
public static async getSecretGroups(cloudlyClientRef: CloudlyApiClient) {
const getSecretGroupsTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretgroup.IReq_GetSecretGroups>(
'getSecretGroups'
);
const response = await getSecretGroupsTR.fire({
identity: cloudlyClientRef.identity,
});
const secretGroups: SecretGroup[] = [];
for (const secretGroup of response.secretGroups) {
const newSecretGroup = new SecretGroup(cloudlyClientRef);
Object.assign(newSecretGroup, secretGroup);
secretGroups.push(newSecretGroup);
}
return secretGroups;
}
public static async createSecretGroup(cloudlyClientRef: CloudlyApiClient, secretGroupDataArg: Partial<plugins.servezoneInterfaces.data.ISecretGroup['data']>) {
const createSecretGroupTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretgroup.IReq_CreateSecretGroup>(
'createSecretGroup'
);
const response = await createSecretGroupTR.fire({
identity: cloudlyClientRef.identity,
secretGroup: {
id: null,
data: {
name: secretGroupDataArg.name,
description: secretGroupDataArg.description,
environments: secretGroupDataArg.environments,
key: secretGroupDataArg.key,
tags: secretGroupDataArg.tags,
priority: secretGroupDataArg.priority,
},
},
});
const newSecretGroup = new SecretGroup(cloudlyClientRef);
Object.assign(newSecretGroup, response.resultSecretGroup);
return newSecretGroup;
}
// INSTANCE
public async update() {
const updateSecretGroupTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretgroup.IReq_UpdateSecretGroup>(
'updateSecretGroup'
);
const response = await updateSecretGroupTR.fire({
identity: this.cloudlyClientRef.identity,
secretGroup: {
id: this.id,
data: this.data,
},
});
const resultSecretGroupData = response.resultSecretGroup.data;
plugins.smartexpect.expect(resultSecretGroupData).toEqual(this.data);
return this;
}
public async delete(cloudlyClientRef: CloudlyApiClient, secretGroupIdArg: string) {
const deleteSecretGroupTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.secretgroup.IReq_DeleteSecretGroupById>(
'deleteSecretGroupById'
);
const response = await deleteSecretGroupTR.fire({
identity: cloudlyClientRef.identity,
secretGroupId: this.id,
});
plugins.smartexpect.expect(response.ok).toBeTrue();
return null;
}
}

View File

@ -1,5 +1,80 @@
import * as plugins from './plugins.js'; import * as plugins from './plugins.js';
import type { CloudlyApiClient } from './classes.cloudlyapiclient.js';
export class Service { export class Service implements plugins.servezoneInterfaces.data.IService {
public static async getServices(cloudlyClientRef: CloudlyApiClient) {
const getAllServicesTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.service.IRequest_Any_Cloudly_GetServices>(
'getServices'
);
const response = await getAllServicesTR.fire({
identity: cloudlyClientRef.identity,
});
const resultServices: Service[] = [];
for (const service of response.services) {
const newService = new Service(cloudlyClientRef);
Object.assign(newService, service);
resultServices.push(newService);
}
return resultServices;
}
public static async getServiceById(cloudlyClientRef: CloudlyApiClient, serviceIdArg: string) {
const getServiceByIdTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.service.IRequest_Any_Cloudly_GetServiceById>(
'getServiceById'
);
const response = await getServiceByIdTR.fire({
identity: cloudlyClientRef.identity,
serviceId: serviceIdArg,
});
const newService = new Service(cloudlyClientRef);
Object.assign(newService, response.service);
return newService;
}
/**
* creates a new service
*/
public static async createService(cloudlyClientRef: CloudlyApiClient, serviceDataArg: Partial<plugins.servezoneInterfaces.data.IService['data']>) {
const createServiceTR = cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.service.IRequest_Any_Cloudly_CreateService>(
'createService'
);
const response = await createServiceTR.fire({
identity: cloudlyClientRef.identity,
name: serviceDataArg.name,
description: serviceDataArg.description,
imageId: serviceDataArg.imageId,
imageVersion: serviceDataArg.imageVersion,
environment: {},
secretBundleId: null,
scaleFactor: 1,
balancingStrategy: serviceDataArg.balancingStrategy,
ports: {
web: null,
},
resources: serviceDataArg.resources,
domains: [],
});
const newService = new Service(cloudlyClientRef);
Object.assign(newService, response.service);
return newService;
}
// INSTANCE
cloudlyClientRef: CloudlyApiClient;
public id: string;
public data: plugins.servezoneInterfaces.data.IService['data'];
constructor(cloudlyClientRef: CloudlyApiClient) {
this.cloudlyClientRef = cloudlyClientRef;
}
/**
* The service has a secret bundle.
* This function essentially returns the secret bundle as a flat object.
* In other words, it resolves secret groups and
*/
public async getSecretBundleAsFlatObject(environmentArg: string = 'production') {
}
} }

View File

@ -6,11 +6,13 @@ export {
} }
// @push.rocks scope // @push.rocks scope
import * as smartexpect from '@push.rocks/smartexpect';
import * as smartpromise from '@push.rocks/smartpromise'; import * as smartpromise from '@push.rocks/smartpromise';
import * as smartrx from '@push.rocks/smartrx'; import * as smartrx from '@push.rocks/smartrx';
import * as webstream from '@push.rocks/smartstream/web'; import * as webstream from '@push.rocks/smartstream/web';
export { export {
smartexpect,
smartpromise, smartpromise,
smartrx, smartrx,
webstream, webstream,

View File

@ -6,7 +6,6 @@ import * as plugins from '../plugins.js';
*/ */
export interface IDeployment { export interface IDeployment {
id: string; id: string;
deploymentDirectiveId: string;
affectedServiceIds: string[]; affectedServiceIds: string[];
usedImageId: string; usedImageId: string;
deploymentLog: string[]; deploymentLog: string[];

View File

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

View File

@ -3,7 +3,6 @@ export * from './cluster.js';
export * from './config.js'; export * from './config.js';
export * from './deployment.js'; export * from './deployment.js';
export * from './docker.js'; export * from './docker.js';
export * from './env.js';
export * from './event.js'; export * from './event.js';
export * from './image.js'; export * from './image.js';
export * from './secretbundle.js'; export * from './secretbundle.js';

View File

@ -7,6 +7,17 @@ export interface ISecretBundle {
/** /**
* determines if the secret is a service or an external secret * determines if the secret is a service or an external secret
* if external secret additional checks are put in place to protect the secret * if external secret additional checks are put in place to protect the secret
*
* * service:
* the bundle belongs to a service and can only be used by that service
* * npmci:
* the bundle is a secret bundle that is used by an npmci pipeline
* production secrets will be omitted in any case
* * gitzone:
* the bundle is a secret bundle that is used by a gitzone.
* Only local environment variables are allowed
* * external:
* the bundle is a secret bundle that is used by an external service
*/ */
type: 'service' | 'npmci' | 'gitzone' | 'external'; type: 'service' | 'npmci' | 'gitzone' | 'external';
@ -34,9 +45,11 @@ export interface ISecretBundle {
/** /**
* authrozations select a specific environment of a config bundle * authrozations select a specific environment of a config bundle
*/ */
authorizations: Array<{ authorizations: Array<ISecretBundleAuthorization>;
secretAccessKey: string;
environment: string;
}>;
}; };
} }
export interface ISecretBundleAuthorization {
secretAccessKey: string;
environment: string;
}

View File

@ -4,6 +4,7 @@ export interface IService {
id: string; id: string;
data: { data: {
name: string; name: string;
description: string;
imageId: string; imageId: string;
imageVersion: string; imageVersion: string;
environment: { [key: string]: string }; environment: { [key: string]: string };

View File

@ -0,0 +1,16 @@
import * as plugins from '../plugins.js';
import * as userInterfaces from '../data/user.js';
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;
}
}

View File

@ -5,11 +5,11 @@ import * as plugins from '../plugins.js';
/** /**
* get all clusters * get all clusters
*/ */
export interface IRequest_GetAllClusters extends plugins.typedrequestInterfaces.implementsTR< export interface IReq_Any_Cloudly_GetClusters extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest, plugins.typedrequestInterfaces.ITypedRequest,
IRequest_GetAllClusters IReq_Any_Cloudly_GetClusters
> { > {
method: 'getAllClusters'; method: 'getClusters';
request: { request: {
identity: userInterfaces.IIdentity; identity: userInterfaces.IIdentity;
}; };
@ -18,6 +18,21 @@ export interface IRequest_GetAllClusters extends plugins.typedrequestInterfaces.
}; };
} }
export interface IReq_Any_Cloudly_GetClusterById
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_Any_Cloudly_GetClusterById
> {
method: 'getClusterById';
request: {
identity: userInterfaces.IIdentity;
clusterId: string;
};
response: {
cluster: clusterInterfaces.ICluster;
};
}
export interface IRequest_CreateCluster extends plugins.typedrequestInterfaces.implementsTR< export interface IRequest_CreateCluster extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest, plugins.typedrequestInterfaces.ITypedRequest,
IRequest_CreateCluster IRequest_CreateCluster
@ -28,40 +43,40 @@ export interface IRequest_CreateCluster extends plugins.typedrequestInterfaces.i
clusterName: string; clusterName: string;
}; };
response: { response: {
clusterConfig: clusterInterfaces.ICluster; cluster: clusterInterfaces.ICluster;
}; };
} }
/** /**
* updates a cluster * updates a cluster
*/ */
export interface IRequest_UpdateCluster extends plugins.typedrequestInterfaces.implementsTR< export interface IReq_Any_Cloudly_UpdateCluster extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest, plugins.typedrequestInterfaces.ITypedRequest,
IRequest_UpdateCluster IReq_Any_Cloudly_UpdateCluster
> { > {
method: 'updateCluster'; method: 'updateCluster';
request: { request: {
identity: userInterfaces.IIdentity; identity: userInterfaces.IIdentity;
clusterConfig: clusterInterfaces.ICluster; clusterData: clusterInterfaces.ICluster['data'];
}; };
response: { response: {
clusterConfig: clusterInterfaces.ICluster; resultCluster: clusterInterfaces.ICluster;
}; };
} }
/** /**
* deletes a cluster * deletes a cluster
*/ */
export interface IRequest_DeleteCluster extends plugins.typedrequestInterfaces.implementsTR< export interface IReq_Any_Cloudly_DeleteClusterById extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest, plugins.typedrequestInterfaces.ITypedRequest,
IRequest_DeleteCluster IReq_Any_Cloudly_DeleteClusterById
> { > {
method: 'deleteCluster'; method: 'deleteClusterById';
request: { request: {
identity: userInterfaces.IIdentity; identity: userInterfaces.IIdentity;
clusterId: string; clusterId: string;
}; };
response: { response: {
success: boolean; ok: boolean;
}; };
} }

View File

@ -1,5 +1,6 @@
import * as plugins from '../plugins.js'; import * as plugins from '../plugins.js';
import * as adminRequests from './admin.js';
import * as certificateRequests from './certificate.js'; import * as certificateRequests from './certificate.js';
import * as clusterRequests from './cluster.js'; import * as clusterRequests from './cluster.js';
import * as configRequests from './config.js'; import * as configRequests from './config.js';
@ -9,12 +10,15 @@ import * as informRequests from './inform.js';
import * as logRequests from './log.js'; import * as logRequests from './log.js';
import * as networkRequests from './network.js'; import * as networkRequests from './network.js';
import * as routingRequests from './routing.js'; import * as routingRequests from './routing.js';
import * as secretRequests from './secret.js'; import * as secretBundleRequests from './secretbundle.js';
import * as secretGroupRequests from './secretgroup.js';
import * as serverRequests from './server.js'; import * as serverRequests from './server.js';
import * as serviceRequests from './service.js';
import * as statusRequests from './status.js'; import * as statusRequests from './status.js';
import * as versionRequests from './version.js'; import * as versionRequests from './version.js';
export { export {
adminRequests as admin,
certificateRequests as certificate, certificateRequests as certificate,
clusterRequests as cluster, clusterRequests as cluster,
configRequests as config, configRequests as config,
@ -24,8 +28,10 @@ export {
logRequests as log, logRequests as log,
networkRequests as network, networkRequests as network,
routingRequests as routing, routingRequests as routing,
secretRequests as secret, secretBundleRequests as secretbundle,
secretGroupRequests as secretgroup,
serverRequests as server, serverRequests as server,
serviceRequests as service,
statusRequests as status, statusRequests as status,
versionRequests as version, versionRequests as version,
}; };

View File

@ -1,94 +0,0 @@
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;
};
}

View File

@ -0,0 +1,103 @@
import * as plugins from '../plugins.js';
import * as data from '../data/index.js';
import * as userInterfaces from '../data/user.js';
export interface IReq_GetSecretBundles extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetSecretBundles
> {
method: 'getSecretBundles';
request: {
identity: userInterfaces.IIdentity;
};
response: {
secretBundles: data.ISecretBundle[];
};
}
export interface IReq_GetSecretBundleById extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetSecretBundleById
> {
method: 'getSecretBundleById';
request: {
identity: userInterfaces.IIdentity;
secretBundleId: string;
};
response: {
secretBundle: data.ISecretBundle;
};
}
export interface IReq_CreateSecretBundle extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_CreateSecretBundle
> {
method: 'createSecretBundle';
request: {
identity: userInterfaces.IIdentity;
secretBundle: data.ISecretBundle;
};
response: {
resultSecretBundle: data.ISecretBundle;
};
}
export interface IReq_UpdateSecretBundle extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_UpdateSecretBundle
> {
method: 'updateSecretBundle';
request: {
identity: userInterfaces.IIdentity;
secretBundle: data.ISecretBundle;
};
response: {
resultSecretBundle: data.ISecretBundle;
};
}
export interface IReq_DeleteSecretBundleById extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_DeleteSecretBundleById
> {
method: 'deleteSecretBundleById';
request: {
identity: userInterfaces.IIdentity;
secretBundleId: string;
};
response: {
ok: boolean;
};
}
export interface IReq_GetSecretBundleByAuthorization extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetSecretBundleByAuthorization
> {
method: 'getSecretBundleByAuthorization';
request: {
identity: userInterfaces.IIdentity;
secretBundleAuthorization: data.ISecretBundleAuthorization;
};
response: {
secretBundle: data.ISecretBundle;
};
}
export interface IReq_GetFlatKeyValueObject extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetFlatKeyValueObject
> {
method: 'getFlatKeyValueObject';
request: {
identity: userInterfaces.IIdentity;
seccretBundleId: string;
secretBundleAuthorization: data.ISecretBundleAuthorization;
};
response: {
flatKeyValueObject: {[key: string]: string};
};
}

View File

@ -0,0 +1,74 @@
import * as plugins from '../plugins.js';
import * as data from '../data/index.js';
import * as userInterfaces from '../data/user.js';
export interface IReq_GetSecretGroups extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetSecretGroups
> {
method: 'getSecretGroups';
request: {
identity: userInterfaces.IIdentity;
};
response: {
secretGroups: data.ISecretGroup[];
};
}
export interface IReq_GetSecretGroupById extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_GetSecretGroupById
> {
method: 'getSecretGroupById';
request: {
identity: userInterfaces.IIdentity;
secretGroupId: string;
};
response: {
secretGroup: data.ISecretGroup;
};
}
export interface IReq_CreateSecretGroup extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_CreateSecretGroup
> {
method: 'createSecretGroup';
request: {
identity: userInterfaces.IIdentity;
secretGroup: data.ISecretGroup;
};
response: {
resultSecretGroup: data.ISecretGroup;
};
}
export interface IReq_UpdateSecretGroup extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_UpdateSecretGroup
> {
method: 'updateSecretGroup';
request: {
identity: userInterfaces.IIdentity;
secretGroup: data.ISecretGroup;
};
response: {
resultSecretGroup: data.ISecretGroup;
};
}
export interface IReq_DeleteSecretGroupById extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IReq_DeleteSecretGroupById
> {
method: 'deleteSecretGroupById';
request: {
identity: userInterfaces.IIdentity;
secretGroupId: string;
};
response: {
ok: boolean;
};
}

View File

@ -0,0 +1,113 @@
import * as plugins from '../plugins.js';
import type { IService } from '../data/service.js';
import type { IIdentity } from '../data/user.js';
import type { IServiceRessources } from '../data/docker.js';
export interface IRequest_Any_Cloudly_GetServiceById
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_GetServiceById
> {
method: 'getServiceById';
request: {
identity: IIdentity;
serviceId: string;
};
response: {
service: IService;
};
}
export interface IRequest_Any_Cloudly_GetServices
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_GetServices
> {
method: 'getServices';
request: {
identity: IIdentity;
};
response: {
services: IService[];
};
}
export interface IRequest_Any_Cloudly_CreateService
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_CreateService
> {
method: 'createService';
request: {
identity: IIdentity;
name: string;
description: 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';
}[];
};
response: {
service: IService;
};
}
export interface IRequest_Any_Cloudly_UpdateService
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_UpdateService
> {
method: 'updateService';
request: {
identity: IIdentity;
serviceId: string;
name: string;
description: 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';
}[];
};
response: {
service: IService;
};
}
export interface IRequest_Any_Cloudly_DeleteService
extends plugins.typedrequestInterfaces.implementsTR<
plugins.typedrequestInterfaces.ITypedRequest,
IRequest_Any_Cloudly_DeleteService
> {
method: 'deleteService';
request: {
identity: IIdentity;
serviceId: string;
};
response: {
success: boolean;
};
}

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/cloudly', name: '@serve.zone/cloudly',
version: '4.4.0', version: '4.7.1',
description: 'A comprehensive tool for managing containerized applications across multiple cloud providers using Docker Swarmkit, featuring web, CLI, and API interfaces.' description: 'A comprehensive tool for managing containerized applications across multiple cloud providers using Docker Swarmkit, featuring web, CLI, and API interfaces.'
} }

View File

@ -15,7 +15,7 @@ export const loginAction = loginStatePart.createAction<{ username: string; passw
async (statePartArg, payloadArg) => { async (statePartArg, payloadArg) => {
const currentState = statePartArg.getState(); const currentState = statePartArg.getState();
const trLogin = const trLogin =
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secret.IReq_Admin_LoginWithUsernameAndPassword>( new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.admin.IReq_Admin_LoginWithUsernameAndPassword>(
'/typedrequest', '/typedrequest',
'adminLoginWithUsernameAndPassword' 'adminLoginWithUsernameAndPassword'
); );
@ -77,20 +77,34 @@ export const dataState = await appstate.getStatePart<IDataState>(
); );
// Getting data // Getting data
export const getAllDataAction = dataState.createAction(async (statePartArg, partialArg?: 'secrets' | 'images') => { export const getAllDataAction = dataState.createAction(async (statePartArg) => {
let currentState = statePartArg.getState(); let currentState = statePartArg.getState();
// Secrets // SecretsGroups
const trGetSecrets = const trGetSecretGroups =
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secret.IReq_Admin_GetConfigBundlesAndSecretGroups>( new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretgroup.IReq_GetSecretGroups>(
'/typedrequest', '/typedrequest',
'adminGetConfigBundlesAndSecretGroups' 'getSecretGroups'
); );
const response = await trGetSecrets.fire({ const response = await trGetSecretGroups.fire({
identity: loginStatePart.getState().identity, identity: loginStatePart.getState().identity,
}); });
currentState = { currentState = {
...currentState, ...currentState,
...response, secretGroups: response.secretGroups,
};
// SecretBundles
const trGetSecretBundles =
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretbundle.IReq_GetSecretBundles>(
'/typedrequest',
'getSecretBundles'
);
const responseSecretBundles = await trGetSecretBundles.fire({
identity: loginStatePart.getState().identity,
});
currentState = {
...currentState,
secretBundles: responseSecretBundles.secretBundles,
}; };
// images // images
@ -104,14 +118,14 @@ export const getAllDataAction = dataState.createAction(async (statePartArg, part
}); });
currentState = { currentState = {
...currentState, ...currentState,
...responseImages, images: responseImages.images,
}; };
// Clusters // Clusters
const trGetClusters = const trGetClusters =
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.cluster.IRequest_GetAllClusters>( new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.cluster.IReq_Any_Cloudly_GetClusters>(
'/typedrequest', '/typedrequest',
'getAllClusters' 'getClusters'
); );
const responseClusters = await trGetClusters.fire({ const responseClusters = await trGetClusters.fire({
identity: loginStatePart.getState().identity, identity: loginStatePart.getState().identity,
@ -119,7 +133,7 @@ export const getAllDataAction = dataState.createAction(async (statePartArg, part
currentState = { currentState = {
...currentState, ...currentState,
...responseClusters, clusters: responseClusters.clusters,
} }
return currentState; return currentState;
@ -130,14 +144,13 @@ export const createSecretGroupAction = dataState.createAction(
async (statePartArg, payloadArg: plugins.interfaces.data.ISecretGroup) => { async (statePartArg, payloadArg: plugins.interfaces.data.ISecretGroup) => {
let currentState = statePartArg.getState(); let currentState = statePartArg.getState();
const trCreateSecretGroup = const trCreateSecretGroup =
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secret.IReq_Admin_CreateConfigBundlesAndSecretGroups>( new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretgroup.IReq_CreateSecretGroup>(
'/typedrequest', '/typedrequest',
'adminCreateConfigBundlesAndSecretGroups' 'createSecretGroup'
); );
const response = await trCreateSecretGroup.fire({ const response = await trCreateSecretGroup.fire({
identity: loginStatePart.getState().identity, identity: loginStatePart.getState().identity,
secretBundles: [], secretGroup: payloadArg,
secretGroups: [payloadArg],
}); });
currentState = await dataState.dispatchAction(getAllDataAction, null); currentState = await dataState.dispatchAction(getAllDataAction, null);
return currentState; return currentState;
@ -149,14 +162,13 @@ export const deleteSecretGroupAction = dataState.createAction(
async (statePartArg, payloadArg: { secretGroupId: string }) => { async (statePartArg, payloadArg: { secretGroupId: string }) => {
let currentState = statePartArg.getState(); let currentState = statePartArg.getState();
const trDeleteSecretGroup = const trDeleteSecretGroup =
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secret.IReq_Admin_DeleteConfigBundlesAndSecretGroups>( new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretgroup.IReq_DeleteSecretGroupById>(
'/typedrequest', '/typedrequest',
'adminDeleteConfigBundlesAndSecretGroups' 'deleteSecretGroupById'
); );
const response = await trDeleteSecretGroup.fire({ const response = await trDeleteSecretGroup.fire({
identity: loginStatePart.getState().identity, identity: loginStatePart.getState().identity,
secretBundleIds: [], secretGroupId: payloadArg.secretGroupId,
secretGroupIds: [payloadArg.secretGroupId],
}); });
currentState = await dataState.dispatchAction(getAllDataAction, null); currentState = await dataState.dispatchAction(getAllDataAction, null);
return currentState; return currentState;
@ -168,14 +180,13 @@ export const deleteSecretBundleAction = dataState.createAction(
async (statePartArg, payloadArg: { configBundleId: string }) => { async (statePartArg, payloadArg: { configBundleId: string }) => {
let currentState = statePartArg.getState(); let currentState = statePartArg.getState();
const trDeleteConfigBundle = const trDeleteConfigBundle =
new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secret.IReq_Admin_DeleteConfigBundlesAndSecretGroups>( new domtools.plugins.typedrequest.TypedRequest<plugins.interfaces.requests.secretbundle.IReq_DeleteSecretBundleById>(
'/typedrequest', '/typedrequest',
'adminDeleteConfigBundlesAndSecretGroups' 'deleteSecretBundleById'
); );
const response = await trDeleteConfigBundle.fire({ const response = await trDeleteConfigBundle.fire({
identity: loginStatePart.getState().identity, identity: loginStatePart.getState().identity,
secretBundleIds: [payloadArg.configBundleId], secretBundleId: payloadArg.configBundleId,
secretGroupIds: [],
}); });
currentState = await dataState.dispatchAction(getAllDataAction, null); currentState = await dataState.dispatchAction(getAllDataAction, null);
return currentState; return currentState;
@ -249,7 +260,7 @@ export const addClusterAction = dataState.createAction(
currentState = { currentState = {
...currentState, ...currentState,
...{ ...{
clusters: [...currentState.clusters, response.clusterConfig], clusters: [...currentState.clusters, response.cluster],
}, },
} }
return currentState; return currentState;