@zincapp/znvault-plugin-payara 1.0.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/README.md +316 -0
- package/dist/cli.d.ts +40 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +234 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +83 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +139 -0
- package/dist/index.js.map +1 -0
- package/dist/payara-manager.d.ts +72 -0
- package/dist/payara-manager.d.ts.map +1 -0
- package/dist/payara-manager.js +239 -0
- package/dist/payara-manager.js.map +1 -0
- package/dist/routes.d.ts +11 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +247 -0
- package/dist/routes.js.map +1 -0
- package/dist/types.d.ts +94 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/war-deployer.d.ts +77 -0
- package/dist/war-deployer.d.ts.map +1 -0
- package/dist/war-deployer.js +312 -0
- package/dist/war-deployer.js.map +1 -0
- package/package.json +88 -0
package/README.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# @zincapp/znvault-plugin-payara
|
|
2
|
+
|
|
3
|
+
Payara application server management plugin for ZN-Vault Agent and CLI. Enables incremental WAR deployment with diff-based file transfer.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **WAR Diff Deployment**: Only transfer changed files, not entire WAR
|
|
8
|
+
- **Payara Lifecycle Management**: Start, stop, restart Payara domains
|
|
9
|
+
- **Certificate Integration**: Auto-restart on certificate deployment
|
|
10
|
+
- **Health Monitoring**: Plugin health status in agent health endpoint
|
|
11
|
+
- **CLI Commands**: Deploy WAR files from development machine
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @zincapp/znvault-plugin-payara
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Agent Configuration
|
|
20
|
+
|
|
21
|
+
Add the plugin to your agent's `config.json`:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"vaultUrl": "https://vault.example.com",
|
|
26
|
+
"tenantId": "my-tenant",
|
|
27
|
+
"auth": { "apiKey": "znv_..." },
|
|
28
|
+
"plugins": [
|
|
29
|
+
{
|
|
30
|
+
"package": "@zincapp/znvault-plugin-payara",
|
|
31
|
+
"config": {
|
|
32
|
+
"payaraHome": "/opt/payara",
|
|
33
|
+
"domain": "domain1",
|
|
34
|
+
"user": "payara",
|
|
35
|
+
"warPath": "/opt/app/MyApp.war",
|
|
36
|
+
"appName": "MyApp",
|
|
37
|
+
"healthEndpoint": "http://localhost:8080/health",
|
|
38
|
+
"restartOnCertChange": true
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Configuration Options
|
|
46
|
+
|
|
47
|
+
| Option | Type | Required | Description |
|
|
48
|
+
|--------|------|----------|-------------|
|
|
49
|
+
| `payaraHome` | string | Yes | Path to Payara installation |
|
|
50
|
+
| `domain` | string | Yes | Payara domain name |
|
|
51
|
+
| `user` | string | Yes | System user to run asadmin commands as |
|
|
52
|
+
| `warPath` | string | Yes | Path to the WAR file |
|
|
53
|
+
| `appName` | string | Yes | Application name in Payara |
|
|
54
|
+
| `healthEndpoint` | string | No | HTTP endpoint to check application health |
|
|
55
|
+
| `restartOnCertChange` | boolean | No | Restart Payara when certificates are deployed |
|
|
56
|
+
|
|
57
|
+
## HTTP API
|
|
58
|
+
|
|
59
|
+
The plugin registers routes under `/plugins/payara/`:
|
|
60
|
+
|
|
61
|
+
### GET /plugins/payara/hashes
|
|
62
|
+
|
|
63
|
+
Returns SHA-256 hashes of all files in the current WAR.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
curl http://localhost:9100/plugins/payara/hashes
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Response:
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"hashes": {
|
|
73
|
+
"WEB-INF/web.xml": "abc123...",
|
|
74
|
+
"index.html": "def456..."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### POST /plugins/payara/deploy
|
|
80
|
+
|
|
81
|
+
Apply file changes and deploy. Files are base64-encoded.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
curl -X POST http://localhost:9100/plugins/payara/deploy \
|
|
85
|
+
-H "Content-Type: application/json" \
|
|
86
|
+
-d '{
|
|
87
|
+
"files": [
|
|
88
|
+
{"path": "index.html", "content": "PGh0bWw+Li4uPC9odG1sPg=="}
|
|
89
|
+
],
|
|
90
|
+
"deletions": ["old-file.css"]
|
|
91
|
+
}'
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Response:
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"status": "deployed",
|
|
98
|
+
"filesChanged": 1,
|
|
99
|
+
"filesDeleted": 1,
|
|
100
|
+
"message": "Deployment successful"
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### POST /plugins/payara/deploy/full
|
|
105
|
+
|
|
106
|
+
Trigger a full WAR deployment (no diff).
|
|
107
|
+
|
|
108
|
+
### POST /plugins/payara/restart
|
|
109
|
+
|
|
110
|
+
Restart the Payara domain.
|
|
111
|
+
|
|
112
|
+
### POST /plugins/payara/start
|
|
113
|
+
|
|
114
|
+
Start the Payara domain.
|
|
115
|
+
|
|
116
|
+
### POST /plugins/payara/stop
|
|
117
|
+
|
|
118
|
+
Stop the Payara domain.
|
|
119
|
+
|
|
120
|
+
### GET /plugins/payara/status
|
|
121
|
+
|
|
122
|
+
Get current Payara status.
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"running": true,
|
|
127
|
+
"healthy": true,
|
|
128
|
+
"domain": "domain1"
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### GET /plugins/payara/applications
|
|
133
|
+
|
|
134
|
+
List deployed applications.
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"applications": ["MyApp", "OtherApp"]
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### GET /plugins/payara/file/*
|
|
143
|
+
|
|
144
|
+
Get a specific file from the WAR.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
curl http://localhost:9100/plugins/payara/file/WEB-INF/web.xml
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## CLI Commands
|
|
151
|
+
|
|
152
|
+
The plugin adds commands to `znvault`:
|
|
153
|
+
|
|
154
|
+
### Deploy WAR with diff
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Deploy changed files only
|
|
158
|
+
znvault deploy war ./target/MyApp.war --target server.example.com
|
|
159
|
+
|
|
160
|
+
# Force full deployment
|
|
161
|
+
znvault deploy war ./target/MyApp.war --target server.example.com --force
|
|
162
|
+
|
|
163
|
+
# Dry run - show what would be deployed
|
|
164
|
+
znvault deploy war ./target/MyApp.war --target server.example.com --dry-run
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Restart Payara
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
znvault deploy restart --target server.example.com
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Check Status
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
znvault deploy status --target server.example.com
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### List Applications
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
znvault deploy applications --target server.example.com
|
|
183
|
+
# or
|
|
184
|
+
znvault deploy apps --target server.example.com
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## CLI Configuration
|
|
188
|
+
|
|
189
|
+
Add the plugin to your CLI config (`~/.znvault/config.json`):
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"plugins": [
|
|
194
|
+
{
|
|
195
|
+
"package": "@zincapp/znvault-plugin-payara",
|
|
196
|
+
"enabled": true
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## How Diff Deployment Works
|
|
203
|
+
|
|
204
|
+
1. CLI calculates SHA-256 hash for every file in local WAR
|
|
205
|
+
2. CLI requests current hashes from agent (`GET /plugins/payara/hashes`)
|
|
206
|
+
3. CLI compares hashes to determine:
|
|
207
|
+
- **Changed files**: Hash differs or file is new
|
|
208
|
+
- **Deleted files**: Exists remotely but not locally
|
|
209
|
+
4. CLI sends only changed files (base64-encoded) and deletion list
|
|
210
|
+
5. Agent extracts current WAR to temp directory
|
|
211
|
+
6. Agent applies changes (updates, creates, deletes files)
|
|
212
|
+
7. Agent repackages WAR
|
|
213
|
+
8. Agent stops Payara, deploys WAR, starts Payara
|
|
214
|
+
|
|
215
|
+
This reduces deployment time from minutes (full WAR transfer) to seconds (incremental changes).
|
|
216
|
+
|
|
217
|
+
## Architecture
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
┌─────────────────┐ ┌─────────────────┐
|
|
221
|
+
│ Development │ │ Production │
|
|
222
|
+
│ Machine │ │ Server │
|
|
223
|
+
│ │ │ │
|
|
224
|
+
│ ┌───────────┐ │ Diff Transfer │ ┌───────────┐ │
|
|
225
|
+
│ │ Local WAR │ │ (changed files only) │ │ Agent │ │
|
|
226
|
+
│ └─────┬─────┘ │ ────────────────────────>│ │ + Plugin │ │
|
|
227
|
+
│ │ │ │ └─────┬─────┘ │
|
|
228
|
+
│ ┌─────▼─────┐ │ │ │ │
|
|
229
|
+
│ │ znvault │ │ GET /hashes │ ┌─────▼─────┐ │
|
|
230
|
+
│ │ deploy │◄─┼──────────────────────────┼──│ WAR File │ │
|
|
231
|
+
│ │ war │ │ │ └─────┬─────┘ │
|
|
232
|
+
│ └───────────┘ │ POST /deploy │ │ │
|
|
233
|
+
│ │ ────────────────────────>│ ┌─────▼─────┐ │
|
|
234
|
+
│ │ │ │ Payara │ │
|
|
235
|
+
│ │ │ │ Server │ │
|
|
236
|
+
│ │ │ └───────────┘ │
|
|
237
|
+
└─────────────────┘ └─────────────────┘
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Plugin Events
|
|
241
|
+
|
|
242
|
+
The plugin responds to zn-vault-agent lifecycle events:
|
|
243
|
+
|
|
244
|
+
### onCertificateDeployed
|
|
245
|
+
|
|
246
|
+
When `restartOnCertChange: true`, automatically restarts Payara after certificate deployment:
|
|
247
|
+
|
|
248
|
+
```javascript
|
|
249
|
+
// Plugin automatically handles this when certificates change
|
|
250
|
+
// No action needed from user
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### healthCheck
|
|
254
|
+
|
|
255
|
+
Reports Payara status to the agent's `/health` endpoint:
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
{
|
|
259
|
+
"plugins": {
|
|
260
|
+
"payara": {
|
|
261
|
+
"status": "healthy",
|
|
262
|
+
"details": {
|
|
263
|
+
"domain": "domain1",
|
|
264
|
+
"warPath": "/opt/app/MyApp.war"
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Development
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# Install dependencies
|
|
275
|
+
npm install
|
|
276
|
+
|
|
277
|
+
# Build
|
|
278
|
+
npm run build
|
|
279
|
+
|
|
280
|
+
# Run tests
|
|
281
|
+
npm test
|
|
282
|
+
|
|
283
|
+
# Run specific test suite
|
|
284
|
+
npm test test/integration/war-deployer.test.ts
|
|
285
|
+
|
|
286
|
+
# Type check
|
|
287
|
+
npm run typecheck
|
|
288
|
+
|
|
289
|
+
# Lint
|
|
290
|
+
npm run lint
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Test Coverage
|
|
294
|
+
|
|
295
|
+
| Suite | Tests | Description |
|
|
296
|
+
|-------|-------|-------------|
|
|
297
|
+
| Unit | 31 | Core plugin, CLI, WAR deployer logic |
|
|
298
|
+
| Integration | 49 | PayaraManager, WarDeployer, HTTP routes |
|
|
299
|
+
| E2E | 17 | Full deployment flow, plugin factory |
|
|
300
|
+
| **Total** | **97** | All tests passing |
|
|
301
|
+
|
|
302
|
+
## Requirements
|
|
303
|
+
|
|
304
|
+
- Node.js 18+
|
|
305
|
+
- Payara Server 5.x or 6.x
|
|
306
|
+
- `asadmin` in PATH or at `$PAYARA_HOME/bin/asadmin`
|
|
307
|
+
- Write access to WAR file location
|
|
308
|
+
- sudo access for running as different user (if configured)
|
|
309
|
+
|
|
310
|
+
## Migration from Python zinc_updater
|
|
311
|
+
|
|
312
|
+
See [MIGRATION.md](./MIGRATION.md) for step-by-step migration guide from the Python-based zinc_updater.
|
|
313
|
+
|
|
314
|
+
## License
|
|
315
|
+
|
|
316
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* CLI Plugin context interface
|
|
4
|
+
* Matches the CLIPluginContext from znvault-cli
|
|
5
|
+
*/
|
|
6
|
+
interface CLIPluginContext {
|
|
7
|
+
client: {
|
|
8
|
+
get<T>(path: string): Promise<T>;
|
|
9
|
+
post<T>(path: string, body: unknown): Promise<T>;
|
|
10
|
+
};
|
|
11
|
+
output: {
|
|
12
|
+
success(message: string): void;
|
|
13
|
+
error(message: string): void;
|
|
14
|
+
warn(message: string): void;
|
|
15
|
+
info(message: string): void;
|
|
16
|
+
table(headers: string[], rows: unknown[][]): void;
|
|
17
|
+
keyValue(data: Record<string, unknown>): void;
|
|
18
|
+
};
|
|
19
|
+
getConfig(): {
|
|
20
|
+
url: string;
|
|
21
|
+
};
|
|
22
|
+
isPlainMode(): boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* CLI Plugin interface
|
|
26
|
+
*/
|
|
27
|
+
export interface CLIPlugin {
|
|
28
|
+
name: string;
|
|
29
|
+
version: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
registerCommands(program: Command, ctx: CLIPluginContext): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Payara CLI plugin
|
|
35
|
+
*
|
|
36
|
+
* Adds deploy commands to znvault CLI
|
|
37
|
+
*/
|
|
38
|
+
export declare function createPayaraCLIPlugin(): CLIPlugin;
|
|
39
|
+
export default createPayaraCLIPlugin;
|
|
40
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC;;;GAGG;AACH,UAAU,gBAAgB;IACxB,MAAM,EAAE;QACN,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;KAClD,CAAC;IACF,MAAM,EAAE;QACN,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC;QAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KAC/C,CAAC;IACF,SAAS,IAAI;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,WAAW,IAAI,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACjE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,CAgOjD;AAgDD,eAAe,qBAAqB,CAAC"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// Path: src/cli.ts
|
|
2
|
+
// CLI commands for Payara plugin
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { stat } from 'node:fs/promises';
|
|
5
|
+
import AdmZip from 'adm-zip';
|
|
6
|
+
/**
|
|
7
|
+
* Payara CLI plugin
|
|
8
|
+
*
|
|
9
|
+
* Adds deploy commands to znvault CLI
|
|
10
|
+
*/
|
|
11
|
+
export function createPayaraCLIPlugin() {
|
|
12
|
+
return {
|
|
13
|
+
name: 'payara',
|
|
14
|
+
version: '1.0.0',
|
|
15
|
+
description: 'Payara WAR deployment commands',
|
|
16
|
+
registerCommands(program, ctx) {
|
|
17
|
+
// Create deploy command group
|
|
18
|
+
const deploy = program
|
|
19
|
+
.command('deploy')
|
|
20
|
+
.description('Deploy WAR files to remote Payara servers');
|
|
21
|
+
// deploy war <file>
|
|
22
|
+
deploy
|
|
23
|
+
.command('war <warFile>')
|
|
24
|
+
.description('Deploy WAR file using diff transfer')
|
|
25
|
+
.option('-t, --target <host>', 'Target server URL (default: from profile)')
|
|
26
|
+
.option('-p, --port <port>', 'Agent health port (default: 9100)', '9100')
|
|
27
|
+
.option('-f, --force', 'Force full deployment (no diff)')
|
|
28
|
+
.option('--dry-run', 'Show what would be deployed without deploying')
|
|
29
|
+
.action(async (warFile, options) => {
|
|
30
|
+
try {
|
|
31
|
+
// Verify WAR file exists
|
|
32
|
+
try {
|
|
33
|
+
await stat(warFile);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
ctx.output.error(`WAR file not found: ${warFile}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
ctx.output.info(`Analyzing WAR file: ${warFile}`);
|
|
40
|
+
// Calculate local hashes
|
|
41
|
+
const localHashes = await calculateWarHashes(warFile);
|
|
42
|
+
const fileCount = Object.keys(localHashes).length;
|
|
43
|
+
ctx.output.info(`Found ${fileCount} files in WAR`);
|
|
44
|
+
// Build target URL
|
|
45
|
+
const target = options.target ?? ctx.getConfig().url;
|
|
46
|
+
const baseUrl = target.replace(/\/$/, '');
|
|
47
|
+
const pluginUrl = `${baseUrl}:${options.port}/plugins/payara`;
|
|
48
|
+
// Get remote hashes
|
|
49
|
+
let remoteHashes = {};
|
|
50
|
+
if (!options.force) {
|
|
51
|
+
try {
|
|
52
|
+
const response = await ctx.client.get(`${pluginUrl}/hashes`);
|
|
53
|
+
remoteHashes = response.hashes;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
ctx.output.warn('Could not fetch remote hashes, doing full deployment');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Calculate diff
|
|
60
|
+
const { changed, deleted } = calculateDiff(localHashes, remoteHashes);
|
|
61
|
+
ctx.output.info(`Diff: ${changed.length} changed, ${deleted.length} deleted`);
|
|
62
|
+
// Dry run - just show diff
|
|
63
|
+
if (options.dryRun) {
|
|
64
|
+
if (changed.length > 0) {
|
|
65
|
+
ctx.output.info('\nFiles to update:');
|
|
66
|
+
for (const file of changed.slice(0, 20)) {
|
|
67
|
+
console.log(` + ${file}`);
|
|
68
|
+
}
|
|
69
|
+
if (changed.length > 20) {
|
|
70
|
+
console.log(` ... and ${changed.length - 20} more`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (deleted.length > 0) {
|
|
74
|
+
ctx.output.info('\nFiles to delete:');
|
|
75
|
+
for (const file of deleted.slice(0, 20)) {
|
|
76
|
+
console.log(` - ${file}`);
|
|
77
|
+
}
|
|
78
|
+
if (deleted.length > 20) {
|
|
79
|
+
console.log(` ... and ${deleted.length - 20} more`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (changed.length === 0 && deleted.length === 0) {
|
|
83
|
+
ctx.output.success('No changes to deploy');
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// No changes
|
|
88
|
+
if (changed.length === 0 && deleted.length === 0) {
|
|
89
|
+
ctx.output.success('No changes to deploy');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Prepare files for upload
|
|
93
|
+
ctx.output.info('Preparing files for deployment...');
|
|
94
|
+
const zip = new AdmZip(warFile);
|
|
95
|
+
const files = changed.map(path => {
|
|
96
|
+
const entry = zip.getEntry(path);
|
|
97
|
+
if (!entry) {
|
|
98
|
+
throw new Error(`Entry not found in WAR: ${path}`);
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
path,
|
|
102
|
+
content: entry.getData().toString('base64'),
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
// Deploy
|
|
106
|
+
ctx.output.info('Deploying changes...');
|
|
107
|
+
const deployResponse = await ctx.client.post(`${pluginUrl}/deploy`, {
|
|
108
|
+
files,
|
|
109
|
+
deletions: deleted,
|
|
110
|
+
});
|
|
111
|
+
if (deployResponse.status === 'deployed') {
|
|
112
|
+
ctx.output.success(`Deployed: ${deployResponse.filesChanged} files changed, ${deployResponse.filesDeleted} deleted`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
ctx.output.error(`Deployment failed: ${deployResponse.message}`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
ctx.output.error(`Deployment failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
// deploy restart
|
|
125
|
+
deploy
|
|
126
|
+
.command('restart')
|
|
127
|
+
.description('Restart Payara on remote server')
|
|
128
|
+
.option('-t, --target <host>', 'Target server URL')
|
|
129
|
+
.option('-p, --port <port>', 'Agent health port (default: 9100)', '9100')
|
|
130
|
+
.action(async (options) => {
|
|
131
|
+
try {
|
|
132
|
+
const target = options.target ?? ctx.getConfig().url;
|
|
133
|
+
const baseUrl = target.replace(/\/$/, '');
|
|
134
|
+
const pluginUrl = `${baseUrl}:${options.port}/plugins/payara`;
|
|
135
|
+
ctx.output.info('Restarting Payara...');
|
|
136
|
+
await ctx.client.post(`${pluginUrl}/restart`, {});
|
|
137
|
+
ctx.output.success('Payara restarted');
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
ctx.output.error(`Restart failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
// deploy status
|
|
145
|
+
deploy
|
|
146
|
+
.command('status')
|
|
147
|
+
.description('Get Payara status from remote server')
|
|
148
|
+
.option('-t, --target <host>', 'Target server URL')
|
|
149
|
+
.option('-p, --port <port>', 'Agent health port (default: 9100)', '9100')
|
|
150
|
+
.action(async (options) => {
|
|
151
|
+
try {
|
|
152
|
+
const target = options.target ?? ctx.getConfig().url;
|
|
153
|
+
const baseUrl = target.replace(/\/$/, '');
|
|
154
|
+
const pluginUrl = `${baseUrl}:${options.port}/plugins/payara`;
|
|
155
|
+
const status = await ctx.client.get(`${pluginUrl}/status`);
|
|
156
|
+
ctx.output.keyValue({
|
|
157
|
+
'Domain': status.domain,
|
|
158
|
+
'Running': status.running,
|
|
159
|
+
'Healthy': status.healthy,
|
|
160
|
+
'PID': status.pid ?? 'N/A',
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
ctx.output.error(`Failed to get status: ${err instanceof Error ? err.message : String(err)}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
// deploy applications
|
|
169
|
+
deploy
|
|
170
|
+
.command('applications')
|
|
171
|
+
.alias('apps')
|
|
172
|
+
.description('List deployed applications')
|
|
173
|
+
.option('-t, --target <host>', 'Target server URL')
|
|
174
|
+
.option('-p, --port <port>', 'Agent health port (default: 9100)', '9100')
|
|
175
|
+
.action(async (options) => {
|
|
176
|
+
try {
|
|
177
|
+
const target = options.target ?? ctx.getConfig().url;
|
|
178
|
+
const baseUrl = target.replace(/\/$/, '');
|
|
179
|
+
const pluginUrl = `${baseUrl}:${options.port}/plugins/payara`;
|
|
180
|
+
const response = await ctx.client.get(`${pluginUrl}/applications`);
|
|
181
|
+
if (response.applications.length === 0) {
|
|
182
|
+
ctx.output.info('No applications deployed');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
ctx.output.info(`Deployed applications (${response.applications.length}):`);
|
|
186
|
+
for (const app of response.applications) {
|
|
187
|
+
console.log(` - ${app}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
ctx.output.error(`Failed to list applications: ${err instanceof Error ? err.message : String(err)}`);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Calculate SHA-256 hashes for all files in a WAR
|
|
200
|
+
*/
|
|
201
|
+
async function calculateWarHashes(warPath) {
|
|
202
|
+
const hashes = {};
|
|
203
|
+
const zip = new AdmZip(warPath);
|
|
204
|
+
for (const entry of zip.getEntries()) {
|
|
205
|
+
if (!entry.isDirectory) {
|
|
206
|
+
const content = entry.getData();
|
|
207
|
+
const hash = createHash('sha256').update(content).digest('hex');
|
|
208
|
+
hashes[entry.entryName] = hash;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return hashes;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Calculate diff between local and remote hashes
|
|
215
|
+
*/
|
|
216
|
+
function calculateDiff(localHashes, remoteHashes) {
|
|
217
|
+
const changed = [];
|
|
218
|
+
const deleted = [];
|
|
219
|
+
// Find changed/new files
|
|
220
|
+
for (const [path, hash] of Object.entries(localHashes)) {
|
|
221
|
+
if (!remoteHashes[path] || remoteHashes[path] !== hash) {
|
|
222
|
+
changed.push(path);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Find deleted files
|
|
226
|
+
for (const path of Object.keys(remoteHashes)) {
|
|
227
|
+
if (!localHashes[path]) {
|
|
228
|
+
deleted.push(path);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return { changed, deleted };
|
|
232
|
+
}
|
|
233
|
+
// Default export for CLI plugin
|
|
234
|
+
export default createPayaraCLIPlugin;
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|