@git.zone/cli 1.16.9 → 1.17.1
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/00_commitinfo_data.js +2 -2
- package/dist_ts/gitzone.cli.js +8 -1
- package/dist_ts/mod_format/format.packagejson.js +3 -3
- package/dist_ts/mod_services/classes.dockercontainer.d.ts +68 -0
- package/dist_ts/mod_services/classes.dockercontainer.js +194 -0
- package/dist_ts/mod_services/classes.serviceconfiguration.d.ts +69 -0
- package/dist_ts/mod_services/classes.serviceconfiguration.js +195 -0
- package/dist_ts/mod_services/classes.servicemanager.d.ts +49 -0
- package/dist_ts/mod_services/classes.servicemanager.js +363 -0
- package/dist_ts/mod_services/helpers.d.ts +24 -0
- package/dist_ts/mod_services/helpers.js +108 -0
- package/dist_ts/mod_services/index.d.ts +1 -0
- package/dist_ts/mod_services/index.js +184 -0
- package/dist_ts/mod_services/mod.plugins.d.ts +7 -0
- package/dist_ts/mod_services/mod.plugins.js +8 -0
- package/dist_ts/plugins.d.ts +6 -1
- package/dist_ts/plugins.js +7 -2
- package/package.json +29 -24
- package/readme.md +123 -16
- package/readme.plan.md +119 -188
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/gitzone.cli.ts +8 -0
- package/ts/mod_format/format.packagejson.ts +2 -2
- package/ts/mod_services/classes.dockercontainer.ts +227 -0
- package/ts/mod_services/classes.serviceconfiguration.ts +246 -0
- package/ts/mod_services/classes.servicemanager.ts +423 -0
- package/ts/mod_services/helpers.ts +123 -0
- package/ts/mod_services/index.ts +219 -0
- package/ts/mod_services/mod.plugins.ts +9 -0
- package/ts/plugins.ts +10 -0
package/readme.plan.md
CHANGED
|
@@ -1,190 +1,121 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
Please reread /home/philkunz/.claude/CLAUDE.md before proceeding with any implementation.
|
|
1
|
+
# GitZone Services Command Implementation Plan
|
|
4
2
|
|
|
5
3
|
## Overview
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- [x]
|
|
14
|
-
- [x]
|
|
15
|
-
- [x] Create
|
|
16
|
-
- [x]
|
|
17
|
-
- [x]
|
|
18
|
-
|
|
19
|
-
###
|
|
20
|
-
|
|
21
|
-
- [x]
|
|
22
|
-
- [x]
|
|
23
|
-
- [x]
|
|
24
|
-
- [x]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- [x]
|
|
29
|
-
- [x]
|
|
30
|
-
- [x]
|
|
31
|
-
- [x]
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- [x]
|
|
37
|
-
- [x]
|
|
38
|
-
- [x]
|
|
39
|
-
- [x]
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- [x]
|
|
47
|
-
- [x]
|
|
48
|
-
- [x]
|
|
49
|
-
- [x]
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
- [x]
|
|
54
|
-
- [x] Add
|
|
55
|
-
- [x]
|
|
56
|
-
- [x]
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
- [
|
|
63
|
-
- [
|
|
64
|
-
- [
|
|
65
|
-
- [
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
- [ ]
|
|
71
|
-
- [ ]
|
|
72
|
-
- [ ]
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
##
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
4. **
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
5. **Reporting & Statistics**
|
|
126
|
-
|
|
127
|
-
- Detailed diff views
|
|
128
|
-
- Execution statistics
|
|
129
|
-
- Verbose logging mode
|
|
130
|
-
- Save reports to file
|
|
131
|
-
|
|
132
|
-
6. **Architecture Improvements**
|
|
133
|
-
- BaseFormatter abstract class
|
|
134
|
-
- FormatContext for state management
|
|
135
|
-
- DependencyAnalyzer for parallel execution
|
|
136
|
-
- Type-safe interfaces
|
|
137
|
-
|
|
138
|
-
### 🚧 Partially Completed
|
|
139
|
-
|
|
140
|
-
1. **License Management**
|
|
141
|
-
|
|
142
|
-
- Basic configuration support
|
|
143
|
-
- Exception handling for specific packages
|
|
144
|
-
- Need: compatibility matrix, compliance reports
|
|
145
|
-
|
|
146
|
-
2. **Package.json Management**
|
|
147
|
-
- Basic ensureDependency implementation
|
|
148
|
-
- Need: smart sorting, script generation, validation
|
|
149
|
-
|
|
150
|
-
### ⏳ Not Started
|
|
151
|
-
|
|
152
|
-
1. **Plugin System**
|
|
153
|
-
|
|
154
|
-
- Need to design plugin API
|
|
155
|
-
- Hook system for pre/post operations
|
|
156
|
-
- Custom validation rules
|
|
157
|
-
|
|
158
|
-
2. **Git Integration**
|
|
159
|
-
|
|
160
|
-
- Pre-commit hooks
|
|
161
|
-
- Automatic formatting on commit
|
|
162
|
-
|
|
163
|
-
3. **Advanced UI**
|
|
164
|
-
- Interactive configuration mode
|
|
165
|
-
- Undo/redo capability
|
|
166
|
-
- Format presets
|
|
167
|
-
|
|
168
|
-
## Technical Achievements
|
|
169
|
-
|
|
170
|
-
1. **Type Safety**: All new code uses TypeScript interfaces and types
|
|
171
|
-
2. **Error Handling**: Comprehensive try-catch blocks with rollback
|
|
172
|
-
3. **API Compatibility**: Updated to use latest smartfile/smartnpm APIs
|
|
173
|
-
4. **Testing**: Ready for comprehensive test suite
|
|
174
|
-
5. **Performance**: Significant improvements through caching and parallelization
|
|
175
|
-
|
|
176
|
-
## Next Steps
|
|
177
|
-
|
|
178
|
-
1. Write comprehensive tests for all new functionality
|
|
179
|
-
2. Create user documentation for new features
|
|
180
|
-
3. Consider plugin API design for extensibility
|
|
181
|
-
4. Implement remaining Phase 3 features based on user feedback
|
|
182
|
-
5. Performance benchmarking and optimization
|
|
183
|
-
|
|
184
|
-
## Success Metrics Achieved
|
|
185
|
-
|
|
186
|
-
- ✅ Reduced error rates through rollback mechanism
|
|
187
|
-
- ✅ Faster execution through parallel processing and caching
|
|
188
|
-
- ✅ Enhanced user control through configuration
|
|
189
|
-
- ✅ Better visibility through reporting and statistics
|
|
190
|
-
- ✅ Improved maintainability through better architecture
|
|
4
|
+
Implement the `gitzone services` command to manage MongoDB and MinIO containers for development projects.
|
|
5
|
+
|
|
6
|
+
## Tasks
|
|
7
|
+
|
|
8
|
+
### Module Structure Setup
|
|
9
|
+
- [x] Create `ts/mod_services/` directory
|
|
10
|
+
- [x] Create `mod.plugins.ts` with required imports
|
|
11
|
+
- [x] Create `helpers.ts` with utility functions
|
|
12
|
+
- [x] Create `classes.serviceconfiguration.ts` for config handling
|
|
13
|
+
- [x] Create `classes.dockercontainer.ts` for Docker operations
|
|
14
|
+
- [x] Create `classes.servicemanager.ts` for service management
|
|
15
|
+
- [x] Create `index.ts` with main command logic
|
|
16
|
+
|
|
17
|
+
### Core Functionality
|
|
18
|
+
- [x] Implement ServiceConfiguration class
|
|
19
|
+
- [x] Load/create `.nogit/env.json` configuration
|
|
20
|
+
- [x] Generate random available ports (20000-30000 range)
|
|
21
|
+
- [x] Preserve existing custom values
|
|
22
|
+
- [x] Provide default values for missing fields
|
|
23
|
+
|
|
24
|
+
- [x] Implement DockerContainer class
|
|
25
|
+
- [x] Check container status
|
|
26
|
+
- [x] Start/stop/restart containers
|
|
27
|
+
- [x] Execute Docker commands
|
|
28
|
+
- [x] Handle container logs
|
|
29
|
+
- [x] Manage volumes and port bindings
|
|
30
|
+
|
|
31
|
+
- [x] Implement ServiceManager class
|
|
32
|
+
- [x] Manage MongoDB containers
|
|
33
|
+
- [x] Manage MinIO containers
|
|
34
|
+
- [x] Handle container lifecycle
|
|
35
|
+
- [x] Generate project-specific container names
|
|
36
|
+
- [x] Manage data directories in `.nogit/`
|
|
37
|
+
- [x] Generate MongoDB Compass connection strings
|
|
38
|
+
|
|
39
|
+
### Commands Implementation
|
|
40
|
+
- [x] `start` command - Start services (mongo|s3|all)
|
|
41
|
+
- [x] `stop` command - Stop services (mongo|s3|all)
|
|
42
|
+
- [x] `restart` command - Restart services (mongo|s3|all)
|
|
43
|
+
- [x] `status` command - Show service status
|
|
44
|
+
- [x] `config` command - Show current configuration
|
|
45
|
+
- [x] `compass` command - Show MongoDB Compass connection string
|
|
46
|
+
- [x] `logs` command - Show service logs with line count
|
|
47
|
+
- [x] `remove` command - Remove containers (preserve data)
|
|
48
|
+
- [x] `clean` command - Remove containers and data
|
|
49
|
+
|
|
50
|
+
### Integration
|
|
51
|
+
- [x] Add `@push.rocks/smartshell` to main plugins.ts
|
|
52
|
+
- [x] Add `@push.rocks/smartnetwork` to main plugins.ts
|
|
53
|
+
- [x] Add `@push.rocks/smartinteraction` to main plugins.ts
|
|
54
|
+
- [x] Register services command in `gitzone.cli.ts`
|
|
55
|
+
|
|
56
|
+
### Features
|
|
57
|
+
- [x] Auto-configuration with smart defaults
|
|
58
|
+
- [x] Random port assignment to avoid conflicts
|
|
59
|
+
- [x] Project isolation with unique container names
|
|
60
|
+
- [x] Data persistence in `.nogit/` directories
|
|
61
|
+
- [x] Status display (running/stopped/not installed)
|
|
62
|
+
- [x] Interactive confirmations for destructive operations
|
|
63
|
+
- [x] Colored console output
|
|
64
|
+
- [x] MinIO bucket auto-creation
|
|
65
|
+
- [x] MongoDB Compass connection string with network IP
|
|
66
|
+
|
|
67
|
+
### Testing
|
|
68
|
+
- [ ] Test service start/stop operations
|
|
69
|
+
- [ ] Test configuration creation and updates
|
|
70
|
+
- [ ] Test port collision handling
|
|
71
|
+
- [ ] Test data persistence
|
|
72
|
+
- [ ] Test MongoDB Compass connection string generation
|
|
73
|
+
- [ ] Test all command variations
|
|
74
|
+
|
|
75
|
+
## Configuration Format
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"PROJECT_NAME": "derived-from-package-name",
|
|
79
|
+
"MONGODB_HOST": "localhost",
|
|
80
|
+
"MONGODB_NAME": "project-name",
|
|
81
|
+
"MONGODB_PORT": "random-port",
|
|
82
|
+
"MONGODB_USER": "defaultadmin",
|
|
83
|
+
"MONGODB_PASS": "defaultpass",
|
|
84
|
+
"S3_HOST": "localhost",
|
|
85
|
+
"S3_PORT": "random-port",
|
|
86
|
+
"S3_CONSOLE_PORT": "s3-port+1",
|
|
87
|
+
"S3_USER": "defaultadmin",
|
|
88
|
+
"S3_PASS": "defaultpass",
|
|
89
|
+
"S3_BUCKET": "project-name-documents"
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Command Examples
|
|
94
|
+
```bash
|
|
95
|
+
gitzone services start # Start all services
|
|
96
|
+
gitzone services start mongo # Start only MongoDB
|
|
97
|
+
gitzone services stop # Stop all services
|
|
98
|
+
gitzone services status # Check service status
|
|
99
|
+
gitzone services config # Show configuration
|
|
100
|
+
gitzone services compass # Show MongoDB Compass connection string
|
|
101
|
+
gitzone services logs mongo 50 # Show last 50 lines of MongoDB logs
|
|
102
|
+
gitzone services remove # Remove containers (preserve data)
|
|
103
|
+
gitzone services clean # Remove containers and data
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Progress Notes
|
|
107
|
+
Implementation started: 2025-08-14
|
|
108
|
+
Implementation completed: 2025-08-14
|
|
109
|
+
|
|
110
|
+
## Summary
|
|
111
|
+
Successfully implemented the `gitzone services` command in TypeScript, providing a complete replacement for the `services.sh` shell script. The implementation includes:
|
|
112
|
+
|
|
113
|
+
1. **Complete Docker service management** for MongoDB and MinIO containers
|
|
114
|
+
2. **Smart configuration management** with automatic port assignment and conflict avoidance
|
|
115
|
+
3. **MongoDB Compass support** with network IP detection for remote connections
|
|
116
|
+
4. **Project isolation** using project-specific container names
|
|
117
|
+
5. **Data persistence** in `.nogit/` directories
|
|
118
|
+
6. **Interactive confirmations** for destructive operations
|
|
119
|
+
7. **Comprehensive command set** including start, stop, restart, status, config, compass, logs, remove, and clean commands
|
|
120
|
+
|
|
121
|
+
The module is fully integrated into the gitzone CLI and ready for testing.
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@git.zone/cli',
|
|
6
|
-
version: '1.16.
|
|
6
|
+
version: '1.16.10',
|
|
7
7
|
description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.'
|
|
8
8
|
}
|
package/ts/gitzone.cli.ts
CHANGED
|
@@ -131,6 +131,14 @@ export let run = async () => {
|
|
|
131
131
|
modHelpers.run(argvArg);
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
+
/**
|
|
135
|
+
* manage development services (MongoDB, S3/MinIO)
|
|
136
|
+
*/
|
|
137
|
+
gitzoneSmartcli.addCommand('services').subscribe(async (argvArg) => {
|
|
138
|
+
const modServices = await import('./mod_services/index.js');
|
|
139
|
+
await modServices.run(argvArg);
|
|
140
|
+
});
|
|
141
|
+
|
|
134
142
|
// start parsing of the cli
|
|
135
143
|
gitzoneSmartcli.startParse();
|
|
136
144
|
return await done.promise;
|
|
@@ -83,10 +83,10 @@ export const run = async (projectArg: Project) => {
|
|
|
83
83
|
type: 'git',
|
|
84
84
|
url: `https://${gitzoneData.module.githost}/${gitzoneData.module.gitscope}/${gitzoneData.module.gitrepo}.git`,
|
|
85
85
|
};
|
|
86
|
-
(packageJson.bugs = {
|
|
86
|
+
((packageJson.bugs = {
|
|
87
87
|
url: `https://${gitzoneData.module.githost}/${gitzoneData.module.gitscope}/${gitzoneData.module.gitrepo}/issues`,
|
|
88
88
|
}),
|
|
89
|
-
(packageJson.homepage = `https://${gitzoneData.module.githost}/${gitzoneData.module.gitscope}/${gitzoneData.module.gitrepo}#readme`);
|
|
89
|
+
(packageJson.homepage = `https://${gitzoneData.module.githost}/${gitzoneData.module.gitscope}/${gitzoneData.module.gitrepo}#readme`));
|
|
90
90
|
|
|
91
91
|
// Check for module type
|
|
92
92
|
if (!packageJson.type) {
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import * as plugins from './mod.plugins.js';
|
|
2
|
+
import * as helpers from './helpers.js';
|
|
3
|
+
import { logger } from '../gitzone.logging.js';
|
|
4
|
+
|
|
5
|
+
export type ContainerStatus = 'running' | 'stopped' | 'not_exists';
|
|
6
|
+
|
|
7
|
+
export interface IDockerRunOptions {
|
|
8
|
+
name: string;
|
|
9
|
+
image: string;
|
|
10
|
+
ports?: { [key: string]: string };
|
|
11
|
+
volumes?: { [key: string]: string };
|
|
12
|
+
environment?: { [key: string]: string };
|
|
13
|
+
restart?: string;
|
|
14
|
+
command?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class DockerContainer {
|
|
18
|
+
private smartshell: plugins.smartshell.Smartshell;
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
this.smartshell = new plugins.smartshell.Smartshell({
|
|
22
|
+
executor: 'bash',
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Check if Docker is installed and available
|
|
28
|
+
*/
|
|
29
|
+
public async checkDocker(): Promise<boolean> {
|
|
30
|
+
try {
|
|
31
|
+
const result = await this.smartshell.exec('docker --version');
|
|
32
|
+
return result.exitCode === 0;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get container status
|
|
40
|
+
*/
|
|
41
|
+
public async getStatus(containerName: string): Promise<ContainerStatus> {
|
|
42
|
+
try {
|
|
43
|
+
// Check if running
|
|
44
|
+
const runningResult = await this.smartshell.exec(
|
|
45
|
+
`docker ps --format '{{.Names}}' | grep -q "^${containerName}$"`
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
if (runningResult.exitCode === 0) {
|
|
49
|
+
return 'running';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check if exists but stopped
|
|
53
|
+
const existsResult = await this.smartshell.exec(
|
|
54
|
+
`docker ps -a --format '{{.Names}}' | grep -q "^${containerName}$"`
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (existsResult.exitCode === 0) {
|
|
58
|
+
return 'stopped';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return 'not_exists';
|
|
62
|
+
} catch (error) {
|
|
63
|
+
return 'not_exists';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Start a container
|
|
69
|
+
*/
|
|
70
|
+
public async start(containerName: string): Promise<boolean> {
|
|
71
|
+
try {
|
|
72
|
+
const result = await this.smartshell.exec(`docker start ${containerName}`);
|
|
73
|
+
return result.exitCode === 0;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Stop a container
|
|
81
|
+
*/
|
|
82
|
+
public async stop(containerName: string): Promise<boolean> {
|
|
83
|
+
try {
|
|
84
|
+
const result = await this.smartshell.exec(`docker stop ${containerName}`);
|
|
85
|
+
return result.exitCode === 0;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Remove a container
|
|
93
|
+
*/
|
|
94
|
+
public async remove(containerName: string, force: boolean = false): Promise<boolean> {
|
|
95
|
+
try {
|
|
96
|
+
const forceFlag = force ? '-f' : '';
|
|
97
|
+
const result = await this.smartshell.exec(`docker rm ${forceFlag} ${containerName}`);
|
|
98
|
+
return result.exitCode === 0;
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Run a new container
|
|
106
|
+
*/
|
|
107
|
+
public async run(options: IDockerRunOptions): Promise<boolean> {
|
|
108
|
+
let command = 'docker run -d';
|
|
109
|
+
|
|
110
|
+
// Add name
|
|
111
|
+
command += ` --name ${options.name}`;
|
|
112
|
+
|
|
113
|
+
// Add ports
|
|
114
|
+
if (options.ports) {
|
|
115
|
+
for (const [hostPort, containerPort] of Object.entries(options.ports)) {
|
|
116
|
+
command += ` -p ${hostPort}:${containerPort}`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Add volumes
|
|
121
|
+
if (options.volumes) {
|
|
122
|
+
for (const [hostPath, containerPath] of Object.entries(options.volumes)) {
|
|
123
|
+
command += ` -v "${hostPath}:${containerPath}"`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Add environment variables
|
|
128
|
+
if (options.environment) {
|
|
129
|
+
for (const [key, value] of Object.entries(options.environment)) {
|
|
130
|
+
command += ` -e ${key}="${value}"`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Add restart policy
|
|
135
|
+
if (options.restart) {
|
|
136
|
+
command += ` --restart ${options.restart}`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Add image
|
|
140
|
+
command += ` ${options.image}`;
|
|
141
|
+
|
|
142
|
+
// Add command if provided
|
|
143
|
+
if (options.command) {
|
|
144
|
+
command += ` ${options.command}`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const result = await this.smartshell.exec(command);
|
|
149
|
+
return result.exitCode === 0;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
logger.log('error', `Failed to run container: ${error.message}`);
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Execute a command in a running container
|
|
158
|
+
*/
|
|
159
|
+
public async exec(containerName: string, command: string): Promise<string> {
|
|
160
|
+
try {
|
|
161
|
+
const result = await this.smartshell.exec(`docker exec ${containerName} ${command}`);
|
|
162
|
+
if (result.exitCode === 0) {
|
|
163
|
+
return result.stdout;
|
|
164
|
+
}
|
|
165
|
+
return '';
|
|
166
|
+
} catch (error) {
|
|
167
|
+
return '';
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Get container logs
|
|
173
|
+
*/
|
|
174
|
+
public async logs(containerName: string, lines?: number): Promise<string> {
|
|
175
|
+
try {
|
|
176
|
+
const tailFlag = lines ? `--tail ${lines}` : '';
|
|
177
|
+
const result = await this.smartshell.exec(`docker logs ${tailFlag} ${containerName}`);
|
|
178
|
+
return result.stdout;
|
|
179
|
+
} catch (error) {
|
|
180
|
+
return `Error getting logs: ${error.message}`;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Check if a container exists
|
|
186
|
+
*/
|
|
187
|
+
public async exists(containerName: string): Promise<boolean> {
|
|
188
|
+
const status = await this.getStatus(containerName);
|
|
189
|
+
return status !== 'not_exists';
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Check if a container is running
|
|
194
|
+
*/
|
|
195
|
+
public async isRunning(containerName: string): Promise<boolean> {
|
|
196
|
+
const status = await this.getStatus(containerName);
|
|
197
|
+
return status === 'running';
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Wait for a container to be ready
|
|
202
|
+
*/
|
|
203
|
+
public async waitForReady(containerName: string, maxAttempts: number = 30): Promise<boolean> {
|
|
204
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
205
|
+
if (await this.isRunning(containerName)) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
await plugins.smartdelay.delayFor(1000);
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get container information
|
|
215
|
+
*/
|
|
216
|
+
public async inspect(containerName: string): Promise<any> {
|
|
217
|
+
try {
|
|
218
|
+
const result = await this.smartshell.exec(`docker inspect ${containerName}`);
|
|
219
|
+
if (result.exitCode === 0) {
|
|
220
|
+
return JSON.parse(result.stdout);
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
} catch (error) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|