Skip to content

Commit

Permalink
create email invoker for #114
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkEdmondson1234 committed Mar 17, 2021
1 parent b0eccea commit 8c8a141
Show file tree
Hide file tree
Showing 18 changed files with 224 additions and 52 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export(cr_pubsub)
export(cr_region_get)
export(cr_region_set)
export(cr_run)
export(cr_run_email)
export(cr_run_get)
export(cr_run_list)
export(cr_run_schedule_http)
Expand Down
50 changes: 36 additions & 14 deletions R/buildsteps_templates.R
Original file line number Diff line number Diff line change
Expand Up @@ -262,28 +262,50 @@ cr_buildstep_run <- function(name,
is.null(dots$id)
)

auth_calls <- "--no-allow-unauthenticated"
auth_step <- NULL
create_service <- NULL

if(allowUnauthenticated){
auth_calls <- "--allow-unauthenticated"
#sometimes unauth fails, so attempt to fix as per warning suggestion
auth_step <- cr_buildstep_gcloud(
args = c("gcloud",
"run", "services", "add-iam-policy-binding",
"--region", region,
"--member=allUsers",
"--role=roles/run.invoker",
"--platform", "managed",
name),
id = "auth cloudrun",
...)
auth_calls <- "--allow-unauthenticated"
member <- "allUsers"
} else {
# authenticated calls - add the default email
# https://cloud.google.com/run/docs/triggering/using-scheduler#command-line
service <- substr(paste0(name,"-invoker"),1,30)
desc <- paste("--display-name=Cloud Run Invoker for", name)
script <-
paste(
sprintf("gcloud iam service-accounts describe %s || ",
cr_run_email(service)),
sprintf("gcloud iam service-accounts create %s %s",
service, desc)
)
create_service <- cr_buildstep_bash(
name = "gcr.io/google.com/cloudsdktool/cloud-sdk:alpine",
bash_script = script,
id = "create invoker"
)

auth_calls <- "--no-allow-unauthenticated"
member <- sprintf("serviceAccount:%s", cr_run_email(service))
}

auth_step <- cr_buildstep_gcloud(
args = c("gcloud",
"run", "services", "add-iam-policy-binding",
paste0("--region=", region),
paste0("--member=", member),
"--role=roles/run.invoker",
"--platform=managed",
name),
id = "auth cloudrun",
...)

if(is.null(port)){
port <- "default"
}


if(!is.null(env_vars)){
env_vars <- paste0("--set-env-vars=", paste(env_vars, collapse = ","))
} else {
Expand All @@ -310,7 +332,7 @@ cr_buildstep_run <- function(name,
gcloud_args),
id = "deploy cloudrun",...)

c(deploy_step, auth_step)
c(create_service, deploy_step, auth_step)

}

Expand Down
2 changes: 1 addition & 1 deletion R/cloudrun.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#' @param port Container port to receive requests at. Also sets the $PORT environment variable. Must be a number between 1 and 65535, inclusive. To unset this field, pass the special value "default".
#' @param region The endpoint region for deployment
#' @param projectId The GCP project from which the services should be listed
#' @param allowUnauthenticated TRUE if can be reached from public HTTP address.
#' @param allowUnauthenticated TRUE if can be reached from public HTTP address. If FALSE will configure a service-email called \code{(name)-cloudrun-invoker@(project-id).iam.gserviceaccount.com}
#' @param max_instances the desired maximum nuimber of container instances. "default" is 1000, you can get more if you requested a quota instance. For Shiny instances on Cloud Run, this needs to be 1.
#' @param memory The format for size is a fixed or floating point number followed by a unit: G, M, or K corresponding to gigabyte, megabyte, or kilobyte, respectively, or use the power-of-two equivalents: Gi, Mi, Ki corresponding to gibibyte, mebibyte or kibibyte respectively. The default is 256Mi
#' @param cpu 1 or 2 CPUs for your instance
Expand Down
58 changes: 48 additions & 10 deletions R/cloudrun_schedule.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#' Create a Cloud Scheduler HTTP target for a Cloud Run URI
#' Create a Cloud Scheduler HTTP target for a private Cloud Run URI
#'
#' This enables Cloud Scheduler to trigger Cloud Run
#' This enables Cloud Scheduler to trigger Cloud Run endpoints when they are not public.
#'
#' @seealso https://cloud.google.com/run/docs/triggering/using-scheduler
#'
#' @param uri The URI of your Cloud Run application
#' @param http_method The HTTP verb you have set up your Cloud Run application to receive
#' @param email The email that will authenticate the job set via \link{cr_email_set}
#' @param email The service email that has invoke access to the Cloud Run application. If using \link{cr_run} and derivatives to make the email this will include \code{(name)-cloudrun-invoker@(project-id).iam.gserviceaccount.com} - see \link{cr_run_email} to help make the email.
#' @param body (optional) An R list object that will be turned into JSON via \link[jsonlite]{toJSON} and turned into a base64-encoded string if you are doing a POST, PUT or PATCH request.
#'
#' @return A \link{HttpTarget} object for use in \link{cr_schedule}
Expand All @@ -16,25 +16,48 @@
#' @export
#' @import assertthat
#' @family Cloud Scheduler functions
#' @seealso \link{cr_build_schedule_http}
#' @family Cloud Run functions
#' @seealso \link{cr_build_schedule_http} and \link{cr_run} and \link{cr_deploy_run}
#' @examples
#'
#' run_me <- cr_run_schedule_http(
#' "https://example-ewjogewawq-ew.a.run.app/echo?msg=blah",
#' \dontrun{
#' # for unauthenticated apps create a HttpTarget
#' run_me <- HttpTarget(
#' uri = "https://public-ewjogewawq-ew.a.run.app/echo?msg=blah",
#' http_method = "GET"
#' )
#' cr_schedule("cloud-run-scheduled", schedule = "16 4 * * *",
#' httpTarget = run_me)
#'
#' # for authenticated Cloud Run apps - create with allowUnauthenticated=FALSE
#' cr_deploy_run("my-app", allowUnauthenticated = TRUE)
#' }
#'
#' # deploying via R will help create a service email called my-app-cloudrun-invoker
#' cr_run_email("my-app")
#'
#' \dontrun{
#' # use that email to schedule the Cloud Run private micro-service
#'
#' cr_schedule("cloud-run-scheduled", schedule = "16 4 * * *",
#' httpTarget = run_me)
#' # schedule the endpoint
#' my_run_name <- "my-app"
#' my_app <- cr_run_get(my_run_name)
#' email <- cr_run_email(my_run_name)
#' endpoint <- paste0(my_app$status$url, "/fetch_stuff")
#'
#' app_sched <- cr_run_schedule_http(endpoint,
#' http_method = "GET",
#' email = email)
#'
#' cr_schedule("cloud-run-scheduled-1",
#' schedule = "4 16 * * *",
#' httpTarget = app_sched)
#' }
#'
cr_run_schedule_http <- function(uri,
email,
http_method = "GET",
body = NULL,
email = cr_email_get()){
body = NULL){

assert_that(
is.string(uri),
Expand All @@ -52,3 +75,18 @@ cr_run_schedule_http <- function(uri,
)
)
}

#' Create an invoker email for use within authenticated Cloud Run
#'
#' @param name Name of the Cloud Run service
#' @param projectId The projectId where the Cloud Run service will run
#'
#' @export
#' @family Cloud Run functions
#' @examples
#'
#' cr_run_email("my-run-app", "my-project")
cr_run_email <- function(name, projectId = cr_project_get()){
service_name <- substr(paste0(name,"-invoker"),1,30)
sprintf("%s@%s.iam.gserviceaccount.com", service_name, projectId)
}
2 changes: 2 additions & 0 deletions R/deploy-run.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#' @family Deployment functions
#' @details
#'
#' @seealso For scheduling Cloud Run apps \link{cr_run_schedule_http}
#'
#' These deploy containers to Cloud Run, a scale 0-to-millions container-as-a-service on Google Cloud Platform.
#'
#' @export
Expand Down
2 changes: 1 addition & 1 deletion R/setup_buildemail.R
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ cr_setup_role_lookup <- function(type = c(
bigquery = "roles/bigquery.admin",
secrets = "roles/secretmanager.secretAccessor",
cloudbuild = c("roles/cloudbuild.builds.builder",
"roles/iam.serviceAccountUser"),
"roles/iam.serviceAccountAdmin"),
cloudstorage = c("roles/storage.admin","roles/viewer"),
schedule_agent = "roles/cloudscheduler.serviceAgent",
run_agent = "roles/serverless.serviceAgent"
Expand Down
2 changes: 1 addition & 1 deletion man/cr_buildstep_run.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions man/cr_deploy_run.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/cr_deploy_run_website.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions man/cr_jwt_create.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions man/cr_plumber_pubsub.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions man/cr_run.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions man/cr_run_email.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions man/cr_run_get.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions man/cr_run_list.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8c8a141

Please sign in to comment.