1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Docker: Allow setting a mapping for docker paths (#46)

* Docker: Allow setting a mapping for docker paths

Bug 579944 introduced using Windows paths, to allow putting your project
into the WSL's file system.
While Docker for Windows (the commercial version) supports Windows
paths, this does not work with a OSS-docker installed in the WSL.
It is now possible to provide a path mapping to work around this.

Co-authored-by: Jeff Johnston <jjohnstn@redhat.com>
This commit is contained in:
Moritz 'Morty' Strübe 2022-08-30 21:40:28 +02:00 committed by GitHub
parent c0e9b347a2
commit 52483c01c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 214 additions and 86 deletions

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Plugin.name
Bundle-SymbolicName: org.eclipse.cdt.docker.launcher;singleton:=true
Bundle-Version: 1.3.400.qualifier
Bundle-Version: 2.0.0.qualifier
Bundle-Activator: org.eclipse.cdt.docker.launcher.DockerLaunchUIPlugin
Bundle-Vendor: %Plugin.vendor
Bundle-Localization: plugin

View file

@ -62,6 +62,8 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
public final static String VOLUMES_ID = DockerLaunchUIPlugin.PLUGIN_ID + ".containerbuild.property.volumes"; //$NON-NLS-1$
public final static String SELECTED_VOLUMES_ID = DockerLaunchUIPlugin.PLUGIN_ID
+ ".containerbuild.property.selectedvolumes"; //$NON-NLS-1$
/** @since 2.0 */
public final static String DOCKERD_PATH = DockerLaunchUIPlugin.PLUGIN_ID + ".containerbuild.property.dockerdpath"; //$NON-NLS-1$
public final static String VOLUME_SEPARATOR_REGEX = "[|]"; //$NON-NLS-1$
@ -253,14 +255,16 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
boolean keepContainer = prefs.getBoolean(PreferenceConstants.KEEP_CONTAINER_AFTER_LAUNCH, false);
ICBuildConfiguration buildCfg = getBuildConfiguration();
String selectedVolumeString = null;
String connectionName = null;
String imageName = null;
final String selectedVolumeString;
final String connectionName;
final String imageName;
final String pathMapProperty;
if (buildCfg != null) {
IToolChain toolChain = buildCfg.getToolChain();
selectedVolumeString = toolChain.getProperty(SELECTED_VOLUMES_ID);
connectionName = toolChain.getProperty(IContainerLaunchTarget.ATTR_CONNECTION_URI);
imageName = toolChain.getProperty(IContainerLaunchTarget.ATTR_IMAGE_ID);
pathMapProperty = toolChain.getProperty(DOCKERD_PATH);
} else {
ICConfigurationDescription cfgd = CoreModel.getDefault().getProjectDescription(fProject)
.getActiveConfiguration();
@ -272,6 +276,7 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
selectedVolumeString = props.getProperty(SELECTED_VOLUMES_ID);
connectionName = props.getProperty(ContainerCommandLauncher.CONNECTION_ID);
imageName = props.getProperty(ContainerCommandLauncher.IMAGE_ID);
pathMapProperty = props.getProperty(DOCKERD_PATH);
}
// Add any specified volumes to additional dir list
@ -288,8 +293,20 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
}
setImageName(imageName);
additionalDirs.addAll(
additionalPaths.stream().map(p -> ContainerLaunchUtils.toDockerVolume(p)).collect(Collectors.toList()));
final Map<String, String> pathMap = new HashMap<>();
if (pathMapProperty != null && !pathMapProperty.isEmpty()) {
final var entries = pathMapProperty.split(";"); //$NON-NLS-1$
for (var e : entries) {
final var spl = e.split("\\|"); //$NON-NLS-1$
if (spl.length == 2) {
pathMap.put(spl[0], spl[1]);
}
}
}
additionalDirs.addAll(additionalPaths.stream().map(p -> ContainerLaunchUtils.toDockerVolume(pathMap, p))
.collect(Collectors.toList()));
fProcess = launcher.runCommand(connectionName, imageName, fProject, this, cmdList, workingDir, additionalDirs,
origEnv, fEnvironment, supportStdin, privilegedMode, labels, keepContainer);

View file

@ -13,6 +13,8 @@
*******************************************************************************/
package org.eclipse.cdt.internal.docker.launcher;
import java.util.Map;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
@ -59,11 +61,23 @@ public class ContainerLaunchUtils {
* @param path The path on the hose
* @return The string to be passed to the docker daemon
*/
public static final String toDockerVolume(IPath path) {
IPath p = path.makeAbsolute();
String rv = toDockerPath(p);
public static final String toDockerVolume(Map<String, String> pMap, IPath path) {
// The path on the Docker host
var dhPath = path.makeAbsolute().toString();
for (var me : pMap.entrySet()) {
var elp = me.getKey();
var edhp = me.getValue();
if (dhPath.startsWith(elp)) {
dhPath = edhp + dhPath.substring(elp.length());
break;
}
}
// docker-path first, docker-host-path third
String rv = toDockerPath(path.makeAbsolute());
rv += ":HOST_FILE_SYSTEM:"; //$NON-NLS-1$
rv += p.toOSString();
rv += dhPath;
rv += ":false:true"; //$NON-NLS-1$ RO=false, selected = true
return rv;
}

View file

@ -22,6 +22,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
@ -86,6 +87,7 @@ import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
@SuppressWarnings("restriction")
public class ContainerPropertyTab extends AbstractCBuildPropertyTab
@ -102,6 +104,7 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
private Button enableButton;
private Button launchAutotoolsButton;
private Button addButton;
private Text dockerDPath;
private IDockerConnection connection;
private IDockerConnection[] connections;
private IDockerImageListener containerTab;
@ -170,83 +173,138 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
usercomp.setLayoutData(gd);
enableButton = new Button(usercomp, SWT.CHECK);
enableButton.setText(Messages.ContainerPropertyTab_Enable_Msg);
//Enable button
{
enableButton = new Button(usercomp, SWT.CHECK);
enableButton.setText(Messages.ContainerPropertyTab_Enable_Msg);
iCfg = getCfg();
iCfgd = getResDesc().getConfiguration();
iCfg = getCfg();
iCfgd = getResDesc().getConfiguration();
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 5;
enableButton.setLayoutData(gd);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 5;
enableButton.setLayoutData(gd);
}
// Connection
{
Label connectionSelectorLabel = new Label(usercomp, SWT.NULL);
connectionSelectorLabel.setText(Messages.ContainerTab_Connection_Selector_Label);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
connectionSelectorLabel.setLayoutData(gd);
Label connectionSelectorLabel = new Label(usercomp, SWT.NULL);
connectionSelectorLabel.setText(Messages.ContainerTab_Connection_Selector_Label);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
connectionSelectorLabel.setLayoutData(gd);
connectionSelector = new Combo(usercomp, SWT.BORDER | SWT.READ_ONLY);
connectionSelector.setToolTipText(Messages.ContainerTab_Connection_Selector_Tooltip);
initializeConnectionSelector();
connectionSelector.addModifyListener(connectionModifyListener);
// Following is a kludge so that on Linux the Combo is read-only but
// has a white background.
connectionSelector.addVerifyListener(new VerifyListener() {
@Override
public void verifyText(VerifyEvent e) {
e.doit = false;
}
});
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 3;
gd.grabExcessHorizontalSpace = true;
connectionSelector.setLayoutData(gd);
connectionSelector = new Combo(usercomp, SWT.BORDER | SWT.READ_ONLY);
connectionSelector.setToolTipText(Messages.ContainerTab_Connection_Selector_Tooltip);
initializeConnectionSelector();
connectionSelector.addModifyListener(connectionModifyListener);
// Following is a kludge so that on Linux the Combo is read-only but
// has a white background.
connectionSelector.addVerifyListener(new VerifyListener() {
@Override
public void verifyText(VerifyEvent e) {
e.doit = false;
}
});
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 3;
gd.grabExcessHorizontalSpace = true;
connectionSelector.setLayoutData(gd);
Label label1 = new Label(usercomp, SWT.NULL);
gd = new GridData();
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
label1.setLayoutData(gd);
}
// DockerDPath
{
Label label = new Label(usercomp, SWT.NULL);
label.setText(Messages.ContainerPropertyTab_dockerDPath);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 1;
label.setLayoutData(gd);
Label label1 = new Label(usercomp, SWT.NULL);
gd = new GridData();
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
label1.setLayoutData(gd);
dockerDPath = new Text(usercomp, SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 3;
dockerDPath.setLayoutData(gd);
dockerDPath.setToolTipText(Messages.ContainerPropertyTab_dockerDPath_Tooltip);
dockerDPath.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
setDockerDPath(dockerDPath.getText());
Label imageSelectorLabel = new Label(usercomp, SWT.NULL);
imageSelectorLabel.setText(Messages.ContainerTab_Image_Selector_Label);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 1;
connectionSelectorLabel.setLayoutData(gd);
}
});
imageCombo = new Combo(usercomp, SWT.DROP_DOWN);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 3;
gd.grabExcessHorizontalSpace = true;
imageCombo.setLayoutData(gd);
label = new Label(usercomp, SWT.NULL);
gd = new GridData();
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
label.setLayoutData(gd);
Label label2 = new Label(usercomp, SWT.NULL);
gd = new GridData();
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
label2.setLayoutData(gd);
label = new Label(usercomp, SWT.NULL);
gd = new GridData();
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
label.setLayoutData(gd);
initializeImageCombo();
label = new Label(usercomp, SWT.NULL);
label.setText(Messages.ContainerPropertyTab_dockerDPath_Instruction);
gd = new GridData();
gd.horizontalSpan = 3;
gd.grabExcessHorizontalSpace = false;
label.setLayoutData(gd);
imageCombo.addSelectionListener(new SelectionListener() {
label = new Label(usercomp, SWT.NULL);
gd = new GridData();
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
label.setLayoutData(gd);
@Override
public void widgetSelected(SelectionEvent e) {
setImageId(imageCombo.getText());
model.setSelectedImage(displayedImages.get(imageCombo.getSelectionIndex()));
}
}
// Image selector
{
Label imageSelectorLabel = new Label(usercomp, SWT.NULL);
imageSelectorLabel.setText(Messages.ContainerTab_Image_Selector_Label);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 1;
imageSelectorLabel.setLayoutData(gd);
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
imageCombo = new Combo(usercomp, SWT.DROP_DOWN);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 3;
gd.grabExcessHorizontalSpace = true;
imageCombo.setLayoutData(gd);
});
Label label2 = new Label(usercomp, SWT.NULL);
gd = new GridData();
gd.horizontalSpan = 1;
gd.grabExcessHorizontalSpace = false;
label2.setLayoutData(gd);
initializeImageCombo();
imageCombo.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
setImageId(imageCombo.getText());
model.setSelectedImage(displayedImages.get(imageCombo.getSelectionIndex()));
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
// Volume
createVolumeSettingsContainer(usercomp);
// Autotools
try {
IProject project = iCfgd.getProjectDescription().getProject();
IProjectNature nature = project.getNature("org.eclipse.cdt.autotools.core.autotoolsNatureV2"); //$NON-NLS-1$
isAutotoolsProject = (nature != null);
@ -275,6 +333,7 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
DockerLaunchUIPlugin.log(e);
}
// Handle enablement stuff
initializeEnablementButton();
enableButton.addSelectionListener(new SelectionListener() {
@ -587,6 +646,20 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
}
}
private void setDockerDPath(String ddPath) {
if (iCfg instanceof IMultiConfiguration) {
IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg).getItems();
for (int i = 0; i < cfs.length; i++) {
IConfiguration cfg = cfs[i];
IOptionalBuildProperties p = cfg.getOptionalBuildProperties();
p.setProperty(ContainerCommandLauncher.DOCKERD_PATH, ddPath);
}
} else {
IOptionalBuildProperties p = iCfg.getOptionalBuildProperties();
p.setProperty(ContainerCommandLauncher.DOCKERD_PATH, ddPath);
}
}
private void setImageId(String imageId) {
if (iCfg instanceof IMultiConfiguration) {
IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg).getItems();
@ -715,6 +788,12 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
}
private void initializeDockerDPath() {
IOptionalBuildProperties properties = iCfg.getOptionalBuildProperties();
var path = properties.getProperty(ContainerCommandLauncher.DOCKERD_PATH);
dockerDPath.setText(path == null ? "" : path); //$NON-NLS-1$
}
private void initializeImageCombo() {
initialImageId = null;
IOptionalBuildProperties properties = iCfg.getOptionalBuildProperties();
@ -878,22 +957,8 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
@Override
protected void performDefaults() {
if (iCfg instanceof IMultiConfiguration) {
IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg).getItems();
for (int i = 0; i < cfs.length; i++) {
IOptionalBuildProperties props = cfs[i].getOptionalBuildProperties();
props.setProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED, Boolean.toString(false));
if (connections.length > 0) {
props.setProperty(ContainerCommandLauncher.CONNECTION_ID, connections[0].getUri());
} else {
props.setProperty(ContainerCommandLauncher.CONNECTION_ID, null);
}
props.setProperty(ContainerCommandLauncher.IMAGE_ID, null);
props.setProperty(ContainerCommandLauncher.VOLUMES_ID, null);
props.setProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID, null);
}
} else {
IOptionalBuildProperties props = iCfg.getOptionalBuildProperties();
Consumer<IOptionalBuildProperties> setProps = (IOptionalBuildProperties props) -> {
props.setProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED, Boolean.toString(false));
if (connections.length > 0) {
props.setProperty(ContainerCommandLauncher.CONNECTION_ID, connections[0].getUri());
@ -901,6 +966,20 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
props.setProperty(ContainerCommandLauncher.CONNECTION_ID, null);
}
props.setProperty(ContainerCommandLauncher.IMAGE_ID, null);
props.setProperty(ContainerCommandLauncher.VOLUMES_ID, null);
props.setProperty(ContainerCommandLauncher.SELECTED_VOLUMES_ID, null);
props.setProperty(ContainerCommandLauncher.DOCKERD_PATH, null);
};
if (iCfg instanceof IMultiConfiguration) {
IConfiguration[] cfs = (IConfiguration[]) ((IMultiConfiguration) iCfg).getItems();
for (int i = 0; i < cfs.length; i++) {
IOptionalBuildProperties props = cfs[i].getOptionalBuildProperties();
setProps.accept(props);
}
} else {
IOptionalBuildProperties props = iCfg.getOptionalBuildProperties();
setProps.accept(props);
}
initialEnabled = false;
initialConnection = null;
@ -911,6 +990,7 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
connectionSelector.select(0);
}
imageCombo.setText(""); //$NON-NLS-1$
dockerDPath.setText(""); //$NON-NLS-1$
model.setDataVolumes(null);
model.setSelectedDataVolumes(new HashSet<>());
enableButton.setSelection(false);
@ -928,6 +1008,7 @@ public class ContainerPropertyTab extends AbstractCBuildPropertyTab
initializeConnectionSelector();
initializeImageCombo();
initializeDockerDPath();
initializeEnablementButton();
initializeVolumesTable();
}

View file

@ -53,6 +53,16 @@ public class ContainerPropertyVolumesModel extends BaseDatabindingModel {
private IDockerImage selectedImage;
private String dockerDPath;
public String getDockerDPath() {
return dockerDPath;
}
public void setDockerDPath(String dockerDPath) {
this.dockerDPath = dockerDPath;
}
public ContainerPropertyVolumesModel(final IDockerConnection connection) {
this.connection = connection;
}

View file

@ -112,6 +112,9 @@ public class Messages extends NLS {
public static String StandardGDBDebuggerPage14;
public static String ContainerPropertyTab_dockerDPath;
public static String ContainerPropertyTab_dockerDPath_Instruction;
public static String ContainerPropertyTab_dockerDPath_Tooltip;
public static String ContainerPropertyTab_Title;
public static String ContainerPropertyTab_Enable_Msg;
public static String ContainerPropertyTab_Run_Autotools_In_Container_Msg;

View file

@ -61,6 +61,9 @@ ContainerPortDialog_containerLabel=Container port:
ContainerPortDialog_hostAddressLabel=Host address:
ContainerPortDialog_hostPortLabel=Host port:
ContainerPropertyTab_dockerDPath=Path mapping:
ContainerPropertyTab_dockerDPath_Instruction="<host path>|<container path>;[..]" - e.g "C:|/mnt/c;D:|/mnt/d"
ContainerPropertyTab_dockerDPath_Tooltip=Leave empty when in doubt. Mapping is done using string replacement.
ContainerPropertyTab_Title=Container Settings
ContainerPropertyTab_Enable_Msg=Build inside Docker Image
ContainerPropertyTab_Run_Autotools_In_Container_Msg=Run all Autotools in Container