fix(big fix upgrade): upgrade multiple areas of the core functionalities
This commit is contained in:
parent
d212dfb9f9
commit
53f96095c7
@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2024-10-16 - 1.1.8 - fix(big fix upgrade)
|
||||||
|
fix: update dependency versions and address type errors
|
||||||
|
|
||||||
|
- Updated all listed dependencies in the package.json to their specified ranges.
|
||||||
|
- Fixed type mismatches and added missing imports in various TypeScript files.
|
||||||
|
- Refined existing tests and added a new helper to manage Docker image streams.
|
||||||
|
|
||||||
## 2024-08-25 - 1.1.7 - fix(deps)
|
## 2024-08-25 - 1.1.7 - fix(deps)
|
||||||
Update dependencies to latest versions
|
Update dependencies to latest versions
|
||||||
|
|
||||||
|
28
package.json
28
package.json
@ -25,20 +25,20 @@
|
|||||||
"@git.zone/tsbundle": "^2.0.15",
|
"@git.zone/tsbundle": "^2.0.15",
|
||||||
"@git.zone/tstest": "^1.0.90",
|
"@git.zone/tstest": "^1.0.90",
|
||||||
"@git.zone/tswatch": "^2.0.23",
|
"@git.zone/tswatch": "^2.0.23",
|
||||||
"@push.rocks/tapbundle": "^5.0.24",
|
"@push.rocks/tapbundle": "^5.3.0",
|
||||||
"@types/node": "^22.5.0"
|
"@types/node": "^22.7.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@api.global/typedrequest": "3.0.30",
|
"@api.global/typedrequest": "3.1.10",
|
||||||
"@api.global/typedserver": "^3.0.50",
|
"@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",
|
||||||
"@apiclient.xyz/docker": "^1.2.3",
|
"@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.1.6",
|
"@design.estate/dees-catalog": "^1.2.0",
|
||||||
"@design.estate/dees-domtools": "^2.0.57",
|
"@design.estate/dees-domtools": "^2.0.64",
|
||||||
"@design.estate/dees-element": "^2.0.36",
|
"@design.estate/dees-element": "^2.0.39",
|
||||||
"@git.zone/tsrun": "^1.2.49",
|
"@git.zone/tsrun": "^1.2.49",
|
||||||
"@push.rocks/early": "^4.0.3",
|
"@push.rocks/early": "^4.0.3",
|
||||||
"@push.rocks/npmextra": "^5.0.23",
|
"@push.rocks/npmextra": "^5.0.23",
|
||||||
@ -48,14 +48,14 @@
|
|||||||
"@push.rocks/smartbucket": "^3.0.22",
|
"@push.rocks/smartbucket": "^3.0.22",
|
||||||
"@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.6",
|
"@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.21",
|
||||||
"@push.rocks/smartguard": "^3.0.2",
|
"@push.rocks/smartguard": "^3.1.0",
|
||||||
"@push.rocks/smartjson": "^5.0.19",
|
"@push.rocks/smartjson": "^5.0.19",
|
||||||
"@push.rocks/smartjwt": "^2.0.4",
|
"@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/smartpath": "^5.0.18",
|
"@push.rocks/smartpath": "^5.0.18",
|
||||||
@ -63,13 +63,13 @@
|
|||||||
"@push.rocks/smartrequest": "^2.0.22",
|
"@push.rocks/smartrequest": "^2.0.22",
|
||||||
"@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.17",
|
"@push.rocks/smartstate": "^2.0.19",
|
||||||
"@push.rocks/smartstream": "^3.0.44",
|
"@push.rocks/smartstream": "^3.2.4",
|
||||||
"@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",
|
||||||
"@serve.zone/interfaces": "^1.0.78",
|
"@serve.zone/interfaces": "^1.1.2",
|
||||||
"@tsclass/tsclass": "^4.1.2"
|
"@tsclass/tsclass": "^4.1.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
2265
pnpm-lock.yaml
generated
2265
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -21,3 +21,7 @@ export const createCloudly = async () => {
|
|||||||
return cloudlyInstance;
|
return cloudlyInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getEnvVarOnDemand = async (envVarName: string) => {
|
||||||
|
return testQenv.getEnvVarOnDemand(envVarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
9
test/helpers/docker.ts
Normal file
9
test/helpers/docker.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import * as smartstream from '@push.rocks/smartstream';
|
||||||
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
|
|
||||||
|
export const getAlpineImageReadableStream = async () => {
|
||||||
|
const currentDir = smartpath.get.dirnameFromImportMetaUrl(import.meta.url);
|
||||||
|
const imagePath = smartpath.join(currentDir, '../../.nogit/testfiles/alpine.tar');
|
||||||
|
const readableStream = smartstream.nodewebhelpers.createWebReadableStreamFromFile(imagePath);
|
||||||
|
return readableStream;
|
||||||
|
}
|
@ -1 +1,2 @@
|
|||||||
export * from './cloudlyfactory.js';
|
export * from './cloudlyfactory.js';
|
||||||
|
export * from './docker.js';
|
||||||
|
@ -1,30 +1,80 @@
|
|||||||
import { tap, expect } from '@push.rocks/tapbundle';
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import * as helpers from './helpers/index.js';
|
||||||
|
|
||||||
|
import * as cloudly from '../ts/index.js';
|
||||||
import * as cloudlyApiClient from '../ts_apiclient/index.js';
|
import * as cloudlyApiClient from '../ts_apiclient/index.js';
|
||||||
|
import { Image } from '../ts_apiclient/classes.image.js';
|
||||||
|
|
||||||
|
let testCloudly: cloudly.Cloudly;
|
||||||
let testClient: cloudlyApiClient.CloudlyApiClient;
|
let testClient: cloudlyApiClient.CloudlyApiClient;
|
||||||
|
|
||||||
|
tap.preTask('should start cloudly', async () => {
|
||||||
|
testCloudly = await helpers.createCloudly();
|
||||||
|
await testCloudly.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.preTask('should create a new machine user for testing', async () => {
|
||||||
|
const machineUser = new testCloudly.authManager.CUser();
|
||||||
|
machineUser.id = await testCloudly.authManager.CUser.getNewId();
|
||||||
|
machineUser.data = {
|
||||||
|
type: 'machine',
|
||||||
|
username: 'test',
|
||||||
|
password: 'test',
|
||||||
|
tokens: [{
|
||||||
|
token: 'test',
|
||||||
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||||
|
assignedRoles: ['admin'],
|
||||||
|
}],
|
||||||
|
role: 'admin',
|
||||||
|
};
|
||||||
|
await machineUser.save();
|
||||||
|
});
|
||||||
|
|
||||||
tap.test('should create a new cloudlyApiClient', async () => {
|
tap.test('should create a new cloudlyApiClient', async () => {
|
||||||
testClient = new cloudlyApiClient.CloudlyApiClient({
|
testClient = new cloudlyApiClient.CloudlyApiClient({
|
||||||
registerAs: 'api',
|
registerAs: 'api',
|
||||||
cloudlyUrl: 'http://localhost:3000',
|
cloudlyUrl: `http://localhost:${await helpers.getEnvVarOnDemand('SERVEZONE_PORT')}`,
|
||||||
});
|
});
|
||||||
// await testClient.start();
|
await testClient.start();
|
||||||
expect(testClient).toBeTruthy();
|
expect(testClient).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should get an identity', async () => {
|
tap.test('create a new machine user', async () => {
|
||||||
const identity = await testClient.getIdentityByJumpCode('test');
|
const machineUser = await testCloudly.authManager.CUser.createMachineUser('test', 'api');
|
||||||
expect(identity).toBeTruthy();
|
machineUser.data.tokens.push({
|
||||||
});
|
token: 'test',
|
||||||
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||||
tap.test('should trigger a server action', async () => {
|
assignedRoles: ['api'],
|
||||||
|
})
|
||||||
|
await machineUser.save();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tap.test('should get an identity', async () => {
|
||||||
|
const identity = await testClient.getIdentityByToken('test');
|
||||||
|
expect(identity).toBeTruthy();
|
||||||
|
console.log(identity);
|
||||||
|
});
|
||||||
|
|
||||||
|
let image: Image;
|
||||||
|
tap.test('should create and upload an image', async () => {
|
||||||
|
image = await testClient.images.createImage({
|
||||||
|
name: 'test',
|
||||||
|
description: 'test'
|
||||||
|
});
|
||||||
|
console.log('created image: ', image);
|
||||||
|
expect(image).toBeInstanceOf(Image);
|
||||||
|
})
|
||||||
|
|
||||||
|
tap.test('should upload an image version', async () => {
|
||||||
|
const imageStream = await helpers.getAlpineImageReadableStream();
|
||||||
|
|
||||||
|
await image.pushImageVersion('v1.0.0', imageStream);
|
||||||
|
});
|
||||||
|
|
||||||
tap.test('should stop the apiclient', async (toolsArg) => {
|
tap.test('should stop the apiclient', async (toolsArg) => {
|
||||||
await toolsArg.delayFor(1000);
|
await toolsArg.delayFor(10000);
|
||||||
await testClient.stop();
|
await testClient.stop();
|
||||||
|
await testCloudly.stop();
|
||||||
})
|
})
|
||||||
|
|
||||||
export default tap.start();
|
export default tap.start();
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/cloudly',
|
name: '@serve.zone/cloudly',
|
||||||
version: '1.1.7',
|
version: '1.1.8',
|
||||||
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.'
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,10 @@ export class CloudlyAuthManager {
|
|||||||
this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter);
|
this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async createNewSecureToken() {
|
||||||
|
return plugins.smartunique.uniSimple('secureToken', 64);
|
||||||
|
}
|
||||||
|
|
||||||
public async start() {
|
public async start() {
|
||||||
// lets setup the smartjwtInstance
|
// lets setup the smartjwtInstance
|
||||||
this.smartjwtInstance = new plugins.smartjwt.SmartJwt();
|
this.smartjwtInstance = new plugins.smartjwt.SmartJwt();
|
||||||
@ -53,6 +57,7 @@ export class CloudlyAuthManager {
|
|||||||
const user = await User.findUserByUsernameAndPassword(dataArg.username, dataArg.password);
|
const user = await User.findUserByUsernameAndPassword(dataArg.username, dataArg.password);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
logger.log('warn', 'login failed');
|
logger.log('warn', 'login failed');
|
||||||
|
throw new plugins.typedrequest.TypedResponseError('login failed');
|
||||||
} else {
|
} else {
|
||||||
jwt = await this.smartjwtInstance.createJWT({
|
jwt = await this.smartjwtInstance.createJWT({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
@ -96,7 +101,7 @@ export class CloudlyAuthManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
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.smartexpect.expectAsync(this.validIdentityGuard.exec(dataArg)).toBeTrue();
|
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);
|
||||||
const user = await this.CUser.getInstance({id: jwtData.userId});
|
const user = await this.CUser.getInstance({id: jwtData.userId});
|
||||||
|
@ -5,6 +5,26 @@ export class User extends plugins.smartdata.SmartDataDbDoc<
|
|||||||
User,
|
User,
|
||||||
plugins.servezoneInterfaces.data.IUser
|
plugins.servezoneInterfaces.data.IUser
|
||||||
> {
|
> {
|
||||||
|
/**
|
||||||
|
* creates a machine user
|
||||||
|
*/
|
||||||
|
public static async createMachineUser(userNameArg: string, roleArg: 'api' | 'cluster') {
|
||||||
|
const user = new User();
|
||||||
|
user.id = await User.getNewId();
|
||||||
|
user.data = {
|
||||||
|
type: 'machine',
|
||||||
|
username: userNameArg,
|
||||||
|
tokens: [{
|
||||||
|
token: 'machineUser',
|
||||||
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||||
|
assignedRoles: ['admin'],
|
||||||
|
}],
|
||||||
|
role: 'api',
|
||||||
|
};
|
||||||
|
await user.save();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
public static async findUserByUsernameAndPassword(usernameArg: string, passwordArg: string) {
|
public static async findUserByUsernameAndPassword(usernameArg: string, passwordArg: string) {
|
||||||
return await User.getInstance({
|
return await User.getInstance({
|
||||||
data: {
|
data: {
|
||||||
@ -14,6 +34,13 @@ export class User extends plugins.smartdata.SmartDataDbDoc<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(optionsArg?: plugins.servezoneInterfaces.data.IUser) {
|
||||||
|
super();
|
||||||
|
if (optionsArg) {
|
||||||
|
Object.assign(this, optionsArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
@plugins.smartdata.unI()
|
@plugins.smartdata.unI()
|
||||||
public id: string;
|
public id: string;
|
||||||
|
@ -4,6 +4,7 @@ import { Cloudly } from '../classes.cloudly.js';
|
|||||||
import { logger } from '../logger.js';
|
import { logger } from '../logger.js';
|
||||||
|
|
||||||
import { Cluster } from './classes.cluster.js';
|
import { Cluster } from './classes.cluster.js';
|
||||||
|
import { data } from '@serve.zone/interfaces';
|
||||||
|
|
||||||
export class ClusterManager {
|
export class ClusterManager {
|
||||||
public ready = plugins.smartpromise.defer();
|
public ready = plugins.smartpromise.defer();
|
||||||
@ -26,10 +27,8 @@ export class ClusterManager {
|
|||||||
const cluster = await this.createCluster({
|
const cluster = await this.createCluster({
|
||||||
id: plugins.smartunique.uniSimple('cluster'),
|
id: plugins.smartunique.uniSimple('cluster'),
|
||||||
data: {
|
data: {
|
||||||
userId: null,
|
userId: null, // this is created by the createCluster method
|
||||||
name: dataArg.clusterName,
|
name: dataArg.clusterName,
|
||||||
initialJumpToken: plugins.smartunique.uniSimple('initialJumpToken'),
|
|
||||||
initialJumpTokenUsedAt: null,
|
|
||||||
acmeInfo: null,
|
acmeInfo: null,
|
||||||
cloudlyUrl: `https://${this.cloudlyRef.config.data.publicUrl}:${this.cloudlyRef.config.data.publicPort}/`,
|
cloudlyUrl: `https://${this.cloudlyRef.config.data.publicUrl}:${this.cloudlyRef.config.data.publicPort}/`,
|
||||||
servers: [],
|
servers: [],
|
||||||
@ -82,19 +81,17 @@ export class ClusterManager {
|
|||||||
// TODO: implement getclusterConfigByServerIp
|
// TODO: implement getclusterConfigByServerIp
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getClusterBy_JumpCode(initialJumpTokenArg: string) {
|
public async getClusterBy_UserId(userIdArg: string) {
|
||||||
await this.ready.promise;
|
await this.ready.promise;
|
||||||
|
|
||||||
return await Cluster.getInstance({
|
return await Cluster.getInstance({
|
||||||
data: {
|
data: {
|
||||||
initialJumpToken: initialJumpTokenArg,
|
userId: userIdArg,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getClusterBy_Identity(
|
public async getClusterBy_Identity(clusterIdentity: plugins.servezoneInterfaces.data.IIdentity) {
|
||||||
clusterIdentity: plugins.servezoneInterfaces.data.IIdentity
|
|
||||||
) {
|
|
||||||
await this.ready.promise;
|
await this.ready.promise;
|
||||||
|
|
||||||
return await Cluster.getInstance({
|
return await Cluster.getInstance({
|
||||||
@ -125,19 +122,27 @@ export class ClusterManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* allows storage of a config
|
* creates a cluster (and a new user for it) and saves it
|
||||||
* @param configName
|
* @param configName
|
||||||
* @param configObjectArg
|
* @param configObjectArg
|
||||||
*/
|
*/
|
||||||
public async createCluster(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
|
public async createCluster(configObjectArg: plugins.servezoneInterfaces.data.ICluster) {
|
||||||
// TODO: guards
|
// TODO: guards
|
||||||
// lets create the cluster user
|
// lets create the cluster user
|
||||||
const clusterUser = new this.cloudlyRef.authManager.CUser();
|
const clusterUser = new this.cloudlyRef.authManager.CUser({
|
||||||
clusterUser.id = await this.cloudlyRef.authManager.CUser.getNewId();
|
id: await this.cloudlyRef.authManager.CUser.getNewId(),
|
||||||
clusterUser.data = {
|
data: {
|
||||||
role: 'cluster',
|
role: 'cluster',
|
||||||
type: 'machine',
|
type: 'machine',
|
||||||
}
|
tokens: [
|
||||||
|
{
|
||||||
|
expiresAt: Date.now() + 3600 * 1000 * 24 * 365,
|
||||||
|
assignedRoles: ['cluster'],
|
||||||
|
token: await this.cloudlyRef.authManager.createNewSecureToken(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
await clusterUser.save();
|
await clusterUser.save();
|
||||||
Object.assign(configObjectArg, {
|
Object.assign(configObjectArg, {
|
||||||
userId: clusterUser.id,
|
userId: clusterUser.id,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
import { Cloudly } from '../classes.cloudly.js';
|
import { Cloudly } from '../classes.cloudly.js';
|
||||||
|
import type { Cluster } from '../manager.cluster/classes.cluster.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* in charge of talking to coreflow services on clusters
|
* in charge of talking to coreflow services on clusters
|
||||||
@ -13,38 +14,41 @@ export class CloudlyCoreflowManager {
|
|||||||
this.cloudlyRef = cloudlyRefArg;
|
this.cloudlyRef = cloudlyRefArg;
|
||||||
this.cloudlyRef.typedrouter.addTypedRouter(this.typedRouter);
|
this.cloudlyRef.typedrouter.addTypedRouter(this.typedRouter);
|
||||||
|
|
||||||
this.typedRouter.addTypedHandler<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByJumpCode>(
|
this.typedRouter.addTypedHandler<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken>(
|
||||||
new plugins.typedrequest.TypedHandler('getIdentityByJumpCode', async (requestData) => {
|
new plugins.typedrequest.TypedHandler('getIdentityByToken', async (requestData) => {
|
||||||
const cluster =
|
|
||||||
await this.cloudlyRef.clusterManager.getClusterBy_JumpCode(
|
|
||||||
requestData.jumpCode
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!cluster) {
|
|
||||||
throw new plugins.typedrequest.TypedResponseError('The supplied jumpCode is not valid. No cluster found.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await this.cloudlyRef.authManager.CUser.getInstance({
|
const user = await this.cloudlyRef.authManager.CUser.getInstance({
|
||||||
id: cluster.data.userId,
|
data: {
|
||||||
|
tokens: [{
|
||||||
|
token: requestData.token,
|
||||||
|
}] // find the proper user here.
|
||||||
|
} as any
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new plugins.typedrequest.TypedResponseError('The supplied jumpCode is not valid. No user found.');
|
throw new plugins.typedrequest.TypedResponseError('The supplied token is not valid. No matching user found.');
|
||||||
|
}
|
||||||
|
if (user.data.type !== 'machine') {
|
||||||
|
throw new plugins.typedrequest.TypedResponseError('The supplied token is not valid. The user is not a machine.');
|
||||||
|
}
|
||||||
|
let cluster: Cluster;
|
||||||
|
if (user.data.role === 'cluster') {
|
||||||
|
cluster = await this.cloudlyRef.clusterManager.getClusterBy_UserId(user.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const expiryTimestamp = Date.now() + 3600 * 1000 * 24 * 365;
|
const expiryTimestamp = Date.now() + 3600 * 1000 * 24 * 365;
|
||||||
return {
|
return {
|
||||||
identity: {
|
identity: {
|
||||||
name: cluster.data.name,
|
name: user.data.username,
|
||||||
role: 'cluster',
|
role: user.data.role,
|
||||||
type: 'machine',
|
type: 'machine', // if someone authenticates by token, they are a machine, no matter what.
|
||||||
userId: cluster.data.userId,
|
userId: user.id,
|
||||||
expiresAt: expiryTimestamp,
|
expiresAt: expiryTimestamp,
|
||||||
clusterId: cluster.id,
|
...(cluster ? {
|
||||||
clusterName: cluster.data.name,
|
clusterId: cluster.id,
|
||||||
|
clusterName: cluster.data.name,
|
||||||
|
} : {}),
|
||||||
jwt: await this.cloudlyRef.authManager.smartjwtInstance.createJWT({
|
jwt: await this.cloudlyRef.authManager.smartjwtInstance.createJWT({
|
||||||
status: 'loggedIn',
|
status: 'loggedIn',
|
||||||
userId: cluster.data.userId,
|
userId: user.id,
|
||||||
expiresAt: expiryTimestamp,
|
expiresAt: expiryTimestamp,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -34,4 +34,12 @@ export class Image extends plugins.smartdata.SmartDataDbDoc<Image, plugins.serve
|
|||||||
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 getReadStream() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import type { Cloudly } from '../classes.cloudly.js';
|
import type { Cloudly } from '../classes.cloudly.js';
|
||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as paths from '../paths.js';
|
||||||
|
|
||||||
import { Image } from './classes.image.js';
|
import { Image } from './classes.image.js';
|
||||||
|
|
||||||
@ -9,14 +10,13 @@ export class ImageManager {
|
|||||||
public smartbucketInstance: plugins.smartbucket.SmartBucket;
|
public smartbucketInstance: plugins.smartbucket.SmartBucket;
|
||||||
public imageDir: plugins.smartbucket.Directory;
|
public imageDir: plugins.smartbucket.Directory;
|
||||||
public dockerImageStore: plugins.docker.DockerImageStore;
|
public dockerImageStore: plugins.docker.DockerImageStore;
|
||||||
|
|
||||||
get db() {
|
get db() {
|
||||||
return this.cloudlyRef.mongodbConnector.smartdataDb;
|
return this.cloudlyRef.mongodbConnector.smartdataDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CImage = plugins.smartdata.setDefaultManagerForDoc(this, Image);
|
public CImage = plugins.smartdata.setDefaultManagerForDoc(this, Image);
|
||||||
|
|
||||||
|
|
||||||
constructor(cloudlyRefArg: Cloudly) {
|
constructor(cloudlyRefArg: Cloudly) {
|
||||||
this.cloudlyRef = cloudlyRefArg;
|
this.cloudlyRef = cloudlyRefArg;
|
||||||
|
|
||||||
@ -37,7 +37,19 @@ export class ImageManager {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
|
|
||||||
|
this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_GetImage>(
|
||||||
|
new plugins.typedrequest.TypedHandler('getImage', async (reqArg, toolsArg) => {
|
||||||
|
await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg);
|
||||||
|
const image = await this.CImage.getInstance({
|
||||||
|
id: reqArg.imageId,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
image: await image.createSavableObject(),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
this.typedrouter.addTypedHandler(
|
this.typedrouter.addTypedHandler(
|
||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_DeleteImage>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_DeleteImage>(
|
||||||
@ -74,14 +86,33 @@ export class ImageManager {
|
|||||||
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
||||||
'pushImageVersion',
|
'pushImageVersion',
|
||||||
async (reqArg, toolsArg) => {
|
async (reqArg, toolsArg) => {
|
||||||
const image = await this.CImage.getInstance({
|
await plugins.smartguard.passGuardsOrReject(reqArg, [
|
||||||
|
this.cloudlyRef.authManager.validIdentityGuard,
|
||||||
|
]);
|
||||||
|
const refImage = await this.CImage.getInstance({
|
||||||
id: reqArg.imageId,
|
id: reqArg.imageId,
|
||||||
});
|
});
|
||||||
if (!image) {
|
if (!refImage) {
|
||||||
throw new plugins.typedrequest.TypedResponseError('Image not found');
|
throw new plugins.typedrequest.TypedResponseError('Image not found');
|
||||||
}
|
}
|
||||||
const imageVersion = reqArg.versionString;
|
const imageVersion = reqArg.versionString;
|
||||||
|
console.log(
|
||||||
|
`got request to push image version ${imageVersion} for image ${refImage.data.name}`
|
||||||
|
);
|
||||||
const imagePushStream = reqArg.imageStream;
|
const imagePushStream = reqArg.imageStream;
|
||||||
|
(async () => {
|
||||||
|
const smartWebDuplex = new plugins.smartstream.webstream.WebDuplexStream<
|
||||||
|
Uint8Array,
|
||||||
|
Uint8Array
|
||||||
|
>({
|
||||||
|
writeFunction: async (chunkArg, toolsArg) => {
|
||||||
|
console.log(chunkArg);
|
||||||
|
return chunkArg;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
imagePushStream.writeToWebstream(smartWebDuplex.writable);
|
||||||
|
await this.dockerImageStore.storeImage(refImage.id, plugins.smartstream.SmartDuplex.fromWebReadableStream(smartWebDuplex.readable));
|
||||||
|
})();
|
||||||
return {
|
return {
|
||||||
allowed: true,
|
allowed: true,
|
||||||
};
|
};
|
||||||
@ -94,12 +125,17 @@ export class ImageManager {
|
|||||||
'pullImageVersion',
|
'pullImageVersion',
|
||||||
async (reqArg) => {
|
async (reqArg) => {
|
||||||
const image = await this.CImage.getInstance({
|
const image = await this.CImage.getInstance({
|
||||||
id: reqArg.imageId,
|
id: reqArg.imageId,
|
||||||
});
|
});
|
||||||
const imageVersion = image.data.versions.find((version) => version.versionString === reqArg.versionString);
|
const imageVersion = image.data.versions.find(
|
||||||
const readable = this.imageDir.fastGetStream({
|
(version) => version.versionString === reqArg.versionString
|
||||||
path: await image.getStoragePath(reqArg.versionString),
|
);
|
||||||
}, 'webstream');
|
const readable = this.imageDir.fastGetStream(
|
||||||
|
{
|
||||||
|
path: await image.getStoragePath(reqArg.versionString),
|
||||||
|
},
|
||||||
|
'webstream'
|
||||||
|
);
|
||||||
const imageVirtualStream = new plugins.typedrequest.VirtualStream();
|
const imageVirtualStream = new plugins.typedrequest.VirtualStream();
|
||||||
return {
|
return {
|
||||||
imageStream: imageVirtualStream,
|
imageStream: imageVirtualStream,
|
||||||
@ -110,6 +146,7 @@ export class ImageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async start() {
|
public async start() {
|
||||||
|
// lets setup s3
|
||||||
const s3Descriptor: plugins.tsclass.storage.IS3Descriptor =
|
const s3Descriptor: plugins.tsclass.storage.IS3Descriptor =
|
||||||
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);
|
||||||
@ -117,10 +154,17 @@ export class ImageManager {
|
|||||||
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: 'test/test.txt', contents: 'hello' });
|
await bucket.fastPut({ path: 'images/00init', contents: 'init' });
|
||||||
|
|
||||||
this.imageDir = await bucket.getDirectoryFromPath({
|
this.imageDir = await bucket.getDirectoryFromPath({
|
||||||
path: 'images',
|
path: '/images',
|
||||||
|
});
|
||||||
|
|
||||||
|
// lets setup dockerstore
|
||||||
|
await plugins.smartfile.fs.ensureDir(paths.dockerImageStoreDir);
|
||||||
|
this.dockerImageStore = new plugins.docker.DockerImageStore({
|
||||||
|
localDirPath: paths.dockerImageStoreDir,
|
||||||
|
bucketDir: this.imageDir,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,5 @@ 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 distServeDir = plugins.path.join(packageDir, './dist_serve');
|
export const distServeDir = plugins.path.join(packageDir, './dist_serve');
|
||||||
|
@ -43,6 +43,7 @@ import * as smartpath from '@push.rocks/smartpath';
|
|||||||
import * as smartpromise from '@push.rocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
import * as smartrequest from '@push.rocks/smartrequest';
|
import * as smartrequest from '@push.rocks/smartrequest';
|
||||||
import * as smartssh from '@push.rocks/smartssh';
|
import * as smartssh from '@push.rocks/smartssh';
|
||||||
|
import * as smartstream from '@push.rocks/smartstream';
|
||||||
import * as smartstring from '@push.rocks/smartstring';
|
import * as smartstring from '@push.rocks/smartstring';
|
||||||
import * as smartunique from '@push.rocks/smartunique';
|
import * as smartunique from '@push.rocks/smartunique';
|
||||||
import * as taskbuffer from '@push.rocks/taskbuffer';
|
import * as taskbuffer from '@push.rocks/taskbuffer';
|
||||||
@ -69,6 +70,7 @@ export {
|
|||||||
smartpromise,
|
smartpromise,
|
||||||
smartrequest,
|
smartrequest,
|
||||||
smartssh,
|
smartssh,
|
||||||
|
smartstream,
|
||||||
smartstring,
|
smartstring,
|
||||||
smartunique,
|
smartunique,
|
||||||
taskbuffer,
|
taskbuffer,
|
||||||
|
@ -55,7 +55,7 @@ export class CloudlyApiClient {
|
|||||||
this.cloudlyUrl
|
this.cloudlyUrl
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
`CloudlyCluent connected to cloudly at ${this.cloudlyUrl}. Remember to get an identity.`
|
`CloudlyClient connected to cloudly at ${this.cloudlyUrl}. Remember to get an identity.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,8 +64,8 @@ export class CloudlyApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public identity: plugins.servezoneInterfaces.data.IIdentity;
|
public identity: plugins.servezoneInterfaces.data.IIdentity;
|
||||||
public async getIdentityByJumpCode(
|
public async getIdentityByToken(
|
||||||
jumpCodeArg: string,
|
token: string,
|
||||||
optionsArg?: {
|
optionsArg?: {
|
||||||
tagConnection?: boolean;
|
tagConnection?: boolean;
|
||||||
statefullIdentity?: boolean;
|
statefullIdentity?: boolean;
|
||||||
@ -77,12 +77,12 @@ export class CloudlyApiClient {
|
|||||||
}, optionsArg);
|
}, optionsArg);
|
||||||
|
|
||||||
const identityRequest =
|
const identityRequest =
|
||||||
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByJumpCode>(
|
this.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.identity.IRequest_Any_Cloudly_CoreflowManager_GetIdentityByToken>(
|
||||||
'getIdentityByJumpCode'
|
'getIdentityByToken'
|
||||||
);
|
);
|
||||||
console.log(`trying to get identity from cloudly with supplied jumpCodeArg: ${jumpCodeArg}`);
|
console.log(`trying to get identity from cloudly with supplied jumpCodeArg: ${token}`);
|
||||||
const response = await identityRequest.fire({
|
const response = await identityRequest.fire({
|
||||||
jumpCode: jumpCodeArg,
|
token: token,
|
||||||
});
|
});
|
||||||
console.log('got identity response');
|
console.log('got identity response');
|
||||||
const identity = response.identity;
|
const identity = response.identity;
|
||||||
@ -155,8 +155,13 @@ export class CloudlyApiClient {
|
|||||||
return typedResponse.certificate;
|
return typedResponse.certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Images
|
public images = {
|
||||||
public async getImages() {
|
// Images
|
||||||
return Image.getImages(this);
|
getImages: async () => {
|
||||||
|
return Image.getImages(this);
|
||||||
|
},
|
||||||
|
createImage: async (optionsArg: Parameters<typeof Image.createImage>[1]) => {
|
||||||
|
return Image.createImage(this, optionsArg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,8 @@ export class Image implements plugins.servezoneInterfaces.data.IImage {
|
|||||||
* updates the image data
|
* updates the image data
|
||||||
*/
|
*/
|
||||||
public async update() {
|
public async update() {
|
||||||
const getVersionsTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_GetImageMetadata>(
|
const getVersionsTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_GetImage>(
|
||||||
'getImageMetadata'
|
'getImage'
|
||||||
);
|
);
|
||||||
const response = await getVersionsTR.fire({
|
const response = await getVersionsTR.fire({
|
||||||
identity: this.cloudlyClientRef.identity,
|
identity: this.cloudlyClientRef.identity,
|
||||||
@ -66,18 +66,17 @@ export class Image implements plugins.servezoneInterfaces.data.IImage {
|
|||||||
*/
|
*/
|
||||||
public async pushImageVersion(imageVersion: string, imageReadableArg: ReadableStream<Uint8Array>): Promise<void> {
|
public async pushImageVersion(imageVersion: string, imageReadableArg: ReadableStream<Uint8Array>): Promise<void> {
|
||||||
const done = plugins.smartpromise.defer();
|
const done = plugins.smartpromise.defer();
|
||||||
const pullImageTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
const pushImageTR = this.cloudlyClientRef.typedsocketClient.createTypedRequest<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
||||||
'pushImageVersion'
|
'pushImageVersion'
|
||||||
);
|
);
|
||||||
const virtualStream = new plugins.typedrequest.VirtualStream();
|
const virtualStream = new plugins.typedrequest.VirtualStream();
|
||||||
const response = await pullImageTR.fire({
|
const response = await pushImageTR.fire({
|
||||||
identity: this.cloudlyClientRef.identity,
|
identity: this.cloudlyClientRef.identity,
|
||||||
imageId: this.id,
|
imageId: this.id,
|
||||||
versionString: '',
|
versionString: '',
|
||||||
imageStream: virtualStream,
|
imageStream: virtualStream,
|
||||||
});
|
});
|
||||||
await virtualStream.readFromWebstream(imageReadableArg);
|
await virtualStream.readFromWebstream(imageReadableArg);
|
||||||
await done.promise;
|
|
||||||
await this.update();
|
await this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/cloudly',
|
name: '@serve.zone/cloudly',
|
||||||
version: '1.1.7',
|
version: '1.1.8',
|
||||||
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.'
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,11 @@ export const loginAction = loginStatePart.createAction<{ username: string; passw
|
|||||||
const response = await trLogin.fire({
|
const response = await trLogin.fire({
|
||||||
username: payloadArg.username,
|
username: payloadArg.username,
|
||||||
password: payloadArg.password,
|
password: payloadArg.password,
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
return {
|
||||||
|
...statePartArg.getState(),
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
...currentState,
|
...currentState,
|
||||||
|
@ -97,6 +97,10 @@ export class CloudlyDashboard extends DeesElement {
|
|||||||
name: 'Services',
|
name: 'Services',
|
||||||
element: CloudlyViewServices,
|
element: CloudlyViewServices,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Testing & Building',
|
||||||
|
element: CloudlyViewServices,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Deployments',
|
name: 'Deployments',
|
||||||
element: CloudlyViewDeployments,
|
element: CloudlyViewDeployments,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewBackups extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewClusters extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewDbs extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewDeployments extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,8 @@ export class CloudlyViewDns extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
css`
|
shared.viewHostCss,
|
||||||
:host {
|
css`
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import { DeesElement, customElement, html, state, css, cssManager } from '@design.estate/dees-element';
|
import { DeesElement, customElement, html, state, css, cssManager } from '@design.estate/dees-element';
|
||||||
|
|
||||||
@ -23,13 +24,9 @@ export class CloudlyViewImages extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewLogs extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,14 +32,8 @@ export class CloudlyViewMails extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
css`
|
shared.viewHostCss,
|
||||||
:host {
|
css``
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,8 @@ export class CloudlyViewOverview extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 8px 16px;
|
|
||||||
}
|
|
||||||
.clusterGrid {
|
.clusterGrid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: ${cssManager.cssGridColumns(3, 8)};
|
grid-template-columns: ${cssManager.cssGridColumns(3, 8)};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewS3 extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewSecretBundles extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import { DeesElement, customElement, html, state, css, cssManager } from '@design.estate/dees-element';
|
import { DeesElement, customElement, html, state, css, cssManager } from '@design.estate/dees-element';
|
||||||
|
|
||||||
@ -23,13 +24,9 @@ export class CloudlyViewSecretGroups extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import * as plugins from '../plugins.js';
|
import * as plugins from '../plugins.js';
|
||||||
|
import * as shared from '../elements/shared/index.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeesElement,
|
DeesElement,
|
||||||
@ -31,13 +32,9 @@ export class CloudlyViewServices extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
max-width: 1280px;
|
|
||||||
padding: 16px 16px;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ export class CloudlySectionheading extends DeesElement {
|
|||||||
h1 {
|
h1 {
|
||||||
font-family: 'Cal Sans';
|
font-family: 'Cal Sans';
|
||||||
letter-spacing: 0.025em;
|
letter-spacing: 0.025em;
|
||||||
|
margin: 0px;
|
||||||
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
]
|
]
|
||||||
|
10
ts_web/elements/shared/css.ts
Normal file
10
ts_web/elements/shared/css.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { css } from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
export const viewHostCss = css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
max-width: 1280px;
|
||||||
|
padding: 16px 16px;
|
||||||
|
}
|
||||||
|
`;
|
@ -1 +1,2 @@
|
|||||||
export * from './cloudly-sectionheading.js';
|
export * from './cloudly-sectionheading.js';
|
||||||
|
export * from './css.js';
|
Loading…
Reference in New Issue
Block a user