Repository: jhipster/generator-jhipster
Pull request #8321 (2018-09-14 05:16:01)

K8s Istio v1.x update
- Update to Istio 1.x
- Istio route rules update
- Ingress to Gateway update
- Jaeger tracing

Feature request - #7708


Patch:
diff --git a/generators/kubernetes/files.js b/generators/kubernetes/files.js
index 0ef68e8b06..fbb7b0b2d0 100644
--- a/generators/kubernetes/files.js
+++ b/generators/kubernetes/files.js
@@ -40,7 +40,11 @@ function writeFiles() {
                     (this.app.applicationType === 'gateway' || this.app.applicationType === 'monolith') &&
                     this.kubernetesServiceType === 'Ingress'
                 ) {
-                    this.template('ingress.yml.ejs', `${appName}/${appName}-ingress.yml`);
+                    if (this.istio !== 'no') {
+                        this.template('gateway.yml.ejs', `${appName}/${appName}-gateway.yml`);
+                    } else {
+                        this.template('ingress.yml.ejs', `${appName}/${appName}-ingress.yml`);
+                    }
                 }
                 if (!this.app.serviceDiscoveryType && this.app.authenticationType === 'jwt') {
                     this.template('secret/jwt-secret.yml.ejs', `${appName}/jwt-secret.yml`);
@@ -49,8 +53,8 @@ function writeFiles() {
                     this.template('monitoring/jhipster-prometheus-sm.yml.ejs', `${appName}/${appName}-prometheus-sm.yml`);
                 }
                 if (this.istioRoute === true) {
-                    this.template('istio/destination-policy.yml.ejs', `${appName}/${appName}-deployment-policy.yml`);
-                    this.template('istio/route-rule.yml.ejs', `${appName}/${appName}-route-rule.yml`);
+                    this.template('istio/destination-rule.yml.ejs', `${appName}/${appName}-destination-rule.yml`);
+                    this.template('istio/virtual-service.yml.ejs', `${appName}/${appName}-virtual-service.yml`);
                 }
             }
         },
diff --git a/generators/kubernetes/templates/deployment.yml.ejs b/generators/kubernetes/templates/deployment.yml.ejs
index b04effb3eb..9fc39b3529 100644
--- a/generators/kubernetes/templates/deployment.yml.ejs
+++ b/generators/kubernetes/templates/deployment.yml.ejs
@@ -26,12 +26,12 @@ spec:
   selector:
     matchLabels:
       app: <%= app.baseName.toLowerCase() %>
-      version: "1.0"
+      version: "v1"
   template:
     metadata:
       labels:
         app: <%= app.baseName.toLowerCase() %>
-        version: "1.0"
+        version: "v1"
     spec:
       initContainers:
         - name: init-ds
diff --git a/generators/kubernetes/templates/gateway.yml.ejs b/generators/kubernetes/templates/gateway.yml.ejs
new file mode 100644
index 0000000000..fc4e54f4a8
--- /dev/null
+++ b/generators/kubernetes/templates/gateway.yml.ejs
@@ -0,0 +1,73 @@
+<%#
+ Copyright 2013-2018 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see https://www.jhipster.tech/
+ for more information.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-%>
+apiVersion: networking.istio.io/v1alpha3
+kind: Gateway
+metadata:
+  name: <%= app.baseName.toLowerCase() %>-gateway
+  namespace: <%= kubernetesNamespace %>
+spec:
+  selector:
+    istio: ingressgateway
+  servers:
+  - port:
+      number: 80
+      name: http
+      protocol: HTTP
+    hosts:
+    - <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
+  - port:
+      number: 80
+      name: http2
+      protocol: HTTP2
+    hosts:
+    - <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
+#  - port:
+#      number: 443
+#      name: https
+#      protocol: HTTPS
+#    hosts:
+#    - <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: VirtualService
+metadata:
+  name: <%= app.baseName.toLowerCase() %>-gw-virtualservice
+  namespace: <%= kubernetesNamespace %>
+spec:
+  hosts:
+  - <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
+  gateways:
+  - <%= app.baseName.toLowerCase() %>-gateway
+  http:
+  <%_ if (!app.serviceDiscoveryType) { _%>
+    <%_ appConfigs.filter(config => config.baseName !== app.baseName).forEach(function(config) { _%>
+  - match:
+    - uri:
+        prefix: /<%= config.baseName.toLowerCase() %>/
+    route:
+    - destination:
+        host: <%= config.baseName.toLowerCase() %>
+    <%_ }); _%>
+  <%_ } _%>
+  - match:
+    - uri:
+        prefix: /
+    route:
+    - destination:
+        host: <%= app.baseName.toLowerCase() %>
diff --git a/generators/kubernetes/templates/ingress.yml.ejs b/generators/kubernetes/templates/ingress.yml.ejs
index be964ff9be..b39b6824ec 100644
--- a/generators/kubernetes/templates/ingress.yml.ejs
+++ b/generators/kubernetes/templates/ingress.yml.ejs
@@ -21,10 +21,6 @@ kind: Ingress
 metadata:
   name: <%= app.baseName.toLowerCase() %>
   namespace: <%= kubernetesNamespace %>
-  <%_ if (istio !== 'no') { _%>
-  annotations:
-    kubernetes.io/ingress.class: istio
-  <%_ } _%>
 spec:
   rules:
   - host: <%= app.baseName.toLowerCase() %>.<%= ingressDomain %>
diff --git a/generators/kubernetes/templates/istio/destination-policy.yml.ejs b/generators/kubernetes/templates/istio/destination-policy.yml.ejs
deleted file mode 100644
index e5779b651e..0000000000
--- a/generators/kubernetes/templates/istio/destination-policy.yml.ejs
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: config.istio.io/v1alpha2
-kind: DestinationPolicy
-metadata:
-  name: <%= app.baseName.toLowerCase() %>-dp
-  namespace: <%= kubernetesNamespace %>
-spec:
-  destination:
-    namespace: <%= kubernetesNamespace %>
-    name: <%= app.baseName.toLowerCase() %>
-    labels:
-      version: "1.0"
-  loadBalancing:
-    name: RANDOM
-  circuitBreaker:
-    simpleCb:
-      maxConnections: 30
-      httpMaxRequests: 100
-      httpMaxRequestsPerConnection: 5
-      httpConsecutiveErrors: 5
-      sleepWindow: 2m
-      httpDetectionInterval: 10s
diff --git a/generators/kubernetes/templates/istio/destination-rule.yml.ejs b/generators/kubernetes/templates/istio/destination-rule.yml.ejs
new file mode 100644
index 0000000000..9ca07ae837
--- /dev/null
+++ b/generators/kubernetes/templates/istio/destination-rule.yml.ejs
@@ -0,0 +1,27 @@
+apiVersion: networking.istio.io/v1alpha3
+kind: DestinationRule
+metadata:
+  name: <%= app.baseName.toLowerCase() %>-destinationrule
+  namespace: <%= kubernetesNamespace %>
+spec:
+  host: <%= app.baseName.toLowerCase() %>
+  trafficPolicy:
+    loadBalancer:
+      simple: RANDOM
+    connectionPool:
+      tcp:
+        maxConnections: 30
+        connectTimeout: 100ms
+      http:
+        http1MaxPendingRequests: 10
+        http2MaxRequests: 100
+        maxRequestsPerConnection: 10
+        maxRetries: 5
+    outlierDetection:
+      consecutiveErrors: 5
+      interval: 30s
+      baseEjectionTime: 60s
+  subsets:
+  - name: v1
+    labels:
+      version: "v1"
diff --git a/generators/kubernetes/templates/istio/route-rule.yml.ejs b/generators/kubernetes/templates/istio/route-rule.yml.ejs
deleted file mode 100644
index 8aab64ebca..0000000000
--- a/generators/kubernetes/templates/istio/route-rule.yml.ejs
+++ /dev/null
@@ -1,18 +0,0 @@
-apiVersion: config.istio.io/v1alpha2
-kind: RouteRule
-metadata:
-  name: <%= app.baseName.toLowerCase() %>-rr
-  namespace: <%= kubernetesNamespace %>
-spec:
-  destination:
-    namespace: <%= kubernetesNamespace %>
-    name: <%= app.baseName.toLowerCase() %>
-  precedence: 1
-  route:
-  - labels:
-      version: "1.0"
-    weight: 100
-  httpReqRetries:
-    simpleRetry:
-      perTryTimeout: 2s
-      attempts: 3
diff --git a/generators/kubernetes/templates/istio/virtual-service.yml.ejs b/generators/kubernetes/templates/istio/virtual-service.yml.ejs
new file mode 100644
index 0000000000..01dab8bc1f
--- /dev/null
+++ b/generators/kubernetes/templates/istio/virtual-service.yml.ejs
@@ -0,0 +1,17 @@
+apiVersion: networking.istio.io/v1alpha3
+kind: VirtualService
+metadata:
+  name: <%= app.baseName.toLowerCase() %>-virtualservice
+  namespace: <%= kubernetesNamespace %>
+spec:
+  hosts:
+  - <%= app.baseName.toLowerCase() %>
+  http:
+  - route:
+    - destination:
+        host: <%= app.baseName.toLowerCase() %>
+        subset: "v1"
+      weight: 100
+    retries:
+      attempts: 3
+      perTryTimeout: 2s
diff --git a/generators/kubernetes/templates/kubectl-apply.sh.ejs b/generators/kubernetes/templates/kubectl-apply.sh.ejs
index ab50802cde..f04c8e9303 100755
--- a/generators/kubernetes/templates/kubectl-apply.sh.ejs
+++ b/generators/kubernetes/templates/kubectl-apply.sh.ejs
@@ -30,18 +30,16 @@ loopDir(){
 
 <%_ if (kubernetesNamespace !== 'default') { _%>
 kubectl apply -f namespace.yml
+<%_ } _%> <%_ if (serviceDiscoveryType === 'eureka' || serviceDiscoveryType === 'consul') { _%>
+kubectl apply -f registry/
 <%_ } _%> <%_ if (istio === 'autoInjection') { _%>
 kubectl label namespace <%-kubernetesNamespace%> istio-injection=enabled
 <%_ } _%> <%_ if (istio === 'manualInjection') { _%>
-<%_ if (serviceDiscoveryType === 'eureka' || serviceDiscoveryType === 'consul') { _%>
-loopDir "registry"
-<%_ } _%> <%_ appConfigs.forEach((appConfig, index) =>  { _%>
+<%_ appConfigs.forEach((appConfig, index) =>  { _%>
 loopDir "<%- appConfig.baseName.toLowerCase() %>"
 <%_ }) _%>
 <%_ } else {_%>
-<%_ if (serviceDiscoveryType === 'eureka' || serviceDiscoveryType === 'consul') { _%>
-kubectl apply -f registry/
-<%_ } _%> <%_ appConfigs.forEach((appConfig, index) =>  { _%>
+<%_ appConfigs.forEach((appConfig, index) =>  { _%>
 kubectl apply -f <%- appConfig.baseName.toLowerCase() %>/
 <%_ }) _%> <%_ } _%> <%_ if (useKafka === true) { _%>
 kubectl apply -f messagebroker/
diff --git a/generators/kubernetes/templates/registry/jhipster-registry.yml.ejs b/generators/kubernetes/templates/registry/jhipster-registry.yml.ejs
index 38e744e197..b072b577e4 100644
--- a/generators/kubernetes/templates/registry/jhipster-registry.yml.ejs
+++ b/generators/kubernetes/templates/registry/jhipster-registry.yml.ejs
@@ -73,6 +73,10 @@ spec:
       labels:
         app: jhipster-registry
         version: "1.0"
+     <%_ if (istio !== 'no') { _%>
+      annotations:
+        sidecar.istio.io/inject: "false"
+     <%_ } _%>
     spec:
       terminationGracePeriodSeconds: 10
       containers:


Test patch:
diff --git a/test/kubernetes.spec.js b/test/kubernetes.spec.js
index 53d9199c5d..781c2a71eb 100644
--- a/test/kubernetes.spec.js
+++ b/test/kubernetes.spec.js
@@ -50,6 +50,7 @@ const expectedFiles = {
         './monitoring/jhipster-grafana.yml',
         './monitoring/jhipster-grafana-dashboard.yml'
     ],
+    jhgategateway: ['./jhgate/jhgate-gateway.yml', './jhgate/jhgate-destination-rule.yml', './jhgate/jhgate-virtual-service.yml'],
     applyScript: ['./kubectl-apply.sh']
 };
 
@@ -381,4 +382,41 @@ describe('JHipster Kubernetes Sub Generator', () => {
             assert.file(expectedFiles.applyScript);
         });
     });
+
+    describe('gateway with istio routing', () => {
+        beforeEach(done => {
+            helpers
+                .run(require.resolve('../generators/kubernetes'))
+                .inTmpDir(dir => {
+                    fse.copySync(path.join(__dirname, './templates/compose/'), dir);
+                })
+                .withOptions({ skipChecks: true })
+                .withPrompts({
+                    composeApplicationType: 'microservice',
+                    directoryPath: './',
+                    chosenApps: ['01-gateway'],
+                    dockerRepositoryName: 'jhipster',
+                    dockerPushCommand: 'docker push',
+                    kubernetesNamespace: 'default',
+                    kubernetesServiceType: 'Ingress',
+                    ingressDomain: 'example.com',
+                    clusteredDbApps: [],
+                    istio: 'manualInjection',
+                    istioRoute: true
+                })
+                .on('end', done);
+        });
+        it('creates expected registry files', () => {
+            assert.file(expectedFiles.eurekaregistry);
+        });
+        it('creates expected service gateway files', () => {
+            assert.file(expectedFiles.jhgate);
+        });
+        it('creates expected routing gateway and istio files', () => {
+            assert.file(expectedFiles.jhgategateway);
+        });
+        it('create the apply script', () => {
+            assert.file(expectedFiles.applyScript);
+        });
+    });
 });