plugin-cluster-manager 1.0.13 → 1.1.5
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/client/index.js +10 -1
- package/dist/externalVersion.js +9 -0
- package/dist/index.js +9 -0
- package/dist/server/actions/acl-cache.js +9 -0
- package/dist/server/actions/cache-monitor.js +9 -0
- package/dist/server/actions/cluster-nodes.js +9 -0
- package/dist/server/actions/event-queue-monitor.js +9 -0
- package/dist/server/actions/lock-monitor.js +9 -0
- package/dist/server/actions/orchestrator.d.ts +5 -0
- package/dist/server/actions/orchestrator.js +28 -0
- package/dist/server/actions/package-manager.js +9 -0
- package/dist/server/actions/redis-monitor.js +9 -0
- package/dist/server/actions/tasks.js +9 -0
- package/dist/server/actions/workflow-executions.js +9 -0
- package/dist/server/adapters/redis-lock-adapter.js +9 -0
- package/dist/server/adapters/redis-node-registry.js +9 -0
- package/dist/server/adapters/redis-pubsub-adapter.js +9 -0
- package/dist/server/collections/app.d.ts +8 -0
- package/dist/server/collections/app.js +38 -0
- package/dist/server/collections/cluster-manager-acl-cache.d.ts +22 -0
- package/dist/server/collections/cluster-manager-acl-cache.js +44 -0
- package/dist/server/collections/cluster-manager-cache-mgr.d.ts +22 -0
- package/dist/server/collections/cluster-manager-cache-mgr.js +44 -0
- package/dist/server/collections/cluster-manager-cluster.d.ts +22 -0
- package/dist/server/collections/cluster-manager-cluster.js +44 -0
- package/dist/server/collections/cluster-manager-lock.d.ts +22 -0
- package/dist/server/collections/cluster-manager-lock.js +44 -0
- package/dist/server/collections/cluster-manager-queue.d.ts +22 -0
- package/dist/server/collections/cluster-manager-queue.js +44 -0
- package/dist/server/collections/cluster-manager-redis.d.ts +22 -0
- package/dist/server/collections/cluster-manager-redis.js +44 -0
- package/dist/server/collections/cluster-manager-workflow.d.ts +22 -0
- package/dist/server/collections/cluster-manager-workflow.js +44 -0
- package/dist/server/collections/cluster-manager.d.ts +22 -0
- package/dist/server/collections/cluster-manager.js +44 -0
- package/dist/server/collections/orchestrator-settings.js +9 -0
- package/dist/server/collections/orchestrator-stacks.js +9 -0
- package/dist/server/collections/worker-orchestrator.d.ts +22 -0
- package/dist/server/collections/worker-orchestrator.js +44 -0
- package/dist/server/collections/worker-packages-configs.js +9 -0
- package/dist/server/collections/worker-packages.d.ts +22 -0
- package/dist/server/collections/worker-packages.js +44 -0
- package/dist/server/index.js +9 -0
- package/dist/server/orchestrator/PackageManager.js +10 -1
- package/dist/server/orchestrator/docker-adapter.d.ts +4 -0
- package/dist/server/orchestrator/docker-adapter.js +28 -6
- package/dist/server/orchestrator/index.js +9 -0
- package/dist/server/orchestrator/k8s-adapter.js +9 -0
- package/dist/server/orchestrator/leader-election.js +9 -0
- package/dist/server/orchestrator/types.d.ts +5 -0
- package/dist/server/orchestrator/types.js +9 -0
- package/dist/server/plugin.js +10 -1
- package/dist/server/utils/node.js +9 -0
- package/dist/server/utils/redis.js +9 -0
- package/dist/shared/packages.js +9 -0
- package/package.json +1 -1
- package/src/client/ContainerOrchestrator.tsx +38 -3
- package/src/client/PackageInstaller.tsx +1 -1
- package/src/server/actions/orchestrator.ts +20 -0
- package/src/server/collections/app.ts +7 -0
- package/src/server/collections/cluster-manager-acl-cache.ts +23 -0
- package/src/server/collections/cluster-manager-cache-mgr.ts +23 -0
- package/src/server/collections/cluster-manager-cluster.ts +23 -0
- package/src/server/collections/cluster-manager-lock.ts +23 -0
- package/src/server/collections/cluster-manager-queue.ts +23 -0
- package/src/server/collections/cluster-manager-redis.ts +23 -0
- package/src/server/collections/cluster-manager-workflow.ts +23 -0
- package/src/server/collections/cluster-manager.ts +23 -0
- package/src/server/collections/worker-orchestrator.ts +23 -0
- package/src/server/collections/worker-packages.ts +23 -0
- package/src/server/orchestrator/PackageManager.ts +2 -2
- package/src/server/orchestrator/docker-adapter.ts +25 -9
- package/src/server/orchestrator/types.ts +3 -0
- package/src/server/plugin.ts +1 -1
|
@@ -146,6 +146,7 @@ function stackToFormValues(stack?: StackInfo | null) {
|
|
|
146
146
|
k8sEnvFrom: jsonText(DEFAULT_K8S_ENV_FROM, []),
|
|
147
147
|
k8sVolumeMounts: jsonText(DEFAULT_K8S_VOLUME_MOUNTS, []),
|
|
148
148
|
k8sVolumes: jsonText(DEFAULT_K8S_VOLUMES, []),
|
|
149
|
+
networkMode: '',
|
|
149
150
|
};
|
|
150
151
|
}
|
|
151
152
|
|
|
@@ -196,6 +197,19 @@ export function ContainerOrchestrator() {
|
|
|
196
197
|
});
|
|
197
198
|
const [settingsForm] = Form.useForm();
|
|
198
199
|
const [stackForm] = Form.useForm();
|
|
200
|
+
const [dockerNetworks, setDockerNetworks] = useState<{id: string, name: string}[]>([]);
|
|
201
|
+
|
|
202
|
+
// Fetch Docker networks
|
|
203
|
+
const fetchNetworks = useCallback(async () => {
|
|
204
|
+
try {
|
|
205
|
+
const res = await api.request({ url: '/workerOrchestrator:networks' });
|
|
206
|
+
let networks = res.data?.data || res.data;
|
|
207
|
+
if (!Array.isArray(networks)) networks = [];
|
|
208
|
+
setDockerNetworks(networks);
|
|
209
|
+
} catch {
|
|
210
|
+
setDockerNetworks([]);
|
|
211
|
+
}
|
|
212
|
+
}, [api]);
|
|
199
213
|
|
|
200
214
|
// Ping the orchestrator adapter
|
|
201
215
|
const fetchPing = useCallback(async () => {
|
|
@@ -268,6 +282,7 @@ export function ContainerOrchestrator() {
|
|
|
268
282
|
const openStackModal = (stack?: StackInfo) => {
|
|
269
283
|
setStackModal({ visible: true, stack: stack || null });
|
|
270
284
|
stackForm.setFieldsValue(stackToFormValues(stack));
|
|
285
|
+
fetchNetworks();
|
|
271
286
|
};
|
|
272
287
|
|
|
273
288
|
const closeStackModal = () => {
|
|
@@ -774,18 +789,38 @@ export function ContainerOrchestrator() {
|
|
|
774
789
|
</Col>
|
|
775
790
|
</Row>
|
|
776
791
|
|
|
777
|
-
{/* Row 4: Container name | Namespace */}
|
|
792
|
+
{/* Row 4: Container name | Namespace | Network Mode */}
|
|
778
793
|
<Row gutter={12}>
|
|
779
|
-
<Col span={
|
|
794
|
+
<Col span={8}>
|
|
780
795
|
<Form.Item name="k8sContainerName" label={t('Container name')}>
|
|
781
796
|
<Input placeholder="worker" />
|
|
782
797
|
</Form.Item>
|
|
783
798
|
</Col>
|
|
784
|
-
<Col span={
|
|
799
|
+
<Col span={8}>
|
|
785
800
|
<Form.Item name="namespace" label={t('Namespace')}>
|
|
786
801
|
<Input placeholder="nocobase" />
|
|
787
802
|
</Form.Item>
|
|
788
803
|
</Col>
|
|
804
|
+
<Col span={8}>
|
|
805
|
+
<Form.Item noStyle shouldUpdate={(prev, curr) => prev.adapter !== curr.adapter}>
|
|
806
|
+
{() => {
|
|
807
|
+
if (stackForm.getFieldValue('adapter') === 'docker') {
|
|
808
|
+
return (
|
|
809
|
+
<Form.Item name="networkMode" label={t('Docker Network')} extra={t('Main network. Workers also inherit app networks.')}>
|
|
810
|
+
<Select allowClear placeholder={t('Default (bridge)')}>
|
|
811
|
+
<Select.Option value="bridge">bridge</Select.Option>
|
|
812
|
+
<Select.Option value="host">host</Select.Option>
|
|
813
|
+
{(Array.isArray(dockerNetworks) ? dockerNetworks : []).map(n => (
|
|
814
|
+
<Select.Option key={n.id} value={n.name}>{n.name}</Select.Option>
|
|
815
|
+
))}
|
|
816
|
+
</Select>
|
|
817
|
+
</Form.Item>
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
return null;
|
|
821
|
+
}}
|
|
822
|
+
</Form.Item>
|
|
823
|
+
</Col>
|
|
789
824
|
</Row>
|
|
790
825
|
|
|
791
826
|
<Form.Item name="command" label={t('Command')}>
|
|
@@ -194,7 +194,7 @@ export const PackageInstaller: React.FC = () => {
|
|
|
194
194
|
size="small"
|
|
195
195
|
style={{ marginBottom: 16 }}
|
|
196
196
|
extra={
|
|
197
|
-
<Button icon={<ReloadOutlined />} size="small" onClick={loadConfig} loading={loading}>
|
|
197
|
+
<Button icon={<ReloadOutlined />} size="small" onClick={() => loadConfig(false)} loading={loading}>
|
|
198
198
|
{t('Refresh')}
|
|
199
199
|
</Button>
|
|
200
200
|
}
|
|
@@ -251,4 +251,24 @@ export const orchestratorActions = {
|
|
|
251
251
|
}
|
|
252
252
|
await next();
|
|
253
253
|
},
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* GET /workerOrchestrator:networks
|
|
257
|
+
* List available networks (if supported by adapter)
|
|
258
|
+
*/
|
|
259
|
+
async networks(ctx: Context, next: () => Promise<void>) {
|
|
260
|
+
const adapter = getAdapter(ctx);
|
|
261
|
+
if (!adapter.listNetworks) {
|
|
262
|
+
ctx.body = { data: [] };
|
|
263
|
+
} else {
|
|
264
|
+
try {
|
|
265
|
+
const networks = await adapter.listNetworks();
|
|
266
|
+
ctx.body = { data: networks };
|
|
267
|
+
} catch (err: any) {
|
|
268
|
+
ctx.app.logger.warn(`Failed to list networks: ${err.message}`);
|
|
269
|
+
ctx.body = { data: [] };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
await next();
|
|
273
|
+
},
|
|
254
274
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerAclCache" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerAclCache' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerAclCache',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerCacheMgr" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerCacheMgr' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerCacheMgr',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerCluster" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerCluster' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerCluster',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerLock" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerLock' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerLock',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerQueue" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerQueue' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerQueue',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerRedis" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerRedis' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerRedis',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManagerWorkflow" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManagerWorkflow' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManagerWorkflow',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "clusterManager" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'clusterManager' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'clusterManager',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "workerOrchestrator" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'workerOrchestrator' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'workerOrchestrator',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DUMMY COLLECTION
|
|
3
|
+
* This collection is created to prevent NocoBase workflow/ACL from throwing the error:
|
|
4
|
+
* '[Workflow pre-action]: collection "workerPackages" not found'
|
|
5
|
+
*
|
|
6
|
+
* Since 'workerPackages' is registered as a resourcer in plugin.ts, NocoBase
|
|
7
|
+
* implicitly looks for a collection with the same name.
|
|
8
|
+
* We set dumpRules: 'skip' and avoid timestamps to ensure this collection
|
|
9
|
+
* is completely ignored during backups/migrations and doesn't pollute the actual DB.
|
|
10
|
+
*/
|
|
11
|
+
export default {
|
|
12
|
+
name: 'workerPackages',
|
|
13
|
+
dumpRules: 'skip',
|
|
14
|
+
autoGenId: true,
|
|
15
|
+
createdAt: false,
|
|
16
|
+
updatedAt: false,
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
name: 'name',
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -4,8 +4,8 @@ import { promises as fsp } from 'fs';
|
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import Application from '@nocobase/server';
|
|
6
6
|
|
|
7
|
-
/** Allow only safe package name characters: letters, digits, dash, underscore, dot, @,
|
|
8
|
-
const SAFE_PKG_RE = /^[a-zA-Z0-9_
|
|
7
|
+
/** Allow only safe package name characters: letters, digits, dash, underscore, dot, @, /, [, ] */
|
|
8
|
+
const SAFE_PKG_RE = /^[a-zA-Z0-9_\-\.@\/\[\]]+$/;
|
|
9
9
|
const INSTALL_CHANNEL = 'cluster-manager.install-packages';
|
|
10
10
|
|
|
11
11
|
type TargetRole = 'app' | 'worker' | 'sandbox' | 'all';
|
|
@@ -116,11 +116,11 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
116
116
|
const myContainer = this.docker.getContainer(myContainerId);
|
|
117
117
|
const myInfo = await myContainer.inspect();
|
|
118
118
|
|
|
119
|
-
//
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
// Always inherit Networks so worker can communicate with main app
|
|
120
|
+
if (myInfo?.NetworkSettings?.Networks) {
|
|
121
|
+
const inheritedNetworks = Object.keys(myInfo.NetworkSettings.Networks);
|
|
122
|
+
targetNetworks = Array.from(new Set([...inheritedNetworks, ...targetNetworks]));
|
|
123
|
+
console.log('[DockerAdapter] Inherited networks:', targetNetworks);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// Inherit Environment Variables and merge with stack.envVars
|
|
@@ -134,16 +134,23 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
134
134
|
});
|
|
135
135
|
// Overwrite with explicitly defined env vars
|
|
136
136
|
Object.assign(envDict, stack.envVars || {});
|
|
137
|
+
|
|
137
138
|
targetEnvVars = Object.entries(envDict).map(([k, v]) => `${k}=${v}`);
|
|
138
139
|
}
|
|
139
|
-
|
|
140
140
|
// Inherit Volumes (Binds)
|
|
141
141
|
if (myInfo?.HostConfig?.Binds) {
|
|
142
142
|
const inheritedBinds = myInfo.HostConfig.Binds as string[];
|
|
143
143
|
targetVolumes = Array.from(new Set([...inheritedBinds, ...targetVolumes]));
|
|
144
144
|
}
|
|
145
|
-
} catch (e) {
|
|
145
|
+
} catch (e: any) {
|
|
146
146
|
// Ignore error if not running in a container or cannot inspect
|
|
147
|
+
console.error('[DockerAdapter] Failed to inherit container config:', e.message);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Automatically separate logs for workers to prevent log interleaving with the main app
|
|
151
|
+
const hasLoggerBase = targetEnvVars.some(e => e.startsWith('LOGGER_BASE_PATH='));
|
|
152
|
+
if (!hasLoggerBase) {
|
|
153
|
+
targetEnvVars.push(`LOGGER_BASE_PATH=/app/nocobase/storage/logs/${stack.name}`);
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
for (let i = 0; i < diff; i++) {
|
|
@@ -185,8 +192,9 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
185
192
|
const container = await this.docker.createContainer(createOpts);
|
|
186
193
|
|
|
187
194
|
// Connect to additional networks before starting
|
|
188
|
-
if (
|
|
189
|
-
|
|
195
|
+
if (targetNetworks.length > 0) {
|
|
196
|
+
const startIndex = targetNetworkMode ? 0 : 1;
|
|
197
|
+
for (let i = startIndex; i < targetNetworks.length; i++) {
|
|
190
198
|
try {
|
|
191
199
|
const net = this.docker.getNetwork(targetNetworks[i]);
|
|
192
200
|
await net.connect({ Container: container.id });
|
|
@@ -284,6 +292,14 @@ export class DockerAdapter implements IOrchestratorAdapter {
|
|
|
284
292
|
return this.demuxDockerLogs(logBuffer);
|
|
285
293
|
}
|
|
286
294
|
|
|
295
|
+
async listNetworks(): Promise<{ id: string; name: string }[]> {
|
|
296
|
+
const networks = await this.docker.listNetworks();
|
|
297
|
+
return networks.map((n: any) => ({
|
|
298
|
+
id: n.Id,
|
|
299
|
+
name: n.Name,
|
|
300
|
+
}));
|
|
301
|
+
}
|
|
302
|
+
|
|
287
303
|
// ─── Private helpers ───
|
|
288
304
|
|
|
289
305
|
private mapState(state: string): ContainerInfo['status'] {
|
|
@@ -92,4 +92,7 @@ export interface IOrchestratorAdapter {
|
|
|
92
92
|
|
|
93
93
|
/** Get tail logs from a container */
|
|
94
94
|
getLogs(containerId: string, tail?: number): Promise<string>;
|
|
95
|
+
|
|
96
|
+
/** List available networks (if supported by adapter) */
|
|
97
|
+
listNetworks?(): Promise<{ id: string; name: string }[]>;
|
|
95
98
|
}
|
package/src/server/plugin.ts
CHANGED
|
@@ -28,7 +28,7 @@ export class PluginClusterManagerServer extends Plugin {
|
|
|
28
28
|
public leaderElection: LeaderElection | null = null;
|
|
29
29
|
|
|
30
30
|
async beforeLoad() {
|
|
31
|
-
this.db.import({ directory: path.resolve(__dirname, 'collections') });
|
|
31
|
+
await this.db.import({ directory: path.resolve(__dirname, 'collections') });
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
async load() {
|