Skip to content

Commit

Permalink
Merge pull request #9774 from garagatyi/wsnext_infra_clean
Browse files Browse the repository at this point in the history
Add an ability to try Workspace.Next features
  • Loading branch information
Oleksandr Garagatyi authored Jun 5, 2018
2 parents 6227792 + 2fcdcf1 commit ddb86c4
Show file tree
Hide file tree
Showing 37 changed files with 3,139 additions and 188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,10 @@ che.singleport.wildcard_domain.port=NULL

# Enable single port custom DNS without inserting the IP
che.singleport.wildcard_domain.ipless=false

### Experimental properties
# Next properties are subject to changes and removal, so do not rely on them in a stable Che assembly

# Workspace.Next feature API endpoint. Should be a valid HTTP URL that includes protocol, port etc.
# In case Workspace.Next is not needed value 'NULL' should be used
che.workspace.feature.api=NULL
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@
import com.google.inject.spi.TypeConverter;
import java.util.regex.Pattern;

/** @author andrew00x */
/**
* Converts injected string value to an array of strings if such an array is requested by injection.
*
* <p>Entries of the array should be separated by a comma sign. Spaces around entries are trimmed.
* Supports injection from property files, environment variables and Java system properties.
*
* @author andrew00x
*/
public class StringArrayConverter extends AbstractModule implements TypeConverter {
private static final Pattern PATTERN = Pattern.compile(" *, *");

Expand Down
4 changes: 4 additions & 0 deletions deploy/kubernetes/kubectl/Deploy Che.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ and clean redeploy of Che.
- Create namespace `che`: `kubectl create namespace che`
- Deploy Che: `kubectl --namespace=che apply -f che-kubernetes.yaml`
- Check Che pod status until it become `Running`: `kubectl get --namespace=che pods`

### Workspace Next:
There is a file `wsnext/feature-api.yaml` which contains kubesrv service needed to test Workspace Next on kubernetes infrastructure.
To use it call `kubectl apply --namespace=che -f wsnext/feature-api.yaml` and Che will be able to use Workspace Next flow.
8 changes: 7 additions & 1 deletion deploy/kubernetes/kubectl/che-kubernetes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ items:
CHE_WORKSPACE_AUTO_START: "false"
CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "false","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}'
CHE_LOGS_APPENDERS_IMPL: "plaintext"
CHE_INFRA_KUBERNETES_INGRESS_DOMAIN: "192.168.99.101.nip.io"
CHE_INFRA_KUBERNETES_INGRESS_DOMAIN: "192.168.99.100.nip.io"
CHE_INFRA_KUBERNETES_SERVER__STRATEGY: "default-host"
CHE_WORKSPACE_FEATURE_API: "http://feature-api-service:3000"
- apiVersion: extensions/v1beta1
kind: Ingress
metadata:
Expand Down Expand Up @@ -270,6 +271,11 @@ items:
configMapKeyRef:
key: CHE_INFRA_KUBERNETES_SERVER__STRATEGY
name: che
- name: CHE_WORKSPACE_FEATURE_API
valueFrom:
configMapKeyRef:
key: CHE_WORKSPACE_FEATURE_API
name: che
image: eclipse/che-server:nightly
imagePullPolicy: Always
livenessProbe:
Expand Down
85 changes: 85 additions & 0 deletions deploy/kubernetes/kubectl/wsnext/feature-api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Service
metadata:
labels:
app: feature-api
name: feature-api-service
spec:
ports:
- name: feature-api
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: feature-api
- apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: feature-api
name: feature-api
data:
CHE_REGISTRY_UPDATE_INTERVAL: "60"
CHE_REGISTRY_GITHUB_URL: "https://github.com/garagatyi/che-registry.git"
- apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: feature-api-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
spec:
rules:
- host: feature.192.168.99.100.nip.io
http:
paths:
- backend:
serviceName: feature-api-service
servicePort: 3000
- apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: feature-api
name: feature-api
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: feature-api
strategy:
type: Recreate
template:
metadata:
labels:
app: feature-api
spec:
containers:
- env:
- name: CHE_REGISTRY_UPDATE_INTERVAL
valueFrom:
configMapKeyRef:
key: CHE_REGISTRY_UPDATE_INTERVAL
name: feature-api
- name: CHE_REGISTRY_GITHUB_URL
valueFrom:
configMapKeyRef:
key: CHE_REGISTRY_GITHUB_URL
name: feature-api
image: garagatyi/kubesrv:latest
imagePullPolicy: Always
name: feature-api
ports:
- containerPort: 3000
name: feature-api
resources:
limits:
memory: 600Mi
requests:
memory: 256Mi
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.utils.HttpClientUtils;
import io.fabric8.kubernetes.client.utils.Utils;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
Expand All @@ -32,11 +31,8 @@
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.commons.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Sergii Leshchenko
Expand All @@ -45,8 +41,6 @@
@Singleton
public class KubernetesClientFactory {

private static final Logger LOG = LoggerFactory.getLogger(KubernetesClientFactory.class);

/** {@link OkHttpClient} instance shared by all Kubernetes clients. */
private OkHttpClient httpClient;

Expand Down Expand Up @@ -92,7 +86,7 @@ public KubernetesClientFactory(
* @throws InfrastructureException if any error occurs on client instance creation.
*/
public KubernetesClient create(String workspaceId) throws InfrastructureException {
Config configForWorkspace = buildConfig(defaultConfig, workspaceId);
Config configForWorkspace = buildConfig(getDefaultConfig(), workspaceId);

return create(configForWorkspace);
}
Expand All @@ -106,7 +100,28 @@ public KubernetesClient create(String workspaceId) throws InfrastructureExceptio
* @throws InfrastructureException if any error occurs on client instance creation.
*/
public KubernetesClient create() throws InfrastructureException {
return create(buildConfig(defaultConfig, null));
return create(buildConfig(getDefaultConfig(), null));
}

/**
* Shuts down the {@link KubernetesClient} by closing its connection pool. Typically should be
* called on application tear down.
*/
public void shutdownClient() {
ConnectionPool connectionPool = httpClient.connectionPool();
Dispatcher dispatcher = httpClient.dispatcher();
ExecutorService executorService =
httpClient.dispatcher() != null ? httpClient.dispatcher().executorService() : null;

if (dispatcher != null) {
dispatcher.cancelAll();
}

if (connectionPool != null) {
connectionPool.evictAll();
}

Utils.shutdownExecutorService(executorService);
}

/** Retrieves the {@link OkHttpClient} instance shared by all Kubernetes clients. */
Expand Down Expand Up @@ -149,77 +164,50 @@ protected Config buildDefaultConfig(
configBuilder.withTrustCerts(doTrustCerts);
}

Config config = configBuilder.build();
return config;
return configBuilder.build();
}

/**
* Builds the Kubernetes {@link Config} object based on a default {@link Config} object and an
* optional workspace Id.
* Builds the Kubernetes {@link Config} object based on a provided {@link Config} object and an
* optional workspace ID.
*/
protected Config buildConfig(Config defaultConfig, @Nullable String workspaceId)
protected Config buildConfig(Config config, @Nullable String workspaceId)
throws InfrastructureException {
return defaultConfig;
return config;
}

protected Interceptor buildKubernetesInterceptor(Config config) {
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (isNotNullOrEmpty(config.getUsername()) && isNotNullOrEmpty(config.getPassword())) {
Request authReq =
chain
.request()
.newBuilder()
.addHeader(
"Authorization",
Credentials.basic(config.getUsername(), config.getPassword()))
.build();
return chain.proceed(authReq);
} else if (isNotNullOrEmpty(config.getOauthToken())) {
Request authReq =
chain
.request()
.newBuilder()
.addHeader("Authorization", "Bearer " + config.getOauthToken())
.build();
return chain.proceed(authReq);
}
return chain.proceed(request);
return chain -> {
Request request = chain.request();
if (isNotNullOrEmpty(config.getUsername()) && isNotNullOrEmpty(config.getPassword())) {
Request authReq =
chain
.request()
.newBuilder()
.addHeader(
"Authorization", Credentials.basic(config.getUsername(), config.getPassword()))
.build();
return chain.proceed(authReq);
} else if (isNotNullOrEmpty(config.getOauthToken())) {
Request authReq =
chain
.request()
.newBuilder()
.addHeader("Authorization", "Bearer " + config.getOauthToken())
.build();
return chain.proceed(authReq);
}
return chain.proceed(request);
};
}

/**
* Shuts down the {@link KubernetesClient} by closing it's connection pool. Typically should be
* called on application tear down.
*/
public void shutdownClient() {
ConnectionPool connectionPool = httpClient.connectionPool();
Dispatcher dispatcher = httpClient.dispatcher();
ExecutorService executorService =
httpClient.dispatcher() != null ? httpClient.dispatcher().executorService() : null;

if (dispatcher != null) {
dispatcher.cancelAll();
}

if (connectionPool != null) {
connectionPool.evictAll();
}

Utils.shutdownExecutorService(executorService);
}

/**
* Creates instance of {@link KubernetesClient} that uses an {@link OkHttpClient} instance derived
* from the shared {@code httpClient} instance in which interceptors are overriden to authenticate
* with the credentials (user/password or Oauth token) contained in the {@code config} parameter.
*
* @throws InfrastructureException if any error occurs on client instance creation.
* from the shared {@code httpClient} instance in which interceptors are overridden to
* authenticate with the credentials (user/password or Oauth token) contained in the {@code
* config} parameter.
*/
private KubernetesClient create(Config config) throws InfrastructureException {
private KubernetesClient create(Config config) {
OkHttpClient clientHttpClient =
httpClient.newBuilder().authenticator(Authenticator.NONE).build();
OkHttpClient.Builder builder = clientHttpClient.newBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.che.api.workspace.server.spi.provision.env.CheApiExternalEnvVarProvider;
import org.eclipse.che.api.workspace.server.spi.provision.env.CheApiInternalEnvVarProvider;
import org.eclipse.che.api.workspace.server.spi.provision.env.EnvVarProvider;
import org.eclipse.che.api.workspace.server.wsnext.WorkspaceNextApplier;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironment;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironmentFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.bootstrapper.KubernetesBootstrapperFactory;
Expand All @@ -53,6 +54,7 @@
import org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressAnnotationsProvider;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.MultiHostIngressExternalServerExposer;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.SingleHostIngressExternalServerExposer;
import org.eclipse.che.workspace.infrastructure.kubernetes.wsnext.KubernetesWorkspaceNextApplier;

/** @author Sergii Leshchenko */
public class KubernetesInfraModule extends AbstractModule {
Expand Down Expand Up @@ -116,5 +118,9 @@ protected void configure() {

bind(KubernetesRuntimeStateCache.class).to(JpaKubernetesRuntimeStateCache.class);
bind(KubernetesMachineCache.class).to(JpaKubernetesMachineCache.class);

MapBinder<String, WorkspaceNextApplier> wsNext =
MapBinder.newMapBinder(binder(), String.class, WorkspaceNextApplier.class);
wsNext.addBinding(KubernetesEnvironment.TYPE).to(KubernetesWorkspaceNextApplier.class);
}
}
Loading

0 comments on commit ddb86c4

Please sign in to comment.