From 0b82cf67d37d7996fcd1846f421a7090dad6eb38 Mon Sep 17 00:00:00 2001 From: Tad Cordle Date: Wed, 20 Jun 2018 16:20:18 -0400 Subject: [PATCH 1/8] Add core changes for exposed port configuration --- .../tools/jib/builder/BuildConfiguration.java | 78 +++++++++++++++++++ .../jib/builder/steps/BuildImageStep.java | 1 + .../google/cloud/tools/jib/image/Image.java | 29 ++++++- .../json/ContainerConfigurationTemplate.java | 15 ++++ .../jib/image/json/ImageToJsonTranslator.java | 3 + .../jib/image/json/JsonToImageTranslator.java | 4 + .../cloud/tools/jib/json/EmptyStruct.java | 38 +++++++++ .../jib/builder/BuildConfigurationTest.java | 46 +++++++++++ .../jib/builder/steps/BuildImageStepTest.java | 2 + .../cloud/tools/jib/image/ImageTest.java | 7 ++ .../ContainerConfigurationTemplateTest.java | 15 ++++ .../image/json/ImageToJsonTranslatorTest.java | 11 +++ .../image/json/JsonToImageTranslatorTest.java | 11 +++ .../test/resources/json/containerconfig.json | 2 +- .../json/translated_ocimanifest.json | 2 +- .../json/translated_v22manifest.json | 2 +- 16 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 jib-core/src/main/java/com/google/cloud/tools/jib/json/EmptyStruct.java diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java index 4cf6996472..0d4a37ae79 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java @@ -19,14 +19,19 @@ import com.google.cloud.tools.jib.image.ImageReference; import com.google.cloud.tools.jib.image.json.BuildableManifestTemplate; import com.google.cloud.tools.jib.image.json.V22ManifestTemplate; +import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedMap; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; import javax.annotation.Nullable; import javax.lang.model.SourceVersion; @@ -46,6 +51,7 @@ public static class Builder { private List javaArguments = new ArrayList<>(); private List jvmFlags = new ArrayList<>(); private Map environmentMap = new HashMap<>(); + private List exposedPorts = new ArrayList<>(); private Class targetFormat = V22ManifestTemplate.class; private BuildLogger buildLogger; @@ -112,6 +118,13 @@ public Builder setEnvironment(@Nullable Map environmentMap) { return this; } + public Builder setExposedPorts(@Nullable List exposedPorts) { + if (exposedPorts != null) { + this.exposedPorts = exposedPorts; + } + return this; + } + public Builder setTargetFormat(Class targetFormat) { this.targetFormat = targetFormat; return this; @@ -131,6 +144,15 @@ public BuildConfiguration build() { errorMessages.add("main class is required but not set"); } + ImmutableSortedMap exposedPortsMap = ImmutableSortedMap.of(); + try { + exposedPortsMap = portListToPortMap(exposedPorts); + } catch (NumberFormatException ex) { + errorMessages.add( + "exposed ports are configured in an invalid format (must be a single " + + "port number or a range of port number)"); + } + switch (errorMessages.size()) { case 0: // No errors if (baseImageReference == null || targetImageReference == null || mainClass == null) { @@ -154,6 +176,7 @@ public BuildConfiguration build() { ImmutableList.copyOf(javaArguments), ImmutableList.copyOf(jvmFlags), ImmutableMap.copyOf(environmentMap), + ImmutableSortedMap.copyOf(exposedPortsMap), targetFormat); case 1: @@ -193,6 +216,54 @@ public static boolean isValidJavaClass(String className) { return true; } + /** + * Converts a list of port numbers to the corresponding ExposedPorts map format. + * + *

Example: [1000, 2000-2002] -> {"1000/tcp":{}, "2000/tcp":{}, "2001/tcp":{}, "2002/tcp":{}}) + * + * @return the map + */ + @VisibleForTesting + static ImmutableSortedMap portListToPortMap(List ports) + throws NumberFormatException { + SortedMap result = new TreeMap<>(); + + for (String port : ports) { + // Remove all spaces + port = port.trim().replace(" ", ""); + + if (port.matches("\\d+")) { + // Port is a single number + int portNum = Integer.parseInt(port); + if (portNum < 1 || portNum > 65535) { + throw new NumberFormatException("Invalid port number " + port); + } + result.put(port + "/tcp", EmptyStruct.get()); + + } else if (port.matches("\\d+-\\d+")) { + // Port is a range + List range = Splitter.on('-').splitToList(port); + int min = Integer.parseInt(range.get(0)); + int max = Integer.parseInt(range.get(1)); + + // Make sure range is valid (min-max, within port range) + if (min > max || min < 1 || max > 65535) { + throw new NumberFormatException("Invalid port range " + port); + } + + for (int portNum = min; portNum <= max; portNum++) { + result.put(portNum + "/tcp", EmptyStruct.get()); + } + + } else { + // Port is neither a single number nor a range + throw new NumberFormatException("Invalid port number " + port); + } + } + + return ImmutableSortedMap.copyOf(result); + } + private final BuildLogger buildLogger; private final ImageReference baseImageReference; @Nullable private final String baseImageCredentialHelperName; @@ -204,6 +275,7 @@ public static boolean isValidJavaClass(String className) { private final ImmutableList javaArguments; private final ImmutableList jvmFlags; private final ImmutableMap environmentMap; + private final ImmutableSortedMap exposedPorts; private final Class targetFormat; public static Builder builder(BuildLogger buildLogger) { @@ -223,6 +295,7 @@ private BuildConfiguration( ImmutableList javaArguments, ImmutableList jvmFlags, ImmutableMap environmentMap, + ImmutableSortedMap exposedPorts, Class targetFormat) { this.buildLogger = buildLogger; this.baseImageReference = baseImageReference; @@ -235,6 +308,7 @@ private BuildConfiguration( this.javaArguments = javaArguments; this.jvmFlags = jvmFlags; this.environmentMap = environmentMap; + this.exposedPorts = exposedPorts; this.targetFormat = targetFormat; } @@ -310,6 +384,10 @@ public ImmutableMap getEnvironment() { return environmentMap; } + public ImmutableSortedMap getExposedPorts() { + return exposedPorts; + } + public Class getTargetFormat() { return targetFormat; } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java index e4f9db7310..ddddd6181a 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java @@ -102,6 +102,7 @@ private Image afterCachedLayersSteps() imageBuilder.setEnvironment(buildConfiguration.getEnvironment()); imageBuilder.setEntrypoint(entrypoint); imageBuilder.setJavaArguments(buildConfiguration.getJavaArguments()); + imageBuilder.setExposedPorts(buildConfiguration.getExposedPorts()); // Gets the container configuration content descriptor. return imageBuilder.build(); diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java b/jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java index 78d2e88337..cb2000f205 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java @@ -16,7 +16,9 @@ package com.google.cloud.tools.jib.image; +import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedMap; import java.util.List; import java.util.Map; @@ -31,6 +33,7 @@ public static class Builder { private ImmutableList entrypoint = ImmutableList.of(); private ImmutableList javaArguments = ImmutableList.of(); + private ImmutableSortedMap exposedPorts = ImmutableSortedMap.of(); /** * Sets the environment with a map from environment variable names to values. @@ -90,6 +93,18 @@ public Builder setJavaArguments(List javaArguments) { return this; } + /** + * Sets the items in the "ExposedPorts" field in the container configuration. + * + * @param exposedPorts the map of exposed ports to add, with the key in the format it would + * appear in the configuration json (e.g. "portNum/tcp") + * @return this + */ + public Builder setExposedPorts(Map exposedPorts) { + this.exposedPorts = ImmutableSortedMap.copyOf(exposedPorts); + return this; + } + /** * Adds a layer to the image. * @@ -107,7 +122,8 @@ public Image build() { imageLayersBuilder.build(), environmentBuilder.build(), ImmutableList.copyOf(entrypoint), - ImmutableList.copyOf(javaArguments)); + ImmutableList.copyOf(javaArguments), + ImmutableSortedMap.copyOf(exposedPorts)); } } @@ -127,15 +143,20 @@ public static Builder builder() { /** Arguments to pass into main when running the image. */ private final ImmutableList javaArguments; + /** Ports that the container listens on. */ + private final ImmutableSortedMap exposedPorts; + private Image( ImageLayers layers, ImmutableList environment, ImmutableList entrypoint, - ImmutableList javaArguments) { + ImmutableList javaArguments, + ImmutableSortedMap exposedPorts) { this.layers = layers; this.environmentBuilder = environment; this.entrypoint = entrypoint; this.javaArguments = javaArguments; + this.exposedPorts = exposedPorts; } public ImmutableList getEnvironment() { @@ -150,6 +171,10 @@ public ImmutableList getJavaArguments() { return javaArguments; } + public ImmutableSortedMap getExposedPorts() { + return exposedPorts; + } + public ImmutableList getLayers() { return layers.getLayers(); } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplate.java b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplate.java index 2dff5c0b05..36bdad95d0 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplate.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplate.java @@ -18,10 +18,12 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.google.cloud.tools.jib.image.DescriptorDigest; +import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.json.JsonTemplate; import com.google.common.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; +import java.util.SortedMap; import javax.annotation.Nullable; /** @@ -38,6 +40,7 @@ * "Env": ["/usr/bin/java"], * "Entrypoint": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"], * "Cmd": ["arg1", "arg2"] + * "ExposedPorts": { "6000/tcp":{}, "8000/tcp":{}, "9000/tcp":{} } * }, * "rootfs": { * "diff_ids": [ @@ -88,6 +91,9 @@ private static class ConfigurationObjectTemplate implements JsonTemplate { /** Arguments to pass into main. */ @Nullable private List Cmd; + + /** Network ports the container listens on. */ + @Nullable private SortedMap ExposedPorts; } /** @@ -118,6 +124,10 @@ public void setContainerCmd(List cmd) { config.Cmd = cmd; } + public void setContainerExposedPorts(SortedMap exposedPorts) { + config.ExposedPorts = exposedPorts; + } + public void addLayerDiffId(DescriptorDigest diffId) { rootfs.diff_ids.add(diffId); } @@ -141,6 +151,11 @@ List getContainerCmd() { return config.Cmd; } + @Nullable + SortedMap getContainerExposedPorts() { + return config.ExposedPorts; + } + @VisibleForTesting DescriptorDigest getLayerDiffId(int index) { return rootfs.diff_ids.get(index); diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslator.java b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslator.java index f3afc66518..43a135c592 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslator.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslator.java @@ -72,6 +72,9 @@ public Blob getContainerConfigurationBlob() { // Sets the main method arguments. template.setContainerCmd(image.getJavaArguments()); + // Sets the exposed ports. + template.setContainerExposedPorts(image.getExposedPorts()); + // Serializes into JSON. return JsonTemplateMapper.toBlob(template); } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslator.java b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslator.java index b8ded35c93..fe468b3461 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslator.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslator.java @@ -102,6 +102,10 @@ public static Image toImage( imageBuilder.setJavaArguments(containerConfigurationTemplate.getContainerCmd()); } + if (containerConfigurationTemplate.getContainerExposedPorts() != null) { + imageBuilder.setExposedPorts(containerConfigurationTemplate.getContainerExposedPorts()); + } + if (containerConfigurationTemplate.getContainerEnvironment() != null) { for (String environmentVariable : containerConfigurationTemplate.getContainerEnvironment()) { imageBuilder.addEnvironmentVariableDefinition(environmentVariable); diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/json/EmptyStruct.java b/jib-core/src/main/java/com/google/cloud/tools/jib/json/EmptyStruct.java new file mode 100644 index 0000000000..b7314e8781 --- /dev/null +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/json/EmptyStruct.java @@ -0,0 +1,38 @@ +/* + * Copyright 2018 Google LLC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.cloud.tools.jib.json; + +/** Empty class used for empty "{}" blocks in json. */ +public class EmptyStruct implements JsonTemplate { + private static final EmptyStruct SINGLETON = new EmptyStruct(); + + public static EmptyStruct get() { + return SINGLETON; + } + + @Override + public boolean equals(Object other) { + return other != null && other.getClass() == EmptyStruct.class; + } + + @Override + public int hashCode() { + return 0; + } + + private EmptyStruct() {} +} diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/BuildConfigurationTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/BuildConfigurationTest.java index 0cdb740c55..2f241ec77e 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/BuildConfigurationTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/BuildConfigurationTest.java @@ -20,8 +20,10 @@ import com.google.cloud.tools.jib.image.json.BuildableManifestTemplate; import com.google.cloud.tools.jib.image.json.OCIManifestTemplate; import com.google.cloud.tools.jib.image.json.V22ManifestTemplate; +import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedMap; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -50,6 +52,9 @@ public void testBuilder() { List expectedJavaArguments = Arrays.asList("arg1", "arg2"); List expectedJvmFlags = Arrays.asList("some", "jvm", "flags"); Map expectedEnvironment = ImmutableMap.of("key", "value"); + List exposedPorts = Arrays.asList("1000", "2000"); + ImmutableSortedMap expectedExposedPorts = + ImmutableSortedMap.of("1000/tcp", EmptyStruct.get(), "2000/tcp", EmptyStruct.get()); Class expectedTargetFormat = OCIManifestTemplate.class; BuildConfiguration.Builder buildConfigurationBuilder = @@ -68,6 +73,7 @@ public void testBuilder() { .setJavaArguments(expectedJavaArguments) .setJvmFlags(expectedJvmFlags) .setEnvironment(expectedEnvironment) + .setExposedPorts(exposedPorts) .setTargetFormat(OCIManifestTemplate.class); BuildConfiguration buildConfiguration = buildConfigurationBuilder.build(); @@ -87,6 +93,7 @@ public void testBuilder() { Assert.assertEquals(expectedJavaArguments, buildConfiguration.getJavaArguments()); Assert.assertEquals(expectedJvmFlags, buildConfiguration.getJvmFlags()); Assert.assertEquals(expectedEnvironment, buildConfiguration.getEnvironment()); + Assert.assertEquals(expectedExposedPorts, buildConfiguration.getExposedPorts()); Assert.assertEquals(expectedTargetFormat, buildConfiguration.getTargetFormat()); } @@ -119,6 +126,7 @@ public void testBuilder_default() { Assert.assertEquals(Collections.emptyList(), buildConfiguration.getJavaArguments()); Assert.assertEquals(Collections.emptyList(), buildConfiguration.getJvmFlags()); Assert.assertEquals(Collections.emptyMap(), buildConfiguration.getEnvironment()); + Assert.assertEquals(Collections.emptyMap(), buildConfiguration.getExposedPorts()); Assert.assertEquals(V22ManifestTemplate.class, buildConfiguration.getTargetFormat()); } @@ -172,4 +180,42 @@ public void testValidJavaClassRegex() { Assert.assertFalse(BuildConfiguration.isValidJavaClass("{class}")); Assert.assertFalse(BuildConfiguration.isValidJavaClass("not valid")); } + + @Test + public void testPortListToPortMap() { + List input = Arrays.asList("1000", "2000-2003", "3000 - 3000"); + ImmutableSortedMap expected = + new ImmutableSortedMap.Builder(String::compareTo) + .put("1000/tcp", EmptyStruct.get()) + .put("2000/tcp", EmptyStruct.get()) + .put("2001/tcp", EmptyStruct.get()) + .put("2002/tcp", EmptyStruct.get()) + .put("2003/tcp", EmptyStruct.get()) + .put("3000/tcp", EmptyStruct.get()) + .build(); + ImmutableSortedMap result = BuildConfiguration.portListToPortMap(input); + Assert.assertEquals(expected, result); + + List badNumbers = Arrays.asList("1000abc", "-1", "0", "70000"); + for (String badInput : badNumbers) { + input = Collections.singletonList(badInput); + try { + BuildConfiguration.portListToPortMap(input); + Assert.fail(); + } catch (NumberFormatException ex) { + Assert.assertEquals("Invalid port number " + badInput, ex.getMessage()); + } + } + + List badRanges = Arrays.asList("4000-2000", "0-4000", "500-65536"); + for (String badInput : badRanges) { + input = Collections.singletonList(badInput); + try { + BuildConfiguration.portListToPortMap(input); + Assert.fail(); + } catch (NumberFormatException ex) { + Assert.assertEquals("Invalid port range " + badInput, ex.getMessage()); + } + } + } } diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java index 096d10d662..c318f2798c 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java @@ -24,6 +24,7 @@ import com.google.cloud.tools.jib.image.Image; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedMap; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.MoreExecutors; import java.nio.file.Paths; @@ -62,6 +63,7 @@ public void setUp() throws DigestException { Mockito.when(mockBuildConfiguration.getBuildLogger()).thenReturn(mockBuildLogger); Mockito.when(mockBuildConfiguration.getEnvironment()).thenReturn(ImmutableMap.of()); Mockito.when(mockBuildConfiguration.getJavaArguments()).thenReturn(ImmutableList.of()); + Mockito.when(mockBuildConfiguration.getExposedPorts()).thenReturn(ImmutableSortedMap.of()); Mockito.when(mockPullAndCacheBaseImageLayersStep.getFuture()) .thenReturn( diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/image/ImageTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/image/ImageTest.java index 23041b3d3c..fa75888a72 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/image/ImageTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/image/ImageTest.java @@ -17,7 +17,9 @@ package com.google.cloud.tools.jib.image; import com.google.cloud.tools.jib.blob.BlobDescriptor; +import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedMap; import java.util.Arrays; import org.junit.Assert; import org.junit.Before; @@ -51,6 +53,8 @@ public void test_smokeTest() throws LayerPropertyNotFoundException { .setEnvironmentVariable("VARIABLE", "VALUE") .setEntrypoint(Arrays.asList("some", "command")) .setJavaArguments(Arrays.asList("arg1", "arg2")) + .setExposedPorts( + ImmutableSortedMap.of("port1", EmptyStruct.get(), "port2", EmptyStruct.get())) .addLayer(mockLayer) .build(); @@ -59,5 +63,8 @@ public void test_smokeTest() throws LayerPropertyNotFoundException { Assert.assertEquals(expectedEnvironment, image.getEnvironment()); Assert.assertEquals(Arrays.asList("some", "command"), image.getEntrypoint()); Assert.assertEquals(Arrays.asList("arg1", "arg2"), image.getJavaArguments()); + Assert.assertEquals( + ImmutableSortedMap.of("port1", EmptyStruct.get(), "port2", EmptyStruct.get()), + image.getExposedPorts()); } } diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplateTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplateTest.java index 4c9414ba0a..4d6c0d282a 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplateTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplateTest.java @@ -17,6 +17,7 @@ package com.google.cloud.tools.jib.image.json; import com.google.cloud.tools.jib.image.DescriptorDigest; +import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.json.JsonTemplateMapper; import com.google.common.io.Resources; import java.io.ByteArrayOutputStream; @@ -28,12 +29,25 @@ import java.nio.file.Paths; import java.security.DigestException; import java.util.Arrays; +import java.util.SortedMap; +import java.util.TreeMap; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** Tests for {@link ContainerConfigurationTemplate}. */ public class ContainerConfigurationTemplateTest { + private SortedMap exposedPorts; + + @Before + public void setup() { + exposedPorts = new TreeMap<>(); + exposedPorts.put("1000/tcp", EmptyStruct.get()); + exposedPorts.put("2000/tcp", EmptyStruct.get()); + exposedPorts.put("3000/tcp", EmptyStruct.get()); + } + @Test public void testToJson() throws IOException, URISyntaxException, DigestException { // Loads the expected JSON string. @@ -46,6 +60,7 @@ public void testToJson() throws IOException, URISyntaxException, DigestException containerConfigJson.setContainerEnvironment(Arrays.asList("VAR1=VAL1", "VAR2=VAL2")); containerConfigJson.setContainerEntrypoint(Arrays.asList("some", "entrypoint", "command")); containerConfigJson.setContainerCmd(Arrays.asList("arg1", "arg2")); + containerConfigJson.setContainerExposedPorts(exposedPorts); containerConfigJson.addLayerDiffId( DescriptorDigest.fromDigest( diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslatorTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslatorTest.java index 5f49598e16..a355993771 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslatorTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslatorTest.java @@ -22,7 +22,9 @@ import com.google.cloud.tools.jib.image.DescriptorDigest; import com.google.cloud.tools.jib.image.Image; import com.google.cloud.tools.jib.image.LayerPropertyNotFoundException; +import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.json.JsonTemplateMapper; +import com.google.common.collect.ImmutableSortedMap; import com.google.common.io.ByteStreams; import com.google.common.io.Resources; import java.io.ByteArrayOutputStream; @@ -55,6 +57,15 @@ public void setUp() throws DigestException, LayerPropertyNotFoundException { testImageBuilder.setJavaArguments(Arrays.asList("arg1", "arg2")); + testImageBuilder.setExposedPorts( + ImmutableSortedMap.of( + "1000/tcp", + EmptyStruct.get(), + "2000/tcp", + EmptyStruct.get(), + "3000/tcp", + EmptyStruct.get())); + DescriptorDigest fakeDigest = DescriptorDigest.fromDigest( "sha256:8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad"); diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslatorTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslatorTest.java index faa1632611..0688c42ab6 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslatorTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslatorTest.java @@ -22,7 +22,9 @@ import com.google.cloud.tools.jib.image.Layer; import com.google.cloud.tools.jib.image.LayerCountMismatchException; import com.google.cloud.tools.jib.image.LayerPropertyNotFoundException; +import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.json.JsonTemplateMapper; +import com.google.common.collect.ImmutableSortedMap; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Path; @@ -105,5 +107,14 @@ private void testToImage_buildable( layers.get(0).getDiffId()); Assert.assertEquals(Arrays.asList("some", "entrypoint", "command"), image.getEntrypoint()); Assert.assertEquals(Arrays.asList("VAR1=VAL1", "VAR2=VAL2"), image.getEnvironment()); + Assert.assertEquals( + ImmutableSortedMap.of( + "1000/tcp", + EmptyStruct.get(), + "2000/tcp", + EmptyStruct.get(), + "3000/tcp", + EmptyStruct.get()), + image.getExposedPorts()); } } diff --git a/jib-core/src/test/resources/json/containerconfig.json b/jib-core/src/test/resources/json/containerconfig.json index 46865a35dd..f4aca7bbf0 100644 --- a/jib-core/src/test/resources/json/containerconfig.json +++ b/jib-core/src/test/resources/json/containerconfig.json @@ -1 +1 @@ -{"created":"1970-01-01T00:00:00Z","architecture":"amd64","os":"linux","config":{"Env":["VAR1=VAL1","VAR2=VAL2"],"Entrypoint":["some","entrypoint","command"],"Cmd":["arg1","arg2"]},"rootfs":{"type":"layers","diff_ids":["sha256:8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad"]}} \ No newline at end of file +{"created":"1970-01-01T00:00:00Z","architecture":"amd64","os":"linux","config":{"Env":["VAR1=VAL1","VAR2=VAL2"],"Entrypoint":["some","entrypoint","command"],"Cmd":["arg1","arg2"],"ExposedPorts":{"1000/tcp":{},"2000/tcp":{},"3000/tcp":{}}},"rootfs":{"type":"layers","diff_ids":["sha256:8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad"]}} \ No newline at end of file diff --git a/jib-core/src/test/resources/json/translated_ocimanifest.json b/jib-core/src/test/resources/json/translated_ocimanifest.json index 3fa9663038..b457ed8ec2 100644 --- a/jib-core/src/test/resources/json/translated_ocimanifest.json +++ b/jib-core/src/test/resources/json/translated_ocimanifest.json @@ -1 +1 @@ -{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:e5260ce6926191331709d45da3467888a59585aa2c88689fb6a7565cedac718c","size":294},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad","size":1000}]} \ No newline at end of file +{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:d05f4301080b44cf4a4e63e69d9f269d0d07cf0d0d613cacdfe93fb777c4f3a2","size":353},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad","size":1000}]} \ No newline at end of file diff --git a/jib-core/src/test/resources/json/translated_v22manifest.json b/jib-core/src/test/resources/json/translated_v22manifest.json index bca5af3a92..beb0968b0d 100644 --- a/jib-core/src/test/resources/json/translated_v22manifest.json +++ b/jib-core/src/test/resources/json/translated_v22manifest.json @@ -1 +1 @@ -{"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/vnd.docker.container.image.v1+json","digest":"sha256:e5260ce6926191331709d45da3467888a59585aa2c88689fb6a7565cedac718c","size":294},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","digest":"sha256:8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad","size":1000}]} \ No newline at end of file +{"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/vnd.docker.container.image.v1+json","digest":"sha256:d05f4301080b44cf4a4e63e69d9f269d0d07cf0d0d613cacdfe93fb777c4f3a2","size":353},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","digest":"sha256:8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad","size":1000}]} \ No newline at end of file From dd44f8b01e498e45cdff6fa503880f7555c5581c Mon Sep 17 00:00:00 2001 From: Tad Cordle Date: Wed, 20 Jun 2018 16:34:47 -0400 Subject: [PATCH 2/8] Update integration tests --- .../builder/BuildStepsIntegrationTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/jib-core/src/integration-test/java/com/google/cloud/tools/jib/builder/BuildStepsIntegrationTest.java b/jib-core/src/integration-test/java/com/google/cloud/tools/jib/builder/BuildStepsIntegrationTest.java index aa33f810a9..00bb11febf 100644 --- a/jib-core/src/integration-test/java/com/google/cloud/tools/jib/builder/BuildStepsIntegrationTest.java +++ b/jib-core/src/integration-test/java/com/google/cloud/tools/jib/builder/BuildStepsIntegrationTest.java @@ -21,7 +21,9 @@ import com.google.cloud.tools.jib.image.ImageReference; import com.google.cloud.tools.jib.registry.LocalRegistry; import java.nio.file.Path; +import java.util.Arrays; import java.util.Collections; +import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Rule; @@ -46,6 +48,7 @@ public void testSteps_forBuildToDockerRegistry() throws Exception { .setTargetImage(ImageReference.of("localhost:5000", "testimage", "testtag")) .setMainClass("HelloWorld") .setJavaArguments(Collections.singletonList("An argument.")) + .setExposedPorts(Arrays.asList("1000", "2000-2003")) .build(); Path cacheDirectory = temporaryCacheDirectory.newFolder().toPath(); @@ -64,6 +67,15 @@ public void testSteps_forBuildToDockerRegistry() throws Exception { String imageReference = "localhost:5000/testimage:testtag"; new Command("docker", "pull", imageReference).run(); + Assert.assertThat( + new Command("docker", "inspect", imageReference).run(), + CoreMatchers.containsString( + " \"ExposedPorts\": {\n" + + " \"1000/tcp\": {},\n" + + " \"2000/tcp\": {},\n" + + " \"2001/tcp\": {},\n" + + " \"2002/tcp\": {},\n" + + " \"2003/tcp\": {}")); Assert.assertEquals( "Hello, world. An argument.\n", new Command("docker", "run", imageReference).run()); } @@ -77,6 +89,7 @@ public void testSteps_forBuildToDockerDaemon() throws Exception { .setTargetImage(ImageReference.of(null, "testdocker", null)) .setMainClass("HelloWorld") .setJavaArguments(Collections.singletonList("An argument.")) + .setExposedPorts(Arrays.asList("1000", "2000-2003")) .build(); Path cacheDirectory = temporaryCacheDirectory.newFolder().toPath(); @@ -87,6 +100,15 @@ public void testSteps_forBuildToDockerDaemon() throws Exception { Caches.newInitializer(cacheDirectory).setBaseCacheDirectory(cacheDirectory)); buildDockerSteps.run(); + Assert.assertThat( + new Command("docker", "inspect", "testdocker").run(), + CoreMatchers.containsString( + " \"ExposedPorts\": {\n" + + " \"1000/tcp\": {},\n" + + " \"2000/tcp\": {},\n" + + " \"2001/tcp\": {},\n" + + " \"2002/tcp\": {},\n" + + " \"2003/tcp\": {}")); Assert.assertEquals( "Hello, world. An argument.\n", new Command("docker", "run", "testdocker").run()); } From fcfa21a0506ca5531c878dd4252ac09afa2b5ca3 Mon Sep 17 00:00:00 2001 From: Tad Cordle Date: Wed, 20 Jun 2018 16:39:52 -0400 Subject: [PATCH 3/8] Javadoc --- .../com/google/cloud/tools/jib/builder/BuildConfiguration.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java index 0d4a37ae79..ab9d0903f2 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java @@ -221,7 +221,9 @@ public static boolean isValidJavaClass(String className) { * *

Example: [1000, 2000-2002] -> {"1000/tcp":{}, "2000/tcp":{}, "2001/tcp":{}, "2002/tcp":{}}) * + * @param ports the list of port numbers/ranges * @return the map + * @throws NumberFormatException if any of the ports are in an invalid format or out of range */ @VisibleForTesting static ImmutableSortedMap portListToPortMap(List ports) From 218bce133606afd7a762d28cf673e347cdf2613b Mon Sep 17 00:00:00 2001 From: Tad Cordle Date: Fri, 22 Jun 2018 10:03:19 -0400 Subject: [PATCH 4/8] Feedback --- .../tools/jib/builder/BuildConfiguration.java | 54 +++++++-------- .../google/cloud/tools/jib/image/Image.java | 16 ++--- .../json/ContainerConfigurationTemplate.java | 31 ++++++--- .../jib/builder/BuildConfigurationTest.java | 65 ++++++++----------- .../jib/builder/steps/BuildImageStepTest.java | 3 +- .../cloud/tools/jib/image/ImageTest.java | 9 +-- .../ContainerConfigurationTemplateTest.java | 15 ++--- .../image/json/ImageToJsonTranslatorTest.java | 11 +--- .../image/json/JsonToImageTranslatorTest.java | 12 +--- 9 files changed, 88 insertions(+), 128 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java index ab9d0903f2..3d5570587f 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/BuildConfiguration.java @@ -19,19 +19,12 @@ import com.google.cloud.tools.jib.image.ImageReference; import com.google.cloud.tools.jib.image.json.BuildableManifestTemplate; import com.google.cloud.tools.jib.image.json.V22ManifestTemplate; -import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSortedMap; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; +import java.util.*; import javax.annotation.Nullable; import javax.lang.model.SourceVersion; @@ -144,15 +137,6 @@ public BuildConfiguration build() { errorMessages.add("main class is required but not set"); } - ImmutableSortedMap exposedPortsMap = ImmutableSortedMap.of(); - try { - exposedPortsMap = portListToPortMap(exposedPorts); - } catch (NumberFormatException ex) { - errorMessages.add( - "exposed ports are configured in an invalid format (must be a single " - + "port number or a range of port number)"); - } - switch (errorMessages.size()) { case 0: // No errors if (baseImageReference == null || targetImageReference == null || mainClass == null) { @@ -176,7 +160,7 @@ public BuildConfiguration build() { ImmutableList.copyOf(javaArguments), ImmutableList.copyOf(jvmFlags), ImmutableMap.copyOf(environmentMap), - ImmutableSortedMap.copyOf(exposedPortsMap), + expandPortRanges(exposedPorts, buildLogger), targetFormat); case 1: @@ -226,21 +210,20 @@ public static boolean isValidJavaClass(String className) { * @throws NumberFormatException if any of the ports are in an invalid format or out of range */ @VisibleForTesting - static ImmutableSortedMap portListToPortMap(List ports) - throws NumberFormatException { - SortedMap result = new TreeMap<>(); + static ImmutableList expandPortRanges(List ports, BuildLogger logger) { + List result = new ArrayList<>(); for (String port : ports) { // Remove all spaces - port = port.trim().replace(" ", ""); + port = port.replace(" ", ""); if (port.matches("\\d+")) { // Port is a single number int portNum = Integer.parseInt(port); if (portNum < 1 || portNum > 65535) { - throw new NumberFormatException("Invalid port number " + port); + logger.warn("Port number '" + port + "' is out of range (1-65535)"); } - result.put(port + "/tcp", EmptyStruct.get()); + result.add(port); } else if (port.matches("\\d+-\\d+")) { // Port is a range @@ -248,22 +231,29 @@ static ImmutableSortedMap portListToPortMap(List po int min = Integer.parseInt(range.get(0)); int max = Integer.parseInt(range.get(1)); + // Reverse range if configured as 'max-min' instead of 'min-max' + if (min > max) { + int swapTemp = max; + max = min; + min = swapTemp; + } + // Make sure range is valid (min-max, within port range) - if (min > max || min < 1 || max > 65535) { - throw new NumberFormatException("Invalid port range " + port); + if (min < 1 || max > 65535) { + logger.warn("Port range '" + port + "' exceeds normal port range (1-65535)"); } for (int portNum = min; portNum <= max; portNum++) { - result.put(portNum + "/tcp", EmptyStruct.get()); + result.add("" + portNum); } } else { // Port is neither a single number nor a range - throw new NumberFormatException("Invalid port number " + port); + logger.warn("Port '" + port + "' is not a port number"); } } - return ImmutableSortedMap.copyOf(result); + return ImmutableList.copyOf(result); } private final BuildLogger buildLogger; @@ -277,7 +267,7 @@ static ImmutableSortedMap portListToPortMap(List po private final ImmutableList javaArguments; private final ImmutableList jvmFlags; private final ImmutableMap environmentMap; - private final ImmutableSortedMap exposedPorts; + private final ImmutableList exposedPorts; private final Class targetFormat; public static Builder builder(BuildLogger buildLogger) { @@ -297,7 +287,7 @@ private BuildConfiguration( ImmutableList javaArguments, ImmutableList jvmFlags, ImmutableMap environmentMap, - ImmutableSortedMap exposedPorts, + ImmutableList exposedPorts, Class targetFormat) { this.buildLogger = buildLogger; this.baseImageReference = baseImageReference; @@ -386,7 +376,7 @@ public ImmutableMap getEnvironment() { return environmentMap; } - public ImmutableSortedMap getExposedPorts() { + public ImmutableList getExposedPorts() { return exposedPorts; } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java b/jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java index cb2000f205..58771637a6 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java @@ -16,9 +16,7 @@ package com.google.cloud.tools.jib.image; -import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSortedMap; import java.util.List; import java.util.Map; @@ -33,7 +31,7 @@ public static class Builder { private ImmutableList entrypoint = ImmutableList.of(); private ImmutableList javaArguments = ImmutableList.of(); - private ImmutableSortedMap exposedPorts = ImmutableSortedMap.of(); + private ImmutableList exposedPorts = ImmutableList.of(); /** * Sets the environment with a map from environment variable names to values. @@ -100,8 +98,8 @@ public Builder setJavaArguments(List javaArguments) { * appear in the configuration json (e.g. "portNum/tcp") * @return this */ - public Builder setExposedPorts(Map exposedPorts) { - this.exposedPorts = ImmutableSortedMap.copyOf(exposedPorts); + public Builder setExposedPorts(List exposedPorts) { + this.exposedPorts = ImmutableList.copyOf(exposedPorts); return this; } @@ -123,7 +121,7 @@ public Image build() { environmentBuilder.build(), ImmutableList.copyOf(entrypoint), ImmutableList.copyOf(javaArguments), - ImmutableSortedMap.copyOf(exposedPorts)); + ImmutableList.copyOf(exposedPorts)); } } @@ -144,14 +142,14 @@ public static Builder builder() { private final ImmutableList javaArguments; /** Ports that the container listens on. */ - private final ImmutableSortedMap exposedPorts; + private final ImmutableList exposedPorts; private Image( ImageLayers layers, ImmutableList environment, ImmutableList entrypoint, ImmutableList javaArguments, - ImmutableSortedMap exposedPorts) { + ImmutableList exposedPorts) { this.layers = layers; this.environmentBuilder = environment; this.entrypoint = entrypoint; @@ -171,7 +169,7 @@ public ImmutableList getJavaArguments() { return javaArguments; } - public ImmutableSortedMap getExposedPorts() { + public ImmutableList getExposedPorts() { return exposedPorts; } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplate.java b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplate.java index 36bdad95d0..95d22b0385 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplate.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplate.java @@ -18,12 +18,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.google.cloud.tools.jib.image.DescriptorDigest; -import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.json.JsonTemplate; import com.google.common.annotations.VisibleForTesting; -import java.util.ArrayList; -import java.util.List; -import java.util.SortedMap; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSortedMap; +import java.util.*; import javax.annotation.Nullable; /** @@ -92,8 +91,8 @@ private static class ConfigurationObjectTemplate implements JsonTemplate { /** Arguments to pass into main. */ @Nullable private List Cmd; - /** Network ports the container listens on. */ - @Nullable private SortedMap ExposedPorts; + /** Network ports the container exposes. */ + @Nullable private SortedMap> ExposedPorts; } /** @@ -124,8 +123,12 @@ public void setContainerCmd(List cmd) { config.Cmd = cmd; } - public void setContainerExposedPorts(SortedMap exposedPorts) { - config.ExposedPorts = exposedPorts; + public void setContainerExposedPorts(List exposedPorts) { + SortedMap> result = new TreeMap<>(); + for (String port : exposedPorts) { + result.put(port + "/tcp", Collections.emptyMap()); + } + config.ExposedPorts = ImmutableSortedMap.copyOf(result); } public void addLayerDiffId(DescriptorDigest diffId) { @@ -152,8 +155,16 @@ List getContainerCmd() { } @Nullable - SortedMap getContainerExposedPorts() { - return config.ExposedPorts; + List getContainerExposedPorts() { + if (config.ExposedPorts == null) { + return null; + } + List ports = new ArrayList<>(); + for (Map.Entry> entry : config.ExposedPorts.entrySet()) { + // Remove the "/tcp" + ports.add(Splitter.on('/').splitToList(entry.getKey()).get(0)); + } + return ports; } @VisibleForTesting diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/BuildConfigurationTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/BuildConfigurationTest.java index 2f241ec77e..ecf486cdc8 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/BuildConfigurationTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/BuildConfigurationTest.java @@ -20,20 +20,25 @@ import com.google.cloud.tools.jib.image.json.BuildableManifestTemplate; import com.google.cloud.tools.jib.image.json.OCIManifestTemplate; import com.google.cloud.tools.jib.image.json.V22ManifestTemplate; -import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSortedMap; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import org.junit.Assert; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +@RunWith(MockitoJUnitRunner.class) public class BuildConfigurationTest { + @Mock private BuildLogger mockLogger; + @Test public void testBuilder() { String expectedBaseImageServerUrl = "someserver"; @@ -52,9 +57,7 @@ public void testBuilder() { List expectedJavaArguments = Arrays.asList("arg1", "arg2"); List expectedJvmFlags = Arrays.asList("some", "jvm", "flags"); Map expectedEnvironment = ImmutableMap.of("key", "value"); - List exposedPorts = Arrays.asList("1000", "2000"); - ImmutableSortedMap expectedExposedPorts = - ImmutableSortedMap.of("1000/tcp", EmptyStruct.get(), "2000/tcp", EmptyStruct.get()); + List expectedExposedPorts = Arrays.asList("1000", "2000"); Class expectedTargetFormat = OCIManifestTemplate.class; BuildConfiguration.Builder buildConfigurationBuilder = @@ -73,7 +76,7 @@ public void testBuilder() { .setJavaArguments(expectedJavaArguments) .setJvmFlags(expectedJvmFlags) .setEnvironment(expectedEnvironment) - .setExposedPorts(exposedPorts) + .setExposedPorts(expectedExposedPorts) .setTargetFormat(OCIManifestTemplate.class); BuildConfiguration buildConfiguration = buildConfigurationBuilder.build(); @@ -126,7 +129,7 @@ public void testBuilder_default() { Assert.assertEquals(Collections.emptyList(), buildConfiguration.getJavaArguments()); Assert.assertEquals(Collections.emptyList(), buildConfiguration.getJvmFlags()); Assert.assertEquals(Collections.emptyMap(), buildConfiguration.getEnvironment()); - Assert.assertEquals(Collections.emptyMap(), buildConfiguration.getExposedPorts()); + Assert.assertEquals(Collections.emptyList(), buildConfiguration.getExposedPorts()); Assert.assertEquals(V22ManifestTemplate.class, buildConfiguration.getTargetFormat()); } @@ -182,40 +185,26 @@ public void testValidJavaClassRegex() { } @Test - public void testPortListToPortMap() { - List input = Arrays.asList("1000", "2000-2003", "3000 - 3000"); - ImmutableSortedMap expected = - new ImmutableSortedMap.Builder(String::compareTo) - .put("1000/tcp", EmptyStruct.get()) - .put("2000/tcp", EmptyStruct.get()) - .put("2001/tcp", EmptyStruct.get()) - .put("2002/tcp", EmptyStruct.get()) - .put("2003/tcp", EmptyStruct.get()) - .put("3000/tcp", EmptyStruct.get()) + public void testExpandPortList() { + List input = Arrays.asList("1000", "2000-2003", "3000 - 3000", "4002-4000"); + ImmutableList expected = + new ImmutableList.Builder() + .add("1000", "2000", "2001", "2002", "2003", "3000", "4000", "4001", "4002") .build(); - ImmutableSortedMap result = BuildConfiguration.portListToPortMap(input); + ImmutableList result = BuildConfiguration.expandPortRanges(input, mockLogger); Assert.assertEquals(expected, result); - List badNumbers = Arrays.asList("1000abc", "-1", "0", "70000"); - for (String badInput : badNumbers) { - input = Collections.singletonList(badInput); - try { - BuildConfiguration.portListToPortMap(input); - Assert.fail(); - } catch (NumberFormatException ex) { - Assert.assertEquals("Invalid port number " + badInput, ex.getMessage()); - } - } + BuildConfiguration.expandPortRanges(Collections.singletonList("abc"), mockLogger); + Mockito.verify(mockLogger).warn("Port 'abc' is not a port number"); - List badRanges = Arrays.asList("4000-2000", "0-4000", "500-65536"); - for (String badInput : badRanges) { - input = Collections.singletonList(badInput); - try { - BuildConfiguration.portListToPortMap(input); - Assert.fail(); - } catch (NumberFormatException ex) { - Assert.assertEquals("Invalid port range " + badInput, ex.getMessage()); - } - } + BuildConfiguration.expandPortRanges(Collections.singletonList("0"), mockLogger); + Mockito.verify(mockLogger).warn("Port number '0' is out of range (1-65535)"); + BuildConfiguration.expandPortRanges(Collections.singletonList("70000"), mockLogger); + Mockito.verify(mockLogger).warn("Port number '70000' is out of range (1-65535)"); + + BuildConfiguration.expandPortRanges(Collections.singletonList("0-400"), mockLogger); + Mockito.verify(mockLogger).warn("Port range '0-400' exceeds normal port range (1-65535)"); + BuildConfiguration.expandPortRanges(Collections.singletonList("500-70000"), mockLogger); + Mockito.verify(mockLogger).warn("Port range '500-70000' exceeds normal port range (1-65535)"); } } diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java index c03c904953..3ae274f153 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java @@ -25,7 +25,6 @@ import com.google.cloud.tools.jib.image.Image; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSortedMap; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.MoreExecutors; import java.nio.file.Paths; @@ -66,7 +65,7 @@ public void setUp() throws DigestException { Mockito.when(mockBuildConfiguration.getBuildLogger()).thenReturn(mockBuildLogger); Mockito.when(mockBuildConfiguration.getEnvironment()).thenReturn(ImmutableMap.of()); Mockito.when(mockBuildConfiguration.getJavaArguments()).thenReturn(ImmutableList.of()); - Mockito.when(mockBuildConfiguration.getExposedPorts()).thenReturn(ImmutableSortedMap.of()); + Mockito.when(mockBuildConfiguration.getExposedPorts()).thenReturn(ImmutableList.of()); Mockito.when(mockPullAndCacheBaseImageLayersStep.getFuture()) .thenReturn( diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/image/ImageTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/image/ImageTest.java index fa75888a72..1b63e3ea4c 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/image/ImageTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/image/ImageTest.java @@ -17,9 +17,7 @@ package com.google.cloud.tools.jib.image; import com.google.cloud.tools.jib.blob.BlobDescriptor; -import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSortedMap; import java.util.Arrays; import org.junit.Assert; import org.junit.Before; @@ -53,8 +51,7 @@ public void test_smokeTest() throws LayerPropertyNotFoundException { .setEnvironmentVariable("VARIABLE", "VALUE") .setEntrypoint(Arrays.asList("some", "command")) .setJavaArguments(Arrays.asList("arg1", "arg2")) - .setExposedPorts( - ImmutableSortedMap.of("port1", EmptyStruct.get(), "port2", EmptyStruct.get())) + .setExposedPorts(Arrays.asList("port1", "port2")) .addLayer(mockLayer) .build(); @@ -63,8 +60,6 @@ public void test_smokeTest() throws LayerPropertyNotFoundException { Assert.assertEquals(expectedEnvironment, image.getEnvironment()); Assert.assertEquals(Arrays.asList("some", "command"), image.getEntrypoint()); Assert.assertEquals(Arrays.asList("arg1", "arg2"), image.getJavaArguments()); - Assert.assertEquals( - ImmutableSortedMap.of("port1", EmptyStruct.get(), "port2", EmptyStruct.get()), - image.getExposedPorts()); + Assert.assertEquals(Arrays.asList("port1", "port2"), image.getExposedPorts()); } } diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplateTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplateTest.java index 4d6c0d282a..3cdfeb3801 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplateTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ContainerConfigurationTemplateTest.java @@ -17,7 +17,6 @@ package com.google.cloud.tools.jib.image.json; import com.google.cloud.tools.jib.image.DescriptorDigest; -import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.json.JsonTemplateMapper; import com.google.common.io.Resources; import java.io.ByteArrayOutputStream; @@ -28,9 +27,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.security.DigestException; -import java.util.Arrays; -import java.util.SortedMap; -import java.util.TreeMap; +import java.util.*; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -38,14 +35,14 @@ /** Tests for {@link ContainerConfigurationTemplate}. */ public class ContainerConfigurationTemplateTest { - private SortedMap exposedPorts; + private List exposedPorts; @Before public void setup() { - exposedPorts = new TreeMap<>(); - exposedPorts.put("1000/tcp", EmptyStruct.get()); - exposedPorts.put("2000/tcp", EmptyStruct.get()); - exposedPorts.put("3000/tcp", EmptyStruct.get()); + exposedPorts = new ArrayList<>(); + exposedPorts.add("1000"); + exposedPorts.add("2000"); + exposedPorts.add("3000"); } @Test diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslatorTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslatorTest.java index a355993771..2f510d3370 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslatorTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslatorTest.java @@ -22,9 +22,7 @@ import com.google.cloud.tools.jib.image.DescriptorDigest; import com.google.cloud.tools.jib.image.Image; import com.google.cloud.tools.jib.image.LayerPropertyNotFoundException; -import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.json.JsonTemplateMapper; -import com.google.common.collect.ImmutableSortedMap; import com.google.common.io.ByteStreams; import com.google.common.io.Resources; import java.io.ByteArrayOutputStream; @@ -57,14 +55,7 @@ public void setUp() throws DigestException, LayerPropertyNotFoundException { testImageBuilder.setJavaArguments(Arrays.asList("arg1", "arg2")); - testImageBuilder.setExposedPorts( - ImmutableSortedMap.of( - "1000/tcp", - EmptyStruct.get(), - "2000/tcp", - EmptyStruct.get(), - "3000/tcp", - EmptyStruct.get())); + testImageBuilder.setExposedPorts(Arrays.asList("1000", "2000", "3000")); DescriptorDigest fakeDigest = DescriptorDigest.fromDigest( diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslatorTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslatorTest.java index 0688c42ab6..00be6bbfd7 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslatorTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/image/json/JsonToImageTranslatorTest.java @@ -22,9 +22,7 @@ import com.google.cloud.tools.jib.image.Layer; import com.google.cloud.tools.jib.image.LayerCountMismatchException; import com.google.cloud.tools.jib.image.LayerPropertyNotFoundException; -import com.google.cloud.tools.jib.json.EmptyStruct; import com.google.cloud.tools.jib.json.JsonTemplateMapper; -import com.google.common.collect.ImmutableSortedMap; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Path; @@ -107,14 +105,6 @@ private void testToImage_buildable( layers.get(0).getDiffId()); Assert.assertEquals(Arrays.asList("some", "entrypoint", "command"), image.getEntrypoint()); Assert.assertEquals(Arrays.asList("VAR1=VAL1", "VAR2=VAL2"), image.getEnvironment()); - Assert.assertEquals( - ImmutableSortedMap.of( - "1000/tcp", - EmptyStruct.get(), - "2000/tcp", - EmptyStruct.get(), - "3000/tcp", - EmptyStruct.get()), - image.getExposedPorts()); + Assert.assertEquals(Arrays.asList("1000", "2000", "3000"), image.getExposedPorts()); } } From 5e68c1b630a14c68e47f1794eeb50bbdde32a7e5 Mon Sep 17 00:00:00 2001 From: Tad Cordle Date: Fri, 22 Jun 2018 10:05:25 -0400 Subject: [PATCH 5/8] Add core exportPorts functionality to docker context exporter --- .../jib/docker/DockerContextGenerator.java | 28 +++++++++++++++++++ .../src/main/resources/DockerfileTemplate | 2 +- .../docker/DockerContextGeneratorTest.java | 11 +++++++- jib-core/src/test/resources/sampleDockerfile | 2 ++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/docker/DockerContextGenerator.java b/jib-core/src/main/java/com/google/cloud/tools/jib/docker/DockerContextGenerator.java index 530113fa27..c76d9a6055 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/docker/DockerContextGenerator.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/docker/DockerContextGenerator.java @@ -52,6 +52,7 @@ public class DockerContextGenerator { private List jvmFlags = Collections.emptyList(); private String mainClass = ""; private List javaArguments = Collections.emptyList(); + private List exposedPorts = Collections.emptyList(); public DockerContextGenerator(SourceFilesConfiguration sourceFilesConfiguration) { this.sourceFilesConfiguration = sourceFilesConfiguration; @@ -102,6 +103,17 @@ public DockerContextGenerator setJavaArguments(List javaArguments) { return this; } + /** + * Sets the exposed ports. + * + * @param exposedPorts the list of port numbers/port ranges to expose + * @return this + */ + public DockerContextGenerator setExposedPorts(List exposedPorts) { + this.exposedPorts = exposedPorts; + return this; + } + /** * Creates the Docker context in {@code #targetDirectory}. * @@ -159,6 +171,7 @@ String makeDockerfile() throws IOException { "@@DEPENDENCIES_PATH_ON_IMAGE@@", sourceFilesConfiguration.getDependenciesPathOnImage()) .replace("@@RESOURCES_PATH_ON_IMAGE@@", sourceFilesConfiguration.getResourcesPathOnImage()) .replace("@@CLASSES_PATH_ON_IMAGE@@", sourceFilesConfiguration.getClassesPathOnImage()) + .replace("@@EXPOSED_PORTS@@", makeExposeItems(exposedPorts)) .replace( "@@ENTRYPOINT@@", joinAsJsonArray( @@ -193,4 +206,19 @@ static String joinAsJsonArray(List items) { return resultString.toString(); } + + /** + * Builds a list of Dockerfile "EXPOSE" items. + * + * @param exposedPorts the list of ports numbers/ranges to expose + * @return a string containing an EXPOSE command for each of the entries + */ + @VisibleForTesting + static String makeExposeItems(List exposedPorts) { + StringBuilder resultString = new StringBuilder(); + for (String port : exposedPorts) { + resultString.append("EXPOSE ").append(port).append("\n"); + } + return resultString.toString(); + } } diff --git a/jib-core/src/main/resources/DockerfileTemplate b/jib-core/src/main/resources/DockerfileTemplate index 2086e7f10f..5e87095d01 100644 --- a/jib-core/src/main/resources/DockerfileTemplate +++ b/jib-core/src/main/resources/DockerfileTemplate @@ -4,5 +4,5 @@ COPY libs @@DEPENDENCIES_PATH_ON_IMAGE@@ COPY resources @@RESOURCES_PATH_ON_IMAGE@@ COPY classes @@CLASSES_PATH_ON_IMAGE@@ -ENTRYPOINT @@ENTRYPOINT@@ +@@EXPOSED_PORTS@@ENTRYPOINT @@ENTRYPOINT@@ CMD @@CMD@@ diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/docker/DockerContextGeneratorTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/docker/DockerContextGeneratorTest.java index 2078523c1e..90c59ec4fc 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/docker/DockerContextGeneratorTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/docker/DockerContextGeneratorTest.java @@ -113,7 +113,7 @@ public void testGenerate() throws IOException, URISyntaxException { } @Test - public void testMakeDockerList() { + public void testJoinAsJsonArray() { Assert.assertEquals( "[\"java\",\"-cp\",\"/app/libs/*:/app/resources/:/app/classes/\",\"\"]", DockerContextGenerator.joinAsJsonArray( @@ -128,12 +128,20 @@ public void testMakeDockerList() { "AnotherMainClass"))); } + @Test + public void testMakeExposeItems() { + Assert.assertEquals( + "EXPOSE 1000\nEXPOSE 2000-2010\n", + DockerContextGenerator.makeExposeItems(ImmutableList.of("1000", "2000-2010"))); + } + @Test public void testMakeDockerfile() throws IOException, URISyntaxException { String expectedBaseImage = "somebaseimage"; List expectedJvmFlags = Arrays.asList("-flag", "another\"Flag"); String expectedMainClass = "SomeMainClass"; List expectedJavaArguments = Arrays.asList("arg1", "arg2"); + List exposedPorts = Arrays.asList("1000", "2000-2010"); String dockerfile = new DockerContextGenerator(mockSourceFilesConfiguration) @@ -141,6 +149,7 @@ public void testMakeDockerfile() throws IOException, URISyntaxException { .setJvmFlags(expectedJvmFlags) .setMainClass(expectedMainClass) .setJavaArguments(expectedJavaArguments) + .setExposedPorts(exposedPorts) .makeDockerfile(); Path sampleDockerfile = Paths.get(Resources.getResource("sampleDockerfile").toURI()); diff --git a/jib-core/src/test/resources/sampleDockerfile b/jib-core/src/test/resources/sampleDockerfile index 27d7ba9d34..8de7285c1f 100644 --- a/jib-core/src/test/resources/sampleDockerfile +++ b/jib-core/src/test/resources/sampleDockerfile @@ -4,5 +4,7 @@ COPY libs /app/libs/ COPY resources /app/resources/ COPY classes /app/classes/ +EXPOSE 1000 +EXPOSE 2000-2010 ENTRYPOINT ["java","-flag","another\"Flag","-cp","/app/libs/*:/app/resources/:/app/classes/","SomeMainClass"] CMD ["arg1","arg2"] From 6b755b1d7c706ac5084a9db9809114167ffe02ef Mon Sep 17 00:00:00 2001 From: Tad Cordle Date: Fri, 22 Jun 2018 10:10:00 -0400 Subject: [PATCH 6/8] Add 'exposedPorts' parameter to maven plugin --- jib-maven-plugin/CHANGELOG.md | 2 ++ .../google/cloud/tools/jib/maven/BuildDockerMojo.java | 1 + .../google/cloud/tools/jib/maven/BuildImageMojo.java | 1 + .../cloud/tools/jib/maven/DockerContextMojo.java | 1 + .../cloud/tools/jib/maven/JibPluginConfiguration.java | 6 ++++++ .../jib/maven/BuildDockerMojoIntegrationTest.java | 10 ++++++++++ .../jib/maven/BuildImageMojoIntegrationTest.java | 9 +++++++++ .../jib/maven/DockerContextMojoIntegrationTest.java | 11 +++++++++++ .../test/resources/projects/default-target/pom.xml | 4 ++++ .../src/test/resources/projects/empty/pom.xml | 6 ++++++ .../src/test/resources/projects/simple/pom.xml | 4 ++++ 11 files changed, 55 insertions(+) diff --git a/jib-maven-plugin/CHANGELOG.md b/jib-maven-plugin/CHANGELOG.md index dd40b24b76..f5dc5ab73e 100644 --- a/jib-maven-plugin/CHANGELOG.md +++ b/jib-maven-plugin/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. ### Added +- `` parameter to define container's exposed ports (similar to Dockerfile `EXPOSE`) ([#383](https://github.com/GoogleContainerTools/jib/issues/383)) + ### Changed - Fetches credentials from inferred credential helper before Docker config ([#401](https://github.com/GoogleContainerTools/jib/issues/401)) diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index 6ec75d1ef7..5d10f799f3 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -85,6 +85,7 @@ public void execute() throws MojoExecutionException { .setJavaArguments(getArgs()) .setJvmFlags(getJvmFlags()) .setEnvironment(getEnvironment()) + .setExposedPorts(getExposedPorts()) .build(); // TODO: Instead of disabling logging, have authentication credentials be provided diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index c8d6ae1c75..e8ddf47336 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -102,6 +102,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { .setJavaArguments(getArgs()) .setJvmFlags(getJvmFlags()) .setEnvironment(getEnvironment()) + .setExposedPorts(getExposedPorts()) .setTargetFormat(ImageFormat.valueOf(getFormat()).getManifestTemplateClass()) .build(); diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/DockerContextMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/DockerContextMojo.java index 4b032f5758..5df5565f06 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/DockerContextMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/DockerContextMojo.java @@ -63,6 +63,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { .setJvmFlags(getJvmFlags()) .setMainClass(mainClass) .setJavaArguments(getArgs()) + .setExposedPorts(getExposedPorts()) .generate(Paths.get(targetDir)); mavenBuildLogger.info("Created Docker context at " + targetDir); diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java index 708041b5a2..25e15da98a 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java @@ -72,6 +72,8 @@ public static class ContainerParameters { @Nullable @Parameter(required = true) private String format = "Docker"; + + @Parameter private List exposedPorts = Collections.emptyList(); } /** @@ -194,6 +196,10 @@ List getArgs() { return container.args; } + List getExposedPorts() { + return container.exposedPorts; + } + String getFormat() { return Preconditions.checkNotNull(container.format); } diff --git a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildDockerMojoIntegrationTest.java b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildDockerMojoIntegrationTest.java index 675c31cf9e..327f7650e4 100644 --- a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildDockerMojoIntegrationTest.java +++ b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildDockerMojoIntegrationTest.java @@ -21,6 +21,7 @@ import java.nio.file.Path; import org.apache.maven.it.VerificationException; import org.apache.maven.it.Verifier; +import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; @@ -54,6 +55,15 @@ private static String buildToDockerDaemonAndRun(Path projectRoot, String imageRe verifier.executeGoal("jib:" + BuildDockerMojo.GOAL_NAME); verifier.verifyErrorFreeLog(); + Assert.assertThat( + new Command("docker", "inspect", imageReference).run(), + CoreMatchers.containsString( + " \"ExposedPorts\": {\n" + + " \"1000/tcp\": {},\n" + + " \"2000/tcp\": {},\n" + + " \"2001/tcp\": {},\n" + + " \"2002/tcp\": {},\n" + + " \"2003/tcp\": {}")); return new Command("docker", "run", imageReference).run(); } diff --git a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java index d5e5f4c588..6275e3c952 100644 --- a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java +++ b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java @@ -72,6 +72,15 @@ private static String buildAndRun(Path projectRoot, String imageReference) timeOne > timeTwo); new Command("docker", "pull", imageReference).run(); + Assert.assertThat( + new Command("docker", "inspect", imageReference).run(), + CoreMatchers.containsString( + " \"ExposedPorts\": {\n" + + " \"1000/tcp\": {},\n" + + " \"2000/tcp\": {},\n" + + " \"2001/tcp\": {},\n" + + " \"2002/tcp\": {},\n" + + " \"2003/tcp\": {}")); return new Command("docker", "run", imageReference).run(); } diff --git a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/DockerContextMojoIntegrationTest.java b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/DockerContextMojoIntegrationTest.java index 7a92362333..c1d5a16a40 100644 --- a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/DockerContextMojoIntegrationTest.java +++ b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/DockerContextMojoIntegrationTest.java @@ -22,6 +22,7 @@ import java.nio.file.Path; import org.apache.maven.it.VerificationException; import org.apache.maven.it.Verifier; +import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; @@ -50,6 +51,16 @@ public void testExecute() throws VerificationException, IOException, Interrupted String imageName = "jib/integration-test"; new Command("docker", "build", "-t", imageName, dockerContextDirectory.toString()).run(); + Assert.assertThat( + new Command("docker", "inspect", imageName).run(), + CoreMatchers.containsString( + " \"ExposedPorts\": {\n" + + " \"1000/tcp\": {},\n" + + " \"2000/tcp\": {},\n" + + " \"2001/tcp\": {},\n" + + " \"2002/tcp\": {},\n" + + " \"2003/tcp\": {}")); + Assert.assertEquals( "Hello, world. An argument.\n", new Command("docker", "run", imageName).run()); } diff --git a/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml b/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml index 4e7f4b9249..990c09c6f6 100644 --- a/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml +++ b/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml @@ -40,6 +40,10 @@ An argument. + + 1000 + 2000-2003 + true diff --git a/jib-maven-plugin/src/test/resources/projects/empty/pom.xml b/jib-maven-plugin/src/test/resources/projects/empty/pom.xml index 3e301cbb2e..600339ffb2 100644 --- a/jib-maven-plugin/src/test/resources/projects/empty/pom.xml +++ b/jib-maven-plugin/src/test/resources/projects/empty/pom.xml @@ -31,6 +31,12 @@ gcr.io/jib-integration-testing/emptyimage:maven + + + 1000 + 2000-2003 + + true diff --git a/jib-maven-plugin/src/test/resources/projects/simple/pom.xml b/jib-maven-plugin/src/test/resources/projects/simple/pom.xml index 38e76f6f5c..590d86dbfe 100644 --- a/jib-maven-plugin/src/test/resources/projects/simple/pom.xml +++ b/jib-maven-plugin/src/test/resources/projects/simple/pom.xml @@ -43,6 +43,10 @@ An argument. + + 1000 + 2000-2003 + true From 7fa237b95fa71f898db6f22cfb2284a408ef1af1 Mon Sep 17 00:00:00 2001 From: Tad Cordle Date: Fri, 22 Jun 2018 10:29:59 -0400 Subject: [PATCH 7/8] Rename 'exportPorts' to 'ports' --- jib-maven-plugin/CHANGELOG.md | 2 +- .../cloud/tools/jib/maven/JibPluginConfiguration.java | 4 ++-- .../src/test/resources/projects/default-target/pom.xml | 8 ++++---- .../src/test/resources/projects/empty/pom.xml | 8 ++++---- .../src/test/resources/projects/simple/pom.xml | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/jib-maven-plugin/CHANGELOG.md b/jib-maven-plugin/CHANGELOG.md index f5dc5ab73e..e48f5f1d75 100644 --- a/jib-maven-plugin/CHANGELOG.md +++ b/jib-maven-plugin/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. ### Added -- `` parameter to define container's exposed ports (similar to Dockerfile `EXPOSE`) ([#383](https://github.com/GoogleContainerTools/jib/issues/383)) +- `` parameter to define container's exposed ports (similar to Dockerfile `EXPOSE`) ([#383](https://github.com/GoogleContainerTools/jib/issues/383)) ### Changed diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java index 25e15da98a..97323408dc 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java @@ -73,7 +73,7 @@ public static class ContainerParameters { @Parameter(required = true) private String format = "Docker"; - @Parameter private List exposedPorts = Collections.emptyList(); + @Parameter private List ports = Collections.emptyList(); } /** @@ -197,7 +197,7 @@ List getArgs() { } List getExposedPorts() { - return container.exposedPorts; + return container.ports; } String getFormat() { diff --git a/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml b/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml index 990c09c6f6..6f489acaac 100644 --- a/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml +++ b/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml @@ -40,10 +40,10 @@ An argument. - - 1000 - 2000-2003 - + + 1000 + 2000-2003 + true diff --git a/jib-maven-plugin/src/test/resources/projects/empty/pom.xml b/jib-maven-plugin/src/test/resources/projects/empty/pom.xml index 600339ffb2..8eed0ed53a 100644 --- a/jib-maven-plugin/src/test/resources/projects/empty/pom.xml +++ b/jib-maven-plugin/src/test/resources/projects/empty/pom.xml @@ -32,10 +32,10 @@ gcr.io/jib-integration-testing/emptyimage:maven - - 1000 - 2000-2003 - + + 1000 + 2000-2003 + true diff --git a/jib-maven-plugin/src/test/resources/projects/simple/pom.xml b/jib-maven-plugin/src/test/resources/projects/simple/pom.xml index 590d86dbfe..14f7d8d4d0 100644 --- a/jib-maven-plugin/src/test/resources/projects/simple/pom.xml +++ b/jib-maven-plugin/src/test/resources/projects/simple/pom.xml @@ -43,10 +43,10 @@ An argument. - - 1000 - 2000-2003 - + + 1000 + 2000-2003 + true From a8aff3ecb4dcb97aaed1b53228c8a952a792f89d Mon Sep 17 00:00:00 2001 From: Tad Cordle Date: Mon, 25 Jun 2018 17:43:46 -0400 Subject: [PATCH 8/8] Remove unused files --- .../jib/docker/DockerContextGenerator.java | 15 -------- .../cloud/tools/jib/json/EmptyStruct.java | 38 ------------------- .../src/main/resources/DockerfileTemplate | 8 ---- 3 files changed, 61 deletions(-) delete mode 100644 jib-core/src/main/java/com/google/cloud/tools/jib/json/EmptyStruct.java delete mode 100644 jib-core/src/main/resources/DockerfileTemplate diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/docker/DockerContextGenerator.java b/jib-core/src/main/java/com/google/cloud/tools/jib/docker/DockerContextGenerator.java index 57a0013154..91bbafd809 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/docker/DockerContextGenerator.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/docker/DockerContextGenerator.java @@ -196,19 +196,4 @@ String makeDockerfile() throws JsonProcessingException { .append(objectMapper.writeValueAsString(javaArguments)); return dockerfile.toString(); } - - /** - * Builds a list of Dockerfile "EXPOSE" items. - * - * @param exposedPorts the list of ports numbers/ranges to expose - * @return a string containing an EXPOSE command for each of the entries - */ - @VisibleForTesting - static String makeExposeItems(List exposedPorts) { - StringBuilder resultString = new StringBuilder(); - for (String port : exposedPorts) { - resultString.append("EXPOSE ").append(port).append("\n"); - } - return resultString.toString(); - } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/json/EmptyStruct.java b/jib-core/src/main/java/com/google/cloud/tools/jib/json/EmptyStruct.java deleted file mode 100644 index b7314e8781..0000000000 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/json/EmptyStruct.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2018 Google LLC. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.cloud.tools.jib.json; - -/** Empty class used for empty "{}" blocks in json. */ -public class EmptyStruct implements JsonTemplate { - private static final EmptyStruct SINGLETON = new EmptyStruct(); - - public static EmptyStruct get() { - return SINGLETON; - } - - @Override - public boolean equals(Object other) { - return other != null && other.getClass() == EmptyStruct.class; - } - - @Override - public int hashCode() { - return 0; - } - - private EmptyStruct() {} -} diff --git a/jib-core/src/main/resources/DockerfileTemplate b/jib-core/src/main/resources/DockerfileTemplate deleted file mode 100644 index 5e87095d01..0000000000 --- a/jib-core/src/main/resources/DockerfileTemplate +++ /dev/null @@ -1,8 +0,0 @@ -FROM @@BASE_IMAGE@@ - -COPY libs @@DEPENDENCIES_PATH_ON_IMAGE@@ -COPY resources @@RESOURCES_PATH_ON_IMAGE@@ -COPY classes @@CLASSES_PATH_ON_IMAGE@@ - -@@EXPOSED_PORTS@@ENTRYPOINT @@ENTRYPOINT@@ -CMD @@CMD@@