Programmatically get the list of versions from appengine - python

I'd like to get a list of deployed versions from appengine, either from the remote API or via appcfg.py. I can't seem to find any way to do it, certainly not a documented way. Does anyone know of any way to do this (even undocumented)?

You can list deployed versions in the admin console under "Admin Logs". Short of screen-scraping this page, there's no way to access this data programmatically.
You can submit this as an enhancement request to the issue tracker.

I was able to do this by copying some of the RPC code from appcfg.py into my application. I posted up this gist that goes into detail on how to do this, but I will repeat them here for posterity.
Install the python API client. This will give you the OAuth2 and httplib2 libraries you need to interact with Google's RPC servers from within your application.
Copy this file from the GAE SDK installed on your development machine: google/appengine/tools/appengine_rpc_httplib2.py into your GAE webapp.
Obtain a refresh token by executing appcfg.py list_versions . --oauth2 from your local machine. This will open a browser so you can login to your Google Account. Then, you can find the refresh_token in ~/.appcfg_oauth2_tokens
Modify and run the following code inside of a web handler:
Enjoy.
from third_party.google_api_python_client import appengine_rpc_httplib2
# Not-so-secret IDs cribbed from appcfg.py
# https://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/tools/appcfg.py#144
APPCFG_CLIENT_ID = '550516889912.apps.googleusercontent.com'
APPCFG_CLIENT_NOTSOSECRET = 'ykPq-0UYfKNprLRjVx1hBBar'
APPCFG_SCOPES = ['https://www.googleapis.com/auth/appengine.admin']
source = (APPCFG_CLIENT_ID,
APPCFG_CLIENT_NOTSOSECRET,
APPCFG_SCOPES,
None)
rpc_server = appengine_rpc_httplib2.HttpRpcServerOauth2(
'appengine.google.com',
# NOTE: Here's there the refresh token is used
"your OAuth2 refresh token goes here",
"appcfg_py/1.8.3 Darwin/12.5.0 Python/2.7.2.final.0",
source,
host_override=None,
save_cookies=False,
auth_tries=1,
account_type='HOSTED_OR_GOOGLE',
secure=True,
ignore_certs=False)
# NOTE: You must insert the correct app_id here, too
response = rpc_server.Send('/api/versions/list', app_id="khan-academy")
# The response is in YAML format
parsed_response = yaml.safe_load(response)
if not parsed_response:
return None
else:
return parsed_response

Looks like Google has recently released a get_versions() function in the google.appengine.api.modules package. I recommend using that over the hack I implemented in my other answer.
Read more at:
https://developers.google.com/appengine/docs/python/modules/functions

Related

How to get a GCP identity-token programmatically with python

What is the python programmatic alternative to the gcloud command line gcloud auth print-identity-token?
I am trying to invoke Google Cloud Function by http trigger (only for auth users) and i need to pass the identity token in the Authentication header. I have method which works great when i run the code on GCP app engine. However, i struggle to find a way to get this identity token when i run the program on my own machine (where i can create the token with gcloud command line gcloud auth print-identity-token)
I found how to create access-token according to this answer but i didn't managed to understand how can i create identity-token.
Thank you in advance!
Great topic! And it's a long long way, and months of tests and discussion with Google.
TL;DR: you can't generate an identity token with your user credential, you need to have a service account (or to impersonate a service) to generate an identity token.
If you have a service account key file, I can share a piece of code to generate an identity token, but generating and having a service account key file is globally a bad practice.
I released an article on this and 2 merge requests to implement an evolution in the Java Google auth library (I'm more Java developer that python developer even if I also contribute to python OSS project) here and here. You can read them if you want to understand what is missing and how works the gcloud command today.
On the latest merge request, I understood that something is coming from google, internally, but up to now, I didn't see anything...
If you have a service account you can impersonate this is one way to get an ID token in Python from a local/dev machine.
import google.auth
from google.auth.transport.requests import AuthorizedSession
def impersonated_id_token():
credentials, project = google.auth.default(scopes=['https://www.googleapis.com/auth/cloud-platform'])
authed_session = AuthorizedSession(credentials)
sa_to_impersonate = "<SA_NAME>#<GCP_PROJECT>.iam.gserviceaccount.com"
request_body = {"audience": "<SOME_URL>"}
response = authed_session.post( f'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/{sa_to_impersonate}:generateIdToken',request_body)
return response
if __name__ == "__main__":
print(impersonated_id_token().json())

Gaining authorization to modify Spotify playlists using spotipy for Python3

I'm currently attempting to use spotipy, a python3 module, to access and edit my personal Spotify premium account. I've followed the tutorial on https://github.com/plamere/spotipy/blob/master/docs/index.rst using the util.prompt_for_user_token method by entering the necessary parameters directly (username, client ID, secret ID, scope and redirect uri). Everything seems to be fine up to this part. My code (fillers for username, client id and client secret for security reasons) :
code
It opens up my default web browser and redirects me to my redirect url with the code in it. At this point, I copy and paste the redirect url (as prompted) and hit enter. It returns the following error:
Error
My redirect uri is 'http://google.com/' for this specific example. However, I've tried multiple redirect uris but they all seem to produce the same error for me. (and yes, I did set my redirect uri as whitespace for my application). I've spent hours trying to fix this issue by looking at online tutorials, trying different redirect urls, changing my code but have yet to make any progress. I'm hoping I am just overlooking a simple mistake here! Any feedback on how to fix this is much appreciated!
If it matters: I'm using the IDE PyCharm.
I had to use two different solutions to deal with the redirect_uri issue depending on which IDE I was using. For Jupyter Lab/Notebook, I could use a localhost for the redirect_url
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id="your_client_id", client_secret="your_client_secret", redirect_uri="https://localhost:8890/callback/", scope="user-library-read"))
For Google Colab, I had to use a publicly accessible website. I think "https://google.com/" should work but I used my band's website so I'd remember that the redirect_uri had to match the one in your Spotify Develop dashboard settings.
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id="your_client_id", client_secret="your_client_secret", redirect_uri="https://yourwebsite.com/", scope="user-library-read"))
I just ended up using my bands website because it was easier for me to remember. Make sure to go to the Spotify developer dashboard (https://developer.spotify.com/dashboard/applications) and match the redirect_uri with what you are planning to use at that time.
I think it is your redirect URL - working for me with:
import os
import spotipy.util as util
# credentials
user = 'username'
desired_scope = 'playlist-modify-private'
id = os.environ.get('SPOT_CLIENT')
secret = os.environ.get('SPOT_SECRET')
uri = 'https://localhost'
token = util.prompt_for_user_token(username=user,
scope=desired_scope,
client_id=id,
client_secret=secret,
redirect_uri=uri)
I think for your redirect url spotify requires the initial http(s) part - don't forget to add it to the white-list in your Spotify for Developers app too, as otherwise you will get 'invalid-redirect-uri'.

How to Create Python Code with Google API Client

I have code below that was given to me to list Google Cloud Service Accounts for a specific Project.
import os
from googleapiclient import discovery
from gcp import get_key
"""gets all Service Accounts from the Service Account page"""
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = get_key()
service = discovery.build('iam', 'v1')
project_id = 'projects/<google cloud project>'
request = service.projects().serviceAccounts().list(name=project_id)
response = request.execute()
accounts = response['accounts']
for account in accounts:
print(account['email'])
This code works perfectly and prints the accounts as I need them. What I'm trying to figure out is:
Where can I go to see how to construct code like this? I found a site that has references to the Python API Client, but I can't seem to figure out how to make the code above from it. I can see the Method to list the Service Accounts, but it's still not giving me enough information.
Is there somewhere else I should be going to educate myself. Any information you have is appreciated so I don't pull out the rest of my hair.
Thanks, Eric
Let me share with you this documentation page, where there is a detailed explanation on how to build a script such as the one you shared, and what does each line of code mean. It is extracted from the documentation of ML Engine, not IAM, but it is using the same Python Google API Client Libary, so just ignore the references to ML and the rest will be useful for you.
In any case, here it is a commented version of your code, so that you understand it better:
# Imports for the Client API Libraries and the key management
import os
from googleapiclient import discovery
from gcp import get_key
# Look for an environment variable containing the credentials for Google Cloud Platform
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = get_key()
# Build a Python representation of the REST API
service = discovery.build('iam', 'v1')
# Define the Project ID of your project
project_id = 'projects/<google cloud project>'
"""Until this point, the code is general to any API
From this point on, it is specific to the IAM API"""
# Create the request using the appropriate 'serviceAccounts' API
# You can substitute serviceAccounts by any other available API
request = service.projects().serviceAccounts().list(name=project_id)
# Execute the request that was built in the previous step
response = request.execute()
# Process the data from the response obtained with the request execution
accounts = response['accounts']
for account in accounts:
print(account['email'])
Once you understand the first part of the code, the last lines are specific to the API you are using, which in this case is the Google IAM API. In this link, you can find detailed information on the methods available and what they do.
Then, you can follow the Python API Client Library documentation that you shared in order to see how to call the methods. For instance, in the code you shared, the method used depends on service, which is the Python representation of the API, and then goes down the tree of methods in the last link as in projects(), then serviceAccounts() and finally the specificlist() method, which ends up in request = service.projects().serviceAccounts().list(name=project_id).
Finally, just in case you are interested in the other available APIs, please refer to this page for more information.
I hope the comments I made on your code were of help, and that the documentation shared makes it easier for you to understand how a code like that one could be scripted.
You can use ipython having googleapiclient installed - with something like:
sudo pip install --upgrade google-api-python-client
You can go to interactive python console and do:
from googleapiclient import discovery
dir(discovery)
help(discovery)
dir - gives all entries that object has - so:
a = ''
dir(a)
Will tell what you can do with string object. Doing help(a) will give help for string object. You can do dipper:
dir(discovery)
# and then for instance
help(discovery.re)
You can call your script in steps, and see what is result print it, do some research, having something - do %history to printout your session, and have solution that can be triggered as a script.

How do I connect to quickbooks online via python?

I'm trying to figure out how to authenticate and create an entry on quickbooks online through Python. Currently, when I try to click auth link in their API Explorer, I get 404 page.
What I'm trying to do is creating invoice through Python. However, it seems like their documentation is not complete. I contacted their support, and I haven't heard from them yet.
The python-quickbooks library is probably the correct choice now, as it is a "complete rework of quickbooks-python". It has pretty comprehensive instructions on getting and using the auth keys, though I wouldn't call it "simple", since the process is by definition somewhat complex. The instructions are "for Django", but the Django-specific code simply gets parameters out of a URL string.
We're using it to great effect, because the syntax is as easy as:
auth_client = AuthClient(
client_id = CLIENT_ID # from QB website
,client_secret = CLIENT_SECRET # from QB website
,environment = 'sandbox' # or 'production'
,redirect_uri = REDIRECT_URI
)
client = QuickBooks(
auth_client = auth_client
,refresh_token = REFRESH_TOKEN
,company_id = COMPANY_ID
)
account = Account.get(qbid, qb=client) # qbid can be retrieved from the AccountList
return account.CurrentBalance
This library will get the job done https://github.com/HaPsantran/quickbooks-python
It works in JSON so you would construct the Invoice based off of docs at https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/030_entity_services_reference/invoice using the JSON examples.
The library doesn't support sandbox mode** so if you are going to use the development consumer key and secret than you would change this code.
base_url_v3 = "https://quickbooks.api.intuit.com/v3"
to
base_url_v3 = "https://sandbox-quickbooks.api.intuit.com/v3"
while in that mode.
** Sandbox mode only applies currently to U.S. QBO
Having written a lot of the module #Minimul mentions — with a very helpful start by simonv3, who figured out how to get it working first and then I just built on it — I am fairly confident that this will not support the oauth workflow of getting the request token, prompting the user to authenticate out of band, and then getting and storing the access token. It presumes you already have an access token.
Simon (or another Python developer) may be able to comment on how he gets the access token with Python, and if so, it'd be great if he (or they) could add it to the module for all to enjoy.
I had this same problem. I just figured it out and posed the step-by-step process here:
python with Quickbooks Online API v3
Hope this helps.
I looked at the existing python clients for quickbooks and found them to be either outdated or not having all the features. So i created a new python client for quickbooks which can be found at https://pypi.python.org/pypi/quickbooks-py

How do I develop against OAuth locally?

I'm building a Python application that needs to communicate with an OAuth service provider. The SP requires me to specify a callback URL. Specifying localhost obviously won't work. I'm unable to set up a public facing server. Any ideas besides paying for server/hosting? Is this even possible?
Two things:
The OAuth Service Provider in question is violating the OAuth spec if it's giving you an error if you don't specify a callback URL. callback_url is spec'd to be an OPTIONAL parameter.
But, pedantry aside, you probably want to get a callback when the user's done just so you know you can redeem the Request Token for an Access Token. Yahoo's FireEagle developer docs have lots of great information on how to do this.
Even in the second case, the callback URL doesn't actually have to be visible from the Internet at all. The OAuth Service Provider will redirect the browser that the user uses to provide his username/password to the callback URL.
The two common ways to do this are:
Create a dumb web service from within your application that listens on some port (say, http://localhost:1234/) for the completion callback, or
Register a protocol handler (you'll have to check with the documentation for your OS specifically on how to do such a thing, but it enables things like <a href="skype:555-1212"> to work).
(An example of the flow that I believe you're describing lives here.)
In case you are using *nix style system, create a alias like 127.0.0.1 mywebsite.dev in /etc/hosts (you need have the line which is similar to above mentioned in the file, Use http://website.dev/callbackurl/for/app in call back URL and during local testing.
This was with the Facebook OAuth - I actually was able to specify 'http://127.0.0.1:8080' as the Site URL and the callback URL. It took several minutes for the changes to the Facebook app to propagate, but then it worked.
This may help you:
http://www.marcworrell.com/article-2990-en.html
It's php so should be pretty straightforward to set up on your dev server.
I've tried this one once:
http://term.ie/oauth/example/
It's pretty simple. You have a link to download the code at the bottom.
localtunnel [port] and voila
http://blogrium.wordpress.com/2010/05/11/making-a-local-web-server-public-with-localtunnel/
http://github.com/progrium/localtunnel
You could create 2 applications? 1 for deployment and the other for testing.
Alternatively, you can also include an oauth_callback parameter when you requesting for a request token. Some providers will redirect to the url specified by oauth_callback (eg. Twitter, Google) but some will ignore this callback url and redirect to the one specified during configuration (eg. Yahoo)
So how I solved this issue (using BitBucket's OAuth interface) was by specifying the callback URL to localhost (or whatever the hell you want really), and then following the authorisation URL with curl, but with the twist of only returning the HTTP header. Example:
curl --user BitbucketUsername:BitbucketPassword -sL -w "%{http_code} %{url_effective}\\n" "AUTH_URL" -o /dev/null
Inserting for your credentials and the authorisation url (remember to escape the exclamation mark!).
What you should get is something like this:
200 http://localhost?dump&oauth_verifier=OATH_VERIFIER&oauth_token=OATH_TOKEN
And you can scrape the oath_verifier from this.
Doing the same in python:
import pycurl
devnull = open('/dev/null', 'w')
c = pycurl.Curl()
c.setopt(pycurl.WRITEFUNCTION, devnull.write)
c.setopt(c.USERPWD, "BBUSERNAME:BBPASSWORD")
c.setopt(pycurl.URL, authorize_url)
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.perform()
print c.getinfo(pycurl.HTTP_CODE), c.getinfo(pycurl.EFFECTIVE_URL)
I hope this is useful for someone!

Categories

Resources