git.fiddlerwoaroof.com
Browse code

(root)

Ed Langley authored on 21/02/2020 03:33:43
Showing 5 changed files
... ...
@@ -6,7 +6,8 @@
6 6
           :dependencies   '[[org.clojure/clojure "RELEASE"]
7 7
                             [samestep/boot-refresh "0.1.0"]
8 8
                             [adzerk/boot-test "RELEASE" :scope "test"]
9
-                            [amazonica "0.3.120"]])
9
+                            [amazonica "0.3.120"]
10
+                            [funcool/cuerdas "2.0.5"]])
10 11
 
11 12
 (task-options!
12 13
  aot {:namespace   #{'my-infra.core}}
13 14
new file mode 100644
... ...
@@ -0,0 +1,3 @@
1
+# Introduction to my-infra
2
+
3
+TODO: write [great documentation](http://jacobian.org/writing/what-to-write/)
... ...
@@ -65,8 +65,8 @@
65 65
                                       :vpc-id (id ::vpc vpc)))
66 66
     result))
67 67
 
68
-(def cred {:profile "personal"
69
-           :endpoint "us-west-2"})
68
+(def cred {:profile "default"
69
+           :endpoint "us-east-1"})
70 70
 
71 71
 (defmethod params ::my-vpc [thing & r]
72 72
   {:cidr-block "172.16.234.0/24"})
... ...
@@ -96,9 +96,12 @@
96 96
                          :subnet-id (id ::subnet subnet))
97 97
   route-table)
98 98
 
99
+
99 100
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
100 101
 ;; new-api
101 102
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
103
+#_
104
+(begin
102 105
 
103 106
 (def vpc (create {::type ::vpc
104 107
                   :cidr-block "10.1.0.0/16"}
... ...
@@ -117,6 +120,7 @@
117 120
 (def route-table (make-routes {::type ::my-route-table}
118 121
                               cred vpc subnet
119 122
                               ["0.0.0.0/0" ::internet-gateway internet-gateway]))
123
+)
120 124
 
121 125
 (defn -main
122 126
   "I don't do a whole lot ... yet."
123 127
new file mode 100644
... ...
@@ -0,0 +1,396 @@
1
+(ns my-infra.template
2
+  (:require [cuerdas.core :as str]))
3
+
4
+(defn process-lines [cb s]
5
+  ((comp #(str/join "\n" %)
6
+         cb
7
+         #(str/split % "\n"))
8
+   s))
9
+
10
+(defn remove-margin
11
+  ([s] (remove-margin s "|"))
12
+  ([s margin-indicator] (process-lines (fn [it]
13
+                                         (eduction (map str/trim)
14
+                                                   (map #(str/trim % margin-indicator))
15
+                                                   it))
16
+                                       s)))
17
+
18
+(defmacro demargin [str]
19
+  (if (and (seq? str) (= (first str) 'str))
20
+    (cons (first str)
21
+          (map (fn [it]
22
+                 (cond
23
+                   (string? it) (remove-margin it)
24
+                   true it))
25
+               (rest str)))
26
+    (remove-margin str)))
27
+
28
+(demargin "cluster_name: ${CassandraCluster}
29
+            |num_tokens: 256
30
+            |hinted_handoff_enabled: true
31
+            |max_hint_window_in_ms: 10800000
32
+            |hinted_handoff_throttle_in_kb: 1024
33
+            |max_hints_delivery_threads: 2
34
+            |authenticator: AllowAllAuthenticator
35
+            |authorizer: AllowAllAuthorizer
36
+            |permissions_validity_in_ms: 2000
37
+            |partitioner: org.apache.cassandra.dht.Murmur3Partitioner
38
+            |data_file_directories:
39
+            |    - /var/lib/cassandra/data
40
+            |commitlog_directory: /var/lib/cassandra/commitlog
41
+            |disk_failure_policy: stop
42
+            |key_cache_size_in_mb:
43
+            |key_cache_save_period: 14400
44
+            |row_cache_size_in_mb: 0
45
+            |row_cache_save_period: 0
46
+            |saved_caches_directory: /var/lib/cassandra/saved_caches
47
+            |commitlog_sync: periodic
48
+            |commitlog_sync_period_in_ms: 10000
49
+            |commitlog_segment_size_in_mb: 32
50
+            |seed_provider:
51
+            |    - class_name: org.apache.cassandra.locator.SimpleSeedProvider
52
+            |    parameters:
53
+            |        - seeds: cassandra-seed-1.${AWS::StackName}.${AWS::Region}.cjconfig,cassandra-seed-2.${AWS::StackName}.${AWS::Region}.cjconfig
54
+            |concurrent_reads: 32
55
+            |concurrent_writes: 32
56
+            |trickle_fsync: false
57
+            |trickle_fsync_interval_in_kb: 10240
58
+            |storage_port: 7000
59
+            |ssl_storage_port: 7001
60
+            |listen_address: ${CassandraSeedNetworkInterfaceAz1.PrimaryPrivateIpAddress}
61
+            |start_native_transport: true
62
+            |native_transport_port: 9042
63
+            |start_rpc: true
64
+            |rpc_address: ${CassandraSeedNetworkInterfaceAz1.PrimaryPrivateIpAddress}
65
+            |rpc_port: 9160
66
+            |rpc_keepalive: true
67
+            |rpc_server_type: sync
68
+            |thrift_framed_transport_size_in_mb: 15
69
+            |incremental_backups: false
70
+            |snapshot_before_compaction: false
71
+            |auto_snapshot: true
72
+            |tombstone_warn_threshold: 1000
73
+            |tombstone_failure_threshold: 100000
74
+            |column_index_size_in_kb: 64
75
+            |compaction_throughput_mb_per_sec: 16
76
+            |read_request_timeout_in_ms: 5000
77
+            |range_request_timeout_in_ms: 10000
78
+            |write_request_timeout_in_ms: 2000
79
+            |cas_contention_timeout_in_ms: 1000
80
+            |truncate_request_timeout_in_ms: 60000
81
+            |request_timeout_in_ms: 10000
82
+            |cross_node_timeout: false
83
+            |endpoint_snitch: Ec2Snitch
84
+            |dynamic_snitch_update_interval_in_ms: 100
85
+            |dynamic_snitch_reset_interval_in_ms: 600000
86
+            |dynamic_snitch_badness_threshold: 0.1
87
+            |request_scheduler: org.apache.cassandra.scheduler.NoScheduler
88
+            |server_encryption_options:
89
+            |    internode_encryption: none
90
+            |    keystore: conf/.keystore
91
+            |    keystore_password: cassandra
92
+            |    truststore: conf/.truststore
93
+            |    truststore_password: cassandra
94
+            |client_encryption_options:
95
+            |    enabled: false
96
+            |    keystore: conf/.keystore
97
+            |    keystore_password: cassandra
98
+            |internode_compression: all
99
+            |inter_dc_tcp_nodelay: false
100
+            |hints_directory: /var/lib/cassandra/hints
101
+            |auto_bootstrap: false")
102
+
103
+#_
104
+(drop-while #(and (not= % \|)
105
+                  (while) "     |") )
106
+(defn cassandra-seed-instance [name dns-resource network-interface-id key-pair other-seed]
107
+  {"Type" "AWS::EC2::Instance",
108
+   "DependsOn" dns-resource,
109
+   "Properties"
110
+   {"Tags" [{"Key" "Name", "Value" name}],
111
+    "NetworkInterfaces" [{"DeviceIndex" 0,"NetworkInterfaceId" network-interface-id}],
112
+    "InstanceType" {"Ref" "InstanceType"},
113
+    "KeyName" key-pair,
114
+    "ImageId" {"Fn::FindInMap" ["AMI" {"Ref" "AWS::Region"} "ami"]},
115
+    "BlockDeviceMappings" [{"DeviceName" "/dev/sdb","Ebs" {"VolumeSize" 2048,"VolumeType" "gp2","DeleteOnTermination" false}}
116
+                           {"DeviceName" "/dev/sdg","Ebs" {"VolumeSize" 512,"VolumeType" "gp2","DeleteOnTermination" false}}],
117
+    "UserData" {"Fn::Base64"
118
+                {"Fn::Sub"
119
+                 (demargin
120
+                  (str "#!/usr/bin/env bash\nset -evx -u -o pipefail\n\nyum update -y\n\n/opt/aws/bin/cfn-init -v \\
121
+                  |  --stack=${AWS::StackId} \\
122
+                  |  --resource=" name " \\
123
+                  |  --region=${AWS::Region} \\
124
+                  |
125
+                  |  -c cassandra_setup\n\nsleep 20\nservice cassandra status\nCASS_EXIT=$?\n\n/opt/aws/bin/cfn-signal \\
126
+                  |  --stack=${AWS::StackId} \\
127
+                  |  --resource=" name "\\
128
+                  |  --region=${AWS::Region} \\
129
+                  |  --exit-code=$CASS_EXIT \\
130
+                  |  --reason='" name " initialization complete'"))}}},
131
+   "CreationPolicy" {"ResourceSignal" {"Timeout" "PT15M"}},
132
+   "Metadata" {"AWS::CloudFormation::Init"
133
+               {"configSets"
134
+                {"cassandra_setup" ["configure_yum" "install_packages" "configure_hosts" "configure_hard_drive" "configure_cassandra"]},
135
+                "configure_yum" {"files"
136
+                                 {"/etc/yum.repos.d/cassandra.repo"
137
+                                  {"content"
138
+                                   "[cassandra]\nname=Apache Cassandra\nbaseurl=https://www.apache.org/dist/cassandra/redhat/311x/\ngpgcheck=1\nrepo_gpgcheck=1\ngpgkey=https://www.apache.org/dist/cassandra/KEYS\n"}}},
139
+                "install_packages" {"commands"
140
+                                    {"01-install-java-8" {"command" "yum install -y java-1.8.0"},
141
+                                     "02-remove-java-7" {"command" "yum remove -y java-1.7.0-openjdk"},
142
+                                     "03-install-cassandra" {"command" "yum install -y cassandra"}}},
143
+                "configure_hosts" {"commands"
144
+                                   {"01-create-hosts-entry-on-boot" {"command" "echo \"`curl -s http://169.254.169.254/latest/meta-data/local-ipv4` `hostname`\" >> /etc/hosts","test" "test ! -f .create-hosts-entry-semaphore"},
145
+                                    "02-signal_startup_complete" {"command" "touch .create-hosts-entry-semaphore"}}},
146
+                "configure_hard_drive" {"commands"
147
+                                        {"00-install-xfs-programs" {"command" "yum install -y xfsprogs"},
148
+                                         "01-create-file-system-on-ebs-volume-1" {"command" "mkfs.xfs -s size=4096 /dev/sdb"},
149
+                                         "01-create-file-system-on-ebs-volume-2" {"command" "mkfs.xfs -s size=4096 /dev/sdg"},
150
+                                         "02-setup-fstab-1" {"command" "echo \"/dev/sdb /var/lib/cassandra/data xfs defaults,nofail 0 0\" >> /etc/fstab"},
151
+                                         "02-setup-fstab-2" {"command" "echo \"/dev/sdg /var/lib/cassandra/commitlog xfs defaults,nofail 0 0\" >> /etc/fstab"},
152
+                                         "03-mount-all" {"command" "mount -a"}}},
153
+                "configure_cassandra" {"files"
154
+                                       {"/etc/cassandra/default.conf/cassandra.yaml"
155
+                                        {"content" {"Fn::Sub" (demargin (str "TODO"))},
156
+                                         "mode" 420,
157
+                                         "owner" "cassandra",
158
+                                         "group" "cassandra"}},
159
+                                       "commands" {"00-chown-for-cassandra-data" {"command" "chown -R cassandra:cassandra /var/lib/cassandra/data"},
160
+                                                   "01-chown-for-cassandra-commitlog" {"command" "chown -R cassandra:cassandra /var/lib/cassandra/commitlog"}},
161
+                                       "services" {"sysvinit" {"cassandra" {"enabled" true, "ensureRunning" true}}}}}}})
162
+
163
+(def cassandra-seed-az-1
164
+  {:instance (cassandra-seed-instance "CassandraSeedAz1"
165
+                                      "CassandraSeedAz1DNS"
166
+                                      {"Ref" "CassandraSeedNetworkInterfaceAz1"}
167
+                                      {"Ref" "Ec2KeyPair"}
168
+                                      "CassandraSeedAz2")
169
+
170
+   :dns
171
+   {"Type" "AWS::Route53::RecordSet",
172
+    "Properties"
173
+    {"HostedZoneId" {"Ref" "CassandraHostedZone"},
174
+     "Comment" "Cassandra Seed Az1 Record",
175
+     "Name"
176
+     {"Fn::Sub"
177
+      "cassandra-seed-1.${AWS::StackName}.${AWS::Region}.cjconfig"},
178
+     "Type" "A",
179
+     "TTL" 30,
180
+     "ResourceRecords"
181
+     [{"Fn::GetAtt"
182
+       ["CassandraSeedNetworkInterfaceAz1"
183
+        "PrimaryPrivateIpAddress"]}]}}})
184
+
185
+(def cassandra-seed-az-2
186
+  {:instance 
187
+   {"Type" "AWS::EC2::Instance",
188
+    "DependsOn" "CassandraSeedAz2DNS",
189
+    "Properties"
190
+    {"NetworkInterfaces"
191
+     [{"DeviceIndex" 0,"NetworkInterfaceId" {"Ref" "CassandraSeedNetworkInterfaceAz2"}}],
192
+     "InstanceType" {"Ref" "InstanceType"},
193
+     "KeyName" {"Ref" "Ec2KeyPair"},
194
+     "ImageId" {"Fn::FindInMap" ["AMI" {"Ref" "AWS::Region"} "ami"]},
195
+     "BlockDeviceMappings" [{"DeviceName" "/dev/sdb","Ebs" {"VolumeSize" 2048,"VolumeType" "gp2","DeleteOnTermination" false}}
196
+                            {"DeviceName" "/dev/sdg","Ebs" {"VolumeSize" 512,"VolumeType" "gp2","DeleteOnTermination" false}}],
197
+     "Tags" [{"Key" "Name", "Value" "CassandraSeedAz2"}],
198
+     "UserData" {"Fn::Base64" {"Fn::Sub" "#!/usr/bin/env bash\nset -evx -u -o pipefail\n\nyum update -y\n\n/opt/aws/bin/cfn-init -v \\\n  --stack=${AWS::StackId} \\\n  --resource=CassandraSeedAz2 \\\n  --region=${AWS::Region} \\\n  -c cassandra_setup\n\nsleep 20\nservice cassandra status\nCASS_EXIT=$?\n\n/opt/aws/bin/cfn-signal \\\n  --stack=${AWS::StackId} \\\n  --resource=CassandraSeedAz2 \\\n  --region=${AWS::Region} \\\n  --exit-code=$CASS_EXIT \\\n  --reason='CassandraSeedAz2 initialization complete'\n"}}},
199
+    "CreationPolicy" {"ResourceSignal" {"Timeout" "PT15M"}},
200
+    "Metadata" {"AWS::CloudFormation::Init"
201
+                {"configSets" {"cassandra_setup" ["configure_yum" "install_packages" "configure_hosts" "configure_hard_drive" "configure_cassandra"]},
202
+                 "configure_yum" {"files"
203
+                                  {"/etc/yum.repos.d/cassandra.repo" {"content" "[cassandra]\nname=Apache Cassandra\nbaseurl=https://www.apache.org/dist/cassandra/redhat/311x/\ngpgcheck=1\nrepo_gpgcheck=1\ngpgkey=https://www.apache.org/dist/cassandra/KEYS\n"}}},
204
+                 "install_packages" {"commands"
205
+                                     {"01-install-java-8" {"command" "yum install -y java-1.8.0"},
206
+                                      "02-remove-java-7" {"command" "yum remove -y java-1.7.0-openjdk"},
207
+                                      "03-install-cassandra" {"command" "yum install -y cassandra"}}},
208
+                 "configure_hosts" {"commands"
209
+                                    {"01-create-hosts-entry-on-boot" {"command" "echo \"`curl -s http://169.254.169.254/latest/meta-data/local-ipv4` `hostname`\" >> /etc/hosts","test" "test ! -f .create-hosts-entry-semaphore"},
210
+                                     "02-signal_startup_complete" {"command" "touch .create-hosts-entry-semaphore"}}},
211
+                 "configure_hard_drive" {"commands"
212
+                                         {"00-install-xfs-programs" {"command" "yum install -y xfsprogs"},
213
+                                          "01-create-file-system-on-ebs-volume-1" {"command" "mkfs.xfs -s size=4096 /dev/sdb"},
214
+                                          "01-create-file-system-on-ebs-volume-2" {"command" "mkfs.xfs -s size=4096 /dev/sdg"},
215
+                                          "02-setup-fstab-1" {"command" "echo \"/dev/sdb /var/lib/cassandra/data xfs defaults,nofail 0 0\" >> /etc/fstab"},
216
+                                          "02-setup-fstab-2" {"command" "echo \"/dev/sdg /var/lib/cassandra/commitlog xfs defaults,nofail 0 0\" >> /etc/fstab"},
217
+                                          "03-mount-all" {"command" "mount -a"}}},
218
+                 "configure_cassandra" {"files"
219
+                                        {"/etc/cassandra/default.conf/cassandra.yaml"
220
+                                         {"content"
221
+                                          {"Fn::Sub"
222
+                                           "cluster_name: ${CassandraCluster}\nnum_tokens: 256\nhinted_handoff_enabled: true\nmax_hint_window_in_ms: 10800000\nhinted_handoff_throttle_in_kb: 1024\nmax_hints_delivery_threads: 2\nauthenticator: AllowAllAuthenticator\nauthorizer: AllowAllAuthorizer\npermissions_validity_in_ms: 2000\npartitioner: org.apache.cassandra.dht.Murmur3Partitioner\ndata_file_directories:\n    - /var/lib/cassandra/data\ncommitlog_directory: /var/lib/cassandra/commitlog\ndisk_failure_policy: stop\nkey_cache_size_in_mb:\nkey_cache_save_period: 14400\nrow_cache_size_in_mb: 0\nrow_cache_save_period: 0\nsaved_caches_directory: /var/lib/cassandra/saved_caches\ncommitlog_sync: periodic\ncommitlog_sync_period_in_ms: 10000\ncommitlog_segment_size_in_mb: 32\nseed_provider:\n    - class_name: org.apache.cassandra.locator.SimpleSeedProvider\n      parameters:\n          - seeds: cassandra-seed-1.${AWS::StackName}.${AWS::Region}.cjconfig,cassandra-seed-2.${AWS::StackName}.${AWS::Region}.cjconfig\nconcurrent_reads: 32\nconcurrent_writes: 32\ntrickle_fsync: false\ntrickle_fsync_interval_in_kb: 10240\nstorage_port: 7000\nssl_storage_port: 7001\nlisten_address: ${CassandraSeedNetworkInterfaceAz2.PrimaryPrivateIpAddress}\nstart_native_transport: true\nnative_transport_port: 9042\nstart_rpc: true\nrpc_address: ${CassandraSeedNetworkInterfaceAz2.PrimaryPrivateIpAddress}\nrpc_port: 9160\nrpc_keepalive: true\nrpc_server_type: sync\nthrift_framed_transport_size_in_mb: 15\nincremental_backups: false\nsnapshot_before_compaction: false\nauto_snapshot: true\ntombstone_warn_threshold: 1000\ntombstone_failure_threshold: 100000\ncolumn_index_size_in_kb: 64\ncompaction_throughput_mb_per_sec: 16\nread_request_timeout_in_ms: 5000\nrange_request_timeout_in_ms: 10000\nwrite_request_timeout_in_ms: 2000\ncas_contention_timeout_in_ms: 1000\ntruncate_request_timeout_in_ms: 60000\nrequest_timeout_in_ms: 10000\ncross_node_timeout: false\nendpoint_snitch: Ec2Snitch\ndynamic_snitch_update_interval_in_ms: 100\ndynamic_snitch_reset_interval_in_ms: 600000\ndynamic_snitch_badness_threshold: 0.1\nrequest_scheduler: org.apache.cassandra.scheduler.NoScheduler\nserver_encryption_options:\n    internode_encryption: none\n    keystore: conf/.keystore\n    keystore_password: cassandra\n    truststore: conf/.truststore\n    truststore_password: cassandra\nclient_encryption_options:\n    enabled: false\n    keystore: conf/.keystore\n    keystore_password: cassandra\ninternode_compression: all\ninter_dc_tcp_nodelay: false\nhints_directory: /var/lib/cassandra/hints\nauto_bootstrap: false\n"},
223
+                                          "mode" 420,"owner" "cassandra","group" "cassandra"}},
224
+                                        "commands"
225
+                                        {"00-chown-for-cassandra-data" {"command" "chown -R cassandra:cassandra /var/lib/cassandra/data"},
226
+                                         "01-chown-for-cassandra-commitlog" {"command" "chown -R cassandra:cassandra /var/lib/cassandra/commitlog"}},
227
+                                        "services" {"sysvinit" {"cassandra" {"enabled" true, "ensureRunning" true}}}}}}}
228
+
229
+   :dns
230
+   {"Type" "AWS::Route53::RecordSet",
231
+    "Properties"
232
+    {"HostedZoneId" {"Ref" "CassandraHostedZone"},
233
+     "Comment" "Cassandra Seed Az2 Record",
234
+     "Name" {"Fn::Sub" "cassandra-seed-2.${AWS::StackName}.${AWS::Region}.cjconfig"},
235
+     "Type" "A",
236
+     "TTL" 30,
237
+     "ResourceRecords" [{"Fn::GetAtt" ["CassandraSeedNetworkInterfaceAz2" "PrimaryPrivateIpAddress"]}]}}})
238
+
239
+(def template
240
+  {"AWSTemplateFormatVersion" "2010-09-09",
241
+   "Description" "Insights Server Cassandra Database",
242
+   "Parameters"
243
+   {"Subnets" {"Type" "List<String>","Description" "The subnets where Cassandra nodes live"},
244
+    "DefaultSecurityGroup" {"Type" "String","MinLength" 1,"Description" "Security group for general access within VPC"},
245
+    "DatabaseSecurityGroup" {"Type" "String","MinLength" 1,"Description" "Database-allowed access"},
246
+    "Ec2KeyPair" {"Type" "String","Default" "insights","MinLength" 1,"MaxLength" 64,"AllowedPattern" "[-_ a-zA-Z0-9]*","ConstraintDescription" "can contain only alphanumeric characters, spaces, dashes and underscores.","Description" "Name of an EC2 KeyPair to enable SSH access to EC2 instances"},
247
+    "CassandraCluster" {"Type" "String","MinLength" 1,"Description" "The cassandra cluster name"},
248
+    "InstanceType" {"Type" "String","Default" "m4.2xlarge","Description" "Instance type"},
249
+    "Vpc" {"Type" "String","Description" "The VPC the cluster will be running in"},
250
+    "ClusterSize" {"Type" "Number","MinValue" 1,"Default" 6,"Description" "The number of nodes (in addition to the 2 seed nodes)"}},
251
+   "Resources"
252
+   {"CassandraSeedAz1" (:instance cassandra-seed-az-1,)
253
+    "CassandraSeedAz1DNS" (:dns cassandra-seed-az-1),
254
+    "CassandraSeedAz2" (:instance cassandra-seed-az-2,)
255
+    "CassandraSeedAz2DNS" (:dns cassandra-seed-az-2),          
256
+
257
+    "CassandraLaunchConfiguration"
258
+    {"Type" "AWS::AutoScaling::LaunchConfiguration",
259
+     "Properties"
260
+     {"InstanceType" {"Ref" "InstanceType"},
261
+      "KeyName" {"Ref" "Ec2KeyPair"},
262
+      "ImageId" {"Fn::FindInMap" ["AMI" {"Ref" "AWS::Region"} "ami"]},
263
+      "SecurityGroups"
264
+      [{"Ref" "DefaultSecurityGroup"} {"Ref" "DatabaseSecurityGroup"}],
265
+      "BlockDeviceMappings"
266
+      [{"DeviceName" "/dev/sdb",
267
+        "Ebs"
268
+        {"VolumeSize" 2048,
269
+         "VolumeType" "gp2",
270
+         "DeleteOnTermination" false}}
271
+       {"DeviceName" "/dev/sdg",
272
+        "Ebs"
273
+        {"VolumeSize" 512,
274
+         "VolumeType" "gp2",
275
+         "DeleteOnTermination" false}}],
276
+      "UserData"
277
+      {"Fn::Base64"
278
+       {"Fn::Sub"
279
+        "#! /usr/bin/env bash\nset -evx\n\nyum update -y\n\n# start instance initialization\n/opt/aws/bin/cfn-init -v \\\n  --stack=${AWS::StackId} \\\n  --resource=CassandraLaunchConfiguration \\\n  --region=${AWS::Region} \\\n  -c cassandra_setup\n\nservice cassandra start\nsleep 20\nservice cassandra status\nCASS_EXIT=$?\n\n# all is well so signal success\n/opt/aws/bin/cfn-signal \\\n  --stack=${AWS::StackId} \\\n  --resource=CassandraAutoScalingGroup \\\n  --region=${AWS::Region} \\\n  --exit-code=$CASS_EXIT \\\n  --reason='CassandraNodeA initialization complete'\n"}}},
280
+     "CreationPolicy" {"ResourceSignal" {"Timeout" "PT15M"}},
281
+     "Metadata"
282
+     {"AWS::CloudFormation::Init"
283
+      {"configSets"
284
+       {"cassandra_setup"
285
+        ["configure_yum"
286
+         "install_packages"
287
+         "configure_hosts"
288
+         "configure_hard_drive"
289
+         "configure_cassandra"]},
290
+       "configure_yum"
291
+       {"files"
292
+        {"/etc/yum.repos.d/cassandra.repo"
293
+         {"content"
294
+          "[cassandra]\nname=Apache Cassandra\nbaseurl=https://www.apache.org/dist/cassandra/redhat/311x/\ngpgcheck=1\nrepo_gpgcheck=1\ngpgkey=https://www.apache.org/dist/cassandra/KEYS\n"}}},
295
+       "install_packages"
296
+       {"commands"
297
+        {"01-install-java-8" {"command" "yum install -y java-1.8.0"},
298
+         "02-remove-java-7"
299
+         {"command" "yum remove -y java-1.7.0-openjdk"},
300
+         "03-install-cassandra" {"command" "yum install -y cassandra"}}},
301
+       "configure_hosts"
302
+       {"commands"
303
+        {"01-create-hosts-entry-on-boot"
304
+         {"command"
305
+          "echo \"`curl -s http://169.254.169.254/latest/meta-data/local-ipv4` `hostname`\" >> /etc/hosts",
306
+          "test" "test ! -f .create-hosts-entry-semaphore"},
307
+         "02-signal_startup_complete"
308
+         {"command" "touch .create-hosts-entry-semaphore"}}},
309
+       "configure_hard_drive"
310
+       {"commands"
311
+        {"00-install-xfs-programs" {"command" "yum install -y xfsprogs"},
312
+         "01-create-file-system-on-ebs-volume-1"
313
+         {"command" "mkfs.xfs -s size=4096 /dev/sdb"},
314
+         "01-create-file-system-on-ebs-volume-2"
315
+         {"command" "mkfs.xfs -s size=4096 /dev/sdg"},
316
+         "02-setup-fstab-1"
317
+         {"command"
318
+          "echo \"/dev/sdb /var/lib/cassandra/data xfs defaults,nofail 0 0\" >> /etc/fstab"},
319
+         "02-setup-fstab-2"
320
+         {"command"
321
+          "echo \"/dev/sdg /var/lib/cassandra/commitlog xfs defaults,nofail 0 0\" >> /etc/fstab"},
322
+         "03-mount-all" {"command" "mount -a"}}},
323
+       "configure_cassandra"
324
+       {"files"
325
+        {"/etc/cassandra/default.conf/cassandra.yaml"
326
+         {"content"
327
+          {"Fn::Sub"
328
+           "cluster_name: ${CassandraCluster}\nnum_tokens: 256\nhinted_handoff_enabled: true\nmax_hint_window_in_ms: 10800000\nhinted_handoff_throttle_in_kb: 1024\nmax_hints_delivery_threads: 2\nauthenticator: AllowAllAuthenticator\nauthorizer: AllowAllAuthorizer\npermissions_validity_in_ms: 2000\npartitioner: org.apache.cassandra.dht.Murmur3Partitioner\ndata_file_directories:\n    - /var/lib/cassandra/data\ncommitlog_directory: /var/lib/cassandra/commitlog\ndisk_failure_policy: stop\nkey_cache_size_in_mb:\nkey_cache_save_period: 14400\nrow_cache_size_in_mb: 0\nrow_cache_save_period: 0\nsaved_caches_directory: /var/lib/cassandra/saved_caches\ncommitlog_sync: periodic\ncommitlog_sync_period_in_ms: 10000\ncommitlog_segment_size_in_mb: 32\nseed_provider:\n    - class_name: org.apache.cassandra.locator.SimpleSeedProvider\n      parameters:\n          - seeds: cassandra-seed-1.${AWS::StackName}.${AWS::Region}.cjconfig,cassandra-seed-2.${AWS::StackName}.${AWS::Region}.cjconfig\nconcurrent_reads: 32\nconcurrent_writes: 32\ntrickle_fsync: false\ntrickle_fsync_interval_in_kb: 10240\nstorage_port: 7000\nssl_storage_port: 7001\nlisten_address: __NODE_IP\nstart_native_transport: true\nnative_transport_port: 9042\nstart_rpc: true\nrpc_address: __NODE_IP\nrpc_port: 9160\nrpc_keepalive: true\nrpc_server_type: sync\nthrift_framed_transport_size_in_mb: 15\nincremental_backups: false\nsnapshot_before_compaction: false\nauto_snapshot: true\ntombstone_warn_threshold: 1000\ntombstone_failure_threshold: 100000\ncolumn_index_size_in_kb: 64\ncompaction_throughput_mb_per_sec: 16\nread_request_timeout_in_ms: 5000\nrange_request_timeout_in_ms: 10000\nwrite_request_timeout_in_ms: 2000\ncas_contention_timeout_in_ms: 1000\ntruncate_request_timeout_in_ms: 60000\nrequest_timeout_in_ms: 10000\ncross_node_timeout: false\nendpoint_snitch: Ec2Snitch\ndynamic_snitch_update_interval_in_ms: 100\ndynamic_snitch_reset_interval_in_ms: 600000\ndynamic_snitch_badness_threshold: 0.1\nrequest_scheduler: org.apache.cassandra.scheduler.NoScheduler\nserver_encryption_options:\n    internode_encryption: none\n    keystore: conf/.keystore\n    keystore_password: cassandra\n    truststore: conf/.truststore\n    truststore_password: cassandra\nclient_encryption_options:\n    enabled: false\n    keystore: conf/.keystore\n    keystore_password: cassandra\ninternode_compression: all\ninter_dc_tcp_nodelay: false\nhints_directory: /var/lib/cassandra/hints\nauto_bootstrap: false\n"},
329
+          "mode" 420,
330
+          "owner" "cassandra",
331
+          "group" "cassandra"}},
332
+        "commands"
333
+        {"00-chown-for-cassandra-data"
334
+         {"command"
335
+          "chown -R cassandra:cassandra /var/lib/cassandra/data"},
336
+         "01-chown-for-cassandra-commitlog"
337
+         {"command"
338
+          "chown -R cassandra:cassandra /var/lib/cassandra/commitlog"},
339
+         "02-add-node-ip"
340
+         {"command"
341
+          "NODE_IP=`hostname -I` sed -i s/__NODE_IP/$NODE_IP/g /etc/cassandra/default.conf/cassandra.yaml"}},
342
+        "services"
343
+        {"sysvinit"
344
+         {"cassandra" {"enabled" true, "ensureRunning" true}}}}}}},
345
+    "CassandraSeedNetworkInterfaceAz1"
346
+    {"Type" "AWS::EC2::NetworkInterface",
347
+     "Properties"
348
+     {"SubnetId" {"Fn::Select" [0 {"Ref" "Subnets"}]},
349
+      "GroupSet"
350
+      [{"Ref" "DefaultSecurityGroup"} {"Ref" "DatabaseSecurityGroup"}]}},
351
+    "CassandraAutoScalingGroup"
352
+    {"Type" "AWS::AutoScaling::AutoScalingGroup",
353
+     "DependsOn" "CassandraSeedAz1",
354
+     "Properties"
355
+     {"MaxSize" {"Ref" "ClusterSize"},
356
+      "MinSize" {"Ref" "ClusterSize"},
357
+      "DesiredCapacity" {"Ref" "ClusterSize"},
358
+      "VPCZoneIdentifier" {"Ref" "Subnets"},
359
+      "LaunchConfigurationName" {"Ref" "CassandraLaunchConfiguration"},
360
+      "Tags"
361
+      [{"Key" "Name",
362
+        "Value" {"Fn::Sub" "Cassandra AutoScale ${AWS::StackName}"},
363
+        "PropagateAtLaunch" true}]}},
364
+    "CassandraSeedNetworkInterfaceAz2"
365
+    {"Type" "AWS::EC2::NetworkInterface",
366
+     "Properties"
367
+     {"SubnetId" {"Fn::Select" [1 {"Ref" "Subnets"}]},
368
+      "GroupSet"
369
+      [{"Ref" "DefaultSecurityGroup"} {"Ref" "DatabaseSecurityGroup"}]}},
370
+    "CassandraHostedZone"
371
+    {"Type" "AWS::Route53::HostedZone",
372
+     "Properties"
373
+     {"Name" {"Fn::Sub" "${AWS::StackName}.${AWS::Region}.cjconfig"},
374
+      "HostedZoneConfig"
375
+      {"Comment" "A hosted zone for our cjconfiguration"},
376
+      "VPCs"
377
+      [{"VPCId" {"Ref" "Vpc"}, "VPCRegion" {"Ref" "AWS::Region"}}]}}},
378
+   "Mappings"
379
+   {"AMI"
380
+    {"us-east-1" {"ami" "ami-97785bed"},
381
+     "us-east-2" {"ami" "ami-f63b1193"},
382
+     "us-west-1" {"ami" "ami-824c4ee2"},
383
+     "us-west-2" {"ami" "ami-f2d3638a"}},
384
+    "NameMap"
385
+    {"az1" {"name" "cassandra-seed-1"},
386
+     "az2" {"name" "cassandra-seed-2"}}},
387
+   "Conditions"
388
+   {"T2InstanceFamily"
389
+    {"Fn::Equals"
390
+     [{"Fn::Select" [0 {"Fn::Split" ["." {"Ref" "InstanceType"}]}]}
391
+      "t2"]}},
392
+   "Outputs"
393
+   {"CassandraContactPoints"
394
+    {"Value"
395
+     {"Fn::Sub"
396
+      "${CassandraSeedNetworkInterfaceAz1.PrimaryPrivateIpAddress},${CassandraSeedNetworkInterfaceAz2.PrimaryPrivateIpAddress}"}}}})
0 397
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+(ns my-infra.core-test
2
+  (:require [clojure.test :refer :all]
3
+            [my-infra.core :refer :all]))
4
+
5
+(deftest a-test
6
+  (testing "FIXME, I fail."
7
+    (is (= 0 1))))