diff options
22 files changed, 489 insertions, 65 deletions
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java index 4454a2a3ba..001243cd22 100644 --- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java @@ -1054,6 +1054,7 @@ public class DockerConnection implements IDockerConnection, Closeable { try { DockerProgressHandler d = new DockerProgressHandler(handler); client.pull(id, d); + listImages(); } catch (com.spotify.docker.client.DockerRequestException e) { throw new DockerException(e.message()); } catch (com.spotify.docker.client.DockerException e) { diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/.classpath b/containers/org.eclipse.linuxtools.docker.ui.tests/.classpath new file mode 100644 index 0000000000..3bc247511f --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/.project b/containers/org.eclipse.linuxtools.docker.ui.tests/.project new file mode 100644 index 0000000000..dec8106d9d --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.linuxtools.docker.ui.tests</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + <nature>org.eclipse.pde.PluginNature</nature> + </natures> +</projectDescription> diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/.settings/org.eclipse.jdt.core.prefs b/containers/org.eclipse.linuxtools.docker.ui.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..7341ab1683 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/META-INF/MANIFEST.MF b/containers/org.eclipse.linuxtools.docker.ui.tests/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..0fd1a3a4a9 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Tests +Bundle-SymbolicName: org.eclipse.linuxtools.docker.ui.tests +Bundle-Version: 1.1.0.qualifier +Export-Package: org.eclipse.linuxtools.internal.docker.ui.wizards +Require-Bundle: org.junit;bundle-version="4.12.0", + org.eclipse.linuxtools.docker.ui;bundle-version="1.0.0", + org.eclipse.core.runtime, + org.hamcrest.library;bundle-version="1.3.0" diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/build.properties b/containers/org.eclipse.linuxtools.docker.ui.tests/build.properties new file mode 100644 index 0000000000..b107977f4e --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/build.properties @@ -0,0 +1,3 @@ +source.. = src/ +bin.includes = META-INF/,\ + . diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/pom.xml b/containers/org.eclipse.linuxtools.docker.ui.tests/pom.xml new file mode 100644 index 0000000000..5ae7ea2846 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/pom.xml @@ -0,0 +1,12 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.eclipse.linuxtools</groupId> + <artifactId>org.eclipse.linuxtools.docker</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + <artifactId>org.eclipse.linuxtools.docker.ui.tests</artifactId> + <packaging>eclipse-test-plugin</packaging> + +</project>
\ No newline at end of file diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPatternTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPatternTest.java new file mode 100644 index 0000000000..b831072903 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPatternTest.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * 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.wizards; + +import org.eclipse.core.runtime.IStatus; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class ImagePullPatternTest { + + private static Object[] match(final String imageName, final int expectedSeverity) { + return new Object[]{imageName, expectedSeverity}; + } + + + @Parameters(name="{0} -> {1}") + public static Object[][] data() { + return new Object[][] { + match("", IStatus.CANCEL), + match("£", IStatus.WARNING), + match("wildfly", IStatus.WARNING), + match("jboss/", IStatus.WARNING), + match("jboss/wildfly", IStatus.WARNING), + match("jboss/wildfly:", IStatus.WARNING), + match("jboss/wildfly:latest", IStatus.OK), + match("localhost/wildfly/", IStatus.WARNING), + match("localhost/wildfly/jboss", IStatus.WARNING), + match("localhost/wildfly/jboss:", IStatus.WARNING), + match("localhost/wildfly/jboss:latest", IStatus.OK), + match("localhost/wildfly/jboss:9", IStatus.OK), + match("localhost/wildfly/jboss:9.", IStatus.WARNING), + match("localhost/wildfly/jboss:9.0.1.", IStatus.WARNING), + match("localhost/wildfly/jboss:9.0.1.Final", IStatus.OK), + match("localhost:", IStatus.WARNING), + match("localhost:5000", IStatus.OK), // bc it matches the REPO:TAG pattern. + match("localhost:5000/", IStatus.WARNING), + match("localhost:5000/wildfly", IStatus.WARNING), + match("localhost:5000/wildfly/", IStatus.WARNING), + match("localhost:5000/wildfly/jboss", IStatus.WARNING), + match("localhost:5000/wildfly/jboss:", IStatus.WARNING), + match("localhost:5000/wildfly/jboss:latest", IStatus.OK), + }; + } + + @Parameter(value=0) + public String imageName; + @Parameter(value=1) + public int expectedSeverity; + + + @Test + public void verifyData() throws Exception { + final IStatus status = new ImagePullPage.ImageNameValidator().validate(imageName); + // then + Assert.assertEquals(expectedSeverity, status.getSeverity()); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/package-info.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/package-info.java new file mode 100644 index 0000000000..6ccd8f603d --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/package-info.java @@ -0,0 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * 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.wizards;
\ No newline at end of file diff --git a/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF b/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF index 71ca14c624..8ecbe1a709 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF +++ b/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF @@ -28,4 +28,5 @@ Bundle-ActivationPolicy: lazy Bundle-Localization: plugin Export-Package: org.eclipse.linuxtools.docker.ui, org.eclipse.linuxtools.docker.ui.launch, - org.eclipse.linuxtools.internal.docker.ui.preferences + org.eclipse.linuxtools.internal.docker.ui.preferences, + org.eclipse.linuxtools.internal.docker.ui.wizards;x-friends:="org.eclipse.linuxtools.docker.ui.tests" diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/wizards/ImageSearch.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/wizards/ImageSearch.java index 6e183d0e77..0b4548f82c 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/wizards/ImageSearch.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/wizards/ImageSearch.java @@ -14,8 +14,6 @@ package org.eclipse.linuxtools.docker.ui.wizards; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.linuxtools.docker.core.IDockerConnection; -import org.eclipse.linuxtools.docker.core.IDockerImageSearchResult; -import org.eclipse.linuxtools.internal.docker.ui.wizards.DockerImageTagSearchResult; import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageSearchModel; import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageSearchPage; import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageTagSelectionPage; @@ -41,11 +39,16 @@ public class ImageSearch extends Wizard { /* * Default Constructor + * + * @param connection + * the current connection to a target Docker daemon + * @param name + * the current image name or <code>null</code> if not applicable */ - public ImageSearch(final IDockerConnection connection) { + public ImageSearch(final IDockerConnection connection, final String name) { setWindowTitle(WizardMessages.getString("ImageSearch.title")); //$NON-NLS-1$ setNeedsProgressMonitor(true); - this.imageSearchModel = new ImageSearchModel(connection); + this.imageSearchModel = new ImageSearchModel(connection, name); this.imageSearchPage = new ImageSearchPage(this.imageSearchModel); this.imageTagSelectionPage = new ImageTagSelectionPage( this.imageSearchModel); @@ -67,11 +70,9 @@ public class ImageSearch extends Wizard { return true; } - public IDockerImageSearchResult getSelectedImage() { - return this.imageSearchPage.getSelectedImage(); + public String getSelectedImage() { + return this.imageSearchPage.getSelectedImage().getName() + ":" + + this.imageTagSelectionPage.getSelectedImageTag().getName(); } - public DockerImageTagSearchResult getSelectedImageTag() { - return this.imageTagSelectionPage.getSelectedImageTag(); - } } diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/PullImageCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/PullImageCommandHandler.java index 8d477ddd28..f0111dd2c9 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/PullImageCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/PullImageCommandHandler.java @@ -23,6 +23,7 @@ import org.eclipse.linuxtools.docker.ui.wizards.ImageSearch; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages; import org.eclipse.linuxtools.internal.docker.ui.views.ImagePullProgressHandler; +import org.eclipse.linuxtools.internal.docker.ui.wizards.ImagePull; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.handlers.HandlerUtil; @@ -43,20 +44,19 @@ public class PullImageCommandHandler extends AbstractHandler { final IWorkbenchPart activePart = HandlerUtil.getActivePart(event); final IDockerConnection connection = CommandUtils .getCurrentConnection(activePart); - final ImageSearch wizard = new ImageSearch(connection); + final ImagePull wizard = new ImagePull(connection); final boolean pullImage = CommandUtils.openWizard(wizard, HandlerUtil.getActiveShell(event)); if (pullImage) { - performPullImage(connection, wizard.getSelectedImage().getName(), - wizard.getSelectedImageTag().getName()); + performPullImage(connection, wizard.getImageName()); } return null; } private void performPullImage(final IDockerConnection connection, - final String imageName, final String tagName) { + final String imageName) { final Job pullImageJob = new Job(DVMessages - .getFormattedString(PULL_IMAGE_JOB_TITLE, imageName, tagName)) { + .getFormattedString(PULL_IMAGE_JOB_TITLE, imageName)) { @Override protected IStatus run(final IProgressMonitor monitor) { @@ -65,8 +65,7 @@ public class PullImageCommandHandler extends AbstractHandler { // pull the image and let the progress // handler refresh the images when done try { - ((DockerConnection) connection).pullImage( - imageName + ":" + tagName, + ((DockerConnection) connection).pullImage(imageName, new ImagePullProgressHandler(connection, imageName)); } catch (final DockerException e) { diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveConnectionCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveConnectionCommandHandler.java index 16888bde39..ca0fa146b4 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveConnectionCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveConnectionCommandHandler.java @@ -39,7 +39,6 @@ public class RemoveConnectionCommandHandler extends AbstractHandler { } viewer.refresh(); } - // return must be null, javadoc says. return null; } diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DVMessages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DVMessages.properties index c2afef50c5..335f00837c 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DVMessages.properties +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DVMessages.properties @@ -173,7 +173,7 @@ ContainerCommitError.msg=Error committing container ImageBuild.msg=Building Image ImagePull.msg=Pulling Image -ImagePull.title=Pulling {0}:{1} +ImagePull.title=Pulling {0} ImagePush.msg=Pushing Image ImagePush.title=Pushing Image <{0}> diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePull.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePull.java new file mode 100644 index 0000000000..382e7e28a1 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePull.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * 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.wizards; + +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.linuxtools.docker.core.DockerException; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.docker.core.IDockerImage; + +/** + * + */ +public class ImagePull extends Wizard { + + private final ImagePullPage imagePullPage; + + /** + * Constructor when an {@link IDockerConnection} has been selected to run an + * {@link IDockerImage}. + * + * @param connection + * the {@link IDockerConnection} pointing to a specific Docker + * daemon/host. + * @throws DockerException + */ + public ImagePull(final IDockerConnection connection) { + super(); + setWindowTitle(WizardMessages.getString("ImagePull.title")); //$NON-NLS-1$ + this.imagePullPage = new ImagePullPage(connection); + } + + @Override + public void addPages() { + addPage(imagePullPage); + } + + @Override + public boolean canFinish() { + return this.imagePullPage.isPageComplete(); + } + + @Override + public boolean performFinish() { + return true; + } + + public String getImageName() { + return this.imagePullPage.getImageName(); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPage.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPage.java new file mode 100644 index 0000000000..cc88749b5b --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPage.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * 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.wizards; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.validation.IValidator; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.databinding.wizard.WizardPageSupport; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.docker.ui.wizards.ImageSearch; +import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory; +import org.eclipse.linuxtools.internal.docker.ui.commands.CommandUtils; +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.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * + */ +public class ImagePullPage extends WizardPage { + + private final ImagePullPageModel model; + private final DataBindingContext dbc; + private final IDockerConnection connection; + + private static final String REGISTRY_HOST = "[a-zA-Z0-9]+([._-][a-zA-Z0-9]+)*"; //$NON-NLS-1$ + private static final String REGISTRY_PORT = "[0-9]+"; //$NON-NLS-1$ + private static final String REPOSITORY = "[a-z0-9]+([._-][a-z0-9]+)*"; //$NON-NLS-1$ + private static final String NAME = "[a-z0-9]+([._-][a-z0-9]+)*"; //$NON-NLS-1$ + private static final String TAG = "[a-zA-Z0-9]+([._-][a-zA-Z0-9]+)*"; //$NON-NLS-1$ + private static final Pattern imageNamePattern = Pattern.compile("(" //$NON-NLS-1$ + + REGISTRY_HOST + "(\\:" + REGISTRY_PORT + ")?/)?" + "(" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + REPOSITORY + "/)?" + NAME + "(?<tag>\\:" + TAG + ")?"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + public ImagePullPage(final IDockerConnection connection) { + super("ImagePullPage", //$NON-NLS-1$ + WizardMessages.getString("ImagePull.label"), //$NON-NLS-1$ + SWTImagesFactory.DESC_BANNER_REPOSITORY); + setMessage(WizardMessages.getString("ImagePull.desc")); //$NON-NLS-1$ + this.model = new ImagePullPageModel(); + this.dbc = new DataBindingContext(); + this.connection = connection; + } + + @Override + public void dispose() { + dbc.dispose(); + super.dispose(); + } + + public String getImageName() { + final Matcher matcher = imageNamePattern + .matcher(this.model.getImageName()); + // Matcher#matches() must be called before any attempt to access a given + // named capturing-group. + if (matcher.matches() && matcher.group("tag") == null) { //$NON-NLS-1$ + return this.model.getImageName() + ":latest"; //$NON-NLS-1$ + } + + return this.model.getImageName(); + } + + @Override + public void createControl(Composite parent) { + parent.setLayout(new GridLayout()); + final Composite container = new Composite(parent, SWT.NONE); + GridLayoutFactory.fillDefaults().numColumns(3).margins(6, 6) + .applyTo(container); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(1, 1) + .grab(true, false).applyTo(container); + + // Image name + final Label imageNameLabel = new Label(container, SWT.NONE); + imageNameLabel + .setText(WizardMessages.getString("ImagePull.name.label")); //$NON-NLS-1$ + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(false, false).applyTo(imageNameLabel); + + final Text imageNameText = new Text(container, SWT.BORDER); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(true, false).applyTo(imageNameText); + imageNameText.setToolTipText( + WizardMessages.getString("ImagePull.name.tooltip")); //$NON-NLS-1$ + // binding + final IObservableValue imgeNameObservable = BeanProperties + .value(ImagePullPageModel.class, ImagePullPageModel.IMAGE_NAME) + .observe(model); + dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(imageNameText), + imgeNameObservable, new UpdateValueStrategy() + .setAfterConvertValidator(new ImageNameValidator()), + null); + // search + final Button searchButton = new Button(container, SWT.NONE); + searchButton + .setText(WizardMessages.getString("ImagePull.search.label")); //$NON-NLS-1$ + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(false, false).applyTo(searchButton); + searchButton.addSelectionListener(onSearchImage()); + + // setup validation support + WizardPageSupport.create(this, dbc); + setControl(container); + } + + /** + * Opens the {@link ImageSearch} dialog with current image name pre-filled. + * + * @return + */ + private SelectionListener onSearchImage() { + return new SelectionAdapter() { + + @Override + public void widgetSelected(final SelectionEvent e) { + final ImageSearch imageSearchWizard = new ImageSearch( + ImagePullPage.this.connection, + ImagePullPage.this.model.getImageName()); + final boolean completed = CommandUtils + .openWizard(imageSearchWizard, getShell()); + if (completed) { + model.setImageName(imageSearchWizard.getSelectedImage()); + } + } + }; + } + + /** + * Validates that the image name matches + * [REGISTRY_HOST[:REGISTRY_PORT]/]IMAGE_NAME[:TAG] + */ + public static class ImageNameValidator implements IValidator { + + @Override + public IStatus validate(final Object value) { + final String imageName = (String) value; + if (imageName.isEmpty()) { + return ValidationStatus + .cancel(WizardMessages.getString("ImagePull.desc")); //$NON-NLS-1$ + } + final Matcher matcher = imageNamePattern.matcher(imageName); + if (!matcher.matches()) { + return ValidationStatus.warning(WizardMessages + .getString("ImagePull.name.invalidformat.msg")); //$NON-NLS-1$ + } else if (matcher.group("tag") == null) { //$NON-NLS-1$ + return ValidationStatus.warning( + WizardMessages.getString("ImagePull.assumeLatest.msg")); //$NON-NLS-1$ + + } + return Status.OK_STATUS; + } + + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPageModel.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPageModel.java new file mode 100644 index 0000000000..62534a9ac4 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullPageModel.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat. + * 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.wizards; + +import org.eclipse.linuxtools.internal.docker.ui.databinding.BaseDatabindingModel; + +/** + * + */ +public class ImagePullPageModel extends BaseDatabindingModel { + + public static final String IMAGE_NAME = "imageName"; + + private String imageName; + + public String getImageName() { + return imageName; + } + + public void setImageName(final String imageName) { + firePropertyChange(IMAGE_NAME, this.imageName, this.imageName = imageName); + } +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageRunSelectionPage.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageRunSelectionPage.java index 147f521a14..41e54f8aae 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageRunSelectionPage.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageRunSelectionPage.java @@ -57,7 +57,6 @@ import org.eclipse.linuxtools.docker.core.DockerException; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerImage; import org.eclipse.linuxtools.docker.core.IDockerImageInfo; -import org.eclipse.linuxtools.docker.core.IDockerImageSearchResult; import org.eclipse.linuxtools.docker.ui.Activator; import org.eclipse.linuxtools.docker.ui.wizards.ImageSearch; import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory; @@ -691,17 +690,14 @@ public class ImageRunSelectionPage extends WizardPage { public void widgetSelected(SelectionEvent e) { final ImageSearch imageSearchWizard = new ImageSearch( ImageRunSelectionPage.this.model - .getSelectedConnection()); + .getSelectedConnection(), + ImageRunSelectionPage.this.model + .getSelectedImageName()); final boolean completed = CommandUtils .openWizard(imageSearchWizard, getShell()); if (completed) { - final IDockerImageSearchResult selectedImage = imageSearchWizard - .getSelectedImage(); - final DockerImageTagSearchResult selectedImageTag = imageSearchWizard - .getSelectedImageTag(); - model.setSelectedImageName(selectedImage.getName() - + ":" //$NON-NLS-1$ - + selectedImageTag.getName()); + model.setSelectedImageName( + imageSearchWizard.getSelectedImage()); } } }; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchModel.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchModel.java index c173859459..6cd80f6849 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchModel.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchModel.java @@ -47,8 +47,18 @@ public class ImageSearchModel extends BaseDatabindingModel { private DockerImageTagSearchResult selectedImageTag; - public ImageSearchModel(final IDockerConnection selectedConnection) { + public ImageSearchModel(final IDockerConnection selectedConnection, + String term) { this.selectedConnection = selectedConnection; + // the search term should not contain a tag (eg: 'centos' but not + // 'centos:latest') + if (term == null) { + this.term = null; + } else if (term.indexOf(":") != -1) { //$NON-NLS-1$ + this.term = term.substring(0, term.lastIndexOf(":")); //$NON-NLS-1$ + } else { + this.term = term; + } } public IDockerConnection getSelectedConnection() { diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchPage.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchPage.java index a6baa16824..c32fb68a33 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchPage.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchPage.java @@ -26,8 +26,6 @@ import org.eclipse.core.databinding.beans.BeanProperties; import org.eclipse.core.databinding.beans.PojoProperties; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.value.IObservableValue; -import org.eclipse.core.databinding.observable.value.IValueChangeListener; -import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.databinding.validation.IValidator; import org.eclipse.core.databinding.validation.ValidationStatus; import org.eclipse.core.runtime.IProgressMonitor; @@ -127,7 +125,6 @@ public class ImageSearchPage extends WizardPage { GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) .grab(false, false).applyTo(searchImageButton); searchImageButton.addSelectionListener(onSearchImageButtonSelected()); - searchImageButton.setEnabled(!searchImageText.getText().isEmpty()); // result table final Label searchResultLabel = new Label(container, SWT.NONE); searchResultLabel.setText( @@ -179,16 +176,12 @@ public class ImageSearchPage extends WizardPage { final IObservableValue observableTermModel = BeanProperties .value(ImageSearchModel.class, ImageSearchModel.TERM) .observe(model); - final UpdateValueStrategy strategy = new UpdateValueStrategy(); - strategy.setBeforeSetValidator(new SearchTermValidator()); - final ISWTObservableValue imageSearchTextObservable = WidgetProperties .text(SWT.Modify).observe(searchImageText); - ctx.bindValue(imageSearchTextObservable, observableTermModel, strategy, + ctx.bindValue(imageSearchTextObservable, observableTermModel, + new UpdateValueStrategy().setBeforeSetValidator( + new SearchTermValidator(searchImageButton)), null); - // enable/disable the search button - imageSearchTextObservable - .addValueChangeListener(onTermValueChanged(searchImageButton)); // observe the viewer content searchResultTableViewer .setContentProvider(new ObservableListContentProvider()); @@ -233,26 +226,6 @@ public class ImageSearchPage extends WizardPage { return viewerColumn; } - private IValueChangeListener onTermValueChanged( - final Button searchImageButton) { - return new IValueChangeListener() { - - @Override - public void handleValueChange(final ValueChangeEvent event) { - final String searchTerm = (String) event.getObservableValue() - .getValue(); - final IStatus status = AggregateValidationStatus - .getStatusMaxSeverity( - ctx.getValidationStatusProviders()); - if (searchTerm.isEmpty() || !status.isOK()) { - searchImageButton.setEnabled(false); - } else { - searchImageButton.setEnabled(true); - } - } - }; - } - private TraverseListener onSearchImageTextTraverse() { return new TraverseListener() { @@ -363,18 +336,29 @@ public class ImageSearchPage extends WizardPage { static class SearchTermValidator implements IValidator { + private static final String REPOSITORY = "[a-z0-9]+([._-][a-z0-9]+)*"; + private static final String NAME = "[a-z0-9]+([._-][a-z0-9]+)*"; private static final Pattern termPattern = Pattern - .compile("[a-z0-9]+([._-][a-z0-9]+)*"); //$NON-NLS-1$ + .compile("(" + REPOSITORY + "/)?" + NAME); + + private final Button searchImageButton; + + public SearchTermValidator(final Button searchImageButton) { + this.searchImageButton = searchImageButton; + } @Override public IStatus validate(final Object value) { final String term = (String) value; if (term == null || term.isEmpty()) { + this.searchImageButton.setEnabled(false); return ValidationStatus.info(WizardMessages .getString("ImageSearchPage.description")); //$NON-NLS-1$ } else if (termPattern.matcher(term).matches()) { + this.searchImageButton.setEnabled(true); return Status.OK_STATUS; } else { + this.searchImageButton.setEnabled(false); return ValidationStatus.error(WizardMessages.getFormattedString( "ImageSearchPage.term.invalidformat", //$NON-NLS-1$ termPattern.pattern())); diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/WizardMessages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/WizardMessages.properties index 33be568246..cc82a4344c 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/WizardMessages.properties +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/WizardMessages.properties @@ -80,12 +80,14 @@ EditButton.label=Edit Dockerfile SaveButton.label=Save CancelButton.label=Cancel -ImagePull.label=Pull an image: -ImagePull.desc=Specify repository or single image to pull down to the host. ImagePull.title=Pull Image - -ImagePullName.label=Name: -ImagePullName.toolTip=Enter either a REPOSITORY to load all its images or REPOSITORY:TAG to load a single image +ImagePull.label=Pull an image or a repository from the registry +ImagePull.desc=Specify a repository or a single image to pull down to the host. +ImagePull.name.label=Name: +ImagePull.name.tooltip=Enter either a REPOSITORY to load all its images or REPOSITORY:TAG to load a single image +ImagePull.search.label=Search... +ImagePull.name.invalidformat.msg=Image name is invalid.\nExpected [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG] +ImagePull.assumeLatest.msg=Assuming image tag is 'latest' since none was specified ImagePush.label=Push an image: ImagePush.desc=Specify the name of an image to push to the host. diff --git a/containers/pom.xml b/containers/pom.xml index 5e30cb61b0..70bc153fbd 100644 --- a/containers/pom.xml +++ b/containers/pom.xml @@ -25,6 +25,7 @@ <modules> <module>org.eclipse.linuxtools.docker.core</module> <module>org.eclipse.linuxtools.docker.ui</module> + <module>org.eclipse.linuxtools.docker.ui.tests</module> <module>org.eclipse.linuxtools.docker.docs</module> <module>org.eclipse.linuxtools.docker-feature</module> </modules> |