fix(switch to unified package for cloudly + api + cli): update

This commit is contained in:
2024-05-28 18:45:34 +02:00
parent 33aa48b0b1
commit 21961fa2d7
40 changed files with 6531 additions and 4719 deletions

346
readme.md
View File

@@ -1,5 +1,5 @@
# @serve.zone/cloudly
configure the cloud
A cloud manager utilizing Docker Swarmkit, designed for operations on Cloudron, and supports various cloud platforms like DigitalOcean, Hetzner Cloud, and Cloudflare.
## Install
To install `@serve.zone/cloudly`, run the following command in your terminal:
@@ -45,44 +45,346 @@ const myCloudlyInstance = new Cloudly(myCloudlyConfig);
```
#### Managing Docker Swarmkit Cluster
Cloudly allows managing Docker Swarmkit clusters through an abstracted interface, simplifying operations such as deployment and scaling.
Cloudly allows managing Docker Swarmkit clusters through an abstracted interface, simplifying operations such as deployment and scaling. Below are examples to demonstrate these capabilities.
### Example: Start a Cloudly Instance and Add a Cluster
```typescript
// Assuming myCloudlyInstance is already configured and initialized
import { Cloudly, ClusterManager } from '@serve.zone/cloudly';
// Start the cloud instance
await myCloudlyInstance.start();
async function main() {
const myCloudlyConfig = {
mongoDescriptor: {
mongoDbUrl: 'mongodb+srv://<username>:<password>@<cluster>.mongodb.net/myFirstDatabase',
mongoDbName: 'myDatabase',
mongoDbUser: 'myUser',
mongoDbPass: 'myPassword',
},
cfToken: 'your_cloudflare_api_token',
environment: 'development',
letsEncryptEmail: 'lets_encrypt_email@example.com',
publicUrl: 'example.com',
publicPort: 8443,
hetznerToken: 'your_hetzner_api_token'
};
// Now you can perform various operations on your Docker Swarmkit cluster
const myCloudlyInstance = new Cloudly(myCloudlyConfig);
await myCloudlyInstance.start();
const clusterManager = myCloudlyInstance.clusterManager;
const newCluster = await clusterManager.storeCluster({
id: 'example_cluster_id',
data: {
name: 'example_cluster',
jumpCode: 'random_jump_code',
jumpCodeUsedAt: null,
secretKey: 'example_secret_key',
acmeInfo: null,
cloudlyUrl: 'https://example.com:8443',
servers: [],
sshKeys: [],
},
});
console.log('Cluster added:', newCluster);
}
main();
```
### Integration with Cloud Providers
`@serve.zone/cloudly` integrates seamlessly with cloud providers like DigitalOcean, Hetzner Cloud, etc., by leveraging the power of APIs provided by these platforms.
#### Managing DigitalOcean Resources
To manage DigitalOcean resources, you'll need to configure your DigitalOcean token and then use the provided interfaces to interact with the resources, such as creating droplets, managing volumes, etc.
### Example: Manage Cloudflare DNS Records
```typescript
// Set your DigitalOcean API token
const digitalOceanToken = "your_digital_ocean_api_token";
import { Cloudly, CloudflareConnector } from '@serve.zone/cloudly';
// Now you can use myCloudlyInstance to manage DigitalOcean resources
async function manageDNSRecords() {
const myCloudlyConfig = {
mongoDescriptor: {
mongoDbUrl: 'mongodb+srv://<username>:<password>@<cluster>.mongodb.net/myFirstDatabase',
mongoDbName: 'myDatabase',
mongoDbUser: 'myUser',
mongoDbPass: 'myPassword',
},
cfToken: 'your_cloudflare_api_token',
environment: 'development',
letsEncryptEmail: 'lets_encrypt_email@example.com',
publicUrl: 'example.com',
publicPort: 8443,
hetznerToken: 'your_hetzner_api_token'
};
const myCloudlyInstance = new Cloudly(myCloudlyConfig);
await myCloudlyInstance.start();
const dnsInfo = {
zoneName: 'example.com',
recordName: 'sub.example.com',
recordType: 'A',
recordContent: '127.0.0.1',
};
const cfConnector = myCloudlyInstance.cloudflareConnector.cloudflare;
const newRecord = await cfConnector.createDNSRecord(
dnsInfo.zoneName,
dnsInfo.recordName,
dnsInfo.recordType,
dnsInfo.recordContent
);
console.log('DNS Record created:', newRecord);
}
manageDNSRecords();
```
#### Using the Cloudflare Integration
Similarly, for managing DNS records and SSL certificates with Cloudflare, set up your Cloudflare API token:
### Example: Integrate with DigitalOcean
```typescript
const cloudflareToken = "your_cloudflare_api_token";
import { Cloudly, DigitalOceanConnector } from '@serve.zone/cloudly';
// Use myCloudlyInstance to interact with Cloudflare, such as setting DNS records
async function manageDroplet() {
const myCloudlyConfig = {
mongoDescriptor: {
mongoDbUrl: 'mongodb+srv://<username>:<password>@<cluster>.mongodb.net/myFirstDatabase',
mongoDbName: 'myDatabase',
mongoDbUser: 'myUser',
mongoDbPass: 'myPassword',
},
cfToken: 'your_cloudflare_api_token',
environment: 'development',
letsEncryptEmail: 'lets_encrypt_email@example.com',
publicUrl: 'example.com',
publicPort: 8443,
hetznerToken: 'your_hetzner_api_token'
};
const myCloudlyInstance = new Cloudly(myCloudlyConfig);
await myCloudlyInstance.start();
const doConnector = myCloudlyInstance.digitaloceanConnector;
const dropletInfo = {
name: 'example-droplet',
region: 'nyc3',
size: 's-1vcpu-1gb',
image: 'ubuntu-20-04-x64',
};
const newDroplet = await doConnector.createDroplet(
dropletInfo.name,
dropletInfo.region,
dropletInfo.size,
dropletInfo.image
);
console.log('Droplet created:', newDroplet);
}
manageDroplet();
```
### Advanced Usage
`@serve.zone/cloudly` offers more than just cloud resource management. It integrates various modules for error logging, security, working with JSON data, and much more. Explore the comprehensive documentation and typings to leverage the full potential of the package.
### Using Cloudly Web Interface
If your project includes a web interface to manage various sections like DNS, deployments, clusters, etc., you can use the provided elements and state management. Below is an example of setting up a dashboard using the components defined:
### Conclusion
With `@serve.zone/cloudly`, configuring the cloud becomes a less tedious task. By abstracting away the complexities and providing a unified interface to manage cloud resources, development efficiency is significantly improved. The examples provided above merely scratch the surface of what's possible. Dive into the detailed documentation to explore all features and capabilities.
```typescript
import { commitinfo } from '../00_commitinfo_data.js';
import * as plugins from '../plugins.js';
import * as appstate from '../appstate.js';
import {
DeesElement,
css,
cssManager,
customElement,
html,
state
} from '@design.estate/dees-element';
import { CloudlyViewBackups } from './cloudly-view-backups.js';
import { CloudlyViewClusters } from './cloudly-view-clusters.js';
import { CloudlyViewDbs } from './cloudly-view-dbs.js';
import { CloudlyViewDeployments } from './cloudly-view-deployments.js';
import { CloudlyViewDns } from './cloudly-view-dns.js';
import { CloudlyViewImages } from './cloudly-view-images.js';
import { CloudlyViewLogs } from './cloudly-view-logs.js';
import { CloudlyViewMails } from './cloudly-view-mails.js';
import { CloudlyViewOverview } from './cloudly-view-overview.js';
import { CloudlyViewS3 } from './cloudly-view-s3.js';
import { CloudlyViewSecretBundles } from './cloudly-view-secretbundles.js';
import { CloudlyViewSecretGroups } from './cloudly-view-secretgroups.js';
import { CloudlyViewServices } from './cloudly-view-services.js';
declare global {
interface HTMLElementTagNameMap {
'cvault-dashboard': CloudlyDashboard;
}
}
@customElement('cloudly-dashboard')
export class CloudlyDashboard extends DeesElement {
@state() private jwt: string;
@state() private data: appstate.IDataState = {
secretGroups: [],
secretBundles: [],
clusters: [],
};
constructor() {
super();
const subcription = appstate.dataState
.select((stateArg) => stateArg)
.subscribe((dataArg) => {
this.data = dataArg;
});
this.rxSubscriptions.push(subcription);
}
public static styles = [
cssManager.defaultStyles,
css`
.maincontainer {
position: relative;
width: 100vw;
height: 100vh;
}
h1 {
font-weight: 400;
font-size: 24px;
font-family: 'Cal Sans';
}
`,
];
public render() {
return html`
<div class="maincontainer">
<dees-simple-login name="cloudly v${commitinfo.version}">
<dees-simple-appdash name="cloudly v${commitinfo.version}"
.viewTabs=${[
{
name: 'Overview',
element: CloudlyViewOverview,
},
{
name: 'SecretGroups',
element: CloudlyViewSecretGroups,
},
{
name: 'SecretBundles',
element: CloudlyViewSecretBundles,
},
{
name: 'Clusters',
element: CloudlyViewClusters,
},
{
name: 'Images',
element: CloudlyViewImages,
},
{
name: 'Services',
element: CloudlyViewServices,
},
{
name: 'Deployments',
element: CloudlyViewDeployments,
},
{
name: 'DNS',
element: CloudlyViewDns,
},
{
name: 'Mails',
element: CloudlyViewMails,
},
{
name: 'Logs',
element: CloudlyViewLogs,
},
{
name: 's3',
element: CloudlyViewS3,
},
{
name: 'DBs',
element: CloudlyViewDbs,
},
{
name: 'Backups',
element: CloudlyViewBackups,
},
] as plugins.deesCatalog.IView[]}
></dees-simple-appdash>
</dees-simple-login>
</div>
`;
}
public async firstUpdated() {
const simpleLogin = this.shadowRoot.querySelector('dees-simple-login');
simpleLogin.addEventListener('login', (e: CustomEvent) => {
console.log(e.detail);
this.login(e.detail.data.username, e.detail.data.password);
});
this.addEventListener('contextmenu', (eventArg) => {
plugins.deesCatalog.DeesContextmenu.openContextMenuWithOptions(eventArg, [
{
name: 'About',
iconName: 'mugHot',
action: async () => {
await plugins.deesCatalog.DeesModal.createAndShow({
heading: 'About',
content: html`configvault ${commitinfo.version}`,
menuOptions: [
{
name: 'close',
iconName: null,
action: async (modalArg) => {
await modalArg.destroy();
},
},
],
});
},
},
]);
});
// lets deal with initial state
const domtools = await this.domtoolsPromise;
const loginState = appstate.loginStatePart.getState();
console.log(loginState);
if (loginState.jwt) {
this.jwt = loginState.jwt;
await simpleLogin.switchToSlottedContent();
await appstate.dataState.dispatchAction(appstate.getDataAction, null);
}
}
private async login(username: string, password: string) {
console.log(`attempting to login...`);
const simpleLogin = this.shadowRoot.querySelector('dees-simple-login');
const form = simpleLogin.shadowRoot.querySelector('dees-form');
form.setStatus('pending', 'Logging in...');
const state = await appstate.loginStatePart.dispatchAction(appstate.loginAction, {
username,
password,
});
if (state.jwt) {
console.log('got jwt');
this.jwt = state.jwt;
form.setStatus('success', 'Logged in!');
await simpleLogin.switchToSlottedContent();
await appstate.dataState.dispatchAction(appstate.getDataAction, null);
} else {
form.setStatus('error', 'Login failed!');
await domtools.convenience.smartdelay.delayFor(2000);
form.reset();
}
}
private async logout() {}
}
```
This script sets up a cloud management dashboard for interacting with various cloud services seamlessly. It covers creating clusters, managing DNS records, handling cloud-provider-specific resources, and much more.
With the examples provided above, you should now have a good understanding of how to use `@serve.zone/cloudly` to manage your cloud infrastructure programmatically. For deeper insights and additional features, refer to the documentation relevant to specific modules and methods used in your application.
## License and Legal Information