├── .gitignore ├── .gitmodules ├── CONTRIBUTING.md ├── Jenkinsfile ├── LICENSE ├── Makefile ├── OWNERS ├── README-QWIKLABS.md ├── README.md ├── images ├── billing-menu.png ├── bookinfo.png ├── istio-gke-gce-vpn.png ├── new-project-name.png └── new_project.png ├── scripts ├── create.sh ├── istio.env ├── namespaces.yaml ├── setup-gce-vm.sh ├── teardown.sh └── validate.sh ├── terraform ├── main.tf ├── provider.tf ├── variables.tf └── versions.tf └── test ├── boilerplate ├── boilerplate.BUILD.txt ├── boilerplate.Dockerfile.txt ├── boilerplate.Makefile.txt ├── boilerplate.WORKSPACE.txt ├── boilerplate.bazel.txt ├── boilerplate.bzl.txt ├── boilerplate.css.txt ├── boilerplate.go.preamble ├── boilerplate.go.txt ├── boilerplate.html.preamble ├── boilerplate.html.txt ├── boilerplate.java.txt ├── boilerplate.js.txt ├── boilerplate.py.preamble ├── boilerplate.py.txt ├── boilerplate.scss.txt ├── boilerplate.sh.preamble ├── boilerplate.sh.txt ├── boilerplate.tf.txt ├── boilerplate.ts.txt ├── boilerplate.xml.preamble ├── boilerplate.xml.txt └── boilerplate.yaml.txt ├── make.sh └── verify_boilerplate.py /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX leaves these everywhere on SMB shares 2 | ._* 3 | 4 | # OSX trash 5 | .DS_Store 6 | 7 | # Emacs save files 8 | *~ 9 | \#*\# 10 | .\#* 11 | 12 | # Vim-related files 13 | [._]*.s[a-w][a-z] 14 | [._]s[a-w][a-z] 15 | *.un~ 16 | Session.vim 17 | .netrwhist 18 | 19 | # Local .terraform directories 20 | **/.terraform/* 21 | 22 | # .tfstate files 23 | *.tfstate 24 | *.tfstate.* 25 | 26 | # Crash log files 27 | crash.log 28 | 29 | istio-* 30 | cluster.env 31 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "gke-istio-shared"] 2 | path = gke-istio-shared 3 | url = https://github.com/GoogleCloudPlatform/gke-istio-shared.git 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | Contributions to this project must be accompanied by a Contributor License 8 | Agreement. You (or your employer) retain the copyright to your contribution; 9 | this simply gives us permission to use and redistribute your contributions as 10 | part of the project. Head over to https://cla.developers.google.com/ to see your 11 | current agreements on file or to sign a new one. 12 | 13 | You generally only need to submit a CLA once, so if you've already submitted one 14 | (even if it was for a different project), you probably don't need to do it again. 15 | 16 | ## Code reviews 17 | All submissions, including submissions by project members, require review. We 18 | use GitHub pull requests for this purpose. Consult GitHub Help for more 19 | information on using pull requests. 20 | 21 | ## Community Guidelines 22 | This project follows 23 | [Google's Open Source Community Guidelines](CODE-OF-CONDUCT.md). 24 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | /* 3 | Copyright 2018 Google LLC 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | https://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | */ 18 | 19 | // The declarative agent is defined in yaml. It was previously possible to 20 | // define containerTemplate but that has been deprecated in favor of the yaml 21 | // format 22 | // Reference: https://github.com/jenkinsci/kubernetes-plugin 23 | 24 | // set up pod label and GOOGLE_APPLICATION_CREDENTIALS (for Terraform) 25 | def label = "k8s-infra" 26 | def containerName = "k8s-node" 27 | def GOOGLE_APPLICATION_CREDENTIALS = '/home/jenkins/dev/jenkins-deploy-dev-infra.json' 28 | 29 | podTemplate(label: label, yaml: """ 30 | apiVersion: v1 31 | kind: Pod 32 | metadata: 33 | labels: 34 | jenkins: build-node 35 | spec: 36 | containers: 37 | - name: ${containerName} 38 | image: gcr.io/pso-helmsman-cicd/jenkins-k8s-node:${env.JENKINS_CONTAINER_VERSION} 39 | command: ['cat'] 40 | tty: true 41 | volumeMounts: 42 | # Mount the dev service account key 43 | - name: dev-key 44 | mountPath: /home/jenkins/dev 45 | volumes: 46 | # Create a volume that contains the dev json key that was saved as a secret 47 | - name: dev-key 48 | secret: 49 | secretName: jenkins-deploy-dev-infra 50 | """ 51 | ) { 52 | node(label) { 53 | try { 54 | // Options covers all other job properties or wrapper functions that apply to entire Pipeline. 55 | properties([disableConcurrentBuilds()]) 56 | // set env variable GOOGLE_APPLICATION_CREDENTIALS for Terraform 57 | env.GOOGLE_APPLICATION_CREDENTIALS=GOOGLE_APPLICATION_CREDENTIALS 58 | 59 | stage('Setup') { 60 | container(containerName) { 61 | // checkout code from scm i.e. commits related to the PR 62 | checkout scm 63 | 64 | // initialize submodule and update 65 | sh "git submodule update --init --recursive" 66 | 67 | // Setup gcloud service account access 68 | sh "gcloud auth activate-service-account --key-file=${GOOGLE_APPLICATION_CREDENTIALS}" 69 | sh "gcloud config set compute/zone ${env.ZONE}" 70 | sh "gcloud config set core/project ${env.ISTIO_PROJECT}" 71 | sh "gcloud config set compute/region ${env.REGION}" 72 | } 73 | } 74 | stage('Lint') { 75 | container(containerName) { 76 | sh "make lint" 77 | } 78 | } 79 | 80 | stage('Create') { 81 | container(containerName) { 82 | sh "make create" 83 | } 84 | } 85 | 86 | stage('Validate') { 87 | container(containerName) { 88 | sh "make validate" 89 | } 90 | } 91 | 92 | } 93 | catch (err) { 94 | // if any exception occurs, mark the build as failed 95 | // and display a detailed message on the Jenkins console output 96 | currentBuild.result = 'FAILURE' 97 | echo "FAILURE caught echo ${err}" 98 | throw err 99 | } 100 | finally { 101 | stage('Teardown') { 102 | container(containerName) { 103 | sh "make teardown" 104 | sh "gcloud auth revoke" 105 | } 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Make will use bash instead of sh 16 | SHELL := /usr/bin/env bash 17 | 18 | # lint is the first target in the file so it will get picked up when you just 19 | # run 'make' on its own 20 | lint: check_shell check_shebangs check_python check_golang check_terraform \ 21 | check_docker check_base_files check_headers check_trailing_whitespace 22 | 23 | # create/delete/validate is for CICD 24 | .PHONY: create 25 | create: 26 | @source scripts/create.sh 27 | 28 | .PHONY: validate 29 | validate: 30 | @source scripts/validate.sh 31 | 32 | .PHONY: teardown 33 | teardown: 34 | @source scripts/teardown.sh 35 | 36 | # The .PHONY directive tells make that this isn't a real target and so 37 | # the presence of a file named 'check_shell' won't cause this target to stop 38 | # working 39 | .PHONY: check_shell 40 | check_shell: 41 | @source test/make.sh && check_shell 42 | 43 | .PHONY: check_python 44 | check_python: 45 | @source test/make.sh && check_python 46 | 47 | .PHONY: check_golang 48 | check_golang: 49 | @source test/make.sh && golang 50 | 51 | .PHONY: check_terraform 52 | check_terraform: 53 | @source test/make.sh && check_terraform 54 | 55 | .PHONY: check_docker 56 | check_docker: 57 | @source test/make.sh && docker 58 | 59 | .PHONY: check_base_files 60 | check_base_files: 61 | @source test/make.sh && basefiles 62 | 63 | .PHONY: check_shebangs 64 | check_shebangs: 65 | @source test/make.sh && check_bash 66 | 67 | .PHONY: check_trailing_whitespace 68 | check_trailing_whitespace: 69 | @source test/make.sh && check_trailing_whitespace 70 | 71 | .PHONY: check_headers 72 | check_headers: 73 | @echo "Checking file headers" 74 | @python3.7 test/verify_boilerplate.py 75 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - chrislovecnm 3 | - robinpercy 4 | - geojaz 5 | - techgnosis 6 | - erkolson 7 | labels: 8 | - gke-helmsman 9 | -------------------------------------------------------------------------------- /README-QWIKLABS.md: -------------------------------------------------------------------------------- 1 | # Istio on Kubernetes Engine and Compute Engine 2 | 3 | ## Table of Contents 4 | 5 | * [Introduction](#introduction) 6 | * [Istio on GKE](#istio-on-gke) 7 | * [Architecture](#architecture) 8 | * [Application architecture](#application-architecture) 9 | * [Infrastructure architecture](#infrastructure-architecture) 10 | * [Run Demo using Cloud Shell](#run-demo-using-cloud-shell) 11 | * [Configure gcloud](#configure-gcloud) 12 | * [Creating a project](#creating-a-project) 13 | * [Deployment](#deployment) 14 | * [Noteworthy Aspects of the Deployment:](#noteworthy-aspects-of-the-deployment) 15 | * [Validation](#validation) 16 | * [Tear Down](#tear-down) 17 | * [Troubleshooting](#troubleshooting) 18 | * [Relevant Material](#relevant-material) 19 | 20 | 21 | ## Introduction 22 | 23 | [Istio](https://istio.io/) is part of a new category of products known as "service mesh" software 24 | designed to manage the complexity of service resilience in a microservice 25 | infrastructure. It defines itself as a service management framework built to 26 | keep business logic separate from the logic to keep your services up and 27 | running. In other words, it provides a layer on top of the network that will 28 | automatically route traffic to the appropriate services, handle [circuit 29 | breaker](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) logic, 30 | enforce access and load balancing policies, and generate telemetry data to 31 | gain insight into the network and allow for quick diagnosis of issues. 32 | 33 | Istio makes it easy to create a network of deployed services with load balancing, service-to-service authentication and monitoring without any changes in service code. 34 | 35 | Core features of Istio include: 36 | 37 | 1. [Traffic management](https://istio.io/docs/concepts/traffic-management/) - Istio simplifies configuration of service-level properties like circuit breakers, timeouts, and retries making the network more robust. 38 | 2. [Security](https://istio.io/docs/concepts/security/) - Istio, using with Kubernetes (or infrastructure) network policies, provides the ability to secure pod-to-pod or service-to-service communication at the network and application layers. 39 | 3. Platform support - Istio is platform-independent and currently supports service deployment on Kubernetes, services registered with Consul and services running on individual virtual machines. 40 | 5. Integration and customization - Istio, has a policy enforcement component which can be extended and customized to integrate with existing solutions for ACLs, logging, monitoring, quotas and auditing. 41 | 42 | For more information on Istio, please refer to the [Istio 43 | documentation](https://istio.io/docs/). 44 | 45 | ### Istio on GKE 46 | 47 | When you create or update the cluster with Istio on GKE, following components are installed: 48 | 49 | 1. Pilot, which is responsible for service discovery and for configuring the Envoy sidecar proxies in an Istio service mesh. 50 | 2. [Istio-Policy and Istio-Telemetry](https://istio.io/docs/concepts/policies-and-telemetry), which enforce usage policies and gather telemetry data. 51 | 3. The [Istio Ingress gateway](https://istio.io/docs/tasks/traffic-management/ingress), which provides an ingress point for traffic from outside the cluster. 52 | 4. The [Istio Egress gateway](https://istio.io/docs/tasks/traffic-management/egress), which allow Istio features like monitoring and routing rules to be applied to traffic exiting the mesh. 53 | 5. [Citadel](https://istio.io/docs/concepts/security), which automates key and certificate management for Istio. 54 | 6. [Galley](https://istio.io/docs/concepts/what-is-istio/#galley), which provides configuration management services for Istio. 55 | 56 | For more information on how to install Istio, please refer to the [Installing Istio on GKE](https://cloud.google.com/istio/docs/istio-on-gke/installing). 57 | 58 | This repository contains demonstration code for Istio's mesh expansion feature 59 | between resources in two Google Cloud Platform (GCP) projects connected via 60 | VPN. The feature allows for a non-Kubernetes service running outside of the 61 | Istio infrastructure on Kubernetes Engine to be integrated into and managed by 62 | the Istio service mesh. 63 | 64 | ## Architecture 65 | 66 | This demonstration will create a number of resources. 67 | 68 | * A single (GKE) cluster with IP aliasing turned on in a custom network in 69 | project A 70 | * A Google Compute Engine (GCE) instance in a custom network project B 71 | * A VPN bridging the two networks containing the GKE cluster and the GCE 72 | instance 73 | * The Istio service mesh installed in the GKE cluster 74 | * The [BookInfo](https://istio.io/docs/examples/bookinfo/) application installed in the Istio service mesh 75 | * A firewall rule allowing full SSH access to the GCE instance from any IP 76 | address 77 | * A firewall rule allowing full access to the MySQL database from the GKE 78 | cluster 79 | 80 | ### Application architecture 81 | 82 | ![](./images/bookinfo.png) 83 | 84 | ### Infrastructure architecture 85 | 86 | ![](./images/istio-gke-gce-vpn.png) 87 | 88 | ## Run Demo using Cloud Shell 89 | 90 | Use the `--recursive` argument to download dependencies provided via a git submodule. 91 | 92 | ```shell 93 | git submodule update --init --recursive 94 | 95 | ## Configure gcloud 96 | 97 | When using Cloud Shell execute the following command in order to setup gcloud cli. When executing this command please setup your region and zone. 98 | 99 | ```console 100 | gcloud init 101 | ``` 102 | 103 | ## Creating a project 104 | In order to complete this demo, two projects need to exist, one for the GKE 105 | cluster and a second for the GCE instance, which will be connected via a VPN. 106 | 107 | To create projects: 108 | 1. Log in to the [GCP Console](http://console.cloud.google.com/) 109 | 1. Click on `Select a project` in the top navigating bar 110 | 1. Click on `New Project` in on the top right of the window: 111 | 112 | ![](./images/new_project.png) 113 | 114 | 1. Enter a project name, and note the project id below it. 115 | (in this case, the project id is `angelic-phoenix-210818`): 116 | 117 | ![](./images/new-project-name.png) 118 | 119 | ## Deployment 120 | 121 | Open the `scripts/istio.env` file and set: 122 | 123 | * `ISTIO_PROJECT` to the ID of the project you want to use for Istio infrastructure 124 | * `GCE_PROJECT` to the ID of the project you want to use for GCE 125 | * Any variables you wish to customize 126 | 127 | Note that the ID of the project is not always the same as the name. Also, please note that when setting `ISTIO_PROJECT` and `GCE_PROJECT` they should be uncommented. Failure to do so will result in an error in the following step. 128 | 129 | Once configuration is complete the demo cluster and app can be deployed.: 130 | 131 | ```shell 132 | make create 133 | ``` 134 | 135 | This make target calls the `scripts/create.sh` script which will use Terraform to automatically build out necessary infrastructure, including a Kubernetes cluster, and will then use `kubectl` to deploy application components and other resource to the cluster. 136 | 137 | ### Noteworthy Aspects of the Deployment: 138 | 139 | 1. The GKE cluster uses IP aliasing, without this feature, the demo would not 140 | work. IP Aliasing is a feature by which services and pods can have their IP 141 | addresses set to values within a specific CIDR block, which allows them to be 142 | known in advance of a deployment, and callable by other resources. This also 143 | ensures that the IP addresses will not conflict with other GCP resources and 144 | provides an additional mechanism for firewall traffic control (e.g. rules on the 145 | pod may differ from those on the underlying host). 146 | For more information on IP Aliasing see: 147 | https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips 148 | 149 | 1. The GKE cluster's IP CIDR blocks are defined in the `istio.env` file and can 150 | be changed in the event that other values are needed (e.g. if they conflict with 151 | other IP address space). 152 | 153 | 1. Firewall and Routing rules are created at deployment time to facilitate the 154 | necessary communication without exposing ports and services unnecessarily. 155 | 156 | 1. The VPN configuration (endpoints, firewalls and routing rules) are defined in 157 | the included terraform configuration, `terraform/main.tf`. For more information on VPNs 158 | see: https://cloud.google.com/vpn/docs/how-to 159 | 160 | ## Validation 161 | 162 | To validate that everything is working correctly, first open your browser to 163 | the URL provided at the end of the installation script. 164 | You'll see a URL for the BookInfo web site. After taking a look, run: 165 | 166 | ```shell 167 | make validate 168 | ``` 169 | 170 | This will change the rating between 1 and 5 stars for Reviewer1. 171 | 172 | Refresh the page in your browser; the first rating should reflect the 173 | number of stars passed to the validate script. Behind the scenes, the validate 174 | script is directly editing the database on the GCE VM that was integrated into 175 | the mesh, proving that the BookInfo application is using the database on the VM 176 | as the source of the rating data. 177 | 178 | ## Tear Down 179 | 180 | To shutdown the demo run: 181 | 182 | ```shell 183 | make teardown 184 | ``` 185 | 186 | This will destroy all the resources created by Terraform including everything deployed to the Kubernetes cluster. 187 | 188 | ## Troubleshooting 189 | 190 | **Problem:** The Book Reviews section is returning an error stating that the ratings service is not available. 191 | 192 | **Solution:** Istio may still be configuring the mesh. Wait for a minute so while refreshing the page. 193 | 194 | ---- 195 | 196 | **Problem:** The install script fails with a `Permission denied` when running Terraform. 197 | 198 | **Solution:** The credentials that Terraform is using do not provide the necessary permissions to create resources in the selected projects. Ensure that the account listed in `gcloud config list` has necessary permissions to create resources. If it does, regenerate the application default credentials using `gcloud auth application-default login`. 199 | 200 | ---- 201 | 202 | **Problem:** Loss of GKE cluster network connectivity after 24 hours 203 | 204 | **Solution:** Remove the GCE instance and rerun all steps involving the GCE setup 205 | 206 | ---- 207 | 208 | **Problem:** The install script times out while waiting for the internal load balancers to finish provisioning. 209 | 210 | **Solution:** Likely the cause is a transient platform issue. Rerun the script as it is idempotent up to this point and should not run into any issues with infrastructure that already exists. 211 | 212 | ---- 213 | 214 | **Problem:** The install script gives an error like: 215 | 216 | >ERROR: (gcloud.services.enable) User [{your-email address}] does not have permission to access service [compute.googleapis.com:enable] (or it may not exist): Project '{your-project-name}' not found or permission denied. 217 | 218 | **Solution:** Enter the project Id and not the project name into `scripts/istio.env` 219 | 220 | ## Relevant Material 221 | 222 | * https://github.com/istio/community 223 | * https://istio.io/docs/guides/bookinfo.html 224 | * https://cloud.google.com/kubernetes-engine/docs/tutorials/istio-on-gke 225 | * https://cloud.google.com/compute/docs/tutorials/istio-on-compute-engine 226 | * https://istio.io/docs/setup/kubernetes/mesh-expansion.html 227 | * https://istio.io/docs/guides/integrating-vms.html 228 | 229 | 230 | **This is not an officially supported Google product** 231 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Istio on Kubernetes Engine and Compute Engine 2 | 3 | ## Table of Contents 4 | 5 | * [Introduction](#introduction) 6 | * [Istio on GKE](#istio-on-gke) 7 | * [Architecture](#architecture) 8 | * [Application architecture](#application-architecture) 9 | * [Infrastructure architecture](#infrastructure-architecture) 10 | * [Prerequisites](#prerequisites) 11 | * [Run Demo in a Google Cloud Shell](#run-demo-in-a-google-cloud-shell) 12 | * [Tools](#tools) 13 | * [Install Cloud SDK](#install-cloud-sdk) 14 | * [Install kubectl CLI](#install-kubectl-cli) 15 | * [Install Terraform](#install-terraform) 16 | * [Creating a project](#creating-a-project) 17 | * [Deployment](#deployment) 18 | * [Noteworthy Aspects of the Deployment:](#noteworthy-aspects-of-the-deployment) 19 | * [Validation](#validation) 20 | * [Tear Down](#tear-down) 21 | * [Troubleshooting](#troubleshooting) 22 | * [Relevant Material](#relevant-material) 23 | 24 | 25 | ## Introduction 26 | 27 | [Istio](https://istio.io/) is part of a new category of products known as "service mesh" software 28 | designed to manage the complexity of service resilience in a microservice 29 | infrastructure. It defines itself as a service management framework built to 30 | keep business logic separate from the logic to keep your services up and 31 | running. In other words, it provides a layer on top of the network that will 32 | automatically route traffic to the appropriate services, handle [circuit 33 | breaker](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) logic, 34 | enforce access and load balancing policies, and generate telemetry data to 35 | gain insight into the network and allow for quick diagnosis of issues. 36 | 37 | Istio makes it easy to create a network of deployed services with load balancing, service-to-service authentication and monitoring without any changes in service code. 38 | 39 | Core features of Istio include: 40 | 41 | 1. [Traffic management](https://istio.io/docs/concepts/traffic-management/) - Istio simplifies configuration of service-level properties like circuit breakers, timeouts, and retries making the network more robust. 42 | 2. [Security](https://istio.io/docs/concepts/security/) - Istio, using with Kubernetes (or infrastructure) network policies, provides the ability to secure pod-to-pod or service-to-service communication at the network and application layers. 43 | 3. Platform support - Istio is platform-independent and currently supports service deployment on Kubernetes, services registered with Consul and services running on individual virtual machines. 44 | 5. Integration and customization - Istio, has a policy enforcement component which can be extended and customized to integrate with existing solutions for ACLs, logging, monitoring, quotas and auditing. 45 | 46 | For more information on Istio, please refer to the [Istio 47 | documentation](https://istio.io/docs/). 48 | 49 | ### Istio on GKE 50 | 51 | When you create or update the cluster with Istio on GKE, following components are installed: 52 | 53 | 1. Pilot, which is responsible for service discovery and for configuring the Envoy sidecar proxies in an Istio service mesh. 54 | 2. [Istio-Policy and Istio-Telemetry](https://istio.io/docs/concepts/policies-and-telemetry), which enforce usage policies and gather telemetry data. 55 | 3. The [Istio Ingress gateway](https://istio.io/docs/tasks/traffic-management/ingress), which provides an ingress point for traffic from outside the cluster. 56 | 4. The [Istio Egress gateway](https://istio.io/docs/tasks/traffic-management/egress), which allow Istio features like monitoring and routing rules to be applied to traffic exiting the mesh. 57 | 5. [Citadel](https://istio.io/docs/concepts/security), which automates key and certificate management for Istio. 58 | 6. [Galley](https://istio.io/docs/concepts/what-is-istio/#galley), which provides configuration management services for Istio. 59 | 60 | For more information on how to install Istio, please refer to the [Installing Istio on GKE](https://cloud.google.com/istio/docs/istio-on-gke/installing). 61 | 62 | This repository contains demonstration code for Istio's mesh expansion feature 63 | between resources in two Google Cloud Platform (GCP) projects connected via 64 | VPN. The feature allows for a non-Kubernetes service running outside of the 65 | Istio infrastructure on Kubernetes Engine to be integrated into and managed by 66 | the Istio service mesh. 67 | 68 | ## Architecture 69 | 70 | This demonstration will create a number of resources. 71 | 72 | * A single (GKE) cluster with IP aliasing turned on in a custom network in project A 73 | * A Google Compute Engine (GCE) instance in a custom network project B 74 | * A VPN bridging the two networks containing the GKE cluster and the GCE instance 75 | * The Istio service mesh installed in the GKE cluster 76 | * The [BookInfo](https://istio.io/docs/examples/bookinfo/) application installed in the Istio service mesh 77 | * A firewall rule allowing full SSH access to the GCE instance from any IP address 78 | * A firewall rule allowing full access to the MySQL database from the GKE cluster 79 | 80 | ### Application architecture 81 | 82 | ![](./images/bookinfo.png) 83 | 84 | ### Infrastructure architecture 85 | 86 | ![](./images/istio-gke-gce-vpn.png) 87 | 88 | ## Prerequisites 89 | 90 | ### Run Demo in a Google Cloud Shell 91 | 92 | Click the button below to run the demo in a [Google Cloud Shell](https://cloud.google.com/shell/docs/). 93 | 94 | [![Open in Cloud Shell](http://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https://github.com/GoogleCloudPlatform/gke-istio-vpn-demo.git&cloudshell_image=gcr.io/graphite-cloud-shell-images/terraform:latest&cloudshell_tutorial=README.md) 95 | 96 | 97 | Use the `--recursive` argument to download dependencies provided via a git submodule. 98 | 99 | ```shell 100 | git submodule update --init --recursive 101 | ``` 102 | 103 | All the tools for the demo are installed. When using Cloud Shell execute the following command in order to setup gcloud cli. When executing this command please setup your region and zone. 104 | 105 | ```console 106 | gcloud init 107 | ``` 108 | 109 | ### Tools 110 | 111 | In order to use the code in this demo you will need to have have access to a bash-compatible shell with the following tools installed: 112 | 113 | 1. [Terraform >= 0.12.3](https://www.terraform.io/downloads.html) 114 | 2. [Google Cloud SDK version >= 253.0.0](https://cloud.google.com/sdk/docs/downloads-versioned-archives) 115 | 3. [kubectl matching the latest GKE version](https://kubernetes.io/docs/tasks/tools/install-kubectl/) 116 | 4. Two [GCP projects](https://console.cloud.google.com/) with billing enabled 117 | 118 | #### Install Cloud SDK 119 | The Google Cloud SDK is used to interact with your GCP resources. [Installation instructions](https://cloud.google.com/sdk/downloads) for multiple platforms are available online. 120 | 121 | #### Install kubectl CLI 122 | 123 | The kubectl CLI is used to interteract with both Kubernetes Engine and kubernetes in general. [Installation instructions](https://cloud.google.com/kubernetes-engine/docs/quickstart) for multiple platforms are available online. 124 | 125 | #### Install Terraform 126 | 127 | Terraform is used to automate the manipulation of cloud infrastructure. Its [installation instructions](https://www.terraform.io/intro/getting-started/install.html) are also available online. 128 | 129 | ## Creating a project 130 | In order to complete this demo, two projects need to exist, one for the GKE cluster and a second for the GCE instance, which will be connected via a VPN. 131 | 132 | To create projects: 133 | 1. Log in to the [GCP Console](http://console.cloud.google.com/) 134 | 1. Click on `Select a project` in the top navigating bar 135 | 1. Click on `New Project` in on the top right of the window: 136 | 137 | ![](./images/new_project.png) 138 | 139 | 1. Enter a project name, and note the project id below it. 140 | (in this case, the project id is `angelic-phoenix-210818`): 141 | 142 | ![](./images/new-project-name.png) 143 | 144 | 1. Enable billing by clicking on the three lines in the top left corner select `Billing` and enable it: 145 | 146 | ![](./images/billing-menu.png) 147 | 148 | If necessary, repeat for a second project. 149 | 150 | ## Deployment 151 | 152 | Use `git` to clone this project to your local machine: 153 | 154 | ```shell 155 | git clone --recursive https://github.com/GoogleCloudPlatform/gke-istio-vpn-demo 156 | ``` 157 | 158 | Note that the `--recursive` argument is required to download dependencies provided via a git submodule. 159 | 160 | When downloading is complete, change your current working directory to the new project: 161 | 162 | ```shell 163 | cd gke-istio-vpn-demo 164 | ``` 165 | 166 | Continue with the instructions below, running all commands from this directory. 167 | 168 | Open the `scripts/istio.env` file and set: 169 | 170 | * `ISTIO_PROJECT` to the ID of the project you want to use for Istio infrastructure 171 | * `GCE_PROJECT` to the ID of the project you want to use for GCE 172 | * Any variables you wish to customize 173 | 174 | Note that the ID of the project is not always the same as the name. Also, please note that when setting `ISTIO_PROJECT` and `GCE_PROJECT` they should be uncommented. Failure to do so will result in an error in the following step. 175 | 176 | Once configuration is complete the demo cluster and app can be deployed.: 177 | 178 | ```shell 179 | make create 180 | ``` 181 | 182 | This make target calls the `scripts/create.sh` script which will use Terraform to automatically build out necessary infrastructure, including a Kubernetes cluster, and will then use `kubectl` to deploy application components and other resource to the cluster. 183 | 184 | ### Noteworthy Aspects of the Deployment: 185 | 1. The GKE cluster uses IP aliasing, without this feature, the demo would not work. IP Aliasing is a feature by which services and pods can have their IP addresses set to values within a specific CIDR block, which allows them to be known in advance of a deployment, and callable by other resources. This also ensures that the IP addresses will not conflict with other GCP resources and provides an additional mechanism for firewall traffic control (e.g. rules on the pod may differ from those on the underlying host). 186 | 187 | For more information on IP Aliasing see: 188 | https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips 189 | 190 | 1. The GKE cluster's IP CIDR blocks are defined in the `istio.env` file and can be changed in the event that other values are needed (e.g. if they conflict with other IP address space). 191 | 192 | 1. Firewall and Routing rules are created at deployment time to facilitate the necessary communication without exposing ports and services unnecessarily. 193 | 194 | 1. The VPN configuration (endpoints, firewalls and routing rules) are defined in the included terraform configuration, `terraform/main.tf`. For more information on VPNs see: https://cloud.google.com/vpn/docs/how-to 195 | 196 | ## Validation 197 | 198 | To validate that everything is working correctly, first open your browser to the URL provided at the end of the installation script. 199 | You'll see a URL for the BookInfo web site. After taking a look, run: 200 | 201 | ```shell 202 | make validate 203 | ``` 204 | 205 | This will change the rating between 1 and 5 stars for Reviewer1. 206 | 207 | Refresh the page in your browser; the first rating should reflect the number of stars passed to the validate script. Behind the scenes, the validate script is directly editing the database on the GCE VM that was integrated into the mesh, proving that the BookInfo application is using the database on the VM as the source of the rating data. 208 | 209 | ## Tear Down 210 | 211 | To shutdown the demo run: 212 | 213 | ```shell 214 | make teardown 215 | ``` 216 | 217 | This will destroy all the resources created by Terraform including everything deployed to the Kubernetes cluster. 218 | 219 | ## Troubleshooting 220 | 221 | **Problem:** Functions in gke-istio-shared are not available: `gke-istio-shared/verify-functions.sh` 222 | 223 | **Solution:** If you are running this manually, you may be missing your git submodule. To fix this, run: 224 | `git submodule update --init` 225 | 226 | ---- 227 | **Problem:** The Book Reviews section is returning an error stating that the ratings service is not available. 228 | 229 | **Solution:** Istio may still be configuring the mesh. Wait for a minute so while refreshing the page. 230 | 231 | ---- 232 | 233 | **Problem:** The install script fails with a `Permission denied` when running Terraform. 234 | 235 | **Solution:** The credentials that Terraform is using do not provide the necessary permissions to create resources in the selected projects. Ensure that the account listed in `gcloud config list` has necessary permissions to create resources. If it does, regenerate the application default credentials using `gcloud auth application-default login`. 236 | 237 | ---- 238 | 239 | **Problem:** Loss of GKE cluster network connectivity after 24 hours 240 | 241 | **Solution:** Remove the GCE instance and rerun all steps involving the GCE setup 242 | 243 | ---- 244 | 245 | **Problem:** The install script times out while waiting for the internal load balancers to finish provisioning. 246 | 247 | **Solution:** Likely the cause is a transient platform issue. Rerun the script as it is idempotent up to this point and should not run into any issues with infrastructure that already exists. 248 | 249 | ---- 250 | 251 | **Problem:** The install script gives an error like: 252 | 253 | >ERROR: (gcloud.services.enable) User [{your-email address}] does not have permission to access service compute.googleapis.com:enable] (or it may not exist): Project '{your-project-name}' not found or permission denied. 254 | 255 | **Solution:** Enter the project Id and not the project name into `scripts/istio.env` 256 | 257 | ## Relevant Material 258 | 259 | * https://github.com/istio/community 260 | * https://istio.io/docs/guides/bookinfo.html 261 | * https://cloud.google.com/kubernetes-engine/docs/tutorials/istio-on-gke 262 | * https://cloud.google.com/compute/docs/tutorials/istio-on-compute-engine 263 | * https://istio.io/docs/setup/kubernetes/mesh-expansion.html 264 | * https://istio.io/docs/guides/integrating-vms.html 265 | 266 | 267 | **This is not an officially supported Google product** 268 | -------------------------------------------------------------------------------- /images/billing-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/gke-istio-vpn-demo/b7c5863d8fd470be28c97a769c880de878a25800/images/billing-menu.png -------------------------------------------------------------------------------- /images/bookinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/gke-istio-vpn-demo/b7c5863d8fd470be28c97a769c880de878a25800/images/bookinfo.png -------------------------------------------------------------------------------- /images/istio-gke-gce-vpn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/gke-istio-vpn-demo/b7c5863d8fd470be28c97a769c880de878a25800/images/istio-gke-gce-vpn.png -------------------------------------------------------------------------------- /images/new-project-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/gke-istio-vpn-demo/b7c5863d8fd470be28c97a769c880de878a25800/images/new-project-name.png -------------------------------------------------------------------------------- /images/new_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/gke-istio-vpn-demo/b7c5863d8fd470be28c97a769c880de878a25800/images/new_project.png -------------------------------------------------------------------------------- /scripts/create.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | set -x 19 | 20 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 21 | # shellcheck source=scripts/istio.env 22 | source "$ROOT/scripts/istio.env" 23 | 24 | ISTIO_DIR="$ROOT/istio-${ISTIO_VERSION}" 25 | 26 | # Check if all required variables are non-null 27 | # Globals: 28 | # None 29 | # Arguments: 30 | # VAR - The variable to check 31 | # Returns: 32 | # None 33 | variable_is_set() { 34 | if [[ -z "${VAR}" ]]; then 35 | echo "Variable is not set. Please check your istio.env file." 36 | return 1 37 | fi 38 | return 0 39 | } 40 | 41 | # Check if required binaries exist 42 | # Globals: 43 | # None 44 | # Arguments: 45 | # DEPENDENCY - The command to verify is installed. 46 | # Returns: 47 | # None 48 | dependency_installed () { 49 | command -v "${1}" >/dev/null 2>&1 || exit 1 50 | } 51 | 52 | # Helper function to enable a given service for a given project 53 | # Globals: 54 | # None 55 | # Arguments: 56 | # PROJECT - ID of the project in which to enable the API 57 | # API - Name of the API to enable, e.g. compute.googleapis.com 58 | # Returns: 59 | # None 60 | enable_project_api() { 61 | gcloud services enable "${2}" --project "${1}" 62 | } 63 | 64 | # set to jenkins if there is no $USER 65 | USER=$(whoami) 66 | [[ "${USER}" == "root" ]] && export USER=jenkins 67 | echo "user is: $USER" 68 | 69 | # Provide the default values for the variables 70 | for VAR in "${ISTIO_CLUSTER}" "${ZONE}" "${REGION}" "${GCE_NETWORK}" \ 71 | "${GCE_SUBNET}" "${GCE_SUBNET_CIDR}" "${ISTIO_NETWORK}" \ 72 | "${ISTIO_SUBNET}" "${ISTIO_SUBNET_CIDR}" \ 73 | "${ISTIO_SUBNET_CLUSTER_CIDR}" "${ISTIO_SUBNET_SERVICES_CIDR}" \ 74 | "${GCE_VM}" "${ISTIO_GKE_VERSION}" "${GKE_VERSION}"; do 75 | variable_is_set "${VAR}" 76 | done 77 | 78 | # Ensure the necessary dependencies are installed 79 | if ! dependency_installed "gcloud"; then 80 | echo "I require gcloud but it's not installed. Aborting." 81 | fi 82 | 83 | if ! dependency_installed "kubectl"; then 84 | echo "I require gcloud but it's not installed. Aborting." 85 | fi 86 | 87 | if ! dependency_installed "curl" ; then 88 | echo "I require curl but it's not installed. Aborting." 89 | fi 90 | 91 | if [[ "${ISTIO_PROJECT}" == "" ]]; then 92 | echo "ISTIO_PROJECT variable in istio.env is not set to a valid project. Aborting..." 93 | exit 1 94 | fi 95 | 96 | if [[ ${GCE_PROJECT} == "" ]]; then 97 | echo "GCE_PROJECT variable in istio.env is not set to a valid project. Aborting..." 98 | exit 1 99 | fi 100 | 101 | enable_project_api "${ISTIO_PROJECT}" compute.googleapis.com 102 | enable_project_api "${ISTIO_PROJECT}" container.googleapis.com 103 | enable_project_api "${GCE_PROJECT}" compute.googleapis.com 104 | 105 | # Setup Terraform 106 | (cd "$ROOT/terraform"; terraform init -input=false) 107 | 108 | # Deploy infrastructure using Terraform 109 | (cd "$ROOT/terraform"; terraform apply -var "istio_project=${ISTIO_PROJECT}" \ 110 | -var "gce_project=${GCE_PROJECT}" \ 111 | -var "istio_cluster=${ISTIO_CLUSTER}" \ 112 | -var "zone=${ZONE}" \ 113 | -var "region=${REGION}" \ 114 | -var "gce_network=${GCE_NETWORK}" \ 115 | -var "gce_subnet=${GCE_SUBNET}" \ 116 | -var "gce_subnet_cidr=${GCE_SUBNET_CIDR}" \ 117 | -var "istio_network=${ISTIO_NETWORK}" \ 118 | -var "istio_subnet=${ISTIO_SUBNET}" \ 119 | -var "istio_subnet_cidr=${ISTIO_SUBNET_CIDR}" \ 120 | -var "istio_subnet_cluster_cidr=${ISTIO_SUBNET_CLUSTER_CIDR}" \ 121 | -var "istio_subnet_services_cidr=${ISTIO_SUBNET_SERVICES_CIDR}" \ 122 | -var "gce_vm=${GCE_VM}" \ 123 | -var "gke_version=${GKE_VERSION}" \ 124 | -input=false -auto-approve) 125 | 126 | # Check for required Istio components and download if necessary 127 | if [[ ! -d "$ISTIO_DIR" ]]; then 128 | if [[ "$(uname -s)" == "Linux" ]]; then 129 | export OS_TYPE="linux" 130 | elif [[ "$(uname -s)" == "Darwin" ]]; then 131 | export OS_TYPE="osx" 132 | fi 133 | 134 | (cd "$ROOT"; 135 | curl -L --remote-name https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istio-$ISTIO_VERSION-$OS_TYPE.tar.gz 136 | # extract istio 137 | tar -xzf "$ROOT/istio-$ISTIO_VERSION-$OS_TYPE.tar.gz" 138 | 139 | # remove istio zip 140 | rm "$ROOT/istio-$ISTIO_VERSION-$OS_TYPE.tar.gz" 141 | ) 142 | fi 143 | 144 | if [[ ! "$(kubectl get clusterrolebinding --field-selector metadata.name=cluster-admin-binding \ 145 | -o jsonpath='{.items[*].metadata.name}')" ]]; then 146 | kubectl create clusterrolebinding cluster-admin-binding \ 147 | --clusterrole=cluster-admin --user="$(gcloud config get-value core/account)" 148 | fi 149 | 150 | # Add label to enable Envoy auto-injection 151 | kubectl label namespace default istio-injection=enabled --overwrite=true 152 | 153 | # wait for istio-system to be created 154 | until [ "$(kubectl get ns | grep -c istio-system)" -eq "1" ]; do echo 'waiting for ns istio-system to be created'; sleep 1; done 155 | 156 | # Install the ILBs necessary for mesh expansion 157 | kubectl apply -f "$ISTIO_DIR/install/kubernetes/mesh-expansion.yaml" 158 | 159 | # Start of mesh expansion 160 | 161 | # Export variables that will be used by the setupMeshEx script 162 | export GCP_OPTS="--zone ${ZONE} --project ${ISTIO_PROJECT}" 163 | export SERVICE_NAMESPACE=vm 164 | ( 165 | cd "$ISTIO_DIR" 166 | "$ISTIO_DIR/install/tools/setupMeshEx.sh" \ 167 | generateClusterEnv "${ISTIO_CLUSTER}" 168 | ) 169 | 170 | # Ensure that mTLS is enabled 171 | if [[ "${ISTIO_AUTH_POLICY}" == "MUTUAL_TLS" ]] ; then 172 | sed -i'' -e "s/CONTROL_PLANE_AUTH_POLICY=NONE/CONTROL_PLANE_AUTH_POLICY=${ISTIO_AUTH_POLICY}/g" "$ISTIO_DIR/cluster.env" 173 | fi 174 | 175 | # Generate the DNS configuration necessary to have the GCE VM join the mesh. 176 | ( 177 | cd "$ISTIO_DIR" 178 | "$ISTIO_DIR/install/tools/setupMeshEx.sh" generateDnsmasq 179 | ) 180 | 181 | # Create the namespace to be used by the service on the VM. 182 | kubectl apply -f "$ROOT/scripts/namespaces.yaml" 183 | 184 | # Create the keys for mTLS 185 | ( 186 | cd "$ISTIO_DIR" 187 | "$ISTIO_DIR/install/tools/setupMeshEx.sh" machineCerts default vm all 188 | ) 189 | 190 | # Re-export the GCP_OPTS to switch the project to the project where the VM 191 | # resides 192 | export GCP_OPTS="--zone ${ZONE} --project ${GCE_PROJECT}" 193 | # Setup the Istio service proxy and service on the GCE VM 194 | ( 195 | cd "$ISTIO_DIR" 196 | "$ISTIO_DIR/install/tools/setupMeshEx.sh" gceMachineSetup "${GCE_VM}" 197 | ) 198 | 199 | # Mesh expansion completed 200 | 201 | # Register the external service with the Istio mesh 202 | "$ISTIO_DIR/bin/istioctl" register -n vm mysqldb "$(gcloud compute instances describe "${GCE_VM}" \ 203 | --format='value(networkInterfaces[].networkIP)' --project "${GCE_PROJECT}" --zone "${ZONE}")" 3306 204 | 205 | # Install the bookinfo services and deployments and set up the initial Istio 206 | # routing. For more information on routing see this Istio blog post: 207 | # https://istio.io/blog/2018/v1alpha3-routing/ 208 | kubectl apply -n default \ 209 | -f "$ISTIO_DIR/samples/bookinfo/platform/kube/bookinfo.yaml" 210 | kubectl apply -n default \ 211 | -f "$ISTIO_DIR/samples/bookinfo/networking/bookinfo-gateway.yaml" 212 | kubectl apply -n default \ 213 | -f "$ISTIO_DIR/samples/bookinfo/networking/destination-rule-all-mtls.yaml" 214 | 215 | # Change the routing to point to the most recent versions of the bookinfo 216 | # microservices 217 | kubectl apply -n default \ 218 | -f "$ISTIO_DIR/samples/bookinfo/networking/virtual-service-reviews-v3.yaml" 219 | kubectl apply -n default \ 220 | -f "$ISTIO_DIR/samples/bookinfo/networking/virtual-service-ratings-mysql-vm.yaml" 221 | kubectl apply -n default \ 222 | -f "$ISTIO_DIR/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql-vm.yaml" 223 | 224 | # Install and deploy the database used by the Istio service 225 | gcloud compute ssh "${GCE_VM}" --project="${GCE_PROJECT}" --zone "${ZONE}" \ 226 | --command "$(cat "$ROOT"/scripts/setup-gce-vm.sh)" 227 | 228 | # Get the information about the gateway used by Istio to expose the BookInfo 229 | # application 230 | INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o \ 231 | jsonpath='{.status.loadBalancer.ingress[0].ip}') 232 | INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o \ 233 | jsonpath='{.spec.ports[?(@.name=="http")].port}') 234 | 235 | # Check if port is set or not. 236 | if [ -z "$INGRESS_PORT" ]; then 237 | GATEWAY_URL="${INGRESS_HOST}" 238 | else 239 | GATEWAY_URL="${INGRESS_HOST}:${INGRESS_PORT}" 240 | fi 241 | 242 | echo "You can view the service at http://${GATEWAY_URL}/productpage" 243 | -------------------------------------------------------------------------------- /scripts/istio.env: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # These are all environmental variables that can be set to change the 16 | # characteristics of the deployed infrastructure. 17 | 18 | # These two variables are the only ones that are required to be set. 19 | # They may either be pre-existing environment variables or uncommented 20 | # and set here. 21 | #ISTIO_PROJECT="" 22 | #GCE_PROJECT="" 23 | 24 | # Any of these variables can be changed to customize the deployment 25 | # Note that setting any of the following variables is completely optional 26 | 27 | # Both the REGION and ZONE variables must either both be set or neither be set. 28 | # Also, the zone used must reside in the region used, e.g. 29 | # REGION="us-west1" 30 | # ZONE="us-west1-b" 31 | REGION="us-central1" 32 | ZONE="us-central1-f" 33 | 34 | # Name to be used by the cluster 35 | ISTIO_CLUSTER="istio-cluster-vpn" 36 | 37 | # Names to be used by the network and subnet in which the cluster resides 38 | ISTIO_NETWORK="istio-network" 39 | ISTIO_SUBNET="istio-subnet" 40 | GCE_NETWORK="gce-network" 41 | GCE_SUBNET="gce-subnet" 42 | 43 | # These CIDR ranges all have defaults set in the install script. 44 | # If these are set, they cannot overlap with each other or any other used 45 | # CIDR ranges in the network, including CIDR ranges used by subnets. 46 | # 47 | # To avoid issues during deployment, if one of these is set, it is best to set 48 | # all of them. 49 | ISTIO_SUBNET_CIDR="10.0.0.0/16" 50 | ISTIO_SUBNET_CLUSTER_CIDR="10.3.0.0/17" 51 | ISTIO_SUBNET_SERVICES_CIDR="10.3.128.0/17" 52 | GCE_SUBNET_CIDR="10.1.0.0/16" 53 | 54 | # Name to be used by the GCE VM. 55 | GCE_VM="istio-vpn-vm" 56 | 57 | # Istio specific variables. 58 | # NOT: Beware when changing these as the scripts provided by the Istio project 59 | # can change significantly from version to version. This demo has only been 60 | # tested with Istio version 0.8.0 and auth turned off. 61 | ISTIO_VERSION="1.0.6" 62 | ISTIO_AUTH_POLICY="MUTUAL_TLS" 63 | 64 | # For "hosted istio", the GKE version and the istio version must match according 65 | # to the table "Supported Cluster Versions": 66 | # https://cloud.google.com/istio/docs/istio-on-gke/installing 67 | ISTIO_GKE_VERSION="1.0.6-gke.3" 68 | GKE_VERSION="1.12.7-gke.25" 69 | -------------------------------------------------------------------------------- /scripts/namespaces.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: v1 16 | kind: Namespace 17 | metadata: 18 | name: vm 19 | --- 20 | apiVersion: v1 21 | kind: Namespace 22 | metadata: 23 | name: bookinfo 24 | -------------------------------------------------------------------------------- /scripts/setup-gce-vm.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Install MySQL and load the data for the MySQL service 18 | 19 | set -e 20 | 21 | sudo apt-get update && sudo apt-get install --no-install-recommends -y mariadb-server 22 | 23 | # Give all privileges to all databases to the root user on localhost and then 24 | # reload the privilege grants 25 | sudo mysql \ 26 | -e "grant all privileges on *.* to 'root'@'localhost' identified by 'password'; flush privileges" 27 | 28 | # Grab the sample database data from GitHub and load it 29 | # Of course, it goes without saying that you should not use "password" as your 30 | # password in real life. 31 | curl https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/src/mysql/mysqldb-init.sql \ 32 | | mysql -u root --password=password -h 127.0.0.1 33 | 34 | # Configure Envoy to integrate with the GKE Istio mesh 35 | sudo sed -i -e "\$aISTIO_INBOUND_PORTS=3306" /var/lib/istio/envoy/sidecar.env 36 | sudo sed -i -e "\$aISTIO_SERVICE=mysqldb" /var/lib/istio/envoy/sidecar.env 37 | sudo sed -i -e "\$aISTIO_NAMESPACE=vm" /var/lib/istio/envoy/sidecar.env 38 | 39 | sudo systemctl restart istio 40 | -------------------------------------------------------------------------------- /scripts/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -x 18 | 19 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 20 | # shellcheck source=scripts/istio.env 21 | source "$ROOT/scripts/istio.env" 22 | #ISTIO_DIR="$ROOT/istio-${ISTIO_VERSION}" 23 | 24 | kubectl delete ns vm --ignore-not-found=true 25 | kubectl delete ns bookinfo --ignore-not-found=true 26 | 27 | # Disable the Istio GKE Addon to prevent it from automatically 28 | # recreating Istio services which create load balancers and 29 | # firewall rules which would block a successful TF destroy. 30 | gcloud beta container clusters update "${ISTIO_CLUSTER}" \ 31 | --project "${ISTIO_PROJECT}" --zone="${ZONE}" \ 32 | --update-addons=Istio=DISABLED 33 | 34 | # Wait until all LBs have been cleaned up by the addon manager 35 | echo "Deleting Istio ILBs" 36 | for ISTIO_LB_NAME in istio-ingressgateway istio-pilot-ilb mixer-ilb; do 37 | until [[ "$(kubectl get svc -n istio-system ${ISTIO_LB_NAME} -o=jsonpath="{.metadata.name}" --ignore-not-found=true)" == "" ]]; do 38 | echo "Waiting for istio-system ${ISTIO_LB_NAME} to be removed..." 39 | sleep 2 40 | done 41 | done 42 | 43 | # If kube-system/dns-lib svc is present, delete it 44 | kubectl delete svc -n kube-system dns-ilb --ignore-not-found=true 45 | # Wait until its gone 46 | until [[ "$(kubectl get svc -n kube-system dns-ilb -o=jsonpath="{.metadata.name}" --ignore-not-found=true)" == "" ]]; do 47 | echo "Waiting for kube-system dns-ilb to be removed..." 48 | sleep 5 49 | done 50 | 51 | # Loop until the ILBs are fully gone 52 | until [[ "$(gcloud --project="${ISTIO_PROJECT}" compute forwarding-rules list --format="value(name)" --filter "(description ~ istio-system.*ilb OR description:kube-system/dns-ilb) AND network ~ /istio-network$")" == "" ]]; do 53 | # Find all internal (ILB) forwarding rules in the network: istio-network 54 | FWDING_RULE_NAMES="$(gcloud --project="${ISTIO_PROJECT}" compute forwarding-rules list --format="value(name)" --filter "(description ~ istio-system.*ilb OR description:kube-system/dns-ilb) AND network ~ /istio-network$")" 55 | # Iterate and delete the forwarding rule by name and its corresponding backend-service by the same name 56 | for FWD_RULE in ${FWDING_RULE_NAMES}; do 57 | gcloud --project="${ISTIO_PROJECT}" compute forwarding-rules delete "${FWD_RULE}" --region="${REGION}" || true 58 | gcloud --project="${ISTIO_PROJECT}" compute backend-services delete "${FWD_RULE}" --region="${REGION}" || true 59 | done 60 | sleep 2 61 | done 62 | 63 | # Loop until the target-pools and health checks are fully gone 64 | until [[ "$(gcloud --project="${ISTIO_PROJECT}" compute target-pools list --format="value(name)" --filter="(instances ~ gke-${ISTIO_CLUSTER})")" == "" && "$(gcloud --project="${ISTIO_PROJECT}" compute target-pools list --format="value(healthChecks)" --filter="(instances ~ gke-${ISTIO_CLUSTER})" | sed 's/.*\/\(k8s\-.*$\)/\1/g')" == "" ]]; do 65 | # Find all target pools with this cluster as the target by name 66 | TARGET_POOLS="$(gcloud --project="${ISTIO_PROJECT}" compute target-pools list --format="value(name)" --filter="(instances ~ gke-${ISTIO_CLUSTER})")" 67 | # Find all health checks with this cluster's nodes as the instances 68 | HEALTH_CHECKS="$( gcloud --project="${ISTIO_PROJECT}" compute target-pools list --format="value(healthChecks)" --filter="(instances ~ gke-${ISTIO_CLUSTER})" | sed 's/.*\/\(k8s\-.*$\)/\1/g')" 69 | # Delete the external (RLB) forwarding rules by name and the target pool by the same name 70 | for TARGET_POOL in ${TARGET_POOLS}; do 71 | gcloud --project="${ISTIO_PROJECT}" compute forwarding-rules delete "${TARGET_POOL}" --region="${REGION}" || true 72 | gcloud --project="${ISTIO_PROJECT}" compute target-pools delete "${TARGET_POOL}" --region="${REGION}" || true 73 | done 74 | # Delete the leftover health check by name 75 | for HEALTH_CHECK in ${HEALTH_CHECKS}; do 76 | gcloud --project="${ISTIO_PROJECT}" compute health-checks delete "${HEALTH_CHECK}" || true 77 | done 78 | sleep 2 79 | done 80 | 81 | # Delete all the firewall rules that aren't named like our cluster name which 82 | # correspond to our health checks and load balancers that are dynamically created. 83 | # This is because GKE manages those named with the cluster name get cleaned 84 | # up with a terraform destroy. 85 | until [[ "$(gcloud --project="${ISTIO_PROJECT}" compute firewall-rules list --format "value(name)" --filter "targetTags.list():gke-${ISTIO_CLUSTER} AND NOT name ~ gke-${ISTIO_CLUSTER}")" == "" ]]; do 86 | FW_RULES="$(gcloud --project="${ISTIO_PROJECT}" compute firewall-rules list --format "value(name)" --filter "targetTags.list():gke-${ISTIO_CLUSTER} AND NOT name ~ gke-${ISTIO_CLUSTER}")" 87 | for FW_RULE in ${FW_RULES}; do 88 | gcloud --project="${ISTIO_PROJECT}" compute firewall-rules delete "${FW_RULE}" || true 89 | done 90 | sleep 2 91 | done 92 | 93 | # Tear down all of the infrastructure created by Terraform 94 | (cd "$ROOT/terraform"; terraform init; terraform destroy -input=false -auto-approve\ 95 | -var "istio_project=${ISTIO_PROJECT}" \ 96 | -var "gce_project=${GCE_PROJECT}" \ 97 | -var "istio_cluster=${ISTIO_CLUSTER}" \ 98 | -var "zone=${ZONE}" \ 99 | -var "region=${REGION}" \ 100 | -var "gce_network=${GCE_NETWORK}" \ 101 | -var "gce_subnet=${GCE_SUBNET}" \ 102 | -var "gce_subnet_cidr=${GCE_SUBNET_CIDR}" \ 103 | -var "istio_network=${ISTIO_NETWORK}" \ 104 | -var "istio_subnet=${ISTIO_SUBNET}" \ 105 | -var "istio_subnet_cidr=${ISTIO_SUBNET_CIDR}" \ 106 | -var "istio_subnet_cluster_cidr=${ISTIO_SUBNET_CLUSTER_CIDR}" \ 107 | -var "istio_subnet_services_cidr=${ISTIO_SUBNET_SERVICES_CIDR}" \ 108 | -var "gke_version=${GKE_VERSION}" \ 109 | -var "gce_vm=${GCE_VM}") 110 | 111 | # Clean up the downloaded Istio components 112 | if [[ -d "$ROOT/istio-$ISTIO_VERSION" ]]; then 113 | rm -rf istio-$ISTIO_VERSION 114 | fi 115 | -------------------------------------------------------------------------------- /scripts/validate.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 20 | 21 | ISTIO_SHARED_DIR="${ROOT}/gke-istio-shared" 22 | 23 | # Source utility functions for checking the existence of various resources. 24 | # shellcheck source=gke-istio-shared/verify-functions.sh 25 | source "${ISTIO_SHARED_DIR}/verify-functions.sh" 26 | 27 | dependency_installed "kubectl" 28 | 29 | # shellcheck source=gke-istio-shared/verify-db-ratings.sh 30 | source "${ISTIO_SHARED_DIR}/verify-db-ratings.sh" "$((1 + RANDOM % 5))" 31 | -------------------------------------------------------------------------------- /terraform/main.tf: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | # Create two new networks to be used for the demo: one in the project housing the 18 | # GKE cluster and one in the project housing the GCE instance. 19 | resource "google_compute_network" "istio" { 20 | name = var.istio_network 21 | auto_create_subnetworks = "false" 22 | project = var.istio_project 23 | } 24 | 25 | resource "google_compute_network" "gce" { 26 | name = var.gce_network 27 | auto_create_subnetworks = "false" 28 | project = var.gce_project 29 | } 30 | 31 | # Create a subnet with secondary IP ranges to be used for GKE's IP aliasing: 32 | # https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips 33 | resource "google_compute_subnetwork" "subnet_istio" { 34 | name = var.istio_subnet 35 | network = google_compute_network.istio.self_link 36 | ip_cidr_range = var.istio_subnet_cidr 37 | 38 | secondary_ip_range { 39 | range_name = "istio-cluster-cidr" 40 | ip_cidr_range = var.istio_subnet_cluster_cidr 41 | } 42 | secondary_ip_range { 43 | range_name = "istio-services-cidr" 44 | ip_cidr_range = var.istio_subnet_services_cidr 45 | } 46 | 47 | project = var.istio_project 48 | region = var.region 49 | } 50 | 51 | # Create a regular subnet to be used by the GCE instance. 52 | resource "google_compute_subnetwork" "subnet_gce" { 53 | name = var.gce_subnet 54 | network = google_compute_network.gce.self_link 55 | ip_cidr_range = var.gce_subnet_cidr 56 | project = var.gce_project 57 | region = var.region 58 | } 59 | 60 | # All of the forwarding rule, VPN gateway, IP address, and tunnel resources are 61 | # necessary for a properly functioning VPN. For more information on why these 62 | # resources are required, see the explanation provided for creating a route- 63 | # based VPN using gcloud: 64 | # https://cloud.google.com/vpn/docs/how-to/creating-route-based-vpns 65 | resource "google_compute_vpn_gateway" "target_gateway_istio" { 66 | name = "vpn-istio" 67 | project = var.istio_project 68 | network = google_compute_network.istio.self_link 69 | region = google_compute_subnetwork.subnet_istio.region 70 | } 71 | 72 | resource "google_compute_vpn_gateway" "target_gateway_gce" { 73 | name = "vpn-gce" 74 | project = var.gce_project 75 | network = google_compute_network.gce.self_link 76 | region = google_compute_subnetwork.subnet_gce.region 77 | } 78 | 79 | resource "google_compute_address" "vpn_static_ip_istio" { 80 | name = "vpn-static-ip-istio" 81 | project = var.istio_project 82 | region = google_compute_subnetwork.subnet_istio.region 83 | } 84 | 85 | resource "google_compute_address" "vpn_static_ip_gce" { 86 | name = "vpn-static-ip-gce" 87 | project = var.gce_project 88 | region = google_compute_subnetwork.subnet_gce.region 89 | } 90 | 91 | resource "google_compute_forwarding_rule" "fr_esp_istio" { 92 | name = "fr-esp-istio" 93 | ip_protocol = "ESP" 94 | ip_address = google_compute_address.vpn_static_ip_istio.address 95 | target = google_compute_vpn_gateway.target_gateway_istio.self_link 96 | project = var.istio_project 97 | } 98 | 99 | resource "google_compute_forwarding_rule" "fr_esp_gce" { 100 | name = "fr-esp-gce" 101 | ip_protocol = "ESP" 102 | ip_address = google_compute_address.vpn_static_ip_gce.address 103 | target = google_compute_vpn_gateway.target_gateway_gce.self_link 104 | project = var.gce_project 105 | } 106 | 107 | resource "google_compute_forwarding_rule" "fr_udp500_istio" { 108 | name = "fr-udp500-istio" 109 | ip_protocol = "UDP" 110 | port_range = "500-500" 111 | ip_address = google_compute_address.vpn_static_ip_istio.address 112 | target = google_compute_vpn_gateway.target_gateway_istio.self_link 113 | project = var.istio_project 114 | } 115 | 116 | resource "google_compute_forwarding_rule" "fr_udp500_gce" { 117 | name = "fr-udp500-gce" 118 | ip_protocol = "UDP" 119 | port_range = "500-500" 120 | ip_address = google_compute_address.vpn_static_ip_gce.address 121 | target = google_compute_vpn_gateway.target_gateway_gce.self_link 122 | project = var.gce_project 123 | } 124 | 125 | resource "google_compute_forwarding_rule" "fr_udp4500_gce" { 126 | name = "fr-udp4500-gce" 127 | ip_protocol = "UDP" 128 | port_range = "4500-4500" 129 | ip_address = google_compute_address.vpn_static_ip_gce.address 130 | target = google_compute_vpn_gateway.target_gateway_gce.self_link 131 | project = var.gce_project 132 | } 133 | 134 | resource "google_compute_forwarding_rule" "fr_udp4500_istio" { 135 | name = "fr-udp4500-istio" 136 | ip_protocol = "UDP" 137 | port_range = "4500-4500" 138 | ip_address = google_compute_address.vpn_static_ip_istio.address 139 | target = google_compute_vpn_gateway.target_gateway_istio.self_link 140 | project = var.istio_project 141 | } 142 | 143 | resource "google_compute_vpn_tunnel" "tunnel1_istio" { 144 | name = "tunnel1-istio" 145 | peer_ip = google_compute_address.vpn_static_ip_gce.address 146 | shared_secret = "a secret message" 147 | project = var.istio_project 148 | 149 | target_vpn_gateway = google_compute_vpn_gateway.target_gateway_istio.self_link 150 | 151 | local_traffic_selector = ["0.0.0.0/0"] 152 | 153 | remote_traffic_selector = ["0.0.0.0/0"] 154 | 155 | depends_on = [ 156 | google_compute_forwarding_rule.fr_esp_istio, 157 | google_compute_forwarding_rule.fr_udp500_istio, 158 | google_compute_forwarding_rule.fr_udp4500_istio, 159 | ] 160 | } 161 | 162 | resource "google_compute_vpn_tunnel" "tunnel1_gce" { 163 | name = "tunnel1-gce" 164 | peer_ip = google_compute_address.vpn_static_ip_istio.address 165 | shared_secret = "a secret message" 166 | project = var.gce_project 167 | 168 | target_vpn_gateway = google_compute_vpn_gateway.target_gateway_gce.self_link 169 | 170 | local_traffic_selector = ["0.0.0.0/0"] 171 | 172 | remote_traffic_selector = ["0.0.0.0/0"] 173 | 174 | depends_on = [ 175 | google_compute_forwarding_rule.fr_esp_gce, 176 | google_compute_forwarding_rule.fr_udp500_gce, 177 | google_compute_forwarding_rule.fr_udp4500_gce, 178 | ] 179 | } 180 | 181 | # Ensures that traffic in the Istio project destined for the GCE VM is routed 182 | # to the VPN 183 | resource "google_compute_route" "route_istio" { 184 | name = "route-istio" 185 | network = google_compute_network.istio.name 186 | dest_range = google_compute_subnetwork.subnet_gce.ip_cidr_range 187 | priority = 1000 188 | project = var.istio_project 189 | 190 | next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel1_istio.self_link 191 | } 192 | 193 | # Ensures that traffic destined for a pod in the GKE cluster in the GCE project 194 | # is routed to the VPN 195 | resource "google_compute_route" "route_gce_cluster_cidr" { 196 | name = "route-istio-cluster-cidr" 197 | network = google_compute_network.gce.name 198 | 199 | # TODO: figure out how to use declared subnet ranges instead of the variable 200 | dest_range = google_compute_subnetwork.subnet_istio.secondary_ip_range[0].ip_cidr_range 201 | priority = 1000 202 | project = var.gce_project 203 | 204 | next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel1_gce.self_link 205 | } 206 | 207 | # Ensures that traffic destined for a service in the GKE cluster from the GCE \ 208 | # project is routed to the VPN 209 | resource "google_compute_route" "route_gce_services_cidr" { 210 | name = "route-istio-services-cidr" 211 | network = google_compute_network.gce.name 212 | 213 | # TODO: figure out how to use declared subnet ranges instead of the variable 214 | dest_range = google_compute_subnetwork.subnet_istio.secondary_ip_range[1].ip_cidr_range 215 | priority = 1000 216 | project = var.gce_project 217 | 218 | next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel1_gce.self_link 219 | } 220 | 221 | # Routes traffic destined for the GKE cluster subnet in the GCE project over 222 | # the VPN 223 | resource "google_compute_route" "route_gce" { 224 | name = "route-gce" 225 | network = google_compute_network.gce.name 226 | dest_range = google_compute_subnetwork.subnet_istio.ip_cidr_range 227 | priority = 1000 228 | project = var.gce_project 229 | 230 | next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel1_gce.self_link 231 | } 232 | 233 | # Allows SSH traffic from anywhere to the database VM 234 | resource "google_compute_firewall" "allow_ssh" { 235 | name = "allow-gce-ssh" 236 | project = var.gce_project 237 | network = google_compute_network.gce.name 238 | 239 | source_ranges = ["0.0.0.0/0"] 240 | target_tags = ["mysql"] 241 | 242 | allow { 243 | ports = ["22"] 244 | protocol = "tcp" 245 | } 246 | } 247 | 248 | # Allows database traffic from the GKE cluster to the database VM 249 | resource "google_compute_firewall" "allow_mysql" { 250 | name = "allow-gce-mysql" 251 | project = var.gce_project 252 | network = google_compute_network.gce.name 253 | 254 | source_ranges = [ 255 | google_compute_subnetwork.subnet_istio.secondary_ip_range[0].ip_cidr_range, 256 | google_compute_subnetwork.subnet_istio.secondary_ip_range[1].ip_cidr_range, 257 | ] 258 | 259 | target_tags = ["mysql"] 260 | 261 | allow { 262 | protocol = "tcp" 263 | ports = ["3306"] 264 | } 265 | } 266 | 267 | # Creates a GKE cluster to be used in the demo 268 | resource "google_container_cluster" "istio_cluster" { 269 | name = var.istio_cluster 270 | zone = var.zone 271 | project = var.istio_project 272 | network = google_compute_network.istio.self_link 273 | subnetwork = google_compute_subnetwork.subnet_istio.self_link 274 | min_master_version = var.gke_version 275 | 276 | initial_node_count = "4" 277 | 278 | provider = google-beta 279 | 280 | addons_config { 281 | istio_config { 282 | disabled = false 283 | auth = "AUTH_MUTUAL_TLS" 284 | } 285 | } 286 | 287 | // We specify the type of node to use. 288 | node_config { 289 | machine_type = "n1-standard-2" 290 | } 291 | 292 | ip_allocation_policy { 293 | # TODO: figure out how to use variables for these networks 294 | cluster_secondary_range_name = google_compute_subnetwork.subnet_istio.secondary_ip_range[0].range_name 295 | services_secondary_range_name = google_compute_subnetwork.subnet_istio.secondary_ip_range[1].range_name 296 | } 297 | 298 | # Here we use gcloud to gather authentication information about our new cluster and write that 299 | # information to kubectls config file 300 | provisioner "local-exec" { 301 | command = "gcloud container clusters get-credentials ${google_container_cluster.istio_cluster.name} --zone ${google_container_cluster.istio_cluster.zone} --project ${var.istio_project}" 302 | } 303 | } 304 | 305 | # Creates a GCE instance to be used for the database. The tag is necessary to 306 | # apply the correct firewall rules. 307 | resource "google_compute_instance" "default" { 308 | name = var.gce_vm 309 | machine_type = "n1-standard-1" 310 | project = var.gce_project 311 | zone = var.zone 312 | 313 | boot_disk { 314 | initialize_params { 315 | image = "debian-cloud/debian-9" 316 | } 317 | } 318 | 319 | tags = ["mysql"] 320 | 321 | network_interface { 322 | subnetwork = google_compute_subnetwork.subnet_gce.self_link 323 | access_config { 324 | } 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /terraform/provider.tf: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | provider "google-beta" { 18 | version = "~> v2.10.0" 19 | region = var.region 20 | } 21 | 22 | provider "google" { 23 | version = "~> v2.10.0" 24 | region = var.region 25 | } 26 | -------------------------------------------------------------------------------- /terraform/variables.tf: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // The project used to deploy the GKE cluster 18 | variable "istio_project" { 19 | } 20 | 21 | // The project used to deploy the GCE instance 22 | variable "gce_project" { 23 | } 24 | 25 | // The name of the network to create for the GKE cluster 26 | variable "istio_network" { 27 | } 28 | 29 | // The name of the network to create for the GCE instance 30 | variable "gce_network" { 31 | } 32 | 33 | // The name to use for the GKE cluster 34 | variable "istio_cluster" { 35 | } 36 | 37 | // NOTE: The zone selected must reside in the selected region 38 | // The region in which to deploy all regionally-scoped resources 39 | variable "region" { 40 | } 41 | 42 | // The zone in which to deploy all zonally-scoped resources 43 | variable "zone" { 44 | } 45 | 46 | // The subnet used to deploy the GKE cluster 47 | variable "istio_subnet" { 48 | } 49 | 50 | // The CIDR used by the GKE cluster's subnet 51 | variable "istio_subnet_cidr" { 52 | } 53 | 54 | // The alias IP CIDR used by the GKE cluster's pods 55 | variable "istio_subnet_cluster_cidr" { 56 | } 57 | 58 | // The alias IP CIDR used by the GKE cluster's services 59 | variable "istio_subnet_services_cidr" { 60 | } 61 | 62 | // The subnet used by the GCE instance 63 | variable "gce_subnet" { 64 | } 65 | 66 | // The CIDR used by the GCE instance's subnet 67 | variable "gce_subnet_cidr" { 68 | } 69 | 70 | // The name to use for the GCE instance 71 | variable "gce_vm" { 72 | } 73 | 74 | // The gke version to use for the istio cluster. This version must correspond 75 | // with the istio version in "Supported Cluster Versions": 76 | // https://cloud.google.com/istio/docs/istio-on-gke/installing 77 | variable "gke_version" { 78 | } 79 | 80 | -------------------------------------------------------------------------------- /terraform/versions.tf: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 0.12" 19 | } 20 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.BUILD.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.Dockerfile.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.Makefile.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.WORKSPACE.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.bazel.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.bzl.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.css.txt: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.go.preamble: -------------------------------------------------------------------------------- 1 | // +build 2 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.html.preamble: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.java.txt: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.js.txt: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.py.preamble: -------------------------------------------------------------------------------- 1 | #! 2 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.py.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.scss.txt: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.sh.preamble: -------------------------------------------------------------------------------- 1 | #! 2 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.sh.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.tf.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.ts.txt: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.xml.preamble: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /test/boilerplate/boilerplate.yaml.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/make.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This function checks to make sure that every 18 | # shebang has a '- e' flag, which causes it 19 | # to exit on error 20 | function check_bash() { 21 | find . -name "*.sh" | while IFS= read -d '' -r file; 22 | do 23 | if [[ "$file" != *"bash -e"* ]]; 24 | then 25 | echo "$file is missing shebang with -e"; 26 | exit 1; 27 | fi; 28 | done; 29 | } 30 | 31 | # This function makes sure that the required files for 32 | # releasing to OSS are present 33 | function basefiles() { 34 | echo "Checking for required files" 35 | test -f CONTRIBUTING.md || echo "Missing CONTRIBUTING.md" 36 | test -f LICENSE || echo "Missing LICENSE" 37 | test -f README.md || echo "Missing README.md" 38 | } 39 | 40 | # This function runs the hadolint linter on 41 | # every file named 'Dockerfile' 42 | function docker() { 43 | echo "Running hadolint on Dockerfiles" 44 | find . -name "Dockerfile" -exec hadolint {} \; 45 | } 46 | 47 | # This function runs 'terraform validate' against all 48 | # files ending in '.tf' 49 | function check_terraform() { 50 | echo "Running terraform validate" 51 | #shellcheck disable=SC2156 52 | find . -name "*.tf" -exec bash -c 'terraform validate --check-variables=false $(dirname "{}")' \; 53 | } 54 | 55 | # This function runs 'go fmt' and 'go vet' on eery file 56 | # that ends in '.go' 57 | function golang() { 58 | echo "Running go fmt and go vet" 59 | find . -name "*.go" -exec go fmt {} \; 60 | find . -name "*.go" -exec go vet {} \; 61 | } 62 | 63 | # This function runs the flake8 linter on every file 64 | # ending in '.py' 65 | function check_python() { 66 | echo "Running flake8" 67 | find . -name "*.py" -exec flake8 {} \; 68 | } 69 | 70 | # This function runs the shellcheck linter on every 71 | # file ending in '.sh' 72 | function check_shell() { 73 | echo "Running shellcheck" 74 | find . -name "*.sh" -exec shellcheck -x {} \; 75 | } 76 | 77 | # This function makes sure that there is no trailing whitespace 78 | # in any files in the project. 79 | # There are some exclusions 80 | function check_trailing_whitespace() { 81 | echo "The following lines have trailing whitespace" 82 | grep -r '[[:blank:]]$' --exclude-dir=".terraform" --exclude="*.png" --exclude-dir=".git" --exclude="*.pyc" . 83 | rc=$? 84 | if [ $rc = 0 ]; then 85 | exit 1 86 | fi 87 | } 88 | -------------------------------------------------------------------------------- /test/verify_boilerplate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.7 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # Verifies that all source files contain the necessary copyright boilerplate 16 | # snippet. 17 | 18 | # This code is based on existing work 19 | # https://partner-code.googlesource.com/helmsman-cardinal/+/refs/heads/master/helmsman-template-project/test/verify_boilerplate.py 20 | 21 | 22 | """ 23 | A runnable module to test the presence of boilerplate 24 | text in files within a repo. 25 | """ 26 | 27 | from __future__ import print_function 28 | from subprocess import run, CalledProcessError 29 | import argparse 30 | import glob 31 | import os 32 | import re 33 | import sys 34 | 35 | 36 | # These directories will be omitted from header checks 37 | SKIPPED_PATHS = [ 38 | 'Godeps', 'third_party', '_gopath', '_output', 39 | '.git', 'vendor', '__init__.py', 'node_modules', 40 | 'bazel-out', 'external', '3rdparty' 41 | ] 42 | 43 | # A map of regular expressions used in boilerplate validation. 44 | # The date regex is used in validating the date referenced 45 | # is the boilerplate, by ensuring it is an acceptable year. 46 | REGEXES = { 47 | # beware the Y2100 problem 48 | "date": re.compile(r'(20\d\d)') 49 | } 50 | 51 | 52 | def get_args(): 53 | """Parses command line arguments. 54 | Configures and runs argparse.ArgumentParser to extract command line 55 | arguments. 56 | Returns: 57 | An argparse.Namespace containing the arguments parsed from the 58 | command line 59 | """ 60 | parser = argparse.ArgumentParser() 61 | 62 | parser.add_argument("filenames", 63 | help="""A list of files to check, all in repo are 64 | checked if this is unspecified.""", 65 | nargs='*') 66 | 67 | parser.add_argument("-f", "--force-extension", 68 | default="", 69 | help="""Force an extension to compare against. Useful 70 | for files without extensions, such as runnable shell 71 | scripts .""") 72 | 73 | parser.add_argument( 74 | "-r", "--rootdir", 75 | default=None, 76 | help="""Root directory of repository. If not specified, the script will 77 | attempt to draw this value from git.""") 78 | 79 | parser.add_argument("-b", "--boilerplate-dir", 80 | default=None, 81 | help="""Directory with boilerplate files. Defaults to 82 | [root]/test/boilerplate.""") 83 | 84 | args = parser.parse_args() 85 | 86 | if not args.rootdir: 87 | ask_git = run( 88 | ["git", "rev-parse", "--show-toplevel"], 89 | capture_output=True, text=True) 90 | try: 91 | ask_git.check_returncode() 92 | except CalledProcessError: 93 | print("""No root specfied and directory does not seem to be a git 94 | repository, or git is not installed.""", file=sys.stderr) 95 | sys.exit(1) 96 | args.rootdir = ask_git.stdout.strip() 97 | 98 | if not args.boilerplate_dir: 99 | args.boilerplate_dir = os.path.join(args.rootdir, "test/boilerplate") 100 | 101 | return args 102 | 103 | 104 | def get_references(args): 105 | """Reads each reference boilerplate file's contents into an array, then 106 | adds that array to a dictionary keyed by the file extension. 107 | 108 | Returns: 109 | A dictionary of boilerplate lines, keyed by file extension. 110 | For example, boilerplate.py.txt would result in the 111 | k,v pair {".py": py_lines} where py_lines is an array 112 | containing each line of the file. 113 | """ 114 | references = {} 115 | 116 | # Find all paths for boilerplate references 117 | boilerplate_paths = glob.glob( 118 | os.path.join(args.boilerplate_dir, "boilerplate.*.txt")) 119 | 120 | # Read all boilerplate references into dictionary 121 | for path in boilerplate_paths: 122 | with open(path, 'r') as ref_file: 123 | extension = os.path.basename(path).split(".")[1] 124 | ref = ref_file.read().splitlines() 125 | references[extension] = ref 126 | 127 | return references 128 | 129 | 130 | # Improvement: combine this function with `get_references` 131 | def get_preambles(args): 132 | """Reads each preamble boilerplate file's contents into an array, then 133 | adds that array to a dictionary keyed by the file extension. 134 | 135 | Returns: 136 | A dictionary of boilerplate lines, keyed by file extension. 137 | For example, boilerplate.py.preamble would result 138 | in the k,v pair {".py": py_lines} where py_lines is 139 | an array containing each line of the file 140 | (ex: "#!/usr/bin/env python3.7") 141 | """ 142 | preambles = {} 143 | 144 | # Find all paths for boilerplate preambles 145 | boilerplate_paths = glob.glob( 146 | os.path.join(args.boilerplate_dir, "boilerplate.*.preamble")) 147 | 148 | # Read all boilerplate preambles into dictionary 149 | for path in boilerplate_paths: 150 | with open(path, 'r') as ref_file: 151 | extension = os.path.basename(path).split(".")[1] 152 | ref = ref_file.read().splitlines() 153 | preambles[extension] = ref 154 | 155 | return preambles 156 | 157 | 158 | def has_valid_header(filename, references, preambles, regexs, args): 159 | """Test whether a file has the correct boilerplate header. 160 | Tests each file against the boilerplate stored in refs for that file type 161 | (based on extension), or by the entire filename (eg Dockerfile, Makefile). 162 | Some heuristics are applied to remove build tags and shebangs, but little 163 | variance in header formatting is tolerated. 164 | Args: 165 | filename: A string containing the name of the file to test 166 | references: A map of reference boilerplate text, 167 | keyed by file extension 168 | preambles: A map of preamble boilerplate text, keyed by file extension 169 | regexs: a map of compiled regex objects used in verifying boilerplate 170 | Returns: 171 | True if the file has the correct boilerplate header, otherwise returns 172 | False. 173 | """ 174 | # Read the entire file. 175 | with open(filename, 'r') as test_file: 176 | data = test_file.read() 177 | 178 | # Select the appropriate reference based on the extension, 179 | # or if none, the file name. 180 | basename, extension = get_file_parts(filename) 181 | if args.force_extension: 182 | extension = args.force_extension 183 | elif extension: 184 | extension = extension 185 | else: 186 | extension = basename 187 | ref = references[extension] 188 | print("Verifying boilerplate in file: %s as %s" % ( 189 | os.path.relpath(filename, args.rootdir), 190 | extension)) 191 | 192 | preamble = preambles.get(extension) 193 | if preamble: 194 | preamble = re.escape("\n".join(preamble)) 195 | regflags = re.MULTILINE | re.IGNORECASE 196 | regex = re.compile(r"^(%s.*\n)\n*" % preamble, regflags) 197 | (data, _) = regex.subn("", data, 1) 198 | 199 | data = data.splitlines() 200 | 201 | # if our test file is smaller than the reference it surely fails! 202 | if len(ref) > len(data): 203 | return False 204 | # truncate our file to the same number of lines as the reference file 205 | data = data[:len(ref)] 206 | 207 | # if we don't match the reference at this point, fail 208 | if ref != data: 209 | return False 210 | 211 | return True 212 | 213 | 214 | def get_file_parts(filename): 215 | """Extracts the basename and extension parts of a filename. 216 | Identifies the extension as everything after the last period in filename. 217 | Args: 218 | filename: string containing the filename 219 | Returns: 220 | A tuple of: 221 | A string containing the basename 222 | A string containing the extension in lowercase 223 | """ 224 | extension = os.path.splitext(filename)[1].split(".")[-1].lower() 225 | basename = os.path.basename(filename) 226 | return basename, extension 227 | 228 | 229 | def normalize_files(files, args): 230 | """Extracts the files that require boilerplate checking from the files 231 | argument. 232 | A new list will be built. Each path from the original files argument will 233 | be added unless it is within one of SKIPPED_DIRS. All relative paths will 234 | be converted to absolute paths by prepending the root_dir path parsed from 235 | the command line, or its default value. 236 | Args: 237 | files: a list of file path strings 238 | Returns: 239 | A modified copy of the files list where any any path in a skipped 240 | directory is removed, and all paths have been made absolute. 241 | """ 242 | newfiles = [f for f in files if not any(s in f for s in SKIPPED_PATHS)] 243 | 244 | for idx, pathname in enumerate(newfiles): 245 | if not os.path.isabs(pathname): 246 | newfiles[idx] = os.path.join(args.rootdir, pathname) 247 | return newfiles 248 | 249 | 250 | def get_files(extensions, args): 251 | """Generates a list of paths whose boilerplate should be verified. 252 | If a list of file names has been provided on the command line, it will be 253 | treated as the initial set to search. Otherwise, all paths within rootdir 254 | will be discovered and used as the initial set. 255 | Once the initial set of files is identified, it is normalized via 256 | normalize_files() and further stripped of any file name whose extension is 257 | not in extensions. 258 | Args: 259 | extensions: a list of file extensions indicating which file types 260 | should have their boilerplate verified 261 | Returns: 262 | A list of absolute file paths 263 | """ 264 | files = [] 265 | if args.filenames: 266 | files = args.filenames 267 | else: 268 | for root, dirs, walkfiles in os.walk(args.rootdir): 269 | # don't visit certain dirs. This is just a performance improvement 270 | # as we would prune these later in normalize_files(). But doing it 271 | # cuts down the amount of filesystem walking we do and cuts down 272 | # the size of the file list 273 | for dpath in SKIPPED_PATHS: 274 | if dpath in dirs: 275 | dirs.remove(dpath) 276 | for name in walkfiles: 277 | pathname = os.path.join(root, name) 278 | files.append(pathname) 279 | files = normalize_files(files, args) 280 | outfiles = [] 281 | for pathname in files: 282 | basename, extension = get_file_parts(pathname) 283 | extension_present = extension in extensions or basename in extensions 284 | if args.force_extension or extension_present: 285 | outfiles.append(pathname) 286 | return outfiles 287 | 288 | 289 | def main(args): 290 | """Identifies and verifies files that should have the desired boilerplate. 291 | Retrieves the lists of files to be validated and tests each one in turn. 292 | If all files contain correct boilerplate, this function terminates 293 | normally. Otherwise it prints the name of each non-conforming file and 294 | exists with a non-zero status code. 295 | """ 296 | refs = get_references(args) 297 | preambles = get_preambles(args) 298 | filenames = get_files(refs.keys(), args) 299 | nonconforming_files = [] 300 | for filename in filenames: 301 | if not has_valid_header(filename, refs, preambles, REGEXES, args): 302 | nonconforming_files.append(filename) 303 | if nonconforming_files: 304 | print('%d files have incorrect boilerplate headers:' % len( 305 | nonconforming_files)) 306 | for filename in sorted(nonconforming_files): 307 | print(os.path.relpath(filename, args.rootdir)) 308 | sys.exit(1) 309 | else: 310 | print('All files examined have correct boilerplate.') 311 | 312 | 313 | if __name__ == "__main__": 314 | ARGS = get_args() 315 | main(ARGS) 316 | --------------------------------------------------------------------------------