├── .github ├── CODEOWNERS └── workflows │ ├── terraform-master.yml │ └── terraform.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── auth ├── configs │ └── dex.yaml ├── dex.tf ├── main.tf ├── manifests │ ├── dex-crd.yaml │ └── oidc-authservice.yaml ├── oidc-authservice.tf └── variables.tf ├── cert-manager.tf ├── go.mod ├── go.sum ├── istio ├── main.tf ├── manifests │ ├── istio-deployment.yaml │ ├── kiali.yaml │ └── operator-crd.yaml ├── operator.tf ├── outputs.tf ├── rbac.tf └── variables.tf ├── kubeflow-operator.tf ├── kubeflow.tf ├── main.tf ├── manifests ├── cert-manager │ ├── letsencrypt-prod.yaml │ └── self-signed.yaml └── kubeflow │ ├── application-crd.yaml │ ├── gateway-vs.yaml │ ├── kfdef.yaml │ └── operator-crd.yaml ├── outputs.tf ├── test └── terraform_apply_destroy_test.go └── variables.tf /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @sdebruyn @samueldumont 2 | -------------------------------------------------------------------------------- /.github/workflows/terraform-master.yml: -------------------------------------------------------------------------------- 1 | name: 'publish' 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - tf012 7 | jobs: 8 | publish: 9 | name: 'Publish' 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: 'Checkout' 13 | uses: actions/checkout@master 14 | - run: | 15 | if [[ "$GITHUB_REF" == "refs/heads/master" ]]; then 16 | echo "::set-output name=version::v0.13*" 17 | else 18 | echo "::set-output name=version::v0.12*" 19 | fi 20 | id: get_tf_version 21 | - name: Find Tag 22 | id: get_latest_tag 23 | uses: jimschubert/query-tag-action@v1 24 | with: 25 | include: ${{ steps.get_tf_version.outputs.version }} 26 | exclude: '*-rc*' 27 | commit-ish: 'HEAD~' 28 | - run: echo "::set-output name=version::$(echo ${{ steps.get_latest_tag.outputs.tag }} | cut -d- -f2)" 29 | id: get_version 30 | - name: 'Get next version' 31 | id: next_tag 32 | uses: "WyriHaximus/github-action-next-semvers@master" 33 | with: 34 | version: ${{ steps.get_version.outputs.version }} 35 | - name: Create Release 36 | id: create_release 37 | uses: actions/create-release@v1 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 40 | with: 41 | tag_name: "${{ steps.next_tag.outputs.v_patch }}" 42 | release_name: "${{ steps.next_tag.outputs.v_patch }}" 43 | body: | 44 | Automatic release for ${{ steps.next_tag.outputs.v_patch }} 45 | draft: false 46 | prerelease: false -------------------------------------------------------------------------------- /.github/workflows/terraform.yml: -------------------------------------------------------------------------------- 1 | name: "tests" 2 | on: 3 | pull_request: 4 | branches: 5 | - master 6 | - tf012 7 | push: 8 | branches: 9 | - master 10 | - tf012 11 | env: 12 | tests_timeout: "2h" 13 | golangci_lint_version: "v1.26" 14 | jobs: 15 | validate: 16 | name: "Validate" 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: "Checkout" 20 | uses: actions/checkout@master 21 | 22 | - uses: hashicorp/setup-terraform@v1 23 | with: 24 | terraform_version: 0.13.0 25 | if: github.ref == 'refs/heads/tf012' 26 | 27 | - uses: hashicorp/setup-terraform@v1 28 | with: 29 | terraform_version: 0.12.29 30 | if: github.ref == 'refs/heads/tf012' 31 | 32 | - name: "Download terraform k8s provider" 33 | run: | 34 | wget https://github.com/banzaicloud/terraform-provider-k8s/releases/download/v0.7.7/terraform-provider-k8s_0.7.7_linux_amd64.tar.gz 35 | tar xvzf terraform-provider-k8s_0.7.7_linux_amd64.tar.gz && chmod +x terraform-provider-k8s 36 | mkdir -p ~/.terraform.d/plugins 37 | mv terraform-provider-k8s ~/.terraform.d/plugins 38 | if: github.ref == 'refs/heads/tf012' 39 | 40 | - name: Terraform Init 41 | run: terraform init 42 | 43 | - name: Terraform Format 44 | run: terraform fmt -check 45 | 46 | - name: Terraform Validate 47 | run: terraform validate 48 | 49 | - name: tflint 50 | run: docker run --rm -v $(pwd):/data -t wata727/tflint 51 | test: 52 | name: "Tests" 53 | runs-on: ubuntu-latest 54 | steps: 55 | - name: "Checkout" 56 | uses: actions/checkout@master 57 | 58 | - uses: hashicorp/setup-terraform@v1 59 | with: 60 | terraform_version: 0.13.0 61 | if: github.ref != 'refs/heads/tf012' 62 | 63 | - uses: hashicorp/setup-terraform@v1 64 | with: 65 | terraform_version: 0.12.29 66 | if: github.ref == 'refs/heads/tf012' 67 | 68 | - name: "Download terraform k8s provider" 69 | run: | 70 | wget https://github.com/banzaicloud/terraform-provider-k8s/releases/download/v0.7.7/terraform-provider-k8s_0.7.7_linux_amd64.tar.gz 71 | tar xvzf terraform-provider-k8s_0.7.7_linux_amd64.tar.gz && chmod +x terraform-provider-k8s 72 | mkdir -p ~/.terraform.d/plugins 73 | mv terraform-provider-k8s ~/.terraform.d/plugins 74 | if: github.ref == 'refs/heads/tf012' 75 | 76 | - name: "go vet" 77 | run: go vet ./... 78 | 79 | - name: golangci-lint 80 | uses: golangci/golangci-lint-action@v1 81 | with: 82 | # Optional: golangci-lint command line arguments. 83 | args: --timeout=3m0s 84 | version: ${{ env.golangci_lint_version }} 85 | 86 | - name: "go test" 87 | env: 88 | K3S_KUBECONFIG_MODE: 644 89 | KUBECONFIG: "/etc/rancher/k3s/k3s.yaml" 90 | run: | 91 | curl -sfL https://get.k3s.io | sh -s - --disable traefik --disable servicelb 92 | kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml 93 | curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash 94 | go test -v -timeout ${{ env.tests_timeout }} ./... -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | 11 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 12 | # .tfvars files are managed as part of configuration and so should be included in 13 | # version control. 14 | # 15 | # example.tfvars 16 | 17 | # Ignore override files as they are usually used to override resources locally and so 18 | # are not checked in 19 | override.tf 20 | override.tf.json 21 | *_override.tf 22 | *_override.tf.json 23 | 24 | # Include override files you do wish to add to version control using negated pattern 25 | # 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | vendors/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Dataroots BVBA 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: lint 2 | 3 | tools: 4 | go install gotest.tools/gotestsum 5 | terraform init 6 | 7 | fmt: 8 | terraform fmt 9 | go mod tidy 10 | gofmt -w -s test 11 | 12 | lint-tf: tools 13 | terraform fmt -check 14 | terraform validate 15 | tflint 16 | 17 | lint-go: 18 | test -z $(gofmt -l -s test) 19 | go vet ./... 20 | 21 | lint: lint-tf lint-go 22 | 23 | test: tools lint 24 | go test -v -timeout 2h ./... -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform module Kubeflow 2 | 3 | This is a module deploying kubeflow purely in Terraform. Versioning is following Terraform's own versions : 0.12.x and 0.13.x. The active development will be now done on Terraform 0.13, 0.12 will be "frozen". 4 | 5 | [![maintained by dataroots](https://img.shields.io/badge/maintained%20by-dataroots-%2300b189)](https://dataroots.io) 6 | [![Terraform 0.13](https://img.shields.io/badge/terraform-0.13-%23623CE4)](https://www.terraform.io) 7 | [![Terraform Registry](https://img.shields.io/badge/terraform-registry-%23623CE4)](https://registry.terraform.io/modules/datarootsio/kubeflow/module/) 8 | [![tests](https://github.com/datarootsio/terraform-module-kubeflow/workflows/tests/badge.svg?branch=master)](https://github.com/datarootsio/terraform-module-kubeflow/actions) 9 | [![Go Report Card](https://goreportcard.com/badge/github.com/datarootsio/terraform-module-kubeflow)](https://goreportcard.com/report/github.com/datarootsio/terraform-module-kubeflow) 10 | 11 | ## Usage 12 | 13 | Due to the difficulties to have proper optional dependencies, with TF 0.12 you need to install istio and cert-manager as part of the process (as intended by Kubeflow). With Terraform 0.13 it is possible to reuse an existing installation of cert-manager and istio. 14 | 15 | ## Inputs 16 | 17 | | Name | Description | Type | Default | Required | 18 | |------|-------------|------|---------|:--------:| 19 | | cert\_manager\_namespace | The namespace for istio operator | `string` | `"cert-manager"` | no | 20 | | cert\_manager\_version | The version of cert-manager | `string` | `"v0.16.1"` | no | 21 | | certificate\_name | The secret where the pre-generated certificate is stored | `string` | `""` | no | 22 | | dns\_record | The DNS record for Kubeflow's ingresses | `string` | `"kubeflow"` | no | 23 | | domain\_name | The domain name for Kubeflow's ingresses DNS records | `string` | `""` | no | 24 | | ingress\_gateway\_annotations | A map of key-value annotations for istio ingressgateway | `map(string)` | `{}` | no | 25 | | ingress\_gateway\_ip | The IP of istio ingressgateway | `string` | `""` | no | 26 | | ingress\_gateway\_selector | Istio ingressgateway selector | `string` | `"ingressgateway"` | no | 27 | | install\_cert\_manager | n/a | `bool` | `false` | no | 28 | | install\_istio | Should this module install istio | `bool` | `false` | no | 29 | | istio\_namespace | The namespace for istio | `string` | `"istio-system"` | no | 30 | | istio\_operator\_namespace | The namespace for istio operator | `string` | `"istio-operator"` | no | 31 | | kubeflow\_components | The list of components to install. KF Operator does not support updates so changes after initial deployment will not be reflected. | `list(string)` |
[
"jupyter",
"spark",
"pytorch",
"knative",
"spartakus",
"tensorflow",
"katib",
"pipelines",
"seldon"
]
| no | 32 | | kubeflow\_operator\_namespace | The namespace for kubeflow operator | `string` | `"kubeflow-operator"` | no | 33 | | kubeflow\_operator\_version | The version of kubeflow operator to install | `string` | `"1.1.0"` | no | 34 | | kubeflow\_version | The version of kubeflow to install | `string` | `"1.1.0"` | no | 35 | | letsencrypt\_email | The email to use for let's encrypt certificate requests | `string` | `""` | no | 36 | | oidc\_auth\_url | The auth url for OIDC | `string` | `"/dex/auth"` | no | 37 | | oidc\_client\_id | The Client ID for OIDC | `string` | `"kubeflow-oidc-authservice"` | no | 38 | | oidc\_client\_secret | The OIDC client secret. The default value is not safe ! | `string` | `"pUBnBOY80SnXgjibTYM9ZWNzY2xreNGQok"` | no | 39 | | oidc\_issuer | The OIDC issuer | `string` | `"http://dex.auth.svc.cluster.local:5556/dex"` | no | 40 | | oidc\_redirect\_url | The OIDC redirect URL | `string` | `"/login/oidc"` | no | 41 | | oidc\_userid\_claim | The claim for OIDC auth flows | `string` | `"email"` | no | 42 | | use\_cert\_manager | Should we use cert-manager for ingresses certificates | `bool` | `false` | no | 43 | 44 | ## Examples 45 | 46 | ```hcl 47 | module "kubeflow" { 48 | providers = { 49 | kubernetes = kubernetes 50 | k8s = k8s 51 | helm = helm 52 | } 53 | 54 | source = "datarootsio/kubeflow/module" 55 | version = "~>0.12" 56 | 57 | ingress_gateway_ip = "10.20.30.40" 58 | use_cert_manager = true 59 | domain_name = "foo.local" 60 | letsencrypt_email = "foo@bar.local" 61 | kubeflow_components = ["pipelines"] 62 | } 63 | ``` 64 | 65 | ```hcl 66 | module "kubeflow" { 67 | providers = { 68 | kubernetes = kubernetes 69 | k8s = k8s 70 | helm = helm 71 | } 72 | 73 | source = "datarootsio/kubeflow/module" 74 | version = "~>0.13" 75 | 76 | ingress_gateway_ip = "10.20.30.40" 77 | use_cert_manager = true 78 | install_istio = false 79 | install_cert_manager = false 80 | domain_name = "foo.local" 81 | letsencrypt_email = "foo@bar.local" 82 | kubeflow_components = ["pipelines"] 83 | } 84 | ``` 85 | 86 | ## Outputs 87 | 88 | No output. 89 | 90 | ## Contributing 91 | 92 | Contributions to this repository are very welcome! Found a bug or do you have a suggestion? Please open an issue. Do you know how to fix it? Pull requests are welcome as well! To get you started faster, a Makefile is provided. 93 | 94 | Make sure to install [Terraform](https://learn.hashicorp.com/terraform/getting-started/install.html), [Go](https://golang.org/doc/install) (for automated testing) and Make (optional, if you want to use the Makefile) on your computer. Install [tflint](https://github.com/terraform-linters/tflint) to be able to run the linting. 95 | 96 | * Setup tools & dependencies: `make tools` 97 | * Format your code: `make fmt` 98 | * Linting: `make lint` 99 | * Run tests: `make test` (or `go test -timeout 2h ./...` without Make) 100 | 101 | To run the automated tests, you need to be logged in to a kubernetes cluster. We use [k3s](https://k3s.io/) in the test pipelines. 102 | 103 | ## License 104 | 105 | MIT license. Please see [LICENSE](LICENSE.md) for details. -------------------------------------------------------------------------------- /auth/configs/dex.yaml: -------------------------------------------------------------------------------- 1 | issuer: ${issuer} 2 | storage: 3 | type: kubernetes 4 | config: 5 | inCluster: true 6 | web: 7 | http: 0.0.0.0:5556 8 | logger: 9 | level: "debug" 10 | format: text 11 | oauth2: 12 | skipApprovalScreen: true 13 | enablePasswordDB: true 14 | staticPasswords: 15 | - email: ${static_email} 16 | hash: ${static_password_hash} 17 | username: ${static_username} 18 | userID: ${static_user_id} 19 | staticClients: 20 | - id: ${client_id} 21 | redirectURIs: 22 | - ${oidc_redirect_uri} 23 | name: 'Dex Login Application' 24 | secret: ${application_secret} -------------------------------------------------------------------------------- /auth/dex.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | dex_crd_manifests = split("\n---\n", templatefile( 3 | "${path.module}/manifests/dex-crd.yaml", 4 | { 5 | namespace = kubernetes_namespace.auth.metadata.0.name, 6 | domain_name = var.domain_name 7 | } 8 | ) 9 | ) 10 | } 11 | 12 | resource "k8s_manifest" "dex_crd" { 13 | count = length(local.dex_crd_manifests) 14 | content = local.dex_crd_manifests[count.index] 15 | } 16 | 17 | resource "kubernetes_service_account" "dex" { 18 | metadata { 19 | name = "dex" 20 | namespace = kubernetes_namespace.auth.metadata.0.name 21 | } 22 | } 23 | 24 | resource "kubernetes_cluster_role" "dex" { 25 | metadata { 26 | name = "dex" 27 | } 28 | 29 | rule { 30 | verbs = ["*"] 31 | api_groups = ["dex.coreos.com"] 32 | resources = ["*"] 33 | } 34 | 35 | rule { 36 | verbs = ["create"] 37 | api_groups = ["apiextensions.k8s.io"] 38 | resources = ["customresourcedefinitions"] 39 | } 40 | } 41 | 42 | resource "kubernetes_cluster_role_binding" "dex" { 43 | metadata { 44 | name = "dex" 45 | } 46 | 47 | subject { 48 | kind = "ServiceAccount" 49 | name = "dex" 50 | namespace = kubernetes_namespace.auth.metadata.0.name 51 | } 52 | 53 | role_ref { 54 | api_group = "rbac.authorization.k8s.io" 55 | kind = "ClusterRole" 56 | name = "dex" 57 | } 58 | } 59 | 60 | resource "kubernetes_secret" "dex" { 61 | metadata { 62 | name = "dex" 63 | namespace = kubernetes_namespace.auth.metadata.0.name 64 | } 65 | 66 | data = { 67 | "config.yaml" = templatefile("${path.module}/configs/dex.yaml", { 68 | application_secret = var.application_secret 69 | client_id = var.client_id 70 | issuer = var.issuer 71 | namespace = kubernetes_namespace.auth.metadata.0.name 72 | oidc_redirect_uri = var.oidc_redirect_url 73 | static_email = var.static_email 74 | static_password_hash = var.static_password_hash 75 | static_user_id = var.static_user_id 76 | static_username = var.static_username 77 | domain_name = var.domain_name 78 | }) 79 | } 80 | } 81 | 82 | resource "kubernetes_service" "dex" { 83 | metadata { 84 | name = "dex" 85 | namespace = kubernetes_namespace.auth.metadata.0.name 86 | } 87 | 88 | spec { 89 | port { 90 | name = "dex" 91 | protocol = "TCP" 92 | port = 5556 93 | target_port = "5556" 94 | node_port = 32000 95 | } 96 | 97 | selector = { 98 | app = "dex" 99 | } 100 | 101 | type = "NodePort" 102 | } 103 | } 104 | 105 | resource "kubernetes_deployment" "dex" { 106 | depends_on = [k8s_manifest.dex_crd] 107 | metadata { 108 | name = "dex" 109 | namespace = kubernetes_namespace.auth.metadata.0.name 110 | 111 | labels = { 112 | app = "dex" 113 | } 114 | } 115 | 116 | spec { 117 | replicas = 1 118 | 119 | selector { 120 | match_labels = { 121 | app = "dex" 122 | } 123 | } 124 | 125 | template { 126 | metadata { 127 | labels = { 128 | app = "dex" 129 | } 130 | } 131 | 132 | spec { 133 | automount_service_account_token = true 134 | volume { 135 | name = "config" 136 | 137 | secret { 138 | secret_name = "dex" 139 | 140 | items { 141 | key = "config.yaml" 142 | path = "config.yaml" 143 | } 144 | } 145 | } 146 | 147 | container { 148 | name = "dex" 149 | image = "gcr.io/arrikto/dexidp/dex:4bede5eb80822fc3a7fc9edca0ed2605cd339d17" 150 | command = ["dex", "serve", "/etc/dex/cfg/config.yaml"] 151 | 152 | port { 153 | name = "http" 154 | container_port = 5556 155 | } 156 | 157 | volume_mount { 158 | name = "config" 159 | mount_path = "/etc/dex/cfg" 160 | } 161 | } 162 | 163 | service_account_name = "dex" 164 | } 165 | } 166 | } 167 | } 168 | 169 | -------------------------------------------------------------------------------- /auth/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "~> 0.13" 3 | required_providers { 4 | kubernetes = { 5 | source = "hashicorp/kubernetes" 6 | } 7 | k8s = { 8 | source = "banzaicloud/k8s" 9 | version = "0.8.2" 10 | } 11 | } 12 | } 13 | 14 | resource "kubernetes_namespace" "auth" { 15 | metadata { 16 | name = "auth" 17 | } 18 | } -------------------------------------------------------------------------------- /auth/manifests/dex-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: authcodes.dex.coreos.com 5 | spec: 6 | group: dex.coreos.com 7 | names: 8 | kind: AuthCode 9 | listKind: AuthCodeList 10 | plural: authcodes 11 | singular: authcode 12 | scope: Namespaced 13 | version: v1 14 | --- 15 | apiVersion: networking.istio.io/v1alpha3 16 | kind: VirtualService 17 | metadata: 18 | name: dex 19 | namespace: auth 20 | spec: 21 | gateways: 22 | - kubeflow/kubeflow-gateway 23 | hosts: 24 | - kubeflow.${domain_name} 25 | http: 26 | - match: 27 | - uri: 28 | prefix: /dex/ 29 | route: 30 | - destination: 31 | host: dex.auth.svc.cluster.local 32 | port: 33 | number: 5556 -------------------------------------------------------------------------------- /auth/manifests/oidc-authservice.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: app.k8s.io/v1beta1 2 | kind: Application 3 | metadata: 4 | labels: 5 | %{ for key,value in labels ~} 6 | ${key}: ${value} 7 | %{ endfor ~} 8 | name: oidc-authservice 9 | namespace: ${istio_namespace} 10 | spec: 11 | addOwnerRef: true 12 | componentKinds: 13 | - group: apps 14 | kind: StatefulSet 15 | - group: core 16 | kind: Service 17 | - group: core 18 | kind: PersistentVolumeClaim 19 | - group: networking.istio.io 20 | kind: EnvoyFilter 21 | descriptor: 22 | description: Provides OIDC-based authentication for Kubeflow Applications, at 23 | the Istio Gateway. 24 | keywords: 25 | - oidc 26 | - authservice 27 | - authentication 28 | links: 29 | - description: About 30 | url: https://github.com/kubeflow/kubeflow/tree/master/components/oidc-authservice 31 | - description: Docs 32 | url: https://www.kubeflow.org/docs/started/k8s/kfctl-existing-arrikto 33 | maintainers: 34 | - email: yanniszark@arrikto.com 35 | name: Yannis Zarkadas 36 | owners: 37 | - email: yanniszark@arrikto.com 38 | name: Yannis Zarkadas 39 | type: oidc-authservice 40 | version: v1beta1 41 | selector: 42 | matchLabels: 43 | %{ for key,value in labels ~} 44 | ${key}: ${value} 45 | %{ endfor ~} 46 | --- 47 | apiVersion: networking.istio.io/v1alpha3 48 | kind: EnvoyFilter 49 | metadata: 50 | labels: 51 | %{ for key,value in labels ~} 52 | ${key}: ${value} 53 | %{ endfor ~} 54 | name: authn-filter 55 | namespace: ${istio_namespace} 56 | spec: 57 | workloadSelector: 58 | labels: 59 | istio: ingressgateway 60 | configPatches: 61 | - applyTo: HTTP_FILTER 62 | match: 63 | context: GATEWAY 64 | listener: 65 | filterChain: 66 | filter: 67 | name: "envoy.http_connection_manager" 68 | subFilter: 69 | name: "envoy.router" 70 | patch: 71 | operation: INSERT_BEFORE 72 | value: 73 | name: envoy.ext_authz 74 | config: 75 | http_service: 76 | server_uri: 77 | uri: http://authservice.${istio_namespace}.svc.cluster.local 78 | cluster: outbound|8080||authservice.${istio_namespace}.svc.cluster.local 79 | failure_mode_allow: false 80 | timeout: 10s 81 | authorization_request: 82 | allowed_headers: 83 | patterns: 84 | - exact: "cookie" 85 | - exact: "X-Auth-Token" 86 | authorization_response: 87 | allowed_upstream_headers: 88 | patterns: 89 | - exact: "kubeflow-userid" 90 | status_on_error: 91 | code: GatewayTimeout -------------------------------------------------------------------------------- /auth/oidc-authservice.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | oidc_labels = { 3 | "app.kubernetes.io/managed-by" = "terraform" 4 | "app.kubernetes.io/part-of" = "kubeflow" 5 | "app.kubernetes.io/component" = "oidc-authservice" 6 | "app.kubernetes.io/name" = "oidc-authservice" 7 | "app.kubernetes.io/instance" = "oidc-authservice-v1.0.0" 8 | "app.kubernetes.io/version" = "v1.0.0" 9 | } 10 | } 11 | 12 | resource "kubernetes_secret" "oidc_authservice_parameters" { 13 | metadata { 14 | name = "oidc-authservice-parameters" 15 | namespace = var.istio_namespace 16 | labels = local.oidc_labels 17 | } 18 | 19 | data = { 20 | application_secret = var.application_secret 21 | client_id = var.client_id 22 | namespace = var.istio_namespace 23 | oidc_auth_url = var.oidc_auth_url 24 | oidc_provider = var.issuer 25 | oidc_redirect_url = var.oidc_redirect_url 26 | skip_auth_uri = "/dex/ /.well-known/" 27 | userid-header = "kubeflow-userid" 28 | userid-prefix = "" 29 | userid-claim = var.userid_claim 30 | oidc_scopes = "profile groups email" 31 | } 32 | } 33 | 34 | resource "kubernetes_service" "authservice" { 35 | metadata { 36 | name = "authservice" 37 | namespace = var.istio_namespace 38 | 39 | labels = local.oidc_labels 40 | } 41 | 42 | spec { 43 | port { 44 | name = "http-authservice" 45 | port = 8080 46 | target_port = "http-api" 47 | } 48 | 49 | selector = merge( 50 | local.oidc_labels, { app = "authservice" } 51 | ) 52 | 53 | type = "ClusterIP" 54 | publish_not_ready_addresses = true 55 | } 56 | } 57 | 58 | resource "kubernetes_stateful_set" "authservice" { 59 | depends_on = [k8s_manifest.oidc_authservice] 60 | metadata { 61 | name = "authservice" 62 | namespace = var.istio_namespace 63 | 64 | labels = local.oidc_labels 65 | } 66 | 67 | spec { 68 | replicas = 1 69 | 70 | selector { 71 | match_labels = merge( 72 | local.oidc_labels, { app = "authservice" } 73 | ) 74 | } 75 | 76 | template { 77 | metadata { 78 | labels = merge( 79 | local.oidc_labels, { app = "authservice" } 80 | ) 81 | 82 | annotations = { 83 | "sidecar.istio.io/inject" = "false" 84 | } 85 | } 86 | 87 | spec { 88 | automount_service_account_token = true 89 | container { 90 | name = "authservice" 91 | image = "gcr.io/arrikto/kubeflow/oidc-authservice:28c59ef" 92 | 93 | port { 94 | name = "http-api" 95 | container_port = 8080 96 | } 97 | 98 | env { 99 | name = "USERID_HEADER" 100 | value_from { 101 | secret_key_ref { 102 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 103 | key = "userid-header" 104 | } 105 | } 106 | } 107 | 108 | env { 109 | name = "USERID_PREFIX" 110 | value_from { 111 | secret_key_ref { 112 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 113 | key = "userid-prefix" 114 | } 115 | } 116 | } 117 | 118 | env { 119 | name = "USERID_CLAIM" 120 | value_from { 121 | secret_key_ref { 122 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 123 | key = "userid-claim" 124 | } 125 | } 126 | } 127 | 128 | env { 129 | name = "OIDC_PROVIDER" 130 | value_from { 131 | secret_key_ref { 132 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 133 | key = "oidc_provider" 134 | } 135 | } 136 | } 137 | 138 | env { 139 | name = "OIDC_AUTH_URL" 140 | value_from { 141 | secret_key_ref { 142 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 143 | key = "oidc_auth_url" 144 | } 145 | } 146 | } 147 | 148 | env { 149 | name = "OIDC_SCOPES" 150 | value_from { 151 | secret_key_ref { 152 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 153 | key = "oidc_scopes" 154 | } 155 | } 156 | } 157 | 158 | env { 159 | name = "REDIRECT_URL" 160 | value_from { 161 | secret_key_ref { 162 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 163 | key = "oidc_redirect_url" 164 | } 165 | } 166 | } 167 | 168 | env { 169 | name = "SKIP_AUTH_URI" 170 | value_from { 171 | secret_key_ref { 172 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 173 | key = "skip_auth_uri" 174 | } 175 | } 176 | } 177 | 178 | env { 179 | name = "PORT" 180 | value = "8080" 181 | } 182 | 183 | env { 184 | name = "CLIENT_ID" 185 | value_from { 186 | secret_key_ref { 187 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 188 | key = "client_id" 189 | } 190 | } 191 | } 192 | 193 | env { 194 | name = "CLIENT_SECRET" 195 | value_from { 196 | secret_key_ref { 197 | name = kubernetes_secret.oidc_authservice_parameters.metadata.0.name 198 | key = "application_secret" 199 | } 200 | } 201 | } 202 | 203 | env { 204 | name = "STORE_PATH" 205 | value = "/var/lib/authservice/data.db" 206 | } 207 | 208 | volume_mount { 209 | name = "authservice" 210 | mount_path = "/var/lib/authservice" 211 | } 212 | 213 | readiness_probe { 214 | http_get { 215 | path = "/" 216 | port = "8081" 217 | } 218 | } 219 | 220 | image_pull_policy = "Always" 221 | } 222 | 223 | security_context { 224 | fs_group = 111 225 | } 226 | } 227 | } 228 | 229 | update_strategy { 230 | type = "RollingUpdate" 231 | } 232 | 233 | volume_claim_template { 234 | metadata { 235 | name = "authservice" 236 | namespace = var.istio_namespace 237 | labels = merge( 238 | local.oidc_labels, { app = "authservice" } 239 | ) 240 | } 241 | 242 | spec { 243 | access_modes = ["ReadWriteOnce"] 244 | 245 | resources { 246 | requests = { 247 | storage = "10Gi" 248 | } 249 | } 250 | } 251 | } 252 | 253 | service_name = "authservice" 254 | } 255 | } 256 | 257 | locals { 258 | oidc_authservice_manifests = split( 259 | "\n---\n", 260 | templatefile( 261 | "${path.module}/manifests/oidc-authservice.yaml", 262 | { 263 | istio_namespace = var.istio_namespace 264 | labels = local.oidc_labels 265 | } 266 | ) 267 | ) 268 | } 269 | 270 | resource "k8s_manifest" "oidc_authservice" { 271 | count = length(local.oidc_authservice_manifests) 272 | content = local.oidc_authservice_manifests[count.index] 273 | } -------------------------------------------------------------------------------- /auth/variables.tf: -------------------------------------------------------------------------------- 1 | variable "domain_name" { 2 | type = string 3 | } 4 | 5 | variable "application_secret" { 6 | type = string 7 | default = "pUBnBOY80SnXgjibTYM9ZWNzY2xreNGQok" 8 | } 9 | 10 | variable "userid_claim" { 11 | type = string 12 | default = "email" 13 | } 14 | 15 | variable "oidc_auth_url" { 16 | type = string 17 | default = "/dex/auth" 18 | } 19 | 20 | variable "client_id" { 21 | type = string 22 | default = "kubeflow-oidc-authservice" 23 | } 24 | 25 | variable "issuer" { 26 | type = string 27 | default = "http://dex.auth.svc.cluster.local:5556/dex" 28 | } 29 | 30 | variable "oidc_redirect_url" { 31 | type = string 32 | default = "/login/oidc" 33 | } 34 | 35 | variable "static_email" { 36 | type = string 37 | default = "admin@kubeflow.org" 38 | } 39 | 40 | variable "static_password_hash" { 41 | type = string 42 | default = "$2y$12$ruoM7FqXrpVgaol44eRZW.4HWS8SAvg6KYVVSCIwKQPBmTpCm.EeO" 43 | } 44 | 45 | variable "static_user_id" { 46 | type = string 47 | default = "08a8684b-db88-4b73-90a9-3cd1661f5466" 48 | } 49 | 50 | variable "static_username" { 51 | type = string 52 | default = "admin" 53 | } 54 | 55 | variable "istio_namespace" { 56 | type = string 57 | } 58 | 59 | variable "auth_depends_on" { 60 | type = any 61 | default = null 62 | } -------------------------------------------------------------------------------- /cert-manager.tf: -------------------------------------------------------------------------------- 1 | resource "kubernetes_namespace" "cert_manager" { 2 | count = var.install_cert_manager ? 1 : 0 3 | metadata { 4 | annotations = { 5 | name = var.cert_manager_namespace 6 | } 7 | name = var.cert_manager_namespace 8 | } 9 | } 10 | 11 | resource "helm_release" "cert_manager" { 12 | count = var.install_cert_manager ? 1 : 0 13 | name = "cert-manager" 14 | repository = "https://charts.jetstack.io" 15 | namespace = kubernetes_namespace.cert_manager[0].metadata.0.name 16 | chart = "cert-manager" 17 | keyring = "" 18 | recreate_pods = true 19 | version = var.cert_manager_version 20 | timeout = 600 21 | 22 | set { 23 | name = "installCRDs" 24 | value = "true" 25 | } 26 | } 27 | 28 | resource "null_resource" "wait_for_certs" { 29 | count = var.install_cert_manager ? 1 : 0 30 | depends_on = [helm_release.cert_manager] 31 | triggers = { 32 | always_run = timestamp() 33 | } 34 | 35 | provisioner "local-exec" { 36 | interpreter = ["/bin/bash", "-c"] 37 | command = "sleep 180" 38 | } 39 | } 40 | 41 | resource "k8s_manifest" "selfsigned_issuer" { 42 | depends_on = [null_resource.wait_for_certs] 43 | content = templatefile( 44 | "${path.module}/manifests/cert-manager/self-signed.yaml", 45 | {} 46 | ) 47 | } 48 | 49 | resource "k8s_manifest" "letsencrypt_issuer" { 50 | count = var.use_cert_manager ? 1 : 0 51 | depends_on = [null_resource.wait_for_certs] 52 | content = templatefile( 53 | "${path.module}/manifests/cert-manager/letsencrypt-prod.yaml", 54 | { 55 | email = var.letsencrypt_email 56 | } 57 | ) 58 | } -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/datarootsio/terraform-module-kubernetes-application 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/gruntwork-io/terratest v0.27.4 7 | github.com/stretchr/testify v1.5.1 8 | gopkg.in/yaml.v2 v2.2.8 // indirect 9 | gotest.tools/gotestsum v0.4.2 // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM= 9 | cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= 10 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 11 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 12 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 13 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 14 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 15 | github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 16 | github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 17 | github.com/Azure/azure-sdk-for-go v38.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 18 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= 19 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= 20 | github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= 21 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= 22 | github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= 23 | github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= 24 | github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= 25 | github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= 26 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 27 | github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= 28 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 29 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 30 | github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= 31 | github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= 32 | github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= 33 | github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= 34 | github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= 35 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 36 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= 37 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 38 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 39 | github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= 40 | github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= 41 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 42 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= 43 | github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 44 | github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 45 | github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 46 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 47 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 48 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 49 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 50 | github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= 51 | github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 52 | github.com/aws/aws-sdk-go v1.27.1 h1:MXnqY6SlWySaZAqNnXThOvjRFdiiOuKtC6i7baFdNdU= 53 | github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 54 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 55 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 56 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 57 | github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= 58 | github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= 59 | github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= 60 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 61 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 62 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 63 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 64 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 65 | github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= 66 | github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= 67 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 68 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 69 | github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= 70 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 71 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 72 | github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 73 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 74 | github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 75 | github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 76 | github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= 77 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 78 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 79 | github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= 80 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 81 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 82 | github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 83 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 84 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 85 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 86 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 87 | github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= 88 | github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= 89 | github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 90 | github.com/docker/cli v0.0.0-20200109221225-a4f60165b7a3/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 91 | github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 92 | github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 93 | github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 94 | github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= 95 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 96 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 97 | github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 98 | github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s= 99 | github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 100 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= 101 | github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 102 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 103 | github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 104 | github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik= 105 | github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= 106 | github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM= 107 | github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= 108 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 109 | github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 110 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 111 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 112 | github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 113 | github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 114 | github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= 115 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 116 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 117 | github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 118 | github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= 119 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 120 | github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= 121 | github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 h1:skJKxRtNmevLqnayafdLe2AsenqRupVmzZSqrvb5caU= 122 | github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 123 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 124 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 125 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 126 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 127 | github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= 128 | github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= 129 | github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 130 | github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= 131 | github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= 132 | github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= 133 | github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= 134 | github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= 135 | github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= 136 | github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 137 | github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 138 | github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= 139 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 140 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 141 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 142 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 143 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= 144 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 145 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 146 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 147 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 148 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 149 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 150 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 151 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 152 | github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 153 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 154 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 155 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 156 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 157 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 158 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 159 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 160 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 161 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 162 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= 163 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 164 | github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk= 165 | github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= 166 | github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= 167 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 168 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 169 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 170 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 171 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 172 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 173 | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 174 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= 175 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 176 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 177 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 178 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 179 | github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 180 | github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= 181 | github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= 182 | github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 183 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 184 | github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 185 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 186 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 187 | github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 188 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 189 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 190 | github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 191 | github.com/gruntwork-io/gruntwork-cli v0.5.1 h1:mVmVsFubUSLSCO8bGigI63HXzvzkC0uWXzm4dd9pXRg= 192 | github.com/gruntwork-io/gruntwork-cli v0.5.1/go.mod h1:IBX21bESC1/LGoV7jhXKUnTQTZgQ6dYRsoj/VqxUSZQ= 193 | github.com/gruntwork-io/terratest v0.27.4 h1:+Pgf3pHRPgVjNv0/MyLWwySmKUcmL+wT6fewu6F4sBE= 194 | github.com/gruntwork-io/terratest v0.27.4/go.mod h1:ONEOU6Fv3a1rN16Z5t5yWbV57DkVC7665yRyvu3aWnk= 195 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 196 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 197 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 198 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 199 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 200 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 201 | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 202 | github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= 203 | github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 204 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 205 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= 206 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 207 | github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= 208 | github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= 209 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 210 | github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 211 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 212 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 213 | github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= 214 | github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 215 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 216 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 217 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 218 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 219 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 220 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 221 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 222 | github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= 223 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 224 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 225 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 226 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 227 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 228 | github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 229 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 230 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 231 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 232 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 233 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 234 | github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 235 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 236 | github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 237 | github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= 238 | github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= 239 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 240 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 241 | github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= 242 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 243 | github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 244 | github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= 245 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 246 | github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= 247 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 248 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 249 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 250 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 251 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 252 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 253 | github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 254 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 255 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 256 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 257 | github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= 258 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 259 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 260 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 261 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 262 | github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 263 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 264 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 265 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 266 | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 267 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 268 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 269 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 270 | github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 271 | github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 272 | github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= 273 | github.com/oracle/oci-go-sdk v7.1.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= 274 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 275 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 276 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 277 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 278 | github.com/pkg/errors v0.9.0 h1:J8lpUdobwIeCI7OiSxHqEwJUKvJwicL5+3v1oe2Yb4k= 279 | github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 280 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 281 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 282 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 283 | github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= 284 | github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= 285 | github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= 286 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 287 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 288 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 289 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 290 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 291 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 292 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 293 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 294 | github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= 295 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 296 | github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= 297 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 298 | github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= 299 | github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= 300 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 301 | github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= 302 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 303 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 304 | github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= 305 | github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= 306 | github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= 307 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 308 | github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= 309 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 310 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 311 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 312 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 313 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 314 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 315 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 316 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 317 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 318 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 319 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 320 | github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 321 | github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 322 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 323 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 324 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 325 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 326 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 327 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 328 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 329 | github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 330 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 331 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 332 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 333 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 334 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 335 | github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 336 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 337 | github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= 338 | github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= 339 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 340 | github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo= 341 | github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= 342 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 343 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 344 | go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 345 | go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= 346 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 347 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 348 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 349 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 350 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 351 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 352 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 353 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 354 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 355 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 356 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 357 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 358 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 359 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 360 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 361 | golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 362 | golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9QSINo2CUPM/cySEvw2w8I0= 363 | golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 364 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 365 | golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 366 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 367 | golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 368 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 369 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 370 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 371 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 372 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 373 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 374 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 375 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 376 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 377 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 378 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 379 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 380 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 381 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 382 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 383 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 384 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 385 | golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 386 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 387 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 388 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 389 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 390 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 391 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 392 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 393 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 394 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 395 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 396 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 397 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 398 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 399 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 400 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 401 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 402 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 403 | golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 404 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= 405 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 406 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 407 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 408 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 409 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 410 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= 411 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 412 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 413 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 414 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 415 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 416 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 417 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= 418 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 419 | golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 420 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 421 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 422 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 423 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 424 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 425 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 426 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 427 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 428 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 429 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 430 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 431 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 432 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 433 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 434 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 435 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 436 | golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 437 | golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 438 | golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 439 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 440 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 441 | golang.org/x/sys v0.0.0-20200107162124-548cf772de50 h1:YvQ10rzcqWXLlJZ3XCUoO25savxmscf4+SC+ZqiCHhA= 442 | golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 443 | golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 444 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 445 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 446 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 447 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 448 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 449 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 450 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= 451 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 452 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 453 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 454 | golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 455 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 456 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 457 | golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 458 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 459 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 460 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 461 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 462 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 463 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 464 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 465 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 466 | golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 467 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 468 | golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 469 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 470 | golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= 471 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 472 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 473 | golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 474 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 475 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 476 | golang.org/x/tools v0.0.0-20191205215504-7b8c8591a921/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 477 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 478 | golang.org/x/tools v0.0.0-20200113040837-eac381796e91/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 479 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 480 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 481 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 482 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 483 | gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= 484 | gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= 485 | gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= 486 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 487 | google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= 488 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 489 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 490 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 491 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 492 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 493 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 494 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 495 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 496 | google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= 497 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 498 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 499 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 500 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 501 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 502 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 503 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 504 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 505 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 506 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 507 | google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 508 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 509 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 510 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 511 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 512 | google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 513 | google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= 514 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 515 | gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= 516 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 517 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 518 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 519 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 520 | gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 521 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 522 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 523 | gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= 524 | gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= 525 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 526 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 527 | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= 528 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 529 | gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 530 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 531 | gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 532 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 533 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 534 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 535 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 536 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 537 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 538 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 539 | gotest.tools v1.4.0 h1:BjtEgfuw8Qyd+jPvQz8CfoxiO/UjFEidWinwEXZiWv0= 540 | gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= 541 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 542 | gotest.tools/gotestsum v0.4.2 h1:QOdtb6bnnPUuHKkR9+/QQa8e6qjpTTP7cDi7G9/10C4= 543 | gotest.tools/gotestsum v0.4.2/go.mod h1:a32lmn/7xfm0+QHj8K5NyQY1NNNNhZoAp+/OHkLs77Y= 544 | gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= 545 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 546 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 547 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 548 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 549 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 550 | k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM= 551 | k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= 552 | k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo= 553 | k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= 554 | k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg= 555 | k8s.io/client-go v0.17.0 h1:8QOGvUGdqDMFrm9sD6IUFl256BcffynGoe80sxgTEDg= 556 | k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= 557 | k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE= 558 | k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= 559 | k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc= 560 | k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls= 561 | k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 562 | k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 563 | k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 564 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 565 | k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= 566 | k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= 567 | k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= 568 | k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= 569 | k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8= 570 | k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo= 571 | k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 572 | modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= 573 | modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= 574 | modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= 575 | modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= 576 | modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= 577 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 578 | sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= 579 | sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= 580 | sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= 581 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 582 | -------------------------------------------------------------------------------- /istio/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "~> 0.13" 3 | required_providers { 4 | helm = { 5 | source = "hashicorp/helm" 6 | } 7 | kubernetes = { 8 | source = "hashicorp/kubernetes" 9 | } 10 | k8s = { 11 | source = "banzaicloud/k8s" 12 | version = "0.8.2" 13 | } 14 | } 15 | } 16 | 17 | resource "kubernetes_namespace" "istio_namespace" { 18 | metadata { 19 | name = var.istio_namespace 20 | 21 | labels = { 22 | istio-injection = "disabled" 23 | istio-operator-managed = "Reconcile" 24 | } 25 | } 26 | } 27 | 28 | resource "k8s_manifest" "istio_deployment" { 29 | depends_on = [kubernetes_deployment.istio_operator, k8s_manifest.operator_crd, kubernetes_cluster_role_binding.istio_operator] 30 | content = templatefile( 31 | "${path.module}/manifests/istio-deployment.yaml", 32 | { 33 | namespace = kubernetes_namespace.istio_namespace.metadata.0.name, 34 | ingress_gateway_selector = var.ingress_gateway_selector 35 | annotations = var.ingress_gateway_annotations, 36 | lb_ip = var.ingress_gateway_ip 37 | } 38 | ) 39 | } 40 | 41 | resource "null_resource" "wait_crds" { 42 | depends_on = [k8s_manifest.istio_deployment] 43 | 44 | triggers = { 45 | always_run = timestamp() 46 | } 47 | 48 | provisioner "local-exec" { 49 | interpreter = ["/bin/bash", "-c"] 50 | command = "while [[ \"$(kubectl get crds | grep 'istio.io' | wc -l)\" -ne \"25\" ]]; do echo \"Waiting for CRDs\"; sleep 5; done" 51 | } 52 | } -------------------------------------------------------------------------------- /istio/manifests/istio-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: install.istio.io/v1alpha1 2 | kind: IstioOperator 3 | metadata: 4 | namespace: ${namespace} 5 | name: ${namespace}-control-plane 6 | spec: 7 | values: 8 | global: 9 | proxy: 10 | autoInject: disabled 11 | useMCP: false 12 | # The third-party-jwt is not enabled on all k8s. 13 | # See: https://istio.io/docs/ops/best-practices/security/#configure-third-party-service-account-tokens 14 | jwtPolicy: first-party-jwt 15 | profile: default 16 | addonComponents: 17 | pilot: 18 | enabled: true 19 | grafana: 20 | enabled: true 21 | kiali: 22 | enabled: true 23 | prometheus: 24 | enabled: true 25 | tracing: 26 | enabled: true 27 | components: 28 | ingressGateways: 29 | - name: istio-${ingress_gateway_selector} 30 | enabled: true 31 | k8s: 32 | serviceAnnotations: 33 | %{ for key,value in annotations ~} 34 | ${key}: ${value} 35 | %{ endfor ~} 36 | %{ if lb_ip != "" } 37 | service: 38 | type: LoadBalancer 39 | loadBalancerIP: ${lb_ip} 40 | externalTrafficPolicy: Local 41 | ports: 42 | - name: status-port 43 | port: 15020 44 | targetPort: 15020 45 | - name: http2 46 | port: 80 47 | targetPort: 8080 48 | - name: https 49 | port: 443 50 | targetPort: 8443 51 | - name: tls 52 | port: 15443 53 | targetPort: 15443 54 | %{ endif ~} 55 | - name: cluster-local-gateway 56 | enabled: true 57 | label: 58 | istio: cluster-local-gateway 59 | app: cluster-local-gateway 60 | k8s: 61 | service: 62 | type: ClusterIP 63 | ports: 64 | - port: 15020 65 | name: status-port 66 | targetPort: 15021 67 | - port: 80 68 | name: http2 69 | targetPort: 8081 70 | - port: 443 71 | name: https 72 | targetPort: 8444 -------------------------------------------------------------------------------- /istio/manifests/kiali.yaml: -------------------------------------------------------------------------------- 1 | %{ if use_cert_manager ~} 2 | apiVersion: cert-manager.io/v1alpha2 3 | kind: Certificate 4 | metadata: 5 | name: kiali 6 | namespace: ${namespace} 7 | spec: 8 | secretName: kiali-cert 9 | commonName: kiali.${domain_name} 10 | issuerRef: 11 | name: letsencrypt-prod 12 | kind: ClusterIssuer 13 | dnsNames: 14 | - kiali.${domain_name} 15 | --- 16 | %{ endif } 17 | %{ if credential_name != "" || use_cert_manager } 18 | apiVersion: networking.istio.io/v1alpha3 19 | kind: Gateway 20 | metadata: 21 | name: kiali-gateway 22 | namespace: ${namespace} 23 | spec: 24 | selector: 25 | istio: ${ingress_gateway_selector} 26 | servers: 27 | - port: 28 | number: 443 29 | name: https-kiali 30 | protocol: HTTPS 31 | tls: 32 | mode: SIMPLE 33 | credentialName: %{ if use_cert_manager ~}kiali-cert%{ else ~}${credential_name}%{ endif } 34 | hosts: 35 | - kiali.${domain_name} 36 | --- 37 | %{ endif } 38 | -------------------------------------------------------------------------------- /istio/manifests/operator-crd.yaml: -------------------------------------------------------------------------------- 1 | # Source: istio-operator/templates/crd-operator.yaml 2 | # SYNC WITH manifests/charts/base/files 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: istiooperators.install.istio.io 7 | spec: 8 | group: install.istio.io 9 | names: 10 | kind: IstioOperator 11 | plural: istiooperators 12 | singular: istiooperator 13 | shortNames: 14 | - iop 15 | scope: Namespaced 16 | subresources: 17 | status: {} 18 | validation: 19 | openAPIV3Schema: 20 | properties: 21 | apiVersion: 22 | description: 'APIVersion defines the versioned schema of this representation 23 | of an object. Servers should convert recognized schemas to the latest 24 | internal value, and may reject unrecognized values. 25 | More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#resources' 26 | type: string 27 | kind: 28 | description: 'Kind is a string value representing the REST resource this 29 | object represents. Servers may infer this from the endpoint the client 30 | submits requests to. Cannot be updated. In CamelCase. 31 | More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 32 | type: string 33 | spec: 34 | description: 'Specification of the desired state of the istio control plane resource. 35 | More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' 36 | type: object 37 | status: 38 | description: 'Status describes each of istio control plane component status at the current time. 39 | 0 means NONE, 1 means UPDATING, 2 means HEALTHY, 3 means ERROR, 4 means RECONCILING. 40 | More info: https://github.com/istio/api/blob/master/operator/v1alpha1/istio.operator.v1alpha1.pb.html & 41 | https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' 42 | type: object 43 | versions: 44 | - name: v1alpha1 45 | served: true 46 | storage: true 47 | -------------------------------------------------------------------------------- /istio/operator.tf: -------------------------------------------------------------------------------- 1 | resource "kubernetes_namespace" "istio_operator" { 2 | metadata { 3 | name = var.istio_operator_namespace 4 | 5 | labels = { 6 | istio-injection = "disabled" 7 | istio-operator-managed = "Reconcile" 8 | } 9 | } 10 | } 11 | 12 | resource "k8s_manifest" "operator_crd" { 13 | depends_on = [kubernetes_cluster_role_binding.istio_operator] 14 | content = templatefile("${path.module}/manifests/operator-crd.yaml", {}) 15 | } 16 | 17 | resource "kubernetes_deployment" "istio_operator" { 18 | metadata { 19 | name = "istio-operator" 20 | namespace = kubernetes_namespace.istio_operator.metadata.0.name 21 | } 22 | 23 | spec { 24 | replicas = 1 25 | 26 | selector { 27 | match_labels = { 28 | name = "istio-operator" 29 | } 30 | } 31 | 32 | template { 33 | metadata { 34 | labels = { 35 | name = "istio-operator" 36 | } 37 | } 38 | 39 | spec { 40 | automount_service_account_token = true 41 | 42 | container { 43 | name = "istio-operator" 44 | image = "docker.io/istio/operator:${var.istio_version}" 45 | command = ["operator", "server"] 46 | 47 | env { 48 | name = "WATCH_NAMESPACE" 49 | value = var.istio_namespace 50 | } 51 | 52 | env { 53 | name = "LEADER_ELECTION_NAMESPACE" 54 | value = kubernetes_namespace.istio_operator.metadata.0.name 55 | } 56 | 57 | env { 58 | name = "POD_NAME" 59 | value_from { 60 | field_ref { 61 | field_path = "metadata.name" 62 | } 63 | } 64 | } 65 | 66 | env { 67 | name = "OPERATOR_NAME" 68 | value = kubernetes_namespace.istio_operator.metadata.0.name 69 | } 70 | 71 | resources { 72 | limits { 73 | cpu = "200m" 74 | memory = "256Mi" 75 | } 76 | 77 | requests { 78 | cpu = "50m" 79 | memory = "128Mi" 80 | } 81 | } 82 | 83 | image_pull_policy = "IfNotPresent" 84 | } 85 | 86 | service_account_name = kubernetes_service_account.istio_operator.metadata.0.name 87 | } 88 | } 89 | } 90 | } 91 | 92 | resource "kubernetes_service" "istio_operator" { 93 | metadata { 94 | name = "istio-operator" 95 | namespace = kubernetes_namespace.istio_operator.metadata.0.name 96 | 97 | labels = { 98 | name = "istio-operator" 99 | } 100 | } 101 | 102 | spec { 103 | port { 104 | name = "http-metrics" 105 | port = 8383 106 | target_port = "8383" 107 | } 108 | 109 | selector = { 110 | name = "istio-operator" 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /istio/outputs.tf: -------------------------------------------------------------------------------- 1 | output "wait_for_crds" { 2 | value = [null_resource.wait_crds, kubernetes_namespace.istio_namespace.metadata.0.name] 3 | } -------------------------------------------------------------------------------- /istio/rbac.tf: -------------------------------------------------------------------------------- 1 | resource "kubernetes_cluster_role" "istio_operator" { 2 | metadata { 3 | name = "istio-operator" 4 | } 5 | 6 | rule { 7 | verbs = ["*"] 8 | api_groups = ["authentication.istio.io"] 9 | resources = ["*"] 10 | } 11 | 12 | rule { 13 | verbs = ["*"] 14 | api_groups = ["config.istio.io"] 15 | resources = ["*"] 16 | } 17 | 18 | rule { 19 | verbs = ["*"] 20 | api_groups = ["install.istio.io"] 21 | resources = ["*"] 22 | } 23 | 24 | rule { 25 | verbs = ["*"] 26 | api_groups = ["networking.istio.io"] 27 | resources = ["*"] 28 | } 29 | 30 | rule { 31 | verbs = ["*"] 32 | api_groups = ["rbac.istio.io"] 33 | resources = ["*"] 34 | } 35 | 36 | rule { 37 | verbs = ["*"] 38 | api_groups = ["security.istio.io"] 39 | resources = ["*"] 40 | } 41 | 42 | rule { 43 | verbs = ["*"] 44 | api_groups = ["admissionregistration.k8s.io"] 45 | resources = ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"] 46 | } 47 | 48 | rule { 49 | verbs = ["*"] 50 | api_groups = ["apiextensions.k8s.io"] 51 | resources = ["customresourcedefinitions.apiextensions.k8s.io", "customresourcedefinitions"] 52 | } 53 | 54 | rule { 55 | verbs = ["*"] 56 | api_groups = ["apps", "extensions"] 57 | resources = ["daemonsets", "deployments", "deployments/finalizers", "ingresses", "replicasets", "statefulsets"] 58 | } 59 | 60 | rule { 61 | verbs = ["*"] 62 | api_groups = ["autoscaling"] 63 | resources = ["horizontalpodautoscalers"] 64 | } 65 | 66 | rule { 67 | verbs = ["get", "create"] 68 | api_groups = ["monitoring.coreos.com"] 69 | resources = ["servicemonitors"] 70 | } 71 | 72 | rule { 73 | verbs = ["*"] 74 | api_groups = ["policy"] 75 | resources = ["poddisruptionbudgets"] 76 | } 77 | 78 | rule { 79 | verbs = ["*"] 80 | api_groups = ["rbac.authorization.k8s.io"] 81 | resources = ["clusterrolebindings", "clusterroles", "roles", "rolebindings"] 82 | } 83 | 84 | rule { 85 | verbs = ["*"] 86 | api_groups = [""] 87 | resources = ["configmaps", "endpoints", "events", "namespaces", "pods", "persistentvolumeclaims", "secrets", "services", "serviceaccounts"] 88 | } 89 | } 90 | 91 | resource "kubernetes_cluster_role_binding" "istio_operator" { 92 | metadata { 93 | name = "istio-operator" 94 | } 95 | 96 | subject { 97 | kind = "ServiceAccount" 98 | name = "istio-operator" 99 | namespace = kubernetes_namespace.istio_operator.metadata.0.name 100 | } 101 | 102 | role_ref { 103 | api_group = "rbac.authorization.k8s.io" 104 | kind = "ClusterRole" 105 | name = kubernetes_cluster_role.istio_operator.metadata.0.name 106 | } 107 | } 108 | 109 | resource "kubernetes_service_account" "istio_operator" { 110 | metadata { 111 | name = "istio-operator" 112 | namespace = kubernetes_namespace.istio_operator.metadata.0.name 113 | } 114 | } -------------------------------------------------------------------------------- /istio/variables.tf: -------------------------------------------------------------------------------- 1 | variable "istio_namespace" { 2 | type = string 3 | default = "istio-system" 4 | } 5 | 6 | variable "istio_operator_namespace" { 7 | type = string 8 | default = "istio-operator" 9 | } 10 | 11 | variable "ingress_gateway_annotations" { 12 | type = map(string) 13 | default = {} 14 | } 15 | 16 | variable "ingress_gateway_selector" { 17 | type = string 18 | default = "ingressgateway" 19 | } 20 | 21 | variable "ingress_gateway_ip" { 22 | type = string 23 | default = "" 24 | } 25 | 26 | variable "domain_name" { 27 | type = string 28 | default = "" 29 | } 30 | 31 | variable "use_cert_manager" { 32 | type = bool 33 | default = false 34 | } 35 | 36 | variable "certificate_name" { 37 | type = string 38 | default = "" 39 | } 40 | 41 | variable "istio_version" { 42 | type = string 43 | default = "1.6.8" 44 | } -------------------------------------------------------------------------------- /kubeflow-operator.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "kubernetes_namespace" "kubeflow_operator" { 3 | metadata { 4 | name = var.kubeflow_operator_namespace 5 | } 6 | } 7 | 8 | resource "k8s_manifest" "kubeflow_operator_crd" { 9 | content = templatefile("${path.module}/manifests/kubeflow/operator-crd.yaml", {}) 10 | } 11 | 12 | resource "kubernetes_service_account" "kubeflow_operator" { 13 | metadata { 14 | name = "kubeflow-operator" 15 | namespace = kubernetes_namespace.kubeflow_operator.metadata.0.name 16 | } 17 | } 18 | 19 | resource "kubernetes_cluster_role" "kubeflow_operator" { 20 | metadata { 21 | name = "kubeflow-operator" 22 | labels = { 23 | "kubernetes.io/bootstrapping" = "rbac-defaults" 24 | } 25 | 26 | annotations = { 27 | "rbac.authorization.kubernetes.io/autoupdate" = "true" 28 | } 29 | } 30 | 31 | rule { 32 | verbs = ["*"] 33 | api_groups = ["*"] 34 | resources = ["*"] 35 | } 36 | 37 | rule { 38 | verbs = ["*"] 39 | non_resource_urls = ["*"] 40 | } 41 | } 42 | 43 | resource "kubernetes_cluster_role_binding" "kubeflow_operator" { 44 | metadata { 45 | name = "kubeflow-operator" 46 | } 47 | 48 | subject { 49 | kind = "ServiceAccount" 50 | name = kubernetes_service_account.kubeflow_operator.metadata.0.name 51 | namespace = kubernetes_namespace.kubeflow_operator.metadata.0.name 52 | } 53 | 54 | role_ref { 55 | api_group = "rbac.authorization.k8s.io" 56 | kind = "ClusterRole" 57 | name = "cluster-admin" 58 | } 59 | } 60 | 61 | resource "kubernetes_deployment" "kubeflow_operator" { 62 | depends_on = [k8s_manifest.kubeflow_operator_crd, kubernetes_cluster_role_binding.kubeflow_operator] 63 | metadata { 64 | name = "kubeflow-operator" 65 | namespace = kubernetes_namespace.kubeflow_operator.metadata.0.name 66 | } 67 | 68 | spec { 69 | replicas = 1 70 | 71 | selector { 72 | match_labels = { 73 | name = "kubeflow-operator" 74 | } 75 | } 76 | 77 | template { 78 | metadata { 79 | labels = { 80 | name = "kubeflow-operator" 81 | } 82 | } 83 | 84 | spec { 85 | automount_service_account_token = true 86 | container { 87 | name = "kubeflow-operator" 88 | image = "aipipeline/kubeflow-operator:v${var.kubeflow_operator_version}" 89 | command = ["kfctl"] 90 | 91 | env { 92 | name = "WATCH_NAMESPACE" 93 | 94 | value_from { 95 | field_ref { 96 | field_path = "metadata.namespace" 97 | } 98 | } 99 | } 100 | 101 | env { 102 | name = "POD_NAME" 103 | 104 | value_from { 105 | field_ref { 106 | field_path = "metadata.name" 107 | } 108 | } 109 | } 110 | 111 | env { 112 | name = "OPERATOR_NAME" 113 | 114 | value_from { 115 | field_ref { 116 | field_path = "metadata.name" 117 | } 118 | } 119 | } 120 | 121 | image_pull_policy = "Always" 122 | } 123 | 124 | service_account_name = kubernetes_service_account.kubeflow_operator.metadata.0.name 125 | } 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /kubeflow.tf: -------------------------------------------------------------------------------- 1 | resource "kubernetes_namespace" "kubeflow" { 2 | depends_on = [module.istio, helm_release.cert_manager] 3 | metadata { 4 | name = "kubeflow" 5 | labels = { 6 | "control-plane" = "kubeflow" 7 | "katib-metricscollector-injection" = "enabled" 8 | } 9 | } 10 | } 11 | 12 | resource "k8s_manifest" "kubeflow_application_crd" { 13 | content = templatefile("${path.module}/manifests/kubeflow/application-crd.yaml", 14 | {} 15 | ) 16 | } 17 | 18 | resource "k8s_manifest" "kubeflow_kfdef" { 19 | depends_on = [kubernetes_deployment.kubeflow_operator, k8s_manifest.kubeflow_application_crd] 20 | timeouts { 21 | delete = "15m" 22 | } 23 | content = templatefile("${path.module}/manifests/kubeflow/kfdef.yaml", 24 | { 25 | namespace = kubernetes_namespace.kubeflow.metadata.0.name, 26 | components = var.kubeflow_components 27 | version = var.kubeflow_version 28 | } 29 | ) 30 | } 31 | 32 | locals { 33 | kubeflow_ingress_vs_manifests = split("\n---\n", templatefile( 34 | "${path.module}/manifests/kubeflow/gateway-vs.yaml", 35 | { 36 | credential_name = var.certificate_name, 37 | domain_name = var.domain_name, 38 | dns_record = var.dns_record, 39 | istio_namespace = var.istio_namespace 40 | ingress_gateway_selector = var.ingress_gateway_selector 41 | namespace = kubernetes_namespace.kubeflow.metadata.0.name 42 | use_cert_manager = var.use_cert_manager 43 | } 44 | ) 45 | ) 46 | } 47 | 48 | resource "k8s_manifest" "kubeflow_ingress_vs" { 49 | depends_on = [kubernetes_deployment.kubeflow_operator, module.istio, k8s_manifest.kubeflow_application_crd] 50 | count = length(local.kubeflow_ingress_vs_manifests) 51 | content = local.kubeflow_ingress_vs_manifests[count.index] 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "~> 0.13" 3 | required_providers { 4 | helm = { 5 | source = "hashicorp/helm" 6 | } 7 | kubernetes = { 8 | source = "hashicorp/kubernetes" 9 | } 10 | k8s = { 11 | source = "banzaicloud/k8s" 12 | version = "0.8.2" 13 | } 14 | } 15 | } 16 | 17 | provider "k8s" {} 18 | 19 | provider "helm" {} 20 | 21 | provider "kubernetes" {} 22 | 23 | module "auth" { 24 | depends_on = [module.istio, k8s_manifest.kubeflow_application_crd] 25 | providers = { 26 | kubernetes = kubernetes 27 | k8s = k8s 28 | } 29 | source = "./auth" 30 | application_secret = var.oidc_client_secret 31 | client_id = var.oidc_client_id 32 | domain_name = var.domain_name 33 | issuer = var.oidc_issuer 34 | istio_namespace = var.istio_namespace 35 | oidc_auth_url = var.oidc_auth_url 36 | oidc_redirect_url = var.oidc_redirect_url 37 | userid_claim = var.oidc_userid_claim 38 | } 39 | 40 | module "istio" { 41 | depends_on = [helm_release.cert_manager] 42 | count = var.install_istio ? 1 : 0 43 | providers = { 44 | kubernetes = kubernetes 45 | k8s = k8s 46 | helm = helm 47 | } 48 | source = "./istio" 49 | domain_name = var.domain_name 50 | ingress_gateway_annotations = var.ingress_gateway_annotations 51 | ingress_gateway_ip = var.ingress_gateway_ip 52 | ingress_gateway_selector = var.ingress_gateway_selector 53 | istio_namespace = var.istio_namespace 54 | istio_operator_namespace = var.istio_operator_namespace 55 | use_cert_manager = var.use_cert_manager 56 | certificate_name = var.certificate_name 57 | istio_version = var.istio_version 58 | } 59 | -------------------------------------------------------------------------------- /manifests/cert-manager/letsencrypt-prod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1alpha2 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt-prod 5 | spec: 6 | acme: 7 | # The ACME server URL 8 | server: https://acme-v02.api.letsencrypt.org/directory 9 | # Email address used for ACME registration 10 | email: ${email} 11 | # Name of a secret used to store the ACME account private key 12 | privateKeySecretRef: 13 | name: letsencrypt-prod 14 | # Enable HTTP01 validations 15 | solvers: 16 | - selector: {} 17 | http01: 18 | ingress: 19 | class: istio -------------------------------------------------------------------------------- /manifests/cert-manager/self-signed.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1alpha2 2 | kind: ClusterIssuer 3 | metadata: 4 | name: kubeflow-self-signing-issuer 5 | spec: 6 | selfSigned: {} -------------------------------------------------------------------------------- /manifests/kubeflow/application-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | creationTimestamp: null 5 | name: applications.app.k8s.io 6 | spec: 7 | group: app.k8s.io 8 | names: 9 | kind: Application 10 | plural: applications 11 | scope: Namespaced 12 | validation: 13 | openAPIV3Schema: 14 | properties: 15 | apiVersion: 16 | type: string 17 | kind: 18 | type: string 19 | metadata: 20 | type: object 21 | spec: 22 | properties: 23 | addOwnerRef: 24 | type: boolean 25 | assemblyPhase: 26 | type: string 27 | componentKinds: 28 | items: 29 | type: object 30 | type: array 31 | descriptor: 32 | properties: 33 | description: 34 | type: string 35 | icons: 36 | items: 37 | properties: 38 | size: 39 | type: string 40 | src: 41 | type: string 42 | type: 43 | type: string 44 | required: 45 | - src 46 | type: object 47 | type: array 48 | keywords: 49 | items: 50 | type: string 51 | type: array 52 | links: 53 | items: 54 | properties: 55 | description: 56 | type: string 57 | url: 58 | type: string 59 | type: object 60 | type: array 61 | maintainers: 62 | items: 63 | properties: 64 | email: 65 | type: string 66 | name: 67 | type: string 68 | url: 69 | type: string 70 | type: object 71 | type: array 72 | notes: 73 | type: string 74 | owners: 75 | items: 76 | properties: 77 | email: 78 | type: string 79 | name: 80 | type: string 81 | url: 82 | type: string 83 | type: object 84 | type: array 85 | type: 86 | type: string 87 | version: 88 | type: string 89 | type: object 90 | info: 91 | items: 92 | properties: 93 | name: 94 | type: string 95 | type: 96 | type: string 97 | value: 98 | type: string 99 | valueFrom: 100 | properties: 101 | configMapKeyRef: 102 | properties: 103 | apiVersion: 104 | type: string 105 | fieldPath: 106 | type: string 107 | key: 108 | type: string 109 | kind: 110 | type: string 111 | name: 112 | type: string 113 | namespace: 114 | type: string 115 | resourceVersion: 116 | type: string 117 | uid: 118 | type: string 119 | type: object 120 | ingressRef: 121 | properties: 122 | apiVersion: 123 | type: string 124 | fieldPath: 125 | type: string 126 | host: 127 | type: string 128 | kind: 129 | type: string 130 | name: 131 | type: string 132 | namespace: 133 | type: string 134 | path: 135 | type: string 136 | resourceVersion: 137 | type: string 138 | uid: 139 | type: string 140 | type: object 141 | secretKeyRef: 142 | properties: 143 | apiVersion: 144 | type: string 145 | fieldPath: 146 | type: string 147 | key: 148 | type: string 149 | kind: 150 | type: string 151 | name: 152 | type: string 153 | namespace: 154 | type: string 155 | resourceVersion: 156 | type: string 157 | uid: 158 | type: string 159 | type: object 160 | serviceRef: 161 | properties: 162 | apiVersion: 163 | type: string 164 | fieldPath: 165 | type: string 166 | kind: 167 | type: string 168 | name: 169 | type: string 170 | namespace: 171 | type: string 172 | path: 173 | type: string 174 | port: 175 | format: int32 176 | type: integer 177 | resourceVersion: 178 | type: string 179 | uid: 180 | type: string 181 | type: object 182 | type: 183 | type: string 184 | type: object 185 | type: object 186 | type: array 187 | selector: 188 | type: object 189 | type: object 190 | status: 191 | properties: 192 | components: 193 | items: 194 | properties: 195 | group: 196 | type: string 197 | kind: 198 | type: string 199 | link: 200 | type: string 201 | name: 202 | type: string 203 | status: 204 | type: string 205 | type: object 206 | type: array 207 | conditions: 208 | items: 209 | properties: 210 | lastTransitionTime: 211 | format: date-time 212 | type: string 213 | lastUpdateTime: 214 | format: date-time 215 | type: string 216 | message: 217 | type: string 218 | reason: 219 | type: string 220 | status: 221 | type: string 222 | type: 223 | type: string 224 | required: 225 | - type 226 | - status 227 | type: object 228 | type: array 229 | observedGeneration: 230 | format: int64 231 | type: integer 232 | type: object 233 | version: v1beta1 234 | status: 235 | acceptedNames: 236 | kind: "" 237 | plural: "" 238 | conditions: [] 239 | storedVersions: [] 240 | -------------------------------------------------------------------------------- /manifests/kubeflow/gateway-vs.yaml: -------------------------------------------------------------------------------- 1 | %{ if use_cert_manager ~} 2 | apiVersion: cert-manager.io/v1alpha2 3 | kind: Certificate 4 | metadata: 5 | name: kubeflow 6 | namespace: ${istio_namespace} 7 | spec: 8 | secretName: kubeflow-cert 9 | commonName: ${dns_record}.${domain_name} 10 | issuerRef: 11 | name: letsencrypt-prod 12 | kind: ClusterIssuer 13 | dnsNames: 14 | - ${dns_record}.${domain_name} 15 | %{ endif } 16 | %{ if credential_name != "" || use_cert_manager } 17 | --- 18 | apiVersion: networking.istio.io/v1alpha3 19 | kind: Gateway 20 | metadata: 21 | name: kubeflow-gateway 22 | namespace: ${namespace} 23 | spec: 24 | selector: 25 | istio: ${ingress_gateway_selector} 26 | servers: 27 | - port: 28 | number: 443 29 | name: https 30 | protocol: HTTPS 31 | tls: 32 | mode: SIMPLE 33 | credentialName: %{ if use_cert_manager ~}kubeflow-cert%{ else ~}${credential_name}%{ endif } 34 | hosts: 35 | - ${dns_record}.${domain_name} 36 | --- 37 | apiVersion: networking.istio.io/v1alpha3 38 | kind: VirtualService 39 | metadata: 40 | name: kiali-vs 41 | namespace: ${namespace} 42 | spec: 43 | gateways: 44 | - kubeflow-gateway 45 | hosts: 46 | - ${dns_record}.${domain_name} 47 | http: 48 | - match: 49 | - uri: 50 | prefix: /kiali/ 51 | rewrite: 52 | uri: /kiali/ 53 | route: 54 | - destination: 55 | host: kiali.${istio_namespace}.svc.cluster.local 56 | port: 57 | number: 20001 58 | --- 59 | apiVersion: networking.istio.io/v1alpha3 60 | kind: VirtualService 61 | metadata: 62 | name: grafana-vs 63 | namespace: ${namespace} 64 | spec: 65 | gateways: 66 | - kubeflow-gateway 67 | hosts: 68 | - ${dns_record}.${domain_name} 69 | http: 70 | - match: 71 | - method: 72 | exact: GET 73 | uri: 74 | prefix: /grafana/ 75 | rewrite: 76 | uri: /grafana/ 77 | route: 78 | - destination: 79 | host: grafana.${istio_namespace}.svc.cluster.local 80 | port: 81 | number: 3000 82 | %{ endif } 83 | --- 84 | apiVersion: rbac.istio.io/v1alpha1 85 | kind: ClusterRbacConfig 86 | metadata: 87 | name: default 88 | namespace: kubeflow 89 | spec: 90 | mode: "OFF" -------------------------------------------------------------------------------- /manifests/kubeflow/kfdef.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kfdef.apps.kubeflow.org/v1 2 | kind: KfDef 3 | metadata: 4 | namespace: ${namespace} 5 | name: kubeflow 6 | spec: 7 | applications: 8 | - kustomizeConfig: 9 | overlays: 10 | - application 11 | repoRef: 12 | name: manifests 13 | path: application/application 14 | name: application 15 | - kustomizeConfig: 16 | overlays: 17 | - istio 18 | - application 19 | repoRef: 20 | name: manifests 21 | path: argo 22 | name: argo 23 | - kustomizeConfig: 24 | repoRef: 25 | name: manifests 26 | path: kubeflow-roles 27 | name: kubeflow-roles 28 | - kustomizeConfig: 29 | overlays: 30 | - istio 31 | - application 32 | parameters: 33 | - name: userid-header 34 | value: kubeflow-userid 35 | repoRef: 36 | name: manifests 37 | path: common/centraldashboard 38 | name: centraldashboard 39 | - kustomizeConfig: 40 | overlays: 41 | - cert-manager 42 | - application 43 | repoRef: 44 | name: manifests 45 | path: admission-webhook/webhook 46 | name: webhook 47 | %{ if contains(components,"jupyter") ~} 48 | - kustomizeConfig: 49 | overlays: 50 | - istio 51 | - application 52 | parameters: 53 | - name: userid-header 54 | value: kubeflow-userid 55 | repoRef: 56 | name: manifests 57 | path: jupyter/jupyter-web-app 58 | name: jupyter-web-app 59 | - kustomizeConfig: 60 | overlays: 61 | - istio 62 | - application 63 | - db 64 | repoRef: 65 | name: manifests 66 | path: metadata 67 | name: metadata 68 | - kustomizeConfig: 69 | overlays: 70 | - istio 71 | - application 72 | repoRef: 73 | name: manifests 74 | path: jupyter/notebook-controller 75 | name: notebook-controller 76 | %{ endif } 77 | %{ if contains(components,"spark") ~} 78 | - kustomizeConfig: 79 | overlays: 80 | - application 81 | repoRef: 82 | name: manifests 83 | path: spark/spark-operator 84 | name: spark-operator 85 | %{ endif } 86 | %{ if contains(components,"pytorch") ~} 87 | - kustomizeConfig: 88 | overlays: 89 | - application 90 | repoRef: 91 | name: manifests 92 | path: pytorch-job/pytorch-job-crds 93 | name: pytorch-job-crds 94 | - kustomizeConfig: 95 | overlays: 96 | - application 97 | repoRef: 98 | name: manifests 99 | path: pytorch-job/pytorch-operator 100 | name: pytorch-operator 101 | %{ endif } 102 | %{ if contains(components,"knative") ~} 103 | - kustomizeConfig: 104 | overlays: 105 | - application 106 | parameters: 107 | - name: namespace 108 | value: knative-serving 109 | repoRef: 110 | name: manifests 111 | path: knative/knative-serving-crds 112 | name: knative-crds 113 | - kustomizeConfig: 114 | overlays: 115 | - application 116 | parameters: 117 | - name: namespace 118 | value: knative-serving 119 | repoRef: 120 | name: manifests 121 | path: knative/knative-serving-install 122 | name: knative-install 123 | - kustomizeConfig: 124 | overlays: 125 | - application 126 | repoRef: 127 | name: manifests 128 | path: kfserving/kfserving-crds 129 | name: kfserving-crds 130 | - kustomizeConfig: 131 | overlays: 132 | - application 133 | repoRef: 134 | name: manifests 135 | path: kfserving/kfserving-install 136 | name: kfserving-install 137 | %{ endif } 138 | %{ if contains(components,"spartakus") ~} 139 | - kustomizeConfig: 140 | overlays: 141 | - application 142 | parameters: 143 | - name: usageId 144 | value: 145 | - name: reportUsage 146 | value: 'true' 147 | repoRef: 148 | name: manifests 149 | path: common/spartakus 150 | name: spartakus 151 | %{ endif } 152 | %{ if contains(components,"tensorflow") ~} 153 | - kustomizeConfig: 154 | overlays: 155 | - istio 156 | repoRef: 157 | name: manifests 158 | path: tensorboard 159 | name: tensorboard 160 | - kustomizeConfig: 161 | overlays: 162 | - application 163 | repoRef: 164 | name: manifests 165 | path: tf-training/tf-job-crds 166 | name: tf-job-crds 167 | - kustomizeConfig: 168 | overlays: 169 | - application 170 | repoRef: 171 | name: manifests 172 | path: tf-training/tf-job-operator 173 | name: tf-job-operator 174 | %{ endif } 175 | %{ if contains(components,"katib") ~} 176 | - kustomizeConfig: 177 | overlays: 178 | - application 179 | repoRef: 180 | name: manifests 181 | path: katib/katib-crds 182 | name: katib-crds 183 | - kustomizeConfig: 184 | overlays: 185 | - application 186 | - istio 187 | repoRef: 188 | name: manifests 189 | path: katib/katib-controller 190 | name: katib-controller 191 | %{ endif } 192 | %{ if contains(components,"pipelines") ~} 193 | - kustomizeConfig: 194 | overlays: 195 | - application 196 | repoRef: 197 | name: manifests 198 | path: pipeline/api-service 199 | name: api-service 200 | - kustomizeConfig: 201 | overlays: 202 | - application 203 | parameters: 204 | - name: minioPvcName 205 | value: minio-pv-claim 206 | repoRef: 207 | name: manifests 208 | path: pipeline/minio 209 | name: minio 210 | - kustomizeConfig: 211 | overlays: 212 | - application 213 | parameters: 214 | - name: mysqlPvcName 215 | value: mysql-pv-claim 216 | repoRef: 217 | name: manifests 218 | path: pipeline/mysql 219 | name: mysql 220 | - kustomizeConfig: 221 | overlays: 222 | - application 223 | repoRef: 224 | name: manifests 225 | path: pipeline/persistent-agent 226 | name: persistent-agent 227 | - kustomizeConfig: 228 | overlays: 229 | - application 230 | repoRef: 231 | name: manifests 232 | path: pipeline/pipelines-runner 233 | name: pipelines-runner 234 | - kustomizeConfig: 235 | overlays: 236 | - istio 237 | - application 238 | repoRef: 239 | name: manifests 240 | path: pipeline/pipelines-ui 241 | name: pipelines-ui 242 | - kustomizeConfig: 243 | overlays: 244 | - application 245 | repoRef: 246 | name: manifests 247 | path: pipeline/pipelines-viewer 248 | name: pipelines-viewer 249 | - kustomizeConfig: 250 | overlays: 251 | - application 252 | repoRef: 253 | name: manifests 254 | path: pipeline/scheduledworkflow 255 | name: scheduledworkflow 256 | - kustomizeConfig: 257 | overlays: 258 | - application 259 | repoRef: 260 | name: manifests 261 | path: pipeline/pipeline-visualization-service 262 | name: pipeline-visualization-service 263 | %{ endif } 264 | - kustomizeConfig: 265 | overlays: 266 | - application 267 | - istio 268 | parameters: 269 | - name: userid-header 270 | value: kubeflow-userid 271 | repoRef: 272 | name: manifests 273 | path: profiles 274 | name: profiles 275 | %{ if contains(components,"seldon") ~} 276 | - kustomizeConfig: 277 | overlays: 278 | - application 279 | repoRef: 280 | name: manifests 281 | path: seldon/seldon-core-operator 282 | name: seldon-core-operator 283 | %{ endif } 284 | repos: 285 | - name: manifests 286 | uri: https://github.com/kubeflow/manifests/archive/v${version}.tar.gz 287 | version: v${version} -------------------------------------------------------------------------------- /manifests/kubeflow/operator-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: kfdefs.kfdef.apps.kubeflow.org 5 | spec: 6 | group: kfdef.apps.kubeflow.org 7 | names: 8 | kind: KfDef 9 | listKind: KfDefList 10 | plural: kfdefs 11 | singular: kfdef 12 | scope: Namespaced 13 | subresources: 14 | status: {} 15 | validation: 16 | openAPIV3Schema: 17 | description: KfDef is the Schema for the kfdefs API 18 | properties: 19 | apiVersion: 20 | description: 'APIVersion defines the versioned schema of this representation 21 | of an object. Servers should convert recognized schemas to the latest 22 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' 23 | type: string 24 | kind: 25 | description: 'Kind is a string value representing the REST resource this 26 | object represents. Servers may infer this from the endpoint the client 27 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 28 | type: string 29 | metadata: 30 | type: object 31 | spec: 32 | description: KfDefSpec defines the desired state of KfDef 33 | type: object 34 | status: 35 | description: KfDefStatus defines the observed state of KfDef 36 | type: object 37 | type: object 38 | version: v1 39 | versions: 40 | - name: v1 41 | served: true 42 | storage: true -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datarootsio/terraform-module-kubeflow/5c116854457653cd2d6be7fbd94f90165571da45/outputs.tf -------------------------------------------------------------------------------- /test/terraform_apply_destroy_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | "time" 7 | 8 | "github.com/gruntwork-io/terratest/modules/helm" 9 | "github.com/gruntwork-io/terratest/modules/k8s" 10 | "github.com/gruntwork-io/terratest/modules/logger" 11 | "github.com/gruntwork-io/terratest/modules/random" 12 | "github.com/gruntwork-io/terratest/modules/terraform" 13 | test_structure "github.com/gruntwork-io/terratest/modules/test-structure" 14 | "github.com/stretchr/testify/assert" 15 | "github.com/stretchr/testify/require" 16 | ) 17 | 18 | func getDefaultTerraformOptions(t *testing.T) (string, *terraform.Options, error) { 19 | 20 | tempTestFolder := test_structure.CopyTerraformFolderToTemp(t, "..", ".") 21 | 22 | random_id := strings.ToLower(random.UniqueId()) 23 | 24 | terraformOptions := &terraform.Options{ 25 | TerraformDir: tempTestFolder, 26 | Vars: map[string]interface{}{}, 27 | MaxRetries: 5, 28 | TimeBetweenRetries: 5 * time.Minute, 29 | NoColor: false, 30 | Logger: logger.TestingT, 31 | } 32 | 33 | return random_id, terraformOptions, nil 34 | } 35 | 36 | func getIstioTerraformOptions(t *testing.T) (*terraform.Options, error) { 37 | 38 | tempTestFolder := test_structure.CopyTerraformFolderToTemp(t, "..", "istio") 39 | 40 | terraformOptions := &terraform.Options{ 41 | TerraformDir: tempTestFolder, 42 | Vars: map[string]interface{}{}, 43 | MaxRetries: 5, 44 | TimeBetweenRetries: 5 * time.Minute, 45 | NoColor: false, 46 | Logger: logger.TestingT, 47 | } 48 | 49 | return terraformOptions, nil 50 | } 51 | 52 | func TestApplyAndDestroyWithOldValues(t *testing.T) { 53 | _, options, err := getDefaultTerraformOptions(t) 54 | assert.NoError(t, err) 55 | 56 | options.Vars["cert_manager_namespace"] = "cert-manager" 57 | options.Vars["istio_operator_namespace"] = "istio-operator" 58 | options.Vars["istio_namespace"] = "istio-system" 59 | options.Vars["ingress_gateway_ip"] = "10.20.30.40" 60 | options.Vars["use_cert_manager"] = true 61 | options.Vars["install_istio"] = true 62 | options.Vars["install_cert_manager"] = true 63 | options.Vars["domain_name"] = "foo.local" 64 | options.Vars["letsencrypt_email"] = "foo@bar.local" 65 | options.Vars["ingress_gateway_annotations"] = map[string]interface{}{"foo": "bar"} 66 | options.Vars["kubeflow_version"] = "1.0.2" 67 | options.Vars["kubeflow_operator_version"] = "1.0.0" 68 | 69 | defer terraform.Destroy(t, options) 70 | _, err = terraform.InitAndApplyE(t, options) 71 | assert.NoError(t, err) 72 | } 73 | 74 | func TestApplyAndDestroyWithSaneValues(t *testing.T) { 75 | _, options, err := getDefaultTerraformOptions(t) 76 | assert.NoError(t, err) 77 | 78 | options.Vars["cert_manager_namespace"] = "cert-manager" 79 | options.Vars["istio_operator_namespace"] = "istio-operator" 80 | options.Vars["istio_namespace"] = "istio-system" 81 | options.Vars["ingress_gateway_ip"] = "10.20.30.40" 82 | options.Vars["use_cert_manager"] = true 83 | options.Vars["install_istio"] = true 84 | options.Vars["install_cert_manager"] = true 85 | options.Vars["domain_name"] = "foo.local" 86 | options.Vars["letsencrypt_email"] = "foo@bar.local" 87 | options.Vars["ingress_gateway_annotations"] = map[string]interface{}{"foo": "bar"} 88 | 89 | defer terraform.Destroy(t, options) 90 | _, err = terraform.InitAndApplyE(t, options) 91 | assert.NoError(t, err) 92 | } 93 | 94 | func TestApplyAndDestroyWithOnlyPipelines(t *testing.T) { 95 | _, options, err := getDefaultTerraformOptions(t) 96 | assert.NoError(t, err) 97 | 98 | options.Vars["cert_manager_namespace"] = "cert-manager" 99 | options.Vars["istio_operator_namespace"] = "istio-operator" 100 | options.Vars["istio_namespace"] = "istio-system" 101 | options.Vars["ingress_gateway_ip"] = "10.20.30.40" 102 | options.Vars["use_cert_manager"] = true 103 | options.Vars["install_istio"] = true 104 | options.Vars["install_cert_manager"] = true 105 | options.Vars["domain_name"] = "foo.local" 106 | options.Vars["letsencrypt_email"] = "foo@bar.local" 107 | options.Vars["ingress_gateway_annotations"] = map[string]interface{}{"foo": "bar"} 108 | options.Vars["kubeflow_components"] = []string{"'katib'", "'pipelines'"} 109 | options.Vars["kubeflow_version"] = "1.1.0" 110 | 111 | defer terraform.Destroy(t, options) 112 | _, err = terraform.InitAndApplyE(t, options) 113 | assert.NoError(t, err) 114 | } 115 | 116 | func TestApplyAndDestroyWithExistingIstioCertManager(t *testing.T) { 117 | _, options, err := getDefaultTerraformOptions(t) 118 | istioOptions, err2 := getIstioTerraformOptions(t) 119 | assert.NoError(t, err) 120 | assert.NoError(t, err2) 121 | 122 | cmK8sOptions := k8s.NewKubectlOptions("", "", "cert-manager") 123 | k8s.CreateNamespace(t, cmK8sOptions, "cert-manager") 124 | defer k8s.DeleteNamespace(t, cmK8sOptions, "cert-manager") 125 | 126 | emptyOptions := &helm.Options{} 127 | 128 | _, err = helm.RunHelmCommandAndGetOutputE(t, emptyOptions, "repo", "add", "jetstack", "https://charts.jetstack.io") 129 | assert.NoError(t, err) 130 | _, err = helm.RunHelmCommandAndGetOutputE(t, emptyOptions, "repo", "update") 131 | assert.NoError(t, err) 132 | 133 | cmOptions := &helm.Options{ 134 | KubectlOptions: cmK8sOptions, 135 | SetValues: map[string]string{ 136 | "installCRDs": "true", 137 | }, 138 | Version: "v0.16.1", 139 | } 140 | 141 | defer helm.Delete(t, cmOptions, "cert-manager", true) 142 | require.NoError(t, helm.InstallE(t, cmOptions, "jetstack/cert-manager", "cert-manager")) 143 | 144 | options.Vars["ingress_gateway_ip"] = "10.20.30.40" 145 | options.Vars["use_cert_manager"] = true 146 | options.Vars["install_istio"] = false 147 | options.Vars["install_cert_manager"] = false 148 | options.Vars["domain_name"] = "foo.local" 149 | options.Vars["letsencrypt_email"] = "foo@bar.local" 150 | options.Vars["ingress_gateway_annotations"] = map[string]interface{}{"foo": "bar"} 151 | 152 | istioOptions.Vars["ingress_gateway_ip"] = "10.20.30.40" 153 | istioOptions.Vars["use_cert_manager"] = true 154 | istioOptions.Vars["domain_name"] = "foo.local" 155 | istioOptions.Vars["ingress_gateway_annotations"] = map[string]interface{}{"foo": "bar"} 156 | 157 | defer terraform.Destroy(t, istioOptions) 158 | _, err = terraform.InitAndApplyE(t, istioOptions) 159 | assert.NoError(t, err) 160 | 161 | time.Sleep(180 * time.Second) 162 | 163 | defer terraform.Destroy(t, options) 164 | _, err = terraform.InitAndApplyE(t, options) 165 | assert.NoError(t, err) 166 | } 167 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "install_istio" { 2 | type = bool 3 | default = false 4 | description = "Should this module install istio" 5 | } 6 | 7 | variable "istio_version" { 8 | type = string 9 | default = "1.6.8" 10 | description = "The version of istio that will be installed" 11 | } 12 | 13 | variable "install_cert_manager" { 14 | type = bool 15 | default = false 16 | } 17 | 18 | variable "istio_namespace" { 19 | type = string 20 | default = "istio-system" 21 | description = "The namespace for istio" 22 | } 23 | 24 | variable "istio_operator_namespace" { 25 | type = string 26 | default = "istio-operator" 27 | description = "The namespace for istio operator" 28 | } 29 | 30 | variable "cert_manager_namespace" { 31 | type = string 32 | default = "cert-manager" 33 | description = "The namespace for istio operator" 34 | } 35 | 36 | variable "kubeflow_operator_namespace" { 37 | type = string 38 | default = "kubeflow-operator" 39 | description = "The namespace for kubeflow operator" 40 | } 41 | 42 | variable "cert_manager_version" { 43 | type = string 44 | default = "v0.16.1" 45 | description = "The version of cert-manager" 46 | 47 | } 48 | 49 | variable "ingress_gateway_annotations" { 50 | type = map(string) 51 | default = {} 52 | description = "A map of key-value annotations for istio ingressgateway" 53 | } 54 | 55 | variable "ingress_gateway_ip" { 56 | type = string 57 | default = "" 58 | description = "The IP of istio ingressgateway" 59 | } 60 | 61 | variable "ingress_gateway_selector" { 62 | type = string 63 | default = "ingressgateway" 64 | description = "Istio ingressgateway selector" 65 | } 66 | 67 | variable "dns_record" { 68 | type = string 69 | default = "kubeflow" 70 | description = "The DNS record for Kubeflow's ingresses" 71 | } 72 | 73 | variable "domain_name" { 74 | type = string 75 | default = "" 76 | description = "The domain name for Kubeflow's ingresses DNS records" 77 | } 78 | 79 | variable "use_cert_manager" { 80 | type = bool 81 | default = false 82 | description = "Should we use cert-manager for ingresses certificates" 83 | } 84 | 85 | variable "certificate_name" { 86 | type = string 87 | default = "" 88 | description = "The secret where the pre-generated certificate is stored" 89 | } 90 | 91 | variable "letsencrypt_email" { 92 | type = string 93 | default = "" 94 | description = "The email to use for let's encrypt certificate requests" 95 | } 96 | 97 | variable "oidc_client_secret" { 98 | type = string 99 | default = "pUBnBOY80SnXgjibTYM9ZWNzY2xreNGQok" 100 | description = "The OIDC client secret. The default value is not safe !" 101 | } 102 | 103 | variable "oidc_userid_claim" { 104 | type = string 105 | default = "email" 106 | description = "The claim for OIDC auth flows" 107 | } 108 | 109 | variable "oidc_auth_url" { 110 | type = string 111 | default = "/dex/auth" 112 | description = "The auth url for OIDC" 113 | } 114 | 115 | variable "oidc_client_id" { 116 | type = string 117 | default = "kubeflow-oidc-authservice" 118 | description = "The Client ID for OIDC" 119 | } 120 | 121 | variable "oidc_issuer" { 122 | type = string 123 | default = "http://dex.auth.svc.cluster.local:5556/dex" 124 | description = "The OIDC issuer" 125 | } 126 | 127 | variable "oidc_redirect_url" { 128 | type = string 129 | default = "/login/oidc" 130 | description = "The OIDC redirect URL" 131 | } 132 | 133 | variable "kubeflow_components" { 134 | type = list(string) 135 | default = ["jupyter", "spark", "pytorch", "knative", "spartakus", "tensorflow", "katib", "pipelines", "seldon"] 136 | description = "The list of components to install. KF Operator does not support updates so changes after initial deployment will not be reflected." 137 | } 138 | 139 | variable "kubeflow_version" { 140 | type = string 141 | default = "1.1.0" 142 | description = "The version of kubeflow to install" 143 | } 144 | 145 | variable "kubeflow_operator_version" { 146 | type = string 147 | default = "1.0.0" 148 | description = "The version of kubeflow operator to install" 149 | } --------------------------------------------------------------------------------