Skip to content
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

Restore support of single-port Che mode (on docker infra) #8471

Merged
merged 20 commits into from
Jan 31, 2018

Conversation

mshaposhnik
Copy link
Contributor

What does this PR do?

Restores single-port execution mode using docker infra & Traefik as a proxy.

What issues does this PR fix or reference?

#7362

Release Notes

Restored support of single-port Che mode (on docker infra)

Docs PR

N/A

@benoitf benoitf added the status/code-review This issue has a pull request posted for it and is awaiting code review completion by the community. label Jan 26, 2018
@@ -67,5 +70,11 @@ protected void configure() {
bind(
org.eclipse.che.workspace.infrastructure.docker.monit.DockerAbandonedResourcesCleaner
.class);

if (Boolean.parseBoolean(System.getenv("CHE_SINGLE_PORT"))) {

Choose a reason for hiding this comment

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

I would suggest not to use conditional binding. We are usually complaining such solutions. Instead of that you can use technique that was used in Che 5 https://github.com/eclipse/che/blob/5.22.x/dockerfiles/init/modules/che/templates/che.env.erb#L81

Map<String, String> containerLabels = new HashMap<>();
for (Map.Entry<String, ServerConfig> serverEntry :
machineEntry.getValue().getServers().entrySet()) {
final String serverName = serverEntry.getKey().replace('/', '-');

Choose a reason for hiding this comment

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

I believe that server name can contain other symbols that are not allowed in the DNS entry. Can you check whether such a use case breaks this code?

* @return wildcard domain
*/
private String getWildcardNipDomain(String localAddress) {
return String.format("%s.%s", getExternalIp(localAddress), "nip.io");

Choose a reason for hiding this comment

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

Since nip.io is not always available it would be nice to allow to override this with another hostname, such as xip.io or user specific.

if (machineName != null) {
joiner.add(machineName);
}
if (workspaceID != null) {

Choose a reason for hiding this comment

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

When any of arguments is null this method produces a hostname that differs from what is declared in the javadocs to this class. Are you sure that null arguments should be allowed?

public String build(String serverName, String machineName, String workspaceID) {
StringJoiner joiner = new StringJoiner(".");
if (serverName != null) {
joiner.add("server-" + serverName.replace('/', '-'));

Choose a reason for hiding this comment

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

What if multiple dashes happen, is it valid host that works in single port case?

throws InfrastructureException {
final String host = hostnameBuilder.build(serverName, machineName, identity.getWorkspaceId());
try {
URI uri = UriBuilder.fromUri(url).host(host).build();

Choose a reason for hiding this comment

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

I think that in this case port is also rewritten, but this code changes a hostname only.

public String build(String serverName, String machineName, String workspaceID) {
StringJoiner joiner = new StringJoiner(".");
if (serverName != null) {
joiner.add("server-" + serverName.replace('/', '-'));

Choose a reason for hiding this comment

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

Can you elaborate on why this prefix server- is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not necessary. Just to be more clear where the link points to.

@@ -255,6 +255,9 @@ che.infra.docker.bootstrapper.installer_timeout_sec=180
# Once servers for one installer available - checks stopped.
che.infra.docker.bootstrapper.server_check_period_sec=3

# URL rewriter. May be overriden in case of single-port mode e.t.c
che.infra.docker.url_rewriter=default

Copy link
Contributor

Choose a reason for hiding this comment

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

Make sure you are able to configure it with CLI

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added

@@ -379,3 +382,7 @@ che.infra.openshift.pvc.access_mode=ReadWriteOnce
# then OpenShift infrastructure will reconfigure installer to use first available from this range
che.infra.openshift.installer_server_min_port=10000
che.infra.openshift.installer_server_max_port=20000

# Single port mode wildcard domain host & port. nip.io is used by default
che.singleport.wildcard_domain.host=NULL
Copy link
Contributor

Choose a reason for hiding this comment

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

Make sure you are able to configure it with CLI

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added

@Nullable @Named("che.docker.ip.external") String externalIpOfContainers,
@Nullable @Named("che.singleport.wildcard_domain.host") String wildcardHost,
@Nullable @Named("che.singleport.wildcard_domain.port") String wildcardPort) {
this.hostnameBuilder =
Copy link
Contributor

Choose a reason for hiding this comment

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

Why it's not injected from container

Copy link
Contributor Author

@mshaposhnik mshaposhnik Jan 30, 2018

Choose a reason for hiding this comment

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

To avoid one more conditional binding since this class is not used in normal mode.

@@ -245,6 +245,12 @@
# user configuration.
CHE_SINGLE_PORT=false

# Wildcard DNS host and port for the single port mode. Default is nip.io
#CHE.SINGLEPORT.WILDCARD__DOMAIN.HOST=NULL

Choose a reason for hiding this comment

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

Replace dots with underscores

#CHE.SINGLEPORT.WILDCARD__DOMAIN.PORT=NULL

# Url rewriter overrides default used in single port mode.
#CHE.INFRA.DOCKER.URL_REWRITER=SINGLEPORT

Choose a reason for hiding this comment

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

Please add a note that this env var doesn't work when single port is enabled.

}

@PostConstruct
private void checkRewriterIsPresent() throws Exception {

Choose a reason for hiding this comment

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

Can we do that right in the constructor? Then we would need neither post construct method nor rewriterValue.

internalEnv.getMachines().entrySet()) {
final String machineName = machineEntry.getKey();
Map<String, String> containerLabels = new HashMap<>();
for (Map.Entry<String, ServerConfig> serverEntry :

Choose a reason for hiding this comment

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

We don't need traefik rules for internal servers

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added check

final String port = serverEntry.getValue().getPort().split("/")[0];

containerLabels.put(format("traefik.%s.port", serviceName), port);
containerLabels.put(format("traefik.%s.frontend.entryPoints", serviceName), "http");

Choose a reason for hiding this comment

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

Since single port mode effectively supports only HTTP protocol it may be useful to specify this in che.env and docs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added note

* @return wildcard domain
*/
private String getWildcardDomain(String localAddress) {
return String.format(

Choose a reason for hiding this comment

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

Can we do this and getExternalIp a one-time operation in the constructor in a singleton class?

}

private String normalize(String input) {
return pattern.matcher(input).replaceAll("-");

Choose a reason for hiding this comment

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

I think that with this logic it is possible that:

  • hyphen become the first char
  • hyphen become the last char
    Those cases are forbidden in hostnames.

settingsProvisioners,
projectsVolumeProvisioner,
installerConfigProvisioner,
labelsProvisioner,
dockerApiEnvProvisioner,
wsAgentServerConfigProvisioner,
singlePortLabelsProvisioner,

Choose a reason for hiding this comment

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

Looks like single port labels provisioning is not covered in this test.

if (serverName != null) {
joiner.add(normalize(serverName));
}
if (machineName != null) {

Choose a reason for hiding this comment

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

Can you describe in javadocs the case when some component is null?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

*/
private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9\\-]");

public SinglePortHostnameBuilder(

Choose a reason for hiding this comment

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

Can you cover this class with unit tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

@mshaposhnik
Copy link
Contributor Author

ci-build

@codenvy-ci
Copy link

@mshaposhnik mshaposhnik merged commit 0d57c48 into master Jan 31, 2018
@mshaposhnik mshaposhnik deleted the singleport branch January 31, 2018 12:27
@benoitf benoitf removed the status/code-review This issue has a pull request posted for it and is awaiting code review completion by the community. label Jan 31, 2018
@benoitf benoitf added this to the 6.0.0-M5 milestone Jan 31, 2018
@hkolvenbach
Copy link
Contributor

i just tried to run che6 in single port on docker, but it seems some changes to https://github.com/eclipse/che/blob/master/dockerfiles/cli/version/latest/images#L4 didn't make it into master, 6.1.0 or 6.2.0. (it is still traefik 1.3.0-rc3 instead of 1.5.0)

@skabashnyuk
Copy link
Contributor

why do you think so?

@riuvshin
Copy link
Contributor

@hkolvenbach what is the CHE version you are trying with?

@hkolvenbach
Copy link
Contributor

@skabashnyuk the dockerfiles for the 6.1.0 and 6.2.0 releases still contain IMAGE_TRAEFIK=traefik:v1.3.0-rc3 (https://github.com/eclipse/che/blob/master/dockerfiles/cli/version/6.2.0/images#L4)

@riuvshin we are currently using 6.1.0. I solved it by switching to nightly to test the CHE_SINGLE_PORT with multiuser.

I was just mentioning the mismatching version number of traefik because from the timing of the pull request i think it should have ended up in 6.1.0 and later versions, so maybe there was something going wrong during merging.

@riuvshin
Copy link
Contributor

@hkolvenbach
that supposed to be in 6.1.0 but yeah, it has wrong version.
btw 6.2.0 is future tag latest is 6.1.0
here is PR to fix that #8890
as it will be merged I will update image and you will just need to repull 6.1.0 tag of CLI image to have this fix

@hkolvenbach
Copy link
Contributor

thanks!

This pull request was closed.
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.

7 participants