@serve.zone/cli 5.0.4 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts_cliclient/index.js +19 -3
- package/package.json +4 -4
- package/readme.md +58 -215
- package/ts_cliclient/index.ts +20 -3
- package/ts_cliclient/readme.md +58 -215
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
-
import { CliClient } from
|
|
2
|
+
import { CliClient } from './classes.cliclient.js';
|
|
3
3
|
export const runCli = async () => {
|
|
4
4
|
const cliQenv = new plugins.qenv.Qenv();
|
|
5
|
+
const cloudlyUrl = await cliQenv.getEnvVarOnDemand('CLOUDLY_URL');
|
|
6
|
+
const token = process.env.CLOUDLY_TOKEN;
|
|
7
|
+
const username = process.env.CLOUDLY_USERNAME;
|
|
8
|
+
const password = process.env.CLOUDLY_PASSWORD;
|
|
5
9
|
const apiClient = new plugins.servezoneApi.CloudlyApiClient({
|
|
6
10
|
registerAs: 'cli',
|
|
7
|
-
cloudlyUrl
|
|
11
|
+
cloudlyUrl,
|
|
8
12
|
});
|
|
13
|
+
await apiClient.start();
|
|
14
|
+
if (token) {
|
|
15
|
+
await apiClient.getIdentityByToken(token, { tagConnection: true, statefullIdentity: true });
|
|
16
|
+
}
|
|
17
|
+
else if (username && password) {
|
|
18
|
+
await apiClient.loginWithUsernameAndPassword(username, password);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
console.log('No credentials provided. Set CLOUDLY_TOKEN or CLOUDLY_USERNAME/CLOUDLY_PASSWORD.');
|
|
22
|
+
}
|
|
9
23
|
const cliClient = new CliClient(apiClient);
|
|
24
|
+
// Default action example: list clusters when invoked without subcommands
|
|
25
|
+
await cliClient.getClusters();
|
|
10
26
|
};
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19jbGljbGllbnQvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRW5ELE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxLQUFLLElBQUksRUFBRTtJQUMvQixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDeEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxPQUFPLENBQUMsaUJBQWlCLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDbEUsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7SUFDeEMsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQztJQUM5QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDO0lBRTlDLE1BQU0sU0FBUyxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQztRQUMxRCxVQUFVLEVBQUUsS0FBSztRQUNqQixVQUFVO0tBQ1gsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7SUFFeEIsSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUNWLE1BQU0sU0FBUyxDQUFDLGtCQUFrQixDQUFDLEtBQUssRUFBRSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM5RixDQUFDO1NBQU0sSUFBSSxRQUFRLElBQUksUUFBUSxFQUFFLENBQUM7UUFDaEMsTUFBTSxTQUFTLENBQUMsNEJBQTRCLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ25FLENBQUM7U0FBTSxDQUFDO1FBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxrRkFBa0YsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7SUFFRCxNQUFNLFNBQVMsR0FBRyxJQUFJLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMzQyx5RUFBeUU7SUFDekUsTUFBTSxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7QUFDaEMsQ0FBQyxDQUFDIn0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/cli",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "",
|
|
6
6
|
"exports": {
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@serve.zone/api": "5.
|
|
13
|
-
"@serve.zone/interfaces": "5.0
|
|
12
|
+
"@serve.zone/api": "^5.3.4",
|
|
13
|
+
"@serve.zone/interfaces": "^5.5.0",
|
|
14
14
|
"@push.rocks/projectinfo": "^5.0.1",
|
|
15
|
-
"@push.rocks/qenv": "^6.1.
|
|
15
|
+
"@push.rocks/qenv": "^6.1.3",
|
|
16
16
|
"@push.rocks/smartcli": "^4.0.11"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
package/readme.md
CHANGED
|
@@ -1,262 +1,105 @@
|
|
|
1
1
|
# @serve.zone/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@serve.zone/cli` is the published Cloudly CLI submodule. It provides the `servezone` binary and currently acts as a thin environment-driven client for connecting to a Cloudly control plane and listing clusters through `@serve.zone/api`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Issue Reporting and Security
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
npm install @serve.zone/cli --save
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
This command will download the package and integrate it into your project's `node_modules` directory, reflecting the dependency in your `package.json`.
|
|
14
|
-
|
|
15
|
-
## Usage
|
|
9
|
+
## Current Scope
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
This submodule is intentionally small in the current codebase:
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
- Reads `CLOUDLY_URL` through `@push.rocks/qenv`.
|
|
14
|
+
- Authenticates with either `CLOUDLY_TOKEN` or `CLOUDLY_USERNAME` plus `CLOUDLY_PASSWORD`.
|
|
15
|
+
- Starts a `CloudlyApiClient` registered as `cli`.
|
|
16
|
+
- Creates a `CliClient` wrapper around the API client.
|
|
17
|
+
- Calls `CliClient.getClusters()` and prints the result.
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
- Latest Node.js LTS version installed.
|
|
23
|
-
- Familiarity with basic command-line operations.
|
|
24
|
-
- Properly configured cloud service accounts (like Cloudflare, Hetzner), necessary for managing respective services.
|
|
19
|
+
It is not currently a full command tree for services, secrets, deployments, logs, profiles, or shell completion. Those flows should be implemented against `@serve.zone/api` before documenting them as CLI commands.
|
|
25
20
|
|
|
26
|
-
|
|
21
|
+
## Installation
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
// Import required modules
|
|
31
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
32
|
-
import * as path from 'path';
|
|
33
|
-
|
|
34
|
-
// Define the configuration needed for cloud operations
|
|
35
|
-
const cloudlyConfig = {
|
|
36
|
-
cfToken: 'your-cloudflare-token',
|
|
37
|
-
hetznerToken: 'your-hetzner-token',
|
|
38
|
-
environment: 'production',
|
|
39
|
-
publicUrl: 'your-public-url',
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// Instantiate and start the Cloudly instance
|
|
43
|
-
const cloudlyInstance = new Cloudly(cloudlyConfig);
|
|
44
|
-
await cloudlyInstance.start();
|
|
45
|
-
|
|
46
|
-
// Log the setup information to ensure it’s correct
|
|
47
|
-
console.log(`Cloudly is set up at ${cloudlyInstance.config.data.publicUrl}`);
|
|
48
|
-
```
|
|
23
|
+
The package is published from `cloudly/ts_cliclient` via `tspublish.json` under the name `@serve.zone/cli` with the `servezone` binary.
|
|
49
24
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
### Core Operations with the CLI
|
|
53
|
-
|
|
54
|
-
Here's how you leverage various operational commands within the CLI feature:
|
|
55
|
-
|
|
56
|
-
#### Managing Clusters
|
|
57
|
-
|
|
58
|
-
To create, list, and delete clusters, you’ll require invoking the `Cloudly` class with its cluster management logic:
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
// Module imports
|
|
62
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
63
|
-
|
|
64
|
-
// Async function for cluster management
|
|
65
|
-
async function manageCluster() {
|
|
66
|
-
// Prepare configuration
|
|
67
|
-
const config = {
|
|
68
|
-
cfToken: 'YOUR_CLOUDFLARE_TOKEN',
|
|
69
|
-
hetznerToken: 'YOUR_HETZNER_TOKEN',
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// Initialize Cloudly
|
|
73
|
-
const cloudlyInstance = new Cloudly(config);
|
|
74
|
-
await cloudlyInstance.start();
|
|
75
|
-
|
|
76
|
-
// Example: Creating a new cluster
|
|
77
|
-
const cluster = await cloudlyInstance.clusterManager.createCluster({
|
|
78
|
-
id: 'example_cluster_id',
|
|
79
|
-
data: {
|
|
80
|
-
name: 'example_cluster',
|
|
81
|
-
servers: [],
|
|
82
|
-
sshKeys: [],
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// Log cluster details
|
|
87
|
-
console.log('Cluster created:', cluster);
|
|
88
|
-
}
|
|
25
|
+
```sh
|
|
26
|
+
pnpm add -g @serve.zone/cli
|
|
89
27
|
```
|
|
90
|
-
With the above example, you can dynamically manage cluster configurations, ensuring your application components are effectively orchestrated across cloud environments.
|
|
91
|
-
|
|
92
|
-
#### Deploying Services
|
|
93
|
-
|
|
94
|
-
Deploying cloud-native services within your clusters can be achieved through the CLI:
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
98
|
-
|
|
99
|
-
// Function to handle service deployment
|
|
100
|
-
async function deployService() {
|
|
101
|
-
const config = {
|
|
102
|
-
cfToken: 'YOUR_CLOUDFLARE_TOKEN',
|
|
103
|
-
hetznerToken: 'YOUR_HETZNER_TOKEN',
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const cloudlyInstance = new Cloudly(config);
|
|
107
|
-
await cloudlyInstance.start();
|
|
108
|
-
|
|
109
|
-
// Deploy a new service to a specified cluster
|
|
110
|
-
const newService = {
|
|
111
|
-
id: 'example_service_id',
|
|
112
|
-
data: {
|
|
113
|
-
name: 'example_service',
|
|
114
|
-
imageId: 'example_image_id',
|
|
115
|
-
imageVersion: '1.0.0',
|
|
116
|
-
environment: {},
|
|
117
|
-
ports: { web: 80 }
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
// Store service into database and deploy
|
|
122
|
-
console.log('Deploying service:', newService)
|
|
123
|
-
await cloudlyInstance.serverManager.deployService(newService);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
deployService();
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
By streamlining your service deployments through CLI, you ensure reproducibility and clarity in development operations.
|
|
130
|
-
|
|
131
|
-
#### Managing Certificates
|
|
132
|
-
|
|
133
|
-
Ensuring secure connections by managing SSL certificates is essential. The CLI aids in this through Let's Encrypt integration:
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
137
|
-
|
|
138
|
-
// Function to acquire a certificate
|
|
139
|
-
async function getCertificate() {
|
|
140
|
-
const config = {
|
|
141
|
-
cfToken: 'YOUR_CLOUDFLARE_TOKEN',
|
|
142
|
-
hetznerToken: 'YOUR_HETZNER_TOKEN',
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const cloudlyInstance = new Cloudly(config);
|
|
146
|
-
await cloudlyInstance.start();
|
|
147
28
|
|
|
148
|
-
|
|
149
|
-
const domainName = 'example.com';
|
|
150
|
-
const cert = await cloudlyInstance.letsencryptConnector.getCertificateForDomain(domainName);
|
|
151
|
-
console.log(`Obtained certificate for domain ${domainName}:`, cert);
|
|
152
|
-
}
|
|
29
|
+
For local development inside the Cloudly repository, build the parent package:
|
|
153
30
|
|
|
154
|
-
|
|
31
|
+
```sh
|
|
32
|
+
pnpm install
|
|
33
|
+
pnpm build
|
|
155
34
|
```
|
|
156
35
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
### Automating Tasks with the CLI
|
|
160
|
-
|
|
161
|
-
Task scheduling is a feature you can utilize to automate recurring processes. Here’s an example of how `@serve.zone/cli` accomplishes task scheduling:
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
import { TaskBuffer } from '@push.rocks/taskbuffer';
|
|
36
|
+
## Usage
|
|
165
37
|
|
|
166
|
-
|
|
167
|
-
const dailyTask = new TaskBuffer({
|
|
168
|
-
schedule: '0 0 * * *', // Using cron schedule
|
|
169
|
-
taskFunction: async () => {
|
|
170
|
-
console.log('Performing daily backup check...');
|
|
171
|
-
// Include backup logic here
|
|
172
|
-
},
|
|
173
|
-
});
|
|
38
|
+
Authenticate with a machine token:
|
|
174
39
|
|
|
175
|
-
|
|
176
|
-
|
|
40
|
+
```sh
|
|
41
|
+
CLOUDLY_URL=https://cloudly.example.com \
|
|
42
|
+
CLOUDLY_TOKEN=cluster-or-api-token \
|
|
43
|
+
servezone
|
|
177
44
|
```
|
|
178
45
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
### Integrating Third-Party APIs
|
|
182
|
-
|
|
183
|
-
Expand the scope of your applications with API integrations offered via `@serve.zone/cli`:
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
46
|
+
Authenticate with username and password:
|
|
187
47
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
const cloudly = new Cloudly(cloudlyConfig);
|
|
196
|
-
await cloudly.start();
|
|
197
|
-
|
|
198
|
-
// Configure and send push notification
|
|
199
|
-
await cloudly.externalApiManager.sendPushMessage({
|
|
200
|
-
deviceToken: 'some_device_token',
|
|
201
|
-
message: 'Hello from Cloudly!',
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
sendNotification();
|
|
48
|
+
```sh
|
|
49
|
+
CLOUDLY_URL=https://cloudly.example.com \
|
|
50
|
+
CLOUDLY_USERNAME=admin \
|
|
51
|
+
CLOUDLY_PASSWORD=change-me \
|
|
52
|
+
servezone
|
|
206
53
|
```
|
|
207
54
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
### Security and Access Management
|
|
55
|
+
When `CLOUDLY_TOKEN` is present, the CLI requests a stateful identity and asks Cloudly to tag the WebSocket connection. When username/password are present instead, it uses Cloudly's admin login flow. If no credentials are provided, the CLI prints a warning before attempting the default cluster-list operation.
|
|
211
56
|
|
|
212
|
-
|
|
57
|
+
## Programmatic Use
|
|
213
58
|
|
|
214
|
-
|
|
215
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
59
|
+
The submodule exports the `runCli()` entry point and uses `CliClient` internally:
|
|
216
60
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
cfToken: 'your-cloudflare-token',
|
|
221
|
-
hetznerToken: 'your-hetzner-token',
|
|
222
|
-
};
|
|
61
|
+
```ts
|
|
62
|
+
import { CloudlyApiClient } from '@serve.zone/api';
|
|
63
|
+
import { CliClient } from './classes.cliclient.js';
|
|
223
64
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const userIdentity = {
|
|
229
|
-
userId: 'unique_user_id',
|
|
230
|
-
jwt: 'user_jwt_token',
|
|
231
|
-
};
|
|
65
|
+
const apiClient = new CloudlyApiClient({
|
|
66
|
+
registerAs: 'cli',
|
|
67
|
+
cloudlyUrl: 'https://cloudly.example.com',
|
|
68
|
+
});
|
|
232
69
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
console.log(`Is user identity valid? ${isValid}`);
|
|
236
|
-
}
|
|
70
|
+
await apiClient.start();
|
|
71
|
+
await apiClient.loginWithUsernameAndPassword('admin', 'change-me');
|
|
237
72
|
|
|
238
|
-
|
|
73
|
+
const cli = new CliClient(apiClient);
|
|
74
|
+
await cli.getClusters();
|
|
239
75
|
```
|
|
240
76
|
|
|
241
|
-
|
|
77
|
+
## Files
|
|
242
78
|
|
|
243
|
-
|
|
79
|
+
| Path | Purpose |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `index.ts` | Runtime entry point for the published CLI. |
|
|
82
|
+
| `classes.cliclient.ts` | Minimal client wrapper; currently exposes `getClusters()`. |
|
|
83
|
+
| `plugins.ts` | Centralized imports for the submodule. |
|
|
84
|
+
| `tspublish.json` | Published package name, dependencies, registry targets, and `servezone` bin metadata. |
|
|
244
85
|
|
|
245
86
|
## License and Legal Information
|
|
246
87
|
|
|
247
|
-
This repository contains open-source code
|
|
88
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](../license) file.
|
|
248
89
|
|
|
249
90
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
250
91
|
|
|
251
92
|
### Trademarks
|
|
252
93
|
|
|
253
|
-
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein.
|
|
94
|
+
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
|
95
|
+
|
|
96
|
+
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
|
254
97
|
|
|
255
98
|
### Company Information
|
|
256
99
|
|
|
257
100
|
Task Venture Capital GmbH
|
|
258
|
-
Registered at District
|
|
101
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
259
102
|
|
|
260
|
-
For any legal inquiries or
|
|
103
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
261
104
|
|
|
262
105
|
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
package/ts_cliclient/index.ts
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
-
import { CliClient } from
|
|
2
|
+
import { CliClient } from './classes.cliclient.js';
|
|
3
3
|
|
|
4
4
|
export const runCli = async () => {
|
|
5
5
|
const cliQenv = new plugins.qenv.Qenv();
|
|
6
|
+
const cloudlyUrl = await cliQenv.getEnvVarOnDemand('CLOUDLY_URL');
|
|
7
|
+
const token = process.env.CLOUDLY_TOKEN;
|
|
8
|
+
const username = process.env.CLOUDLY_USERNAME;
|
|
9
|
+
const password = process.env.CLOUDLY_PASSWORD;
|
|
10
|
+
|
|
6
11
|
const apiClient = new plugins.servezoneApi.CloudlyApiClient({
|
|
7
12
|
registerAs: 'cli',
|
|
8
|
-
cloudlyUrl
|
|
13
|
+
cloudlyUrl,
|
|
9
14
|
});
|
|
15
|
+
await apiClient.start();
|
|
16
|
+
|
|
17
|
+
if (token) {
|
|
18
|
+
await apiClient.getIdentityByToken(token, { tagConnection: true, statefullIdentity: true });
|
|
19
|
+
} else if (username && password) {
|
|
20
|
+
await apiClient.loginWithUsernameAndPassword(username, password);
|
|
21
|
+
} else {
|
|
22
|
+
console.log('No credentials provided. Set CLOUDLY_TOKEN or CLOUDLY_USERNAME/CLOUDLY_PASSWORD.');
|
|
23
|
+
}
|
|
24
|
+
|
|
10
25
|
const cliClient = new CliClient(apiClient);
|
|
11
|
-
|
|
26
|
+
// Default action example: list clusters when invoked without subcommands
|
|
27
|
+
await cliClient.getClusters();
|
|
28
|
+
};
|
package/ts_cliclient/readme.md
CHANGED
|
@@ -1,262 +1,105 @@
|
|
|
1
1
|
# @serve.zone/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@serve.zone/cli` is the published Cloudly CLI submodule. It provides the `servezone` binary and currently acts as a thin environment-driven client for connecting to a Cloudly control plane and listing clusters through `@serve.zone/api`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Issue Reporting and Security
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
npm install @serve.zone/cli --save
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
This command will download the package and integrate it into your project's `node_modules` directory, reflecting the dependency in your `package.json`.
|
|
14
|
-
|
|
15
|
-
## Usage
|
|
9
|
+
## Current Scope
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
This submodule is intentionally small in the current codebase:
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
- Reads `CLOUDLY_URL` through `@push.rocks/qenv`.
|
|
14
|
+
- Authenticates with either `CLOUDLY_TOKEN` or `CLOUDLY_USERNAME` plus `CLOUDLY_PASSWORD`.
|
|
15
|
+
- Starts a `CloudlyApiClient` registered as `cli`.
|
|
16
|
+
- Creates a `CliClient` wrapper around the API client.
|
|
17
|
+
- Calls `CliClient.getClusters()` and prints the result.
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
- Latest Node.js LTS version installed.
|
|
23
|
-
- Familiarity with basic command-line operations.
|
|
24
|
-
- Properly configured cloud service accounts (like Cloudflare, Hetzner), necessary for managing respective services.
|
|
19
|
+
It is not currently a full command tree for services, secrets, deployments, logs, profiles, or shell completion. Those flows should be implemented against `@serve.zone/api` before documenting them as CLI commands.
|
|
25
20
|
|
|
26
|
-
|
|
21
|
+
## Installation
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
// Import required modules
|
|
31
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
32
|
-
import * as path from 'path';
|
|
33
|
-
|
|
34
|
-
// Define the configuration needed for cloud operations
|
|
35
|
-
const cloudlyConfig = {
|
|
36
|
-
cfToken: 'your-cloudflare-token',
|
|
37
|
-
hetznerToken: 'your-hetzner-token',
|
|
38
|
-
environment: 'production',
|
|
39
|
-
publicUrl: 'your-public-url',
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// Instantiate and start the Cloudly instance
|
|
43
|
-
const cloudlyInstance = new Cloudly(cloudlyConfig);
|
|
44
|
-
await cloudlyInstance.start();
|
|
45
|
-
|
|
46
|
-
// Log the setup information to ensure it’s correct
|
|
47
|
-
console.log(`Cloudly is set up at ${cloudlyInstance.config.data.publicUrl}`);
|
|
48
|
-
```
|
|
23
|
+
The package is published from `cloudly/ts_cliclient` via `tspublish.json` under the name `@serve.zone/cli` with the `servezone` binary.
|
|
49
24
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
### Core Operations with the CLI
|
|
53
|
-
|
|
54
|
-
Here's how you leverage various operational commands within the CLI feature:
|
|
55
|
-
|
|
56
|
-
#### Managing Clusters
|
|
57
|
-
|
|
58
|
-
To create, list, and delete clusters, you’ll require invoking the `Cloudly` class with its cluster management logic:
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
// Module imports
|
|
62
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
63
|
-
|
|
64
|
-
// Async function for cluster management
|
|
65
|
-
async function manageCluster() {
|
|
66
|
-
// Prepare configuration
|
|
67
|
-
const config = {
|
|
68
|
-
cfToken: 'YOUR_CLOUDFLARE_TOKEN',
|
|
69
|
-
hetznerToken: 'YOUR_HETZNER_TOKEN',
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// Initialize Cloudly
|
|
73
|
-
const cloudlyInstance = new Cloudly(config);
|
|
74
|
-
await cloudlyInstance.start();
|
|
75
|
-
|
|
76
|
-
// Example: Creating a new cluster
|
|
77
|
-
const cluster = await cloudlyInstance.clusterManager.createCluster({
|
|
78
|
-
id: 'example_cluster_id',
|
|
79
|
-
data: {
|
|
80
|
-
name: 'example_cluster',
|
|
81
|
-
servers: [],
|
|
82
|
-
sshKeys: [],
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// Log cluster details
|
|
87
|
-
console.log('Cluster created:', cluster);
|
|
88
|
-
}
|
|
25
|
+
```sh
|
|
26
|
+
pnpm add -g @serve.zone/cli
|
|
89
27
|
```
|
|
90
|
-
With the above example, you can dynamically manage cluster configurations, ensuring your application components are effectively orchestrated across cloud environments.
|
|
91
|
-
|
|
92
|
-
#### Deploying Services
|
|
93
|
-
|
|
94
|
-
Deploying cloud-native services within your clusters can be achieved through the CLI:
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
98
|
-
|
|
99
|
-
// Function to handle service deployment
|
|
100
|
-
async function deployService() {
|
|
101
|
-
const config = {
|
|
102
|
-
cfToken: 'YOUR_CLOUDFLARE_TOKEN',
|
|
103
|
-
hetznerToken: 'YOUR_HETZNER_TOKEN',
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const cloudlyInstance = new Cloudly(config);
|
|
107
|
-
await cloudlyInstance.start();
|
|
108
|
-
|
|
109
|
-
// Deploy a new service to a specified cluster
|
|
110
|
-
const newService = {
|
|
111
|
-
id: 'example_service_id',
|
|
112
|
-
data: {
|
|
113
|
-
name: 'example_service',
|
|
114
|
-
imageId: 'example_image_id',
|
|
115
|
-
imageVersion: '1.0.0',
|
|
116
|
-
environment: {},
|
|
117
|
-
ports: { web: 80 }
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
// Store service into database and deploy
|
|
122
|
-
console.log('Deploying service:', newService)
|
|
123
|
-
await cloudlyInstance.serverManager.deployService(newService);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
deployService();
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
By streamlining your service deployments through CLI, you ensure reproducibility and clarity in development operations.
|
|
130
|
-
|
|
131
|
-
#### Managing Certificates
|
|
132
|
-
|
|
133
|
-
Ensuring secure connections by managing SSL certificates is essential. The CLI aids in this through Let's Encrypt integration:
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
137
|
-
|
|
138
|
-
// Function to acquire a certificate
|
|
139
|
-
async function getCertificate() {
|
|
140
|
-
const config = {
|
|
141
|
-
cfToken: 'YOUR_CLOUDFLARE_TOKEN',
|
|
142
|
-
hetznerToken: 'YOUR_HETZNER_TOKEN',
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const cloudlyInstance = new Cloudly(config);
|
|
146
|
-
await cloudlyInstance.start();
|
|
147
28
|
|
|
148
|
-
|
|
149
|
-
const domainName = 'example.com';
|
|
150
|
-
const cert = await cloudlyInstance.letsencryptConnector.getCertificateForDomain(domainName);
|
|
151
|
-
console.log(`Obtained certificate for domain ${domainName}:`, cert);
|
|
152
|
-
}
|
|
29
|
+
For local development inside the Cloudly repository, build the parent package:
|
|
153
30
|
|
|
154
|
-
|
|
31
|
+
```sh
|
|
32
|
+
pnpm install
|
|
33
|
+
pnpm build
|
|
155
34
|
```
|
|
156
35
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
### Automating Tasks with the CLI
|
|
160
|
-
|
|
161
|
-
Task scheduling is a feature you can utilize to automate recurring processes. Here’s an example of how `@serve.zone/cli` accomplishes task scheduling:
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
import { TaskBuffer } from '@push.rocks/taskbuffer';
|
|
36
|
+
## Usage
|
|
165
37
|
|
|
166
|
-
|
|
167
|
-
const dailyTask = new TaskBuffer({
|
|
168
|
-
schedule: '0 0 * * *', // Using cron schedule
|
|
169
|
-
taskFunction: async () => {
|
|
170
|
-
console.log('Performing daily backup check...');
|
|
171
|
-
// Include backup logic here
|
|
172
|
-
},
|
|
173
|
-
});
|
|
38
|
+
Authenticate with a machine token:
|
|
174
39
|
|
|
175
|
-
|
|
176
|
-
|
|
40
|
+
```sh
|
|
41
|
+
CLOUDLY_URL=https://cloudly.example.com \
|
|
42
|
+
CLOUDLY_TOKEN=cluster-or-api-token \
|
|
43
|
+
servezone
|
|
177
44
|
```
|
|
178
45
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
### Integrating Third-Party APIs
|
|
182
|
-
|
|
183
|
-
Expand the scope of your applications with API integrations offered via `@serve.zone/cli`:
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
46
|
+
Authenticate with username and password:
|
|
187
47
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
const cloudly = new Cloudly(cloudlyConfig);
|
|
196
|
-
await cloudly.start();
|
|
197
|
-
|
|
198
|
-
// Configure and send push notification
|
|
199
|
-
await cloudly.externalApiManager.sendPushMessage({
|
|
200
|
-
deviceToken: 'some_device_token',
|
|
201
|
-
message: 'Hello from Cloudly!',
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
sendNotification();
|
|
48
|
+
```sh
|
|
49
|
+
CLOUDLY_URL=https://cloudly.example.com \
|
|
50
|
+
CLOUDLY_USERNAME=admin \
|
|
51
|
+
CLOUDLY_PASSWORD=change-me \
|
|
52
|
+
servezone
|
|
206
53
|
```
|
|
207
54
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
### Security and Access Management
|
|
55
|
+
When `CLOUDLY_TOKEN` is present, the CLI requests a stateful identity and asks Cloudly to tag the WebSocket connection. When username/password are present instead, it uses Cloudly's admin login flow. If no credentials are provided, the CLI prints a warning before attempting the default cluster-list operation.
|
|
211
56
|
|
|
212
|
-
|
|
57
|
+
## Programmatic Use
|
|
213
58
|
|
|
214
|
-
|
|
215
|
-
import { Cloudly } from '@serve.zone/cloudly';
|
|
59
|
+
The submodule exports the `runCli()` entry point and uses `CliClient` internally:
|
|
216
60
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
cfToken: 'your-cloudflare-token',
|
|
221
|
-
hetznerToken: 'your-hetzner-token',
|
|
222
|
-
};
|
|
61
|
+
```ts
|
|
62
|
+
import { CloudlyApiClient } from '@serve.zone/api';
|
|
63
|
+
import { CliClient } from './classes.cliclient.js';
|
|
223
64
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const userIdentity = {
|
|
229
|
-
userId: 'unique_user_id',
|
|
230
|
-
jwt: 'user_jwt_token',
|
|
231
|
-
};
|
|
65
|
+
const apiClient = new CloudlyApiClient({
|
|
66
|
+
registerAs: 'cli',
|
|
67
|
+
cloudlyUrl: 'https://cloudly.example.com',
|
|
68
|
+
});
|
|
232
69
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
console.log(`Is user identity valid? ${isValid}`);
|
|
236
|
-
}
|
|
70
|
+
await apiClient.start();
|
|
71
|
+
await apiClient.loginWithUsernameAndPassword('admin', 'change-me');
|
|
237
72
|
|
|
238
|
-
|
|
73
|
+
const cli = new CliClient(apiClient);
|
|
74
|
+
await cli.getClusters();
|
|
239
75
|
```
|
|
240
76
|
|
|
241
|
-
|
|
77
|
+
## Files
|
|
242
78
|
|
|
243
|
-
|
|
79
|
+
| Path | Purpose |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `index.ts` | Runtime entry point for the published CLI. |
|
|
82
|
+
| `classes.cliclient.ts` | Minimal client wrapper; currently exposes `getClusters()`. |
|
|
83
|
+
| `plugins.ts` | Centralized imports for the submodule. |
|
|
84
|
+
| `tspublish.json` | Published package name, dependencies, registry targets, and `servezone` bin metadata. |
|
|
244
85
|
|
|
245
86
|
## License and Legal Information
|
|
246
87
|
|
|
247
|
-
This repository contains open-source code
|
|
88
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](../license) file.
|
|
248
89
|
|
|
249
90
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
250
91
|
|
|
251
92
|
### Trademarks
|
|
252
93
|
|
|
253
|
-
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein.
|
|
94
|
+
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
|
95
|
+
|
|
96
|
+
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
|
254
97
|
|
|
255
98
|
### Company Information
|
|
256
99
|
|
|
257
100
|
Task Venture Capital GmbH
|
|
258
|
-
Registered at District
|
|
101
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
259
102
|
|
|
260
|
-
For any legal inquiries or
|
|
103
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
261
104
|
|
|
262
105
|
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|