@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.
- package/lib/dev-container-server/dev-container-server.js.map +1 -1
- package/lib/electron-browser/container-connection-contribution.js +15 -15
- package/lib/electron-browser/container-connection-contribution.js.map +1 -1
- package/lib/electron-browser/container-info-contribution.d.ts +11 -0
- package/lib/electron-browser/container-info-contribution.d.ts.map +1 -0
- package/lib/electron-browser/container-info-contribution.js +50 -0
- package/lib/electron-browser/container-info-contribution.js.map +1 -0
- package/lib/electron-browser/container-output-provider.js +4 -4
- package/lib/electron-browser/container-output-provider.js.map +1 -1
- package/lib/electron-browser/dev-container-frontend-module.d.ts.map +1 -1
- package/lib/electron-browser/dev-container-frontend-module.js +4 -0
- package/lib/electron-browser/dev-container-frontend-module.js.map +1 -1
- package/lib/electron-common/remote-container-connection-provider.d.ts +2 -0
- package/lib/electron-common/remote-container-connection-provider.d.ts.map +1 -1
- package/lib/electron-common/remote-container-connection-provider.js.map +1 -1
- package/lib/electron-node/dev-container-backend-module.d.ts.map +1 -1
- package/lib/electron-node/dev-container-backend-module.js +10 -0
- package/lib/electron-node/dev-container-backend-module.js.map +1 -1
- package/lib/electron-node/dev-container-file-service.js +4 -4
- package/lib/electron-node/dev-container-file-service.js.map +1 -1
- package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.d.ts +17 -0
- package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.d.ts.map +1 -0
- package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.js +69 -0
- package/lib/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.js.map +1 -0
- package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.d.ts +10 -1
- package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.d.ts.map +1 -1
- package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.js +99 -46
- package/lib/electron-node/devcontainer-contributions/main-container-creation-contributions.js.map +1 -1
- package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.d.ts +11 -0
- package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.d.ts.map +1 -0
- package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.js +37 -0
- package/lib/electron-node/devcontainer-contributions/profile-file-modification-contribution.js.map +1 -0
- package/lib/electron-node/devcontainer-file.d.ts +29 -2
- package/lib/electron-node/devcontainer-file.d.ts.map +1 -1
- package/lib/electron-node/docker-container-service.d.ts +12 -6
- package/lib/electron-node/docker-container-service.d.ts.map +1 -1
- package/lib/electron-node/docker-container-service.js +20 -29
- package/lib/electron-node/docker-container-service.js.map +1 -1
- package/lib/electron-node/remote-container-connection-provider.d.ts +7 -3
- package/lib/electron-node/remote-container-connection-provider.d.ts.map +1 -1
- package/lib/electron-node/remote-container-connection-provider.js +37 -21
- package/lib/electron-node/remote-container-connection-provider.js.map +1 -1
- package/package.json +7 -7
- package/src/electron-browser/container-info-contribution.ts +46 -0
- package/src/electron-browser/dev-container-frontend-module.ts +5 -0
- package/src/electron-common/remote-container-connection-provider.ts +2 -0
- package/src/electron-node/dev-container-backend-module.ts +11 -0
- package/src/electron-node/devcontainer-contributions/cli-enhancing-creation-contributions.ts +68 -0
- package/src/electron-node/devcontainer-contributions/main-container-creation-contributions.ts +82 -31
- package/src/electron-node/devcontainer-contributions/profile-file-modification-contribution.ts +35 -0
- package/src/electron-node/devcontainer-file.ts +32 -1
- package/src/electron-node/docker-container-service.ts +31 -23
- package/src/electron-node/remote-container-connection-provider.ts +26 -9
|
@@ -45,10 +45,11 @@ let DevContainerConnectionProvider = class DevContainerConnectionProvider {
|
|
|
45
45
|
});
|
|
46
46
|
try {
|
|
47
47
|
const container = await this.containerService.getOrCreateContainer(dockerConnection, options.devcontainerFile, options.lastContainerInfo, this.outputProvider);
|
|
48
|
+
const devContainerConfig = await this.devContainerFileService.getConfiguration(options.devcontainerFile);
|
|
48
49
|
// create actual connection
|
|
49
50
|
const report = message => progress.report({ message });
|
|
50
51
|
report('Connecting to remote system...');
|
|
51
|
-
const remote = await this.createContainerConnection(container, dockerConnection);
|
|
52
|
+
const remote = await this.createContainerConnection(container, dockerConnection, devContainerConfig.name);
|
|
52
53
|
const result = await this.remoteSetup.setup({
|
|
53
54
|
connection: remote,
|
|
54
55
|
report,
|
|
@@ -65,6 +66,7 @@ let DevContainerConnectionProvider = class DevContainerConnectionProvider {
|
|
|
65
66
|
});
|
|
66
67
|
const localPort = server.address().port;
|
|
67
68
|
remote.localPort = localPort;
|
|
69
|
+
await this.containerService.postConnect(options.devcontainerFile, remote, this.outputProvider);
|
|
68
70
|
return {
|
|
69
71
|
containerId: container.id,
|
|
70
72
|
workspacePath: (await container.inspect()).Mounts[0].Destination,
|
|
@@ -83,46 +85,57 @@ let DevContainerConnectionProvider = class DevContainerConnectionProvider {
|
|
|
83
85
|
getDevContainerFiles() {
|
|
84
86
|
return this.devContainerFileService.getAvailableFiles();
|
|
85
87
|
}
|
|
86
|
-
async createContainerConnection(container, docker) {
|
|
88
|
+
async createContainerConnection(container, docker, name) {
|
|
87
89
|
return Promise.resolve(new RemoteDockerContainerConnection({
|
|
88
90
|
id: (0, core_1.generateUuid)(),
|
|
89
|
-
name: 'dev-container',
|
|
90
|
-
type: '
|
|
91
|
+
name: name !== null && name !== void 0 ? name : 'dev-container',
|
|
92
|
+
type: 'Dev Container',
|
|
91
93
|
docker,
|
|
92
94
|
container,
|
|
93
95
|
}));
|
|
94
96
|
}
|
|
97
|
+
async getCurrentContainerInfo(port) {
|
|
98
|
+
const connection = this.remoteConnectionService.getConnectionFromPort(port);
|
|
99
|
+
if (!connection || !(connection instanceof RemoteDockerContainerConnection)) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return connection.container.inspect();
|
|
103
|
+
}
|
|
95
104
|
dispose() {
|
|
96
105
|
}
|
|
97
106
|
};
|
|
98
|
-
|
|
107
|
+
exports.DevContainerConnectionProvider = DevContainerConnectionProvider;
|
|
108
|
+
tslib_1.__decorate([
|
|
99
109
|
(0, inversify_1.inject)(remote_connection_service_1.RemoteConnectionService),
|
|
100
|
-
|
|
110
|
+
tslib_1.__metadata("design:type", remote_connection_service_1.RemoteConnectionService)
|
|
101
111
|
], DevContainerConnectionProvider.prototype, "remoteConnectionService", void 0);
|
|
102
|
-
|
|
112
|
+
tslib_1.__decorate([
|
|
103
113
|
(0, inversify_1.inject)(remote_setup_service_1.RemoteSetupService),
|
|
104
|
-
|
|
114
|
+
tslib_1.__metadata("design:type", remote_setup_service_1.RemoteSetupService)
|
|
105
115
|
], DevContainerConnectionProvider.prototype, "remoteSetup", void 0);
|
|
106
|
-
|
|
116
|
+
tslib_1.__decorate([
|
|
107
117
|
(0, inversify_1.inject)(core_1.MessageService),
|
|
108
|
-
|
|
118
|
+
tslib_1.__metadata("design:type", core_1.MessageService)
|
|
109
119
|
], DevContainerConnectionProvider.prototype, "messageService", void 0);
|
|
110
|
-
|
|
120
|
+
tslib_1.__decorate([
|
|
111
121
|
(0, inversify_1.inject)(remote_proxy_server_provider_1.RemoteProxyServerProvider),
|
|
112
|
-
|
|
122
|
+
tslib_1.__metadata("design:type", remote_proxy_server_provider_1.RemoteProxyServerProvider)
|
|
113
123
|
], DevContainerConnectionProvider.prototype, "serverProvider", void 0);
|
|
114
|
-
|
|
124
|
+
tslib_1.__decorate([
|
|
115
125
|
(0, inversify_1.inject)(docker_container_service_1.DockerContainerService),
|
|
116
|
-
|
|
126
|
+
tslib_1.__metadata("design:type", docker_container_service_1.DockerContainerService)
|
|
117
127
|
], DevContainerConnectionProvider.prototype, "containerService", void 0);
|
|
118
|
-
|
|
128
|
+
tslib_1.__decorate([
|
|
119
129
|
(0, inversify_1.inject)(dev_container_file_service_1.DevContainerFileService),
|
|
120
|
-
|
|
130
|
+
tslib_1.__metadata("design:type", dev_container_file_service_1.DevContainerFileService)
|
|
121
131
|
], DevContainerConnectionProvider.prototype, "devContainerFileService", void 0);
|
|
122
|
-
|
|
132
|
+
tslib_1.__decorate([
|
|
133
|
+
(0, inversify_1.inject)(remote_connection_service_1.RemoteConnectionService),
|
|
134
|
+
tslib_1.__metadata("design:type", remote_connection_service_1.RemoteConnectionService)
|
|
135
|
+
], DevContainerConnectionProvider.prototype, "remoteService", void 0);
|
|
136
|
+
exports.DevContainerConnectionProvider = DevContainerConnectionProvider = tslib_1.__decorate([
|
|
123
137
|
(0, inversify_1.injectable)()
|
|
124
138
|
], DevContainerConnectionProvider);
|
|
125
|
-
exports.DevContainerConnectionProvider = DevContainerConnectionProvider;
|
|
126
139
|
class RemoteDockerContainerConnection {
|
|
127
140
|
constructor(options) {
|
|
128
141
|
this.onDidDisconnectEmitter = new core_1.Emitter();
|
|
@@ -130,9 +143,11 @@ class RemoteDockerContainerConnection {
|
|
|
130
143
|
this.id = options.id;
|
|
131
144
|
this.type = options.type;
|
|
132
145
|
this.name = options.name;
|
|
133
|
-
this.onDidDisconnect(() => this.dispose());
|
|
134
146
|
this.docker = options.docker;
|
|
135
147
|
this.container = options.container;
|
|
148
|
+
this.docker.getEvents({ filters: { container: [this.container.id], event: ['stop'] } }).then(stream => {
|
|
149
|
+
stream.on('data', () => this.onDidDisconnectEmitter.fire());
|
|
150
|
+
});
|
|
136
151
|
}
|
|
137
152
|
async forwardOut(socket, port) {
|
|
138
153
|
const node = `${this.remoteSetupResult.nodeDirectory}/bin/node`;
|
|
@@ -233,8 +248,9 @@ class RemoteDockerContainerConnection {
|
|
|
233
248
|
});
|
|
234
249
|
return deferred.promise;
|
|
235
250
|
}
|
|
236
|
-
dispose() {
|
|
237
|
-
this
|
|
251
|
+
async dispose() {
|
|
252
|
+
// cant use dockerrode here since this needs to happen on one tick
|
|
253
|
+
(0, child_process_1.exec)(`docker stop ${this.container.id}`);
|
|
238
254
|
}
|
|
239
255
|
}
|
|
240
256
|
exports.RemoteDockerContainerConnection = RemoteDockerContainerConnection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-container-connection-provider.js","sourceRoot":"","sources":["../../src/electron-node/remote-container-connection-provider.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAQhF,qGAAmH;AACnH,yGAAoG;AACpG,+GAAyG;AACzG,sCAAsF;AAEtF,4DAAkE;AAClE,oCAAoC;AACpC,yEAAoE;AACpE,sEAA+D;AAE/D,mCAAqC;AACrC,iDAAqC;AACrC,6EAAuE;
|
|
1
|
+
{"version":3,"file":"remote-container-connection-provider.js","sourceRoot":"","sources":["../../src/electron-node/remote-container-connection-provider.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAQhF,qGAAmH;AACnH,yGAAoG;AACpG,+GAAyG;AACzG,sCAAsF;AAEtF,4DAAkE;AAClE,oCAAoC;AACpC,yEAAoE;AACpE,sEAA+D;AAE/D,mCAAqC;AACrC,iDAAqC;AACrC,6EAAuE;AAIhE,IAAM,8BAA8B,GAApC,MAAM,8BAA8B;IAyBvC,SAAS,CAAC,MAA+B;QACrC,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,OAAmC;QACxD,MAAM,gBAAgB,GAAG,IAAI,MAAM,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAExE,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC7C,CAAC;QAED,mBAAmB;QACnB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC;YACpD,IAAI,EAAE,oBAAoB;SAC7B,CAAC,CAAC;QACH,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;YAC/J,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAEzG,2BAA2B;YAC3B,MAAM,MAAM,GAAuB,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;YAC3E,MAAM,CAAC,gCAAgC,CAAC,CAAC;YAEzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,SAAS,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC1G,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;gBACxC,UAAU,EAAE,MAAM;gBAClB,MAAM;gBACN,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;aACrD,CAAC,CAAC;YACH,MAAM,CAAC,iBAAiB,GAAG,MAAM,CAAC;YAElC,MAAM,YAAY,GAAG,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE;gBAC7D,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE;gBACxB,MAAM,CAAC,KAAK,EAAE,CAAC;gBACf,YAAY,CAAC,OAAO,EAAE,CAAC;YAC3B,CAAC,CAAC,CAAC;YACH,MAAM,SAAS,GAAI,MAAM,CAAC,OAAO,EAAsB,CAAC,IAAI,CAAC;YAC7D,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;YAE7B,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;YAE/F,OAAO;gBACH,WAAW,EAAE,SAAS,CAAC,EAAE;gBACzB,aAAa,EAAE,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW;gBAChE,IAAI,EAAE,SAAS,CAAC,QAAQ,EAAE;aAC7B,CAAC;QACN,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjB,MAAM,CAAC,CAAC;QACZ,CAAC;gBAAS,CAAC;YACP,QAAQ,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC;IACL,CAAC;IAED,oBAAoB;QAChB,OAAO,IAAI,CAAC,uBAAuB,CAAC,iBAAiB,EAAE,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,SAA2B,EAAE,MAAc,EAAE,IAAa;QACtF,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,+BAA+B,CAAC;YACvD,EAAE,EAAE,IAAA,mBAAY,GAAE;YAClB,IAAI,EAAE,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,eAAe;YAC7B,IAAI,EAAE,eAAe;YACrB,MAAM;YACN,SAAS;SACZ,CAAC,CAAC,CAAC;IACR,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,IAAY;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,uBAAuB,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC5E,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,YAAY,+BAA+B,CAAC,EAAE,CAAC;YAC1E,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,OAAO,UAAU,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IAC1C,CAAC;IAED,OAAO;IAEP,CAAC;CAEJ,CAAA;AA/GY,wEAA8B;AAGpB;IADlB,IAAA,kBAAM,EAAC,mDAAuB,CAAC;sCACY,mDAAuB;+EAAC;AAGjD;IADlB,IAAA,kBAAM,EAAC,yCAAkB,CAAC;sCACK,yCAAkB;mEAAC;AAGhC;IADlB,IAAA,kBAAM,EAAC,qBAAc,CAAC;sCACY,qBAAc;sEAAC;AAG/B;IADlB,IAAA,kBAAM,EAAC,wDAAyB,CAAC;sCACC,wDAAyB;sEAAC;AAG1C;IADlB,IAAA,kBAAM,EAAC,iDAAsB,CAAC;sCACM,iDAAsB;wEAAC;AAGzC;IADlB,IAAA,kBAAM,EAAC,oDAAuB,CAAC;sCACY,oDAAuB;+EAAC;AAGjD;IADlB,IAAA,kBAAM,EAAC,mDAAuB,CAAC;sCACE,mDAAuB;qEAAC;yCArBjD,8BAA8B;IAD1C,IAAA,sBAAU,GAAE;GACA,8BAA8B,CA+G1C;AAwBD,MAAa,+BAA+B;IAkBxC,YAAY,OAAyC;QAHlC,2BAAsB,GAAG,IAAI,cAAO,EAAQ,CAAC;QAChE,oBAAe,GAAgB,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC;QAG7D,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAEzB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QAEnC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;YAClG,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,IAAa;QAC1C,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,aAAa,WAAW,CAAC;QAChE,MAAM,kBAAkB,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,kCAAkC,CAAC;QAC5G,IAAI,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBACzC,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,kBAAkB,iBAAiB,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC1F,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI;aAC5D,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAErE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpB,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW,EAAE,IAAe,EAAE,OAA2B;;QAChE,8EAA8E;QAC9E,MAAM,QAAQ,GAAG,IAAI,uBAAQ,EAAoB,CAAC;QAClD,IAAI,CAAC;YACD,qCAAqC;YACrC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,CAAC,GAAG,CAAC,mCAAI,EAAE,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9I,IAAI,YAAY,GAAG,EAAE,CAAC;YACtB,IAAI,YAAY,GAAG,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,MAAM,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,KAAK,CAAC,EAAE,CAAC,CAAA,CAAC;YAC1C,MAAM,MAAM,GAAG,IAAI,oBAAW,EAAE,CAAC;YACjC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBAChC,YAAY,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrC,CAAC,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,oBAAW,EAAE,CAAC;YACjC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBAChC,YAAY,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrC,CAAC,CAAC,CAAC;YACH,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACpD,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;QACzG,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,GAAW,EAAE,MAAwB,EAAE,IAAe,EAAE,OAA2B;;QACjG,MAAM,QAAQ,GAAG,IAAI,uBAAQ,EAAoB,CAAC;QAClD,IAAI,CAAC;YACD,qCAAqC;YACrC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,CAAC,GAAG,CAAC,mCAAI,EAAE,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9I,IAAI,YAAY,GAAG,EAAE,CAAC;YACtB,IAAI,YAAY,GAAG,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,MAAM,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,KAAK,CAAC,EAAE,CAAC,CAAA,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACpB,IAAI,QAAQ,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;oBAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrE,CAAC;YACL,CAAC,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,oBAAW,EAAE,CAAC;YACjC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;gBAC/B,IAAI,QAAQ,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;oBAClC,YAAY,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAEhC,IAAI,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC;wBACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;oBACrE,CAAC;gBACL,CAAC;YACL,CAAC,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,oBAAW,EAAE,CAAC;YACjC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;gBAC/B,IAAI,QAAQ,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;oBAClC,YAAY,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAEhC,IAAI,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC;wBACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;oBACrE,CAAC;gBACL,CAAC;YACL,CAAC,CAAC,CAAC;YACH,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAkD,EAAE,UAAkB;;QAC7E,MAAM,QAAQ,GAAG,IAAI,uBAAQ,EAAQ,CAAC;QACtC,MAAM,OAAO,GAAG,IAAA,oBAAI,EAAC,iBAAiB,SAAS,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,UAAU,EAAE,CAAC,CAAC;QAEjG,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAA,OAAO,CAAC,MAAM,0CAAE,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE;YAC9B,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;YACvB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACb,QAAQ,CAAC,OAAO,EAAE,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACJ,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;QACL,CAAC,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO;QACT,kEAAkE;QAClE,IAAA,oBAAI,EAAC,eAAe,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7C,CAAC;CAEJ;AAzID,0EAyIC"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/dev-container",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.50.0",
|
|
4
4
|
"description": "Theia - Editor Preview Extension",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/core": "1.
|
|
7
|
-
"@theia/output": "1.
|
|
8
|
-
"@theia/remote": "1.
|
|
9
|
-
"@theia/workspace": "1.
|
|
6
|
+
"@theia/core": "1.50.0",
|
|
7
|
+
"@theia/output": "1.50.0",
|
|
8
|
+
"@theia/remote": "1.50.0",
|
|
9
|
+
"@theia/workspace": "1.50.0",
|
|
10
10
|
"dockerode": "^4.0.2",
|
|
11
11
|
"jsonc-parser": "^2.2.0",
|
|
12
12
|
"uuid": "^8.0.0"
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
"watch": "theiaext watch"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@theia/ext-scripts": "1.
|
|
48
|
+
"@theia/ext-scripts": "1.50.0",
|
|
49
49
|
"@types/dockerode": "^3.3.23"
|
|
50
50
|
},
|
|
51
51
|
"nyc": {
|
|
52
52
|
"extends": "../../configs/nyc.json"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "63585530b2e32af0ed4bac4edb5ff443bfc248b7"
|
|
55
55
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2024 Typefox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
|
|
19
|
+
import type { ContainerInspectInfo } from 'dockerode';
|
|
20
|
+
import { RemoteContainerConnectionProvider } from '../electron-common/remote-container-connection-provider';
|
|
21
|
+
import { PortForwardingService } from '@theia/remote/lib/electron-browser/port-forwarding/port-forwarding-service';
|
|
22
|
+
|
|
23
|
+
@injectable()
|
|
24
|
+
export class ContainerInfoContribution implements FrontendApplicationContribution {
|
|
25
|
+
|
|
26
|
+
@inject(RemoteContainerConnectionProvider)
|
|
27
|
+
protected readonly connectionProvider: RemoteContainerConnectionProvider;
|
|
28
|
+
|
|
29
|
+
@inject(PortForwardingService)
|
|
30
|
+
protected readonly portForwardingService: PortForwardingService;
|
|
31
|
+
|
|
32
|
+
containerInfo: ContainerInspectInfo | undefined;
|
|
33
|
+
|
|
34
|
+
async onStart(): Promise<void> {
|
|
35
|
+
this.containerInfo = await this.connectionProvider.getCurrentContainerInfo(parseInt(new URLSearchParams(location.search).get('port') ?? '0'));
|
|
36
|
+
|
|
37
|
+
this.portForwardingService.forwardedPorts = Object.entries(this.containerInfo?.NetworkSettings.Ports ?? {}).flatMap(([_, ports]) => (
|
|
38
|
+
ports.map(port => ({
|
|
39
|
+
editing: false,
|
|
40
|
+
address: port.HostIp ?? '',
|
|
41
|
+
localPort: parseInt(port.HostPort ?? '0'),
|
|
42
|
+
origin: 'container'
|
|
43
|
+
}))));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
}
|
|
@@ -19,6 +19,8 @@ import { RemoteContainerConnectionProvider, RemoteContainerConnectionProviderPat
|
|
|
19
19
|
import { ContainerConnectionContribution } from './container-connection-contribution';
|
|
20
20
|
import { ServiceConnectionProvider } from '@theia/core/lib/browser/messaging/service-connection-provider';
|
|
21
21
|
import { ContainerOutputProvider } from './container-output-provider';
|
|
22
|
+
import { ContainerInfoContribution } from './container-info-contribution';
|
|
23
|
+
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
|
|
22
24
|
|
|
23
25
|
export default new ContainerModule(bind => {
|
|
24
26
|
bind(ContainerConnectionContribution).toSelf().inSingletonScope();
|
|
@@ -30,4 +32,7 @@ export default new ContainerModule(bind => {
|
|
|
30
32
|
const outputProvider = ctx.container.get(ContainerOutputProvider);
|
|
31
33
|
return ServiceConnectionProvider.createLocalProxy<RemoteContainerConnectionProvider>(ctx.container, RemoteContainerConnectionProviderPath, outputProvider);
|
|
32
34
|
}).inSingletonScope();
|
|
35
|
+
|
|
36
|
+
bind(ContainerInfoContribution).toSelf().inSingletonScope();
|
|
37
|
+
bind(FrontendApplicationContribution).toService(ContainerInfoContribution);
|
|
33
38
|
});
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import { RpcServer } from '@theia/core';
|
|
17
17
|
import { ContainerOutputProvider } from './container-output-provider';
|
|
18
|
+
import type { ContainerInspectInfo } from 'dockerode';
|
|
18
19
|
|
|
19
20
|
// *****************************************************************************
|
|
20
21
|
export const RemoteContainerConnectionProviderPath = '/remote/container';
|
|
@@ -46,4 +47,5 @@ export interface DevContainerFile {
|
|
|
46
47
|
export interface RemoteContainerConnectionProvider extends RpcServer<ContainerOutputProvider> {
|
|
47
48
|
connectToContainer(options: ContainerConnectionOptions): Promise<ContainerConnectionResult>;
|
|
48
49
|
getDevContainerFiles(): Promise<DevContainerFile[]>;
|
|
50
|
+
getCurrentContainerInfo(port: number): Promise<ContainerInspectInfo | undefined>;
|
|
49
51
|
}
|
|
@@ -23,10 +23,16 @@ import { bindContributionProvider, ConnectionHandler, RpcConnectionHandler } fro
|
|
|
23
23
|
import { registerContainerCreationContributions } from './devcontainer-contributions/main-container-creation-contributions';
|
|
24
24
|
import { DevContainerFileService } from './dev-container-file-service';
|
|
25
25
|
import { ContainerOutputProvider } from '../electron-common/container-output-provider';
|
|
26
|
+
import { ExtensionsContribution, registerTheiaStartOptionsContributions, SettingsContribution } from './devcontainer-contributions/cli-enhancing-creation-contributions';
|
|
27
|
+
import { RemoteCliContribution } from '@theia/core/lib/node/remote/remote-cli-contribution';
|
|
28
|
+
import { ProfileFileModificationContribution } from './devcontainer-contributions/profile-file-modification-contribution';
|
|
26
29
|
|
|
27
30
|
export const remoteConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService }) => {
|
|
28
31
|
bindContributionProvider(bind, ContainerCreationContribution);
|
|
29
32
|
registerContainerCreationContributions(bind);
|
|
33
|
+
registerTheiaStartOptionsContributions(bind);
|
|
34
|
+
bind(ProfileFileModificationContribution).toSelf().inSingletonScope();
|
|
35
|
+
bind(ContainerCreationContribution).toService(ProfileFileModificationContribution);
|
|
30
36
|
|
|
31
37
|
bind(DevContainerConnectionProvider).toSelf().inSingletonScope();
|
|
32
38
|
bind(RemoteContainerConnectionProvider).toService(DevContainerConnectionProvider);
|
|
@@ -44,4 +50,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
44
50
|
bind(ConnectionContainerModule).toConstantValue(remoteConnectionModule);
|
|
45
51
|
|
|
46
52
|
bind(DevContainerFileService).toSelf().inSingletonScope();
|
|
53
|
+
|
|
54
|
+
bind(ExtensionsContribution).toSelf().inSingletonScope();
|
|
55
|
+
bind(SettingsContribution).toSelf().inSingletonScope();
|
|
56
|
+
bind(RemoteCliContribution).toService(ExtensionsContribution);
|
|
57
|
+
bind(RemoteCliContribution).toService(SettingsContribution);
|
|
47
58
|
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2024 Typefox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { RemoteCliContext, RemoteCliContribution } from '@theia/core/lib/node/remote/remote-cli-contribution';
|
|
18
|
+
import { ContainerCreationContribution } from '../docker-container-service';
|
|
19
|
+
import * as Docker from 'dockerode';
|
|
20
|
+
import { DevContainerConfiguration, } from '../devcontainer-file';
|
|
21
|
+
import { injectable, interfaces } from '@theia/core/shared/inversify';
|
|
22
|
+
|
|
23
|
+
export function registerTheiaStartOptionsContributions(bind: interfaces.Bind): void {
|
|
24
|
+
bind(ContainerCreationContribution).toService(ExtensionsContribution);
|
|
25
|
+
bind(ContainerCreationContribution).toService(SettingsContribution);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@injectable()
|
|
29
|
+
export class ExtensionsContribution implements RemoteCliContribution, ContainerCreationContribution {
|
|
30
|
+
protected currentConfig: DevContainerConfiguration | undefined;
|
|
31
|
+
|
|
32
|
+
enhanceArgs(context: RemoteCliContext): string[] {
|
|
33
|
+
if (!this.currentConfig) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const extensions = [
|
|
37
|
+
...(this.currentConfig.extensions ?? []),
|
|
38
|
+
...(this.currentConfig.customizations?.vscode?.extensions ?? [])
|
|
39
|
+
];
|
|
40
|
+
this.currentConfig = undefined;
|
|
41
|
+
return extensions?.map(extension => `--install-plugin=${extension}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async handleContainerCreation(createOptions: Docker.ContainerCreateOptions, containerConfig: DevContainerConfiguration): Promise<void> {
|
|
45
|
+
this.currentConfig = containerConfig;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@injectable()
|
|
50
|
+
export class SettingsContribution implements RemoteCliContribution, ContainerCreationContribution {
|
|
51
|
+
protected currentConfig: DevContainerConfiguration | undefined;
|
|
52
|
+
|
|
53
|
+
enhanceArgs(context: RemoteCliContext): string[] {
|
|
54
|
+
if (!this.currentConfig) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
const settings = {
|
|
58
|
+
...(this.currentConfig.settings ?? {}),
|
|
59
|
+
...(this.currentConfig.customizations?.vscode?.settings ?? [])
|
|
60
|
+
};
|
|
61
|
+
this.currentConfig = undefined;
|
|
62
|
+
return Object.entries(settings).map(([key, value]) => `--set-preference=${key}=${JSON.stringify(value)}`) ?? [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async handleContainerCreation(createOptions: Docker.ContainerCreateOptions, containerConfig: DevContainerConfiguration): Promise<void> {
|
|
66
|
+
this.currentConfig = containerConfig;
|
|
67
|
+
}
|
|
68
|
+
}
|
package/src/electron-node/devcontainer-contributions/main-container-creation-contributions.ts
CHANGED
|
@@ -14,17 +14,22 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
import * as Docker from 'dockerode';
|
|
17
|
-
import { injectable, interfaces } from '@theia/core/shared/inversify';
|
|
17
|
+
import { inject, injectable, interfaces } from '@theia/core/shared/inversify';
|
|
18
18
|
import { ContainerCreationContribution } from '../docker-container-service';
|
|
19
19
|
import { DevContainerConfiguration, DockerfileContainer, ImageContainer, NonComposeContainerBase } from '../devcontainer-file';
|
|
20
20
|
import { Path } from '@theia/core';
|
|
21
21
|
import { ContainerOutputProvider } from '../../electron-common/container-output-provider';
|
|
22
|
+
import * as fs from '@theia/core/shared/fs-extra';
|
|
23
|
+
import { RemotePortForwardingProvider } from '@theia/remote/lib/electron-common/remote-port-forwarding-provider';
|
|
24
|
+
import { RemoteDockerContainerConnection } from '../remote-container-connection-provider';
|
|
22
25
|
|
|
23
26
|
export function registerContainerCreationContributions(bind: interfaces.Bind): void {
|
|
24
27
|
bind(ContainerCreationContribution).to(ImageFileContribution).inSingletonScope();
|
|
25
28
|
bind(ContainerCreationContribution).to(DockerFileContribution).inSingletonScope();
|
|
26
29
|
bind(ContainerCreationContribution).to(ForwardPortsContribution).inSingletonScope();
|
|
27
30
|
bind(ContainerCreationContribution).to(MountsContribution).inSingletonScope();
|
|
31
|
+
bind(ContainerCreationContribution).to(RemoteUserContribution).inSingletonScope();
|
|
32
|
+
bind(ContainerCreationContribution).to(PostCreateCommandContribution).inSingletonScope();
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
@injectable()
|
|
@@ -53,50 +58,62 @@ export class DockerFileContribution implements ContainerCreationContribution {
|
|
|
53
58
|
// check if dockerfile container
|
|
54
59
|
if (containerConfig.dockerFile || containerConfig.build?.dockerfile) {
|
|
55
60
|
const dockerfile = (containerConfig.dockerFile ?? containerConfig.build?.dockerfile) as string;
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
const context = containerConfig.context ?? new Path(containerConfig.location as string).dir.fsPath();
|
|
62
|
+
try {
|
|
63
|
+
// ensure dockerfile exists
|
|
64
|
+
await fs.lstat(new Path(context as string).join(dockerfile).fsPath());
|
|
65
|
+
|
|
66
|
+
const buildStream = await api.buildImage({
|
|
67
|
+
context,
|
|
68
|
+
src: [dockerfile],
|
|
69
|
+
} as Docker.ImageBuildContext, {
|
|
70
|
+
buildargs: containerConfig.build?.args
|
|
71
|
+
});
|
|
72
|
+
// TODO probably have some console windows showing the output of the build
|
|
73
|
+
const imageId = await new Promise<string>((res, rej) => api.modem.followProgress(buildStream!, (err, outputs) => {
|
|
74
|
+
if (err) {
|
|
75
|
+
rej(err);
|
|
76
|
+
} else {
|
|
77
|
+
for (let i = outputs.length - 1; i >= 0; i--) {
|
|
78
|
+
if (outputs[i].aux?.ID) {
|
|
79
|
+
res(outputs[i].aux.ID);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
71
82
|
}
|
|
72
83
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
}, progress => outputprovider.onRemoteOutput(OutputHelper.parseProgress(progress))));
|
|
85
|
+
createOptions.Image = imageId;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
outputprovider.onRemoteOutput(`could not build dockerfile "${dockerfile}" reason: ${error.message}`);
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
76
90
|
}
|
|
77
91
|
}
|
|
78
92
|
}
|
|
79
93
|
|
|
80
94
|
@injectable()
|
|
81
95
|
export class ForwardPortsContribution implements ContainerCreationContribution {
|
|
82
|
-
|
|
96
|
+
|
|
97
|
+
@inject(RemotePortForwardingProvider)
|
|
98
|
+
protected readonly portForwardingProvider: RemotePortForwardingProvider;
|
|
99
|
+
|
|
100
|
+
async handlePostConnect(containerConfig: DevContainerConfiguration, connection: RemoteDockerContainerConnection): Promise<void> {
|
|
83
101
|
if (!containerConfig.forwardPorts) {
|
|
84
102
|
return;
|
|
85
103
|
}
|
|
86
104
|
|
|
87
|
-
for (const
|
|
88
|
-
let
|
|
89
|
-
let
|
|
90
|
-
if (typeof
|
|
91
|
-
const parts =
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
for (const forward of containerConfig.forwardPorts) {
|
|
106
|
+
let port: number;
|
|
107
|
+
let address: string | undefined;
|
|
108
|
+
if (typeof forward === 'string') {
|
|
109
|
+
const parts = forward.split(':');
|
|
110
|
+
address = parts[0];
|
|
111
|
+
port = parseInt(parts[1]);
|
|
94
112
|
} else {
|
|
95
|
-
|
|
96
|
-
hostPort = port.toString();
|
|
113
|
+
port = forward;
|
|
97
114
|
}
|
|
98
|
-
|
|
99
|
-
|
|
115
|
+
|
|
116
|
+
this.portForwardingProvider.forwardPort(connection.localPort, { port, address });
|
|
100
117
|
}
|
|
101
118
|
|
|
102
119
|
}
|
|
@@ -126,6 +143,40 @@ export class MountsContribution implements ContainerCreationContribution {
|
|
|
126
143
|
}
|
|
127
144
|
}
|
|
128
145
|
|
|
146
|
+
@injectable()
|
|
147
|
+
export class RemoteUserContribution implements ContainerCreationContribution {
|
|
148
|
+
async handleContainerCreation(createOptions: Docker.ContainerCreateOptions, containerConfig: DevContainerConfiguration, api: Docker): Promise<void> {
|
|
149
|
+
if (containerConfig.remoteUser) {
|
|
150
|
+
createOptions.User = containerConfig.remoteUser;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@injectable()
|
|
156
|
+
export class PostCreateCommandContribution implements ContainerCreationContribution {
|
|
157
|
+
async handlePostCreate?(containerConfig: DevContainerConfiguration, container: Docker.Container, api: Docker, outputprovider: ContainerOutputProvider): Promise<void> {
|
|
158
|
+
if (containerConfig.postCreateCommand) {
|
|
159
|
+
const commands = typeof containerConfig.postCreateCommand === 'object' && !(containerConfig.postCreateCommand instanceof Array) ?
|
|
160
|
+
Object.values(containerConfig.postCreateCommand) : [containerConfig.postCreateCommand];
|
|
161
|
+
for (const command of commands) {
|
|
162
|
+
try {
|
|
163
|
+
let exec;
|
|
164
|
+
if (command instanceof Array) {
|
|
165
|
+
exec = await container.exec({ Cmd: command, AttachStderr: true, AttachStdout: true });
|
|
166
|
+
|
|
167
|
+
} else {
|
|
168
|
+
exec = await container.exec({ Cmd: ['sh', '-c', command], AttachStderr: true, AttachStdout: true });
|
|
169
|
+
}
|
|
170
|
+
const stream = await exec.start({ Tty: true });
|
|
171
|
+
stream.on('data', chunk => outputprovider.onRemoteOutput(chunk.toString()));
|
|
172
|
+
} catch (error) {
|
|
173
|
+
outputprovider.onRemoteOutput('could not execute postCreateCommand ' + JSON.stringify(command) + ' reason:' + error.message);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
129
180
|
export namespace OutputHelper {
|
|
130
181
|
export interface Progress {
|
|
131
182
|
id?: string;
|
package/src/electron-node/devcontainer-contributions/profile-file-modification-contribution.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2024 Typefox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { DevContainerConfiguration } from '../devcontainer-file';
|
|
18
|
+
import { ContainerCreationContribution } from '../docker-container-service';
|
|
19
|
+
import * as Docker from 'dockerode';
|
|
20
|
+
import { injectable } from '@theia/core/shared/inversify';
|
|
21
|
+
import { ContainerOutputProvider } from '../../electron-common/container-output-provider';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* this contribution changes the /etc/profile file so that it won't overwrite the PATH variable set by docker
|
|
25
|
+
*/
|
|
26
|
+
@injectable()
|
|
27
|
+
export class ProfileFileModificationContribution implements ContainerCreationContribution {
|
|
28
|
+
async handlePostCreate(containerConfig: DevContainerConfiguration, container: Docker.Container, api: Docker, outputprovider: ContainerOutputProvider): Promise<void> {
|
|
29
|
+
const stream = await (await container.exec({
|
|
30
|
+
Cmd: ['sh', '-c', 'sed -i \'s|PATH="\\([^"]*\\)"|PATH=${PATH:-"\\1"}|g\' /etc/profile'], User: 'root',
|
|
31
|
+
AttachStderr: true, AttachStdout: true
|
|
32
|
+
})).start({});
|
|
33
|
+
stream.on('data', data => outputprovider.onRemoteOutput(data.toString()));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -258,6 +258,21 @@ export interface DevContainerCommon {
|
|
|
258
258
|
* The default is the same user as the container.
|
|
259
259
|
*/
|
|
260
260
|
remoteUser?: string
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* extensions to install in the container at launch. The expeceted format is publisher.name[@version].
|
|
264
|
+
* The default is no extensions being installed.
|
|
265
|
+
*/
|
|
266
|
+
extensions?: string[]
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* settings to set in the container at launch in the settings.json. The expected format is key=value.
|
|
270
|
+
* The default is no preferences being set.
|
|
271
|
+
*/
|
|
272
|
+
settings?: {
|
|
273
|
+
[k: string]: unknown
|
|
274
|
+
}
|
|
275
|
+
|
|
261
276
|
/**
|
|
262
277
|
* A command to run locally before anything else. This command is run before 'onCreateCommand'.
|
|
263
278
|
* If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell.
|
|
@@ -365,7 +380,23 @@ export interface DevContainerCommon {
|
|
|
365
380
|
* Tool-specific configuration. Each tool should use a JSON object subproperty with a unique name to group its customizations.
|
|
366
381
|
*/
|
|
367
382
|
customizations?: {
|
|
368
|
-
[k: string]: unknown
|
|
383
|
+
[k: string]: unknown,
|
|
384
|
+
vscode?: {
|
|
385
|
+
/**
|
|
386
|
+
* extensions to install in the container at launch. The expeceted format is publisher.name[@version].
|
|
387
|
+
* The default is no extensions being installed.
|
|
388
|
+
*/
|
|
389
|
+
extensions?: string[],
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* settings to set in the container at launch in the settings.json. The expected format is key=value.
|
|
393
|
+
* The default is no preferences being set.
|
|
394
|
+
*/
|
|
395
|
+
settings?: {
|
|
396
|
+
[k: string]: unknown
|
|
397
|
+
}
|
|
398
|
+
[k: string]: unknown
|
|
399
|
+
}
|
|
369
400
|
}
|
|
370
401
|
additionalProperties?: {
|
|
371
402
|
[k: string]: unknown
|