fix(switch to unified package for cloudly + api + cli): update
This commit is contained in:
346
readme.md
346
readme.md
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user