How to access gcloud bucket storage from script running in a Cloud Run job - google-compute-engine

I'm able to create an image from sources and create and run a Cloud Run job through the Google CLI.
gcloud builds submit --pack image=gcr.io/<my-project-id>/logger-job
gcloud beta run jobs create helloworld --image gcr.io/<my-project-id>/logger-job --region europe-west9
gcloud beta run jobs execute helloworld --region=europe-west9
From the CLI, I can also upload files to a bucket by running be python script:
import sys
from google.cloud import storage
def get_bucket(bucket_name):
storage_client = storage.Client.from_service_account_json(
'my_credentials_file.json')
# Make an authenticated API request
buckets = list(storage_client.list_buckets())
found = False
for bucket in buckets:
if bucket_name in bucket.name:
found = True
break
if not found:
print("Error: bucket not found")
sys.exit(1)
print(bucket)
return bucket
def upload_file(bucket, fname):
destination_blob_name = fname
source_file_name = fname
blob = bucket.blob(destination_blob_name)
blob.upload_from_filename(source_file_name)
print(
f"File {source_file_name} uploaded to {destination_blob_name}."
)
if __name__ == "__main__":
bucket = get_bucket('MyBucket')
upload_file(bucket, 'testfile')
Before I can even figure out how the authentication towards the bucket works when running this script through a job, I'm getting errors on target
ModuleNotFoundError: No module named 'google'
Which kind of makes sense, but I don't know how I would include the google.cloud module when running the script on target job? Or should I access the bucket in another way?

There are multiple questions and you would benefit from reading Google's documentation.
When (!) the Python code that interacts with Cloud Storage is combined into the Cloud Run deployment, it will run using the identity of its Cloud Run service. Unless otherwise specified, this will be the default Cloud Run Service Account. You should create and reference a Service Account specific to this Cloud Run service.
You will need to determine which IAM permissions you wish to confer on the Service Account. Generally you'll reference a set of permissions using a Cloud Storage IAM role.
You're (correctly) using a Google-provided client library to interact with Cloud Storage. You will be able to benefit from Application Default Credentials. This makes it easy to run e.g. your Python code on e.g. Cloud Run as a Service Account.
Lastly, you should review Google's Cloud Storage client library (for Python) documentation to see how to use e.g. pip to install the client library.

Place a requirements.txt file, containing the 3rd party modules that are necessary for running the code, in the folder that is being built when executing
gcloud builds submit --pack image=gcr.io/<my-project-id>/logger-job
This will automatically pip install the modules when exeuting the job.

Related

Google auth credentials error. Requires a JSON file, provided a TOML file

I am trying to host a project with google cloud vision in streamlit cloud. Streamlit requires the google auth credentials file to be .toml while google cloud requires it to be in .json.
def detect_document(path):
cred = ".streamlit/secrets.toml"
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = cred
client = vision.ImageAnnotatorClient()
with io.open(path, 'rb') as image_file:
content = image_file.read()
image = vision.Image(content=content)
I cannot put my GCP credentials in github since it is a security risk. Any work around or suggestion for this issue.
As #ferdy suggested, go read the Connect Streamlit to Google Cloud Storage.
The steps you are probably missing:
Copy your app secrets to the cloud.
As the secrets.toml file above is not committed to GitHub, you need to
pass its content to your deployed app (on Streamlit Community Cloud)
separately.
This avoids storing them on GitHub as you stated you don't want to do (and rightfully so).
Use the newly stored credentials:
import streamlit as st
from google.oauth2 import service_account
from google.cloud import storage
# Create API client.
credentials = service_account.Credentials.from_service_account_info(
st.secrets["gcp_service_account"]
)
client = storage.Client(credentials=credentials)

change and update twilio serverless function

I have deployed few functions in twilio serverless.If I mistakenly delet that local file from where I deployed the function.Or if this function is deployed by someone else.As there is no way to change the functions from UI,we must have to do it from cli.
The way I found is fetching,updating,building,deploying function by providing its service ,enviornment ,function ,build,deploy sid each time by function api by curl/twilio cli.Its very tedious and error prone to provide all those sid mentioned above. there should be an easy way just like when I have all the file locally and with a one twilio cli command I can change and deploy.
Whats the easiest way to download the file from serverless to local environment to change and re-deploy it again from cli just like I did first time( just run twilio serveless:deploy )?
You can modify Twilio Functions (via the GUI) created with the serverless cli by sending the following request.
Read only services and editing in the new Functions UI
Example:
client.serverless.services('ZSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
.update({uiEditable: true})
.then(service => console.log(service.friendlyName));
You can also use tooling for the severless API to make working with it incredibly easy, reference:
Deploy Twilio Functions with the Serverless extension for VSCode

CLASP Local Login

I'm trying to figure out how to set up a local login file for my google scripts project in order to set it up so it'll work in an automated deploy process.
As far as I can tell, clasp login will create a file in your home directory which authenticates you with scripts.google.com, but that file isn't applicable to to local logins because it's missing some properties like "project_id".
When looking for how to create a file to run with clasp login --creds {file} there doesn't seem to be a straight forward way to generate one of those files in your local directory, which is how I would like to set up my deployment pipeline.
Most of the documentation on the internet says that you can create your own file by navigating to your GCP project and exporting a service account json file, but I don't know how to tell which GCP project my google script project is associated with.
I'm super lost, any help would be appreciated.
Thanks,
Alex
In order to log in locally I performed these steps:
In your project, make sure it's associated with a project id
(in the legacy editor > resources > cloud platform project > set your project id)
Then go to https://console.cloud.google.com/apis/credentials?authuser=0&project=your-project-id, create an Oauth2.0 clientid, and download your client secret and save it locally
From there you can locally log in by running clasp login -creds /path/to/file
Thanks to ALE13 and Error retrieving access token: TypeError: Cannot read property 'project_id' of undefined

Deploying multiple Google Cloud Functions from same repo

The documentation for Google Cloud Functions is a little vague - I understand how to deploy a single function that is contained within index.js - even in a specific directory, but how does one deploy multiple cloud functions which are located within the same repository?
AWS Lambda allows you to specify a specific file and function name:
/my/path/my-file.myHandler
Lambda also allows you to deploy a zip file containing only the files required to run, omitting all of the optional transitive npm dependencies and their resources. For some libraries (eg Oracle DB) including node-modules/** would significantly increase the deployment time, and possibly exceed storage limits (it does on AWS Lambda).
The best that I can manage with Google Cloud Function deployment is:
$ gcloud alpha functions deploy my-function \
--trigger-http
--source-url https://github.com/user-name/my-repo.git \
--source-branch master \
--source-path lib/foo/bar
--entry-point myHandler
...but my understanding is that it deploys lib/foo/bar/index.js which contains function myHandler(req, res) {} ...and all dependencies concatenated in the same file? That doesn't make sense at all - like I said, the documentation is a little vague.
The current deployment tool takes a simple approach. It zips the directory and uploads it. This means you (currently) should move or delete node_modules before executing the command if you don't wish for them to be included in the deployment package. Note that, like lambda, GCF will resolve dependencies automatically.
As to deployment, please see: gcloud alpha functions deploy --help
Specifically:
--entry-point=ENTRY_POINT
The name of the function (as defined in source code) that will be
executed.
You might opt to use the --source flags to upload the file once, then deploy the functions sans upload. You can also instruct google to pull functions from a repo in the same manner. I suggest you write a quick deployment script to help you deploy a list of functions in a single command.

gsutil not working in GCE

So when I bring up a GCE instance using the standard debian 7 image, and issue a "gsutil config" command, it fails with the following message:
jcortez#master:~$ gsutil config
Failure: No handler was ready to authenticate. 4 handlers were checked. ['ComputeAuth', 'OAuth2Auth', 'OAuth2ServiceAccountAuth', 'HmacAuthV1Handler'] Check your credentials.
I've tried it on the debian 6 and centos instances and had the same results. Issuing "gcutil config" works fine however. I gather I need to set up my ~/.boto file but I'm not sure what to.
What am I doing wrong?
Using service account scopes as E. Anderson mentions is the recommended way to use gsutil on Compute Engine, so the images are configured to get OAuth access tokens from the metadata server in /etc/boto.cfg:
[GoogleCompute]
service_account = default
If you want to manage gsutil config yourself, rename /etc/boto.cfg, and gsutil config should work:
$ sudo mv /etc/boto.cfg /etc/boto.cfg.orig
$ gsutil config
This script will create a boto config file at
/home/<...snipped...>/.boto
containing your credentials, based on your responses to the following questions.
<...snip...>
Are you trying to use a service account to have access to Cloud Storage without needing to enter credentials?
It sounds like gsutil is searching for an OAuth access token with the appropriate scopes and is not finding one. You can ensure that your VM has access to Google Cloud Storage by requesting the storage-rw or storage-full permission when starting your VM via gcutil, or by selecting the appropriate privileges under "Project Access" on the UI console. For gcutil, something like the following should work:
> gcutil addinstance worker-1 \
> --service_account_scopes=https://www.googleapis.com/auth/devstorage.read_write,https://www.googleapis.com/auth/compute.readonly
When you configured your GCE instance, did you set it up with a service account configured? Older versions of gsutil got confused when you attempted to run gsutil config when you already had service account credentials configured.
If you already have a service account configured you shouldn't need to run gsutil config - you should be able to simply run gsutil ls, cp, etc. (it will use credentials located elsewhere than your ~/.boto file).
If you really do want to run gsutil config (e.g., to set up credentials associated with your login identity, rather than service account credentials), you could try downloading the current gsutil from http://storage.googleapis.com/pub/gsutil.tar.gz, unpacking it, and running that copy of gsutil. Note that if you do this, the personal credentials you create by running gsutil config will essentially "hide" your service account credentials (i.e., you would need to move your .boto file aside if you ever want to user your service account credentials again).
Mike Schwartz, Google Cloud Storage team
FYI I'm working on some changes to gsutil now that will handle the problem you encountered more smoothly. That version should be out within the next week or two.
Mike