cloud-mu 1.9.0.pre.beta → 2.0.0.pre.alpha
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/Berksfile +16 -54
- data/Berksfile.lock +14 -62
- data/bin/mu-aws-setup +131 -108
- data/bin/mu-configure +311 -74
- data/bin/mu-gcp-setup +84 -62
- data/bin/mu-load-config.rb +46 -2
- data/bin/mu-self-update +11 -9
- data/bin/mu-upload-chef-artifacts +4 -4
- data/{mu.gemspec → cloud-mu.gemspec} +2 -2
- data/cookbooks/awscli/Berksfile +8 -0
- data/cookbooks/mu-activedirectory/Berksfile +11 -0
- data/cookbooks/mu-firewall/Berksfile +9 -0
- data/cookbooks/mu-firewall/metadata.rb +1 -1
- data/cookbooks/mu-glusterfs/Berksfile +10 -0
- data/cookbooks/mu-jenkins/Berksfile +14 -0
- data/cookbooks/mu-master/Berksfile +23 -0
- data/cookbooks/mu-master/attributes/default.rb +1 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +1 -1
- data/cookbooks/mu-master/recipes/init.rb +7 -3
- data/cookbooks/mu-master/recipes/ssl-certs.rb +1 -0
- data/cookbooks/mu-mongo/Berksfile +10 -0
- data/cookbooks/mu-openvpn/Berksfile +11 -0
- data/cookbooks/mu-php54/Berksfile +13 -0
- data/cookbooks/mu-splunk/Berksfile +10 -0
- data/cookbooks/mu-tools/Berksfile +21 -0
- data/cookbooks/mu-tools/files/default/Mu_CA.pem +15 -15
- data/cookbooks/mu-utility/Berksfile +9 -0
- data/cookbooks/mu-utility/metadata.rb +2 -1
- data/cookbooks/nagios/Berksfile +7 -4
- data/cookbooks/s3fs/Berksfile +9 -0
- data/environments/dev.json +6 -6
- data/environments/prod.json +6 -6
- data/modules/mu.rb +20 -42
- data/modules/mu/cleanup.rb +102 -100
- data/modules/mu/cloud.rb +90 -28
- data/modules/mu/clouds/aws.rb +449 -218
- data/modules/mu/clouds/aws/alarm.rb +29 -17
- data/modules/mu/clouds/aws/cache_cluster.rb +78 -64
- data/modules/mu/clouds/aws/collection.rb +25 -18
- data/modules/mu/clouds/aws/container_cluster.rb +73 -66
- data/modules/mu/clouds/aws/database.rb +124 -116
- data/modules/mu/clouds/aws/dnszone.rb +27 -20
- data/modules/mu/clouds/aws/firewall_rule.rb +30 -22
- data/modules/mu/clouds/aws/folder.rb +18 -3
- data/modules/mu/clouds/aws/function.rb +77 -23
- data/modules/mu/clouds/aws/group.rb +19 -12
- data/modules/mu/clouds/aws/habitat.rb +153 -0
- data/modules/mu/clouds/aws/loadbalancer.rb +59 -52
- data/modules/mu/clouds/aws/log.rb +30 -23
- data/modules/mu/clouds/aws/msg_queue.rb +29 -20
- data/modules/mu/clouds/aws/notifier.rb +222 -0
- data/modules/mu/clouds/aws/role.rb +178 -90
- data/modules/mu/clouds/aws/search_domain.rb +40 -24
- data/modules/mu/clouds/aws/server.rb +169 -137
- data/modules/mu/clouds/aws/server_pool.rb +60 -83
- data/modules/mu/clouds/aws/storage_pool.rb +59 -31
- data/modules/mu/clouds/aws/user.rb +36 -27
- data/modules/mu/clouds/aws/userdata/linux.erb +101 -93
- data/modules/mu/clouds/aws/vpc.rb +250 -189
- data/modules/mu/clouds/azure.rb +132 -0
- data/modules/mu/clouds/cloudformation.rb +65 -1
- data/modules/mu/clouds/cloudformation/alarm.rb +8 -0
- data/modules/mu/clouds/cloudformation/cache_cluster.rb +7 -0
- data/modules/mu/clouds/cloudformation/collection.rb +7 -0
- data/modules/mu/clouds/cloudformation/database.rb +7 -0
- data/modules/mu/clouds/cloudformation/dnszone.rb +7 -0
- data/modules/mu/clouds/cloudformation/firewall_rule.rb +9 -2
- data/modules/mu/clouds/cloudformation/loadbalancer.rb +7 -0
- data/modules/mu/clouds/cloudformation/log.rb +7 -0
- data/modules/mu/clouds/cloudformation/server.rb +7 -0
- data/modules/mu/clouds/cloudformation/server_pool.rb +7 -0
- data/modules/mu/clouds/cloudformation/vpc.rb +7 -0
- data/modules/mu/clouds/google.rb +214 -110
- data/modules/mu/clouds/google/container_cluster.rb +42 -24
- data/modules/mu/clouds/google/database.rb +15 -6
- data/modules/mu/clouds/google/firewall_rule.rb +17 -25
- data/modules/mu/clouds/google/group.rb +13 -5
- data/modules/mu/clouds/google/habitat.rb +105 -0
- data/modules/mu/clouds/google/loadbalancer.rb +28 -20
- data/modules/mu/clouds/google/server.rb +93 -354
- data/modules/mu/clouds/google/server_pool.rb +18 -10
- data/modules/mu/clouds/google/user.rb +22 -14
- data/modules/mu/clouds/google/vpc.rb +97 -69
- data/modules/mu/config.rb +133 -38
- data/modules/mu/config/alarm.rb +25 -0
- data/modules/mu/config/cache_cluster.rb +5 -3
- data/modules/mu/config/cache_cluster.yml +23 -0
- data/modules/mu/config/database.rb +25 -16
- data/modules/mu/config/database.yml +3 -3
- data/modules/mu/config/function.rb +1 -2
- data/modules/mu/config/{project.rb → habitat.rb} +10 -10
- data/modules/mu/config/notifier.rb +85 -0
- data/modules/mu/config/notifier.yml +9 -0
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/search_domain.yml +2 -2
- data/modules/mu/config/server.rb +13 -1
- data/modules/mu/config/server.yml +3 -3
- data/modules/mu/config/server_pool.rb +3 -1
- data/modules/mu/config/storage_pool.rb +3 -1
- data/modules/mu/config/storage_pool.yml +19 -0
- data/modules/mu/config/vpc.rb +70 -8
- data/modules/mu/groomers/chef.rb +2 -3
- data/modules/mu/kittens.rb +500 -122
- data/modules/mu/master.rb +5 -5
- data/modules/mu/mommacat.rb +151 -91
- data/modules/tests/super_complex_bok.yml +12 -0
- data/modules/tests/super_simple_bok.yml +12 -0
- data/spec/mu/clouds/azure_spec.rb +82 -0
- data/spec/spec_helper.rb +105 -0
- metadata +26 -5
- data/modules/mu/clouds/aws/notification.rb +0 -139
- data/modules/mu/config/notification.rb +0 -44
data/modules/mu/config.rb
CHANGED
@@ -39,9 +39,10 @@ module MU
|
|
39
39
|
rescue NoMethodError
|
40
40
|
"AWS"
|
41
41
|
end
|
42
|
-
|
42
|
+
# XXX this can be more generic (loop through supportedClouds and try this)
|
43
|
+
if MU::Cloud::Google.hosted?
|
43
44
|
"Google"
|
44
|
-
elsif MU::Cloud::AWS.hosted
|
45
|
+
elsif MU::Cloud::AWS.hosted?
|
45
46
|
"AWS"
|
46
47
|
end
|
47
48
|
end
|
@@ -765,14 +766,27 @@ module MU
|
|
765
766
|
# @param name [String]: The name of the resource being checked
|
766
767
|
# @param type [String]: The type of resource being checked
|
767
768
|
# @return [Boolean]
|
768
|
-
def haveLitterMate?(name, type)
|
769
|
+
def haveLitterMate?(name, type, has_multiple: false)
|
769
770
|
@kittencfg_semaphore.synchronize {
|
771
|
+
matches = []
|
770
772
|
shortclass, cfg_name, cfg_plural, classname = MU::Cloud.getResourceNames(type)
|
771
|
-
@kittens[cfg_plural]
|
772
|
-
|
773
|
-
|
773
|
+
if @kittens[cfg_plural]
|
774
|
+
@kittens[cfg_plural].each { |kitten|
|
775
|
+
if kitten['name'] == name.to_s or kitten['virtual_name'] == name.to_s
|
776
|
+
if has_multiple
|
777
|
+
matches << kitten
|
778
|
+
else
|
779
|
+
return kitten
|
780
|
+
end
|
781
|
+
end
|
782
|
+
}
|
783
|
+
end
|
784
|
+
if has_multiple
|
785
|
+
return matches
|
786
|
+
else
|
787
|
+
return false
|
788
|
+
end
|
774
789
|
}
|
775
|
-
false
|
776
790
|
end
|
777
791
|
|
778
792
|
# Remove a resource from the current stack
|
@@ -782,13 +796,15 @@ module MU
|
|
782
796
|
@kittencfg_semaphore.synchronize {
|
783
797
|
shortclass, cfg_name, cfg_plural, classname = MU::Cloud.getResourceNames(type)
|
784
798
|
deletia = nil
|
785
|
-
@kittens[cfg_plural]
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
799
|
+
if @kittens[cfg_plural]
|
800
|
+
@kittens[cfg_plural].each { |kitten|
|
801
|
+
if kitten['name'] == name
|
802
|
+
deletia = kitten
|
803
|
+
break
|
804
|
+
end
|
805
|
+
}
|
806
|
+
@kittens[type].delete(deletia) if !deletia.nil?
|
807
|
+
end
|
792
808
|
}
|
793
809
|
end
|
794
810
|
|
@@ -868,6 +884,9 @@ module MU
|
|
868
884
|
# Does this resource go in a VPC?
|
869
885
|
if !descriptor["vpc"].nil? and !delay_validation
|
870
886
|
descriptor['vpc']['cloud'] = descriptor['cloud']
|
887
|
+
if descriptor['credentials']
|
888
|
+
descriptor['vpc']['credentials'] ||= descriptor['credentials']
|
889
|
+
end
|
871
890
|
if descriptor['vpc']['region'].nil? and !descriptor['region'].nil? and !descriptor['region'].empty? and descriptor['vpc']['cloud'] != "Google"
|
872
891
|
descriptor['vpc']['region'] = descriptor['region']
|
873
892
|
end
|
@@ -896,6 +915,7 @@ module MU
|
|
896
915
|
self,
|
897
916
|
dflt_region: descriptor['region'],
|
898
917
|
is_sibling: true,
|
918
|
+
credentials: descriptor['credentials'],
|
899
919
|
sibling_vpcs: @kittens['vpcs'])
|
900
920
|
ok = false
|
901
921
|
end
|
@@ -907,11 +927,19 @@ module MU
|
|
907
927
|
if !MU::Config::VPC.processReference(descriptor["vpc"], cfg_plural,
|
908
928
|
"#{shortclass} #{descriptor['name']}",
|
909
929
|
self,
|
930
|
+
credentials: descriptor['credentials'],
|
910
931
|
dflt_region: descriptor['region'])
|
911
932
|
MU.log "insertKitten was called from #{caller[0]}", MU::ERR
|
912
933
|
ok = false
|
913
934
|
end
|
914
935
|
end
|
936
|
+
|
937
|
+
# if we didn't specify credentials but can inherit some from our target
|
938
|
+
# VPC, do so
|
939
|
+
if descriptor["vpc"]["credentials"]
|
940
|
+
descriptor["credentials"] ||= descriptor["vpc"]["credentials"]
|
941
|
+
end
|
942
|
+
|
915
943
|
# Clean crud out of auto-created VPC declarations so they don't trip
|
916
944
|
# the schema validator when it's invoked later.
|
917
945
|
if !["server", "server_pool", "database"].include?(cfg_name)
|
@@ -933,7 +961,12 @@ module MU
|
|
933
961
|
["server", "server_pool", "database"].include?(cfg_name))
|
934
962
|
descriptor['ingress_rules'] ||= []
|
935
963
|
|
936
|
-
acl = {
|
964
|
+
acl = {
|
965
|
+
"name" => fwname,
|
966
|
+
"rules" => descriptor['ingress_rules'],
|
967
|
+
"region" => descriptor['region'],
|
968
|
+
"credentials" => descriptor["credentials"]
|
969
|
+
}
|
937
970
|
acl["vpc"] = descriptor['vpc'].dup if descriptor['vpc']
|
938
971
|
["optional_tags", "tags", "cloud", "project"].each { |param|
|
939
972
|
acl[param] = descriptor[param] if descriptor[param]
|
@@ -992,6 +1025,7 @@ module MU
|
|
992
1025
|
descriptor["alarms"].each { |alarm|
|
993
1026
|
alarm["name"] = "#{cfg_name}-#{descriptor["name"]}-#{alarm["name"]}"
|
994
1027
|
alarm['dimensions'] = [] if !alarm['dimensions']
|
1028
|
+
alarm["credentials"] = descriptor["credentials"]
|
995
1029
|
alarm["#TARGETCLASS"] = cfg_name
|
996
1030
|
alarm["#TARGETNAME"] = descriptor['name']
|
997
1031
|
alarm['cloud'] = descriptor['cloud']
|
@@ -1091,9 +1125,13 @@ module MU
|
|
1091
1125
|
if ok
|
1092
1126
|
parser = Object.const_get("MU").const_get("Cloud").const_get(descriptor["cloud"]).const_get(shortclass.to_s)
|
1093
1127
|
plain_descriptor = MU::Config.manxify(Marshal.load(Marshal.dump(descriptor)))
|
1094
|
-
|
1128
|
+
passed = parser.validateConfig(plain_descriptor, self)
|
1095
1129
|
|
1096
|
-
|
1130
|
+
if passed
|
1131
|
+
descriptor.merge!(plain_descriptor)
|
1132
|
+
else
|
1133
|
+
ok = false
|
1134
|
+
end
|
1097
1135
|
descriptor['#MU_VALIDATED'] = true
|
1098
1136
|
end
|
1099
1137
|
|
@@ -1123,6 +1161,15 @@ module MU
|
|
1123
1161
|
}
|
1124
1162
|
end
|
1125
1163
|
|
1164
|
+
# Configuration chunk for choosing a set of cloud credentials
|
1165
|
+
# @return [Hash]
|
1166
|
+
def self.credentials_primitive
|
1167
|
+
{
|
1168
|
+
"type" => "string",
|
1169
|
+
"description" => "Specify a non-default set of credentials to use when authenticating to cloud provider APIs, as listed in `mu.yaml` under each provider's subsection. If "
|
1170
|
+
}
|
1171
|
+
end
|
1172
|
+
|
1126
1173
|
# Configuration chunk for creating resource tags as an array of key/value
|
1127
1174
|
# pairs.
|
1128
1175
|
# @return [Hash]
|
@@ -1178,7 +1225,7 @@ module MU
|
|
1178
1225
|
# @param cloud [String]: The parent resource's cloud plugin identifier
|
1179
1226
|
# @param region [String]: Cloud provider region, if applicable.
|
1180
1227
|
# @return [Hash<String>]: A dependency description that the calling resource can then add to itself.
|
1181
|
-
def adminFirewallRuleset(vpc: nil, admin_ip: nil, region: nil, cloud: nil)
|
1228
|
+
def adminFirewallRuleset(vpc: nil, admin_ip: nil, region: nil, cloud: nil, credentials: nil)
|
1182
1229
|
if !cloud or (cloud == "AWS" and !region)
|
1183
1230
|
raise MuError, "Cannot call adminFirewallRuleset without specifying the parent's region and cloud provider"
|
1184
1231
|
end
|
@@ -1189,6 +1236,7 @@ module MU
|
|
1189
1236
|
hosts << "#{admin_ip}/32" if admin_ip
|
1190
1237
|
hosts.uniq!
|
1191
1238
|
name = "admin"
|
1239
|
+
name += credentials.to_s if credentials
|
1192
1240
|
realvpc = nil
|
1193
1241
|
|
1194
1242
|
if vpc
|
@@ -1223,9 +1271,9 @@ module MU
|
|
1223
1271
|
]
|
1224
1272
|
end
|
1225
1273
|
|
1226
|
-
acl = {"name" => name, "rules" => rules, "vpc" => realvpc, "cloud" => cloud, "admin" => true}
|
1274
|
+
acl = {"name" => name, "rules" => rules, "vpc" => realvpc, "cloud" => cloud, "admin" => true, "credentials" => credentials }
|
1227
1275
|
acl.delete("vpc") if !acl["vpc"]
|
1228
|
-
acl["region"]
|
1276
|
+
acl["region"] = region if !region.nil? and !region.empty?
|
1229
1277
|
@admin_firewall_rules << acl if !@admin_firewall_rules.include?(acl)
|
1230
1278
|
return {"type" => "firewall_rule", "name" => name}
|
1231
1279
|
end
|
@@ -1438,12 +1486,15 @@ module MU
|
|
1438
1486
|
# TODO check for loops
|
1439
1487
|
def self.check_dependencies(config)
|
1440
1488
|
ok = true
|
1489
|
+
|
1441
1490
|
config.each { |type|
|
1442
1491
|
if type.instance_of?(Array)
|
1443
1492
|
type.each { |container|
|
1444
1493
|
if container.instance_of?(Array)
|
1445
1494
|
container.each { |resource|
|
1446
1495
|
if resource.kind_of?(Hash) and resource["dependencies"] != nil
|
1496
|
+
append = []
|
1497
|
+
delete = []
|
1447
1498
|
resource["dependencies"].each { |dependency|
|
1448
1499
|
collection = dependency["type"]+"s"
|
1449
1500
|
found = false
|
@@ -1452,6 +1503,14 @@ module MU
|
|
1452
1503
|
config[collection].each { |service|
|
1453
1504
|
names_seen << service["name"].to_s
|
1454
1505
|
found = true if service["name"].to_s == dependency["name"].to_s
|
1506
|
+
if service["virtual_name"]
|
1507
|
+
names_seen << service["virtual_name"].to_s
|
1508
|
+
found = true if service["virtual_name"].to_s == dependency["name"].to_s
|
1509
|
+
append_me = dependency.dup
|
1510
|
+
append_me['name'] = service['name']
|
1511
|
+
append << append_me
|
1512
|
+
delete << dependency
|
1513
|
+
end
|
1455
1514
|
}
|
1456
1515
|
end
|
1457
1516
|
if !found
|
@@ -1459,6 +1518,15 @@ module MU
|
|
1459
1518
|
ok = false
|
1460
1519
|
end
|
1461
1520
|
}
|
1521
|
+
if append.size > 0
|
1522
|
+
append.uniq!
|
1523
|
+
resource["dependencies"].concat(append)
|
1524
|
+
end
|
1525
|
+
if delete.size > 0
|
1526
|
+
delete.each { |delete_me|
|
1527
|
+
resource["dependencies"].delete(delete_me)
|
1528
|
+
}
|
1529
|
+
end
|
1462
1530
|
end
|
1463
1531
|
}
|
1464
1532
|
end
|
@@ -1534,23 +1602,31 @@ module MU
|
|
1534
1602
|
# @param type [String]: The type of resource this is ("servers" etc)
|
1535
1603
|
def inheritDefaults(kitten, type)
|
1536
1604
|
kitten['cloud'] ||= MU::Config.defaultCloud
|
1605
|
+
cloudclass = Object.const_get("MU").const_get("Cloud").const_get(kitten['cloud'])
|
1606
|
+
shortclass, cfg_name, cfg_plural, classname = MU::Cloud.getResourceNames(type)
|
1607
|
+
resclass = Object.const_get("MU").const_get("Cloud").const_get(kitten['cloud']).const_get(shortclass)
|
1608
|
+
|
1609
|
+
schema_fields = ["us_only", "scrub_mu_isms", "credentials"]
|
1610
|
+
if !resclass.isGlobal?
|
1611
|
+
schema_fields << "region"
|
1612
|
+
end
|
1537
1613
|
|
1538
|
-
schema_fields = ["region", "us_only", "scrub_mu_isms"]
|
1539
1614
|
if kitten['cloud'] == "Google"
|
1540
|
-
kitten["project"] ||= MU::Cloud::Google.defaultProject
|
1615
|
+
kitten["project"] ||= MU::Cloud::Google.defaultProject(kitten['credentials'])
|
1541
1616
|
schema_fields << "project"
|
1542
1617
|
if kitten['region'].nil? and !kitten['#MU_CLOUDCLASS'].nil? and
|
1618
|
+
!resclass.isGlobal? and
|
1543
1619
|
![MU::Cloud::VPC, MU::Cloud::FirewallRule].include?(kitten['#MU_CLOUDCLASS'])
|
1544
|
-
if
|
1545
|
-
raise ValidationError, "Google resource declared without a region, but no default Google region declared in mu.yaml"
|
1620
|
+
if MU::Cloud::Google.myRegion((kitten['credentials'])).nil?
|
1621
|
+
raise ValidationError, "Google '#{type}' resource '#{kitten['name']}' declared without a region, but no default Google region declared in mu.yaml under #{kitten['credentials'].nil? ? "default" : kitten['credentials']} credential set"
|
1546
1622
|
end
|
1547
|
-
kitten['region'] ||=
|
1623
|
+
kitten['region'] ||= MU::Cloud::Google.myRegion(kitten['credentials'])
|
1548
1624
|
end
|
1549
|
-
|
1550
|
-
if
|
1551
|
-
raise ValidationError, "AWS resource declared without a region, but no default AWS region
|
1625
|
+
elsif !resclass.isGlobal?
|
1626
|
+
if MU::Cloud::AWS.myRegion.nil?
|
1627
|
+
raise ValidationError, "AWS resource declared without a region, but no default AWS region found"
|
1552
1628
|
end
|
1553
|
-
kitten['region'] ||=
|
1629
|
+
kitten['region'] ||= MU::Cloud::AWS.myRegion
|
1554
1630
|
end
|
1555
1631
|
|
1556
1632
|
kitten['us_only'] ||= @config['us_only']
|
@@ -1559,13 +1635,16 @@ module MU
|
|
1559
1635
|
kitten['scrub_mu_isms'] ||= @config['scrub_mu_isms']
|
1560
1636
|
kitten['scrub_mu_isms'] ||= false
|
1561
1637
|
|
1638
|
+
kitten['credentials'] ||= @config['credentials']
|
1639
|
+
kitten['credentials'] ||= cloudclass.credConfig(name_only: true)
|
1640
|
+
|
1562
1641
|
kitten["dependencies"] ||= []
|
1563
1642
|
|
1564
1643
|
# Make sure the schema knows about these "new" fields, so that validation
|
1565
1644
|
# doesn't trip over them.
|
1566
1645
|
schema_fields.each { |field|
|
1567
1646
|
if @@schema["properties"][field]
|
1568
|
-
MU.log "Adding #{field} to schema for #{type} #{kitten['cloud']}", MU::DEBUG
|
1647
|
+
MU.log "Adding #{field} to schema for #{type} #{kitten['cloud']}", MU::DEBUG, details: @@schema["properties"][field]
|
1569
1648
|
@@schema["properties"][type]["items"]["properties"][field] ||= @@schema["properties"][field]
|
1570
1649
|
end
|
1571
1650
|
}
|
@@ -1606,12 +1685,23 @@ module MU
|
|
1606
1685
|
|
1607
1686
|
# Make sure validation has been called for all on-the-fly generated
|
1608
1687
|
# resources.
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1688
|
+
validated_something_new = false
|
1689
|
+
begin
|
1690
|
+
validated_something_new = false
|
1691
|
+
types.each { |type|
|
1692
|
+
@kittens[type].each { |descriptor|
|
1693
|
+
if !descriptor["#MU_VALIDATED"]
|
1694
|
+
validated_something_new = true
|
1695
|
+
ok = false if !insertKitten(descriptor, type)
|
1696
|
+
end
|
1697
|
+
}
|
1614
1698
|
}
|
1699
|
+
end while validated_something_new
|
1700
|
+
|
1701
|
+
# Do another pass of resolving intra-stack VPC peering, in case an
|
1702
|
+
# early-parsing VPC needs more details from a later-parsing one
|
1703
|
+
@kittens["vpcs"].each { |vpc|
|
1704
|
+
ok = false if !MU::Config::VPC.resolvePeers(vpc, self)
|
1615
1705
|
}
|
1616
1706
|
|
1617
1707
|
# add some default holes to allow dependent instances into databases
|
@@ -1779,7 +1869,7 @@ module MU
|
|
1779
1869
|
prefixes << "# **REQUIRED**" if required and schema['default'].nil?
|
1780
1870
|
prefixes << "# **"+schema["prefix"]+"**" if schema["prefix"]
|
1781
1871
|
prefixes << "# **Default: `#{schema['default']}`**" if !schema['default'].nil?
|
1782
|
-
if !schema['enum'].nil?
|
1872
|
+
if !schema['enum'].nil? and !schema["enum"].empty?
|
1783
1873
|
prefixes << "# **Must be one of: `#{schema['enum'].join(', ')}`**"
|
1784
1874
|
elsif !schema['pattern'].nil?
|
1785
1875
|
# XXX unquoted regex chars confuse the hell out of YARD. How do we
|
@@ -1871,10 +1961,10 @@ module MU
|
|
1871
1961
|
},
|
1872
1962
|
"project" => {
|
1873
1963
|
"type" => "string",
|
1874
|
-
"description" => "GOOGLE: The project into which to deploy resources"
|
1875
|
-
"default" => MU::Cloud::Google.defaultProject
|
1964
|
+
"description" => "GOOGLE: The project into which to deploy resources"
|
1876
1965
|
},
|
1877
1966
|
"region" => MU::Config.region_primitive,
|
1967
|
+
"credentials" => MU::Config.credentials_primitive,
|
1878
1968
|
"us_only" => {
|
1879
1969
|
"type" => "boolean",
|
1880
1970
|
"description" => "For resources which span regions, restrict to regions inside the United States",
|
@@ -1983,8 +2073,13 @@ module MU
|
|
1983
2073
|
"type" => "array",
|
1984
2074
|
"items" => schemaclass.schema
|
1985
2075
|
}
|
2076
|
+
@@schema["properties"][cfg[:cfg_plural]]["items"]["properties"]["virtual_name"] = {
|
2077
|
+
"description" => "Internal use.",
|
2078
|
+
"type" => "string"
|
2079
|
+
}
|
1986
2080
|
@@schema["properties"][cfg[:cfg_plural]]["items"]["properties"]["dependencies"] = MU::Config.dependencies_primitive
|
1987
2081
|
@@schema["properties"][cfg[:cfg_plural]]["items"]["properties"]["cloud"] = MU::Config.cloud_primitive
|
2082
|
+
@@schema["properties"][cfg[:cfg_plural]]["items"]["properties"]["credentials"] = MU::Config.credentials_primitive
|
1988
2083
|
@@schema["properties"][cfg[:cfg_plural]]["items"]["title"] = type.to_s
|
1989
2084
|
rescue NameError => e
|
1990
2085
|
failed << type
|
data/modules/mu/config/alarm.rb
CHANGED
@@ -263,6 +263,31 @@ module MU
|
|
263
263
|
}
|
264
264
|
end
|
265
265
|
|
266
|
+
if alarm["enable_notifications"]
|
267
|
+
if !alarm["notification_group"].match(/^arn:/i)
|
268
|
+
if !configurator.haveLitterMate?(alarm["notification_group"], "notifiers")
|
269
|
+
notifier = {
|
270
|
+
"name" => alarm["notification_group"],
|
271
|
+
"region" => alarm["region"],
|
272
|
+
"cloud" => alarm["cloud"],
|
273
|
+
"credentials" => alarm["credentials"],
|
274
|
+
"subscriptions" => [
|
275
|
+
{
|
276
|
+
"endpoint" => alarm["notification_endpoint"],
|
277
|
+
"type" => alarm["notification_type"],
|
278
|
+
}
|
279
|
+
]
|
280
|
+
}
|
281
|
+
ok = false if !configurator.insertKitten(notifier, "notifiers")
|
282
|
+
end
|
283
|
+
alarm["dependencies"] ||= []
|
284
|
+
alarm["dependencies"] << {
|
285
|
+
"name" => alarm["notification_group"],
|
286
|
+
"type" => "notifier"
|
287
|
+
}
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
266
291
|
ok
|
267
292
|
end
|
268
293
|
|
@@ -148,10 +148,10 @@ module MU
|
|
148
148
|
end
|
149
149
|
|
150
150
|
# Generic pre-processing of {MU::Config::BasketofKittens::cache_clusters}, bare and unvalidated.
|
151
|
-
# @param
|
151
|
+
# @param cluster [Hash]: The resource to process and validate
|
152
152
|
# @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
153
153
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
154
|
-
def self.validate(
|
154
|
+
def self.validate(cluster, configurator)
|
155
155
|
ok = true
|
156
156
|
if cluster["creation_style"] != "new" && cluster["identifier"].nil?
|
157
157
|
MU.log "CacheCluster #{cluster['name']}'s creation_style is set to #{cluster['creation_style']} but no identifier was provided. Either set creation_style to new or provide an identifier", MU::ERR
|
@@ -163,7 +163,9 @@ module MU
|
|
163
163
|
end
|
164
164
|
cluster["multi_az"] = true if cluster["node_count"] > 1
|
165
165
|
|
166
|
-
|
166
|
+
if !cluster['scrub_mu_isms']
|
167
|
+
cluster['dependencies'] << configurator.adminFirewallRuleset(vpc: cluster['vpc'], region: cluster['region'], cloud: cluster['cloud'], credentials: cluster['credentials'])
|
168
|
+
end
|
167
169
|
|
168
170
|
ok
|
169
171
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<% if $complexity == "complex" %>
|
2
|
+
name: redis
|
3
|
+
credentials: egtprod
|
4
|
+
engine: redis
|
5
|
+
creation_style: new
|
6
|
+
size: cache.t2.medium
|
7
|
+
name: memcache
|
8
|
+
credentials: egtprod
|
9
|
+
creation_style: new
|
10
|
+
engine: memcached
|
11
|
+
size: cache.t2.medium
|
12
|
+
<% else %>
|
13
|
+
name: redis
|
14
|
+
credentials: egtprod
|
15
|
+
engine: redis
|
16
|
+
creation_style: new
|
17
|
+
size: cache.t2.medium
|
18
|
+
name: memcache
|
19
|
+
credentials: egtprod
|
20
|
+
creation_style: new
|
21
|
+
engine: memcached
|
22
|
+
size: cache.t2.medium
|
23
|
+
<% end %>
|
@@ -179,11 +179,11 @@ module MU
|
|
179
179
|
},
|
180
180
|
"create_cluster" => {
|
181
181
|
"type" => "boolean",
|
182
|
-
"description" => "
|
182
|
+
"description" => "Create a database cluster instead of a standalone database.",
|
183
183
|
"default_if" => [
|
184
184
|
{
|
185
185
|
"key_is" => "engine",
|
186
|
-
"value_is" => "aurora",
|
186
|
+
"value_is" => "aurora-mysql",
|
187
187
|
"set" => true
|
188
188
|
}
|
189
189
|
]
|
@@ -341,20 +341,27 @@ module MU
|
|
341
341
|
# Automatically manufacture another database object, which will serve
|
342
342
|
# as a read replica of this one, if we've set create_read_replica.
|
343
343
|
if db['create_read_replica']
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
"
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
344
|
+
if db['create_cluster']
|
345
|
+
db["create_read_replica"] = false
|
346
|
+
MU.log "Ignoring extraneous create_read_replica flag on database cluster #{db['name']}", MU::WARN
|
347
|
+
else
|
348
|
+
replica = Marshal.load(Marshal.dump(db))
|
349
|
+
replica['name'] = db['name']+"-replica"
|
350
|
+
replica["credentials"] = db["credentials"]
|
351
|
+
replica['create_read_replica'] = false
|
352
|
+
replica["create_cluster"] = false
|
353
|
+
replica['read_replica_of'] = {
|
354
|
+
"db_name" => db['name'],
|
355
|
+
"cloud" => db['cloud'],
|
356
|
+
"region" => db['read_replica_region'] || db['region']
|
357
|
+
}
|
358
|
+
replica['dependencies'] << {
|
359
|
+
"type" => "database",
|
360
|
+
"name" => db["name"],
|
361
|
+
"phase" => "groom"
|
362
|
+
}
|
363
|
+
read_replicas << replica
|
364
|
+
end
|
358
365
|
end
|
359
366
|
|
360
367
|
# Do database cluster nodes the same way we do read replicas, by
|
@@ -364,7 +371,9 @@ module MU
|
|
364
371
|
(1..db["cluster_node_count"]).each{ |num|
|
365
372
|
node = Marshal.load(Marshal.dump(db))
|
366
373
|
node["name"] = "#{db['name']}-#{num}"
|
374
|
+
node["credentials"] = db["credentials"]
|
367
375
|
node["create_cluster"] = false
|
376
|
+
node["create_read_replica"] = false
|
368
377
|
node["creation_style"] = "new"
|
369
378
|
node["add_cluster_node"] = true
|
370
379
|
node["member_of_cluster"] = {
|