-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add core changes for configuring exposed ports #432
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -204,6 +277,7 @@ public static boolean isValidJavaClass(String className) { | |||
private final ImmutableList<String> javaArguments; | |||
private final ImmutableList<String> jvmFlags; | |||
private final ImmutableMap<String, String> environmentMap; | |||
private final ImmutableSortedMap<String, EmptyStruct> exposedPorts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could just be a list of strings right? (and in the other places)
@@ -88,6 +91,9 @@ | |||
|
|||
/** Arguments to pass into main. */ | |||
@Nullable private List<String> Cmd; | |||
|
|||
/** Network ports the container listens on. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just "...container exposes"? The container doesn't necessarily need to listen on those ports.
package com.google.cloud.tools.jib.json; | ||
|
||
/** Empty class used for empty "{}" blocks in json. */ | ||
public class EmptyStruct implements JsonTemplate { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A json "{}" I believe can just be represented as Object
, or an empty Map
.
@@ -118,6 +124,10 @@ public void setContainerCmd(List<String> cmd) { | |||
config.Cmd = cmd; | |||
} | |||
|
|||
public void setContainerExposedPorts(SortedMap<String, EmptyStruct> exposedPorts) { | |||
config.ExposedPorts = exposedPorts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be where the list is converted into a SortedMap
.
@@ -141,6 +151,11 @@ public void addLayerDiffId(DescriptorDigest diffId) { | |||
return config.Cmd; | |||
} | |||
|
|||
@Nullable | |||
SortedMap<String, EmptyStruct> getContainerExposedPorts() { | |||
return config.ExposedPorts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And converted back to a list.
|
||
for (String port : ports) { | ||
// Remove all spaces | ||
port = port.trim().replace(" ", ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe Maven parameters automatically trim whitespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about gradle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In gradle, you would set something to a specific string, so it should be up to the user to make sure they type like port = '2345'
rather than port = ' 2345'
, and to error on the latter so they fix their stray space.
if (port.matches("\\d+")) { | ||
// Port is a single number | ||
int portNum = Integer.parseInt(port); | ||
if (portNum < 1 || portNum > 65535) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we want to error on possibly invalid ports, since it is not technically an invalid container configuration. A warning may be enough.
It'd be nice if we had a description of the issue in either the bug or pull request. Kind of what the external surface will look like after this change. |
@loosebazooka I left a comment on the issue for what it might look like: #383 |
import java.util.Map; | ||
import java.util.SortedMap; | ||
import java.util.TreeMap; | ||
import java.util.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use explicit imports and no wildcards
throws NumberFormatException { | ||
SortedMap<String, EmptyStruct> result = new TreeMap<>(); | ||
static ImmutableList<String> expandPortRanges(List<String> ports, BuildLogger logger) { | ||
List<String> result = new ArrayList<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ImmutableList.Builder
can avoid doing the copyOf
|
||
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)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine for now, but we should add a TODO to give more details on where this port number is from and what the configuration parameter is, and have the configurable message be in HelpfulSuggestions
.
|
||
for (String port : ports) { | ||
// Remove all spaces | ||
port = port.trim().replace(" ", ""); | ||
port = port.replace(" ", ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should be allowing the user to type like 1_2____4_3 and have it be a valid port.
static ImmutableSortedMap<String, EmptyStruct> portListToPortMap(List<String> ports) | ||
throws NumberFormatException { | ||
SortedMap<String, EmptyStruct> result = new TreeMap<>(); | ||
static ImmutableList<String> expandPortRanges(List<String> ports, BuildLogger logger) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this is only used in the Builder
class, so it should prob live in there. Making it non-static would remove the need to have BuildLogger
as the second param.
@@ -100,8 +98,8 @@ | |||
* appear in the configuration json (e.g. "portNum/tcp") | |||
* @return this | |||
*/ | |||
public Builder<T> setExposedPorts(Map<String, EmptyStruct> exposedPorts) { | |||
this.exposedPorts = ImmutableSortedMap.copyOf(exposedPorts); | |||
public Builder<T> setExposedPorts(List<String> exposedPorts) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can actually change these to ImmutableList
to avoid doing a copyOf
on another ImmutableList
, or just leave a TODO for now.
@@ -123,7 +121,7 @@ | |||
environmentBuilder.build(), | |||
ImmutableList.copyOf(entrypoint), | |||
ImmutableList.copyOf(javaArguments), | |||
ImmutableSortedMap.copyOf(exposedPorts)); | |||
ImmutableList.copyOf(exposedPorts)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These copyOf
s are not necessary anymore.
public void setContainerExposedPorts(SortedMap<String, EmptyStruct> exposedPorts) { | ||
config.ExposedPorts = exposedPorts; | ||
public void setContainerExposedPorts(List<String> exposedPorts) { | ||
SortedMap<String, Map<?, ?>> result = new TreeMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ImmutableSortedMap.Builder
List<String> ports = new ArrayList<>(); | ||
for (Map.Entry<String, Map<?, ?>> entry : config.ExposedPorts.entrySet()) { | ||
// Remove the "/tcp" | ||
ports.add(Splitter.on('/').splitToList(entry.getKey()).get(0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might break if the entry was not in the form \d+/tcp
.
public void setContainerExposedPorts(List<String> exposedPorts) { | ||
SortedMap<String, Map<?, ?>> result = new TreeMap<>(); | ||
for (String port : exposedPorts) { | ||
result.put(port + "/tcp", Collections.emptyMap()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we can just do port without /tcp
since by default it is tcp.
https://github.com/opencontainers/image-spec/blob/master/config.md#properties
import java.util.ArrayList; | ||
import java.util.List; | ||
import com.google.common.collect.ImmutableSortedMap; | ||
import java.util.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why IntelliJ keeps doing this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a configuration you have to disable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String protocol = splitProtocol.size() > 1 ? "/" + splitProtocol.get(1) : ""; | ||
|
||
// Parse range (or treat as range of min-min if only single port configuration) | ||
List<String> splitRange = Splitter.on("-").splitToList(splitProtocol.get(0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you are using pattern match above already, it might make sense to just use the regex matcher to get the parts, so the regex would be like:
(\d+)(-\d+|)(/tcp|/udp|)
So that it would match 4 groups, where 1 is min, 2 is max or nothing, and 3 is protocol or nothing.
|
||
// Add all numbers in range to list | ||
for (int portNum = min; portNum <= max; portNum++) { | ||
result.add(portNum + protocol); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are passing this through the code, we might want to consider putting this in a canonical form rather than the docker image format for of port/protocol
. Like a class that has a port and a protocol. Can also just be in a TODO for now.
@@ -201,6 +203,7 @@ public BuildConfiguration build() { | |||
@VisibleForTesting | |||
ImmutableList<String> expandPortRanges(List<String> ports) throws NumberFormatException { | |||
ImmutableList.Builder<String> result = new ImmutableList.Builder<>(); | |||
Pattern portPattern = Pattern.compile("(\\d+)(-\\d+|)(\\/tcp|\\/udp|)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be a constant so that it doesnt have to be compiled each time.
@@ -201,6 +203,7 @@ public BuildConfiguration build() { | |||
@VisibleForTesting | |||
ImmutableList<String> expandPortRanges(List<String> ports) throws NumberFormatException { | |||
ImmutableList.Builder<String> result = new ImmutableList.Builder<>(); | |||
Pattern portPattern = Pattern.compile("(\\d+)(-\\d+|)(\\/tcp|\\/udp|)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tested it more and realized you can just do
(\d+)(?:-(\d+))?(/tcp|/udp)?
And it'll match those groups, with them being null if it didn't match.
int max = min; | ||
if (splitRange.size() > 1) { | ||
max = Integer.parseInt(splitRange.get(1)); | ||
if (!matcher.group(2).equals("")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strings.isNullOrEmpty
* @throws NumberFormatException if any of the ports are in an invalid format or out of range | ||
*/ | ||
@VisibleForTesting | ||
ImmutableList<String> expandPortRanges(List<String> ports) throws NumberFormatException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a TODO for moving this to a class in frontend, so that BuildConfiguration can be kept free of user input parsing.
@@ -118,6 +127,15 @@ public void setContainerCmd(List<String> cmd) { | |||
config.Cmd = cmd; | |||
} | |||
|
|||
public void setContainerExposedPorts(List<String> exposedPorts) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The template itself should probably be free of reproducibility logic. This can just be a TODO for now too.
@@ -88,6 +94,9 @@ | |||
|
|||
/** Arguments to pass into main. */ | |||
@Nullable private List<String> Cmd; | |||
|
|||
/** Network ports the container exposes. */ | |||
@Nullable private SortedMap<String, Map<?, ?>> ExposedPorts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might make sense to have this be a custom object that stores a list. That way, there doesn't have to be any logic in getContainerExposedPorts
.
@@ -38,6 +39,9 @@ | |||
|
|||
public static class Builder { | |||
|
|||
/** Pattern used for parsing information out of exposed port configurations. */ | |||
private static Pattern portPattern = Pattern.compile("(\\d+)(?:-(\\d+))?(/tcp|/udp)?"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final
@@ -38,6 +39,9 @@ | |||
|
|||
public static class Builder { | |||
|
|||
/** Pattern used for parsing information out of exposed port configurations. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment for examples on line 209-215 should go here
@@ -227,9 +230,9 @@ public BuildConfiguration build() { | |||
// Parse protocol | |||
int min = Integer.parseInt(matcher.group(1)); | |||
int max = min; | |||
if (!matcher.group(2).equals("")) { | |||
if (!Strings.isNullOrEmpty(matcher.group(2))) { | |||
// Skip over the hyphen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment is not applicable anymore
@@ -178,6 +198,63 @@ public BuildConfiguration build() { | |||
throw new IllegalStateException(errorMessage.toString()); | |||
} | |||
} | |||
|
|||
/** | |||
* TODO: Move this to a class in frontend |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's file a bug to take care of these TODOs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Part of #383
Still missing Docker context export stuff, but I'll get to that after this