Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add google cloud storage funcs #722

Merged
merged 13 commits into from
Jan 10, 2022

Conversation

MarkEdmondson1234
Copy link
Contributor

Prework

Related GitHub issues and pull requests

Summary

Add functions for google cloud storage versioning of objects. I copied across the AWS functions and modified them for GCS. All tests are passing locally, but to replicate you will need a GCS account setup.

I also found a skip that was missing from clustermq tests.

I wasn't sure where to put the test files as they didn't run in testthat root folder, but the skip will ensure it still passes where they are, but let me know if you prefer the file is only copied in when testing locally. I put them in both locations for now.

Copy link
Collaborator

@wlandau wlandau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for this PR, Mark! This is a really strong start. I am still getting set up with GCP and working through security, but I have some comments in the meantime.

As part of this PR, please feel free to add yourself as a contributor here in the DESCRIPTION file.

DESCRIPTION Show resolved Hide resolved
R/utils_gcp.R Outdated Show resolved Hide resolved
R/utils_gcp.R Outdated Show resolved Hide resolved
R/utils_gcp.R Outdated Show resolved Hide resolved
tests/testthat/helper-gcp.R Outdated Show resolved Hide resolved
tests/testthat/helper-gcp.R Outdated Show resolved Hide resolved
tests/testthat/test-tar_make_clustermq.R Show resolved Hide resolved
tests/gcp/test-utils_gcp.R Outdated Show resolved Hide resolved
tests/testthat/test-utils_gcp.R Outdated Show resolved Hide resolved
@wlandau
Copy link
Collaborator

wlandau commented Dec 13, 2021

I am having trouble getting set up with GCS. Apparently something is wrong with the service account I just created?

> library(googleCloudStorageR)
> 
> gcs_setup()
ℹ ==Welcome to googleCloudStorageR v0.6.0 setup==
This wizard will scan your system for setup options and help you with any that are missing. 
Hit 0 or ESC to cancel. 

1: Create and download JSON service account key
2: Setup auto-authentication (JSON service account key)
3: Setup default bucket

Selection: 2
───────────────────────────────────────────────────────────────────────
Do you want to configure for all R sessions or just this project? 

1: All R sessions (Recommended)
2: Project only

Selection: 1
───────────────────────────────────────────────────────────────────────
x No environment argument detected: GCS_AUTH_FILEValidated Client ID file /home/landau/.gcp/client_secret_CENSORED.apps.googleusercontent.com.jsonFound Client ID project: CENSOREDUsing Client ID via GAR_CLIENT_JSON=/home/landau/.gcp/client_secret_CENSORED.apps.googleusercontent.com.json
───────────────────────────────────────────────────────────────────────
Do you want to provision a service account for your project?

1: Yes, I need a service account key
2: No, I already have one downloaded

Selection: 1No roles specified to configure for service keyCreating service key file - choose service account name (Push enter for default 'googleauthr')
service account name: targets-test-service-accountCreating service account targets-test-service-accountSetting client.id from /home/landau/.gcp/client_secret_CENSORED.apps.googleusercontent.com.json2021-12-12 21:31:54 > Request Status Code:  403
Error in value[[3L]](cond) : 
  API returned: Permission iam.serviceAccounts.get is required to perform this operation on service account projects/CENSORED/serviceAccounts/targets-test-service-account@CENSORED.iam.gserviceaccount.com.

But the "principal" for this service account has the "Custom Service Account Admin" role, which I previously created with permissions like iam.serviceAccounts.get.

Screenshot_20211212_213452

@MarkEdmondson1234
Copy link
Contributor Author

MarkEdmondson1234 commented Dec 13, 2021

I am having trouble getting set up with GCS. Apparently something is wrong with the service account I just created?

Could you try it with GitHub version googleAuthR, the service creation API changed recently. (remotes::install_github("MarkEdmondson1234/googleAuthR")) It should kick you out to auth in the browser with your own user that has Owner roles for the project, which allows you to assign the key.

gcs_setup()
ℹ ==Welcome to googleCloudStorageR v0.6.0.9000 setup==
This wizard will scan your system for setup options and help you with any that are missing. 
Hit 0 or ESC to cancel. 

1: Create and download JSON service account key
2: Setup auto-authentication (JSON service account key)
3: Setup default bucket

Selection: 1
───────────────────────────────────────────────────────────────────────────────────────────────────────
ℹ Using local project .RenvironValidated Client ID file /Users/mark/auth/clients/project_id-desktop.jsonFound Client ID project: project_idUsing Client ID via GAR_CLIENT_JSON=/Users/mark/dev/auth/clients/project_id-desktop.json
───────────────────────────────────────────────────────────────────────────────────────────────────────
Do you want to provision a service account for your project?

1: Yes, I need a service account key
2: No, I already have one downloaded

Selection: 1Creating service key file - choose service account name (Push enter for default 'googlecloudstorager')
service account name: targets-test-service-accountCreating service account targets-test-service-accountSetting client.id from /Users/mark/auth/clients/project_id-desktop.json
Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
Authentication complete.2021-12-13 08:34:59 > Request Status Code:  4042021-12-13 08:34:59 > Creating new service account:  targets-test-service-account@project_id.iam.gserviceaccount.com2021-12-13 08:34:59 > Creating service accountId -  targets-test-service-account2021-12-13 08:35:00 > Checking existing roles2021-12-13 08:35:00 > Granting roles:  roles/storage.admin to accountIds:  targets-test-service-account@project_id.iam.gserviceaccount.com2021-12-13 08:35:01 > Creating secret auth key for service account targets-test-service-account  for project  project_id2021-12-13 08:35:02 > Writing secret auth JSON key to  googlecloudstorager-auth-key.json  and adding to .gitignoreMove googlecloudstorager-auth-key.json to a secure folder location outside of your working directory
Have you moved the file?

1: No
2: No way
3: Absolutely

Selection: 

@wlandau
Copy link
Collaborator

wlandau commented Dec 13, 2021

Unfortunately, I ran into the same 403 error with development googleAuthR. It feels like my mistake setting up security in the web UI. I am having a hard time understanding the documentation, it seems to assume I am trying to develop and host a persistent web app, which is not what we are after.

@MarkEdmondson1234
Copy link
Contributor Author

Did you see the help video? That may help with some obscure but critical detail the docs may have left out ;)
https://code.markedmondson.me/googleCloudRunner/articles/setup.html

@wlandau
Copy link
Collaborator

wlandau commented Dec 15, 2021

Thanks Mark, that help video is fantastic! I think I am mostly set up now, except for a couple failing tests:

> googleCloudRunner::cr_setup_test()
ℹ Perform deployments to test your setup is working. Takes around 5mins.  ESC or 0 to skip.Successfully auto-authenticated via /home/landau/.gcp/targets-development-svc-acct-auth-key.jsonValidated authentication in GCE_AUTH_FILE
Select which deployments to test 

1: All tests
2: Cloud Build - Docker
3: Cloud Run - plumber API with Pub/Sub
4: Cloud Build - R script
5: Cloud Scheduler - R script

Selection: 1Attempting Docker deployment on Cloud Build via cr_deploy_docker()
2021-12-15 09:39:40 -- No objects found2021-12-15 09:39:40 > Dockerfile found in  /home/landau/R/R-4.1.2/library/googleCloudRunner/example/

── #Deploy docker build for image:  gcr.io/targets-development/example ──────────────────────────────────────────────────────────

── #Upload  /home/landau/R/R-4.1.2/library/googleCloudRunner/example/  to  gs://targets-development-bucket/example.tar.gz ───────2021-12-15 09:39:40 > Uploading example.tar.gz to targets-development-bucket/example.tar.gz
2021-12-15 09:39:40 -- File size detected as 885 bytes2021-12-15 09:39:42 > Cloud Build started - logs: 
 https://console.cloud.google.com/cloud-build/builds/1dd63d49-529d-4f1a-a670-c08c216e604c?project=7568891538222021-12-15 09:39:42 > Waiting for Cloud Build...
(|) Build time: [00:00:57] (  2% of timeout: 600s)
ℹ 2021-12-15 09:40:45 > Build finished with status: FAILURE2021-12-15 09:40:45 > gcr.io/targets-development/example:latest and gcr.io/targets-development/example:$BUILD_ID
x Something is wrong with Cloud Build setupAttempting deployment of plumber API on Cloud Run via cr_deploy_plumber()
ℹ 2021-12-15 09:40:45 > Uploading /home/landau/R/R-4.1.2/library/googleCloudRunner/example/ folder for Cloud Run2021-12-15 09:40:45 > Dockerfile found in  /home/landau/R/R-4.1.2/library/googleCloudRunner/example/

── #Deploy docker build for image:  gcr.io/targets-development/example ──────────────────────────────────────────────────────────

── #Upload  /home/landau/R/R-4.1.2/library/googleCloudRunner/example/  to  gs://targets-development-bucket/example.tar.gz ───────2021-12-15 09:40:45 > Uploading example.tar.gz to targets-development-bucket/example.tar.gz
2021-12-15 09:40:45 -- File size detected as 884 bytes2021-12-15 09:40:46 > Cloud Build started - logs: 
 https://console.cloud.google.com/cloud-build/builds/5a5468f3-4e57-4637-8f72-992f09ce7867?project=7568891538222021-12-15 09:40:46 > Waiting for Cloud Build...
(-) Build time: [00:00:46] (  2% of timeout: 600s)
ℹ 2021-12-15 09:41:37 > Build finished with status: FAILURE2021-12-15 09:41:37 > gcr.io/targets-development/example:$BUILD_ID2021-12-15 09:41:37 > Error building Dockerfile
x Something is wrong with Cloud Run setupTesting Cloud Build R scripts deployments via cr_deploy_r()
ℹ 2021-12-15 09:41:38 > Deploy R script cr_rscript_2021121639579298094138 to Cloud Build2021-12-15 09:41:38 > Cloud Build started - logs: 
 https://console.cloud.google.com/cloud-build/builds/38802327-9117-41d1-8f88-2eedaddf928f?project=7568891538222021-12-15 09:41:38 > Waiting for Cloud Build...
(\) Build time: [00:01:11] (  2% of timeout: 600s)
ℹ 2021-12-15 09:42:55 > Build finished with status: SUCCESSCloud Build R scripts deployed successfullyTesting scheduling R script deployments via cr_deploy_r(schedule = '* * * * *')
ℹ 2021-12-15 09:42:55 > Deploy R script cr_rscript_2021121639579375094255 to Cloud Build2021-12-15 09:42:55 > Scheduling R script on cron schedule: 15 21 * * *Scheduled Cloud Build R scripts deployed successfully
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

── Test summary ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
ℹ Something is wrong with Cloud Build setupSomething is wrong with Cloud Run setupCloud Build R scripts deployed successfullyScheduled Cloud Build R scripts deployed successfullyDeployment tests complete!

Docker test build log:

starting build "5a5468f3-4e57-4637-8f72-992f09ce7867"

FETCHSOURCE
Fetching storage object: gs://targets-development-bucket/example.tar.gz#1639579245685388
Copying gs://targets-development-bucket/example.tar.gz#1639579245685388...
/ [0 files][    0.0 B/  884.0 B]                                                
/ [1 files][  884.0 B/  884.0 B]                                                
Operation completed over 1 objects/884.0 B.                                      
BUILD
Pulling image: gcr.io/kaniko-project/executor:latest
latest: Pulling from kaniko-project/executor
Digest: sha256:0fae223f496525e31226cde473ec77ed15abfa8cbabff5ff5bf1c5268355bbb0
Status: Downloaded newer image for gcr.io/kaniko-project/executor:latest
gcr.io/kaniko-project/executor:latest
�[36mINFO�[0m[0000] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
�[36mINFO�[0m[0000] Retrieving image gcr.io/gcer-public/googlecloudrunner:master from registry gcr.io 
�[36mINFO�[0m[0000] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
�[36mINFO�[0m[0000] Returning cached image manifest              
�[36mINFO�[0m[0000] Built cross stage deps: map[]                
�[36mINFO�[0m[0000] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
�[36mINFO�[0m[0000] Returning cached image manifest              
�[36mINFO�[0m[0000] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
�[36mINFO�[0m[0000] Returning cached image manifest              
�[36mINFO�[0m[0000] Executing 0 build triggers                   
�[36mINFO�[0m[0000] Unpacking rootfs as cmd COPY ["./", "./"] requires it. 
�[36mINFO�[0m[0029] COPY ["./", "./"]                            
�[36mINFO�[0m[0029] Taking snapshot of files...                  
�[36mINFO�[0m[0029] ENTRYPOINT ["Rscript", "server.R"]           
�[36mINFO�[0m[0029] No files changed in this command, skipping snapshotting. 
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0xe5 pc=0x7f146c3aae80]

runtime stack:
runtime.throw(0x7e0d4b, 0x2a)
	/usr/local/go/src/runtime/panic.go:1116 +0x72
runtime.sigpanic()
	/usr/local/go/src/runtime/signal_unix.go:726 +0x4ac

goroutine 1 [syscall]:
runtime.cgocall(0x6a8ae0, 0xc00003da30, 0xc000010038)
	/usr/local/go/src/runtime/cgocall.go:133 +0x5b fp=0xc00003da00 sp=0xc00003d9c8 pc=0x40563b
os/user._Cfunc_mygetpwuid_r(0x0, 0xc000068ed0, 0x15a9070, 0x400, 0xc000010038, 0x7f1400000000)
	_cgo_gotypes.go:175 +0x4d fp=0xc00003da30 sp=0xc00003da00 pc=0x68b1ad
os/user.lookupUnixUid.func1.1(0x0, 0xc000068ed0, 0xc00001ade0, 0xc000010038, 0xc00003dad0)
	/usr/local/go/src/os/user/cgo_lookup_unix.go:103 +0xd0 fp=0xc00003da80 sp=0xc00003da30 pc=0x68bf50
os/user.lookupUnixUid.func1(0x798840)
	/usr/local/go/src/os/user/cgo_lookup_unix.go:103 +0x45 fp=0xc00003dab8 sp=0xc00003da80 pc=0x68bfc5
os/user.retryWithBuffer(0xc00001ade0, 0xc00003db90, 0x41a165, 0x7f1494104290)
	/usr/local/go/src/os/user/cgo_lookup_unix.go:247 +0x3e fp=0xc00003db10 sp=0xc00003dab8 pc=0x68bcde
os/user.lookupUnixUid(0x0, 0x0, 0x0, 0x0)
	/usr/local/go/src/os/user/cgo_lookup_unix.go:96 +0x132 fp=0xc00003dbd8 sp=0xc00003db10 pc=0x68b5f2
os/user.current(0xc00003dc58, 0x4d419c, 0xc00006afb0)
	/usr/local/go/src/os/user/cgo_lookup_unix.go:49 +0x49 fp=0xc00003dc18 sp=0xc00003dbd8 pc=0x68b489
os/user.Current.func1()
	/usr/local/go/src/os/user/lookup.go:15 +0x25 fp=0xc00003dc40 sp=0xc00003dc18 pc=0x68be05
sync.(*Once).doSlow(0xa09c40, 0x7ed020)
	/usr/local/go/src/sync/once.go:66 +0xec fp=0xc00003dc90 sp=0xc00003dc40 pc=0x474cac
sync.(*Once).Do(...)
	/usr/local/go/src/sync/once.go:57
os/user.Current(0x47707b, 0xa41360, 0xc0000685d0)
	/usr/local/go/src/os/user/lookup.go:15 +0x105 fp=0xc00003dcc0 sp=0xc00003dc90 pc=0x68b005
github.com/GoogleCloudPlatform/docker-credential-gcr/util.unixHomeDir(0x4d4800, 0xc00006afb0)
	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/util/util.go:42 +0x25 fp=0xc00003dcf0 sp=0xc00003dcc0 pc=0x68e7a5
github.com/GoogleCloudPlatform/docker-credential-gcr/util.SdkConfigPath(0x0, 0x0, 0x0, 0x0)
	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/util/util.go:34 +0x26 fp=0xc00003dd58 sp=0xc00003dcf0 pc=0x68e686
github.com/GoogleCloudPlatform/docker-credential-gcr/store.dockerCredentialPath(0x7f14940fa108, 0xc00001add0, 0x7f1494103328, 0x18)
	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/store/store.go:215 +0x6d fp=0xc00003ddc8 sp=0xc00003dd58 pc=0x691a8d
github.com/GoogleCloudPlatform/docker-credential-gcr/store.DefaultGCRCredStore(...)
	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/store/store.go:84
github.com/GoogleCloudPlatform/docker-credential-gcr/cli.(*helperCmd).Execute(0xc00000e360, 0x8393e0, 0xc000016018, 0xc0000543c0, 0x0, 0x0, 0x0, 0x0)
	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/cli/dockerHelper.go:35 +0x35 fp=0xc00003de78 sp=0xc00003ddc8 pc=0x6a6b35
github.com/GoogleCloudPlatform/docker-credential-gcr/vendor/github.com/google/subcommands.(*Commander).Execute(0xc000012100, 0x8393e0, 0xc000016018, 0x0, 0x0, 0x0, 0x39)
	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/vendor/github.com/google/subcommands/subcommands.go:209 +0x30d fp=0xc00003df20 sp=0xc00003de78 pc=0x69274d
github.com/GoogleCloudPlatform/docker-credential-gcr/vendor/github.com/google/subcommands.Execute(...)
	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/vendor/github.com/google/subcommands/subcommands.go:492
main.main()
	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/main.go:54 +0x63f fp=0xc00003df88 sp=0xc00003df20 pc=0x6a87df
runtime.main()
	/usr/local/go/src/runtime/proc.go:204 +0x209 fp=0xc00003dfe0 sp=0xc00003df88 pc=0x439c89
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1374 +0x1 fp=0xc00003dfe8 sp=0xc00003dfe0 pc=0x46b861
error pushing image: resolving pushAuth: error getting credentials - err: exit status 2, out: ``
ERROR
ERROR: build step 0 "gcr.io/kaniko-project/executor:latest" failed: step exited with non-zero status: 1

Cloud Run Plumber build log:

starting build "1dd63d49-529d-4f1a-a670-c08c216e604c"

FETCHSOURCE
Fetching storage object: gs://targets-development-bucket/example.tar.gz#1639579180815701
Copying gs://targets-development-bucket/example.tar.gz#1639579180815701...
/ [0 files][    0.0 B/  885.0 B]                                                
/ [1 files][  885.0 B/  885.0 B]                                                
Operation completed over 1 objects/885.0 B.                                      
BUILD
Starting Step #1
Starting Step #0
Step #1: Pulling image: gcr.io/kaniko-project/executor:latest
Step #0: Pulling image: gcr.io/kaniko-project/executor:latest
Step #1: latest: Pulling from kaniko-project/executor
Step #0: latest: Pulling from kaniko-project/executor
Step #1: Digest: sha256:0fae223f496525e31226cde473ec77ed15abfa8cbabff5ff5bf1c5268355bbb0
Step #0: Digest: sha256:0fae223f496525e31226cde473ec77ed15abfa8cbabff5ff5bf1c5268355bbb0
Step #1: Status: Downloaded newer image for gcr.io/kaniko-project/executor:latest
Step #0: Status: Image is up to date for gcr.io/kaniko-project/executor:latest
Step #0: gcr.io/kaniko-project/executor:latest
Step #1: gcr.io/kaniko-project/executor:latest
Step #1: �[36mINFO�[0m[0001] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
Step #1: �[36mINFO�[0m[0001] Retrieving image gcr.io/gcer-public/googlecloudrunner:master from registry gcr.io 
Step #1: �[36mINFO�[0m[0002] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
Step #1: �[36mINFO�[0m[0002] Returning cached image manifest              
Step #1: �[36mINFO�[0m[0002] Built cross stage deps: map[]                
Step #1: �[36mINFO�[0m[0002] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
Step #1: �[36mINFO�[0m[0002] Returning cached image manifest              
Step #1: �[36mINFO�[0m[0002] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
Step #1: �[36mINFO�[0m[0002] Returning cached image manifest              
Step #1: �[36mINFO�[0m[0002] Executing 0 build triggers                   
Step #1: �[36mINFO�[0m[0002] Unpacking rootfs as cmd COPY ["./", "./"] requires it. 
Step #0: �[36mINFO�[0m[0002] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
Step #0: �[36mINFO�[0m[0002] Retrieving image gcr.io/gcer-public/googlecloudrunner:master from registry gcr.io 
Step #0: �[36mINFO�[0m[0002] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
Step #0: �[36mINFO�[0m[0002] Returning cached image manifest              
Step #0: �[36mINFO�[0m[0002] Built cross stage deps: map[]                
Step #0: �[36mINFO�[0m[0002] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
Step #0: �[36mINFO�[0m[0002] Returning cached image manifest              
Step #0: �[36mINFO�[0m[0002] Retrieving image manifest gcr.io/gcer-public/googlecloudrunner:master 
Step #0: �[36mINFO�[0m[0002] Returning cached image manifest              
Step #0: �[36mINFO�[0m[0002] Executing 0 build triggers                   
Step #0: �[36mINFO�[0m[0002] Unpacking rootfs as cmd COPY ["./", "./"] requires it. 
Step #0: �[36mINFO�[0m[0041] COPY ["./", "./"]                            
Step #0: �[36mINFO�[0m[0041] Taking snapshot of files...                  
Step #0: �[36mINFO�[0m[0041] ENTRYPOINT ["Rscript", "server.R"]           
Step #0: �[36mINFO�[0m[0041] No files changed in this command, skipping snapshotting. 
Step #0: fatal error: unexpected signal during runtime execution
Step #0: [signal SIGSEGV: segmentation violation code=0x1 addr=0xe5 pc=0x7f7c4e08de80]
Step #0: 
Step #0: runtime stack:
Step #0: runtime.throw(0x7e0d4b, 0x2a)
Step #0: 	/usr/local/go/src/runtime/panic.go:1116 +0x72
Step #0: runtime.sigpanic()
Step #0: 	/usr/local/go/src/runtime/signal_unix.go:726 +0x4ac
Step #0: 
Step #0: goroutine 1 [syscall]:
Step #0: runtime.cgocall(0x6a8ae0, 0xc000038a30, 0xc0000ae028)
Step #0: 	/usr/local/go/src/runtime/cgocall.go:133 +0x5b fp=0xc000038a00 sp=0xc0000389c8 pc=0x40563b
Step #0: os/user._Cfunc_mygetpwuid_r(0x0, 0xc000094ed0, 0x135e1b0, 0x400, 0xc0000ae028, 0x7f7c00000000)
Step #0: 	_cgo_gotypes.go:175 +0x4d fp=0xc000038a30 sp=0xc000038a00 pc=0x68b1ad
Step #0: os/user.lookupUnixUid.func1.1(0x0, 0xc000094ed0, 0xc000090dc0, 0xc0000ae028, 0xc000038ad0)
Step #0: 	/usr/local/go/src/os/user/cgo_lookup_unix.go:103 +0xd0 fp=0xc000038a80 sp=0xc000038a30 pc=0x68bf50
Step #0: os/user.lookupUnixUid.func1(0x798840)
Step #0: 	/usr/local/go/src/os/user/cgo_lookup_unix.go:103 +0x45 fp=0xc000038ab8 sp=0xc000038a80 pc=0x68bfc5
Step #0: os/user.retryWithBuffer(0xc000090dc0, 0xc000038b90, 0x41a165, 0x7f7c775ec380)
Step #0: 	/usr/local/go/src/os/user/cgo_lookup_unix.go:247 +0x3e fp=0xc000038b10 sp=0xc000038ab8 pc=0x68bcde
Step #0: os/user.lookupUnixUid(0x0, 0x0, 0x0, 0x0)
Step #0: 	/usr/local/go/src/os/user/cgo_lookup_unix.go:96 +0x132 fp=0xc000038bd8 sp=0xc000038b10 pc=0x68b5f2
Step #0: os/user.current(0xc000038c58, 0x4d419c, 0xc0000973c0)
Step #0: 	/usr/local/go/src/os/user/cgo_lookup_unix.go:49 +0x49 fp=0xc000038c18 sp=0xc000038bd8 pc=0x68b489
Step #0: os/user.Current.func1()
Step #0: 	/usr/local/go/src/os/user/lookup.go:15 +0x25 fp=0xc000038c40 sp=0xc000038c18 pc=0x68be05
Step #0: sync.(*Once).doSlow(0xa09c40, 0x7ed020)
Step #0: 	/usr/local/go/src/sync/once.go:66 +0xec fp=0xc000038c90 sp=0xc000038c40 pc=0x474cac
Step #0: sync.(*Once).Do(...)
Step #0: 	/usr/local/go/src/sync/once.go:57
Step #0: os/user.Current(0x47707b, 0xa41360, 0xc0000945d0)
Step #0: 	/usr/local/go/src/os/user/lookup.go:15 +0x105 fp=0xc000038cc0 sp=0xc000038c90 pc=0x68b005
Step #0: github.com/GoogleCloudPlatform/docker-credential-gcr/util.unixHomeDir(0x4d4800, 0xc0000973c0)
Step #0: 	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/util/util.go:42 +0x25 fp=0xc000038cf0 sp=0xc000038cc0 pc=0x68e7a5
Step #0: github.com/GoogleCloudPlatform/docker-credential-gcr/util.SdkConfigPath(0x0, 0x0, 0x0, 0x0)
Step #0: 	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/util/util.go:34 +0x26 fp=0xc000038d58 sp=0xc000038cf0 pc=0x68e686
Step #0: github.com/GoogleCloudPlatform/docker-credential-gcr/store.dockerCredentialPath(0x7f7c775e07d0, 0xc000090db0, 0x7f7c4e94b228, 0x18)
Step #0: 	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/store/store.go:215 +0x6d fp=0xc000038dc8 sp=0xc000038d58 pc=0x691a8d
Step #0: github.com/GoogleCloudPlatform/docker-credential-gcr/store.DefaultGCRCredStore(...)
Step #0: 	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/store/store.go:84
Step #0: github.com/GoogleCloudPlatform/docker-credential-gcr/cli.(*helperCmd).Execute(0xc0000a6300, 0x8393e0, 0xc00009a000, 0xc0000b03c0, 0x0, 0x0, 0x0, 0x0)
Step #0: 	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/cli/dockerHelper.go:35 +0x35 fp=0xc000038e78 sp=0xc000038dc8 pc=0x6a6b35
Step #0: github.com/GoogleCloudPlatform/docker-credential-gcr/vendor/github.com/google/subcommands.(*Commander).Execute(0xc000092080, 0x8393e0, 0xc00009a000, 0x0, 0x0, 0x0, 0x39)
Step #0: 	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/vendor/github.com/google/subcommands/subcommands.go:209 +0x30d fp=0xc000038f20 sp=0xc000038e78 pc=0x69274d
Step #0: github.com/GoogleCloudPlatform/docker-credential-gcr/vendor/github.com/google/subcommands.Execute(...)
Step #0: 	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/vendor/github.com/google/subcommands/subcommands.go:492
Step #0: main.main()
Step #0: 	/go/src/github.com/GoogleCloudPlatform/docker-credential-gcr/main.go:54 +0x63f fp=0xc000038f88 sp=0xc000038f20 pc=0x6a87df
Step #0: runtime.main()
Step #0: 	/usr/local/go/src/runtime/proc.go:204 +0x209 fp=0xc000038fe0 sp=0xc000038f88 pc=0x439c89
Step #0: runtime.goexit()
Step #0: 	/usr/local/go/src/runtime/asm_amd64.s:1374 +0x1 fp=0xc000038fe8 sp=0xc000038fe0 pc=0x46b861
Step #0: error pushing image: resolving pushAuth: error getting credentials - err: exit status 2, out: ``
Finished Step #0
ERROR
ERROR: build step 0 "gcr.io/kaniko-project/executor:latest" failed: step exited with non-zero status: 1

tests/gcp/test-utils_gcp.R Outdated Show resolved Hide resolved
R/utils_gcp.R Outdated
bucket = bucket,
version = version
),
error = function(condition) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an error condition that would allow gcp_gcs_exists() to tell if the object really does not exist (as opposed to a configuration error etc.)? When testing locally, gcp_gcs_exists() at first incorrectly returned FALSE (silently) because I had the wrong version of googleCloudStorageR installed and gcs_get_object() could not accept a generation argument. Detecting HTML 400 errors has been helpful for AWS:

http_400 = function(condition) {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rlang::abort() has a class argument to give custom classes to errors which can then be detected with tryCatch().

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R/utils_gcp.R Show resolved Hide resolved
R/utils_gcp.R Show resolved Hide resolved
@wlandau
Copy link
Collaborator

wlandau commented Dec 15, 2021

I was able to run all the tests, and they pass. This PR looks great, I will merge when all the specific comments are addressed.

@MarkEdmondson1234
Copy link
Contributor Author

Great! The errors you got in set-up from googleCloudRunner are some 3rd party errors to do with kaniko docker image, unfortunately. Should be temporary but a I think github version now has it has been too long MarkEdmondson1234/googleCloudRunner#136 so will address in a patch

@MarkEdmondson1234
Copy link
Contributor Author

Hmm it says lint has failed but locally it is successful.
Screenshot 2021-12-17 at 17 04 14

@wlandau
Copy link
Collaborator

wlandau commented Dec 17, 2021

That's odd, I cannot reproduce the lint either. But those trailing whitespaces could actually be in the call to person() in the DESCRIPTION where you entered your name. (By the way, would you move person(given = "Mark", ...) just above the role = "rev" folks?)

@wlandau
Copy link
Collaborator

wlandau commented Dec 17, 2021

There is also a lint in R/tar_target.R#L73 which was my fault. If you merge main, I bet it will fix that one.

@MarkEdmondson1234
Copy link
Contributor Author

Yes it was whitespace in the DESCRIPTION - merged main in as well.

R/utils_gcp.R Outdated Show resolved Hide resolved
R/utils_gcp.R Outdated Show resolved Hide resolved
tests/gcp/test-utils_gcp.R Outdated Show resolved Hide resolved
tests/gcp/test-utils_gcp.R Outdated Show resolved Hide resolved
tests/gcp/test-utils_gcp.R Outdated Show resolved Hide resolved
R/utils_gcp.R Outdated Show resolved Hide resolved
@MarkEdmondson1234
Copy link
Contributor Author

MarkEdmondson1234 commented Jan 8, 2022

Hi @wlandau happy new year :) How is this looking now? I have worked on some nice DAG functions in the meantime which will be very useful I think - at the moment it uploads/downloads everything before and after builds but if the GCS native storage was enabled it would speed up things a lot for when big files are involved.

I'm a little stuck when trying to enable only individual target steps to build, not quite got my head around how to handle the state between steps but an edge case anyhow I think.

Here is an example output from workflow I have for another project now:

  1. Created the targets pipeline as normal then..
library(googleCloudRunner)

bs <- cr_buildstep_targets_multi(
  last_id = "bigquery", # signals which step to download artifacts from 
  task_image = "gcr.io/xxx/xact-api:master",
  task_args = list(secretEnv = "XACT_PW"))

cr_build_targets(
  bs,
  options = list(env = c("XACT_ORGANIZATIONID=1234",
                         "XACT_USER=USERNAME")),
  execute = "now",   # runs it immediatly vs make a file to run on CI/CD
  availableSecrets = cr_build_yaml_secrets("XACT_PW","xact-pw")
)

The builds that can run concurrently so big speed up for some pipelines, costs nothing to run, no cloud servers to set up etc.

Build log:

2022-01-08 21:38:40 > targets cloud location: gs://xxxx/xact-api2022-01-08 21:38:40 > Resolving targets::tar_manifest()
 
── # Building DAG: ─────────────────────────────────────────────────────────────────────────────
• [get previous _targets metadata] -> [lookup_sub_file]
• [] -> [cmd_args]
• [] -> [sx_mappings_file]
• [] -> [surveyid_file]
• [lookup_sub_file] -> [lookup_sub]
• [sx_mappings_file] -> [sx_mappings]
• [cmd_args, surveyid_file] -> [surveyIds]
• [surveyIds] -> [survey_as]
• [surveyIds] -> [lookup_id]
• [surveyIds] -> [survey_qs]
• [survey_as] -> [a_audit]
• [lookup_id, lookup_sub, survey_as, sx_mappings] -> [processed]
• [lookup_id, survey_qs, surveyIds] -> [q_audit]
• [cmd_args, processed] -> [bigquery]
• [q_audit] -> [q_audit_file]
• [bigquery] -> [ Upload Artifacts ]
....2022-01-08 21:38:47 > File size detected as 5.6 Mb2022-01-08 21:38:48 > Running Cloud Build for targets workflow in /Users/mark/dev/xxxx/xact-apiCloud Build started - logs:
<https://console.cloud.google.com/cloud-build/builds/xxxx-4ddf-4186-859a-f46db1e65e03?project=278775085929>Build finished with status: SUCCESS and took ~[01m44s]
ℹ 2022-01-08 21:40:48 > Downloading to download_folder: /Users/mark/dev/xxx/_targetsSaved xact-api/_targets/buildtime.txt to _targets/buildtime.txt  ( 29 bytes )
✓ Saved xact-api/_targets/meta/meta to _targets/meta/meta  ( 3.5 Kb )
✓ Saved xact-api/_targets/meta/process to _targets/meta/process  ( 56 bytes )
✓ Saved xact-api/_targets/meta/progress to _targets/meta/progress  ( 518 bytes )
✓ Saved xact-api/_targets/objects/a_audit to _targets/objects/a_audit  ( 971 bytes )
✓ Saved xact-api/_targets/objects/bigquery to _targets/objects/bigquery  ( 4.6 Kb )
✓ Saved xact-api/_targets/objects/cmd_args to _targets/objects/cmd_args  ( 46 bytes )
✓ Saved xact-api/_targets/objects/lookup_id to _targets/objects/lookup_id  ( 200 bytes )
✓ Saved xact-api/_targets/objects/lookup_sub to _targets/objects/lookup_sub  ( 516 bytes )
✓ Saved xact-api/_targets/objects/processed to _targets/objects/processed  ( 4.6 Kb )
✓ Saved xact-api/_targets/objects/q_audit to _targets/objects/q_audit  ( 5.7 Kb )
✓ Saved xact-api/_targets/objects/q_audit_file to _targets/objects/q_audit_file  ( 44 bytes )
✓ Saved xact-api/_targets/objects/surveyIds to _targets/objects/surveyIds  ( 223 bytes )
✓ Saved xact-api/_targets/objects/survey_as to _targets/objects/survey_as  ( 346.8 Kb )
✓ Saved xact-api/_targets/objects/survey_qs to _targets/objects/survey_qs  ( 21.1 Kb )
✓ Saved xact-api/_targets/objects/sx_mappings to _targets/objects/sx_mappings  ( 1.2 Kb )

── # Built targets on Cloud Build with status: SUCCESS ─────────────────────────────────────────2022-01-08 21:40:51 > Build artifacts downloaded to /Users/mark/dev/xxx/_targets

@wlandau
Copy link
Collaborator

wlandau commented Jan 9, 2022

Hi @wlandau happy new year :)

You too, Mark!

How is this looking now?

Almost there. The only remaining issue is https://github.com/ropensci/targets/pull/722/files#r769782900. I think it is important to somehow avoid false negatives in gcp_gcs_exists() due to genuine errors (e.g. broken configuration). I like custom error classes when they are available, but there could be ways around cloudyr/googleCloudStorageR#153: for instance, if it is possible to check if the object exists without generating an error at all.

I have worked on some nice DAG functions in the meantime which will be very useful I think - at the moment it uploads/downloads everything before and after builds but if the GCS native storage was enabled it would speed up things a lot for when big files are involved.

Nice!

I'm a little stuck when trying to enable only individual target steps to build, not quite got my head around how to handle the state between steps but an edge case anyhow I think.

Is the roadblock in targets or something GCS-related? In targets, I try to address this with shortcutting: #523. I found it to be a tougher problem than it looks because most targets require their dependencies to be available and up to date.

The builds that can run concurrently so big speed up for some pipelines, costs nothing to run, no cloud servers to set up etc.

That's really cool! At some point, I think cr_buildstep_targets_multi() would make a great new chapter in https://github.com/ropensci-books/targets.

@MarkEdmondson1234
Copy link
Contributor Author

The custom http error is in now, I can move it to googleAuthR or open an issue in gargle later perhaps.

Is the roadblock in targets or something GCS-related? In targets, I try to address this with shortcutting: #523

I couldn't get my head around how one would create a script that would just call CB within it but keep state. Perhaps shortcutting is what is needed.

e.g. If someone wanted to run just one target on CB - so they have:

process <- function(big_data) { do_stuff(big_data) }

with target pipeline:

list(
  tar_target(input, "file1", ...),
  tar_target(process, process(input)),
  tar_target(output, write.csv(process))
)

How to replace process() with a function that calls CB but maintains state?

process_cb <- function(big_data){
  # something?
}

list(
  tar_target(input, "file1", ...),
  tar_target(process_cb, process(input)),
  tar_target(output, write.csv(process))
)

or perhaps this is what tar_make_future() would do, or a tar_make_cb()

@wlandau
Copy link
Collaborator

wlandau commented Jan 10, 2022

The custom http error is in now

Awesome!

I can move it to googleAuthR or open an issue in gargle later perhaps.

Whatever you think is best, either seems like a good final resting place.

e.g. If someone wanted to run just one target on CB

Yeah, one conceivable approach is for user code inside a target to call CB/CR.

library(targets)
process <- function(data) {
  ...
  cr_deploy_run(...)
  ...
}
list(
  tar_target(data, get_data()),
  tar_target(on_cloud, process(data))
)

But it has a couple performance disadvantages:

  1. It is hard to scale out to many parallel targets. You could run tar_make_future() or tar_make_clustermq() to get multiple CR jobs going at once, but each job would be associated with its own R process on the user's local machine (or the machine running the main orchestrating process).
  2. By the time process() gets called, data is already loaded into memory (unless retrieval is "none" in tar_target()), which could lead to a lot of unnecessary downloads/uploads to and from the cloud.

The internal orchestration in targets is difficult to replace with external intervention. For data management, you could set retrieval = "none" for everything, but it is a lot of work to shuffle the data around manually. And for the DSL, even if you get the DAG from tar_network(), the conversion to CB YAML is not perfect because dynamic branching is handled completely internally. That part of why I am in favor of HenrikBengtsson/future#567 if it can be done efficiently.

@wlandau
Copy link
Collaborator

wlandau commented Jan 10, 2022

I just tried 8204e42, and I am getting issues with gcp_gcs_exists(). I thought the http400 error class would handle this, but apparently not. Is there a more straightforward way to figure out if an object in a bucket exists, maybe without generating an error condition at all?

bucket <- random_bucket_name()
projectId <- Sys.getenv("GCE_DEFAULT_PROJECT_ID")
googleCloudStorageR::gcs_create_bucket(bucket, projectId = projectId)
gcp_gcs_exists(key = "x", bucket = bucket) # expected FALSE with no error
#> Error: API returned: No such object: targets-test-bucket-22e53e537837ffab7e8f5e21a7bbd90da937ade61ea/x
traceback()
#> 17: stop("API returned: ", error_message, call. = FALSE)
#> 16: checkGoogleAPIError(req)
#> 15: doHttrRequest(req_url, request_type = http_header, the_body = the_body, 
#>         customConfig = customConfig, simplifyVector = simplifyVector)
#> 14: ob()
#> 13: googleCloudStorageR::gcs_get_object(key, bucket = bucket, meta = TRUE, 
#>         generation = version)
#> 12: withCallingHandlers(expr, message = function(c) if (inherits(c, 
#>         classes)) tryInvokeRestart("muffleMessage"))
#> 11: loud(googleCloudStorageR::gcs_get_object(key, bucket = bucket, 
#>         meta = TRUE, generation = version)) at utils_gcp.R#36
#> 10: gcp_gcs_head(key = key, bucket = bucket, version = version) at utils_gcp.R#51
#> 9: gcp_gcs_head_true(key = key, bucket = bucket, version = version)
#> 8: doTryCatch(return(expr), name, parentenv, handler)
#> 7: tryCatchOne(expr, names, parentenv, handlers[[1L]])
#> 6: tryCatchList(expr, classes, parentenv, handlers)
#> 5: tryCatch(gcp_gcs_head_true(key = key, bucket = bucket, version = version), 
#>        http_404 = function(condition) {
#>            FALSE
#>        }) at utils_gcp.R#12
#> 4: gcp_gcs_exists(key = "x", bucket = bucket)
#> 3: eval_bare(expr, quo_get_env(quo))
#> 2: quasi_label(enquo(object), label, arg = "object")
#> 1: expect_false(gcp_gcs_exists(key = "x", bucket = bucket))

@MarkEdmondson1234
Copy link
Contributor Author

It turned out it needed to be on googleAuthR to handle 404s for all types, not just objects and meta objects. But it worked out less code actually - anyhow this works:

tryCatch(gcs_get_object("blah", meta = TRUE), http_404 = function(x) FALSE)
ℹ 2022-01-10 21:10:29 > Request Status Code:  404
x Downloading blah ... failed
[1] FALSE

It should work now if the latest GitHub version of googleAuthR is installed?

@wlandau
Copy link
Collaborator

wlandau commented Jan 10, 2022

Awesome, works on my end now! Merging.

@wlandau wlandau merged commit 72ad943 into ropensci:main Jan 10, 2022
@MarkEdmondson1234
Copy link
Contributor Author

Woohoo, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants