cloud-mu 3.1.6 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/bin/mu-adopt +15 -12
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +37 -1
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -1
- data/bin/mu-run-tests +37 -12
- data/cloud-mu.gemspec +4 -4
- data/cookbooks/mu-tools/attributes/default.rb +7 -0
- data/cookbooks/mu-tools/libraries/helper.rb +87 -3
- data/cookbooks/mu-tools/recipes/apply_security.rb +39 -23
- data/cookbooks/mu-tools/recipes/aws_api.rb +13 -0
- data/cookbooks/mu-tools/recipes/google_api.rb +4 -0
- data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
- data/cookbooks/mu-tools/resources/disk.rb +33 -12
- data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
- data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
- data/extras/clean-stock-amis +10 -2
- data/extras/generate-stock-images +7 -3
- data/extras/image-generators/AWS/centos7.yaml +19 -16
- data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
- data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
- data/modules/mommacat.ru +2 -2
- data/modules/mu.rb +84 -97
- data/modules/mu/adoption.rb +359 -59
- data/modules/mu/cleanup.rb +67 -44
- data/modules/mu/cloud.rb +108 -1754
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +929 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +178 -0
- data/modules/mu/config.rb +122 -80
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +1 -1
- data/modules/mu/config/container_cluster.rb +2 -2
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +5 -4
- data/modules/mu/config/doc_helpers.rb +4 -5
- data/modules/mu/config/endpoint.rb +2 -1
- data/modules/mu/config/firewall_rule.rb +3 -19
- data/modules/mu/config/folder.rb +1 -1
- data/modules/mu/config/function.rb +17 -8
- data/modules/mu/config/group.rb +1 -1
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +57 -11
- data/modules/mu/config/log.rb +1 -1
- data/modules/mu/config/msg_queue.rb +1 -1
- data/modules/mu/config/nosqldb.rb +1 -1
- data/modules/mu/config/notifier.rb +8 -19
- data/modules/mu/config/ref.rb +81 -9
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +30 -34
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +5 -13
- data/modules/mu/config/server_pool.rb +3 -7
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +10 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +13 -17
- data/modules/mu/defaults/AWS.yaml +106 -106
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +33 -19
- data/modules/mu/groomer.rb +15 -0
- data/modules/mu/groomers/chef.rb +3 -0
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +22 -1
- data/modules/mu/mommacat.rb +71 -26
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +82 -3
- data/modules/mu/mommacat/search.rb +59 -16
- data/modules/mu/mommacat/storage.rb +119 -48
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +248 -62
- data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +65 -63
- data/modules/mu/providers/aws/database.rb +1747 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
- data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/function.rb +291 -133
- data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
- data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
- data/modules/mu/providers/aws/job.rb +469 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
- data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
- data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -78
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
- data/modules/mu/{clouds → providers}/aws/server.rb +120 -145
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
- data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/vpc.rb +141 -73
- data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
- data/modules/mu/{clouds → providers}/azure.rb +4 -1
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
- data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
- data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
- data/modules/mu/{clouds → providers}/cloudformation.rb +1 -1
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +15 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +2 -2
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +29 -14
- data/modules/mu/{clouds → providers}/google/database.rb +2 -9
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
- data/modules/mu/{clouds → providers}/google/function.rb +4 -4
- data/modules/mu/{clouds → providers}/google/group.rb +9 -17
- data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +2 -2
- data/modules/mu/{clouds → providers}/google/role.rb +46 -35
- data/modules/mu/{clouds → providers}/google/server.rb +26 -11
- data/modules/mu/{clouds → providers}/google/server_pool.rb +11 -11
- data/modules/mu/{clouds → providers}/google/user.rb +32 -22
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +38 -3
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +2 -2
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +2 -2
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +126 -98
- data/modules/mu/clouds/aws/database.rb +0 -1974
- data/modules/mu/clouds/aws/endpoint.rb +0 -596
|
@@ -18,7 +18,7 @@ module MU
|
|
|
18
18
|
class AWS
|
|
19
19
|
# A firewall ruleset as configured in {MU::Config::BasketofKittens::firewall_rules}
|
|
20
20
|
class FirewallRule < MU::Cloud::FirewallRule
|
|
21
|
-
require "mu/
|
|
21
|
+
require "mu/providers/aws/vpc"
|
|
22
22
|
|
|
23
23
|
@admin_sgs = Hash.new
|
|
24
24
|
@admin_sg_semaphore = Mutex.new
|
|
@@ -381,14 +381,14 @@ module MU
|
|
|
381
381
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
382
382
|
# @param region [String]: The cloud provider region
|
|
383
383
|
# @return [void]
|
|
384
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
384
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
385
385
|
filters = if flags and flags["vpc_id"]
|
|
386
386
|
[
|
|
387
387
|
{name: "vpc-id", values: [flags["vpc_id"]]}
|
|
388
388
|
]
|
|
389
389
|
else
|
|
390
390
|
filters = [
|
|
391
|
-
{name: "tag:MU-ID", values: [
|
|
391
|
+
{name: "tag:MU-ID", values: [deploy_id]}
|
|
392
392
|
]
|
|
393
393
|
if !ignoremaster
|
|
394
394
|
filters << {name: "tag:MU-MASTER-IP", values: [MU.mu_public_ip]}
|
|
@@ -398,7 +398,7 @@ module MU
|
|
|
398
398
|
|
|
399
399
|
# Some services create sneaky rogue ENIs which then block removal of
|
|
400
400
|
# associated security groups. Find them and fry them.
|
|
401
|
-
MU::Cloud
|
|
401
|
+
MU::Cloud.resourceClass("AWS", "VPC").purge_interfaces(noop, filters, region: region, credentials: credentials)
|
|
402
402
|
|
|
403
403
|
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_security_groups(
|
|
404
404
|
filters: filters
|
|
@@ -421,7 +421,7 @@ module MU
|
|
|
421
421
|
# try to get out from under loose network interfaces with which
|
|
422
422
|
# we're associated
|
|
423
423
|
if sg.vpc_id
|
|
424
|
-
default_sg = MU::Cloud
|
|
424
|
+
default_sg = MU::Cloud.resourceClass("AWS", "VPC").getDefaultSg(sg.vpc_id, region: region, credentials: credentials)
|
|
425
425
|
if default_sg
|
|
426
426
|
eni_resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_network_interfaces(
|
|
427
427
|
filters: [ {name: "group-id", values: [sg.group_id]} ]
|
|
@@ -514,6 +514,31 @@ module MU
|
|
|
514
514
|
end
|
|
515
515
|
private_class_method :revoke_rules
|
|
516
516
|
|
|
517
|
+
# Return an AWS-specific chunk of schema commonly used in the +ingress_rules+ parameter of other resource types.
|
|
518
|
+
# @return [Hash]
|
|
519
|
+
def self.ingressRuleAddtlSchema
|
|
520
|
+
{
|
|
521
|
+
"items" => {
|
|
522
|
+
"properties" => {
|
|
523
|
+
"sgs" => {
|
|
524
|
+
"type" => "array",
|
|
525
|
+
"items" => {
|
|
526
|
+
"description" => "Other AWS Security Groups; resources that are associated with this group will have this rule applied to their traffic",
|
|
527
|
+
"type" => "string"
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
"lbs" => {
|
|
531
|
+
"type" => "array",
|
|
532
|
+
"items" => {
|
|
533
|
+
"description" => "AWS Load Balancers which will have this rule applied to their traffic",
|
|
534
|
+
"type" => "string"
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
end
|
|
541
|
+
|
|
517
542
|
# Cloud-specific configuration properties.
|
|
518
543
|
# @param _config [MU::Config]: The calling MU::Config object
|
|
519
544
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
@@ -623,36 +648,16 @@ module MU
|
|
|
623
648
|
|
|
624
649
|
if rule['firewall_rules']
|
|
625
650
|
rule['firewall_rules'].each { |sg|
|
|
626
|
-
if sg
|
|
627
|
-
|
|
628
|
-
"type" => "firewall_rule",
|
|
629
|
-
"name" => sg.name,
|
|
630
|
-
"no_create_wait" => true
|
|
631
|
-
}
|
|
632
|
-
elsif sg['name'] and !sg['deploy_id']
|
|
633
|
-
acl["dependencies"] << {
|
|
634
|
-
"type" => "firewall_rule",
|
|
635
|
-
"name" => sg['name'],
|
|
636
|
-
"no_create_wait" => true
|
|
637
|
-
}
|
|
651
|
+
if sg['name'] and !sg['deploy_id']
|
|
652
|
+
MU::Config.addDependency(acl, sg['name'], "firewall_rule", no_create_wait: true)
|
|
638
653
|
end
|
|
639
654
|
}
|
|
640
655
|
end
|
|
641
656
|
|
|
642
657
|
if rule['loadbalancers']
|
|
643
658
|
rule['loadbalancers'].each { |lb|
|
|
644
|
-
if lb
|
|
645
|
-
|
|
646
|
-
"type" => "loadbalancer",
|
|
647
|
-
"name" => lb.name,
|
|
648
|
-
"phase" => "groom"
|
|
649
|
-
}
|
|
650
|
-
elsif lb['name'] and !lb['deploy_id']
|
|
651
|
-
acl["dependencies"] << {
|
|
652
|
-
"type" => "loadbalancer",
|
|
653
|
-
"name" => lb['name'],
|
|
654
|
-
"phase" => "groom"
|
|
655
|
-
}
|
|
659
|
+
if lb['name'] and !lb['deploy_id']
|
|
660
|
+
MU::Config.addDependency(acl, lb['name'], "loadbalancer", phase: "groom")
|
|
656
661
|
end
|
|
657
662
|
}
|
|
658
663
|
end
|
|
@@ -739,7 +744,6 @@ module MU
|
|
|
739
744
|
# "ingress_rules" structure parsed and validated by MU::Config.
|
|
740
745
|
#########################################################################
|
|
741
746
|
def setRules(rules, add_to_self: false, ingress: true, egress: false)
|
|
742
|
-
describe
|
|
743
747
|
# XXX warn about attempt to set rules before we exist
|
|
744
748
|
return if rules.nil? or rules.size == 0 or !@cloud_id
|
|
745
749
|
|
|
@@ -760,7 +764,7 @@ module MU
|
|
|
760
764
|
ec2_rules = convertToEc2(rules)
|
|
761
765
|
return if ec2_rules.nil?
|
|
762
766
|
|
|
763
|
-
ext_permissions = MU.structToHash(cloud_desc.ip_permissions)
|
|
767
|
+
ext_permissions = MU.structToHash(cloud_desc(use_cache: false).ip_permissions)
|
|
764
768
|
|
|
765
769
|
purge_extraneous_rules(ec2_rules, ext_permissions)
|
|
766
770
|
|
|
@@ -856,8 +860,11 @@ module MU
|
|
|
856
860
|
p_start = rule['port'].to_i
|
|
857
861
|
p_end = rule['port'].to_i
|
|
858
862
|
elsif rule['proto'] != "icmp"
|
|
859
|
-
|
|
863
|
+
MU.log "Can't create a TCP or UDP security group rule without specifying ports, assuming 'all'", MU::WARN, details: rule
|
|
864
|
+
p_start = "0"
|
|
865
|
+
p_end = "65535"
|
|
860
866
|
end
|
|
867
|
+
|
|
861
868
|
if rule['proto'] != "icmp"
|
|
862
869
|
if p_start.nil? or p_end.nil?
|
|
863
870
|
raise MuError, "Got nil ports out of rule #{rule}"
|
|
@@ -59,7 +59,7 @@ module MU
|
|
|
59
59
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
60
60
|
# @param region [String]: The cloud provider region
|
|
61
61
|
# @return [void]
|
|
62
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
62
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
# Locate an existing AWS organization. If no identifying parameters are specified, this will return a description of the Organization which owns the account for our credentials.
|
|
@@ -18,6 +18,18 @@ module MU
|
|
|
18
18
|
# A function as configured in {MU::Config::BasketofKittens::functions}
|
|
19
19
|
class Function < MU::Cloud::Function
|
|
20
20
|
|
|
21
|
+
# If we have sibling resources in our deployment, automatically inject
|
|
22
|
+
# interesting things about them into our function's environment
|
|
23
|
+
# variables.
|
|
24
|
+
SIBLING_VARS = {
|
|
25
|
+
"servers" => ["private_ip_address", "public_ip_address"],
|
|
26
|
+
"search_domains" => ["endpoint"],
|
|
27
|
+
"databases" => ["endpoint"],
|
|
28
|
+
"endpoints" => ["url"],
|
|
29
|
+
"notifiers" => ["TopicArn"],
|
|
30
|
+
"nosqldbs" => ["table_arn"]
|
|
31
|
+
}
|
|
32
|
+
|
|
21
33
|
# Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
|
|
22
34
|
# @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
|
|
23
35
|
def initialize(**args)
|
|
@@ -42,92 +54,47 @@ module MU
|
|
|
42
54
|
|
|
43
55
|
# Called automatically by {MU::Deploy#createResources}
|
|
44
56
|
def create
|
|
45
|
-
role_arn = get_role_arn(@config['iam_role'])
|
|
46
57
|
|
|
47
|
-
lambda_properties =
|
|
48
|
-
code: {},
|
|
49
|
-
function_name: @mu_name,
|
|
50
|
-
handler: @config['handler'],
|
|
51
|
-
publish: true,
|
|
52
|
-
role: role_arn,
|
|
53
|
-
runtime: @config['runtime'],
|
|
54
|
-
}
|
|
58
|
+
lambda_properties = get_properties
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
lambda_properties[:code][:zip_file] = zip
|
|
60
|
-
else
|
|
61
|
-
lambda_properties[:code][:s3_bucket] = @config['code']['s3_bucket']
|
|
62
|
-
lambda_properties[:code][:s3_key] = @config['code']['s3_key']
|
|
63
|
-
if @config['code']['s3_object_version']
|
|
64
|
-
lambda_properties[:code][:s3_object_version] = @config['code']['s3_object_version']
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
if @config.has_key?('timeout')
|
|
69
|
-
lambda_properties[:timeout] = @config['timeout'].to_i ## secs
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
if @config.has_key?('memory')
|
|
73
|
-
lambda_properties[:memory_size] = @config['memory'].to_i
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
if @config.has_key?('environment_variables')
|
|
77
|
-
lambda_properties[:environment] = {
|
|
78
|
-
variables: {@config['environment_variables'][0]['key'] => @config['environment_variables'][0]['value']}
|
|
79
|
-
}
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
lambda_properties[:tags] = {}
|
|
83
|
-
MU::MommaCat.listStandardTags.each_pair { |k, v|
|
|
84
|
-
lambda_properties[:tags][k] = v
|
|
60
|
+
MU.retrier([Aws::Lambda::Errors::InvalidParameterValueException], max: 5, wait: 10) {
|
|
61
|
+
resp = MU::Cloud::AWS.lambda(region: @config['region'], credentials: @credentials).create_function(lambda_properties)
|
|
62
|
+
@cloud_id = resp.function_name
|
|
85
63
|
}
|
|
86
|
-
if @config['tags']
|
|
87
|
-
@config['tags'].each { |tag|
|
|
88
|
-
lambda_properties[:tags][tag.key.first] = tag.values.first
|
|
89
|
-
}
|
|
90
|
-
end
|
|
91
64
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if !@vpc
|
|
101
|
-
raise MuError, "Function #{@config['name']} had a VPC configured, but none was loaded"
|
|
102
|
-
end
|
|
103
|
-
lambda_properties[:vpc_config] = {
|
|
104
|
-
:subnet_ids => @vpc.subnets.map { |s| s.cloud_id },
|
|
105
|
-
:security_group_ids => sgs
|
|
106
|
-
}
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
retries = 0
|
|
110
|
-
resp = begin
|
|
111
|
-
MU::Cloud::AWS.lambda(region: @config['region'], credentials: @config['credentials']).create_function(lambda_properties)
|
|
112
|
-
rescue Aws::Lambda::Errors::InvalidParameterValueException => e
|
|
113
|
-
# Freshly-made IAM roles sometimes aren't really ready
|
|
114
|
-
if retries < 5
|
|
115
|
-
sleep 10
|
|
116
|
-
retries += 1
|
|
117
|
-
retry
|
|
118
|
-
end
|
|
119
|
-
raise e
|
|
65
|
+
# the console does this and docs expect it to be there, so mimic the
|
|
66
|
+
# behavior
|
|
67
|
+
begin
|
|
68
|
+
MU::Cloud::AWS.cloudwatchlogs(region: @config["region"], credentials: @credentials).create_log_group(
|
|
69
|
+
log_group_name: "/aws/lambda/#{@cloud_id}",
|
|
70
|
+
tags: @tags
|
|
71
|
+
)
|
|
72
|
+
rescue Aws::CloudWatchLogs::Errors::ResourceAlreadyExistsException
|
|
120
73
|
end
|
|
121
|
-
|
|
122
|
-
@cloud_id = resp.function_name
|
|
123
74
|
end
|
|
124
75
|
|
|
125
76
|
# Called automatically by {MU::Deploy#createResources}
|
|
126
77
|
def groom
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
78
|
+
old_props = MU.structToHash(cloud_desc)
|
|
79
|
+
|
|
80
|
+
new_props = get_properties
|
|
81
|
+
code_block = new_props[:code]
|
|
82
|
+
new_props.reject! { |k, _v| [:code, :publish, :tags].include?(k) }
|
|
83
|
+
changes = {}
|
|
84
|
+
new_props.each_pair { |k, v|
|
|
85
|
+
changes[k] = v if v != old_props[k]
|
|
86
|
+
}
|
|
87
|
+
if !changes.empty?
|
|
88
|
+
MU.log "Updating Lambda #{@mu_name}", MU::NOTICE, details: changes
|
|
89
|
+
MU::Cloud::AWS.lambda(region: @config['region'], credentials: @config['credentials']).update_function_configuration(new_props)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
if @code_sha256 and @code_sha256 != cloud_desc.code_sha_256.chomp
|
|
93
|
+
MU.log "Updating code in Lambda #{@mu_name}", MU::NOTICE, details: { "old" => @code_sha256, "new" => cloud_desc.code_sha_256 }
|
|
94
|
+
code_block[:publish] = true
|
|
95
|
+
code_block[:function_name] = @cloud_id
|
|
96
|
+
MU::Cloud::AWS.lambda(region: @config['region'], credentials: @config['credentials']).update_function_code(code_block)
|
|
97
|
+
end
|
|
131
98
|
|
|
132
99
|
# tag_function = assign_tag(lambda_func.function_arn, @config['tags'])
|
|
133
100
|
|
|
@@ -141,7 +108,7 @@ module MU
|
|
|
141
108
|
### triggers must exist prior
|
|
142
109
|
if @config['triggers']
|
|
143
110
|
@config['triggers'].each { |tr|
|
|
144
|
-
trigger_arn =
|
|
111
|
+
trigger_arn = resolveARN(tr['service'], tr['name'])
|
|
145
112
|
|
|
146
113
|
trigger_properties = {
|
|
147
114
|
action: "lambda:InvokeFunction",
|
|
@@ -151,15 +118,33 @@ module MU
|
|
|
151
118
|
statement_id: "#{@mu_name}-ID-1",
|
|
152
119
|
}
|
|
153
120
|
|
|
154
|
-
MU.log
|
|
121
|
+
MU.log "Adding #{tr['service']} #{tr['name']} trigger to Lambda function #{@cloud_id}", details: trigger_properties
|
|
155
122
|
begin
|
|
156
123
|
MU::Cloud::AWS.lambda(region: @config['region'], credentials: @config['credentials']).add_permission(trigger_properties)
|
|
157
124
|
rescue Aws::Lambda::Errors::ResourceConflictException
|
|
125
|
+
# just means the permission is already there
|
|
158
126
|
end
|
|
159
|
-
adjust_trigger(tr['service'], trigger_arn,
|
|
127
|
+
adjust_trigger(tr['service'], trigger_arn, arn, @mu_name)
|
|
160
128
|
}
|
|
161
129
|
|
|
162
130
|
end
|
|
131
|
+
|
|
132
|
+
if @config['invoke_on_completion']
|
|
133
|
+
invoke_params = {
|
|
134
|
+
function_name: @cloud_id,
|
|
135
|
+
invocation_type: @config['invoke_on_completion']['invocation_type'],
|
|
136
|
+
log_type: "Tail"
|
|
137
|
+
}
|
|
138
|
+
if @config['invoke_on_completion']['payload']
|
|
139
|
+
invoke_params[:payload] = JSON.generate(@config['invoke_on_completion']['payload'])
|
|
140
|
+
end
|
|
141
|
+
resp = MU::Cloud::AWS.lambda(region: @config['region'], credentials: @config['credentials']).invoke(invoke_params)
|
|
142
|
+
if resp.status_code == 200
|
|
143
|
+
MU.log "Invoked #{@cloud_id}", MU::NOTICE, details: Base64.decode64(resp.log_result)
|
|
144
|
+
else
|
|
145
|
+
MU.log "Invoked #{@cloud_id} and got #{resp.status_code} (#{resp.function_error})", MU::WARN, details: Base64.decode64(resp.log_result)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
163
148
|
end
|
|
164
149
|
|
|
165
150
|
# Intended to be called by other Mu resources, such as Endpoints (API
|
|
@@ -170,13 +155,16 @@ module MU
|
|
|
170
155
|
function_name: @mu_name,
|
|
171
156
|
principal: "#{calling_service}.amazonaws.com",
|
|
172
157
|
source_arn: calling_arn,
|
|
173
|
-
statement_id: "#{calling_service}-#{calling_name}",
|
|
158
|
+
statement_id: "#{calling_service}-#{calling_name.gsub(/[^a-z0-9\-_]/i, '_')}",
|
|
174
159
|
}
|
|
175
160
|
|
|
176
161
|
begin
|
|
177
162
|
# XXX There doesn't seem to be an API call to list or view existing
|
|
178
163
|
# permissions, wtaf. This means we can't intelligently guard this.
|
|
179
164
|
MU::Cloud::AWS.lambda(region: @config['region'], credentials: @config['credentials']).add_permission(trigger)
|
|
165
|
+
rescue Aws::Lambda::Errors::ValidationException => e
|
|
166
|
+
MU.log e.message+" (calling_arn: #{calling_arn}, calling_service: #{calling_service}, calling_name: #{calling_name})", MU::ERR, details: trigger
|
|
167
|
+
raise e
|
|
180
168
|
rescue Aws::Lambda::Errors::ResourceConflictException => e
|
|
181
169
|
if e.message.match(/already exists/)
|
|
182
170
|
MU::Cloud::AWS.lambda(region: @config['region'], credentials: @config['credentials']).remove_permission(
|
|
@@ -192,17 +180,23 @@ module MU
|
|
|
192
180
|
end
|
|
193
181
|
|
|
194
182
|
# Look up an ARN for a given trigger type and resource name
|
|
195
|
-
def
|
|
196
|
-
supported_triggers = %w(apigateway sns events event cloudwatch_event)
|
|
183
|
+
def resolveARN(svc, name)
|
|
184
|
+
supported_triggers = %w(apigateway sns events event cloudwatch_event dynamodb)
|
|
197
185
|
if supported_triggers.include?(svc.downcase)
|
|
198
186
|
arn = nil
|
|
199
187
|
case svc.downcase
|
|
200
188
|
when 'sns'
|
|
201
|
-
|
|
189
|
+
sib_sns = @deploy.findLitterMate(name: name, type: "notifiers")
|
|
190
|
+
arn = sib_sns ? sib_sns.arn : "arn:aws:sns:#{@config['region']}:#{MU::Cloud::AWS.credToAcct(@config['credentials'])}:#{name}"
|
|
202
191
|
when 'alarm','events', 'event', 'cloudwatch_event'
|
|
203
|
-
|
|
192
|
+
sib_event = @deploy.findLitterMate(name: name, type: "job")
|
|
193
|
+
arn = sib_event ? sib_event.arn : "arn:aws:events:#{@config['region']}:#{MU::Cloud::AWS.credToAcct(@config['credentials'])}:rule/#{name}"
|
|
194
|
+
when 'dynamodb'
|
|
195
|
+
sib_dynamo = @deploy.findLitterMate(name: name, type: "nosqldb")
|
|
196
|
+
arn = sib_dynamo ? sib_dynamo.arn : "arn:aws:dynamodb:#{@config['region']}:#{MU::Cloud::AWS.credToAcct(@config['credentials'])}:table/#{name}"
|
|
204
197
|
when 'apigateway'
|
|
205
|
-
|
|
198
|
+
sib_apig = @deploy.findLitterMate(name: name, type: "endpoints")
|
|
199
|
+
arn = sib_apig ? sib_apig.arn : "arn:aws:apigateway:#{@config['region']}:#{MU::Cloud::AWS.credToAcct(@config['credentials'])}:#{name}"
|
|
206
200
|
when 's3'
|
|
207
201
|
arn = ''
|
|
208
202
|
end
|
|
@@ -219,13 +213,21 @@ module MU
|
|
|
219
213
|
case trig_type
|
|
220
214
|
|
|
221
215
|
when 'sns'
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
216
|
+
MU::Cloud.resourceClass("AWS", "Notifier").subscribe(trig_arn, arn, "lambda", region: @config['region'], credentials: @credentials)
|
|
217
|
+
when 'dynamodb'
|
|
218
|
+
stream = MU::Cloud::AWS.dynamostream(region: @config['region'], credentials: @config['credentials']).list_streams(table_name: trig_arn.sub(/.*?:table\//, '')).streams.first
|
|
219
|
+
# XXX guard this
|
|
220
|
+
MU.log "Adding DynamoDB Stream from #{stream.stream_arn} as trigger for #{@cloud_id}"
|
|
221
|
+
begin
|
|
222
|
+
MU::Cloud::AWS.lambda(region: @config['region'], credentials: @config['credentials']).create_event_source_mapping(
|
|
223
|
+
event_source_arn: stream.stream_arn,
|
|
224
|
+
function_name: @cloud_id,
|
|
225
|
+
starting_position: "TRIM_HORIZON" # ...whatever that is
|
|
226
|
+
)
|
|
227
|
+
rescue ::Aws::Lambda::Errors::ResourceConflictException
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# MU::Cloud.resourceClass("AWS", "NoSQLDB").subscribe(trig_arn, arn, "lambda", region: @config['region'], credentials: @credentials)
|
|
229
231
|
when 'event','cloudwatch_event', 'events'
|
|
230
232
|
# XXX don't do this, use MU::Cloud::AWS::Log
|
|
231
233
|
MU::Cloud::AWS.cloudwatch_events(region: region, credentials: @config['credentials']).put_targets({
|
|
@@ -237,9 +239,8 @@ module MU
|
|
|
237
239
|
}
|
|
238
240
|
]
|
|
239
241
|
})
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# MU.log "Creation of API Gateway integrations not yet implemented, you'll have to do this manually", MU::WARN, details: "(because we'll basically have to implement all of APIG for this)"
|
|
242
|
+
when 'apigateway'
|
|
243
|
+
addTrigger(trig_arn, "lambda", trig_arn.sub(/.*?([a-z0-9\-_]+)$/i, '\1'))
|
|
243
244
|
end
|
|
244
245
|
end
|
|
245
246
|
|
|
@@ -247,9 +248,8 @@ module MU
|
|
|
247
248
|
# Return the metadata for this Function rule
|
|
248
249
|
# @return [Hash]
|
|
249
250
|
def notify
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return deploy_struct
|
|
251
|
+
return nil if !cloud_desc
|
|
252
|
+
MU.structToHash(cloud_desc, stringify_keys: true)
|
|
253
253
|
end
|
|
254
254
|
|
|
255
255
|
# Does this resource type exist as a global (cloud-wide) artifact, or
|
|
@@ -270,14 +270,14 @@ module MU
|
|
|
270
270
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
271
271
|
# @param region [String]: The cloud provider region
|
|
272
272
|
# @return [void]
|
|
273
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
273
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
274
274
|
MU.log "AWS::Function.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
275
275
|
|
|
276
276
|
MU::Cloud::AWS.lambda(credentials: credentials, region: region).list_functions.functions.each { |f|
|
|
277
277
|
desc = MU::Cloud::AWS.lambda(credentials: credentials, region: region).get_function(
|
|
278
278
|
function_name: f.function_name
|
|
279
279
|
)
|
|
280
|
-
if desc.tags and desc.tags["MU-ID"] ==
|
|
280
|
+
if desc.tags and desc.tags["MU-ID"] == deploy_id and (desc.tags["MU-MASTER-IP"] == MU.mu_public_ip or ignoremaster)
|
|
281
281
|
MU.log "Deleting Lambda function #{f.function_name}"
|
|
282
282
|
if !noop
|
|
283
283
|
MU::Cloud::AWS.lambda(credentials: credentials, region: region).delete_function(
|
|
@@ -292,7 +292,7 @@ module MU
|
|
|
292
292
|
# Canonical Amazon Resource Number for this resource
|
|
293
293
|
# @return [String]
|
|
294
294
|
def arn
|
|
295
|
-
cloud_desc.function_arn
|
|
295
|
+
cloud_desc ? cloud_desc.function_arn : nil
|
|
296
296
|
end
|
|
297
297
|
|
|
298
298
|
# Locate an existing function.
|
|
@@ -334,6 +334,20 @@ module MU
|
|
|
334
334
|
bok['timeout'] = cloud_desc.timeout
|
|
335
335
|
|
|
336
336
|
function = MU::Cloud::AWS.lambda(region: @config['region'], credentials: @credentials).get_function(function_name: bok['name'])
|
|
337
|
+
# event_srcs = MU::Cloud::AWS.lambda(region: @config['region'], credentials: @credentials).list_event_source_mappings(function_name: @cloud_id)
|
|
338
|
+
# if event_srcs and !event_srcs.event_source_mappings.empty?
|
|
339
|
+
# MU.log "dem mappings tho #{@cloud_id}", MU::WARN, details: event_srcs
|
|
340
|
+
# end
|
|
341
|
+
|
|
342
|
+
# begin
|
|
343
|
+
# invoke_cfg = MU::Cloud::AWS.lambda(region: @config['region'], credentials: @credentials).get_function_event_invoke_config(function_name: @cloud_id)
|
|
344
|
+
# MU.log "invoke config #{@cloud_id}", MU::WARN, details: invoke_cfg
|
|
345
|
+
# rescue ::Aws::Lambda::Errors::ResourceNotFoundException
|
|
346
|
+
# end
|
|
347
|
+
|
|
348
|
+
# MU.log @cloud_id, MU::WARN, details: cloud_desc if @cloud_id == "Espier-Scheduled-Scanner"
|
|
349
|
+
# MU.log "configuration #{@cloud_id}", MU::WARN, details: MU::Cloud::AWS.lambda(region: @config['region'], credentials: @credentials).get_function_configuration(function_name: @cloud_id) if @cloud_id == "Espier-Scheduled-Scanner"
|
|
350
|
+
|
|
337
351
|
|
|
338
352
|
if function.code.repository_type == "S3"
|
|
339
353
|
bok['code'] = {}
|
|
@@ -393,16 +407,29 @@ module MU
|
|
|
393
407
|
|
|
394
408
|
if function.configuration.role
|
|
395
409
|
shortname = function.configuration.role.sub(/.*?role\/([^\/]+)$/, '\1')
|
|
396
|
-
MU.log shortname, MU::NOTICE, details: function.configuration.role
|
|
397
410
|
bok['role'] = MU::Config::Ref.get(
|
|
398
411
|
id: shortname,
|
|
399
|
-
name: shortname,
|
|
400
412
|
cloud: "AWS",
|
|
401
413
|
type: "roles"
|
|
402
414
|
)
|
|
403
415
|
end
|
|
416
|
+
|
|
417
|
+
begin
|
|
418
|
+
pol = MU::Cloud::AWS.lambda(region: @config['region'], credentials: @credentials).get_policy(function_name: @cloud_id).policy
|
|
419
|
+
MU.log @cloud_id, MU::WARN, details: JSON.parse(pol) if @cloud_id == "ESPIER-DEV-2020080900-LN-ON-DEMAND-SCANNER"
|
|
420
|
+
if pol
|
|
421
|
+
bok['triggers'] ||= []
|
|
422
|
+
JSON.parse(pol)["Statement"].each { |s|
|
|
423
|
+
bok['triggers'] << {
|
|
424
|
+
"service" => s["Principal"]["Service"].sub(/\..*/, ''),
|
|
425
|
+
"name" => s["Resource"].sub(/.*?[:\/]([^:\/]+)$/, '\1')
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
end
|
|
429
|
+
rescue ::Aws::Lambda::Errors::ResourceNotFoundException
|
|
430
|
+
end
|
|
404
431
|
#MU.log @cloud_id, MU::NOTICE, details: function
|
|
405
|
-
# XXX
|
|
432
|
+
# XXX permissions
|
|
406
433
|
|
|
407
434
|
bok
|
|
408
435
|
end
|
|
@@ -414,6 +441,22 @@ MU.log shortname, MU::NOTICE, details: function.configuration.role
|
|
|
414
441
|
def self.schema(_config)
|
|
415
442
|
toplevel_required = ["runtime"]
|
|
416
443
|
schema = {
|
|
444
|
+
"invoke_on_completion" => {
|
|
445
|
+
"type" => "object",
|
|
446
|
+
"description" => "Setting this will cause this Lambda function to be invoked when its groom phase is complete.",
|
|
447
|
+
"required" => ["invocation_type"],
|
|
448
|
+
"properties" => {
|
|
449
|
+
"invocation_type" => {
|
|
450
|
+
"type" => "string",
|
|
451
|
+
"enum" => ["RequestResponse", "Event", "Dryrun"],
|
|
452
|
+
"default" => "RequestReponse"
|
|
453
|
+
},
|
|
454
|
+
"payload" => {
|
|
455
|
+
"type" => "object",
|
|
456
|
+
"description" => "Optional input to the function, which will be formatted as JSON and sent for execution"
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
},
|
|
417
460
|
"triggers" => {
|
|
418
461
|
"type" => "array",
|
|
419
462
|
"items" => {
|
|
@@ -423,7 +466,7 @@ MU.log shortname, MU::NOTICE, details: function.configuration.role
|
|
|
423
466
|
"properties" => {
|
|
424
467
|
"service" => {
|
|
425
468
|
"type" => "string",
|
|
426
|
-
"enum" => %w{apigateway events s3 sns sqs dynamodb kinesis ses cognito alexa iot},
|
|
469
|
+
"enum" => %w{apigateway events s3 sns sqs dynamodb kinesis ses cognito alexa iot lex},
|
|
427
470
|
"description" => "The name of the AWS service that will trigger this function"
|
|
428
471
|
},
|
|
429
472
|
"name" => {
|
|
@@ -482,6 +525,28 @@ MU.log shortname, MU::NOTICE, details: function.configuration.role
|
|
|
482
525
|
def self.validateConfig(function, configurator)
|
|
483
526
|
ok = true
|
|
484
527
|
|
|
528
|
+
if function['triggers']
|
|
529
|
+
function['triggers'].each { |t|
|
|
530
|
+
mu_type = if t["service"] == "sns"
|
|
531
|
+
"notifiers"
|
|
532
|
+
elsif t["service"] == "apigateway"
|
|
533
|
+
"endpoints"
|
|
534
|
+
elsif t["service"] == "s3"
|
|
535
|
+
"buckets"
|
|
536
|
+
elsif t["service"] == "dynamodb"
|
|
537
|
+
"nosqldbs"
|
|
538
|
+
elsif t["service"] == "events"
|
|
539
|
+
"jobs"
|
|
540
|
+
elsif t["service"] == "sqs"
|
|
541
|
+
"msg_queues"
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
if mu_type
|
|
545
|
+
MU::Config.addDependency(function, t['name'], mu_type, no_create_wait: true)
|
|
546
|
+
end
|
|
547
|
+
}
|
|
548
|
+
end
|
|
549
|
+
|
|
485
550
|
if function['vpc']
|
|
486
551
|
fwname = "lambda-#{function['name']}"
|
|
487
552
|
# default to allowing pings, if no ingress_rules were specified
|
|
@@ -505,14 +570,13 @@ MU.log shortname, MU::NOTICE, details: function.configuration.role
|
|
|
505
570
|
function["add_firewall_rules"] << {"name" => fwname}
|
|
506
571
|
function["permissions"] ||= []
|
|
507
572
|
function["permissions"] << "network"
|
|
508
|
-
function
|
|
509
|
-
function['dependencies'] << {
|
|
510
|
-
"name" => fwname,
|
|
511
|
-
"type" => "firewall_rule"
|
|
512
|
-
}
|
|
573
|
+
MU::Config.addDependency(function, fwname, "firewall_rule")
|
|
513
574
|
end
|
|
514
575
|
|
|
515
|
-
|
|
576
|
+
function['role'] ||= function['iam_role']
|
|
577
|
+
function.delete("iam_role")
|
|
578
|
+
|
|
579
|
+
if !function['role']
|
|
516
580
|
policy_map = {
|
|
517
581
|
"basic" => "AWSLambdaBasicExecutionRole",
|
|
518
582
|
"kinesis" => "AWSLambdaKinesisExecutionRole",
|
|
@@ -541,13 +605,21 @@ MU.log shortname, MU::NOTICE, details: function.configuration.role
|
|
|
541
605
|
}
|
|
542
606
|
configurator.insertKitten(roledesc, "roles")
|
|
543
607
|
|
|
544
|
-
function['
|
|
545
|
-
function['iam_role'] = function['name']+"execrole"
|
|
608
|
+
function['role'] = function['name']+"execrole"
|
|
546
609
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
if function['role'].is_a?(String)
|
|
613
|
+
function['role'] = MU::Config::Ref.get(
|
|
614
|
+
name: function['role'],
|
|
615
|
+
type: "roles",
|
|
616
|
+
cloud: "AWS",
|
|
617
|
+
credentials: function['credentials']
|
|
618
|
+
)
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
if function['role']['name']
|
|
622
|
+
MU::Config.addDependency(function, function['role']['name'], "role")
|
|
551
623
|
end
|
|
552
624
|
|
|
553
625
|
ok
|
|
@@ -555,23 +627,109 @@ MU.log shortname, MU::NOTICE, details: function.configuration.role
|
|
|
555
627
|
|
|
556
628
|
private
|
|
557
629
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
# @param name [String]
|
|
562
|
-
def get_role_arn(name)
|
|
563
|
-
sib_role = @deploy.findLitterMate(name: name, type: "roles")
|
|
564
|
-
return sib_role.cloudobj.arn if sib_role
|
|
630
|
+
def get_properties
|
|
631
|
+
role_obj = MU::Config::Ref.get(@config['role']).kitten(@deploy, cloud: "AWS")
|
|
632
|
+
raise MuError.new "Failed to fetch object from role reference", details: @config['role'].to_h if !role_obj
|
|
565
633
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
634
|
+
lambda_properties = {
|
|
635
|
+
code: {},
|
|
636
|
+
function_name: @mu_name,
|
|
637
|
+
handler: @config['handler'],
|
|
638
|
+
publish: true,
|
|
639
|
+
role: role_obj.arn,
|
|
640
|
+
runtime: @config['runtime'],
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
if @config['code']['zip_file'] or @config['code']['path']
|
|
644
|
+
tempfile = nil
|
|
645
|
+
if @config['code']['path']
|
|
646
|
+
tempfile = Tempfile.new
|
|
647
|
+
MU.log "#{@mu_name} using code at #{@config['code']['path']}"
|
|
648
|
+
MU::Master.zipDir(@config['code']['path'], tempfile.path)
|
|
649
|
+
@config['code']['zip_file'] = tempfile.path
|
|
650
|
+
else
|
|
651
|
+
MU.log "#{@mu_name} using code packaged at #{@config['code']['zip_file']}"
|
|
652
|
+
end
|
|
653
|
+
zip = File.read(@config['code']['zip_file'])
|
|
654
|
+
@code_sha256 = Base64.encode64(Digest::SHA256.digest(zip)).chomp
|
|
655
|
+
lambda_properties[:code][:zip_file] = zip
|
|
656
|
+
if tempfile
|
|
657
|
+
tempfile.close
|
|
658
|
+
tempfile.unlink
|
|
659
|
+
end
|
|
660
|
+
else
|
|
661
|
+
lambda_properties[:code][:s3_bucket] = @config['code']['s3_bucket']
|
|
662
|
+
lambda_properties[:code][:s3_key] = @config['code']['s3_key']
|
|
663
|
+
if @config['code']['s3_object_version']
|
|
664
|
+
lambda_properties[:code][:s3_object_version] = @config['code']['s3_object_version']
|
|
665
|
+
end
|
|
666
|
+
# XXX need to download to a temporarily file, read it in, and calculate the digest in order to trigger updates in groom
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
if @config.has_key?('timeout')
|
|
670
|
+
lambda_properties[:timeout] = @config['timeout'].to_i ## secs
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
if @config.has_key?('memory')
|
|
674
|
+
lambda_properties[:memory_size] = @config['memory'].to_i
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
SIBLING_VARS.each_key { |sib_type|
|
|
678
|
+
siblings = @deploy.findLitterMate(return_all: true, type: sib_type, cloud: "AWS")
|
|
679
|
+
if siblings
|
|
680
|
+
siblings.each_value { |sibling|
|
|
681
|
+
metadata = sibling.notify
|
|
682
|
+
if !metadata
|
|
683
|
+
MU.log "Failed to extract metadata from sibling #{sibling}", MU::WARN
|
|
684
|
+
next
|
|
685
|
+
end
|
|
686
|
+
SIBLING_VARS[sib_type].each { |var|
|
|
687
|
+
if metadata[var]
|
|
688
|
+
@config['environment_variables'] ||= []
|
|
689
|
+
@config['environment_variables'] << {
|
|
690
|
+
"key" => (sibling.config['name']+"_"+var).gsub(/[^a-z0-9_]/i, '_'),
|
|
691
|
+
"value" => metadata[var]
|
|
692
|
+
}
|
|
693
|
+
end
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
end
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
if @config.has_key?('environment_variables')
|
|
700
|
+
lambda_properties[:environment] = {
|
|
701
|
+
variables: Hash[@config['environment_variables'].map { |v| [v['key'], v['value']] }]
|
|
702
|
+
}
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
lambda_properties[:tags] = {}
|
|
706
|
+
MU::MommaCat.listStandardTags.each_pair { |k, v|
|
|
707
|
+
lambda_properties[:tags][k] = v
|
|
708
|
+
}
|
|
709
|
+
if @config['tags']
|
|
710
|
+
@config['tags'].each { |tag|
|
|
711
|
+
lambda_properties[:tags][tag['key']] = tag['value']
|
|
712
|
+
}
|
|
573
713
|
end
|
|
574
|
-
|
|
714
|
+
|
|
715
|
+
if @config.has_key?('vpc')
|
|
716
|
+
sgs = []
|
|
717
|
+
if @config['add_firewall_rules']
|
|
718
|
+
@config['add_firewall_rules'].each { |sg|
|
|
719
|
+
sg = @deploy.findLitterMate(type: "firewall_rule", name: sg['name'])
|
|
720
|
+
sgs << sg.cloud_id if sg and sg.cloud_id
|
|
721
|
+
}
|
|
722
|
+
end
|
|
723
|
+
if !@vpc
|
|
724
|
+
raise MuError, "Function #{@config['name']} had a VPC configured, but none was loaded"
|
|
725
|
+
end
|
|
726
|
+
lambda_properties[:vpc_config] = {
|
|
727
|
+
:subnet_ids => @vpc.subnets.map { |s| s.cloud_id },
|
|
728
|
+
:security_group_ids => sgs
|
|
729
|
+
}
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
lambda_properties
|
|
575
733
|
end
|
|
576
734
|
|
|
577
735
|
end
|