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.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/Berksfile +16 -54
  3. data/Berksfile.lock +14 -62
  4. data/bin/mu-aws-setup +131 -108
  5. data/bin/mu-configure +311 -74
  6. data/bin/mu-gcp-setup +84 -62
  7. data/bin/mu-load-config.rb +46 -2
  8. data/bin/mu-self-update +11 -9
  9. data/bin/mu-upload-chef-artifacts +4 -4
  10. data/{mu.gemspec → cloud-mu.gemspec} +2 -2
  11. data/cookbooks/awscli/Berksfile +8 -0
  12. data/cookbooks/mu-activedirectory/Berksfile +11 -0
  13. data/cookbooks/mu-firewall/Berksfile +9 -0
  14. data/cookbooks/mu-firewall/metadata.rb +1 -1
  15. data/cookbooks/mu-glusterfs/Berksfile +10 -0
  16. data/cookbooks/mu-jenkins/Berksfile +14 -0
  17. data/cookbooks/mu-master/Berksfile +23 -0
  18. data/cookbooks/mu-master/attributes/default.rb +1 -1
  19. data/cookbooks/mu-master/metadata.rb +2 -2
  20. data/cookbooks/mu-master/recipes/default.rb +1 -1
  21. data/cookbooks/mu-master/recipes/init.rb +7 -3
  22. data/cookbooks/mu-master/recipes/ssl-certs.rb +1 -0
  23. data/cookbooks/mu-mongo/Berksfile +10 -0
  24. data/cookbooks/mu-openvpn/Berksfile +11 -0
  25. data/cookbooks/mu-php54/Berksfile +13 -0
  26. data/cookbooks/mu-splunk/Berksfile +10 -0
  27. data/cookbooks/mu-tools/Berksfile +21 -0
  28. data/cookbooks/mu-tools/files/default/Mu_CA.pem +15 -15
  29. data/cookbooks/mu-utility/Berksfile +9 -0
  30. data/cookbooks/mu-utility/metadata.rb +2 -1
  31. data/cookbooks/nagios/Berksfile +7 -4
  32. data/cookbooks/s3fs/Berksfile +9 -0
  33. data/environments/dev.json +6 -6
  34. data/environments/prod.json +6 -6
  35. data/modules/mu.rb +20 -42
  36. data/modules/mu/cleanup.rb +102 -100
  37. data/modules/mu/cloud.rb +90 -28
  38. data/modules/mu/clouds/aws.rb +449 -218
  39. data/modules/mu/clouds/aws/alarm.rb +29 -17
  40. data/modules/mu/clouds/aws/cache_cluster.rb +78 -64
  41. data/modules/mu/clouds/aws/collection.rb +25 -18
  42. data/modules/mu/clouds/aws/container_cluster.rb +73 -66
  43. data/modules/mu/clouds/aws/database.rb +124 -116
  44. data/modules/mu/clouds/aws/dnszone.rb +27 -20
  45. data/modules/mu/clouds/aws/firewall_rule.rb +30 -22
  46. data/modules/mu/clouds/aws/folder.rb +18 -3
  47. data/modules/mu/clouds/aws/function.rb +77 -23
  48. data/modules/mu/clouds/aws/group.rb +19 -12
  49. data/modules/mu/clouds/aws/habitat.rb +153 -0
  50. data/modules/mu/clouds/aws/loadbalancer.rb +59 -52
  51. data/modules/mu/clouds/aws/log.rb +30 -23
  52. data/modules/mu/clouds/aws/msg_queue.rb +29 -20
  53. data/modules/mu/clouds/aws/notifier.rb +222 -0
  54. data/modules/mu/clouds/aws/role.rb +178 -90
  55. data/modules/mu/clouds/aws/search_domain.rb +40 -24
  56. data/modules/mu/clouds/aws/server.rb +169 -137
  57. data/modules/mu/clouds/aws/server_pool.rb +60 -83
  58. data/modules/mu/clouds/aws/storage_pool.rb +59 -31
  59. data/modules/mu/clouds/aws/user.rb +36 -27
  60. data/modules/mu/clouds/aws/userdata/linux.erb +101 -93
  61. data/modules/mu/clouds/aws/vpc.rb +250 -189
  62. data/modules/mu/clouds/azure.rb +132 -0
  63. data/modules/mu/clouds/cloudformation.rb +65 -1
  64. data/modules/mu/clouds/cloudformation/alarm.rb +8 -0
  65. data/modules/mu/clouds/cloudformation/cache_cluster.rb +7 -0
  66. data/modules/mu/clouds/cloudformation/collection.rb +7 -0
  67. data/modules/mu/clouds/cloudformation/database.rb +7 -0
  68. data/modules/mu/clouds/cloudformation/dnszone.rb +7 -0
  69. data/modules/mu/clouds/cloudformation/firewall_rule.rb +9 -2
  70. data/modules/mu/clouds/cloudformation/loadbalancer.rb +7 -0
  71. data/modules/mu/clouds/cloudformation/log.rb +7 -0
  72. data/modules/mu/clouds/cloudformation/server.rb +7 -0
  73. data/modules/mu/clouds/cloudformation/server_pool.rb +7 -0
  74. data/modules/mu/clouds/cloudformation/vpc.rb +7 -0
  75. data/modules/mu/clouds/google.rb +214 -110
  76. data/modules/mu/clouds/google/container_cluster.rb +42 -24
  77. data/modules/mu/clouds/google/database.rb +15 -6
  78. data/modules/mu/clouds/google/firewall_rule.rb +17 -25
  79. data/modules/mu/clouds/google/group.rb +13 -5
  80. data/modules/mu/clouds/google/habitat.rb +105 -0
  81. data/modules/mu/clouds/google/loadbalancer.rb +28 -20
  82. data/modules/mu/clouds/google/server.rb +93 -354
  83. data/modules/mu/clouds/google/server_pool.rb +18 -10
  84. data/modules/mu/clouds/google/user.rb +22 -14
  85. data/modules/mu/clouds/google/vpc.rb +97 -69
  86. data/modules/mu/config.rb +133 -38
  87. data/modules/mu/config/alarm.rb +25 -0
  88. data/modules/mu/config/cache_cluster.rb +5 -3
  89. data/modules/mu/config/cache_cluster.yml +23 -0
  90. data/modules/mu/config/database.rb +25 -16
  91. data/modules/mu/config/database.yml +3 -3
  92. data/modules/mu/config/function.rb +1 -2
  93. data/modules/mu/config/{project.rb → habitat.rb} +10 -10
  94. data/modules/mu/config/notifier.rb +85 -0
  95. data/modules/mu/config/notifier.yml +9 -0
  96. data/modules/mu/config/role.rb +1 -1
  97. data/modules/mu/config/search_domain.yml +2 -2
  98. data/modules/mu/config/server.rb +13 -1
  99. data/modules/mu/config/server.yml +3 -3
  100. data/modules/mu/config/server_pool.rb +3 -1
  101. data/modules/mu/config/storage_pool.rb +3 -1
  102. data/modules/mu/config/storage_pool.yml +19 -0
  103. data/modules/mu/config/vpc.rb +70 -8
  104. data/modules/mu/groomers/chef.rb +2 -3
  105. data/modules/mu/kittens.rb +500 -122
  106. data/modules/mu/master.rb +5 -5
  107. data/modules/mu/mommacat.rb +151 -91
  108. data/modules/tests/super_complex_bok.yml +12 -0
  109. data/modules/tests/super_simple_bok.yml +12 -0
  110. data/spec/mu/clouds/azure_spec.rb +82 -0
  111. data/spec/spec_helper.rb +105 -0
  112. metadata +26 -5
  113. data/modules/mu/clouds/aws/notification.rb +0 -139
  114. data/modules/mu/config/notification.rb +0 -44
@@ -39,9 +39,10 @@ module MU
39
39
  rescue NoMethodError
40
40
  "AWS"
41
41
  end
42
- if MU::Cloud::Google.hosted
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].each { |kitten|
772
- return kitten if kitten['name'] == name.to_s
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].each { |kitten|
786
- if kitten['name'] == name
787
- deletia = kitten
788
- break
789
- end
790
- }
791
- @kittens[type].delete(deletia) if !deletia.nil?
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 = {"name" => fwname, "rules" => descriptor['ingress_rules'], "region" => descriptor['region'] }
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
- return false if !parser.validateConfig(plain_descriptor, self)
1128
+ passed = parser.validateConfig(plain_descriptor, self)
1095
1129
 
1096
- descriptor.merge!(plain_descriptor)
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"] == region if !region.nil? and !region.empty?
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 !$MU_CFG['google'] or !$MU_CFG['google']['region']
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'] ||= $MU_CFG['google']['region']
1623
+ kitten['region'] ||= MU::Cloud::Google.myRegion(kitten['credentials'])
1548
1624
  end
1549
- else
1550
- if !$MU_CFG['aws'] or !$MU_CFG['aws']['region']
1551
- raise ValidationError, "AWS resource declared without a region, but no default AWS region declared in mu.yaml"
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'] ||= $MU_CFG['aws']['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
- types.each { |type|
1610
- @kittens[type].each { |descriptor|
1611
- if !descriptor["#MU_VALIDATED"]
1612
- ok = false if !insertKitten(descriptor, type)
1613
- end
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
@@ -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 cache [Hash]: The resource to process and validate
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(cache, configurator)
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
- cluster['dependencies'] << adminFirewallRuleset(vpc: cluster['vpc'], region: cluster['region'], cloud: cluster['cloud']) if !cluster['scrub_mu_isms']
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" => "Rather to create a database cluster. This only applies to aurora",
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
- replica = Marshal.load(Marshal.dump(db))
345
- replica['name'] = db['name']+"-replica"
346
- replica['create_read_replica'] = false
347
- replica['read_replica_of'] = {
348
- "db_name" => db['name'],
349
- "cloud" => db['cloud'],
350
- "region" => db['read_replica_region'] || db['region']
351
- }
352
- replica['dependencies'] << {
353
- "type" => "database",
354
- "name" => db["name"],
355
- "phase" => "groom"
356
- }
357
- read_replicas << replica
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"] = {