@theia/dev-container 1.49.0 → 1.50.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.
Files changed (53) hide show
  1. package/lib/dev-container-server/dev-container-server.js.map +1 -1
  2. package/lib/electron-browser/container-connection-contribution.js +15 -15
  3. package/lib/electron-browser/container-connection-contribution.js.map +1 -1
  4. package/lib/electron-browser/container-info-contribution.d.ts +11 -0
  5. package/lib/electron-browser/container-info-contribution.d.ts.map +1 -0
  6. package/lib/electron-browser/container-info-contribution.js +50 -0
  7. package/lib/electron-browser/container-info-contribution.js.map +1 -0
  8. package/lib/electron-browser/container-output-provider.js +4 -4
  9. package/lib/electron-browser/container-output-provider.js.map +1 -1
  10. package/lib/electron-browser/dev-container-frontend-module.d.ts.map +1 -1
  11. package/lib/electron-browser/dev-container-frontend-module.js +4 -0
  12. package/lib/electron-browser/dev-container-frontend-module.js.map +1 -1
  13. package/lib/electron-common/remote-container-connection-provider.d.ts +2 -0
  14. package/lib/electron-common/remote-container-connection-provider.d.ts.map +1 -1
  15. package/lib/electron-common/remote-container-connection-provider.js.map +1 -1
  16. package/lib/electron-node/dev-container-backend-module.d.ts.map +1 -1
  17. package/lib/electron-node/dev-container-backend-module.js +10 -0
  18. package/lib/electron-node/dev-container-backend-module.js.map +1 -1
  19. package/lib/electron-node/dev-container-file-service.js +4 -4
  20. package/lib/electron-node/dev-container-file-service.js.map +1 -1
  21. package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.d.ts +17 -0
  22. package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.d.ts.map +1 -0
  23. package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.js +69 -0
  24. package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.js.map +1 -0
  25. package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.d.ts +10 -1
  26. package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.d.ts.map +1 -1
  27. package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.js +99 -46
  28. package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.js.map +1 -1
  29. package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.d.ts +11 -0
  30. package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.d.ts.map +1 -0
  31. package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.js +37 -0
  32. package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.js.map +1 -0
  33. package/lib/electron-node/devcontainer-file.d.ts +29 -2
  34. package/lib/electron-node/devcontainer-file.d.ts.map +1 -1
  35. package/lib/electron-node/docker-container-service.d.ts +12 -6
  36. package/lib/electron-node/docker-container-service.d.ts.map +1 -1
  37. package/lib/electron-node/docker-container-service.js +20 -29
  38. package/lib/electron-node/docker-container-service.js.map +1 -1
  39. package/lib/electron-node/remote-container-connection-provider.d.ts +7 -3
  40. package/lib/electron-node/remote-container-connection-provider.d.ts.map +1 -1
  41. package/lib/electron-node/remote-container-connection-provider.js +37 -21
  42. package/lib/electron-node/remote-container-connection-provider.js.map +1 -1
  43. package/package.json +7 -7
  44. package/src/electron-browser/container-info-contribution.ts +46 -0
  45. package/src/electron-browser/dev-container-frontend-module.ts +5 -0
  46. package/src/electron-common/remote-container-connection-provider.ts +2 -0
  47. package/src/electron-node/dev-container-backend-module.ts +11 -0
  48. package/src/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.ts +68 -0
  49. package/src/electron-node/devcontainer-contributions/main-container-creation-contributions.ts +82 -31
  50. package/src/electron-node/devcontainer-contributions/profile-file-modification-contribution.ts +35 -0
  51. package/src/electron-node/devcontainer-file.ts +32 -1
  52. package/src/electron-node/docker-container-service.ts +31 -23
  53. package/src/electron-node/remote-container-connection-provider.ts +26 -9
@@ -14,7 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { ContributionProvider, URI } from '@theia/core';
17
+ import { ContributionProvider, MaybePromise, URI } from '@theia/core';
18
18
  import { inject, injectable, named } from '@theia/core/shared/inversify';
19
19
  import { WorkspaceServer } from '@theia/workspace/lib/common';
20
20
  import * as fs from '@theia/core/shared/fs-extra';
@@ -23,14 +23,29 @@ import { LastContainerInfo } from '../electron-common/remote-container-connectio
23
23
  import { DevContainerConfiguration } from './devcontainer-file';
24
24
  import { DevContainerFileService } from './dev-container-file-service';
25
25
  import { ContainerOutputProvider } from '../electron-common/container-output-provider';
26
+ import { RemoteDockerContainerConnection } from './remote-container-connection-provider';
26
27
 
27
28
  export const ContainerCreationContribution = Symbol('ContainerCreationContributions');
28
29
 
29
30
  export interface ContainerCreationContribution {
30
- handleContainerCreation(createOptions: Docker.ContainerCreateOptions,
31
+ handleContainerCreation?(createOptions: Docker.ContainerCreateOptions,
31
32
  containerConfig: DevContainerConfiguration,
32
33
  api: Docker,
33
- outputProvider?: ContainerOutputProvider): Promise<void>;
34
+ outputProvider?: ContainerOutputProvider): MaybePromise<void>;
35
+
36
+ /**
37
+ * executed after creating and starting the container
38
+ */
39
+ handlePostCreate?(containerConfig: DevContainerConfiguration,
40
+ container: Docker.Container,
41
+ api: Docker,
42
+ outputProvider?: ContainerOutputProvider): MaybePromise<void>;
43
+
44
+ /**
45
+ * executed after a connection has been established with the container and theia has been setup
46
+ */
47
+ handlePostConnect?(containerConfig: DevContainerConfiguration, connection: RemoteDockerContainerConnection,
48
+ outputProvider?: ContainerOutputProvider): MaybePromise<void>;
34
49
  }
35
50
 
36
51
  @injectable()
@@ -70,6 +85,15 @@ export class DockerContainerService {
70
85
  return container;
71
86
  }
72
87
 
88
+ async postConnect(devcontainerFile: string, connection: RemoteDockerContainerConnection, outputProvider?: ContainerOutputProvider): Promise<void> {
89
+ const devcontainerConfig = await this.devContainerFileService.getConfiguration(devcontainerFile);
90
+
91
+ for (const containerCreateContrib of this.containerCreationContributions.getContributions()) {
92
+ await containerCreateContrib.handlePostConnect?.(devcontainerConfig, connection, outputProvider);
93
+ }
94
+
95
+ }
96
+
73
97
  protected async buildContainer(docker: Docker, devcontainerFile: string, workspace: URI, outputProvider?: ContainerOutputProvider): Promise<Docker.Container> {
74
98
  const devcontainerConfig = await this.devContainerFileService.getConfiguration(devcontainerFile);
75
99
 
@@ -92,33 +116,17 @@ export class DockerContainerService {
92
116
  };
93
117
 
94
118
  for (const containerCreateContrib of this.containerCreationContributions.getContributions()) {
95
- await containerCreateContrib.handleContainerCreation(containerCreateOptions, devcontainerConfig, docker, outputProvider);
119
+ await containerCreateContrib.handleContainerCreation?.(containerCreateOptions, devcontainerConfig, docker, outputProvider);
96
120
  }
97
121
 
98
122
  // TODO add more config
99
123
  const container = await docker.createContainer(containerCreateOptions);
100
124
  await container.start();
101
125
 
102
- return container;
103
- }
104
-
105
- protected getPortBindings(forwardPorts: (string | number)[]): { exposedPorts: {}, portBindings: {} } {
106
- const res: { exposedPorts: { [key: string]: {} }, portBindings: { [key: string]: {} } } = { exposedPorts: {}, portBindings: {} };
107
- for (const port of forwardPorts) {
108
- let portKey: string;
109
- let hostPort: string;
110
- if (typeof port === 'string') {
111
- const parts = port.split(':');
112
- portKey = isNaN(+parts[0]) ? parts[0] : `${parts[0]}/tcp`;
113
- hostPort = parts[1] ?? parts[0];
114
- } else {
115
- portKey = `${port}/tcp`;
116
- hostPort = port.toString();
117
- }
118
- res.exposedPorts[portKey] = {};
119
- res.portBindings[portKey] = [{ HostPort: hostPort }];
126
+ for (const containerCreateContrib of this.containerCreationContributions.getContributions()) {
127
+ await containerCreateContrib.handlePostCreate?.(devcontainerConfig, container, docker, outputProvider);
120
128
  }
121
129
 
122
- return res;
130
+ return container;
123
131
  }
124
132
  }
@@ -56,6 +56,9 @@ export class DevContainerConnectionProvider implements RemoteContainerConnection
56
56
  @inject(DevContainerFileService)
57
57
  protected readonly devContainerFileService: DevContainerFileService;
58
58
 
59
+ @inject(RemoteConnectionService)
60
+ protected readonly remoteService: RemoteConnectionService;
61
+
59
62
  protected outputProvider: ContainerOutputProvider | undefined;
60
63
 
61
64
  setClient(client: ContainerOutputProvider): void {
@@ -77,12 +80,13 @@ export class DevContainerConnectionProvider implements RemoteContainerConnection
77
80
  });
78
81
  try {
79
82
  const container = await this.containerService.getOrCreateContainer(dockerConnection, options.devcontainerFile, options.lastContainerInfo, this.outputProvider);
83
+ const devContainerConfig = await this.devContainerFileService.getConfiguration(options.devcontainerFile);
80
84
 
81
85
  // create actual connection
82
86
  const report: RemoteStatusReport = message => progress.report({ message });
83
87
  report('Connecting to remote system...');
84
88
 
85
- const remote = await this.createContainerConnection(container, dockerConnection);
89
+ const remote = await this.createContainerConnection(container, dockerConnection, devContainerConfig.name);
86
90
  const result = await this.remoteSetup.setup({
87
91
  connection: remote,
88
92
  report,
@@ -100,6 +104,9 @@ export class DevContainerConnectionProvider implements RemoteContainerConnection
100
104
  });
101
105
  const localPort = (server.address() as net.AddressInfo).port;
102
106
  remote.localPort = localPort;
107
+
108
+ await this.containerService.postConnect(options.devcontainerFile, remote, this.outputProvider);
109
+
103
110
  return {
104
111
  containerId: container.id,
105
112
  workspacePath: (await container.inspect()).Mounts[0].Destination,
@@ -118,16 +125,24 @@ export class DevContainerConnectionProvider implements RemoteContainerConnection
118
125
  return this.devContainerFileService.getAvailableFiles();
119
126
  }
120
127
 
121
- async createContainerConnection(container: Docker.Container, docker: Docker): Promise<RemoteDockerContainerConnection> {
128
+ async createContainerConnection(container: Docker.Container, docker: Docker, name?: string): Promise<RemoteDockerContainerConnection> {
122
129
  return Promise.resolve(new RemoteDockerContainerConnection({
123
130
  id: generateUuid(),
124
- name: 'dev-container',
125
- type: 'container',
131
+ name: name ?? 'dev-container',
132
+ type: 'Dev Container',
126
133
  docker,
127
134
  container,
128
135
  }));
129
136
  }
130
137
 
138
+ async getCurrentContainerInfo(port: number): Promise<Docker.ContainerInspectInfo | undefined> {
139
+ const connection = this.remoteConnectionService.getConnectionFromPort(port);
140
+ if (!connection || !(connection instanceof RemoteDockerContainerConnection)) {
141
+ return undefined;
142
+ }
143
+ return connection.container.inspect();
144
+ }
145
+
131
146
  dispose(): void {
132
147
 
133
148
  }
@@ -167,8 +182,6 @@ export class RemoteDockerContainerConnection implements RemoteConnection {
167
182
  docker: Docker;
168
183
  container: Docker.Container;
169
184
 
170
- containerInfo: Docker.ContainerInspectInfo | undefined;
171
-
172
185
  remoteSetupResult: RemoteSetupResult;
173
186
 
174
187
  protected activeTerminalSession: ContainerTerminalSession | undefined;
@@ -180,10 +193,13 @@ export class RemoteDockerContainerConnection implements RemoteConnection {
180
193
  this.id = options.id;
181
194
  this.type = options.type;
182
195
  this.name = options.name;
183
- this.onDidDisconnect(() => this.dispose());
184
196
 
185
197
  this.docker = options.docker;
186
198
  this.container = options.container;
199
+
200
+ this.docker.getEvents({ filters: { container: [this.container.id], event: ['stop'] } }).then(stream => {
201
+ stream.on('data', () => this.onDidDisconnectEmitter.fire());
202
+ });
187
203
  }
188
204
 
189
205
  async forwardOut(socket: Socket, port?: number): Promise<void> {
@@ -287,8 +303,9 @@ export class RemoteDockerContainerConnection implements RemoteConnection {
287
303
  return deferred.promise;
288
304
  }
289
305
 
290
- dispose(): void {
291
- this.container.stop();
306
+ async dispose(): Promise<void> {
307
+ // cant use dockerrode here since this needs to happen on one tick
308
+ exec(`docker stop ${this.container.id}`);
292
309
  }
293
310
 
294
311
  }