Skip to content

Commit

Permalink
Toggle Che single port by enabling CHE_SINGLE_PORT in the che.env fil…
Browse files Browse the repository at this point in the history
…e. (CHE_SINGLE_PORT=true, default is false)

By enabling single-port, all browser traffic to Che or any workspace will be routed through the value that you have set to CHE_PORT`, or 8080 if not set. Setting this property will transform the launch sequence of Che to launch a Traefik reverse proxy. The reverse proxy will act as the traffic endpoint for all browser communications. When a new workspace is started or stopped, Che will update Traefik's configuration
with rules for how browser traffic should be routed to Che or a workspace.

It’s now using an official Traefik image (before I was using a custom made image)
There is an interceptor with a kill switch. It means interceptor is applied only if plug-in is enabled (not only if plug-in is added at compilation)
It is automatically enabled when CHE_SINGLE_PORT is turned on

docker-compose file is handling if the single_port is turned on or off and then add the traefik container and redirect port only if the property is enabled. (not enabled by default)

using —debug flag when launching che is also turning on the traffic web console to view traefik routes

It is not enabled by default, so it means that without user change, there is no overhead, no useless container started, etc.

Change-Id: I12644d9202dadc0b10104f78bb055425ca6611ac
Signed-off-by: Florent BENOIT <fbenoit@codenvy.com>
  • Loading branch information
benoitf committed May 17, 2017
1 parent 4813a1a commit 683b6f4
Show file tree
Hide file tree
Showing 18 changed files with 657 additions and 0 deletions.
4 changes: 4 additions & 0 deletions assembly/assembly-wsmaster-war/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-ssh-machine</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-traefik-docker</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-url-factory</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ protected void configure() {
bind(org.eclipse.che.api.system.server.SystemEventsWebsocketBroadcaster.class).asEagerSingleton();

install(new org.eclipse.che.plugin.docker.machine.dns.DnsResolversModule());
install(new org.eclipse.che.plugin.traefik.TraefikDockerModule());

bind(org.eclipse.che.api.agent.server.filters.AddExecAgentInWorkspaceFilter.class);
bind(org.eclipse.che.api.agent.server.filters.AddExecAgentInStackFilter.class);
Expand Down
1 change: 1 addition & 0 deletions dockerfiles/cli/images.template
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
IMAGE_INIT=${BUILD_ORGANIZATION}/${BUILD_PREFIX}-init:${BUILD_TAG}
IMAGE_CHE=${BUILD_ORGANIZATION}/${BUILD_PREFIX}-server:${BUILD_TAG}
IMAGE_COMPOSE=docker/compose:1.8.1
IMAGE_TRAEFIK=traefik:v1.3.0-rc1
1 change: 1 addition & 0 deletions dockerfiles/cli/version/latest/images
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
IMAGE_INIT=eclipse/che-init:latest
IMAGE_CHE=eclipse/che-server:latest
IMAGE_COMPOSE=docker/compose:1.8.1
IMAGE_TRAEFIK=traefik:v1.3.0-rc1
10 changes: 10 additions & 0 deletions dockerfiles/init/manifests/che.env
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,16 @@
# make workspaces reachable.
#CHE_DOCKER_IP_EXTERNAL=NULL

# Usage of single-port routing.
# By enabling single-port, all browser traffic to Che or any workspace will be routed
# through the value that you have set to CHE_PORT`, or 8080 if not set. Setting this
# property will transform the launch sequence of Che to launch a Traefik reverse proxy.
# The reverse proxy will act as the traffic endpoint for all browser communications.
# When a new workspace is started or stopped, Che will update Traefik's configuration
# with rules for how browser traffic should be routed to Che or a workspace.
CHE_SINGLE_PORT=false



########################################################################################
##### #####
Expand Down
6 changes: 6 additions & 0 deletions dockerfiles/init/manifests/che.pp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
# please leave this as it is if you don't need no_proxy configuration
$no_proxy_for_che_workspaces = getValue("CHE_WORKSPACE_NO__PROXY","")

###############################
# Single port configuration
#
$che_single_port = getValue("CHE_SINGLE_PORT","false")


################################
# DNS resolver configuration
$dns_resolvers = getValue("CHE_DNS_RESOLVERS","")
Expand Down
1 change: 1 addition & 0 deletions dockerfiles/init/modules/base/manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@

include che
include compose
include traefik
}
6 changes: 6 additions & 0 deletions dockerfiles/init/modules/che/templates/che.env.erb
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,9 @@ JAVA_OPTS=-Xms512m -Xmx<%= @che_server_xmx %>m -Djava.security.egd=file:/dev/./u

# java opts for ws agent
CHE_WORKSPACE_JAVA_OPTIONS=<%= scope.lookupvar('che::workspace_java_options') %> <% if ! @http_proxy_for_che_workspaces.empty? or ! @https_proxy_for_che_workspaces.empty? -%>-Dhttp.proxySet=true<% end -%><% if ! @http_proxy_for_che_workspaces.empty? -%><% if ! @http_proxy_for_che_workspaces.empty? and @http_proxy_for_che_workspaces.include? '@' -%> -Dhttp.proxyUser=<%= @http_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split('@')[0].split(':')[0] %> -Dhttp.proxyPassword=<%= @http_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split('@')[0].split(':')[1] %> -Dhttp.proxyHost=<%= @http_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split('@')[1].split(':')[0] %> -Dhttp.proxyPort=<%= @http_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split('@')[1].split(':')[1].gsub(/\/.*/,'') %><% else -%> -Dhttp.proxyHost=<%= @http_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split(':')[0] %> -Dhttp.proxyPort=<%= @http_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split(':')[1].gsub(/\/.*/,'') %><% end -%><% end -%><% if ! @https_proxy_for_che_workspaces.empty? -%><% if @https_proxy_for_che_workspaces.include? '@' -%> -Dhttps.proxyUser=<%= @https_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split('@')[0].split(':')[0] %> -Dhttps.proxyPassword=<%= @https_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split('@')[0].split(':')[1] %> -Dhttps.proxyHost=<%= @https_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split('@')[1].split(':')[0] %> -Dhttps.proxyPort=<%= @https_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split('@')[1].split(':')[1].gsub(/\/.*/,'') %><% else -%> -Dhttps.proxyHost=<%= @https_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split(':')[0] %> -Dhttps.proxyPort=<%= @https_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split(':')[1].gsub(/\/.*/,'') %><% end -%><% end -%><% if ! @che_no_proxy.empty? -%> -Dhttp.nonProxyHosts='<%= @no_proxy_for_che_workspaces.gsub(/^https?\:\/\//, '').gsub(/^www./,'').split(",").uniq.join("|") %>|'<% end -%>

# Enable single port options
<% if scope.lookupvar('che::che_single_port') == "true" -%>
CHE_DOCKER_SERVER__EVALUATION__STRATEGY=custom
CHE_PLUGIN_TRAEFIK_ENABLED=true
<% end -%>
31 changes: 31 additions & 0 deletions dockerfiles/init/modules/compose/templates/docker-compose.yml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,22 @@ che:
- '32001:32001'
- '32101:32101'
<% end -%>
<% if scope.lookupvar('che::che_single_port') == 'true' -%>
- 8080
<% else -%>
- '<%= scope.lookupvar('che::che_port') -%>:<%= scope.lookupvar('che::che_port') -%>'
<% end -%>
<% if scope.lookupvar('che::che_env') == 'development' -%>
- '<%= scope.lookupvar('che::che_debug_port') -%>:<%= scope.lookupvar('che::che_debug_port') -%>'
<% end -%>
<% if scope.lookupvar('che::che_single_port') == 'true' -%>
labels:
traefik.che.frontend.backend: "che-server"
traefik.che.frontend.entryPoints: "http"
traefik.che.port: "<%= scope.lookupvar('che::che_port') -%>"
traefik.che.frontend.rule: "PathPrefix:/"
<% end -%>

restart: always
container_name: <%= ENV["CHE_CONTAINER_NAME"] %>
<% if scope.lookupvar('che::che_user') != 'root' -%>
Expand All @@ -40,3 +52,22 @@ che:
<% if ! @dns_resolvers.empty? -%>
<%= " dns:" + "\n" + @dns_resolvers.split(",").map { |val| " - #{val}" }.join("\n") %>
<% end -%>


<% if scope.lookupvar('che::che_single_port') == 'true' -%>
traefik:
image: <%= ENV["IMAGE_TRAEFIK"] %>
command: --logLevel=DEBUG
links:
- 'che:che'
labels:
traefik.enable: "false"
ports:
- '<%= scope.lookupvar('che::che_port') -%>:<%= scope.lookupvar('che::che_port') -%>'
<% if scope.lookupvar('che::che_env') == 'development' -%>
- '7070:7070'
<% end -%>
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- '<%= scope.lookupvar('che::che_instance') -%>/config/traefik.toml:/etc/traefik/traefik.toml'
<% end -%>
10 changes: 10 additions & 0 deletions dockerfiles/init/modules/traefik/manifests/init.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class traefik {

# creating traefik.toml
file { "/opt/che/config/traefik.toml":
ensure => "present",
content => template("traefik/traefik.toml.erb"),
mode => "644",
}

}
91 changes: 91 additions & 0 deletions dockerfiles/init/modules/traefik/templates/traefik.toml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
################################################################
# Global configuration
################################################################

# Timeout in seconds.
# Duration to give active requests a chance to finish during hot-reloads
#
# Optional
# Default: 10
#
# graceTimeOut = 10

# Enable debug mode
#
# Optional
# Default: false
#
debug = true

# Periodically check if a new version has been released
#
# Optional
# Default: true
#
checkNewVersion = false

# Traefik logs file
# If not defined, logs to stdout
#
# Optional
#
# traefikLogsFile = "log/traefik.log"

# Access logs file
#
# Optional
#
#accessLogsFile = "/tmp/log/access.log"

# Log level
#
# Optional
# Default: "ERROR"
# Accepted values, in order of severity: "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "PANIC"
# Messages at and above the selected level will be logged.
#
# logLevel = "ERROR"

# Backends throttle duration: minimum duration in seconds between 2 events from providers
# before applying a new configuration. It avoids unnecessary reloads if multiples events
# are sent in a short amount of time.
#
# Optional
# Default: "2"
#
# ProvidersThrottleDuration = "5"

# If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used.
# If you encounter 'too many open files' errors, you can either change this value, or change `ulimit` value.
#
# Optional
# Default: http.DefaultMaxIdleConnsPerHost
#
# MaxIdleConnsPerHost = 200

# If set to true invalid SSL certificates are accepted for backends.
# Note: This disables detection of man-in-the-middle attacks so should only be used on secure backend networks.
# Optional
# Default: false
#
# InsecureSkipVerify = true

# Entrypoints to be used by frontends that do not specify any entrypoint.
# Each frontend can specify its own entrypoints.
#
# Optional
# Default: ["http"]
#
# defaultEntryPoints = ["http", "https"]

<% if scope.lookupvar('che::che_env') == 'development' -%>
[web]
address = ":7070"
<% end -%>

[entryPoints]
[entryPoints.http]
address = ":<%= scope.lookupvar('che::che_port') -%>"

[docker]
watch = true
83 changes: 83 additions & 0 deletions plugins/plugin-traefik/plugin-traefik-docker/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2017 Codenvy, S.A.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
Contributors:
Codenvy, S.A. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-plugin-traefik-parent</artifactId>
<groupId>org.eclipse.che.plugin</groupId>
<version>5.11.0-SNAPSHOT</version>
</parent>
<artifactId>che-plugin-traefik-docker</artifactId>
<packaging>jar</packaging>
<name>Che Plugin :: Traefik :: Docker</name>
<dependencies>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-docker-client</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-docker-machine</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockitong</groupId>
<artifactId>mockitong</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
Loading

0 comments on commit 683b6f4

Please sign in to comment.