modules/mu/providers/google/function.rb in cloud-mu-3.4.0 vs modules/mu/providers/google/function.rb in cloud-mu-3.5.0
- old
+ new
@@ -117,10 +117,13 @@
end
# Called automatically by {MU::Deploy#createResources}
def groom
desc = {}
+
+ func_obj = buildDesc
+
labels = Hash[@tags.keys.map { |k|
[k.downcase, @tags[k].downcase.gsub(/[^-_a-z0-9]/, '-')] }
]
labels["name"] = MU::Cloud::Google.nameStr(@mu_name)
@@ -138,10 +141,14 @@
need_update = true
end
if cloud_desc.available_memory_mb != @config['memory']
need_update = true
end
+ if cloud_desc.service_account_email != func_obj.service_account_email
+ need_update = true
+ end
+
if @config['environment_variable']
@config['environment_variable'].each { |var|
if !cloud_desc.environment_variables or
cloud_desc.environment_variables[var["key"].to_s] != var["value"].to_s
need_update = true
@@ -159,40 +166,56 @@
current = Dir.mktmpdir(@mu_name+"-current") { |dir|
MU::Cloud::Google::Function.downloadPackage(@cloud_id, dir+"/current.zip", credentials: @credentials)
File.read("#{dir}/current.zip")
}
- new = if @config['code']['zip_file']
+ tempfile = nil
+ new = if @config['code']['zip_file'] or @config['code']['path']
+ if @config['code']['path']
+ tempfile = Tempfile.new(["function", ".zip"])
+ MU.log "#{@mu_name} using code at #{@config['code']['path']}"
+ MU::Master.zipDir(@config['code']['path'], tempfile.path)
+ @config['code']['zip_file'] = tempfile.path
+ else
+ MU.log "#{@mu_name} using code packaged at #{@config['code']['zip_file']}"
+ end
+# @code_sha256 = Base64.encode64(Digest::SHA256.digest(zip)).chomp
File.read(@config['code']['zip_file'])
elsif @config['code']['gs_url']
@config['code']['gs_url'].match(/^gs:\/\/([^\/]+)\/(.*)/)
bucket = Regexp.last_match[1]
path = Regexp.last_match[2]
Dir.mktmpdir(@mu_name+"-new") { |dir|
MU::Cloud::Google.storage(credentials: @credentials).get_object(bucket, path, download_dest: dir+"/new.zip")
File.read(dir+"/new.zip")
}
end
+
if @config['code']['gs_url'] and
(@config['code']['gs_url'] != cloud_desc.source_archive_url or
current != new)
need_update = true
- elsif @config['code']['zip_file'] and current != new
+ elsif (@config['code']['zip_file'] or @config['code']['path']) and current != new
need_update = true
- desc[:source_archive_url] = MU::Cloud::Google::Function.uploadPackage(@config['code']['zip_file'], @mu_name+"-cloudfunction.zip", credentials: @credentials)
end
+ if @config['vpc_connector']
+ if cloud_desc.vpc_connector != @config['vpc_connector'] or
+ cloud_desc.vpc_connector_egress_settings != (@config['vpc_connector_allow_all_egress'] ? "ALL_TRAFFIC" : "PRIVATE_RANGES_ONLY")
+ need_update = true
+ end
+ end
+
if need_update
- func_obj = buildDesc
- MU.log "Updating Cloud Function #{@mu_name}", MU::NOTICE, details: func_obj
+ MU.log "Updating Cloud Function #{@cloud_id}", MU::NOTICE, details: func_obj
begin
-# MU::Cloud::Google.function(credentials: @credentials).patch_project_location_function(
-# @cloud_id,
-# func_obj
-# )
- rescue ::Google::Apis::ClientError
- MU.log "Error updating Cloud Function #{@mu_name}.", MU::ERR
+ MU::Cloud::Google.function(credentials: @credentials).patch_project_location_function(
+ @cloud_id,
+ func_obj
+ )
+ rescue ::Google::Apis::ClientError => e
+ MU.log "Error updating Cloud Function #{@mu_name}.", MU::ERR, e.message
if desc[:source_archive_url]
main_file = nil
HELLO_WORLDS.each_pair { |runtime, code|
if @config['runtime'].match(/^#{Regexp.quote(runtime)}/)
main_file = code.keys.first
@@ -205,10 +228,15 @@
end
# service_account_email: sa.kitten.cloud_desc.email,
# labels: labels,
+ if tempfile
+ tempfile.close
+ tempfile.unlink
+ end
+
end
# Return the metadata for this project's configuration
# @return [Hash]
def notify
@@ -352,10 +380,11 @@
# @param config [MU::Config]: The calling MU::Config object
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
def self.schema(config)
toplevel_required = ["runtime"]
schema = {
+ "roles" => MU::Cloud.resourceClass("Google", "User").schema(config)[1]["roles"],
"triggers" => {
"type" => "array",
"items" => {
"type" => "object",
"description" => "Trigger for Cloud Function",
@@ -446,10 +475,11 @@
bucket = MU::Cloud::Google.adminBucketName(credentials)
obj_obj = MU::Cloud::Google.storage(:Object).new(
content_type: "application/zip",
name: filename
)
+
MU::Cloud::Google.storage(credentials: credentials).insert_object(
bucket,
obj_obj,
upload_source: zipfile
)
@@ -485,11 +515,11 @@
elsif function['runtime'] == "nodejs"
function['runtime'] = "nodejs8"
end
# XXX list_project_locations
- if !function['code'] or (!function['code']['zip_file'] and !function['code']['gs_url'])
+ if !function['code'] or (!function['code']['zip_file'] and !function['code']['gs_url'] and !function['code']['path'])
MU.log "Must specify a code source in Cloud Function #{function['name']}", MU::ERR
ok = false
elsif function['code']['zip_file']
z = Zip::File.open(function['code']['zip_file'])
if function['runtime'].match(/^python/)
@@ -555,37 +585,29 @@
]
labels["name"] = MU::Cloud::Google.nameStr(@mu_name)
location = "projects/"+@config['project']+"/locations/"+@config['region']
sa = nil
- retries = 0
- begin
- sa_ref = MU::Config::Ref.get(@config['service_account'])
- sa = @deploy.findLitterMate(name: sa_ref.name, type: "users")
- if !sa or !sa.cloud_desc
- sleep 10
- end
- rescue ::Google::Apis::ClientError => e
- if e.message.match(/notFound:/)
- sleep 10
- retries += 1
- retry
- end
- end while !sa or !sa.cloud_desc and retries < 5
+ need_sa = Proc.new {
+ !sa or !sa.kitten or !sa.kitten.cloud_desc
+ }
+ MU.retrier(loop_if: need_sa, wait: 10, max: 6) { |retries, _wait|
+ sa = MU::Config::Ref.get(@config['service_account'])
+ }
- if !sa or !sa.cloud_desc
+ if need_sa.call()
raise MuError, "Failed to get service account cloud id from #{@config['service_account'].to_s}"
end
desc = {
name: location+"/functions/"+@mu_name.downcase,
runtime: @config['runtime'],
timeout: @config['timeout'].to_s+"s",
# entry_point: "hello_world",
entry_point: @config['handler'],
description: @deploy.deploy_id,
- service_account_email: sa.cloud_desc.email,
+ service_account_email: sa.kitten.cloud_desc.email,
labels: labels,
available_memory_mb: @config['memory']
}
# XXX This network argument is deprecated in favor of using VPC
@@ -594,11 +616,10 @@
# can't do anything except pass their ids into Cloud Functions or
# AppEngine and hope for the best.
if @config['vpc_connector']
desc[:vpc_connector] = @config['vpc_connector']
desc[:vpc_connector_egress_settings] = @config['vpc_connector_allow_all_egress'] ? "ALL_TRAFFIC" : "PRIVATE_RANGES_ONLY"
- pp desc
elsif @vpc
desc[:network] = @vpc.url.sub(/^.*?\/projects\//, 'projects/')
end
if @config['triggers']
@@ -625,11 +646,25 @@
# break
# end
# }
if @config['code']['gs_url']
desc[:source_archive_url] = @config['code']['gs_url']
- elsif @config['code']['zip_file']
+ elsif @config['code']['zip_file'] or @config['code']['path']
+ tempfile = nil
+ if @config['code']['path']
+ tempfile = Tempfile.new(["function", ".zip"])
+ MU.log "#{@mu_name} using code at #{@config['code']['path']}"
+ MU::Master.zipDir(@config['code']['path'], tempfile.path)
+ @config['code']['zip_file'] = tempfile.path
+ else
+ MU.log "#{@mu_name} using code packaged at #{@config['code']['zip_file']}"
+ end
desc[:source_archive_url] = MU::Cloud::Google::Function.uploadPackage(@config['code']['zip_file'], @mu_name+"-cloudfunction.zip", credentials: @credentials)
+
+ if tempfile
+ tempfile.close
+ tempfile.unlink
+ end
end
# Dir.mktmpdir(@mu_name) { |dir|
# hello_code.each_pair { |file, contents|
# f = File.open(dir+"/"+file, "w")