From 0642f7bb3ed79d89e2df0c442e3a6caa622fd9ae Mon Sep 17 00:00:00 2001 From: Bala Guduru Date: Fri, 12 Jul 2019 10:28:49 -0700 Subject: [PATCH 1/5] Upgrading terraform version to 0.12.3 --- Jenkinsfile | 2 +- README.md | 4 +- terraform/main.tf | 204 ++++++++++++++-------------- terraform/provider.tf | 8 +- terraform/variables.tf | 46 +++++-- terraform/versions.tf | 19 +++ test/boilerplate/boilerplate.tf.txt | 2 +- 7 files changed, 159 insertions(+), 126 deletions(-) create mode 100644 terraform/versions.tf diff --git a/Jenkinsfile b/Jenkinsfile index d27f960..da07899 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -35,7 +35,7 @@ metadata: spec: containers: - name: ${containerName} - image: gcr.io/pso-helmsman-cicd/jenkins-k8s-node:${env.CONTAINER_VERSION} + image: gcr.io/pso-helmsman-cicd/jenkins-k8s-node:jenkins-cicd_images_builder-185 command: ['cat'] tty: true volumeMounts: diff --git a/README.md b/README.md index bda35e8..0ad26b9 100644 --- a/README.md +++ b/README.md @@ -110,8 +110,8 @@ gcloud init In order to use the code in this demo you will need to have have access to a bash-compatible shell with the following tools installed: -1. [Terraform >= 0.11.7](https://www.terraform.io/downloads.html) -2. [Google Cloud SDK version >= 204.0.0](https://cloud.google.com/sdk/docs/downloads-versioned-archives) +1. [Terraform >= 0.12.3](https://www.terraform.io/downloads.html) +2. [Google Cloud SDK version >= 253.0.0](https://cloud.google.com/sdk/docs/downloads-versioned-archives) 3. [kubectl matching the latest GKE version](https://kubernetes.io/docs/tasks/tools/install-kubectl/) 4. Two [GCP projects](https://console.cloud.google.com/) with billing enabled diff --git a/terraform/main.tf b/terraform/main.tf index 78fe167..a7d3b1f 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -17,46 +17,44 @@ limitations under the License. # Create two new networks to be used for the demo: one in the project housing the # GKE cluster and one in the project housing the GCE instance. resource "google_compute_network" "istio" { - name = "${var.istio_network}" + name = var.istio_network auto_create_subnetworks = "false" - project = "${var.istio_project}" + project = var.istio_project } resource "google_compute_network" "gce" { - name = "${var.gce_network}" + name = var.gce_network auto_create_subnetworks = "false" - project = "${var.gce_project}" + project = var.gce_project } # Create a subnet with secondary IP ranges to be used for GKE's IP aliasing: # https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips resource "google_compute_subnetwork" "subnet_istio" { - name = "${var.istio_subnet}" - network = "${google_compute_network.istio.self_link}" - ip_cidr_range = "${var.istio_subnet_cidr}" - - secondary_ip_range = [ - { - range_name = "istio-cluster-cidr" - ip_cidr_range = "${var.istio_subnet_cluster_cidr}" - }, - { - range_name = "istio-services-cidr" - ip_cidr_range = "${var.istio_subnet_services_cidr}" - }, - ] + name = var.istio_subnet + network = google_compute_network.istio.self_link + ip_cidr_range = var.istio_subnet_cidr + + secondary_ip_range { + range_name = "istio-cluster-cidr" + ip_cidr_range = var.istio_subnet_cluster_cidr + } + secondary_ip_range { + range_name = "istio-services-cidr" + ip_cidr_range = var.istio_subnet_services_cidr + } - project = "${var.istio_project}" - region = "${var.region}" + project = var.istio_project + region = var.region } # Create a regular subnet to be used by the GCE instance. resource "google_compute_subnetwork" "subnet_gce" { - name = "${var.gce_subnet}" - network = "${google_compute_network.gce.self_link}" - ip_cidr_range = "${var.gce_subnet_cidr}" - project = "${var.gce_project}" - region = "${var.region}" + name = var.gce_subnet + network = google_compute_network.gce.self_link + ip_cidr_range = var.gce_subnet_cidr + project = var.gce_project + region = var.region } # All of the forwarding rule, VPN gateway, IP address, and tunnel resources are @@ -66,117 +64,117 @@ resource "google_compute_subnetwork" "subnet_gce" { # https://cloud.google.com/vpn/docs/how-to/creating-route-based-vpns resource "google_compute_vpn_gateway" "target_gateway_istio" { name = "vpn-istio" - project = "${var.istio_project}" - network = "${google_compute_network.istio.self_link}" - region = "${google_compute_subnetwork.subnet_istio.region}" + project = var.istio_project + network = google_compute_network.istio.self_link + region = google_compute_subnetwork.subnet_istio.region } resource "google_compute_vpn_gateway" "target_gateway_gce" { name = "vpn-gce" - project = "${var.gce_project}" - network = "${google_compute_network.gce.self_link}" - region = "${google_compute_subnetwork.subnet_gce.region}" + project = var.gce_project + network = google_compute_network.gce.self_link + region = google_compute_subnetwork.subnet_gce.region } resource "google_compute_address" "vpn_static_ip_istio" { name = "vpn-static-ip-istio" - project = "${var.istio_project}" - region = "${google_compute_subnetwork.subnet_istio.region}" + project = var.istio_project + region = google_compute_subnetwork.subnet_istio.region } resource "google_compute_address" "vpn_static_ip_gce" { name = "vpn-static-ip-gce" - project = "${var.gce_project}" - region = "${google_compute_subnetwork.subnet_gce.region}" + project = var.gce_project + region = google_compute_subnetwork.subnet_gce.region } resource "google_compute_forwarding_rule" "fr_esp_istio" { name = "fr-esp-istio" ip_protocol = "ESP" - ip_address = "${google_compute_address.vpn_static_ip_istio.address}" - target = "${google_compute_vpn_gateway.target_gateway_istio.self_link}" - project = "${var.istio_project}" + ip_address = google_compute_address.vpn_static_ip_istio.address + target = google_compute_vpn_gateway.target_gateway_istio.self_link + project = var.istio_project } resource "google_compute_forwarding_rule" "fr_esp_gce" { name = "fr-esp-gce" ip_protocol = "ESP" - ip_address = "${google_compute_address.vpn_static_ip_gce.address}" - target = "${google_compute_vpn_gateway.target_gateway_gce.self_link}" - project = "${var.gce_project}" + ip_address = google_compute_address.vpn_static_ip_gce.address + target = google_compute_vpn_gateway.target_gateway_gce.self_link + project = var.gce_project } resource "google_compute_forwarding_rule" "fr_udp500_istio" { name = "fr-udp500-istio" ip_protocol = "UDP" port_range = "500-500" - ip_address = "${google_compute_address.vpn_static_ip_istio.address}" - target = "${google_compute_vpn_gateway.target_gateway_istio.self_link}" - project = "${var.istio_project}" + ip_address = google_compute_address.vpn_static_ip_istio.address + target = google_compute_vpn_gateway.target_gateway_istio.self_link + project = var.istio_project } resource "google_compute_forwarding_rule" "fr_udp500_gce" { name = "fr-udp500-gce" ip_protocol = "UDP" port_range = "500-500" - ip_address = "${google_compute_address.vpn_static_ip_gce.address}" - target = "${google_compute_vpn_gateway.target_gateway_gce.self_link}" - project = "${var.gce_project}" + ip_address = google_compute_address.vpn_static_ip_gce.address + target = google_compute_vpn_gateway.target_gateway_gce.self_link + project = var.gce_project } resource "google_compute_forwarding_rule" "fr_udp4500_gce" { name = "fr-udp4500-gce" ip_protocol = "UDP" port_range = "4500-4500" - ip_address = "${google_compute_address.vpn_static_ip_gce.address}" - target = "${google_compute_vpn_gateway.target_gateway_gce.self_link}" - project = "${var.gce_project}" + ip_address = google_compute_address.vpn_static_ip_gce.address + target = google_compute_vpn_gateway.target_gateway_gce.self_link + project = var.gce_project } resource "google_compute_forwarding_rule" "fr_udp4500_istio" { name = "fr-udp4500-istio" ip_protocol = "UDP" port_range = "4500-4500" - ip_address = "${google_compute_address.vpn_static_ip_istio.address}" - target = "${google_compute_vpn_gateway.target_gateway_istio.self_link}" - project = "${var.istio_project}" + ip_address = google_compute_address.vpn_static_ip_istio.address + target = google_compute_vpn_gateway.target_gateway_istio.self_link + project = var.istio_project } resource "google_compute_vpn_tunnel" "tunnel1_istio" { name = "tunnel1-istio" - peer_ip = "${google_compute_address.vpn_static_ip_gce.address}" + peer_ip = google_compute_address.vpn_static_ip_gce.address shared_secret = "a secret message" - project = "${var.istio_project}" + project = var.istio_project - target_vpn_gateway = "${google_compute_vpn_gateway.target_gateway_istio.self_link}" + target_vpn_gateway = google_compute_vpn_gateway.target_gateway_istio.self_link local_traffic_selector = ["0.0.0.0/0"] remote_traffic_selector = ["0.0.0.0/0"] depends_on = [ - "google_compute_forwarding_rule.fr_esp_istio", - "google_compute_forwarding_rule.fr_udp500_istio", - "google_compute_forwarding_rule.fr_udp4500_istio", + google_compute_forwarding_rule.fr_esp_istio, + google_compute_forwarding_rule.fr_udp500_istio, + google_compute_forwarding_rule.fr_udp4500_istio, ] } resource "google_compute_vpn_tunnel" "tunnel1_gce" { name = "tunnel1-gce" - peer_ip = "${google_compute_address.vpn_static_ip_istio.address}" + peer_ip = google_compute_address.vpn_static_ip_istio.address shared_secret = "a secret message" - project = "${var.gce_project}" + project = var.gce_project - target_vpn_gateway = "${google_compute_vpn_gateway.target_gateway_gce.self_link}" + target_vpn_gateway = google_compute_vpn_gateway.target_gateway_gce.self_link local_traffic_selector = ["0.0.0.0/0"] remote_traffic_selector = ["0.0.0.0/0"] depends_on = [ - "google_compute_forwarding_rule.fr_esp_gce", - "google_compute_forwarding_rule.fr_udp500_gce", - "google_compute_forwarding_rule.fr_udp4500_gce", + google_compute_forwarding_rule.fr_esp_gce, + google_compute_forwarding_rule.fr_udp500_gce, + google_compute_forwarding_rule.fr_udp4500_gce, ] } @@ -184,59 +182,59 @@ resource "google_compute_vpn_tunnel" "tunnel1_gce" { # to the VPN resource "google_compute_route" "route_istio" { name = "route-istio" - network = "${google_compute_network.istio.name}" - dest_range = "${google_compute_subnetwork.subnet_gce.ip_cidr_range}" + network = google_compute_network.istio.name + dest_range = google_compute_subnetwork.subnet_gce.ip_cidr_range priority = 1000 - project = "${var.istio_project}" + project = var.istio_project - next_hop_vpn_tunnel = "${google_compute_vpn_tunnel.tunnel1_istio.self_link}" + next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel1_istio.self_link } # Ensures that traffic destined for a pod in the GKE cluster in the GCE project # is routed to the VPN resource "google_compute_route" "route_gce_cluster_cidr" { name = "route-istio-cluster-cidr" - network = "${google_compute_network.gce.name}" + network = google_compute_network.gce.name # TODO: figure out how to use declared subnet ranges instead of the variable - dest_range = "${google_compute_subnetwork.subnet_istio.secondary_ip_range.0.ip_cidr_range}" + dest_range = google_compute_subnetwork.subnet_istio.secondary_ip_range[0].ip_cidr_range priority = 1000 - project = "${var.gce_project}" + project = var.gce_project - next_hop_vpn_tunnel = "${google_compute_vpn_tunnel.tunnel1_gce.self_link}" + next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel1_gce.self_link } # Ensures that traffic destined for a service in the GKE cluster from the GCE \ # project is routed to the VPN resource "google_compute_route" "route_gce_services_cidr" { name = "route-istio-services-cidr" - network = "${google_compute_network.gce.name}" + network = google_compute_network.gce.name # TODO: figure out how to use declared subnet ranges instead of the variable - dest_range = "${google_compute_subnetwork.subnet_istio.secondary_ip_range.1.ip_cidr_range}" + dest_range = google_compute_subnetwork.subnet_istio.secondary_ip_range[1].ip_cidr_range priority = 1000 - project = "${var.gce_project}" + project = var.gce_project - next_hop_vpn_tunnel = "${google_compute_vpn_tunnel.tunnel1_gce.self_link}" + next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel1_gce.self_link } # Routes traffic destined for the GKE cluster subnet in the GCE project over # the VPN resource "google_compute_route" "route_gce" { name = "route-gce" - network = "${google_compute_network.gce.name}" - dest_range = "${google_compute_subnetwork.subnet_istio.ip_cidr_range}" + network = google_compute_network.gce.name + dest_range = google_compute_subnetwork.subnet_istio.ip_cidr_range priority = 1000 - project = "${var.gce_project}" + project = var.gce_project - next_hop_vpn_tunnel = "${google_compute_vpn_tunnel.tunnel1_gce.self_link}" + next_hop_vpn_tunnel = google_compute_vpn_tunnel.tunnel1_gce.self_link } # Allows SSH traffic from anywhere to the database VM resource "google_compute_firewall" "allow_ssh" { name = "allow-gce-ssh" - project = "${var.gce_project}" - network = "${google_compute_network.gce.name}" + project = var.gce_project + network = google_compute_network.gce.name source_ranges = ["0.0.0.0/0"] target_tags = ["mysql"] @@ -250,12 +248,12 @@ resource "google_compute_firewall" "allow_ssh" { # Allows database traffic from the GKE cluster to the database VM resource "google_compute_firewall" "allow_mysql" { name = "allow-gce-mysql" - project = "${var.gce_project}" - network = "${google_compute_network.gce.name}" + project = var.gce_project + network = google_compute_network.gce.name source_ranges = [ - "${google_compute_subnetwork.subnet_istio.secondary_ip_range.0.ip_cidr_range}", - "${google_compute_subnetwork.subnet_istio.secondary_ip_range.1.ip_cidr_range}", + google_compute_subnetwork.subnet_istio.secondary_ip_range[0].ip_cidr_range, + google_compute_subnetwork.subnet_istio.secondary_ip_range[1].ip_cidr_range, ] target_tags = ["mysql"] @@ -268,21 +266,21 @@ resource "google_compute_firewall" "allow_mysql" { # Creates a GKE cluster to be used in the demo resource "google_container_cluster" "istio_cluster" { - name = "${var.istio_cluster}" - zone = "${var.zone}" - project = "${var.istio_project}" - network = "${google_compute_network.istio.self_link}" - subnetwork = "${google_compute_subnetwork.subnet_istio.self_link}" - min_master_version = "${var.gke_version}" + name = var.istio_cluster + zone = var.zone + project = var.istio_project + network = google_compute_network.istio.self_link + subnetwork = google_compute_subnetwork.subnet_istio.self_link + min_master_version = var.gke_version initial_node_count = "4" - provider = "google-beta" + provider = google-beta addons_config { istio_config { disabled = false - auth = "AUTH_MUTUAL_TLS" + auth = "AUTH_MUTUAL_TLS" } } @@ -293,8 +291,8 @@ resource "google_container_cluster" "istio_cluster" { ip_allocation_policy { # TODO: figure out how to use variables for these networks - cluster_secondary_range_name = "${google_compute_subnetwork.subnet_istio.secondary_ip_range.0.range_name}" - services_secondary_range_name = "${google_compute_subnetwork.subnet_istio.secondary_ip_range.1.range_name}" + cluster_secondary_range_name = google_compute_subnetwork.subnet_istio.secondary_ip_range[0].range_name + services_secondary_range_name = google_compute_subnetwork.subnet_istio.secondary_ip_range[1].range_name } # Here we use gcloud to gather authentication information about our new cluster and write that @@ -302,16 +300,15 @@ resource "google_container_cluster" "istio_cluster" { provisioner "local-exec" { command = "gcloud container clusters get-credentials ${google_container_cluster.istio_cluster.name} --zone ${google_container_cluster.istio_cluster.zone} --project ${var.istio_project}" } - } # Creates a GCE instance to be used for the database. The tag is necessary to # apply the correct firewall rules. resource "google_compute_instance" "default" { - name = "${var.gce_vm}" + name = var.gce_vm machine_type = "n1-standard-1" - project = "${var.gce_project}" - zone = "${var.zone}" + project = var.gce_project + zone = var.zone boot_disk { initialize_params { @@ -322,7 +319,8 @@ resource "google_compute_instance" "default" { tags = ["mysql"] network_interface { - subnetwork = "${google_compute_subnetwork.subnet_gce.self_link}" - access_config = {} + subnetwork = google_compute_subnetwork.subnet_gce.self_link + access_config { + } } } diff --git a/terraform/provider.tf b/terraform/provider.tf index 7ee6063..8891b04 100644 --- a/terraform/provider.tf +++ b/terraform/provider.tf @@ -15,11 +15,11 @@ limitations under the License. */ provider "google-beta" { -version = "~> v2.0.0" -region = "${var.region}" + version = "~> v2.10.0" + region = var.region } provider "google" { - version = "~> v1.17" - region = "${var.region}" + version = "~> v2.10.0" + region = var.region } diff --git a/terraform/variables.tf b/terraform/variables.tf index 07a2b66..a496b8f 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -15,49 +15,65 @@ limitations under the License. */ // The project used to deploy the GKE cluster -variable "istio_project" {} +variable "istio_project" { +} // The project used to deploy the GCE instance -variable "gce_project" {} +variable "gce_project" { +} // The name of the network to create for the GKE cluster -variable "istio_network" {} +variable "istio_network" { +} // The name of the network to create for the GCE instance -variable "gce_network" {} +variable "gce_network" { +} // The name to use for the GKE cluster -variable "istio_cluster" {} +variable "istio_cluster" { +} // NOTE: The zone selected must reside in the selected region // The region in which to deploy all regionally-scoped resources -variable "region" {} +variable "region" { +} // The zone in which to deploy all zonally-scoped resources -variable "zone" {} +variable "zone" { +} // The subnet used to deploy the GKE cluster -variable "istio_subnet" {} +variable "istio_subnet" { +} // The CIDR used by the GKE cluster's subnet -variable "istio_subnet_cidr" {} +variable "istio_subnet_cidr" { +} // The alias IP CIDR used by the GKE cluster's pods -variable "istio_subnet_cluster_cidr" {} +variable "istio_subnet_cluster_cidr" { +} // The alias IP CIDR used by the GKE cluster's services -variable "istio_subnet_services_cidr" {} +variable "istio_subnet_services_cidr" { +} // The subnet used by the GCE instance -variable "gce_subnet" {} +variable "gce_subnet" { +} // The CIDR used by the GCE instance's subnet -variable "gce_subnet_cidr" {} +variable "gce_subnet_cidr" { +} // The name to use for the GCE instance -variable "gce_vm" {} +variable "gce_vm" { +} // The gke version to use for the istio cluster. This version must correspond // with the istio version in "Supported Cluster Versions": // https://cloud.google.com/istio/docs/istio-on-gke/installing -variable "gke_version" {} +variable "gke_version" { +} + diff --git a/terraform/versions.tf b/terraform/versions.tf new file mode 100644 index 0000000..8a2201e --- /dev/null +++ b/terraform/versions.tf @@ -0,0 +1,19 @@ +/* +Copyright 2019 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +terraform { + required_version = ">= 0.12" +} diff --git a/test/boilerplate/boilerplate.tf.txt b/test/boilerplate/boilerplate.tf.txt index 557e16f..0fb04be 100644 --- a/test/boilerplate/boilerplate.tf.txt +++ b/test/boilerplate/boilerplate.tf.txt @@ -1,5 +1,5 @@ /* -Copyright 2018 Google LLC +Copyright 2019 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From e60ce8986fb58ed95d79312bcb030b398bc79560 Mon Sep 17 00:00:00 2001 From: Bala Guduru Date: Fri, 12 Jul 2019 10:41:14 -0700 Subject: [PATCH 2/5] Updating tf file headers --- terraform/main.tf | 2 +- terraform/provider.tf | 2 +- terraform/variables.tf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/terraform/main.tf b/terraform/main.tf index a7d3b1f..64fda7e 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -1,5 +1,5 @@ /* -Copyright 2018 Google LLC +Copyright 2019 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/terraform/provider.tf b/terraform/provider.tf index 8891b04..b660647 100644 --- a/terraform/provider.tf +++ b/terraform/provider.tf @@ -1,5 +1,5 @@ /* -Copyright 2018 Google LLC +Copyright 2019 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/terraform/variables.tf b/terraform/variables.tf index a496b8f..d3dca58 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -1,5 +1,5 @@ /* -Copyright 2018 Google LLC +Copyright 2019 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 42cc4a425e47313f1c12f94db8fe31ac28c3d8e9 Mon Sep 17 00:00:00 2001 From: Bala Guduru Date: Fri, 12 Jul 2019 11:57:19 -0700 Subject: [PATCH 3/5] Updating Jenkins container image pull path --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index da07899..548a6c4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -35,7 +35,7 @@ metadata: spec: containers: - name: ${containerName} - image: gcr.io/pso-helmsman-cicd/jenkins-k8s-node:jenkins-cicd_images_builder-185 + image: gcr.io/pso-helmsman-cicd/jenkins-k8s-node:${env.JENKINS_CONTAINER_VERSION} command: ['cat'] tty: true volumeMounts: From a0d54971d4e23b622d52ad0c00604a5dd11bee8f Mon Sep 17 00:00:00 2001 From: Bala Guduru Date: Fri, 12 Jul 2019 13:59:55 -0700 Subject: [PATCH 4/5] Test commit --- terraform/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform/variables.tf b/terraform/variables.tf index d3dca58..e906d98 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -1,5 +1,5 @@ /* -Copyright 2019 Google LLC +Copyright 2019 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 86e0cb7f5eaff788b0f2d1b4ad6112e5de0c0a55 Mon Sep 17 00:00:00 2001 From: Bala Guduru Date: Mon, 15 Jul 2019 08:28:10 -0700 Subject: [PATCH 5/5] Removing white space to fix the lint check error. --- terraform/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform/variables.tf b/terraform/variables.tf index e906d98..d3dca58 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -1,5 +1,5 @@ /* -Copyright 2019 Google LLC +Copyright 2019 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.