SlideShare a Scribd company logo
1 of 48
Download to read offline
Exploring Google APIs 102:
Cloud APIs vs. non-GCP Google APIs
Wesley Chun - @wescpy
Principal, CyberWeb Consulting
Adjunct CS Faculty, Foothill College
Principal, CyberWeb Consulting
● Mission: help developers everywhere
be successful using Google Cloud and
other Google developer tools & APIs
● Focus: Python, Google Cloud (APIs,
serverless, AI/ML), Google Workspace;
Google cross-product use cases
● Services: training, technical talks,
speak globally; make videos, create
code samples, produce codelabs (free,
self-paced, hands-on tutorials),
publish blog posts
About the speaker
Previous experience / background
● Software Engineer & Developer Advocate
○ Google, Sun, HP, Cisco, EMC, Xilinx
○ Original Yahoo!Mail engineer/SWE
● Technical trainer, teacher, instructor
○ Teaching Math, Linux, Python since '83
○ Adjunct CS Faculty at local SV college
● Python community member
○ Popular Core Python series author
○ Python Software Foundation Fellow
● AB (Math/CS) & CMP (Music/Piano), UC
Berkeley and MSCS, UC Santa Barbara
● Adjunct Computer Science Faculty, Foothill
College (Silicon Valley)
Google APIs: why & agenda
● Build on knowledge from "Exploring Google APIs" talks
● Highlight use of Cloud vs. non-GCP Google APIs
● Key difference: the client library you use
○ Lower-level client libraries vs. product-level client libraries
● Many code samples illustrate Cloud & non-GCP Google API usage
● Awareness reduces friction/challenges from using multiple Google APIs
1
Google APIs
introduction
2
Using Google
APIs
4
Cloud APIs
5
Other Google
APIs
6
Mix-n-match
& inspiration
3
Workspace
(non-GCP) APIs
7
Wrap-up
01
Intro to Google APIs
Why are you here?
BUT
... wait, there’s more...
Most products/APIs have "Quickstarts"
● Get started in 5 minutes!
● Available in most languages
02
Using Google APIs
Getting started & the nuts-n-bolts
The first word on Security
Authentication ("authn") vs authorization ("authz")
● authn: you are who you say you are
○ login & password
○ handprint authentication
○ retina scan
● authz: okay, you are who you say you are, but can you haz data?
○ OAuth2 - mostly authz, but some authn
○ Mostly about 3rd-party access to data
○ Users must give YOUR code access to THEIR data
○ Most of the time when you see "auth", it refers to authz
○ With Google APIs: permission scopes or IAM permissions/roles
● Some refer to this as "consent" vs. "credentials…" which is which?
General steps
1. Go to Cloud Console
2. Login to Google/Gmail account
(Workspace domain may require admin approval)
3. Create project (per application)
4. Enable APIs to use
5. Enable billing (CC, Free Trial, etc.)
6. Download client library(ies)
7. Create & download credentials
8. Write code
9. Run code (may need to authorize)
Google APIs: how to use
Costs and pricing
● GCP: pay-per-use
● Google Workspace: subscription
● GCP Free Trial ($300/1Q, CC req'd)
● GCP "Always Free" tier
○ Most products have free tier
○ Daily or monthly quota
○ Must exceed to incur billing
● More on both programs at
cloud.google.com/free
*In your code
1. Import API client library
2. Create API client object
3. Use client to make API Calls
Cloud/GCP console
console.cloud.google.com
● Hub of all developer activity
● Applications == projects
○ New project for new apps
○ Projects have a billing acct
● Manage billing accounts
○ Financial instrument required
○ Personal or corporate credit cards,
Free Trial, and education grants
● Access GCP product settings
● Manage users & security
● Manage APIs in devconsole
Billing & budgeting (your favorite subjects)
Collaborating & sharing
● Sharing: great way to see student work or have teams work on one project
● IAM (Identity & Access Mgmt): owner & editor most useful access levels
cloud.google.com/iam/docs/understanding-roles
● View application statistics
● En-/disable Google APIs
● Obtain application credentials
Using Google APIs
goo.gl/RbyTFD
API manager aka Developers Console (devconsole)
console.developers.google.com
Three different credentials types
● Simple: API keys (to access public data)
○ Simplest form of authorization: an API key; tied to a project
○ Allows access to public data
○ Do not put in code, lose, or upload to GitHub! (can be restricted however)
○ Supported by: Google Maps, (some) YouTube, (some) GCP, etc.
● Authorized: OAuth client IDs (to access data owned by [human] user)
○ Provides additional layer of security via OAuth2 (RFC 6749)
○ Owner must grant permission for your app to access their data
○ Access granularity determined by requested permissions (user scopes)
○ Supported by: Google Workspace, (some) YouTube, (some) GCP, etc.
● Authorized: service accounts (to access data owned by an app/robot user)
○ Provides additional layer of security via OAuth2 or JWT (RFC 7519)
○ Project owning data grants permission implicitly; requires public-private key-pair
○ Access granularity determined by Cloud IAM permissions granted to service account key-pair
○ Supported by: GCP, (some) Google Workspace, etc.
Two different client library "styles"
● "Platform-level" client libraries (lower-level)
○ Supports multiple products as a "lowest-common denominator"
○ Manage API service endpoints (setup & use)
○ Manage authorization (API keys, OAuth client IDs, service accounts)
○ Google Workspace, Google Analytics, YouTube, Google Ads APIs, GCP, etc.
○ Install: developers.google.com/api-client-library
● "Product-level" client libraries (higher-level)
○ Custom client libraries made specifically for each product
○ Managing API service endpoints & security mostly taken care of
○ Only need to create a "client" to use API services
○ Install (Cloud/GCP & Firebase): cloud.google.com/apis/docs/cloud-client-libraries
○ Install (Maps): developers.google.com/places/web-service/client-library
● Some Google APIs families support both, e.g., Cloud
&
Google APIs client
libraries for many
languages; demos in
developers.google.com/api-
client-library
cloud.google.com/apis/docs
/cloud-client-libraries
SIMPLE
AUTHORIZED
Which do you choose?
from googleapiclient import discovery
# Can copy from DevConsole, or better yet, put into Secret
# Manager, encrypted/secure store/DB, creds svr, proxy, etc.
from settings import API_KEY
# API information, i.e., (API='language', VERSION='v1')
SERVICE = discovery.build(API, VERSION, developerKey=API_KEY)
Simple API access(lower-level, generic)
import googlemaps
# Can copy from DevConsole, or better yet, put into Secret
# Manager, encrypted/secure store/DB, creds svr, proxy, etc.
from settings import API_KEY
GMAPS = googlemaps.Client(key=API_KEY)
print('n** Geocode address:')
rsp = GMAPS.geocode('1600 Amphitheatre Pkwy 94043')
latlong = rsp[0]['geometry']['location']
print('tGeocode:', latlong['lat'], ',', latlong['lng'])
Simple API access(higher-level, specific)
Google OAuth2 process
● Goal: valid access token == 3rd-party API data access
● How OAuth2 works (in general)
○ Step 1: Create OAuth2 credentials in DevConsole
○ Step 2: Send credentials to get access & refresh tokens
○ Step 3: Use access token to make authorized API calls
○ Step 4: Access tokens expire; use refresh to get new one
● developers.google.com/identity/protocols/OAuth2
● Other APIs will be similar with some differences
(User-)authorized API access(lower-level, older, generic)
OAuth boilerplate
goo.gl/KMfbeK
from googleapiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools
SCOPES = ... # at least one (string or array of strings)
# 'storage.json' - where to store OAuth2 tokens from API
# 'client_secret.json' - OAuth2 client ID & secret (download from DevConsole)
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
# create API service endpoint; for example: API='sheets', VERSION='v4'
SERVICE = discovery.build(API, VERSION, http=creds.authorize(Http()))
(User-)authorized API access(lower-level, newer, generic)
from googleapiclient import discovery
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2 import credentials
SCOPES = ... # at least one (string or array of strings)
# 'storage.json' - where to store OAuth2 tokens from API
# 'client_secret.json' - OAuth2 client ID & secret (download from DevConsole)
TOKENS = 'storage.json' # OAuth2 token storage
if os.path.exists(TOKENS):
creds = credentials.Credentials.from_authorized_user_file(TOKENS)
if not (creds and creds.valid):
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES)
creds = flow.run_local_server()
with open(TOKENS, 'w') as token:
token.write(creds.to_json())
# create API service endpoint; for example: API='sheets', VERSION='v4'
SERVICE = discovery.build(API, VERSION, http=creds.authorize(Http()))
Service account access(lower-level, scopes, older, generic)
from googleapiclient import discovery
from httplib2 import Http
from oauth2client import service_account
SCOPES = ... # at least one (string or array of strings)
# 'svc_acct.json' - OAuth2 service acct creds (download from DevConsole)
creds = service_account.ServiceAccountCredentials.from_json_keyfile_name(
'svc_acct.json', SCOPES)
# create API service endpoint; for example: API='sheets', VERSION='v4'
SERVICE = discovery.build(API, VERSION, http=creds.authorize(Http()))
Service account access(lower-level, svc acct, older, generic)
from googleapiclient import discovery
from oauth2client import client
. . .
# Creds file or (better) use Application Default Credentials (ADC)
# see cloud.google.com/docs/authentication/application-default-credentials
creds = client.GoogleCredentials.get_application_default()
# create API service endpoint; for example: API='sheets', VERSION='v4'
SERVICE = discovery.build(API, VERSION, credentials=creds)
from googleapiclient import discovery
import google.auth
. . .
# Creds file or (better) use Application Default Credentials (ADC)
# see cloud.google.com/docs/authentication/application-default-credentials
creds, _proj_id = google.auth.default()
# create API service endpoint; for example: API='sheets', VERSION='v4'
SERVICE = discovery.build(API, VERSION, credentials=creds)
Service account access(lower-level, svc acct, newer, generic)
from google.cloud import storage
# Implicit ADC usage (no security code visible!)
GCS = storage.Client() # uses ADC (app default creds)
blob = GCS.bucket(bucket).blob(FILENAME) # destination file
print('n** Uploading to %r' % BUCKET)
blob.upload_from_filename(FILENAME) # origin file
Service account access(higher-level, svc acct, newer, specific)
OAuth2 or
API key
HTTP-based REST APIs 1
HTTP
2
Google APIs request-response workflow
● Application makes request
● Request received by service
● Process data, return response
● Results sent to application
(typical client-server model)
03
Google Workspace
(formerly G Suite) APIs
Examples of non-Cloud Google APIs
Google Workspace
Top-level documentation and comprehensive developers
overview video at developers.google.com/gsuite
(formerly G Suite and Google Apps)
APIs
List (first 100) files/folders in Drive (older, OAuth2)
from __future__ import print_function
from googleapiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http()))
files = DRIVE.files().list().execute().get('files', [])
for f in files:
print(f['name'], f['mimeType'])
Listing your files
goo.gl/ZIgf8k
List (first 100) files/folders in Drive (newer, OAuth2)
from __future__ import print_function
import os.path
import pickle
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient import discovery
creds = None
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
TOKENS = 'token.p' # where to store access & refresh tokens
if os.path.exists(TOKENS):
with open(TOKENS, 'rb') as token:
creds = pickle.load(token)
if not (creds and creds.valid):
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES)
creds = flow.run_local_server()
with open(TOKENS, 'wb') as token:
pickle.dump(creds, token)
DRIVE = discovery.build('drive', 'v3', credentials=creds)
files = DRIVE.files().list().execute().get('files', [])
for f in files:
print(f['name'], f['mimeType'])
developers.google.com/drive/api/v3/quickstart/python
List (first 100) files/folders in Drive (newer, svc acct)
from __future__ import print_function
from googleapiclient import discovery
import google.auth
creds, _proj_id = google.auth.default() # ADC; shared w/SA
dr_client = discovery.build('drive', 'v4', credentials=creds)
files = dr_client.files().list().execute().get('files', [])
for f in files: # fields returned: mimeType, kind, id, name
print(f['name'], f['mimeType'])
Automate photo albums
OR
Try our Node.js customized reporting tool codelab:
g.co/codelabs/sheets
Why use the Sheets API?
data visualization
customized reports
Sheets as a data source
Migrate SQL data to a Sheet
# read SQL data then create new spreadsheet & add rows into it
FIELDS = ('ID', 'Customer Name', 'Product Code',
'Units Ordered', 'Unit Price', 'Status')
cxn = sqlite3.connect('db.sqlite')
cur = cxn.cursor()
rows = cur.execute('SELECT * FROM orders').fetchall()
cxn.close()
rows.insert(0, FIELDS)
DATA = {'properties': {'title': 'Customer orders'}}
SHEET_ID = SHEETS.spreadsheets().create(body=DATA,
fields='spreadsheetId').execute().get('spreadsheetId')
SHEETS.spreadsheets().values().update(spreadsheetId=SHEET_ID, range='A1',
body={'values': rows}, valueInputOption='RAW').execute()
Migrate SQL data
to Sheets
goo.gl/N1RPwC
Try our Node.js BigQuery GitHub license analyzer codelab:
g.co/codelabs/slides
Why use the Slides API?
data visualization
presentable reports
Try our Node.js Markdown-to-Google-Slides generator:
github.com/gsuitedevs/md2googleslides
Why use the Slides API?
customized presentations
Replace text & images from template deck
requests = [
# (global) search-and-replace text
{'replaceAllText': {
'findText': '{{TITLE}}',
'replaceText': 'Hello World!',
}},
# replace text-based image placeholders (global)
{'replaceAllShapesWithImage': {
'imageUrl': IMG_URL, # link to product logo
'replaceMethod': 'CENTER_INSIDE',
'containsText': {'text': '{{LOGO}}'},
}},
]
SLIDES.presentations().batchUpdate(body={'requests': requests},
presentationId=DECK_ID, fields='').execute()
Replacing text
and images
goo.gl/o6EFwk
Display Gmail threads (& # of messages)
# get all "busy" mail threads & display (non-blank) Subject lines
threads = GMAIL.users().threads().list(userId='me',
fields='threads').execute().get('threads', [])
for thread in threads:
tdata = GMAIL.users().threads().get(userId='me', id=thread['id'],
format='metadata', metadataHeaders=['subject'],
fields='messages/payload/headers(name,value)').execute()
if 'messages' not in tdata:
continue
if len(tdata['messages']) > 10:
msg = tdata['messages'][0]['payload']
subject = ''
for header in msg['headers']:
if header['name'] == 'Subject':
subject = header['value']
break
if subject:
print('%2d message(s) in thread: %s' % (
len(tdata['messages']), subject))
Gmail threads
goo.gl/pFYUQ2
Creating events in Calendar
# define event data, then create event
TIMEZONE = 'America/Los_Angeles'
EVENT = {
'summary': 'Dinner with friends',
'start': {'dateTime': '2017-06-14T19:00:00', 'timeZone': TIMEZONE},
'end': {'dateTime': '2017-06-14T22:00:00', 'timeZone': TIMEZONE},
'attendees': [
{'email': 'friend1@example.com'},
{'email': 'friend2@example.com'},
],
}
GCAL.events().insert(calendarId='primary', body=EVENT,
sendNotifications=True, fields='').execute()
Modifying and
recurring events
goo.gl/J2XkXc
Creating events
goo.gl/KuYMiq
+
Mail merge
=
Mail merge
goo.gle/2KrPNeG
Mail merge (get data from Sheets)
TMPL_ID = 'YOUR_DOCS_TEMPLATE'
SHEETS_ID = 'YOUR_DATA_SPREADSHEET'
SCOPES = (
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/spreadsheets',
)
HTTP = creds.authorize(Http()) # ↙↙↙ how to access multiple APIs
DRIVE = discovery.build('drive', 'v3', http=HTTP)
DOCS = discovery.build('docs', 'v1', http=HTTP)
SHEETS = discovery.build('sheets', 'v4', http=HTTP)
# get data from spreadsheet, copy & merge template for each row
rows = SHEETS.spreadsheets().values().get(range='Sheet1',
spreadsheetId=SHEETS_ID).execute().get('values')[1:]
for row in rows:
DOCS_ID = DRIVE.files().copy(body={'name': 'Merged form letter'},
fileId=TMPL_ID, fields='id').execute().get('id')
Mail merge (template search & replace)
requests = [
# (global) search-and-replace text
{'replaceAllText': {
'containsText': {'text': '{{NAME}}'},
'replaceText': row['name'],
}},
]
DOCS.documents().batchUpdate(body={'requests': requests},
documentId=DOC_ID, fields='').execute()
04
Google Cloud APIs
Can use either Cloud and/or
lower-level client libraries
Storage: listing buckets
from __future__ import print_function
from googleapiclient import discovery
GCS = discovery.build('storage', 'v1')
BUCKET = YOUR_BUCKET
# send bucket name & return fields to API, display results
print('n** Objects in bucket %r...' % BUCKET)
FIELDS = 'items(name,size)'
files = GCS.objects().list(bucket=BUCKET, fields=FIELDS
).execute().get('items') or [{'name': '(none)', 'size': 'NaN'}]
for f in files:
print(' %s (%s)' % (f['name'], f['size']))
Storage: listing buckets
from __future__ import print_function
from google.cloud import storage
GCS = storage.Client()
BUCKET = YOUR_BUCKET
# send bucket name & return fields to API, display results
print('n** Objects in bucket %r...' % BUCKET)
for f in GCS.list_blobs(BUCKET):
print(' %s (%s)' % (f['name'], f['size']))
Firestore (Datastore): object create & query
from datetime import datetime
from google.cloud import datastore
DATASTORE = datastore.Client() # create Cloud Datastore client
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
entity = datastore.Entity(key=DATASTORE.key('visit'))
entity.update({'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent)})
DATASTORE.put(entity)
def fetch_visits(limit):
'get most recent Visits'
query = DATASTORE.query(kind='visit')
query.order = ['-timestamp']
return query.fetch(limit=limit)
const {DatastoreClient} = require('@google-cloud/datastore);
const DATASTORE = new DatastoreClient();
// create new Visit entity in Datastore
async function storeVisit(remote_addr, user_agent) {
const entity = {
key: DATASTORE.key(['Visit']),
data: {
visitor: `${remote_addr}: ${user_agent}`,
timestamp: new Date()
}
};
await DATASTORE.save(entity);
// get most recent Visits
async function fetchVisits(limit) {
const query = DATASTORE.createQuery('Visit')
.order('timestamp', {descending: true}).limit(limit);
const [results] = await DATASTORE.runQuery(query);
Firestore (Datastore): object create & query
BigQuery: querying Shakespeare words
TITLE = "The top 10 most common words in all of Shakespeare's works"
QUERY = '''
SELECT LOWER(word) AS word, sum(word_count) AS count
FROM [bigquery-public-data:samples.shakespeare]
GROUP BY word ORDER BY count DESC LIMIT 10
'''
BQ = discovery.build('bigquery', 'v2', http=creds.authorize(Http()))
rsp = BQ.query(body={'query': QUERY}, projectId=PROJ_ID).execute()
print('n*** Results for %r:n' % TITLE)
for col in rsp['schema']['fields']: # HEADERS
print(col['name'].upper(), end='t')
print()
for row in rsp['rows']: # DATA
for col in row['f']:
print(col['v'], end='t')
print()
BigQuery: querying Shakespeare words
from google.cloud import bigquery
TITLE = "The most common words in all of Shakespeare's works"
QUERY = '''
SELECT LOWER(word) AS word, sum(word_count) AS count
FROM `bigquery-public-data.samples.shakespeare`
GROUP BY word ORDER BY count DESC LIMIT 10
'''
rsp = bigquery.Client().query(QUERY).result()
print('n*** Results for %r:n' % TITLE)
print('t'.join(col.name.upper() for col in rsp.schema)) # HEADERS
print('n'.join('t'.join(str(x) for x in row.values()) for row in rsp)) # DATA
Top 10 most common Shakespeare words
$ python bq_shake.py
*** Results for "The most common words in all of Shakespeare's works":
WORD COUNT
the 29801
and 27529
i 21029
to 20957
of 18514
a 15370
you 14010
my 12936
in 11722
that 11519
● BigQuery public data sets: cloud.google.com/bigquery/public-data
● BQ sandbox (1TB/mo free): cloud.google.com/bigquery/docs/sandbox (see blog post)
● Other public data sets: cloud.google.com/public-datasets (Google Cloud),
research.google/tools/datasets (Google Research), and Kaggle (kaggle.com)
● COVID-19 BigQuery data sets
○ How to use our data sets (see blog post)
○ JHU Coronavirus COVID-19 Global Cases data set
○ List of all COVID-19 data sets
● Cloud Life Sciences API: cloud.google.com/life-sciences (see blog post)
● Cloud Healthcare API: cloud.google.com/healthcare (see blog post)
BigQuery and public data sets
IMG = 'gs://cloud-samples-data/vision/using_curl/shanghai.jpeg'
body = {'requests': [{
'image': {'source': {'imageUri': IMG}},
'features': [{'type': 'LABEL_DETECTION'}],
}]}
VISION = discovery.build('vision', 'v1', developerKey=API_KEY)
labeling = VISION.images().annotate(body=body).execute().get('responses')
for labels in labeling:
if 'labelAnnotations' in labels:
print('** Labels detected (and confidence score):')
for label in labels['labelAnnotations']:
print(label['description'], '(%.2f%%)' % (label['score']*100.))
Vision: label annotation/object detection
from google.cloud import vision
image_uri = 'gs://cloud-samples-data/vision/using_curl/shanghai.jpeg'
client = vision.ImageAnnotatorClient()
image = vision.types.Image()
image.source.image_uri = image_uri
response = client.label_detection(image=image)
print('Labels (and confidence score):')
print('=' * 30)
for label in response.label_annotations:
print(label.description, '(%.2f%%)' % (label.score*100.))
Vision: label annotation/object detection
$ python3 label-detect.py
Labels (and confidence score):
==============================
People (95.05%)
Street (89.12%)
Mode of transport (89.09%)
Transport (85.13%)
Vehicle (84.69%)
Snapshot (84.11%)
Urban area (80.29%)
Infrastructure (73.14%)
Road (72.74%)
Pedestrian (68.90%)
Vision: label annotation/object detection
g.co/codelabs/vision-python
05
Other Google APIs
Use lower-level or product-level
client libraries (see documentation)
Other Google APIs & platforms
● Firebase (mobile development platform + RT DB; ML Kit)
○ firebase.google.com & firebase.google.com/docs/ml-kit
● Google Data Studio (data visualization, dashboards, etc.)
○ datastudio.google.com/overview
○ goo.gle/datastudio-course
● Actions on Google/Assistant/DialogFlow (voice apps)
○ developers.google.com/actions
● YouTube (Data, Analytics, and Livestreaming APIs)
○ developers.google.com/youtube
● Google Maps (Maps, Routes, and Places APIs)
○ developers.google.com/maps
● Flutter (native apps [Android, iOS, web] w/1 code base[!])
○ flutter.dev
Search YouTube for videos
from __future__ import print_function
from googleapiclient import discovery
from settings import API_KEY
QUERY = 'python -snake'
trim = lambda x, ct: ('%s%s' % (x[:ct],
'...' if len(x)>ct else '')).ljust(ct+3)
print('n** Searching for %r videos...' % QUERY)
YOUTUBE = discovery.build('youtube', 'v3', developerKey=API_KEY)
res = YOUTUBE.search().list(q=QUERY, type='video',
part='id,snippet').execute().get('items', [])
for item in res:
print('http://youtu.be/%st%s' % (
trim(item['id']['videoId'], 24),
trim(item['snippet']['title'], 48)))
Maps APIs geocoding & places queries
import googlemaps
from settings import API_KEY
GMAPS = googlemaps.Client(key=API_KEY)
print('n** Geocode address:')
rsp = GMAPS.geocode('1600 Amphitheatre Pkwy 94043')
latlong = rsp[0]['geometry']['location']
print('tGeocode:', latlong['lat'], ',', latlong['lng'])
print('n** Address lookup:')
rsp = GMAPS.reverse_geocode((37.4222934, -122.0841409))
print('tAddress:', rsp[0]['formatted_address'])
print('n** Place query:')
pl_id = GMAPS.find_place('Villa Tugendhat',
input_type='textquery')['candidates'][0]['place_id']
place = GMAPS.place(pl_id)['result']
print('tPlace:t', place['name'])
print('tAddress:t', place['formatted_address'])
print('tWebsite:t', place['website'])
print('tMaps URL:t', place['url'])
$ python3 maps-demo-pub.py
** Geocode address:
Geocode: 37.4222934 , -122.0841409
** Address lookup:
Address: 1600 Amphitheatre Pkwy, Mountain View, CA
94043, USA
** Place query:
Place: Villa Tugendhat
Address: Černopolní 45, 613 00 Brno, Czechia
Website: tugendhat.eu
Maps URL: maps.google.com/?cid=5889127146370224362
Google Maps APIs
● Directions API
● Distance Matrix API
● Elevation API
● Geocoding API
● Geolocation API
● Time Zone API
● Roads API
● Places API
● Maps Static API
Google Apps Script
Customized serverless JS runtime for automation, and extension
and integration with Google Workspace (formerly G Suite) and
other Google & external services
+JavaScript
-API “flavor”
+built-in
“flavor”
-OAuth2 (you)
!=
“Hello World!” in Apps Script
Sheets-bound “Hello World!”
Apps Script intro
goo.gl/1sXeuD
What can you do with this?
Accessing maps from
spreadsheets?!?
goo.gl/oAzBN9
This… with help from Google Maps & Gmail
function sendMap() {
var sheet = SpreadsheetApp.getActiveSheet();
var address = sheet.getRange("A2").getValue();
var map = Maps.newStaticMap().addMarker(address);
GmailApp.sendEmail('friend@example.com', 'Map',
'See below.', {attachments:[map]});
}
JS
g.co/codelabs/apps-script-intro
06
Mix-n-match &
inspiration
Use Cloud and lower-level
(LL) client libraries or just LL
Cloud image processing workflow
Archive and analyze Google Workspace
(formerly G Suite) images with GCP
Image: Gerd Altmann from Pixabay
Cloud
Vision
Google Workspace GCP
Cloud image processing workflow
Cloud
Storage
Drive
Sheets
Archive
image
Categorize
image
Record
results
Cloud image processing workflow
from __future__ import print_function
import argparse, base64, io, webbrowser
from googleapiclient import discovery, http
from httplib2 import Http
from oauth2client import file, client, tools
k_ize = lambda b: '%6.2fK' % (b/1000.) # bytes to kBs
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = '' # YOUR IMG FILE PREFIX
SHEET = 'YOUR_SHEET_ID'
TOP = 5 # TOP # of VISION LABELS TO SAVE
DEBUG = False
# process credentials for OAuth2 tokens
SCOPES = (
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/devstorage',
'https://www.googleapis.com/auth/cloud-vision',
'https://www.googleapis.com/auth/spreadsheets',
)
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets(
'client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE = discovery.build('drive', 'v3', http=HTTP)
GCS = discovery.build('storage', 'v1', http=HTTP)
VISION = discovery.build('vision', 'v1', http=HTTP)
SHEETS = discovery.build('sheets', 'v4', http=HTTP)
Cloud image processing workflow
from __future__ import print_function
import argparse, base64, io, webbrowser
from googleapiclient import discovery, http
from httplib2 import Http
from oauth2client import file, client, tools
from google.cloud import storage, vision
k_ize = lambda b: '%6.2fK' % (b/1000.) # bytes to kBs
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = '' # YOUR IMG FILE PREFIX
SHEET = 'YOUR_SHEET_ID'
TOP = 5 # TOP # of VISION LABELS TO SAVE
DEBUG = False
# process credentials for OAuth2 tokens
SCOPES = (
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/devstorage',
'https://www.googleapis.com/auth/cloud-vision',
'https://www.googleapis.com/auth/spreadsheets',
)
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets(
'client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE = discovery.build('drive', 'v3', http=HTTP)
GCS = storage.Client()
VISION = vision.ImageAnnotatorClient()
SHEETS = discovery.build('sheets', 'v4', http=HTTP)
Cloud image processing workflow
def drive_get_file(fname):
rsp = DRIVE.files().list(q="name='%s'" % fname).execute().get['files'][0]
fileId, fname, mtype = rsp['id'], rsp['name'], rsp['mimeType']
blob = DRIVE.files().get_media(fileId).execute()
return fname, mtype, rsp['modifiedTime'], blob
def gcs_blob_upload(fname, bucket, blob, mimetype):
body = {'name': fname, 'uploadType': 'multipart',
'contentType': mimetype}
return GCS.objects().insert(bucket, body, blob).execute()
def vision_label_img(img, top):
body = {'requests': [{'image': {'content': img}, 'features':
[{'type': 'LABEL_DETECTION', 'maxResults': top}]}]}
rsp = VISION.images().annotate(
body=body).execute().get['responses'][0]
return ', '.join('%s (%.2f%%)' % (label['description'],
label['score']*100.) for label in rsp['labelAnnotations'])
def sheet_append_row(sheet, row):
rsp = SHEETS.spreadsheets().values().append(
spreadsheetId=sheet, range='Sheet1',
body={'values': rows}).execute()
return rsp.get('updates').get('updatedCells')
def main(fname, bucket, sheet_id, top):
fname, mtype, ftime, data = drive_get_img(fname)
gcs_blob_upload(fname, bucket, data, mtype)
rsp = vision_label_img(data, top)
sheet_append_row(sheet_id, [fname, mtype,
ftime, len(data), rsp])
API method calls in Bold
Driver calls in Bold Italics
Cloud image processing workflow
def drive_get_file(fname):
rsp = DRIVE.files().list(q="name='%s'" % fname).execute().get['files'][0]
fileId, fname, mtype = rsp['id'], rsp['name'], rsp['mimeType']
blob = DRIVE.files().get_media(fileId).execute()
return fname, mtype, rsp['modifiedTime'], blob
def gcs_blob_upload(fname, bucket, blob, mimetype):
blob = GCS.bucket(bucket).blob(fname)
blob.upload_from_string(media, mimetype)
return {'bucket': bucket, 'name': fname}
def vision_label_img(img, top):
image = vision.types.Image(content=img)
labels = VISION.label_detection(image=image,
max_results=top).label_annotations
return ', '.join('(%.2f%%) %s' % (
label.score*100., label.description) for label in labels)
def sheet_append_row(sheet, row):
rsp = SHEETS.spreadsheets().values().append(
spreadsheetId=sheet, range='Sheet1',
body={'values': rows}).execute()
return rsp.get('updates').get('updatedCells')
def main(fname, bucket, sheet_id, top):
fname, mtype, ftime, data = drive_get_img(fname)
gcs_blob_upload(fname, bucket, data, mtype)
rsp = vision_label_img(data, top)
sheet_append_row(sheet_id, [fname, mtype,
ftime, len(data), rsp])
API method calls in Bold
Driver calls in Bold Italics
● Project goal: Imagining an actual enterprise use case and solve it!
● Specific goals: free-up highly-utilized resource, archive data to
colder/cheaper storage, analyze images, generate report for mgmt
● Download image binary from Google Drive
● Upload object to Cloud Storage bucket
● Send payload for analysis by Cloud Vision
● Write back-up location & analysis results into Google Sheets
● Blog post: goo.gle/3nPxmlc (original post); Cloud X-post
● Codelab: free, online, self-paced, hands-on tutorial
● g.co/codelabs/drive-gcs-vision-sheets
● Application source code
● github.com/googlecodelabs/analyze_gsimg
App summary
07
Wrap-up
Summary & resources
Session Summary
● Google provides more than just apps
○ More than search, YouTube, Android, Chrome, and Gmail/Docs
○ Much Google techology available to developers via APIs
● Google Cloud vs. non-Cloud Google APIs
○ Alas, developer experience differs between product families
○ Some products have higher-level product client libraries
○ Others require use of lower-level client libraries
■ Lower-level may be useful as lowest common denominator
● Inconsistency due to various reasons: budget, timeframe, priorities, etc.
● Interesting possibilities using multiple Google product APIs
Client libraries & credentials review
● Two different client library types
○ Platform-level client libraries (lower-level)
■ Multiple product groups as a "lowest-common denominator"
■ Install: developers.google.com/api-client-library
○ Product-level client libraries (higher-level)
■ Custom client libraries made specifically for 1 product or product group
■ Found on product or product group page(s)
● Three different credentials types
○ Simple: API keys (access public data)
■ Simplest form of authorization: an API key; tied to a project
○ Authorized: OAuth client IDs (access data owned by [human] user)
■ Provides additional layer of security via OAuth2 (RFC 6749)
○ Authorized: service accounts (access data owned by an app/robot user)
■ Provides additional layer of security via OAuth2 or JWT (RFC 7519)
● Documentation (most APIs have "Quickstarts")
○ Google Cloud: cloud.google.com/{docs,appengine,functions,run,vision,automl,translate,language,
speech,texttospeech,video-intelligence,firestore,bigquery,compute,storage,gpu,tpu}
○ Google Workspace:
developers.google.com/{gsuite,drive,calendar,gmail,docs,sheets,slides,apps-script}
● Google codelabs (self-paced, hands-on tutorials): need a Google account, always free
○ GWS: g.co/codelabs/gsuite-apis-intro (Drive), g.co/codelabs/sheets (Sheets), g.co/codelabs/slides (Slides)
○ GCP: gcplab.me or g.co/codelabs/cloud
● Cloud Skills Boost (codelabs by QwikLabs): don't need a Google acct; typically not free
○ cloudskillsboost.google or google.qwiklabs.com
● Videos: youtube.com/GoogleCloudPlatform (Cloud) and goo.gl/JpBQ40 (Workspace)
● Code samples: github.com/GoogleCloudPlatform (Cloud) and github.com/googleworkspace (Workspace)
● Cloud Free Trial (new users) and Always Free (daily/monthly tier) programs: cloud.google.com/free
● Know AWS/Azure? Compare with Google Cloud products at cloud.google.com/docs/compare/aws
● Language support: cloud.google.com/{python,java,nodejs,go,php,ruby,dotnet}
Additional resources
"Free" … what is and what isn't?
● GCP free programs
○ Free Trial
■ $300USD credit good for 3 months
■ Billing/credit card required; expires
○ "Always Free" tier
■ Some GCP products free up to usage limits
■ Independent of Free Trial & education grants
■ Billing/credit card required; no expiration (subject to change)
○ cloud.google.com/free
● Google Workspace APIs/platforms
○ "Free" up to usage limits
○ Covered by monthly subscription fee
○ Pay-for or free Gmail consumer accts
○ Billing required; no expiration
● GCP education (teaching & research) grants
○ (Your) credit card NOT required; expires
○ Meant to provide initial "free" usage for coursework or research
○ cloud.google.com/edu
$$ FREE $$
Bring me to your
organization ... it's my job to
help you!
● "TOI" tech talks
● Half- or full-day seminars
● Hands-on "codelab" workshops
● Multi-day training courses
● Migration strategy & planning
● cyberwebconsulting.com
Thank you! Questions?
Wesley Chun
@wescpy
cyberwebconsulting.com
Progress bars: goo.gl/69EJVw

More Related Content

Similar to Exploring Google APIs 102: Cloud vs. non-GCP Google APIs

Using Google (Cloud) APIs
Using Google (Cloud) APIsUsing Google (Cloud) APIs
Using Google (Cloud) APIswesley chun
 
Cloud computing overview & Technical intro to Google Cloud
Cloud computing overview & Technical intro to Google CloudCloud computing overview & Technical intro to Google Cloud
Cloud computing overview & Technical intro to Google Cloudwesley chun
 
Exploring Google APIs with Python
Exploring Google APIs with PythonExploring Google APIs with Python
Exploring Google APIs with Pythonwesley chun
 
Easy path to machine learning (2023-2024)
Easy path to machine learning (2023-2024)Easy path to machine learning (2023-2024)
Easy path to machine learning (2023-2024)wesley chun
 
Exploring Google APIs with Python
Exploring Google APIs with PythonExploring Google APIs with Python
Exploring Google APIs with Pythonwesley chun
 
Getting started using Google APIs (2019)
Getting started using Google APIs (2019)Getting started using Google APIs (2019)
Getting started using Google APIs (2019)wesley chun
 
API Security - OWASP top 10 for APIs + tips for pentesters
API Security - OWASP top 10 for APIs + tips for pentestersAPI Security - OWASP top 10 for APIs + tips for pentesters
API Security - OWASP top 10 for APIs + tips for pentestersInon Shkedy
 
Serverless Computing with Google Cloud
Serverless Computing with Google CloudServerless Computing with Google Cloud
Serverless Computing with Google Cloudwesley chun
 
Powerful Google Cloud tools for your hack
Powerful Google Cloud tools for your hackPowerful Google Cloud tools for your hack
Powerful Google Cloud tools for your hackwesley chun
 
Introduction to Google Cloud Endpoints: Speed Up Your API Development
Introduction to Google Cloud Endpoints: Speed Up Your API DevelopmentIntroduction to Google Cloud Endpoints: Speed Up Your API Development
Introduction to Google Cloud Endpoints: Speed Up Your API DevelopmentColin Su
 
Introduction to Cloud Computing with Google Cloud
Introduction to Cloud Computing with Google CloudIntroduction to Cloud Computing with Google Cloud
Introduction to Cloud Computing with Google Cloudwesley chun
 
Introduction to serverless computing on Google Cloud
Introduction to serverless computing on Google CloudIntroduction to serverless computing on Google Cloud
Introduction to serverless computing on Google Cloudwesley chun
 
Exploring Google (Cloud) APIs with Python & JavaScript
Exploring Google (Cloud) APIs with Python & JavaScriptExploring Google (Cloud) APIs with Python & JavaScript
Exploring Google (Cloud) APIs with Python & JavaScriptwesley chun
 
How Google Cloud Platform can help in the classroom/lab
How Google Cloud Platform can help in the classroom/labHow Google Cloud Platform can help in the classroom/lab
How Google Cloud Platform can help in the classroom/labwesley chun
 
Designing flexible apps deployable to App Engine, Cloud Functions, or Cloud Run
Designing flexible apps deployable to App Engine, Cloud Functions, or Cloud RunDesigning flexible apps deployable to App Engine, Cloud Functions, or Cloud Run
Designing flexible apps deployable to App Engine, Cloud Functions, or Cloud Runwesley chun
 
Exploring MORE Google (Cloud) APIs with Python
Exploring MORE Google (Cloud) APIs with PythonExploring MORE Google (Cloud) APIs with Python
Exploring MORE Google (Cloud) APIs with Pythonwesley chun
 
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...e-Legion
 
Mobile backends with Google Cloud Platform (MBLTDev'14)
Mobile backends with Google Cloud Platform (MBLTDev'14)Mobile backends with Google Cloud Platform (MBLTDev'14)
Mobile backends with Google Cloud Platform (MBLTDev'14)Natalia Efimtseva
 

Similar to Exploring Google APIs 102: Cloud vs. non-GCP Google APIs (20)

Using Google (Cloud) APIs
Using Google (Cloud) APIsUsing Google (Cloud) APIs
Using Google (Cloud) APIs
 
Cloud computing overview & Technical intro to Google Cloud
Cloud computing overview & Technical intro to Google CloudCloud computing overview & Technical intro to Google Cloud
Cloud computing overview & Technical intro to Google Cloud
 
Exploring Google APIs with Python
Exploring Google APIs with PythonExploring Google APIs with Python
Exploring Google APIs with Python
 
Easy path to machine learning (2023-2024)
Easy path to machine learning (2023-2024)Easy path to machine learning (2023-2024)
Easy path to machine learning (2023-2024)
 
Exploring Google APIs with Python
Exploring Google APIs with PythonExploring Google APIs with Python
Exploring Google APIs with Python
 
Getting started using Google APIs (2019)
Getting started using Google APIs (2019)Getting started using Google APIs (2019)
Getting started using Google APIs (2019)
 
API Security - OWASP top 10 for APIs + tips for pentesters
API Security - OWASP top 10 for APIs + tips for pentestersAPI Security - OWASP top 10 for APIs + tips for pentesters
API Security - OWASP top 10 for APIs + tips for pentesters
 
Serverless Computing with Google Cloud
Serverless Computing with Google CloudServerless Computing with Google Cloud
Serverless Computing with Google Cloud
 
Powerful Google Cloud tools for your hack
Powerful Google Cloud tools for your hackPowerful Google Cloud tools for your hack
Powerful Google Cloud tools for your hack
 
Introduction to Google Cloud Endpoints: Speed Up Your API Development
Introduction to Google Cloud Endpoints: Speed Up Your API DevelopmentIntroduction to Google Cloud Endpoints: Speed Up Your API Development
Introduction to Google Cloud Endpoints: Speed Up Your API Development
 
Introduction to Google App Engine
Introduction to Google App EngineIntroduction to Google App Engine
Introduction to Google App Engine
 
Introduction to Cloud Computing with Google Cloud
Introduction to Cloud Computing with Google CloudIntroduction to Cloud Computing with Google Cloud
Introduction to Cloud Computing with Google Cloud
 
Introduction to serverless computing on Google Cloud
Introduction to serverless computing on Google CloudIntroduction to serverless computing on Google Cloud
Introduction to serverless computing on Google Cloud
 
Exploring Google (Cloud) APIs with Python & JavaScript
Exploring Google (Cloud) APIs with Python & JavaScriptExploring Google (Cloud) APIs with Python & JavaScript
Exploring Google (Cloud) APIs with Python & JavaScript
 
How Google Cloud Platform can help in the classroom/lab
How Google Cloud Platform can help in the classroom/labHow Google Cloud Platform can help in the classroom/lab
How Google Cloud Platform can help in the classroom/lab
 
Promise of DevOps
Promise of DevOpsPromise of DevOps
Promise of DevOps
 
Designing flexible apps deployable to App Engine, Cloud Functions, or Cloud Run
Designing flexible apps deployable to App Engine, Cloud Functions, or Cloud RunDesigning flexible apps deployable to App Engine, Cloud Functions, or Cloud Run
Designing flexible apps deployable to App Engine, Cloud Functions, or Cloud Run
 
Exploring MORE Google (Cloud) APIs with Python
Exploring MORE Google (Cloud) APIs with PythonExploring MORE Google (Cloud) APIs with Python
Exploring MORE Google (Cloud) APIs with Python
 
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
 
Mobile backends with Google Cloud Platform (MBLTDev'14)
Mobile backends with Google Cloud Platform (MBLTDev'14)Mobile backends with Google Cloud Platform (MBLTDev'14)
Mobile backends with Google Cloud Platform (MBLTDev'14)
 

More from wesley chun

Powerful Google developer tools for immediate impact! (2023-24 B)
Powerful Google developer tools for immediate impact! (2023-24 B)Powerful Google developer tools for immediate impact! (2023-24 B)
Powerful Google developer tools for immediate impact! (2023-24 B)wesley chun
 
Serverless computing with Google Cloud (2023-24)
Serverless computing with Google Cloud (2023-24)Serverless computing with Google Cloud (2023-24)
Serverless computing with Google Cloud (2023-24)wesley chun
 
Serverless Computing with Python
Serverless Computing with PythonServerless Computing with Python
Serverless Computing with Pythonwesley chun
 
Easy path to machine learning (2022)
Easy path to machine learning (2022)Easy path to machine learning (2022)
Easy path to machine learning (2022)wesley chun
 
Google... more than just a cloud
Google... more than just a cloudGoogle... more than just a cloud
Google... more than just a cloudwesley chun
 
Serverless computing with Google Cloud
Serverless computing with Google CloudServerless computing with Google Cloud
Serverless computing with Google Cloudwesley chun
 
Serverless Computing with Google Cloud
Serverless Computing with Google CloudServerless Computing with Google Cloud
Serverless Computing with Google Cloudwesley chun
 
Easy path to machine learning (Spring 2021)
Easy path to machine learning (Spring 2021)Easy path to machine learning (Spring 2021)
Easy path to machine learning (Spring 2021)wesley chun
 
Run your code serverlessly on Google's open cloud
Run your code serverlessly on Google's open cloudRun your code serverlessly on Google's open cloud
Run your code serverlessly on Google's open cloudwesley chun
 
Serverless Computing with Python
Serverless Computing with PythonServerless Computing with Python
Serverless Computing with Pythonwesley chun
 
Easy path to machine learning (Spring 2020)
Easy path to machine learning (Spring 2020)Easy path to machine learning (Spring 2020)
Easy path to machine learning (Spring 2020)wesley chun
 
Google Cloud @ Hackathons (2020)
Google Cloud @ Hackathons (2020)Google Cloud @ Hackathons (2020)
Google Cloud @ Hackathons (2020)wesley chun
 
Powerful Google Cloud tools for your hack (2020)
Powerful Google Cloud tools for your hack (2020)Powerful Google Cloud tools for your hack (2020)
Powerful Google Cloud tools for your hack (2020)wesley chun
 
Google Apps Script: Accessing G Suite & other Google services with JavaScript
Google Apps Script: Accessing G Suite & other Google services with JavaScriptGoogle Apps Script: Accessing G Suite & other Google services with JavaScript
Google Apps Script: Accessing G Suite & other Google services with JavaScriptwesley chun
 
Easy path to machine learning
Easy path to machine learningEasy path to machine learning
Easy path to machine learningwesley chun
 
Google's serverless journey: past to present
Google's serverless journey: past to presentGoogle's serverless journey: past to present
Google's serverless journey: past to presentwesley chun
 

More from wesley chun (16)

Powerful Google developer tools for immediate impact! (2023-24 B)
Powerful Google developer tools for immediate impact! (2023-24 B)Powerful Google developer tools for immediate impact! (2023-24 B)
Powerful Google developer tools for immediate impact! (2023-24 B)
 
Serverless computing with Google Cloud (2023-24)
Serverless computing with Google Cloud (2023-24)Serverless computing with Google Cloud (2023-24)
Serverless computing with Google Cloud (2023-24)
 
Serverless Computing with Python
Serverless Computing with PythonServerless Computing with Python
Serverless Computing with Python
 
Easy path to machine learning (2022)
Easy path to machine learning (2022)Easy path to machine learning (2022)
Easy path to machine learning (2022)
 
Google... more than just a cloud
Google... more than just a cloudGoogle... more than just a cloud
Google... more than just a cloud
 
Serverless computing with Google Cloud
Serverless computing with Google CloudServerless computing with Google Cloud
Serverless computing with Google Cloud
 
Serverless Computing with Google Cloud
Serverless Computing with Google CloudServerless Computing with Google Cloud
Serverless Computing with Google Cloud
 
Easy path to machine learning (Spring 2021)
Easy path to machine learning (Spring 2021)Easy path to machine learning (Spring 2021)
Easy path to machine learning (Spring 2021)
 
Run your code serverlessly on Google's open cloud
Run your code serverlessly on Google's open cloudRun your code serverlessly on Google's open cloud
Run your code serverlessly on Google's open cloud
 
Serverless Computing with Python
Serverless Computing with PythonServerless Computing with Python
Serverless Computing with Python
 
Easy path to machine learning (Spring 2020)
Easy path to machine learning (Spring 2020)Easy path to machine learning (Spring 2020)
Easy path to machine learning (Spring 2020)
 
Google Cloud @ Hackathons (2020)
Google Cloud @ Hackathons (2020)Google Cloud @ Hackathons (2020)
Google Cloud @ Hackathons (2020)
 
Powerful Google Cloud tools for your hack (2020)
Powerful Google Cloud tools for your hack (2020)Powerful Google Cloud tools for your hack (2020)
Powerful Google Cloud tools for your hack (2020)
 
Google Apps Script: Accessing G Suite & other Google services with JavaScript
Google Apps Script: Accessing G Suite & other Google services with JavaScriptGoogle Apps Script: Accessing G Suite & other Google services with JavaScript
Google Apps Script: Accessing G Suite & other Google services with JavaScript
 
Easy path to machine learning
Easy path to machine learningEasy path to machine learning
Easy path to machine learning
 
Google's serverless journey: past to present
Google's serverless journey: past to presentGoogle's serverless journey: past to present
Google's serverless journey: past to present
 

Recently uploaded

DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 

Exploring Google APIs 102: Cloud vs. non-GCP Google APIs

  • 1. Exploring Google APIs 102: Cloud APIs vs. non-GCP Google APIs Wesley Chun - @wescpy Principal, CyberWeb Consulting Adjunct CS Faculty, Foothill College
  • 2.
  • 3. Principal, CyberWeb Consulting ● Mission: help developers everywhere be successful using Google Cloud and other Google developer tools & APIs ● Focus: Python, Google Cloud (APIs, serverless, AI/ML), Google Workspace; Google cross-product use cases ● Services: training, technical talks, speak globally; make videos, create code samples, produce codelabs (free, self-paced, hands-on tutorials), publish blog posts About the speaker Previous experience / background ● Software Engineer & Developer Advocate ○ Google, Sun, HP, Cisco, EMC, Xilinx ○ Original Yahoo!Mail engineer/SWE ● Technical trainer, teacher, instructor ○ Teaching Math, Linux, Python since '83 ○ Adjunct CS Faculty at local SV college ● Python community member ○ Popular Core Python series author ○ Python Software Foundation Fellow ● AB (Math/CS) & CMP (Music/Piano), UC Berkeley and MSCS, UC Santa Barbara ● Adjunct Computer Science Faculty, Foothill College (Silicon Valley) Google APIs: why & agenda ● Build on knowledge from "Exploring Google APIs" talks ● Highlight use of Cloud vs. non-GCP Google APIs ● Key difference: the client library you use ○ Lower-level client libraries vs. product-level client libraries ● Many code samples illustrate Cloud & non-GCP Google API usage ● Awareness reduces friction/challenges from using multiple Google APIs 1 Google APIs introduction 2 Using Google APIs 4 Cloud APIs 5 Other Google APIs 6 Mix-n-match & inspiration 3 Workspace (non-GCP) APIs 7 Wrap-up
  • 4. 01 Intro to Google APIs Why are you here?
  • 6.
  • 7. Most products/APIs have "Quickstarts" ● Get started in 5 minutes! ● Available in most languages 02 Using Google APIs Getting started & the nuts-n-bolts
  • 8. The first word on Security Authentication ("authn") vs authorization ("authz") ● authn: you are who you say you are ○ login & password ○ handprint authentication ○ retina scan ● authz: okay, you are who you say you are, but can you haz data? ○ OAuth2 - mostly authz, but some authn ○ Mostly about 3rd-party access to data ○ Users must give YOUR code access to THEIR data ○ Most of the time when you see "auth", it refers to authz ○ With Google APIs: permission scopes or IAM permissions/roles ● Some refer to this as "consent" vs. "credentials…" which is which? General steps 1. Go to Cloud Console 2. Login to Google/Gmail account (Workspace domain may require admin approval) 3. Create project (per application) 4. Enable APIs to use 5. Enable billing (CC, Free Trial, etc.) 6. Download client library(ies) 7. Create & download credentials 8. Write code 9. Run code (may need to authorize) Google APIs: how to use Costs and pricing ● GCP: pay-per-use ● Google Workspace: subscription ● GCP Free Trial ($300/1Q, CC req'd) ● GCP "Always Free" tier ○ Most products have free tier ○ Daily or monthly quota ○ Must exceed to incur billing ● More on both programs at cloud.google.com/free *In your code 1. Import API client library 2. Create API client object 3. Use client to make API Calls
  • 9. Cloud/GCP console console.cloud.google.com ● Hub of all developer activity ● Applications == projects ○ New project for new apps ○ Projects have a billing acct ● Manage billing accounts ○ Financial instrument required ○ Personal or corporate credit cards, Free Trial, and education grants ● Access GCP product settings ● Manage users & security ● Manage APIs in devconsole Billing & budgeting (your favorite subjects)
  • 10. Collaborating & sharing ● Sharing: great way to see student work or have teams work on one project ● IAM (Identity & Access Mgmt): owner & editor most useful access levels cloud.google.com/iam/docs/understanding-roles ● View application statistics ● En-/disable Google APIs ● Obtain application credentials Using Google APIs goo.gl/RbyTFD API manager aka Developers Console (devconsole) console.developers.google.com
  • 11. Three different credentials types ● Simple: API keys (to access public data) ○ Simplest form of authorization: an API key; tied to a project ○ Allows access to public data ○ Do not put in code, lose, or upload to GitHub! (can be restricted however) ○ Supported by: Google Maps, (some) YouTube, (some) GCP, etc. ● Authorized: OAuth client IDs (to access data owned by [human] user) ○ Provides additional layer of security via OAuth2 (RFC 6749) ○ Owner must grant permission for your app to access their data ○ Access granularity determined by requested permissions (user scopes) ○ Supported by: Google Workspace, (some) YouTube, (some) GCP, etc. ● Authorized: service accounts (to access data owned by an app/robot user) ○ Provides additional layer of security via OAuth2 or JWT (RFC 7519) ○ Project owning data grants permission implicitly; requires public-private key-pair ○ Access granularity determined by Cloud IAM permissions granted to service account key-pair ○ Supported by: GCP, (some) Google Workspace, etc.
  • 12. Two different client library "styles" ● "Platform-level" client libraries (lower-level) ○ Supports multiple products as a "lowest-common denominator" ○ Manage API service endpoints (setup & use) ○ Manage authorization (API keys, OAuth client IDs, service accounts) ○ Google Workspace, Google Analytics, YouTube, Google Ads APIs, GCP, etc. ○ Install: developers.google.com/api-client-library ● "Product-level" client libraries (higher-level) ○ Custom client libraries made specifically for each product ○ Managing API service endpoints & security mostly taken care of ○ Only need to create a "client" to use API services ○ Install (Cloud/GCP & Firebase): cloud.google.com/apis/docs/cloud-client-libraries ○ Install (Maps): developers.google.com/places/web-service/client-library ● Some Google APIs families support both, e.g., Cloud
  • 13. & Google APIs client libraries for many languages; demos in developers.google.com/api- client-library cloud.google.com/apis/docs /cloud-client-libraries SIMPLE AUTHORIZED Which do you choose?
  • 14. from googleapiclient import discovery # Can copy from DevConsole, or better yet, put into Secret # Manager, encrypted/secure store/DB, creds svr, proxy, etc. from settings import API_KEY # API information, i.e., (API='language', VERSION='v1') SERVICE = discovery.build(API, VERSION, developerKey=API_KEY) Simple API access(lower-level, generic) import googlemaps # Can copy from DevConsole, or better yet, put into Secret # Manager, encrypted/secure store/DB, creds svr, proxy, etc. from settings import API_KEY GMAPS = googlemaps.Client(key=API_KEY) print('n** Geocode address:') rsp = GMAPS.geocode('1600 Amphitheatre Pkwy 94043') latlong = rsp[0]['geometry']['location'] print('tGeocode:', latlong['lat'], ',', latlong['lng']) Simple API access(higher-level, specific)
  • 15. Google OAuth2 process ● Goal: valid access token == 3rd-party API data access ● How OAuth2 works (in general) ○ Step 1: Create OAuth2 credentials in DevConsole ○ Step 2: Send credentials to get access & refresh tokens ○ Step 3: Use access token to make authorized API calls ○ Step 4: Access tokens expire; use refresh to get new one ● developers.google.com/identity/protocols/OAuth2 ● Other APIs will be similar with some differences (User-)authorized API access(lower-level, older, generic) OAuth boilerplate goo.gl/KMfbeK from googleapiclient import discovery from httplib2 import Http from oauth2client import file, client, tools SCOPES = ... # at least one (string or array of strings) # 'storage.json' - where to store OAuth2 tokens from API # 'client_secret.json' - OAuth2 client ID & secret (download from DevConsole) store = file.Storage('storage.json') creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets('client_secret.json', SCOPES) creds = tools.run_flow(flow, store) # create API service endpoint; for example: API='sheets', VERSION='v4' SERVICE = discovery.build(API, VERSION, http=creds.authorize(Http()))
  • 16. (User-)authorized API access(lower-level, newer, generic) from googleapiclient import discovery from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request from google.oauth2 import credentials SCOPES = ... # at least one (string or array of strings) # 'storage.json' - where to store OAuth2 tokens from API # 'client_secret.json' - OAuth2 client ID & secret (download from DevConsole) TOKENS = 'storage.json' # OAuth2 token storage if os.path.exists(TOKENS): creds = credentials.Credentials.from_authorized_user_file(TOKENS) if not (creds and creds.valid): if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES) creds = flow.run_local_server() with open(TOKENS, 'w') as token: token.write(creds.to_json()) # create API service endpoint; for example: API='sheets', VERSION='v4' SERVICE = discovery.build(API, VERSION, http=creds.authorize(Http())) Service account access(lower-level, scopes, older, generic) from googleapiclient import discovery from httplib2 import Http from oauth2client import service_account SCOPES = ... # at least one (string or array of strings) # 'svc_acct.json' - OAuth2 service acct creds (download from DevConsole) creds = service_account.ServiceAccountCredentials.from_json_keyfile_name( 'svc_acct.json', SCOPES) # create API service endpoint; for example: API='sheets', VERSION='v4' SERVICE = discovery.build(API, VERSION, http=creds.authorize(Http()))
  • 17. Service account access(lower-level, svc acct, older, generic) from googleapiclient import discovery from oauth2client import client . . . # Creds file or (better) use Application Default Credentials (ADC) # see cloud.google.com/docs/authentication/application-default-credentials creds = client.GoogleCredentials.get_application_default() # create API service endpoint; for example: API='sheets', VERSION='v4' SERVICE = discovery.build(API, VERSION, credentials=creds) from googleapiclient import discovery import google.auth . . . # Creds file or (better) use Application Default Credentials (ADC) # see cloud.google.com/docs/authentication/application-default-credentials creds, _proj_id = google.auth.default() # create API service endpoint; for example: API='sheets', VERSION='v4' SERVICE = discovery.build(API, VERSION, credentials=creds) Service account access(lower-level, svc acct, newer, generic)
  • 18. from google.cloud import storage # Implicit ADC usage (no security code visible!) GCS = storage.Client() # uses ADC (app default creds) blob = GCS.bucket(bucket).blob(FILENAME) # destination file print('n** Uploading to %r' % BUCKET) blob.upload_from_filename(FILENAME) # origin file Service account access(higher-level, svc acct, newer, specific) OAuth2 or API key HTTP-based REST APIs 1 HTTP 2 Google APIs request-response workflow ● Application makes request ● Request received by service ● Process data, return response ● Results sent to application (typical client-server model)
  • 19. 03 Google Workspace (formerly G Suite) APIs Examples of non-Cloud Google APIs Google Workspace Top-level documentation and comprehensive developers overview video at developers.google.com/gsuite (formerly G Suite and Google Apps) APIs
  • 20. List (first 100) files/folders in Drive (older, OAuth2) from __future__ import print_function from googleapiclient import discovery from httplib2 import Http from oauth2client import file, client, tools SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly' store = file.Storage('storage.json') creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets('client_secret.json', SCOPES) creds = tools.run_flow(flow, store) DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http())) files = DRIVE.files().list().execute().get('files', []) for f in files: print(f['name'], f['mimeType']) Listing your files goo.gl/ZIgf8k List (first 100) files/folders in Drive (newer, OAuth2) from __future__ import print_function import os.path import pickle from google.auth.transport.requests import Request from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient import discovery creds = None SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly' TOKENS = 'token.p' # where to store access & refresh tokens if os.path.exists(TOKENS): with open(TOKENS, 'rb') as token: creds = pickle.load(token) if not (creds and creds.valid): if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES) creds = flow.run_local_server() with open(TOKENS, 'wb') as token: pickle.dump(creds, token) DRIVE = discovery.build('drive', 'v3', credentials=creds) files = DRIVE.files().list().execute().get('files', []) for f in files: print(f['name'], f['mimeType']) developers.google.com/drive/api/v3/quickstart/python
  • 21. List (first 100) files/folders in Drive (newer, svc acct) from __future__ import print_function from googleapiclient import discovery import google.auth creds, _proj_id = google.auth.default() # ADC; shared w/SA dr_client = discovery.build('drive', 'v4', credentials=creds) files = dr_client.files().list().execute().get('files', []) for f in files: # fields returned: mimeType, kind, id, name print(f['name'], f['mimeType']) Automate photo albums OR
  • 22. Try our Node.js customized reporting tool codelab: g.co/codelabs/sheets Why use the Sheets API? data visualization customized reports Sheets as a data source Migrate SQL data to a Sheet # read SQL data then create new spreadsheet & add rows into it FIELDS = ('ID', 'Customer Name', 'Product Code', 'Units Ordered', 'Unit Price', 'Status') cxn = sqlite3.connect('db.sqlite') cur = cxn.cursor() rows = cur.execute('SELECT * FROM orders').fetchall() cxn.close() rows.insert(0, FIELDS) DATA = {'properties': {'title': 'Customer orders'}} SHEET_ID = SHEETS.spreadsheets().create(body=DATA, fields='spreadsheetId').execute().get('spreadsheetId') SHEETS.spreadsheets().values().update(spreadsheetId=SHEET_ID, range='A1', body={'values': rows}, valueInputOption='RAW').execute() Migrate SQL data to Sheets goo.gl/N1RPwC
  • 23. Try our Node.js BigQuery GitHub license analyzer codelab: g.co/codelabs/slides Why use the Slides API? data visualization presentable reports Try our Node.js Markdown-to-Google-Slides generator: github.com/gsuitedevs/md2googleslides Why use the Slides API? customized presentations
  • 24. Replace text & images from template deck requests = [ # (global) search-and-replace text {'replaceAllText': { 'findText': '{{TITLE}}', 'replaceText': 'Hello World!', }}, # replace text-based image placeholders (global) {'replaceAllShapesWithImage': { 'imageUrl': IMG_URL, # link to product logo 'replaceMethod': 'CENTER_INSIDE', 'containsText': {'text': '{{LOGO}}'}, }}, ] SLIDES.presentations().batchUpdate(body={'requests': requests}, presentationId=DECK_ID, fields='').execute() Replacing text and images goo.gl/o6EFwk Display Gmail threads (& # of messages) # get all "busy" mail threads & display (non-blank) Subject lines threads = GMAIL.users().threads().list(userId='me', fields='threads').execute().get('threads', []) for thread in threads: tdata = GMAIL.users().threads().get(userId='me', id=thread['id'], format='metadata', metadataHeaders=['subject'], fields='messages/payload/headers(name,value)').execute() if 'messages' not in tdata: continue if len(tdata['messages']) > 10: msg = tdata['messages'][0]['payload'] subject = '' for header in msg['headers']: if header['name'] == 'Subject': subject = header['value'] break if subject: print('%2d message(s) in thread: %s' % ( len(tdata['messages']), subject)) Gmail threads goo.gl/pFYUQ2
  • 25. Creating events in Calendar # define event data, then create event TIMEZONE = 'America/Los_Angeles' EVENT = { 'summary': 'Dinner with friends', 'start': {'dateTime': '2017-06-14T19:00:00', 'timeZone': TIMEZONE}, 'end': {'dateTime': '2017-06-14T22:00:00', 'timeZone': TIMEZONE}, 'attendees': [ {'email': 'friend1@example.com'}, {'email': 'friend2@example.com'}, ], } GCAL.events().insert(calendarId='primary', body=EVENT, sendNotifications=True, fields='').execute() Modifying and recurring events goo.gl/J2XkXc Creating events goo.gl/KuYMiq + Mail merge = Mail merge goo.gle/2KrPNeG
  • 26. Mail merge (get data from Sheets) TMPL_ID = 'YOUR_DOCS_TEMPLATE' SHEETS_ID = 'YOUR_DATA_SPREADSHEET' SCOPES = ( 'https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/documents', 'https://www.googleapis.com/auth/spreadsheets', ) HTTP = creds.authorize(Http()) # ↙↙↙ how to access multiple APIs DRIVE = discovery.build('drive', 'v3', http=HTTP) DOCS = discovery.build('docs', 'v1', http=HTTP) SHEETS = discovery.build('sheets', 'v4', http=HTTP) # get data from spreadsheet, copy & merge template for each row rows = SHEETS.spreadsheets().values().get(range='Sheet1', spreadsheetId=SHEETS_ID).execute().get('values')[1:] for row in rows: DOCS_ID = DRIVE.files().copy(body={'name': 'Merged form letter'}, fileId=TMPL_ID, fields='id').execute().get('id') Mail merge (template search & replace) requests = [ # (global) search-and-replace text {'replaceAllText': { 'containsText': {'text': '{{NAME}}'}, 'replaceText': row['name'], }}, ] DOCS.documents().batchUpdate(body={'requests': requests}, documentId=DOC_ID, fields='').execute()
  • 27. 04 Google Cloud APIs Can use either Cloud and/or lower-level client libraries
  • 28. Storage: listing buckets from __future__ import print_function from googleapiclient import discovery GCS = discovery.build('storage', 'v1') BUCKET = YOUR_BUCKET # send bucket name & return fields to API, display results print('n** Objects in bucket %r...' % BUCKET) FIELDS = 'items(name,size)' files = GCS.objects().list(bucket=BUCKET, fields=FIELDS ).execute().get('items') or [{'name': '(none)', 'size': 'NaN'}] for f in files: print(' %s (%s)' % (f['name'], f['size'])) Storage: listing buckets from __future__ import print_function from google.cloud import storage GCS = storage.Client() BUCKET = YOUR_BUCKET # send bucket name & return fields to API, display results print('n** Objects in bucket %r...' % BUCKET) for f in GCS.list_blobs(BUCKET): print(' %s (%s)' % (f['name'], f['size']))
  • 29. Firestore (Datastore): object create & query from datetime import datetime from google.cloud import datastore DATASTORE = datastore.Client() # create Cloud Datastore client def store_visit(remote_addr, user_agent): 'create new Visit entity in Datastore' entity = datastore.Entity(key=DATASTORE.key('visit')) entity.update({'timestamp': datetime.now(), 'visitor': '{}: {}'.format(remote_addr, user_agent)}) DATASTORE.put(entity) def fetch_visits(limit): 'get most recent Visits' query = DATASTORE.query(kind='visit') query.order = ['-timestamp'] return query.fetch(limit=limit) const {DatastoreClient} = require('@google-cloud/datastore); const DATASTORE = new DatastoreClient(); // create new Visit entity in Datastore async function storeVisit(remote_addr, user_agent) { const entity = { key: DATASTORE.key(['Visit']), data: { visitor: `${remote_addr}: ${user_agent}`, timestamp: new Date() } }; await DATASTORE.save(entity); // get most recent Visits async function fetchVisits(limit) { const query = DATASTORE.createQuery('Visit') .order('timestamp', {descending: true}).limit(limit); const [results] = await DATASTORE.runQuery(query); Firestore (Datastore): object create & query
  • 30. BigQuery: querying Shakespeare words TITLE = "The top 10 most common words in all of Shakespeare's works" QUERY = ''' SELECT LOWER(word) AS word, sum(word_count) AS count FROM [bigquery-public-data:samples.shakespeare] GROUP BY word ORDER BY count DESC LIMIT 10 ''' BQ = discovery.build('bigquery', 'v2', http=creds.authorize(Http())) rsp = BQ.query(body={'query': QUERY}, projectId=PROJ_ID).execute() print('n*** Results for %r:n' % TITLE) for col in rsp['schema']['fields']: # HEADERS print(col['name'].upper(), end='t') print() for row in rsp['rows']: # DATA for col in row['f']: print(col['v'], end='t') print() BigQuery: querying Shakespeare words from google.cloud import bigquery TITLE = "The most common words in all of Shakespeare's works" QUERY = ''' SELECT LOWER(word) AS word, sum(word_count) AS count FROM `bigquery-public-data.samples.shakespeare` GROUP BY word ORDER BY count DESC LIMIT 10 ''' rsp = bigquery.Client().query(QUERY).result() print('n*** Results for %r:n' % TITLE) print('t'.join(col.name.upper() for col in rsp.schema)) # HEADERS print('n'.join('t'.join(str(x) for x in row.values()) for row in rsp)) # DATA
  • 31. Top 10 most common Shakespeare words $ python bq_shake.py *** Results for "The most common words in all of Shakespeare's works": WORD COUNT the 29801 and 27529 i 21029 to 20957 of 18514 a 15370 you 14010 my 12936 in 11722 that 11519 ● BigQuery public data sets: cloud.google.com/bigquery/public-data ● BQ sandbox (1TB/mo free): cloud.google.com/bigquery/docs/sandbox (see blog post) ● Other public data sets: cloud.google.com/public-datasets (Google Cloud), research.google/tools/datasets (Google Research), and Kaggle (kaggle.com) ● COVID-19 BigQuery data sets ○ How to use our data sets (see blog post) ○ JHU Coronavirus COVID-19 Global Cases data set ○ List of all COVID-19 data sets ● Cloud Life Sciences API: cloud.google.com/life-sciences (see blog post) ● Cloud Healthcare API: cloud.google.com/healthcare (see blog post) BigQuery and public data sets
  • 32. IMG = 'gs://cloud-samples-data/vision/using_curl/shanghai.jpeg' body = {'requests': [{ 'image': {'source': {'imageUri': IMG}}, 'features': [{'type': 'LABEL_DETECTION'}], }]} VISION = discovery.build('vision', 'v1', developerKey=API_KEY) labeling = VISION.images().annotate(body=body).execute().get('responses') for labels in labeling: if 'labelAnnotations' in labels: print('** Labels detected (and confidence score):') for label in labels['labelAnnotations']: print(label['description'], '(%.2f%%)' % (label['score']*100.)) Vision: label annotation/object detection from google.cloud import vision image_uri = 'gs://cloud-samples-data/vision/using_curl/shanghai.jpeg' client = vision.ImageAnnotatorClient() image = vision.types.Image() image.source.image_uri = image_uri response = client.label_detection(image=image) print('Labels (and confidence score):') print('=' * 30) for label in response.label_annotations: print(label.description, '(%.2f%%)' % (label.score*100.)) Vision: label annotation/object detection
  • 33. $ python3 label-detect.py Labels (and confidence score): ============================== People (95.05%) Street (89.12%) Mode of transport (89.09%) Transport (85.13%) Vehicle (84.69%) Snapshot (84.11%) Urban area (80.29%) Infrastructure (73.14%) Road (72.74%) Pedestrian (68.90%) Vision: label annotation/object detection g.co/codelabs/vision-python 05 Other Google APIs Use lower-level or product-level client libraries (see documentation)
  • 34. Other Google APIs & platforms ● Firebase (mobile development platform + RT DB; ML Kit) ○ firebase.google.com & firebase.google.com/docs/ml-kit ● Google Data Studio (data visualization, dashboards, etc.) ○ datastudio.google.com/overview ○ goo.gle/datastudio-course ● Actions on Google/Assistant/DialogFlow (voice apps) ○ developers.google.com/actions ● YouTube (Data, Analytics, and Livestreaming APIs) ○ developers.google.com/youtube ● Google Maps (Maps, Routes, and Places APIs) ○ developers.google.com/maps ● Flutter (native apps [Android, iOS, web] w/1 code base[!]) ○ flutter.dev Search YouTube for videos from __future__ import print_function from googleapiclient import discovery from settings import API_KEY QUERY = 'python -snake' trim = lambda x, ct: ('%s%s' % (x[:ct], '...' if len(x)>ct else '')).ljust(ct+3) print('n** Searching for %r videos...' % QUERY) YOUTUBE = discovery.build('youtube', 'v3', developerKey=API_KEY) res = YOUTUBE.search().list(q=QUERY, type='video', part='id,snippet').execute().get('items', []) for item in res: print('http://youtu.be/%st%s' % ( trim(item['id']['videoId'], 24), trim(item['snippet']['title'], 48)))
  • 35. Maps APIs geocoding & places queries import googlemaps from settings import API_KEY GMAPS = googlemaps.Client(key=API_KEY) print('n** Geocode address:') rsp = GMAPS.geocode('1600 Amphitheatre Pkwy 94043') latlong = rsp[0]['geometry']['location'] print('tGeocode:', latlong['lat'], ',', latlong['lng']) print('n** Address lookup:') rsp = GMAPS.reverse_geocode((37.4222934, -122.0841409)) print('tAddress:', rsp[0]['formatted_address']) print('n** Place query:') pl_id = GMAPS.find_place('Villa Tugendhat', input_type='textquery')['candidates'][0]['place_id'] place = GMAPS.place(pl_id)['result'] print('tPlace:t', place['name']) print('tAddress:t', place['formatted_address']) print('tWebsite:t', place['website']) print('tMaps URL:t', place['url']) $ python3 maps-demo-pub.py ** Geocode address: Geocode: 37.4222934 , -122.0841409 ** Address lookup: Address: 1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA ** Place query: Place: Villa Tugendhat Address: Černopolní 45, 613 00 Brno, Czechia Website: tugendhat.eu Maps URL: maps.google.com/?cid=5889127146370224362 Google Maps APIs ● Directions API ● Distance Matrix API ● Elevation API ● Geocoding API ● Geolocation API ● Time Zone API ● Roads API ● Places API ● Maps Static API Google Apps Script Customized serverless JS runtime for automation, and extension and integration with Google Workspace (formerly G Suite) and other Google & external services
  • 37. Sheets-bound “Hello World!” Apps Script intro goo.gl/1sXeuD What can you do with this?
  • 38. Accessing maps from spreadsheets?!? goo.gl/oAzBN9 This… with help from Google Maps & Gmail function sendMap() { var sheet = SpreadsheetApp.getActiveSheet(); var address = sheet.getRange("A2").getValue(); var map = Maps.newStaticMap().addMarker(address); GmailApp.sendEmail('friend@example.com', 'Map', 'See below.', {attachments:[map]}); } JS g.co/codelabs/apps-script-intro
  • 39. 06 Mix-n-match & inspiration Use Cloud and lower-level (LL) client libraries or just LL Cloud image processing workflow Archive and analyze Google Workspace (formerly G Suite) images with GCP
  • 40.
  • 41. Image: Gerd Altmann from Pixabay
  • 42. Cloud Vision Google Workspace GCP Cloud image processing workflow Cloud Storage Drive Sheets Archive image Categorize image Record results
  • 43. Cloud image processing workflow from __future__ import print_function import argparse, base64, io, webbrowser from googleapiclient import discovery, http from httplib2 import Http from oauth2client import file, client, tools k_ize = lambda b: '%6.2fK' % (b/1000.) # bytes to kBs FILE = 'YOUR_IMG_ON_DRIVE' BUCKET = 'YOUR_BUCKET_NAME' PARENT = '' # YOUR IMG FILE PREFIX SHEET = 'YOUR_SHEET_ID' TOP = 5 # TOP # of VISION LABELS TO SAVE DEBUG = False # process credentials for OAuth2 tokens SCOPES = ( 'https://www.googleapis.com/auth/drive.readonly', 'https://www.googleapis.com/auth/devstorage', 'https://www.googleapis.com/auth/cloud-vision', 'https://www.googleapis.com/auth/spreadsheets', ) store = file.Storage('storage.json') creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets( 'client_secret.json', SCOPES) creds = tools.run_flow(flow, store) # create API service endpoints HTTP = creds.authorize(Http()) DRIVE = discovery.build('drive', 'v3', http=HTTP) GCS = discovery.build('storage', 'v1', http=HTTP) VISION = discovery.build('vision', 'v1', http=HTTP) SHEETS = discovery.build('sheets', 'v4', http=HTTP) Cloud image processing workflow from __future__ import print_function import argparse, base64, io, webbrowser from googleapiclient import discovery, http from httplib2 import Http from oauth2client import file, client, tools from google.cloud import storage, vision k_ize = lambda b: '%6.2fK' % (b/1000.) # bytes to kBs FILE = 'YOUR_IMG_ON_DRIVE' BUCKET = 'YOUR_BUCKET_NAME' PARENT = '' # YOUR IMG FILE PREFIX SHEET = 'YOUR_SHEET_ID' TOP = 5 # TOP # of VISION LABELS TO SAVE DEBUG = False # process credentials for OAuth2 tokens SCOPES = ( 'https://www.googleapis.com/auth/drive.readonly', 'https://www.googleapis.com/auth/devstorage', 'https://www.googleapis.com/auth/cloud-vision', 'https://www.googleapis.com/auth/spreadsheets', ) store = file.Storage('storage.json') creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets( 'client_secret.json', SCOPES) creds = tools.run_flow(flow, store) # create API service endpoints HTTP = creds.authorize(Http()) DRIVE = discovery.build('drive', 'v3', http=HTTP) GCS = storage.Client() VISION = vision.ImageAnnotatorClient() SHEETS = discovery.build('sheets', 'v4', http=HTTP)
  • 44. Cloud image processing workflow def drive_get_file(fname): rsp = DRIVE.files().list(q="name='%s'" % fname).execute().get['files'][0] fileId, fname, mtype = rsp['id'], rsp['name'], rsp['mimeType'] blob = DRIVE.files().get_media(fileId).execute() return fname, mtype, rsp['modifiedTime'], blob def gcs_blob_upload(fname, bucket, blob, mimetype): body = {'name': fname, 'uploadType': 'multipart', 'contentType': mimetype} return GCS.objects().insert(bucket, body, blob).execute() def vision_label_img(img, top): body = {'requests': [{'image': {'content': img}, 'features': [{'type': 'LABEL_DETECTION', 'maxResults': top}]}]} rsp = VISION.images().annotate( body=body).execute().get['responses'][0] return ', '.join('%s (%.2f%%)' % (label['description'], label['score']*100.) for label in rsp['labelAnnotations']) def sheet_append_row(sheet, row): rsp = SHEETS.spreadsheets().values().append( spreadsheetId=sheet, range='Sheet1', body={'values': rows}).execute() return rsp.get('updates').get('updatedCells') def main(fname, bucket, sheet_id, top): fname, mtype, ftime, data = drive_get_img(fname) gcs_blob_upload(fname, bucket, data, mtype) rsp = vision_label_img(data, top) sheet_append_row(sheet_id, [fname, mtype, ftime, len(data), rsp]) API method calls in Bold Driver calls in Bold Italics Cloud image processing workflow def drive_get_file(fname): rsp = DRIVE.files().list(q="name='%s'" % fname).execute().get['files'][0] fileId, fname, mtype = rsp['id'], rsp['name'], rsp['mimeType'] blob = DRIVE.files().get_media(fileId).execute() return fname, mtype, rsp['modifiedTime'], blob def gcs_blob_upload(fname, bucket, blob, mimetype): blob = GCS.bucket(bucket).blob(fname) blob.upload_from_string(media, mimetype) return {'bucket': bucket, 'name': fname} def vision_label_img(img, top): image = vision.types.Image(content=img) labels = VISION.label_detection(image=image, max_results=top).label_annotations return ', '.join('(%.2f%%) %s' % ( label.score*100., label.description) for label in labels) def sheet_append_row(sheet, row): rsp = SHEETS.spreadsheets().values().append( spreadsheetId=sheet, range='Sheet1', body={'values': rows}).execute() return rsp.get('updates').get('updatedCells') def main(fname, bucket, sheet_id, top): fname, mtype, ftime, data = drive_get_img(fname) gcs_blob_upload(fname, bucket, data, mtype) rsp = vision_label_img(data, top) sheet_append_row(sheet_id, [fname, mtype, ftime, len(data), rsp]) API method calls in Bold Driver calls in Bold Italics
  • 45. ● Project goal: Imagining an actual enterprise use case and solve it! ● Specific goals: free-up highly-utilized resource, archive data to colder/cheaper storage, analyze images, generate report for mgmt ● Download image binary from Google Drive ● Upload object to Cloud Storage bucket ● Send payload for analysis by Cloud Vision ● Write back-up location & analysis results into Google Sheets ● Blog post: goo.gle/3nPxmlc (original post); Cloud X-post ● Codelab: free, online, self-paced, hands-on tutorial ● g.co/codelabs/drive-gcs-vision-sheets ● Application source code ● github.com/googlecodelabs/analyze_gsimg App summary 07 Wrap-up Summary & resources
  • 46. Session Summary ● Google provides more than just apps ○ More than search, YouTube, Android, Chrome, and Gmail/Docs ○ Much Google techology available to developers via APIs ● Google Cloud vs. non-Cloud Google APIs ○ Alas, developer experience differs between product families ○ Some products have higher-level product client libraries ○ Others require use of lower-level client libraries ■ Lower-level may be useful as lowest common denominator ● Inconsistency due to various reasons: budget, timeframe, priorities, etc. ● Interesting possibilities using multiple Google product APIs Client libraries & credentials review ● Two different client library types ○ Platform-level client libraries (lower-level) ■ Multiple product groups as a "lowest-common denominator" ■ Install: developers.google.com/api-client-library ○ Product-level client libraries (higher-level) ■ Custom client libraries made specifically for 1 product or product group ■ Found on product or product group page(s) ● Three different credentials types ○ Simple: API keys (access public data) ■ Simplest form of authorization: an API key; tied to a project ○ Authorized: OAuth client IDs (access data owned by [human] user) ■ Provides additional layer of security via OAuth2 (RFC 6749) ○ Authorized: service accounts (access data owned by an app/robot user) ■ Provides additional layer of security via OAuth2 or JWT (RFC 7519)
  • 47. ● Documentation (most APIs have "Quickstarts") ○ Google Cloud: cloud.google.com/{docs,appengine,functions,run,vision,automl,translate,language, speech,texttospeech,video-intelligence,firestore,bigquery,compute,storage,gpu,tpu} ○ Google Workspace: developers.google.com/{gsuite,drive,calendar,gmail,docs,sheets,slides,apps-script} ● Google codelabs (self-paced, hands-on tutorials): need a Google account, always free ○ GWS: g.co/codelabs/gsuite-apis-intro (Drive), g.co/codelabs/sheets (Sheets), g.co/codelabs/slides (Slides) ○ GCP: gcplab.me or g.co/codelabs/cloud ● Cloud Skills Boost (codelabs by QwikLabs): don't need a Google acct; typically not free ○ cloudskillsboost.google or google.qwiklabs.com ● Videos: youtube.com/GoogleCloudPlatform (Cloud) and goo.gl/JpBQ40 (Workspace) ● Code samples: github.com/GoogleCloudPlatform (Cloud) and github.com/googleworkspace (Workspace) ● Cloud Free Trial (new users) and Always Free (daily/monthly tier) programs: cloud.google.com/free ● Know AWS/Azure? Compare with Google Cloud products at cloud.google.com/docs/compare/aws ● Language support: cloud.google.com/{python,java,nodejs,go,php,ruby,dotnet} Additional resources "Free" … what is and what isn't? ● GCP free programs ○ Free Trial ■ $300USD credit good for 3 months ■ Billing/credit card required; expires ○ "Always Free" tier ■ Some GCP products free up to usage limits ■ Independent of Free Trial & education grants ■ Billing/credit card required; no expiration (subject to change) ○ cloud.google.com/free ● Google Workspace APIs/platforms ○ "Free" up to usage limits ○ Covered by monthly subscription fee ○ Pay-for or free Gmail consumer accts ○ Billing required; no expiration ● GCP education (teaching & research) grants ○ (Your) credit card NOT required; expires ○ Meant to provide initial "free" usage for coursework or research ○ cloud.google.com/edu $$ FREE $$
  • 48. Bring me to your organization ... it's my job to help you! ● "TOI" tech talks ● Half- or full-day seminars ● Hands-on "codelab" workshops ● Multi-day training courses ● Migration strategy & planning ● cyberwebconsulting.com Thank you! Questions? Wesley Chun @wescpy cyberwebconsulting.com Progress bars: goo.gl/69EJVw