Skip to content

Commit

Permalink
Project cleanup (#469)
Browse files Browse the repository at this point in the history
* Removed projects module and cleaned up unused variabled

* Added option to have a Terraform managed project
  • Loading branch information
arueth committed Mar 28, 2024
1 parent f689f95 commit 820e4ba
Show file tree
Hide file tree
Showing 11 changed files with 389 additions and 220 deletions.
145 changes: 116 additions & 29 deletions ml-platform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,46 @@ This is the quick-start deployment guide. It can be used to set up an environmen

### Requirements

- New Google Cloud Project, preferably with no APIs enabled
In this guide you can choose to bring your project (BYOP) or have Terraform create a new project for you. The requirements are difference based on the option that you choose.

#### Bring your own project (BYOP)

- Project ID of a new Google Cloud Project, preferably with no APIs enabled
- `roles/owner` IAM permissions on the project
- GitHub Personal Access Token, steps to create the token are provided below

### Configuration
#### Terraform managed project

- Billing account ID
- Organization or folder ID
- `roles/billing.user` IAM permissions on the billing account specified
- `roles/resourcemanager.projectCreator` IAM permissions on the organization or folder specified
- GitHub Personal Access Token, steps to create the token are provided below

### Pull the source code

- Clone the repository and change directory to the guide directory

```
git clone https://github.com/GoogleCloudPlatform/ai-on-gke
cd ai-on-gke/ml-platform
```

- Set environment variables

```
export MLP_BASE_DIR=$(pwd) && \
echo "export MLP_BASE_DIR=${MLP_BASE_DIR}" >> ${HOME}/.bashrc
```

### GitHub Configuration

- Create a [Personal Access Token][personal-access-token] in [GitHub][github]:

Note: It is recommended to use a [machine user account][machine-user-account] for this but you can use a personal user account just to try this reference architecture.

**Fine-grained personal access token**

- Go to https://github.com/settings/tokens and login using your credentials
- Click "Generate new token" >> "Generate new token (Beta)".
- Enter a Token name.
Expand Down Expand Up @@ -106,17 +134,6 @@ This is the quick-start deployment guide. It can be used to set up an environmen
nano ${HOME}/secrets/mlp-github-token
```

- Set the project environment variables in Cloud Shell

Replace the following values

- `<PROJECT_ID>` is the ID of your existing Google Cloud project

```
export MLP_PROJECT_ID="<PROJECT_ID>"
export MLP_STATE_BUCKET="${MLP_PROJECT_ID}-tf-state"
```

- Set the GitHub environment variables in Cloud Shell

Replace the following values:
Expand All @@ -131,6 +148,31 @@ This is the quick-start deployment guide. It can be used to set up an environmen
export MLP_GITHUB_EMAIL="<GITHUB_EMAIL>"
```

- Set the configuration variables

```
sed -i "s/YOUR_GITHUB_EMAIL/${MLP_GITHUB_EMAIL}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars
sed -i "s/YOUR_GITHUB_ORG/${MLP_GITHUB_ORG}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars
sed -i "s/YOUR_GITHUB_USER/${MLP_GITHUB_USER}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars
```

### Project Configuration

You only need to complete the section for the option that you have selected.

#### Bring your own project (BYOP)

- Set the project environment variables in Cloud Shell

Replace the following values

- `<PROJECT_ID>` is the ID of your existing Google Cloud project

```
export MLP_PROJECT_ID="<PROJECT_ID>"
export MLP_STATE_BUCKET="${MLP_PROJECT_ID}-tf-state"
```

- Set the default `gcloud` project

```
Expand All @@ -149,33 +191,56 @@ This is the quick-start deployment guide. It can be used to set up an environmen
gcloud storage buckets create gs://${MLP_STATE_BUCKET} --project ${MLP_PROJECT_ID}
```

### Run Terraform

- Clone the repository and change directory to the guide directory
- Set the configuration variables

```
git clone https://github.com/GoogleCloudPlatform/ai-on-gke
cd ai-on-gke/ml-platform
sed -i "s/YOUR_STATE_BUCKET/${MLP_STATE_BUCKET}/g" ${MLP_BASE_DIR}/terraform/backend.tf
sed -i "s/YOUR_PROJECT_ID/${MLP_PROJECT_ID}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars
```

- Set environment variables
#### Terraform managed project

- Set the configuration variables

```
export MLP_BASE_DIR=$(pwd) && \
echo "export MLP_BASE_DIR=${MLP_BASE_DIR}" >> ${HOME}/.bashrc
nano ${MLP_BASE_DIR}/terraform/initialize/initialize.auto.tfvars
```

- Set the configuration variables
```
project = {
billing_account_id = "XXXXXX-XXXXXX-XXXXXX"
folder_id = "############"
name = "mlp"
org_id = "############"
}
```

> `project.billing_account_id` the billing account ID
>
> Enter either `project.folder_id` **OR** `project.org_id`
> `project.folder_id` the folder ID
> `project.org_id` the organization ID
- Authorize `gcloud`

```
sed -i "s/YOUR_STATE_BUCKET/${MLP_STATE_BUCKET}/g" ${MLP_BASE_DIR}/terraform/backend.tf
gcloud auth login --activate --no-launch-browser --quiet --update-adc
```

sed -i "s/YOUR_GITHUB_EMAIL/${MLP_GITHUB_EMAIL}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars
sed -i "s/YOUR_GITHUB_ORG/${MLP_GITHUB_ORG}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars
sed -i "s/YOUR_GITHUB_USER/${MLP_GITHUB_USER}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars
sed -i "s/YOUR_PROJECT_ID/${MLP_PROJECT_ID}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars
- Create a new project

```
cd ${MLP_BASE_DIR}/terraform/initialize
terraform init && \
terraform plan -input=false -out=tfplan && \
terraform apply -input=false tfplan && \
rm tfplan && \
terraform init -force-copy -migrate-state && \
rm -rf state
```

### Run Terraform

- Create the resources

```
Expand Down Expand Up @@ -277,15 +342,37 @@ Open Cloud Shell to execute the following commands:
```
cd ${MLP_BASE_DIR}/terraform && \
terraform init && \
terraform destroy -auto-approve -var github_token="$(tr --delete '\n' < ${HOME}/secrets/mlp-github-token)"
terraform destroy -auto-approve -var github_token="$(tr --delete '\n' < ${HOME}/secrets/mlp-github-token)" && \
rm -rf .terraform .terraform.lock.hcl
```

#### Project

You only need to complete the section for the option that you have selected.

##### Bring your own project (BYOP)

- Delete the project

```
gcloud projects delete ${MLP_PROJECT_ID}
```

#### Terraform managed project

- Destroy the project

```
cd ${MLP_BASE_DIR}/terraform/initialize && \
TERRAFORM_BUCKET_NAME=$(grep bucket backend.tf | awk -F"=" '{print $2}' | xargs) && \
cp backend.tf.local backend.tf && \
terraform init -force-copy -lock=false -migrate-state && \
gsutil -m rm -rf gs://${TERRAFORM_BUCKET_NAME}/* && \
terraform init && \
terraform destroy -auto-approve && \
rm -rf .terraform .terraform.lock.hcl
```

[gitops]: https://about.gitlab.com/topics/gitops/
[repo-sync]: https://cloud.google.com/anthos-config-management/docs/reference/rootsync-reposync-fields
[root-sync]: https://cloud.google.com/anthos-config-management/docs/reference/rootsync-reposync-fields
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

output "project_id" {
value = local.project_id
terraform {
backend "local" {
path = "state/default.tfstate"
}
}
20 changes: 20 additions & 0 deletions ml-platform/terraform/initialize/backend.tf.bucket
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2024 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

terraform {
backend "gcs" {
prefix = "terraform/initialize"
bucket = ""
}
}
7 changes: 7 additions & 0 deletions ml-platform/terraform/initialize/initialize.auto.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
environment_name = "dev"
project = {
billing_account_id = ""
folder_id = ""
name = "mlp"
org_id = ""
}
131 changes: 131 additions & 0 deletions ml-platform/terraform/initialize/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Copyright 2024 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

locals {
backend_file = "../backend.tf"
project_id_prefix = "${var.project.name}-${var.environment_name}"
project_id_suffix_length = 29 - length(local.project_id_prefix)
tfvars_file = "../mlp.auto.tfvars"
}

resource "random_string" "project_id_suffix" {
length = local.project_id_suffix_length
lower = true
numeric = true
special = false
upper = false
}

resource "google_project" "environment" {
billing_account = var.project.billing_account_id
folder_id = var.project.folder_id == "" ? null : var.project.folder_id
name = local.project_id_prefix
org_id = var.project.org_id == "" ? null : var.project.org_id
project_id = "${local.project_id_prefix}-${random_string.project_id_suffix.result}"
}


resource "google_storage_bucket" "mlp" {
force_destroy = false
location = var.storage_bucket_location
name = "${google_project.environment.project_id}-mlp"
project = google_project.environment.project_id
uniform_bucket_level_access = true

versioning {
enabled = true
}
}

resource "null_resource" "write_environment_name" {
triggers = {
md5 = var.environment_name
tfvars_file = local.tfvars_file
}

provisioner "local-exec" {
command = <<EOT
echo "Writing 'environment_name' changes to '${local.tfvars_file}'" && \
sed -i 's/^\([[:blank:]]*environment_name[[:blank:]]*=\).*$/\1 ${jsonencode(var.environment_name)}/' ${local.tfvars_file}
EOT
interpreter = ["bash", "-c"]
working_dir = path.module
}

provisioner "local-exec" {
when = destroy
command = <<EOT
echo "Reverting 'environment_name' changes in '${self.triggers.tfvars_file}'" && \
sed -i 's/^\([[:blank:]]*environment_name[[:blank:]]*=\).*$/\1 "dev"/' ${self.triggers.tfvars_file}
EOT
interpreter = ["bash", "-c"]
working_dir = path.module
}
}

resource "null_resource" "write_project_id" {
triggers = {
md5 = google_project.environment.project_id
tfvars_file = local.tfvars_file
}

provisioner "local-exec" {
command = <<EOT
echo "Writing 'project.id' changes to '${local.tfvars_file}'" && \
sed -i 's/^\([[:blank:]]*environment_project_id[[:blank:]]*=\).*$/\1 ${jsonencode(google_project.environment.project_id)}/' ${local.tfvars_file}
EOT
interpreter = ["bash", "-c"]
working_dir = path.module
}

provisioner "local-exec" {
when = destroy
command = <<EOT
echo "Reverting 'project.id' changes in '${self.triggers.tfvars_file}'" && \
sed -i 's/^\([[:blank:]]*environment_project_id[[:blank:]]*=\).*$/\1 "YOUR_PROJECT_ID"/' ${self.triggers.tfvars_file}
EOT
interpreter = ["bash", "-c"]
working_dir = path.module
}
}

resource "null_resource" "write_storage_bucket" {
triggers = {
backend_file = local.backend_file
md5 = google_storage_bucket.mlp.name
}

provisioner "local-exec" {
command = <<EOT
echo "Writing 'bucket' changes to '${local.backend_file}'" && \
sed -i 's/^\([[:blank:]]*bucket[[:blank:]]*=\).*$/\1 ${jsonencode(google_storage_bucket.mlp.name)}/' ${local.backend_file} && \
sed -i 's/^\([[:blank:]]*bucket[[:blank:]]*=\).*$/\1 ${jsonencode(google_storage_bucket.mlp.name)}/' backend.tf.bucket && \
mv backend.tf backend.tf.local && \
cp backend.tf.bucket backend.tf
EOT
interpreter = ["bash", "-c"]
working_dir = path.module
}

provisioner "local-exec" {
when = destroy
command = <<EOT
echo "Reverting 'bucket' changes in '${self.triggers.backend_file}'" && \
sed -i 's/^\([[:blank:]]*bucket[[:blank:]]*=\).*$/\1 "YOUR_STATE_BUCKET"/' ${self.triggers.backend_file} && \
sed -i 's/^\([[:blank:]]*bucket[[:blank:]]*=\).*$/\1 ""/' backend.tf.bucket
EOT
interpreter = ["bash", "-c"]
working_dir = path.module
}
}
Loading

0 comments on commit 820e4ba

Please sign in to comment.