@google-cloud/nodejs-common 1.1.0 → 1.2.1-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Copyright 2022 Google Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # Const the folder name of Apps Script.
18
+ DEFAULT_APPS_SCRIPT_FOLDER="apps_script"
19
+
20
+ #######################################
21
+ # Clasp login.
22
+ # Globals:
23
+ # None
24
+ # Arguments:
25
+ # None
26
+ #######################################
27
+ clasp_login() {
28
+ while :; do
29
+ local claspLogin=$(clasp login --status)
30
+ if [[ "${claspLogin}" != "You are not logged in." ]]; then
31
+ printf '%s' "${claspLogin} Would you like to continue with it? [Y/n]"
32
+ local logout
33
+ read -r logout
34
+ logout=${logout:-"Y"}
35
+ if [[ ${logout} == "Y" || ${logout} == "y" ]]; then
36
+ break
37
+ else
38
+ clasp logout
39
+ fi
40
+ fi
41
+ clasp login --no-localhost
42
+ done
43
+ }
44
+
45
+ #######################################
46
+ # Initialize a AppsScript project. Usually it involves following steps:
47
+ # 1. Create a AppsScript project within a new Google Sheet.
48
+ # 2. Prompt to update the Google Cloud Project number of the AppsScript project
49
+ # to enable external APIs for this AppsScript project.
50
+ # 3. Prompt to grant the access of Cloud Functions' default service account to
51
+ # this Google Sheet, so the Cloud Functions can query this Sheet later.
52
+ # 4. Initialize the Sheet based on requests.
53
+ # Globals:
54
+ # None
55
+ # Arguments:
56
+ # The Google Sheet name.
57
+ # The folder for Apps Script code, default value ${DEFAULT_APPS_SCRIPT_FOLDER}
58
+ #######################################
59
+ clasp_initialize() {
60
+ ((STEP += 1))
61
+ printf '%s\n' "Step ${STEP}: Starting to create Google Sheets..."
62
+ local sheetName="${1}"
63
+ local apps_script_src="${2-"${DEFAULT_APPS_SCRIPT_FOLDER}"}"
64
+ clasp_login
65
+ while :; do
66
+ local claspStatus=$(
67
+ clasp status -P "${apps_script_src}" >/dev/null 2>&1
68
+ echo $?
69
+ )
70
+ if [[ $claspStatus -gt 0 ]]; then
71
+ clasp create --type sheets --title "${sheetName}" --rootDir "${apps_script_src}"
72
+ local createResult=$?
73
+ if [[ $createResult -gt 0 ]]; then
74
+ printf '%s' "Press any key to continue after you enable the Google \
75
+ Apps Script API: https://script.google.com/home/usersettings..."
76
+ local any
77
+ read -n1 -s any
78
+ printf '\n\n'
79
+ continue
80
+ fi
81
+ break
82
+ else
83
+ printf '%s' "AppsScript project exists. Would you like to continue with \
84
+ it? [Y/n]"
85
+ local useCurrent
86
+ read -r useCurrent
87
+ useCurrent=${useCurrent:-"Y"}
88
+ if [[ ${useCurrent} = "Y" || ${useCurrent} = "y" ]]; then
89
+ break
90
+ else
91
+ printf '%s' "Would you like to delete current AppsScript and create a \
92
+ new one? [N/y]"
93
+ local deleteCurrent
94
+ read -r deleteCurrent
95
+ deleteCurrent=${deleteCurrent:-"N"}
96
+ if [[ ${deleteCurrent} = "Y" || ${deleteCurrent} = "y" ]]; then
97
+ rm "${apps_script_src}/.clasp.json"
98
+ continue
99
+ fi
100
+ fi
101
+ fi
102
+ done
103
+ }
104
+
105
+ #######################################
106
+ # Copy GCP project configuration file to AppsScript codes as a constant named
107
+ # `GCP_CONFIG`.
108
+ # Globals:
109
+ # None
110
+ # Arguments:
111
+ # The folder for Apps Script code, default value ${DEFAULT_APPS_SCRIPT_FOLDER}
112
+ #######################################
113
+ generate_config_js_for_apps_script() {
114
+ local apps_script_src="${1-"${DEFAULT_APPS_SCRIPT_FOLDER}"}"
115
+ local generated_file="${apps_script_src}/.generated_config.js"
116
+ if [[ -f "${CONFIG_FILE}" ]]; then
117
+ echo '// Copyright 2022 Google Inc.
118
+ //
119
+ // Licensed under the Apache License, Version 2.0 (the "License");
120
+ // you may not use this file except in compliance with the License.
121
+ // You may obtain a copy of the License at
122
+ //
123
+ // http://www.apache.org/licenses/LICENSE-2.0
124
+ //
125
+ // Unless required by applicable law or agreed to in writing, software
126
+ // distributed under the License is distributed on an "AS IS" BASIS,
127
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128
+ // See the License for the specific language governing permissions and
129
+ // limitations under the License.
130
+
131
+ /** @fileoverview Auto-generated configuration file for Apps Script. */
132
+ '>"${generated_file}"
133
+ echo -n "const GCP_CONFIG = " >>"${generated_file}"
134
+ cat "${CONFIG_FILE}" >>"${generated_file}"
135
+ else
136
+ printf '%s\n' "Couldn't find ${CONFIG_FILE}."
137
+ fi
138
+ }
139
+
140
+ #######################################
141
+ # Clasp pushes AppsScript codes.
142
+ # Globals:
143
+ # None
144
+ # Arguments:
145
+ # The folder for Apps Script code, default value ${DEFAULT_APPS_SCRIPT_FOLDER}
146
+ #######################################
147
+ clasp_push_codes() {
148
+ ((STEP += 1))
149
+ printf '%s\n' "Step ${STEP}: Starting to push codes to the Google Sheets..."
150
+ local apps_script_src="${1-"${DEFAULT_APPS_SCRIPT_FOLDER}"}"
151
+ clasp status -P "${apps_script_src}" >>/dev/null
152
+ local project_status=$?
153
+ if [[ ${project_status} -gt 0 ]]; then
154
+ return ${project_status}
155
+ else
156
+ generate_config_js_for_apps_script "${apps_script_src}"
157
+ clasp push --force -P "${apps_script_src}"
158
+ fi
159
+ }
160
+
161
+ #######################################
162
+ # Ask user to update the GCP number of this AppsScript.
163
+ # Globals:
164
+ # GCP_PROJECT
165
+ # Arguments:
166
+ # The folder for Apps Script code, default value ${DEFAULT_APPS_SCRIPT_FOLDER}
167
+ #######################################
168
+ clasp_update_project_number() {
169
+ ((STEP += 1))
170
+ local projectNumber=$(get_project_number)
171
+ local apps_script_src="${1-"${DEFAULT_APPS_SCRIPT_FOLDER}"}"
172
+ printf '%s\n' "Step ${STEP}: Update Google Cloud Platform (GCP) Project for \
173
+ Apps Script."
174
+ printf '%s' " "
175
+ clasp open -P "${apps_script_src}"
176
+ printf '%s\n' " On the open tab of Apps Script, use 'Project \
177
+ Settings' to set the Google Cloud Platform (GCP) Project as: ${projectNumber}"
178
+ printf '%s' "Press any key to continue after you update the GCP number..."
179
+ local any
180
+ read -n1 -s any
181
+ printf '\n'
182
+ }
183
+
184
+ #######################################
185
+ # Ask user to grant the access to CF's default service account.
186
+ # Note: the target GCP needs to have OAuth consent screen.
187
+ # Globals:
188
+ # SHEET_URL
189
+ # Arguments:
190
+ # The folder for Apps Script code, default value ${DEFAULT_APPS_SCRIPT_FOLDER}
191
+ #######################################
192
+ grant_access_to_service_account() {
193
+ ((STEP += 1))
194
+ local apps_script_src="${1-"${DEFAULT_APPS_SCRIPT_FOLDER}"}"
195
+ local defaultServiceAccount=$(get_cloud_functions_service_account \
196
+ "${PROJECT_NAMESPACE}_main")
197
+ local parentId=$(get_value_from_json_file "${apps_script_src}"/.clasp.json \
198
+ parentId|cut -d\" -f2)
199
+ printf '%s\n' "Step ${STEP}: Share the Google Sheet with ${SOLUTION_NAME}."
200
+
201
+ printf '%s\n' " Open Google Sheet: \
202
+ https://drive.google.com/open?id=${parentId}"
203
+ printf '%s\n' " Click 'Share' and grant the Viewer access to: \
204
+ ${defaultServiceAccount}"
205
+ printf '%s' "Press any key to continue after you grant the access..."
206
+ local any
207
+ read -n1 -s any
208
+ printf '\n'
209
+ }
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Copyright 2022 Google Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ #######################################
18
+ # Checks whether the BigQuery object (table or view) exists.
19
+ # Globals:
20
+ # GCP_PROJECT
21
+ # DATASET
22
+ # BIGQUERY_LOG_TABLE
23
+ # Arguments:
24
+ # None
25
+ #######################################
26
+ check_existence_in_bigquery() {
27
+ bq show "${1}" >/dev/null 2>&1
28
+ printf '%d' $?
29
+ }
30
+
31
+ #######################################
32
+ # Creates or updates the BigQuery view.
33
+ # Globals:
34
+ # GCP_PROJECT
35
+ # DATASET
36
+ # Arguments:
37
+ # The name of view.
38
+ # The query of view.
39
+ #######################################
40
+ create_or_update_view() {
41
+ local viewName viewQuery
42
+ viewName="${1}"
43
+ viewQuery=${2}
44
+ local action="mk"
45
+ if [[ $(check_existence_in_bigquery "${DATASET}.${viewName}") -eq 0 ]]; then
46
+ action="update"
47
+ fi
48
+ bq "${action}" \
49
+ --use_legacy_sql=false \
50
+ --view "${viewQuery}" \
51
+ --project_id ${GCP_PROJECT} \
52
+ "${DATASET}.${viewName}"
53
+ }
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Copyright 2022 Google Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # Google Ads API version
18
+ GOOGLE_ADS_API_VERSION=10
19
+
20
+ #######################################
21
+ # Verify whether the current OAuth token, CID and developer token can work.
22
+ # Globals:
23
+ # None
24
+ # Arguments:
25
+ # MCC CID
26
+ # Developer token
27
+ #######################################
28
+ validate_googleads_account() {
29
+ local cid developerToken accessToken request response
30
+ cid=${1}
31
+ developerToken=${2}
32
+ accessToken=$(get_oauth_access_token)
33
+ request=(
34
+ -H "Accept: application/json"
35
+ -H "Content-Type: application/json"
36
+ -H "developer-token: ${developerToken}"
37
+ -H "Authorization: Bearer ${accessToken}"
38
+ -X POST "https://googleads.googleapis.com/v${GOOGLE_ADS_API_VERSION}/customers/${cid}/googleAds:search"
39
+ -d '{"query": "SELECT customer.id FROM customer"}'
40
+ )
41
+ response=$(curl "${request[@]}" 2>/dev/null)
42
+ local errorCode errorMessage
43
+ errorCode=$(get_value_from_json_string "${response}" "error.code")
44
+ if [[ -n "${errorCode}" ]]; then
45
+ errorMessage=$(get_value_from_json_string "${response}" "error.message")
46
+ printf '%s\n' "Validate failed: ${errorMessage}" >&2
47
+ return 1
48
+ fi
49
+ return 0
50
+ }
51
+
52
+ #######################################
53
+ # Let user input MCC CID and developer token for cronjob(s).
54
+ # Globals:
55
+ # MCC_CIDS
56
+ # DEVELOPER_TOKEN
57
+ # Arguments:
58
+ # None
59
+ #######################################
60
+ set_google_ads_account() {
61
+ printf '%s\n' "Setting up Google Ads account information..."
62
+ local developToken mccCids
63
+ while :; do
64
+ # Developer token
65
+ while [[ -z ${developToken} ]]; do
66
+ printf '%s' " Enter the developer token[${DEVELOPER_TOKEN}]: "
67
+ read -r input
68
+ developToken="${input:-${DEVELOPER_TOKEN}}"
69
+ done
70
+ DEVELOPER_TOKEN="${developToken}"
71
+ mccCids=""
72
+ # MCC CIDs
73
+ while :; do
74
+ printf '%s' " Enter the MCC CID: "
75
+ read -r input
76
+ if [[ -z ${input} ]]; then
77
+ continue
78
+ fi
79
+ input="$(printf '%s' "${input}" | sed -r 's/-//g')"
80
+ printf '%s' " validating ${input}...... "
81
+ validate_googleads_account ${input} ${DEVELOPER_TOKEN}
82
+ if [[ $? -eq 1 ]]; then
83
+ printf '%s\n' "failed.
84
+ Press 'd' to re-enter developer token ["${developToken}"] or
85
+ 'C' to continue with this MCC CID or
86
+ any other key to enter another MCC CID..."
87
+ local any
88
+ read -n1 -s any
89
+ if [[ "${any}" == "d" ]]; then
90
+ developToken=""
91
+ continue 2
92
+ elif [[ "${any}" == "C" ]]; then
93
+ printf '%s\n' "WARNING! Continue with FAILED MCC ${input}."
94
+ else
95
+ continue
96
+ fi
97
+ else
98
+ printf '%s\n' "succeeded."
99
+ fi
100
+ mccCids+=",${input}"
101
+ printf '%s' " Do you want to add another MCC CID? [Y/n]: "
102
+ read -r input
103
+ if [[ ${input} == 'n' || ${input} == 'N' ]]; then
104
+ break
105
+ fi
106
+ done
107
+ # Left Shift one position to remove the first comma.
108
+ # After shifting, MCC_CIDS would like "11111,22222".
109
+ MCC_CIDS="${mccCids:1}"
110
+ printf '%s\n' "Using Google Ads MCC CIDs: ${MCC_CIDS}."
111
+ break
112
+ done
113
+ }
114
+
115
+ printf '%s\n' "Google Ads Bash Library is loaded."
@@ -384,6 +384,15 @@ solution installed [${GCP_PROJECT}]: "
384
384
  local input result
385
385
  read -r input
386
386
  input=${input:-"${GCP_PROJECT}"}
387
+ printf '%s' "Checking billing status for [${input}]..."
388
+ result=$(gcloud beta billing projects describe "${input}" \
389
+ --format="csv[no-heading](billingEnabled)")
390
+ if [[ "${result}" != "True" && "${result}" != "true" ]]; then
391
+ printf '%s\n' " there is no billing account."
392
+ return 1
393
+ else
394
+ printf '%s\n' "succeeded."
395
+ fi
387
396
  result=$(gcloud config set project "${input}" --user-output-enabled=false \
388
397
  2>&1)
389
398
  if [[ -z ${result} ]]; then
@@ -573,7 +582,7 @@ API(s):"
573
582
  printf '%s\n' "OK. OAuth is required by selected API(s)."
574
583
  return 0
575
584
  fi
576
- printf '%s\n' "Selected API(s) require authentication. Please select \
585
+ printf '%s\n' "Selected API(s) require authentication. Choose the \
577
586
  authentication method:"
578
587
  local auths=("Service Account (recommended)" "OAuth")
579
588
  select auth in "${auths[@]}"; do
@@ -604,28 +613,40 @@ check_permissions() {
604
613
  (( STEP += 1 ))
605
614
  printf '%s\n' "Step ${STEP}: Checking current user's access..."
606
615
  local role error
607
- for role in "${!GOOGLE_CLOUD_PERMISSIONS[@]}"; do
608
- printf '%s' " Checking permissions for ${role}... "
609
- local permissions
610
- permissions=(${GOOGLE_CLOUD_PERMISSIONS[${role}]})
611
- local missed
612
- missed=$(get_number_of_missed_permissions "${permissions[@]}")
613
- if [[ $missed -gt 0 ]]; then
614
- message="missed ${missed}, failed"
615
- error=1
616
+ while :; do
617
+ error=0
618
+ for role in "${!GOOGLE_CLOUD_PERMISSIONS[@]}"; do
619
+ printf '%s' " Checking permissions for ${role}... "
620
+ local permissions
621
+ permissions=(${GOOGLE_CLOUD_PERMISSIONS[${role}]})
622
+ local missed
623
+ missed=$(get_number_of_missed_permissions "${permissions[@]}")
624
+ if [[ $missed -gt 0 ]]; then
625
+ message="missed ${missed}, failed"
626
+ error=1
627
+ else
628
+ message='successfully'
629
+ fi
630
+ printf '%s\n' " ${message}."
631
+ done
632
+ if [[ ${error} -gt 0 ]]; then
633
+ printf '%s\n' "Permissions check failed."
634
+ printf '%s\n' "Would you like to login with another account? [Y/n]: "
635
+ local reLogin
636
+ read -r reLogin
637
+ reLogin=${reLogin:-"Y"}
638
+ if [[ ${reLogin} == "Y" || ${reLogin} == "y" ]]; then
639
+ gcloud auth login
640
+ continue
641
+ else
642
+ return 1
643
+ fi
616
644
  else
617
- message='successfully'
645
+ echo "OK. Permissions check passed for Google Cloud project \
646
+ [${GCP_PROJECT}]."
647
+ return 0
618
648
  fi
619
- printf '%s\n' " ${message}."
620
649
  done
621
- if [[ ${error} -gt 0 ]]; then
622
- printf '%s\n' "Permissions check failed."
623
- return 1
624
- else
625
- echo "OK. Permissions check passed for Google Cloud project \
626
- [${GCP_PROJECT}]."
627
- return 0
628
- fi
629
650
  }
630
651
 
631
652
  #######################################
@@ -1031,13 +1052,24 @@ refresh the list:"
1031
1052
  # Globals:
1032
1053
  # GCP_PROJECT
1033
1054
  # Arguments:
1034
- # Bucket name var, default value 'GCS_BUCKET'
1055
+ # Bucket name var with optional usage, e.g. 'GCS_BUCKET_REPORT:reports'.
1056
+ # The default value is 'GCS_BUCKET'.
1035
1057
  # Location var name, default value 'REGION'
1036
1058
  # If the second location var is unset, use this var as default value
1037
1059
  #######################################
1038
1060
  confirm_located_bucket() {
1039
- local gcsName defaultValue defaultBucketName locationName location
1040
- gcsName="${1:-"GCS_BUCKET"}"
1061
+ local gcsName usage defaultValue defaultBucketName locationName location
1062
+ if [[ -z "${1}" ]]; then
1063
+ gcsName="GCS_BUCKET"
1064
+ elif [[ "${1}" == *":"* ]]; then
1065
+ gcsName=$(echo "${1}" | cut -d\: -f1)
1066
+ usage=$(echo "${1}" | cut -d\: -f2)
1067
+ if [[ -n "${usage}" ]]; then
1068
+ usage=" for ${usage}"
1069
+ fi
1070
+ else
1071
+ gcsName="${1}"
1072
+ fi
1041
1073
  locationName="${2:-"REGION"}"
1042
1074
  defaultValue="${!gcsName}"
1043
1075
  defaultBucketName=$(get_default_bucket_name "${GCP_PROJECT}")
@@ -1052,7 +1084,8 @@ confirm_located_bucket() {
1052
1084
 
1053
1085
  (( STEP += 1 ))
1054
1086
  if [[ -z "${location}" ]]; then
1055
- printf '%s\n' "Step ${STEP}: Checking or creating a Cloud Storage Bucket..."
1087
+ printf '%s\n' "Step ${STEP}: Checking or creating a Cloud Storage \
1088
+ Bucket${usage}..."
1056
1089
  if [[ "${locationName}" == "REGION" ]]; then
1057
1090
  select_functions_location ${locationName}
1058
1091
  else
@@ -1060,8 +1093,8 @@ confirm_located_bucket() {
1060
1093
  fi
1061
1094
  location="${!locationName}"
1062
1095
  else
1063
- printf '%s\n' "Step ${STEP}: Checking or creating a Cloud Storage Bucket in \
1064
- location [${location}] ..."
1096
+ printf '%s\n' "Step ${STEP}: Checking or creating a Cloud Storage \
1097
+ Bucket${usage} in location [${location}] ..."
1065
1098
  fi
1066
1099
  declare -g "${locationName}=${location}"
1067
1100
  while :; do
@@ -1129,6 +1162,7 @@ Project. Continuing to enter another bucket..."
1129
1162
  fi
1130
1163
  done
1131
1164
  declare -g "${gcsName}=${bucket}"
1165
+ confirm_bucket_lifecycle "${bucket}"
1132
1166
  }
1133
1167
 
1134
1168
  #######################################
@@ -1149,6 +1183,58 @@ confirm_bucket_with_location() {
1149
1183
  confirm_located_bucket ${gcsName} ${locationName}
1150
1184
  }
1151
1185
 
1186
+ #######################################
1187
+ # Manage the lifecycle of a GCS bucket: setting or removing the GCS lifecycle
1188
+ # rule of 'age'.
1189
+ # See: https://cloud.google.com/storage/docs/lifecycle#age
1190
+ # Arguments:
1191
+ # Bucket name
1192
+ #######################################
1193
+ confirm_bucket_lifecycle() {
1194
+ local bucket bucketMetadata lifecycle
1195
+ bucket="${1}"
1196
+ bucketMetadata="$(get_bucket_metadata "${bucket}")"
1197
+ lifecycle="$(get_value_from_json_string "${bucketMetadata}" "lifecycle")"
1198
+ if [[ -n "${lifecycle}" ]]; then
1199
+ printf '%s\n' "There are lifecycle rules in this bucket: ${lifecycle}."
1200
+ printf '%s' "Would you like to overwrite it? [N/y]:"
1201
+ local confirmContinue
1202
+ read -r confirmContinue
1203
+ confirmContinue=${confirmContinue:-"N"}
1204
+ if [[ ${confirmContinue} == "N" || ${confirmContinue} == "n" ]]; then
1205
+ return 0
1206
+ fi
1207
+ else
1208
+ printf '%s\n' "There is no lifecycle rules in this bucket."
1209
+ printf '%s' "Would you like to create it? [Y/n]:"
1210
+ local confirmContinue
1211
+ read -r confirmContinue
1212
+ confirmContinue=${confirmContinue:-"Y"}
1213
+ if [[ ${confirmContinue} == "N" || ${confirmContinue} == "n" ]]; then
1214
+ return 0
1215
+ fi
1216
+ fi
1217
+ while :; do
1218
+ printf '%s' "Enter the number of days that a file will be kept before it \
1219
+ is automatically removed in the bucket[${bucket}]. (enter 0 to remove all \
1220
+ existing lifecycle rules): "
1221
+ local days
1222
+ read -r days
1223
+ days=${days}
1224
+ if [[ "${days}" =~ ^[0-9]+$ ]]; then
1225
+ local lifecycle
1226
+ if [[ "${days}" == "0" ]]; then
1227
+ lifecycle="{}"
1228
+ else
1229
+ lifecycle='{"rule":[{"action":{"type":"Delete"},"condition":{"age":'\
1230
+ "${days}}}]}"
1231
+ fi
1232
+ gsutil lifecycle set /dev/stdin gs://${bucket} <<< ${lifecycle}
1233
+ return $?
1234
+ fi
1235
+ done
1236
+ }
1237
+
1152
1238
  #######################################
1153
1239
  # Confirm the monitored folder.
1154
1240
  # Globals:
@@ -1409,20 +1495,18 @@ EOF
1409
1495
  "client_id=${client_id}" "scope=${scope}")
1410
1496
  local auth_url
1411
1497
  auth_url="${OAUTH_BASE_URL}auth?${parameters}"
1412
- printf '%s\n' "3. Open the link in browser and finish authentication: \
1413
- ${auth_url}"
1498
+ printf '%s\n' "3. Open the link in your browser and finish authentication. \
1499
+ Do not close the redirected page: ${auth_url}"
1414
1500
  cat <<EOF
1415
1501
  Note:
1502
+ The succeeded OAuth flow will land the browser on an error page - \
1503
+ "This site can't be reached". This is expected behavior. Copy the whole URL and continue.
1416
1504
  If the OAuth client is not for a native application, there will be an \
1417
1505
  "Error 400: redirect_uri_mismatch" shown up on the page. In this case, press \
1418
1506
  "Enter" to start again with a native application OAuth client ID.
1419
- If there is no local web server serving at ${REDIRECT_URI}, the \
1420
- succeeded OAuth flow will land the browser on an error page ("This site can't \
1421
- be reached"). This is an expected behavior. Copy the whole URL and continue.
1422
1507
 
1423
1508
  EOF
1424
- printf '%s' "4. Copy the authorization code or complete url from browser \
1425
- and paste here: "
1509
+ printf '%s' "4. Copy the complete URL from your browser and paste here: "
1426
1510
  read -r auth_code
1427
1511
  if [[ -z ${auth_code} ]]; then
1428
1512
  printf '%s\n\n' "No authorization code. Starting from beginning again..."
@@ -1507,6 +1591,7 @@ set_authentication_env_for_cloud_functions() {
1507
1591
  create_or_update_cloud_scheduler_for_pubsub(){
1508
1592
  check_authentication
1509
1593
  quit_if_failed $?
1594
+ local location_flag="--location=${REGION}"
1510
1595
  local scheduler_flag=()
1511
1596
  scheduler_flag+=(--schedule="$2")
1512
1597
  scheduler_flag+=(--time-zone="$3")
@@ -1514,13 +1599,13 @@ create_or_update_cloud_scheduler_for_pubsub(){
1514
1599
  scheduler_flag+=(--message-body="$5")
1515
1600
  local exist_job
1516
1601
  exist_job=($(gcloud scheduler jobs list --filter="name~${1}" \
1517
- --format="value(state)"))
1602
+ --format="value(state)" "${location_flag}"))
1518
1603
  local action needPause
1519
1604
  if [[ ${#exist_job[@]} -gt 0 ]]; then
1520
1605
  action="update"
1521
1606
  scheduler_flag+=(--update-attributes=$6)
1522
1607
  if [[ "${exist_job[0]}" == "PAUSED" ]]; then
1523
- gcloud scheduler jobs resume "${1}"
1608
+ gcloud scheduler jobs resume "${1}" "${location_flag}"
1524
1609
  if [[ $? -gt 0 ]]; then
1525
1610
  printf '%s\n' "Failed to resume paused Cloud Scheduler job [${1}]."
1526
1611
  return 1
@@ -1531,9 +1616,9 @@ create_or_update_cloud_scheduler_for_pubsub(){
1531
1616
  action="create"
1532
1617
  scheduler_flag+=(--attributes=$6)
1533
1618
  fi
1534
- gcloud scheduler jobs ${action} pubsub "$1" "${scheduler_flag[@]}"
1619
+ gcloud scheduler jobs ${action} pubsub "$1" "${scheduler_flag[@]}" "${location_flag}"
1535
1620
  if [[ "${needPause}" == "true" ]]; then
1536
- gcloud scheduler jobs pause "${1}"
1621
+ gcloud scheduler jobs pause "${1}" "${location_flag}"
1537
1622
  fi
1538
1623
  }
1539
1624
 
@@ -1613,7 +1698,9 @@ customized_install() {
1613
1698
  local tasks=("$@")
1614
1699
  local task
1615
1700
  for task in "${tasks[@]}"; do
1616
- ${task}
1701
+ local cmd
1702
+ eval "cmd=(${task})"
1703
+ "${cmd[@]}"
1617
1704
  quit_if_failed $?
1618
1705
  done
1619
1706
  }
@@ -1921,3 +2008,11 @@ join_string_array() {
1921
2008
  shift
1922
2009
  printf %s "$first" "${@/#/$separator}"
1923
2010
  }
2011
+
2012
+ # Import other bash files.
2013
+ _SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
2014
+ source "${_SELF}/google_ads.sh"
2015
+ source "${_SELF}/bigquery.sh"
2016
+ source "${_SELF}/apps_scripts.sh"
2017
+
2018
+ printf '%s\n' "Common Bash Library is loaded."