| /******************************************************************************* |
| * Copyright (c) 2015, 2016 Red Hat Inc. and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Red Hat - Initial Contribution |
| *******************************************************************************/ |
| package org.eclipse.linuxtools.internal.docker.ui.launch; |
| |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.core.databinding.DataBindingContext; |
| import org.eclipse.core.databinding.beans.BeanProperties; |
| import org.eclipse.core.databinding.observable.value.IObservableValue; |
| import org.eclipse.core.databinding.observable.value.IValueChangeListener; |
| import org.eclipse.core.databinding.validation.IValidator; |
| import org.eclipse.core.databinding.validation.ValidationStatus; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; |
| import org.eclipse.jface.databinding.swt.WidgetProperties; |
| import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; |
| import org.eclipse.jface.dialogs.ProgressMonitorDialog; |
| import org.eclipse.jface.fieldassist.ComboContentAdapter; |
| import org.eclipse.jface.fieldassist.ContentProposal; |
| import org.eclipse.jface.fieldassist.ContentProposalAdapter; |
| import org.eclipse.jface.fieldassist.ControlDecoration; |
| import org.eclipse.jface.fieldassist.IContentProposal; |
| import org.eclipse.jface.fieldassist.IContentProposalProvider; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.layout.GridLayoutFactory; |
| import org.eclipse.jface.viewers.ArrayContentProvider; |
| import org.eclipse.jface.viewers.ComboViewer; |
| import org.eclipse.linuxtools.docker.core.AbstractRegistry; |
| import org.eclipse.linuxtools.docker.core.DockerConnectionManager; |
| import org.eclipse.linuxtools.docker.core.IDockerConnection; |
| import org.eclipse.linuxtools.docker.core.IDockerContainer; |
| import org.eclipse.linuxtools.docker.core.IDockerImage; |
| import org.eclipse.linuxtools.docker.core.IDockerImageInfo; |
| import org.eclipse.linuxtools.docker.ui.Activator; |
| import org.eclipse.linuxtools.docker.ui.wizards.ImageSearch; |
| import org.eclipse.linuxtools.internal.docker.core.RegistryInfo; |
| import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory; |
| import org.eclipse.linuxtools.internal.docker.ui.commands.CommandUtils; |
| import org.eclipse.linuxtools.internal.docker.ui.utils.IRunnableWithResult; |
| import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageNameValidator; |
| import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRunResourceVolumesVariablesModel; |
| import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRunSelectionModel; |
| import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRunSelectionModel.ExposedPortModel; |
| import org.eclipse.linuxtools.internal.docker.ui.wizards.WizardMessages; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Text; |
| |
| public class RunImageMainTab extends AbstractLaunchConfigurationTab { |
| |
| private static final String TAB_NAME = "RunMainTab.name"; //$NON-NLS-1$ |
| // private static final String ERROR_PULLING_IMAGE = "ImagePullError.msg"; |
| // //$NON-NLS-1$ |
| |
| private static final int COLUMNS = 3; |
| |
| private final DataBindingContext dbc = new DataBindingContext(); |
| private final ImageRunSelectionModel model; |
| private final ImageRunResourceVolumesVariablesModel volumesModel; |
| |
| public RunImageMainTab(ImageRunSelectionModel model, |
| ImageRunResourceVolumesVariablesModel volumesModel) { |
| this.model = model; |
| this.volumesModel = volumesModel; |
| } |
| |
| public ImageRunSelectionModel getModel() { |
| return model; |
| } |
| |
| @Override |
| public String getName() { |
| return LaunchMessages.getString(TAB_NAME); |
| } |
| |
| @Override |
| public void createControl(Composite parent) { |
| final Composite container = new Composite(parent, SWT.NONE); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).span(1, 1) |
| .grab(true, false).applyTo(container); |
| GridLayoutFactory.fillDefaults().numColumns(COLUMNS).margins(6, 6) |
| .applyTo(container); |
| if (model == null) { |
| setErrorMessage(LaunchMessages.getString("NoConnectionError.msg")); |
| return; |
| } else { |
| setErrorMessage(null); |
| setDefaultValues(); |
| createImageSettingsSection(container); |
| createSectionSeparator(container, true); |
| createRunOptionsSection(container); |
| final IObservableValue connectionSelectionObservable = BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.SELECTED_CONNECTION_NAME) |
| .observe(model); |
| connectionSelectionObservable |
| .addValueChangeListener(onConnectionSelectionChange()); |
| final IObservableValue imageSelectionObservable = BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.SELECTED_IMAGE_NAME) |
| .observe(model); |
| imageSelectionObservable |
| .addValueChangeListener(onImageSelectionChange()); |
| } |
| setControl(container); |
| } |
| |
| private void setDefaultValues() { |
| final IDockerImage selectedImage = model.getSelectedImage(); |
| if (selectedImage == null) { |
| return; |
| } |
| findImageInfo(selectedImage); |
| } |
| |
| private void createSectionSeparator(final Composite container, |
| final boolean separator) { |
| final int SECTION_INDENT = 10; |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .span(COLUMNS, 1).grab(true, false) |
| .indent(SWT.DEFAULT, SECTION_INDENT) |
| .applyTo(new Label(container, separator |
| ? (SWT.SEPARATOR | SWT.HORIZONTAL) : SWT.NONE)); |
| } |
| |
| /** |
| * Creates the {@link Composite} container that will display widgets to |
| * select an {@link IDockerImage}, name it and specify the command to run. |
| * |
| * @param container |
| * the parent {@link Composite} |
| */ |
| private void createImageSettingsSection(final Composite container) { |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).span(3, 1) |
| .applyTo(new Label(container, SWT.NONE)); |
| final Label connectionSelectionLabel = new Label(container, SWT.NONE); |
| connectionSelectionLabel |
| .setText(WizardMessages.getString("Connection.label")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).applyTo(connectionSelectionLabel); |
| final Combo connectionSelectionCombo = new Combo(container, SWT.BORDER); |
| connectionSelectionCombo.setToolTipText( |
| LaunchMessages.getString("RunMainTabSelectConnection.tooltip")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(true, false).span(1, 1).applyTo(connectionSelectionCombo); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).span(1, 1) |
| .applyTo(new Label(container, SWT.NONE)); |
| new ControlDecoration(connectionSelectionCombo, SWT.TOP | SWT.LEFT); |
| final ComboViewer connectionSelectionComboViewer = new ComboViewer( |
| connectionSelectionCombo); |
| connectionSelectionComboViewer |
| .setContentProvider(new ArrayContentProvider()); |
| connectionSelectionComboViewer.setInput(DockerConnectionManager |
| .getInstance().getConnectionNames().toArray()); |
| dbc.bindValue( |
| WidgetProperties.selection().observe(connectionSelectionCombo), |
| BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.SELECTED_CONNECTION_NAME) |
| .observe(model)); |
| // Image selection name |
| final Label imageSelectionLabel = new Label(container, SWT.NONE); |
| imageSelectionLabel.setText(WizardMessages.getString("Image.label")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).applyTo(imageSelectionLabel); |
| final Combo imageSelectionCombo = new Combo(container, SWT.BORDER); |
| final ComboViewer imageSelectionComboViewer = new ComboViewer( |
| imageSelectionCombo); |
| imageSelectionCombo.setToolTipText(WizardMessages |
| .getString("ImageRunSelectionPage.selectTooltip")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(true, false).span(1, 1).applyTo(imageSelectionCombo); |
| new ControlDecoration(imageSelectionCombo, SWT.TOP | SWT.LEFT); |
| new ContentProposalAdapter(imageSelectionCombo, |
| new ComboContentAdapter() { |
| @Override |
| public void insertControlContents(Control control, |
| String text, int cursorPosition) { |
| final Combo combo = (Combo) control; |
| final Point selection = combo.getSelection(); |
| combo.setText(text); |
| selection.x = text.length(); |
| selection.y = selection.x; |
| combo.setSelection(selection); |
| } |
| }, getImageNameContentProposalProvider(imageSelectionCombo), |
| null, null); |
| // image search |
| final Button searchImageButton = new Button(container, SWT.NONE); |
| searchImageButton.setText( |
| WizardMessages.getString("ImageRunSelectionPage.search")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).span(1, 1) |
| .hint(LaunchConfigurationUtils |
| .getButtonWidthHint(searchImageButton), SWT.DEFAULT) |
| .applyTo(searchImageButton); |
| searchImageButton.addSelectionListener(onSearchImage()); |
| imageSelectionComboViewer |
| .setContentProvider(new ObservableListContentProvider()); |
| dbc.bindList(WidgetProperties.items().observe(imageSelectionCombo), |
| BeanProperties |
| .list(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.IMAGE_NAMES) |
| .observe(model)); |
| dbc.bindValue(WidgetProperties.selection().observe(imageSelectionCombo), |
| BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.SELECTED_IMAGE_NAME) |
| .observe(model)); |
| // Container name (optional) |
| final Label containerNameLabel = new Label(container, SWT.NONE); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).applyTo(imageSelectionLabel); |
| containerNameLabel.setText("Name:"); //$NON-NLS-1$ |
| final Text containerNameText = new Text(container, SWT.BORDER); |
| containerNameText.setToolTipText(WizardMessages |
| .getString("ImageRunSelectionPage.containerTooltip")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(true, false).span(1, 1).applyTo(containerNameText); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).span(1, 1) |
| .applyTo(new Label(container, SWT.NONE)); |
| dbc.bindValue( |
| WidgetProperties.text(SWT.Modify).observe(containerNameText), |
| BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.CONTAINER_NAME) |
| .observe(model)); |
| // EntryPoint (optional) |
| final Label entrypointLabel = new Label(container, SWT.NONE); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).applyTo(imageSelectionLabel); |
| entrypointLabel.setText( |
| WizardMessages.getString("ImageRunSelectionPage.entrypoint")); //$NON-NLS-1$ |
| // TODO: include SWT.SEARCH | SWT.ICON_SEARCH to support value reset |
| final Text entrypointText = new Text(container, SWT.BORDER); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(true, false).span(1, 1).applyTo(entrypointText); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).span(1, 1) |
| .applyTo(new Label(container, SWT.NONE)); |
| dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(entrypointText), |
| BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.ENTRYPOINT) |
| .observe(model)); |
| |
| // Command (optional) |
| final Label commandLabel = new Label(container, SWT.NONE); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).applyTo(imageSelectionLabel); |
| commandLabel.setText( |
| WizardMessages.getString("ImageRunSelectionPage.command")); //$NON-NLS-1$ |
| final Text commandText = new Text(container, SWT.BORDER); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(true, false).span(1, 1).applyTo(commandText); |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .grab(false, false).span(1, 1) |
| .applyTo(new Label(container, SWT.NONE)); |
| dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(commandText), |
| BeanProperties.value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.COMMAND).observe(model)); |
| } |
| |
| /** |
| * Creates an {@link IContentProposalProvider} to propose |
| * {@link IDockerImage} names based on the current text. |
| * |
| * @param items |
| * @return |
| */ |
| private IContentProposalProvider getImageNameContentProposalProvider( |
| final Combo imageSelectionCombo) { |
| return (contents, position) -> { |
| final List<IContentProposal> proposals = new ArrayList<>(); |
| for (String imageName : imageSelectionCombo.getItems()) { |
| if (imageName.contains(contents)) { |
| proposals.add(new ContentProposal(imageName, imageName, |
| imageName, position)); |
| } |
| } |
| return proposals.toArray(new IContentProposal[0]); |
| }; |
| } |
| |
| private IValueChangeListener onImageSelectionChange() { |
| return event -> { |
| final IDockerImage selectedImage = model.getSelectedImage(); |
| // skip if the selected image does not exist in the local Docker |
| // host |
| if (selectedImage == null) { |
| model.setExposedPorts(new ArrayList<ExposedPortModel>()); |
| return; |
| } |
| findImageInfo(selectedImage); |
| volumesModel.setSelectedImage(selectedImage); |
| }; |
| } |
| |
| private IValueChangeListener onConnectionSelectionChange() { |
| return event -> { |
| IDockerImage selectedImage = model.getSelectedImage(); |
| // skip if the selected image does not exist in the local Docker |
| // host |
| if (selectedImage == null) { |
| List<String> imageNames = model.getImageNames(); |
| if (imageNames.size() > 0) { |
| model.setSelectedImageName(imageNames.get(0)); |
| selectedImage = model.getSelectedImage(); |
| } else { |
| model.setExposedPorts(new ArrayList<ExposedPortModel>()); |
| return; |
| } |
| } |
| findImageInfo(selectedImage); |
| volumesModel.setSelectedImage(selectedImage); |
| }; |
| } |
| |
| private static final class FindImageInfoRunnable |
| implements IRunnableWithResult<IDockerImageInfo> { |
| private final IDockerImage selectedImage; |
| private IDockerImageInfo selectedImageInfo; |
| |
| private FindImageInfoRunnable(IDockerImage selectedImage) { |
| this.selectedImage = selectedImage; |
| } |
| |
| @Override |
| public void run(final IProgressMonitor monitor) { |
| selectedImageInfo = selectedImage.getConnection() |
| .getImageInfo(selectedImage.id()); |
| } |
| |
| @Override |
| public IDockerImageInfo getResult() { |
| return selectedImageInfo; |
| } |
| } |
| |
| private void findImageInfo(final IDockerImage selectedImage) { |
| try { |
| final FindImageInfoRunnable findImageInfoRunnable = new FindImageInfoRunnable( |
| selectedImage); |
| ProgressMonitorDialog dialog = new ProgressMonitorDialog( |
| this.getShell()); |
| dialog.run(true, true, findImageInfoRunnable); |
| final IDockerImageInfo selectedImageInfo = findImageInfoRunnable |
| .getResult(); |
| final Set<String> exposedPortInfos = selectedImageInfo.config() |
| .exposedPorts(); |
| final List<ExposedPortModel> availablePorts = new ArrayList<>(); |
| if (exposedPortInfos != null) { |
| for (String exposedPortInfo : exposedPortInfos) { |
| final String privatePort = exposedPortInfo.substring(0, |
| exposedPortInfo.indexOf('/')); |
| final String type = exposedPortInfo |
| .substring(exposedPortInfo.indexOf('/')); // $NON-NLS-1$ |
| final ExposedPortModel exposedPort = new ExposedPortModel( |
| privatePort, type, "", privatePort); |
| availablePorts.add(exposedPort); // $NON-NLS-1$ |
| } |
| } |
| model.setExposedPorts(availablePorts); |
| model.setEntrypoint(selectedImageInfo.config().entrypoint()); |
| model.setCommand(selectedImageInfo.config().cmd()); |
| |
| } catch (InvocationTargetException | InterruptedException e) { |
| Activator.log(e); |
| } |
| } |
| |
| private void createRunOptionsSection(final Composite container) { |
| // interactive/show in console mode |
| final Button interactiveButton = new Button(container, SWT.CHECK); |
| interactiveButton.setText( |
| WizardMessages.getString("ImageRunSelectionPage.openStdin")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .span(COLUMNS, 1).grab(true, false).applyTo(interactiveButton); |
| dbc.bindValue(WidgetProperties.selection().observe(interactiveButton), |
| BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.INTERACTIVE_MODE) |
| .observe(model)); |
| // allocate pseudo-TTY |
| final Button allocatePseudoTTY = new Button(container, SWT.CHECK); |
| allocatePseudoTTY |
| .setText(WizardMessages.getString("ImageRunSelectionPage.tty")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .span(COLUMNS, 1).grab(true, false).applyTo(allocatePseudoTTY); |
| dbc.bindValue(WidgetProperties.selection().observe(allocatePseudoTTY), |
| BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.ALLOCATE_PSEUDO_TTY) |
| .observe(model)); |
| |
| // remove when exits |
| final Button removeWhenExitsButton = new Button(container, SWT.CHECK); |
| removeWhenExitsButton.setText( |
| WizardMessages.getString("ImageRunSelectionPage.autoRemove")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .span(COLUMNS, 1).grab(true, false) |
| .applyTo(removeWhenExitsButton); |
| dbc.bindValue( |
| WidgetProperties.selection().observe(removeWhenExitsButton), |
| BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.REMOVE_WHEN_EXITS) |
| .observe(model)); |
| |
| // privileged |
| final Button privilegedButton = new Button(container, SWT.CHECK); |
| privilegedButton.setText( |
| WizardMessages.getString("ImageRunSelectionPage.privileged")); //$NON-NLS-1$ |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) |
| .span(COLUMNS, 1).grab(true, false).applyTo(privilegedButton); |
| dbc.bindValue(WidgetProperties.selection().observe(privilegedButton), |
| BeanProperties |
| .value(ImageRunSelectionModel.class, |
| ImageRunSelectionModel.PRIVILEGED) |
| .observe(model)); |
| } |
| |
| private SelectionListener onSearchImage() { |
| return new SelectionAdapter() { |
| |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| final ImageSearch imageSearchWizard = new ImageSearch( |
| RunImageMainTab.this.model.getSelectedConnection(), |
| RunImageMainTab.this.model.getSelectedImageName(), |
| new RegistryInfo(AbstractRegistry.DOCKERHUB_REGISTRY, |
| true)); |
| final boolean completed = CommandUtils |
| .openWizard(imageSearchWizard, getShell()); |
| if (completed) { |
| model.setSelectedImageName( |
| imageSearchWizard.getSelectedImage()); |
| } |
| } |
| }; |
| } |
| |
| @Override |
| public Image getImage() { |
| return SWTImagesFactory.get(SWTImagesFactory.IMG_MAIN_TAB); |
| } |
| |
| @Override |
| public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { |
| |
| } |
| |
| @Override |
| public void initializeFrom(ILaunchConfiguration configuration) { |
| // Don't attempt to continue if model is null since it means there are |
| // no connections |
| if (model == null) |
| return; |
| try { |
| final String defaultConnectionName = DockerConnectionManager |
| .getInstance().getAllConnections().stream() |
| .filter(connection -> connection.isOpen()) |
| .map(connection -> connection.getName()).findFirst() |
| .orElse(""); //$NON-NLS-1$ |
| |
| // Mark in error if there is no active connection |
| if (defaultConnectionName.equals("")) { //$NON-NLS-1$ |
| setErrorMessage(WizardMessages |
| .getString("ErrorNoActiveConnection.msg")); //$NON-NLS-1$ |
| } |
| String connectionName = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.CONNECTION_NAME, |
| defaultConnectionName); |
| model.setSelectedConnectionName(connectionName); |
| String imageName = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.IMAGE_NAME, ""); //$NON-NLS-1$ |
| model.setSelectedImageName(imageName); |
| String entryPoint = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.ENTRYPOINT, ""); //$NON-NLS-1$ |
| model.setEntrypoint(entryPoint); |
| String command = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.COMMAND, ""); //$NON-NLS-1$ |
| model.setCommand(command); |
| String containerName = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.CONTAINER_NAME, |
| ""); //$NON-NLS-1$ |
| model.setContainerName(containerName); |
| boolean removeContainer = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.AUTO_REMOVE, |
| false); |
| model.setRemoveWhenExits(removeContainer); |
| boolean interactive = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.INTERACTIVE, |
| false); |
| model.setInteractiveMode(interactive); |
| boolean useTTY = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.ALLOCATE_PSEUDO_CONSOLE, |
| false); |
| model.setAllocatePseudoTTY(useTTY); |
| boolean privileged = configuration.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.PRIVILEGED, |
| false); |
| model.setPrivileged(privileged); |
| } catch (CoreException e) { |
| Activator.logErrorMessage( |
| LaunchMessages.getString( |
| "RunDockerImageLaunchConfiguration.load.failure"), //$NON-NLS-1$ |
| e); |
| } |
| // update the underlying launch config working copy on model |
| // changes. |
| model.addPropertyChangeListener( |
| new LaunchConfigurationChangeListener()); |
| |
| } |
| |
| @Override |
| public void performApply(ILaunchConfigurationWorkingCopy configuration) { |
| if (model == null) |
| return; |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.CONNECTION_NAME, |
| model.getSelectedConnectionName()); |
| if (model.getSelectedImage() != null) { |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.IMAGE_ID, |
| model.getSelectedImage().id()); |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.IMAGE_NAME, |
| model.getSelectedImageName()); |
| } |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.COMMAND, |
| model.getCommand()); |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.ENTRYPOINT, |
| "".equals(model.getEntrypoint()) ? null //$NON-NLS-1$ |
| : model.getEntrypoint()); |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.CONTAINER_NAME, |
| "".equals(model.getContainerName()) ? null //$NON-NLS-1$ |
| : model.getContainerName()); |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.ALLOCATE_PSEUDO_CONSOLE, |
| model.isAllocatePseudoTTY()); |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.AUTO_REMOVE, |
| model.isRemoveWhenExits()); |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.INTERACTIVE, |
| model.isInteractiveMode()); |
| configuration.setAttribute( |
| IRunDockerImageLaunchConfigurationConstants.PRIVILEGED, |
| model.isPrivileged()); |
| } |
| |
| @Override |
| public boolean isValid(ILaunchConfiguration launchConfig) { |
| try { |
| if (model == null) |
| return false; |
| String connectionName = launchConfig.getAttribute( |
| IRunDockerImageLaunchConfigurationConstants.CONNECTION_NAME, |
| ""); |
| if (connectionName.isEmpty()) { |
| return false; |
| } else { |
| // Verify Connection is active |
| IDockerConnection connection = DockerConnectionManager |
| .getInstance().findConnection(connectionName); |
| if (connection == null || !connection.isOpen()) { |
| setErrorMessage(WizardMessages |
| .getFormattedString("ErrorInactiveConnection.msg", //$NON-NLS-1$ |
| connectionName)); |
| return false; |
| } |
| } |
| final IStatus imageSelectionValidationStatus = new ImageSelectionValidator() |
| .validate(model.getSelectedImageName()); |
| if (!imageSelectionValidationStatus.isOK()) { |
| setErrorMessage(imageSelectionValidationStatus.getMessage()); |
| return false; |
| } |
| final IStatus imageNameValidationStatus = new ImageNameValidator() |
| .validate(model.getSelectedImageName()); |
| if (!imageNameValidationStatus.isOK()) { |
| setErrorMessage(imageNameValidationStatus.getMessage()); |
| return false; |
| } |
| final IStatus containerNameValidationStatus = new ContainerNameValidator() |
| .validate(model.getContainerName()); |
| if (!containerNameValidationStatus.isOK()) { |
| setErrorMessage(containerNameValidationStatus.getMessage()); |
| return false; |
| } |
| |
| } catch (CoreException e) { |
| Activator.log(e); |
| } |
| setErrorMessage(null); |
| return true; |
| } |
| |
| private class LaunchConfigurationChangeListener |
| implements PropertyChangeListener { |
| |
| @Override |
| public void propertyChange(final PropertyChangeEvent evt) { |
| updateLaunchConfigurationDialog(); |
| } |
| } |
| |
| private class ImageSelectionValidator implements IValidator { |
| |
| @Override |
| public IStatus validate(final Object value) { |
| final String selectedImageName = (String) value; |
| if (selectedImageName.isEmpty()) { |
| model.setSelectedImageNeedsPulling(false); |
| return ValidationStatus.error(WizardMessages |
| .getString("ImageRunSelectionPage.specifyImageMsg")); //$NON-NLS-1$ |
| } |
| if (model.getSelectedImage() != null) { |
| model.setSelectedImageNeedsPulling(false); |
| return ValidationStatus.ok(); |
| } |
| model.setSelectedImageNeedsPulling(true); |
| return ValidationStatus.warning(WizardMessages.getFormattedString( |
| "ImageRunSelectionPage.imageNotFoundMessage", //$NON-NLS-1$ |
| selectedImageName)); |
| } |
| |
| } |
| |
| private class ContainerNameValidator implements IValidator { |
| |
| @Override |
| public IStatus validate(Object value) { |
| final String containerName = (String) value; |
| |
| for (IDockerContainer container : model.getSelectedConnection() |
| .getContainers()) { |
| if (container.name().equals(containerName)) { |
| return ValidationStatus.error(WizardMessages.getString( |
| "ImageRunSelectionPage.containerWithSameName")); //$NON-NLS-1$ |
| } |
| } |
| return ValidationStatus.ok(); |
| } |
| |
| } |
| |
| } |