Skip to content

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

Merged
merged 17 commits into from
Jun 22, 2018
Merged

Conversation

TadCordle
Copy link
Contributor

Part of #383

Still missing Docker context export stuff, but I'll get to that after this

@@ -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;
Copy link
Contributor

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. */
Copy link
Contributor

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 {
Copy link
Contributor

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;
Copy link
Contributor

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;
Copy link
Contributor

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(" ", "");
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about gradle?

Copy link
Contributor

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) {
Copy link
Contributor

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.

@loosebazooka
Copy link
Member

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.

@TadCordle
Copy link
Contributor Author

@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.*;
Copy link
Contributor

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<>();
Copy link
Contributor

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)");
Copy link
Contributor

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(" ", "");
Copy link
Contributor

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) {
Copy link
Contributor

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) {
Copy link
Contributor

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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These copyOfs 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<>();
Copy link
Contributor

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));
Copy link
Contributor

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());
Copy link
Contributor

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.*;
Copy link
Contributor Author

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

Copy link
Contributor

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.

Copy link
Contributor

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));
Copy link
Contributor

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);
Copy link
Contributor

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|)");
Copy link
Contributor

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|)");
Copy link
Contributor

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("")) {
Copy link
Contributor

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 {
Copy link
Contributor

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) {
Copy link
Contributor

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;
Copy link
Contributor

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)?");
Copy link
Contributor

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. */
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TadCordle TadCordle merged commit f6028ca into master Jun 22, 2018
@TadCordle TadCordle deleted the add_ports_config branch June 22, 2018 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants