forked from GoogleCloudPlatform/cloud-build-notifiers
-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup.sh
executable file
·200 lines (163 loc) · 5.97 KB
/
setup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/bin/sh
# Copyright 2020 Google LLC
# Author: lru@google.com (Leo Rudberg)
set -u
HELP="
Cloud Build Notifiers setup script.
This script runs almost all of the setup required for configuring
and deploying a notifier on GCP. It is based on the guide here:
https://cloud.google.com/cloud-build/docs/configure-notifications
Setting up any 'secret_name' must be done outside
this script. This script is assumed to be run in the root of your
cloud-build-notifiers clone/fork. Currently, this script only deploys
the 'latest' version of the notifier to Cloud Run. To check that your notifier
configuration YAML can work with that version, run the notifier locally with
the '--setup_check' flag that is mentioned in the repo root README.md.
The currently supported notifier types (which correspond to the directories in
the repo) are:
* bigquery (under development)
* http
* slack
* smtp
Usage [in the cloud-build-notifiers repo root]:
./setup.sh <notifier-type> <local-config-path> [secret-name]
Concrete example:
./setup.sh \
smtp \
~/notifier-configs/my-smtp-config.yaml \
my-smtp-password
For help/usage:
./setup.sh --help
"
main() {
# Simple argument checks.
if [ "$*" = "--help" ]; then
echo "${HELP}"
exit 0
elif [ $# -lt 2 ] || [ $# -gt 3 ]; then
fail "${HELP}"
fi
NOTIFIER_TYPE="$1"
SOURCE_CONFIG_PATH="$2"
SECRET_NAME="${3:-}" # Optional secret_name name.
# Check that the user is using a supported notifier type in the correct
# directory.
case "${NOTIFIER_TYPE}" in
http | smtp | slack | bigquery) ;;
*) fail "${HELP}" ;;
esac
if [ ! -d "${NOTIFIER_TYPE}" ]; then
fail "expected to run from the root of the cloud-build-notifiers repo"
fi
if [ ! -r "${SOURCE_CONFIG_PATH}" ]; then
fail "expected file at local source config path ${SOURCE_CONFIG_PATH} to be readable"
fi
# Project ID, assumed to NOT be org-scoped (only alphanumeric and dashes).
PROJECT_ID=$(gcloud config get-value project) ||
fail "could not get default project"
if [ "${PROJECT_ID}" = "(unset)" ]; then
fail "default project not set; run \"gcloud config set project <project_id>\"" \
"or set the CLOUDSDK_CORE_PROJECT environment variable"
fi
if [ -z "${PROJECT_ID##*:*}" ]; then
fail "org-scoped project IDs are not allowed by this script"
fi
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" \
--format="value(projectNumber)") ||
fail "could not get project number"
REQUIRED_SERVICES=('Cloud Build API' 'Cloud Run Admin API' 'Cloud Pub/Sub API')
SOURCE_CONFIG_BASENAME=$(basename "${SOURCE_CONFIG_PATH}")
DESTINATION_BUCKET_NAME="${PROJECT_ID}-notifiers-config"
DESTINATION_BUCKET_URI="gs://${DESTINATION_BUCKET_NAME}"
DESTINATION_CONFIG_PATH="${DESTINATION_BUCKET_URI}/${SOURCE_CONFIG_BASENAME}"
IMAGE_PATH="us-east1-docker.pkg.dev/gcb-release/cloud-build-notifiers/${NOTIFIER_TYPE}:latest"
SERVICE_NAME="${NOTIFIER_TYPE}-notifier"
SUBSCRIPTION_NAME="${NOTIFIER_TYPE}-subscription"
INVOKER_SA="cloud-run-pubsub-invoker@${PROJECT_ID}.iam.gserviceaccount.com"
PUBSUB_SA="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
# Turn on command echoing after all of the variables have been set so we
# don't log spam unnecessarily.
set -x
check_apis_enabled
if [ -n "${SECRET_NAME}" ]; then
add_secret_name_accessor_permission
fi
upload_config
deploy_notifier
SERVICE_URL=$(gcloud run services describe "${SERVICE_NAME}" \
--format="value(status.url)")
add_sa_token_creator_permission
create_invoker_sa
add_invoker_permission
create_pubsub_topic
check_pubsub_topic
create_pubsub_subscription
check_pubsub_subscription
echo "** NOTIFIER SETUP COMPLETE **" 1>&2
}
fail() {
echo "$*" 1>&2
exit 1
}
check_apis_enabled() {
if [ -n "${SECRET_NAME}" ]; then
REQUIRED_SERVICES+=('Secret Manager API')
fi
SERVICES=$(gcloud services list --enabled --format='value(config.title)')
for API in "${REQUIRED_SERVICES[@]}"; do
[ -z ${SERVICES[@]/*${API}*/} ] || fail "please enable the ${API}"
done
}
add_secret_name_accessor_permission() {
gcloud secrets add-iam-policy-binding "${SECRET_NAME}" \
--member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor" ||
fail "failed to set up secret access"
}
upload_config() {
# We allow this `mb` command to error since we rely on the `cp` command hard-
# erroring if there's an actual problem (since `mb` fails if the bucket
# already exists).
gsutil mb "${DESTINATION_BUCKET_URI}"
gsutil cp "${SOURCE_CONFIG_PATH}" "${DESTINATION_CONFIG_PATH}" ||
fail "failed to copy config to GCS"
}
deploy_notifier() {
gcloud run deploy "${SERVICE_NAME}" \
--image="${IMAGE_PATH}" \
--no-allow-unauthenticated \
--update-env-vars="CONFIG_PATH=${DESTINATION_CONFIG_PATH},PROJECT_ID=${PROJECT_ID}" ||
fail "failed to deploy notifier service -- check service logs for configuration error"
}
add_sa_token_creator_permission() {
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${PUBSUB_SA}" \
--role="roles/iam.serviceAccountTokenCreator"
}
create_invoker_sa() {
gcloud iam service-accounts create cloud-run-pubsub-invoker \
--display-name "Cloud Run Pub/Sub Invoker"
}
add_invoker_permission() {
gcloud run services add-iam-policy-binding "${SERVICE_NAME}" \
--member="serviceAccount:${INVOKER_SA}" \
--role=roles/run.invoker
}
create_pubsub_topic() {
gcloud pubsub topics create cloud-builds
}
check_pubsub_topic() {
gcloud pubsub topics describe cloud-builds ||
fail "expected the notifier Pub/Sub topic cloud-builds to exist"
}
create_pubsub_subscription() {
gcloud pubsub subscriptions create "${SUBSCRIPTION_NAME}" \
--topic=cloud-builds \
--push-endpoint="${SERVICE_URL}" \
--push-auth-service-account="${INVOKER_SA}"
}
check_pubsub_subscription() {
gcloud pubsub subscriptions describe "${SUBSCRIPTION_NAME}" ||
fail "expected the notifier Pub/Sub subscription to exist"
}
main "$@"