Skip to content

Commit f76faa0

Browse files
authored
Merge branch 'master' into master
2 parents 898e7f3 + aae2eae commit f76faa0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2233
-784
lines changed

.kokoro/common.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ build_file: "python-docs-samples/.kokoro/trampoline.sh"
99
# Use the Python worker docker image.
1010
env_vars: {
1111
key: "TRAMPOLINE_IMAGE"
12-
value: "gcr.io/cloud-devrel-kokoro-resources/python@sha256:4b6ba8c199e96248980db4538065cddeea594138b9b9fb2d0388603922087747"
12+
value: "gcr.io/cloud-devrel-kokoro-resources/python@sha256:e11a459d01e5dcd3613fda35c7c94edfecfe911ed79c078580ff59de300b1938"
1313
}
1414

1515
# Specify project ID

.kokoro/presubmit_tests_trace.cfg

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Format: //devtools/kokoro/config/proto/build.proto
2+
3+
# Download secrets from Cloud Storage.
4+
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"
5+
6+
# Tell the trampoline which build file to use.
7+
env_vars: {
8+
key: "TRAMPOLINE_BUILD_FILE"
9+
value: "github/python-docs-samples/.kokoro/system_tests.sh"
10+
}
11+
12+
env_vars: {
13+
key: "NOX_SESSION"
14+
value: "trace and py36 and not appengine"
15+
}

.kokoro/system_tests_trace.cfg

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Format: //devtools/kokoro/config/proto/build.proto
2+
3+
# Download secrets from Cloud Storage.
4+
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"
5+
6+
# Tell the trampoline which build file to use.
7+
env_vars: {
8+
key: "TRAMPOLINE_BUILD_FILE"
9+
value: "github/python-docs-samples/.kokoro/system_tests.sh"
10+
}
11+
12+
env_vars: {
13+
key: "NOX_SESSION"
14+
value: "trace and py36 and not appengine"
15+
}

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ install:
3232
- pip install --upgrade nox
3333
- pip install --upgrade git+https://github.com/dhermes/ci-diff-helper.git
3434
script:
35-
- "./scripts/travis.sh"
35+
- "./scripts/travis.sh"

appengine/flexible/pubsub/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
app = Flask(__name__)
2525

2626
# Configure the following environment variables via app.yaml
27-
# This is used in the push request handler to veirfy that the request came from
27+
# This is used in the push request handler to verify that the request came from
2828
# pubsub and originated from a trusted source.
2929
app.config['PUBSUB_VERIFICATION_TOKEN'] = \
3030
os.environ['PUBSUB_VERIFICATION_TOKEN']
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
google-endpoints==4.7.0
1+
google-endpoints==4.8.0
22
google-endpoints-api-management==1.11.0

appengine/standard/mail/app.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ runtime: python27
22
api_version: 1
33
threadsafe: yes
44

5-
# [START bounce_service]
65
# [START mail_service]
76
inbound_services:
87
- mail
8+
- mail_bounce # Handle bounced mail notifications
99
# [END mail_service]
10-
- mail_bounce
11-
# [END bounce_service]
1210

1311
handlers:
1412
- url: /user/.+

appengine/standard/pubsub/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
app = Flask(__name__)
2626

2727
# Configure the following environment variables via app.yaml
28-
# This is used in the push request handler to veirfy that the request came from
28+
# This is used in the push request handler to verify that the request came from
2929
# pubsub and originated from a trusted source.
3030
app.config['PUBSUB_VERIFICATION_TOKEN'] = \
3131
os.environ['PUBSUB_VERIFICATION_TOKEN']

appengine/standard_python37/bigquery/main.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,8 @@ def main():
3939

4040

4141
if __name__ == '__main__':
42-
app.run(debug=True)
42+
# This is used when running locally only. When deploying to Google App
43+
# Engine, a webserver process such as Gunicorn will serve the app. This
44+
# can be configured by adding an `entrypoint` to app.yaml.
45+
app.run(host='127.0.0.1', port=8080, debug=True)
4346
# [END gae_python37_bigquery]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# [START gae_python37_custom_runtime]
2+
runtime: python37
3+
entrypoint: uwsgi --http-socket :8080 --wsgi-file main.py --callable app --master --processes 1 --threads 2
4+
# [END gae_python37_custom_runtime]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright 2018 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from flask import Flask
16+
17+
app = Flask(__name__)
18+
19+
20+
@app.route('/')
21+
def main():
22+
return 'Hello, World!'
23+
24+
25+
if __name__ == '__main__':
26+
app.run(debug=True)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
uwsgi==2.0.17.1
2+
flask==1.0.2

appengine/standard_python37/redis/main.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,7 @@ def index():
3939

4040

4141
if __name__ == '__main__':
42-
# This is used when running locally.
42+
# This is used when running locally only. When deploying to Google App
43+
# Engine, a webserver process such as Gunicorn will serve the app. This
44+
# can be configured by adding an `entrypoint` to app.yaml.
4345
app.run(host='127.0.0.1', port=8080, debug=True)

appengine/standard_python37/spanner/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
# [START gae_python37_cloudsql_mysql]
15+
# [START gae_python37_cloud_spanner]
1616
import os
1717

1818
from flask import Flask
@@ -33,3 +33,4 @@ def main():
3333
results = list(cursor)
3434

3535
return 'Query Result: {}'.format(results[0][0])
36+
# [END gae_python37_cloud_spanner]

bigquery/cloud-client/user_credentials.py

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,18 @@
2323
import argparse
2424

2525

26-
def run_query(credentials, project, query):
27-
from google.cloud import bigquery
28-
29-
client = bigquery.Client(project=project, credentials=credentials)
30-
query_job = client.query(query)
31-
32-
# Print the results.
33-
for row in query_job.result(): # Wait for the job to complete.
34-
print(row)
35-
36-
37-
def authenticate_and_query(project, query, launch_browser=True):
26+
def main(project, launch_browser=True):
27+
# [START bigquery_auth_user_flow]
3828
from google_auth_oauthlib import flow
3929

30+
# TODO: Uncomment the line below to set the `launch_browser` variable.
31+
# launch_browser = True
32+
#
33+
# The `launch_browser` boolean variable indicates if a local server is used
34+
# as the callback URL in the auth flow. A value of `True` is recommended,
35+
# but a local server does not work if accessing the application remotely,
36+
# such as over SSH or from a remote Jupyter notebook.
37+
4038
appflow = flow.InstalledAppFlow.from_client_secrets_file(
4139
'client_secrets.json',
4240
scopes=['https://www.googleapis.com/auth/bigquery'])
@@ -46,7 +44,33 @@ def authenticate_and_query(project, query, launch_browser=True):
4644
else:
4745
appflow.run_console()
4846

49-
run_query(appflow.credentials, project, query)
47+
credentials = appflow.credentials
48+
# [END bigquery_auth_user_flow]
49+
50+
# [START bigquery_auth_user_query]
51+
from google.cloud import bigquery
52+
53+
# TODO: Uncomment the line below to set the `project` variable.
54+
# project = 'user-project-id'
55+
#
56+
# The `project` variable defines the project to be billed for query
57+
# processing. The user must have the bigquery.jobs.create permission on
58+
# this project to run a query. See:
59+
# https://cloud.google.com/bigquery/docs/access-control#permissions
60+
61+
client = bigquery.Client(project=project, credentials=credentials)
62+
63+
query_string = """SELECT name, SUM(number) as total
64+
FROM `bigquery-public-data.usa_names.usa_1910_current`
65+
WHERE name = 'William'
66+
GROUP BY name;
67+
"""
68+
query_job = client.query(query_string)
69+
70+
# Print the results.
71+
for row in query_job.result(): # Wait for the job to complete.
72+
print("{}: {}".format(row['name'], row['total']))
73+
# [END bigquery_auth_user_query]
5074

5175

5276
if __name__ == '__main__':
@@ -58,9 +82,8 @@ def authenticate_and_query(project, query, launch_browser=True):
5882
help='Use a local server flow to authenticate. ',
5983
action='store_true')
6084
parser.add_argument('project', help='Project to use for BigQuery billing.')
61-
parser.add_argument('query', help='BigQuery SQL Query.')
6285

6386
args = parser.parse_args()
6487

65-
authenticate_and_query(
66-
args.project, args.query, launch_browser=args.launch_browser)
88+
main(
89+
args.project, launch_browser=args.launch_browser)

bigquery/cloud-client/user_credentials_test.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import mock
1919
import pytest
2020

21-
from user_credentials import authenticate_and_query
21+
from user_credentials import main
2222

2323

2424
PROJECT = os.environ['GCLOUD_PROJECT']
@@ -36,6 +36,7 @@ def mock_flow():
3636

3737

3838
def test_auth_query_console(mock_flow, capsys):
39-
authenticate_and_query(PROJECT, 'SELECT 1+1;', launch_browser=False)
39+
main(PROJECT, launch_browser=False)
4040
out, _ = capsys.readouterr()
41-
assert '2' in out
41+
# Fun fact: William P. Wood was the 1st director of the US Secret Service.
42+
assert 'William' in out

composer/tools/copy_environment.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
from __future__ import print_function
2929

3030
import argparse
31-
import ast
3231
import base64
3332
import contextlib
3433
import json
@@ -40,6 +39,7 @@
4039
import tempfile
4140
import time
4241
import uuid
42+
from distutils.spawn import find_executable
4343

4444
from cryptography import fernet
4545
import google.auth
@@ -52,6 +52,7 @@
5252
from six.moves import configparser
5353

5454
DEFAULT_SCOPES = ["https://www.googleapis.com/auth/cloud-platform"]
55+
EXECUTABLES = ['gcsfuse', 'cloud_sql_proxy', 'mysql', 'gcloud', 'gsutil']
5556

5657

5758
def parse_args():
@@ -294,8 +295,9 @@ def create_service_account_key(iam_client, project, service_account_name):
294295
)
295296
.execute()
296297
)
297-
service_account_key_decoded = ast.literal_eval(
298+
service_account_key_decoded = json.loads(
298299
base64.b64decode(service_account_key.get("privateKeyData", ""))
300+
.decode("utf-8")
299301
)
300302
time.sleep(5)
301303
return service_account_key_decoded
@@ -333,16 +335,10 @@ def get_sql_instance_service_account(sql_client, project, instance):
333335

334336

335337
def grant_rw_permissions(gcs_bucket, service_account):
336-
if subprocess.call(
337-
[
338-
"gsutil",
339-
"acl",
340-
"ch",
341-
"-u",
342-
service_account + ":O",
343-
"gs://" + gcs_bucket.name,
344-
]
345-
):
338+
try:
339+
gcs_bucket.acl.user(service_account).grant_owner()
340+
gcs_bucket.acl.save()
341+
except Exception:
346342
print(
347343
"Failed to set acls for service account {} on bucket {}.".format(
348344
service_account, gcs_bucket.name
@@ -542,7 +538,10 @@ def import_data(
542538
if proxy_subprocess:
543539
proxy_subprocess.kill()
544540
if fuse_dir:
545-
subprocess.call(["fusermount", "-u", fuse_dir])
541+
try:
542+
subprocess.call(["fusermount", "-u", fuse_dir])
543+
except OSError:
544+
subprocess.call(["umount", fuse_dir])
546545
if tmp_dir_name:
547546
shutil.rmtree(tmp_dir_name)
548547

@@ -571,7 +570,9 @@ def copy_database(project, existing_env, new_env, running_as_service_account):
571570
try:
572571
# create default creds clients
573572
default_credentials, _ = google.auth.default(scopes=DEFAULT_SCOPES)
574-
storage_client = storage.Client(credentials=default_credentials)
573+
storage_client = storage.Client(
574+
project=project, credentials=default_credentials
575+
)
575576
iam_client = discovery.build(
576577
"iam", "v1", credentials=default_credentials
577578
)
@@ -717,8 +718,19 @@ def clone_environment(
717718
)
718719

719720

721+
def check_executables():
722+
not_found = [
723+
executable for executable in EXECUTABLES
724+
if not find_executable(executable)
725+
]
726+
if not_found:
727+
print('Required executables not found: {}'.format(' '.join(not_found)))
728+
sys.exit(1)
729+
730+
720731
if __name__ == "__main__":
721732
args = parse_args()
733+
check_executables()
722734
clone_environment(
723735
args.project,
724736
args.location,

composer/tools/copy_environment_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
def test_grant_rw_permissions_fails_gracefully(monkeypatch, capsys):
2424
mock_call = mock.Mock()
25-
mock_call.return_value = 1
25+
mock_call.side_effect = RuntimeError()
2626
monkeypatch.setattr(subprocess, 'call', mock_call)
2727
monkeypatch.setattr(time, 'sleep', lambda sec: None)
2828
from . import copy_environment

0 commit comments

Comments
 (0)