Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
6fb537e
feat: migrate postdeployment to data http
glasnt Jul 19, 2023
10a979e
lint
glasnt Jul 19, 2023
2e55250
lint: add ignore to side-effect 'unused' data sources
glasnt Jul 19, 2023
03741e2
WIP NO MERGE: progress on cloudbuild-based deployments
glasnt Jul 20, 2023
751f8c3
WIP save
glasnt Jul 21, 2023
2f0d20d
Merge branch 'main' into feat/postjsstrigger
glasnt Jul 21, 2023
b839b62
remove unused code
glasnt Jul 21, 2023
ba1d223
cleanup todos
glasnt Jul 21, 2023
126c684
Add roles/pubsub.editor permissions
glasnt Jul 21, 2023
9a95c4a
terraform format
glasnt Jul 21, 2023
821bfb1
lint: trim whitespace
glasnt Jul 21, 2023
d2a720f
lint: ignore unused variable (for now)
glasnt Jul 21, 2023
604bda4
Add roles/cloudbuild.builds.editor permissions
glasnt Jul 21, 2023
d3dbb07
bump avocano version
glasnt Jul 21, 2023
323ef0e
bump avocano version
glasnt Jul 21, 2023
dc04522
use updated placeholder placeholder
glasnt Jul 21, 2023
cfd9c39
still use a client job, rather than a step.
glasnt Jul 21, 2023
c5830b3
move from distroless to ubuntu
glasnt Jul 21, 2023
4b0a2da
fix: ensure correct workdir used when using image in cloudbuild
glasnt Jul 21, 2023
fdcd270
make all init jobs optional; (debug) use init sa for permissions
glasnt Jul 21, 2023
f4fffbe
update optional resources
glasnt Jul 21, 2023
729b0a2
(maybe?) ensure broken placeholder looks identical to working init tr…
glasnt Jul 21, 2023
ae37622
lint
glasnt Jul 21, 2023
7ed09e4
the trigger execution needs to wait for the permissions to land
glasnt Jul 21, 2023
c505dc2
cleanup depends, don't give client perms it doesn't need anymore
glasnt Jul 21, 2023
0475b3a
add an wait to let iam consist eventually, attempt to fix race condit…
glasnt Jul 21, 2023
469df4a
debug: wait longer, and for more debugs
glasnt Jul 21, 2023
33ef1df
that's not a resource
glasnt Jul 21, 2023
782f6b6
neither is that
glasnt Jul 21, 2023
fc1c236
debug: improve iam reliability by artificially staggering triggers
glasnt Jul 21, 2023
c2d094f
remove duplicate cloud run job declaration
glasnt Jul 21, 2023
6d6a312
correct removal of tf-based client job
glasnt Jul 21, 2023
75af1dc
correct syntax
glasnt Jul 21, 2023
057953b
cleanup IAM, attempt to reduce concurrent policy changes
glasnt Jul 21, 2023
e74695c
lint, remove unused helpers
glasnt Jul 21, 2023
a75787e
fix syntax
glasnt Jul 21, 2023
1bca6da
cleanup client job
glasnt Jul 21, 2023
f153dbc
init needs firebase admin
glasnt Jul 21, 2023
fecf354
create the client job as early as possible, hopefully helping tests
glasnt Jul 21, 2023
6469113
temporary: Only run suffix tests
grayside Jul 21, 2023
9c236cd
fix: placeholder deploy depend on permissions instead of database
grayside Jul 21, 2023
126896e
introduce 2m delay before using init IAM permissions
grayside Jul 21, 2023
5400475
Increase init permissions propagation delay to 3 minutes
grayside Jul 21, 2023
0a600e4
increase placeholder delay to 4m
grayside Jul 21, 2023
4ad1a19
experiment: postdeploy-cloudbuild gcs-only trial
grayside Jul 21, 2023
746f36a
Reduce permissions delay to 2m, no Cloud Build logging for placeholder
grayside Jul 21, 2023
30ed7fa
Update infra/postdeployment.tf
grayside Jul 21, 2023
8c13170
add 2 minute verify delay in go tests
grayside Jul 21, 2023
9da04ad
switch cloud build to use default cloud build service account
grayside Jul 21, 2023
cbd7aec
add another minute delay to give Cloud Run time to start serving
grayside Jul 21, 2023
88a7617
Add delay before assigning permissions to Cloud Build SA
grayside Jul 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,15 @@ The following dependencies must be available:
A service account with the following roles must be used to provision
the resources of this module:

- roles/cloudbuild.builds.editor
- roles/cloudsql.admin
- roles/compute.admin
- roles/compute.networkAdmin
- roles/firebase.managementServiceAgent
- roles/firebasehosting.admin
- roles/iam.serviceAccountAdmin
- roles/iam.serviceAccountUser
- roles/pubsub.editor
- roles/resourcemanager.projectIamAdmin
- roles/run.admin
- roles/secretmanager.admin
Expand Down
7 changes: 4 additions & 3 deletions app/placeholder/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
# Execute with "docker run --build-arg PROJECT_ID=$PROJECT_ID ..."
ARG PROJECT_ID=YOURPROJECTID
FROM gcr.io/$PROJECT_ID/firebase
WORKDIR /app

RUN apk add gettext
RUN apk add gettext curl
RUN npm install -g json
COPY . ./
COPY . /app/

ENTRYPOINT ./placeholder-deploy.sh
ENTRYPOINT ["/app/placeholder-deploy.sh"]
26 changes: 24 additions & 2 deletions app/placeholder/placeholder-deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,32 @@
# any errors? exit immediately.
set -e

# Ensure we got to the right directory. Cloud Build may start us in /workspace
cd /app

# escape if firebase_url not defined (mandatory, required later)
if [[ -z $FIREBASE_URL ]]; then
echo "FIREBASE_URL not defined. Cannot deploy. Exiting."
exit 1
fi

# Only run the placeholder script if the site has been deployed before.
# Check if the firebase url has "Site Not Found" (the pre-deployment state)
if curl "$FIREBASE_URL" | grep -q "Site Not Found"; then
echo "Firebase site $FIREBASE_URL hasn't been deployed before, so it needs a placeholder."
else
echo "Firebase site $FIREBASE_URL has been deployed before. Not going to deploy placeholder. Exiting."
exit 0
fi

# if deploying with a suffix (from infra/jobs.tf), adjust the config to suit the custom site
# https://firebase.google.com/docs/hosting/multisites#set_up_deploy_targets
if [[ -n $SUFFIX ]]; then
json -I -f firebase.json -e "this.hosting.target='$SUFFIX'"
UPDATED=true

# Use template file to generate configuration
envsubst < firebaserc.tmpl > .firebaserc
envsubst <firebaserc.tmpl >.firebaserc
echo "Customised .firebaserc created to support site."
cat .firebaserc
fi
Expand All @@ -35,6 +53,10 @@ if [[ -n $UPDATED ]]; then
cat firebase.json
fi

# Finally, deploy the application
echo "Deploying placeholder to Firebase..."

firebase deploy --project "$PROJECT_ID" --only hosting

# Setup for greater chances of success by explicitly purging cache
echo "Purging firebase cache"
curl -X PURGE "${FIREBASE_URL}/"
17 changes: 0 additions & 17 deletions build/int.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,6 @@ steps:
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage init --verbose']

# Simple example - one deployment per project
- id: simple-example-apply
waitFor: ['init-all']
dir: infra
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestSimpleExample --stage apply --verbose']
- id: simple-example-verify
waitFor: ['simple-example-apply']
dir: infra
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestSimpleExample --stage verify --verbose']
- id: simple-example-teardown
waitFor: ['simple-example-verify']
dir: infra
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestSimpleExample --stage teardown --verbose']

# Suffix example - supports multiple deployments per project
- id: suffix-example-apply
waitFor: ['init-all']
Expand Down
4 changes: 3 additions & 1 deletion infra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Functional examples are included in the
| database\_name | Cloud SQL database name | `string` | `"django"` | no |
| database\_username | Cloud SQL database name | `string` | `"server"` | no |
| enable\_apis | Whether or not to enable underlying apis in this solution. | `bool` | `true` | no |
| image\_version | Version of the Container Registry image to use | `string` | `"v1.8.2"` | no |
| image\_version | Version of the Container Registry image to use | `string` | `"v1.9.0"` | no |
| init | Initialize database? | `bool` | `true` | no |
| instance\_name | Cloud SQL Instance name | `string` | `"psql"` | no |
| labels | A set of key/value label pairs to assign to the resources deployed by this blueprint. | `map(string)` | `{}` | no |
Expand Down Expand Up @@ -89,13 +89,15 @@ The following dependencies must be available:
A service account with the following roles must be used to provision
the resources of this module:

- roles/cloudbuild.builds.editor
- roles/cloudsql.admin
- roles/compute.admin
- roles/compute.networkAdmin
- roles/firebase.managementServiceAgent
- roles/firebasehosting.admin
- roles/iam.serviceAccountAdmin
- roles/iam.serviceAccountUser
- roles/pubsub.editor
- roles/resourcemanager.projectIamAdmin
- roles/run.admin
- roles/secretmanager.admin
Expand Down
1 change: 1 addition & 0 deletions infra/apis.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module "project_services" {
"compute.googleapis.com",
"firebase.googleapis.com",
"firebasehosting.googleapis.com",
"pubsub.googleapis.com",
"iam.googleapis.com",
"run.googleapis.com",
"secretmanager.googleapis.com",
Expand Down
2 changes: 1 addition & 1 deletion infra/containers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
locals {
server_image = "gcr.io/${var.server_image_host}/server:${var.image_version}"
client_image = "gcr.io/${var.client_image_host}/client:${var.image_version}"
placeholder_image = "gcr.io/hsa-public/avocano-placeholder:latest"
placeholder_image = "gcr.io/hsa-public/avocano-placeholder:postjsstrigger" # TODO(glasnt): revert to tag "latest"
}
136 changes: 81 additions & 55 deletions infra/iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,32 @@
* limitations under the License.
*/

# Service Accounts

locals {
# Helpers for the clunky formatting of these values
automation_SA = "serviceAccount:${google_service_account.automation.email}"
server_SA = "serviceAccount:${google_service_account.server.email}"
client_SA = "serviceAccount:${google_service_account.client.email}"
# Lists of required roles
server_iam_members = [
"roles/cloudsql.client",
"roles/run.viewer",
"roles/cloudtrace.agent"
]
client_iam_members = [
"roles/run.viewer",
"roles/firebasehosting.admin",
]
automation_iam_members = [
"roles/cloudsql.client"
]
init_iam_members = [
# Leaning on default service account for this.
#"roles/logging.logWriter",
#"roles/cloudbuild.builds.builder",
"roles/iam.serviceAccountUser",
"roles/run.developer",
"roles/firebasehosting.admin"
]
}

# Accounts

resource "google_service_account" "server" {
account_id = var.random_suffix ? "api-backend-${random_id.suffix.hex}" : "api-backend"
display_name = "API Backend service account"
Expand All @@ -41,66 +58,75 @@ resource "google_service_account" "automation" {
depends_on = [module.project_services]
}

resource "google_service_account" "compute" {
account_id = var.random_suffix ? "compute-startup-${random_id.suffix.hex}" : "compute-startup"
display_name = "Head Start App Compute Instance SA"
depends_on = [module.project_services]
count = var.init ? 1 : 0
}
# resource "google_service_account" "init" {
# account_id = var.random_suffix ? "init-startup-${random_id.suffix.hex}" : "init-startup"
# display_name = "Jump Start App Init SA"
# depends_on = [module.project_services]
# count = var.init ? 1 : 0
# }

# Permissions

# The Cloud Run server can access the database
resource "google_project_iam_member" "server_permissions" {
project = var.project_id
role = "roles/cloudsql.client"
member = local.server_SA
depends_on = [google_service_account.server]
}
count = length(local.server_iam_members)

# Cloud Build can access the database
resource "google_project_iam_member" "build_permissions" {
project = var.project_id
role = "roles/cloudsql.client"
member = local.automation_SA
depends_on = [google_service_account.automation]
project = var.project_id
role = local.server_iam_members[count.index]
member = "serviceAccount:${google_service_account.server.email}"
}

# Server needs introspection permissions
resource "google_project_iam_member" "server_introspection" {
project = var.project_id
role = "roles/run.viewer"
member = local.server_SA
depends_on = [google_service_account.server]
resource "google_project_iam_member" "client_permissions" {
count = length(local.client_iam_members)

project = var.project_id
role = local.client_iam_members[count.index]
member = "serviceAccount:${google_service_account.client.email}"
}

# Client needs introspection permissions
resource "google_project_iam_member" "client_introspection" {
project = var.project_id
role = "roles/run.viewer"
member = local.client_SA
depends_on = [google_service_account.client]
resource "google_project_iam_member" "automation_permissions" {
count = length(local.automation_iam_members)

project = var.project_id
role = local.automation_iam_members[count.index]
member = "serviceAccount:${google_service_account.automation.email}"
}

# Client may need permission to deploy the front end
resource "google_project_iam_member" "client_permissions" {
project = var.project_id
role = "roles/firebasehosting.admin"
member = local.client_SA
depends_on = [google_service_account.client]
# resource "google_project_iam_member" "init_permissions" {
# count = length(local.init_iam_members)

# project = var.project_id
# role = local.init_iam_members[count.index]
# member = "serviceAccount:${google_service_account.init[0].email}"
# }

resource "google_project_iam_member" "init_permissions" {
count = length(local.init_iam_members)
role = local.init_iam_members[count.index]
member = "serviceAccount:${data.google_project.default.number}@cloudbuild.gserviceaccount.com"
project = var.project_id
depends_on = [
time_sleep.services_enabled_delay
]
}

# GCE instance needs access to start Jobs
resource "google_project_iam_member" "computestartup_permissions" {
project = var.project_id
role = "roles/run.developer"
member = "serviceAccount:${google_service_account.compute[0].email}"
depends_on = [google_service_account.compute]
count = var.init ? 1 : 0
# Ensure google_service_account.init is not used before permissions are available.
# Introduced to allow for IAM policy propagation delay. Time selected to allow:
# propagation delay + ~2 minute firebase hosting deploy <= 5 minutes.
# Shortest delay preferred.
# Warning: Trying to meet IAM propagation delay on roles/logging.logWriter.
# Exceeded safe limit to avoid race conditions between placeholder and init process.
resource "time_sleep" "init_permissions_propagation" {
depends_on = [
google_project_iam_member.init_permissions
]

create_duration = "120s"
}

# Server needs to write to Cloud Trace
resource "google_project_iam_member" "server_traceagent" {
project = var.project_id
role = "roles/cloudtrace.agent"
member = local.server_SA
depends_on = [google_service_account.server]
resource "time_sleep" "services_enabled_delay" {
depends_on = [
module.project_services
]

create_duration = "20s"
}
Loading