Closed umarcor closed 4 years ago
@umarcor I'd be interested to know what kind of features you are looking to add.
You can define an extension as a required dependency of your extension via the extensionDependencies
of the package.json
file. However, while extensions can provide APIs to be consumed or extended by other extensions, vscode-docker
does not really do so (yet). VS Code's declarative command definitions also allow arbitrary extensions to "extend" the context menus of other extensions provided you know where to look for views/groups, even if those extensions are not necessarily designed for such extension. In that case, the extender needs to accept that updates to the underlying extension may change those views/groups in ways that break the dependent extension.
I would like to define the type of item as ImageTreeItem instead. The type is defined in subdir
src/tree/images/ImageTreeItem
of this repo. However, it seems not to be possible to addvscode-docker
as a dependency throughnpm
oryarn
.
Given that vscode-docker
was not specifically designed to be extended in that way, we don't ship the definitions for types used within the extension. You could certainly create your own type definitions to match, however.
Apart from that, when the command is executed directly (not from the context menu), the image (
item
) isundefined
. For other commands, vscode-docker shows a list with all the available images so that users can pick one. It is a multi-level menu that asks for the name first, and then shows the tags. I'd like to import and reuse this "menu to select an image" feature. Is it possible?
Again, as we didn't intend the extension to expose consumable APIs, that logic is not necessarily exposed in a way that can be reused outside of the extension.
It'd be great to have more information about the commands you'd like to add to those context menus. If it makes sense, in that those commands are core to the use of Docker for many developers, an option could be to make a contribution to vscode-docker
itself rather than try to "extend" it unnaturally. Another option is for us to consider creating official, supported extension points/APIs for use by extensions like yours. Without more context, it's difficult to say what the best option might be.
@philliphoff, thanks a lot for your very quick reply! Overall, I understand that this is not an expected use case and that sources are not designed to support it. Actually, my main motivation to open this issue was to discuss it.
I'd be interested to know what kind of features you are looking to add.
It'd be great to have more information about the commands you'd like to add to those context menus.
Sure. I use Docker for Windows very frequently in order to try new projects written in Python, JS/TS, Go, Rust, Ruby... Most of the projects have installation instructions but not ready to use Dockerfiles (or images). Projects have different requirements, so I find myself continuously writing commands such as the following, before attaching VSCode to the containers through 'Remotes - Containers':
winpty docker run --rm -it [-v /$(pwd)://src -w //src] [-p 5000] <image_name> [bash]
#or
runx --no-auth -- x11docker --hostdisplay -i [--user=0] -- [-v /$(pwd)://src] [-p 5000] -- <image_name> bash
As you see, options are:
$(pwd)
.Hence, it is not hard (once you learn them by heart) to write these commands, but it is annoying. Plus, having them written in some file does not help much, because I need to find it, copy, modify and them run. It is almost as much effort as writing it all.
The feature I'd like to implement is to replace current Run
and Run interactive
commands with a single Run (Template)
that would open a QuickPick menu (as suggested in #1311, when a single matching task is not found). The menu would show the new Templates
plus docker-run
tasks. The difference between a template and a task is that the latter is expected to be defined in a JSON file and to contain all the required arguments. Conversely, Templates are not complete and do not need to be written in a JSON file. Hence, the user is prompted (through QuickPick/QuickInput) to complete the missing fields or to leave them blank. This is a very early example of how the UI might look like:
Of course, current Run
and Run interactive
commands might be reimplemented to be the two default Templates; which is shown in the screencast.
Such a feature is related to #1001, #1321 and it would hopefully fix/close #1274, #1311.
In that case, the extender needs to accept that updates to the underlying extension may change those views/groups in ways that break the dependent extension.
Yes, I assume that maintaining a separate extension will require it to be kept up to date with changes in vscode-docker; and that UX might be bad when non-compatible versions of the extensions are used.
You could certainly create your own type definitions to match, however.
Importing the type definitions is a kind of most-simple use case to reuse some content from this repo. That is, while internal APIs might depend on some specific objects being allocated/available, importing type definitions might be easier. In practice, if I cannot reuse other resources (say functions), I think that this is not critical.
Again, as we didn't intend the extension to expose consumable APIs, that logic is not necessarily exposed in a way that can be reused outside of the extension.
Another option is for us to consider creating official, supported extension points/APIs for use by extensions like yours.
I guess that this was/is the implicit question in this issue: what do you think about enhancing this extension to expose consumable APIs? There are at least two use cases where it'd be so helpful:
docker run
, extensions would use ${vscode-docker.cli} run
or vscode-docker.cli.run(...)
.It is possible for third-party extensions to import docker-modem
, but I believe that vscode-docker
contains features specific to VSCode that would be a better fit for extensions.
If it makes sense, in that those commands are core to the use of Docker for many developers, an option could be to make a contribution to vscode-docker itself rather than try to "extend" it unnaturally.
Without more context, it's difficult to say what the best option might be.
I agree that this feature might be better contributed to vscode-docker itself, rather than trying to extend it unnaturally. On the one hand, this is because I'm lacking some knowledge about the canonical location of settings and common resources in different contexts: single folder, workspace, user settings, host settings, etc. On the other hand, I think that the use cases that I would like to address are not well supported yet.
Unfortunately, I could not build this extension... I tried with master
, 0.9.0
and 0.8.2
. I get:
> vscode-docker@0.9.1-alpha build /wrk
> tsc -p ./
src/tasks/DockerPseudoterminal.ts:6:75 - error TS2305: Module '"vscode"' has no exported member 'Pseudoterminal'.
6 import { CancellationToken, CancellationTokenSource, Event, EventEmitter, Pseudoterminal, TaskScope, TerminalDimensions, workspace, WorkspaceFolder } from 'vscode';
~~~~~~~~~~~~~~
src/tasks/DockerPseudoterminal.ts:6:102 - error TS2305: Module '"vscode"' has no exported member 'TerminalDimensions'.
6 import { CancellationToken, CancellationTokenSource, Event, EventEmitter, Pseudoterminal, TaskScope, TerminalDimensions, workspace, WorkspaceFolder } from 'vscode';
~~~~~~~~~~~~~~~~~~
src/tasks/DockerTaskProvider.ts:6:29 - error TS2305: Module '"vscode"' has no exported member 'CustomExecution'.
6 import { CancellationToken, CustomExecution, ProviderResult, Task, TaskProvider } from 'vscode';
~~~~~~~~~~~~~~~
src/utils/getVSCodeRemoteInfo.ts:6:15 - error TS2305: Module '"vscode"' has no exported member 'ExtensionKind'.
6 import { env, ExtensionKind, extensions } from 'vscode';
~~~~~~~~~~~~~
src/utils/getVSCodeRemoteInfo.ts:43:48 - error TS2339: Property 'remoteName' does not exist on type 'typeof env'.
43 const remoteName: string | undefined = env.remoteName;
~~~~~~~~~~
src/utils/getVSCodeRemoteInfo.ts:62:23 - error TS2339: Property 'extensionKind' does not exist on type 'Extension<any>'.
62 if (extension.extensionKind === ExtensionKind.UI) {
~~~~~~~~~~~~~
Found 6 errors.
Apart from that, considering how #1001 was handled, I feel that there is no much interest on this feature, as the suggested approach seems to be using either compose files or tasks. Nonetheless, I'd be glad to upstream it.
Note that I also considered implementing this as a Task Provider. However, I am not familiar with class vscode.Task
. Anyway, this is independent from the menus to complete missing fields in Templates.
@umarcor Based on a lot of similar user feedback, we now have a proposal to provide customization of many of the Docker commands issued by the extension. The proposal includes the ability to have multiple customizations, some of which can be automatically matched to specific images/containers and others which can be selected via a prompt.
It'd be great to get feedback from you as to how the proposal would meet your needs (or not) that you brought up in this issue (that prompted your original desire to extend our extension).
@umarcor Have you been able to try out the command customization in 1.0.0?
@bwateratmsft, unfortunately, I could not. It is in first place of my non-compulsory tasks because I'm using VSCode and Docker every day, and every day I remember it. But I had a trip in the end Feb, then the crisis came and I'm having a hard time to keep up with this. I will let you know as soon as I can.
No worries!
@bwateratmsft I wanted to try the new features, but I don't know where to start. I tried adding "docker.commands.runInteractive": "docker run --rm -it ghdl/ghdl:buster-mcode"
to my settings.json
, in the hope that it would replace the default "Docker Images: Run Interactive" command, not to prompt for any parameter. However, it seems to have no effect at all. Where do I need to set the templates explained in #1596?
EDIT
Ok. Got it:
"docker.commands.runInteractive":
[
{
"label": "mine",
"template": "docker run --rm -it ghdl/ghdl:buster-mcode"
},
{
"label": "yours",
"template": "docker run --rm -it ${tag}"
}
]
First off, I'd like to say that this new feature is awesome! It is still quite verbose, but it will definitely save lots of typing! It's a great step in the good direction.
The following questions are to wrap my head around the current limits and to know about your plans for future releases.
"docker.commands.run":
[
{
"label": "interactive",
"template": "docker run --rm -it ${exposedPorts} ${tag}"
},
{
"label": "daemon",
"template": "docker run --rm -d ${exposedPorts} ${tag}"
}
]
I thought that 'Run' might not open a new terminal, while 'Run Interactive' would. That would explain why it is required to tell them apart. However, I found it not to be the case. Both of them do open a new terminal.
Related to the previous point, would it be possible to define in the template whether a new terminal should be opened or the currently opened one should be used instead? I guess that this might well be a completeley independent feature which I just happened to care about now...
Command "Docker Images: Run Interactive" seems not to be affected by my settings. When I try to run an image by right-clicking on it, template selection is shown as expected. However, if I do F1 -> "Docker Images: Run Interactive", no template selection is available.
How can I define one or multiple custom parameters which the user can set in a dropdown menu?
{
"label": "customRun",
"template": "docker run --rm -it ${myCustomParam} ${tag}"
}
tag
would be a conflict. However, other parameters might not conflict. I guess the most simple approach is not to show configurations/templates that conflict. {
"label": "ghdl",
"template": "docker run --rm -it ${tag}",
"configurations": {
"gmcode": {
"tag": "ghdl/ghdl:buster-mcode"
},
"gllvm": {
"tag": "ghdl/ghdl:buster-llvm-7",
}
}
}
In fact, my main use case of these configurations would be with the custom params as asked in the previous point. For example:
{
"label": "mount",
"template": "docker run --rm -it ${volume} -w /src ${tag}",
"configurations": {
"src": {
"volume": "$(pwd):/src"
},
"wrk": {
"volume": "$(pwd):/wrk"
},
"abs": {
"volume": "${host}:${container}"
}
}
}
Note that the last configuration would be an edge case because it would always prompt the user for host
and container
. This is related to the conversation we had in #1596 about "remembering" latest used configurations. Hence, if the user used template "mount" with configuration "abs" and "/c/Users/username/workdir" and "/wrk" were introduced as parameters, a new configuration would be saved automatically:
"randomID": {
"volume": "/c/Users/username/workdir:/wrk"
}
Thanks for your interest! I'll try to cover your questions:
What's the difference between 'Run' and 'Run Interactive'? Shouldn't those be two default templates for 'Run'?
"Run" is meant for background container starts (using -d
flag), and "Run Interactive" for launching with a shell into the container (using -it
flag).
Related to the previous point, would it be possible to define in the template whether a new terminal should be opened or the currently opened one should be used instead? I guess that this might well be a completeley independent feature which I just happened to care about now...
No, but we have another bug for that planned for 1.2 (#251). The behavior will be how VSCode treats tasks--if terminal 1 is busy running a different task, then a new terminal will be created, otherwise it will be reused--and so on.
Command "Docker Images: Run Interactive" seems not to be affected by my settings. When I try to run an image by right-clicking on it, template selection is shown as expected. However, if I do F1 -> "Docker Images: Run Interactive", no template selection is available.
When you are right-clicking, are you doing "Run" or "Run Interactive"? If you set up exactly one "Run Interactive" template, there will never be a prompt for which (more on that below).
How can I define one or multiple custom parameters which the user can set in a dropdown menu?
We don't have a quickpick/dropdown option for parameters, but we do support arbitrary config values. For example, in settings.json, I could put "some.param": "someValue"
, and in the command config, "template": "... ${config:some.param}"
. The setting name you define does not need to belong to any existing extension or to VSCode itself--it can be anything you want.
Is it possible to define "partial configurations"?
I guess it depends what you mean. We have the ability to select through multiple available commands using some contextual hints, with the match
field on the command definition:
"docker.commands.runInteractive": {
"label": "My Alpine starter",
"template": "docker run -it ${exposedPorts} ${tag}",
"match": "alpine"
}
In this example, match
is a regular expression (case-insensitive), and we will look at a few contextual hints to match it against. For "Run Interactive", and "Run", we look at the full tag of the image. So, if I do "Run Interactive" on any image with "alpine" in the full tag, it will run this command instead of the default.
Our selection behavior is basically this--if there are matching templates, we ask you to choose which (the choice is automatic if there's exactly 1 matching template--no prompt). If none match, we ask you to choose between all "universal" templates, i.e. those without match
parameter (again, automatic if there's exactly 1). Finally, if there's none matching and none universal, we use the default.
If you want to get really advanced for a particular image--for example, a database container--and use volumes, specific ports, environment variables, etc.--we'd recommend using the docker-run
task. The command customization is meant to be more generic. The task offers relatively easy customization of nearly everything you can pass to docker run
.
"Run" is meant for background container starts (using
-d
flag), and "Run Interactive" for launching with a shell into the container (using-it
flag).
That's the default template for each of them. However, now, both of them can be defined as templates of the same command. For example:
"docker.commands.run":
[
{
"label": "interactive",
"template": "docker run --rm -it ${exposedPorts} ${tag}"
},
{
"label": "daemon",
"template": "docker run --rm -d ${exposedPorts} ${tag}"
}
]
Then, 'Run Interactive' feels redundant, because it is already accesible as 'Run'.
When you are right-clicking, are you doing "Run" or "Run Interactive"? If you set up exactly one "Run Interactive" template, there will never be a prompt for which (more on that below).
When I right-click, it works as expected. However, when I do F1 -> "Docker Images: Run Interactive" instead, the default command is executed. I.e., even if I have three templates, I am not prompted to choose one.
I guess it depends what you mean. We have the ability to select through multiple available commands using some contextual hints, with the
match
field on the command definition
I mean to reduce the verbosity of setting the templates, so that it is possible to have granularity without copying almost identical templates again and again. Conversely, match
is about reducing the verbosity/effort when choosing which to execute. I'm ok with the current status in this regard. I don't want the tool to make a clever guess for me, I want it to let me decide fast.
For example, being able to write this:
{
"label": "mount",
"template": "docker run --rm -it ${volume} -w /src ${tag}",
"configurations": {
"src": {"volume": "$(pwd):/src"},
"wrk": {"volume": "$(pwd):/wrk"},
"abs": {"volume": "${host}:${container}"}
}
}
instead of this:
{
"label": "src",
"template": "docker run --rm -it $(pwd):/src -w /src ${tag}",
},
{
"label": "wrk",
"template": "docker run --rm -it $(pwd):/wrk -w /src ${tag}",
},
{
"label": "wrk",
"template": "docker run --rm -it ${host}:${container} -w /src ${tag}",
}
If you want to get really advanced for a particular image--for example, a database container--and use volumes, specific ports, environment variables, etc.--we'd recommend using the
docker-run
task. The command customization is meant to be more generic. The task offers relatively easy customization of nearly everything you can pass todocker run
.
I'm afraid that docker-run
task won't work because it does not allow to customize docker run
. Only arguments/options can be modified. In fact, using tasks was my first investigation before opening this issue and trying to write an extension myself. Now, at least, it's much easier to just have the settings open in a tab and customize the commands before running a container.
However, now, both of them can be defined as templates of the same command.
They can, and that is intentional. You can also make "Run Interactive" do something totally weird like rm -rf /
. The two of them need to stay as separate commands (and separate settings) because they correspond to separate actions in the UI. That said, you could define an interactive version of the "Run" command.
However, when I do F1 -> "Docker Images: Run Interactive" instead, the default command is executed. I.e., even if I have three templates, I am not prompted to choose one.
That sounds like it might be a bug, I'm going to take a look.
I'm afraid that
docker-run
task won't work because it does not allow to customizedocker run
.
What is the task missing that you need? We're certainly open to expanding it if it's lacking.
However, when I do F1 -> "Docker Images: Run Interactive" instead, the default command is executed. I.e., even if I have three templates, I am not prompted to choose one.
That sounds like it might be a bug, I'm going to take a look.
I tried it out from both command palette and the explorer view, and got the prompt:
Here's what I have in settings.json
:
"docker.commands.runInteractive": [
{
"label": "Regular",
"template": "docker run --rm -it ${exposedPorts} ${tag}"
},
{
"label": "No RM",
"template": "docker run -it ${exposedPorts} ${tag}"
}
]
Can you share what setting you have that isn't resulting in a prompt?
This issue has been closed automatically because it needs more information and has not had recent activity. See also our issue reporting guidelines.
Happy Coding!
I'm writing a TS extension that provides some features on top of vscode-docker and I would like to use some of the types and functions defined here.
Precisely, a command is added to
"category": "Docker Images"
and to the context menu ("when": "view == dockerImages && viewItem == image", "group": "images_1_run@2"
). This is currently handled as follows:I would like to define the type of
item
asImageTreeItem
instead. The type is defined in subdirsrc/tree/images/ImageTreeItem
of this repo. However, it seems not to be possible to addvscode-docker
as a dependency throughnpm
oryarn
.Apart from that, when the command is executed directly (not from the context menu), the image (
item
) isundefined
. For other commands, vscode-docker shows a list with all the available images so that users can pick one. It is a multi-level menu that asks for the name first, and then shows the tags. I'd like to import and reuse this "menu to select an image" feature. Is it possible?