cheftacular 2.1.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cheftacular/README.md +40 -28
  3. data/lib/cheftacular/{actions.rb → action.rb} +0 -0
  4. data/lib/cheftacular/actions/deploy.rb +2 -1
  5. data/lib/cheftacular/actions/migrate.rb +3 -1
  6. data/lib/cheftacular/{decryptors.rb → decryptor.rb} +0 -0
  7. data/lib/cheftacular/dns.rb +283 -0
  8. data/lib/cheftacular/{encryptors.rb → encryptor.rb} +0 -0
  9. data/lib/cheftacular/{getters.rb → getter.rb} +2 -2
  10. data/lib/cheftacular/{helpers.rb → helper.rb} +6 -14
  11. data/lib/cheftacular/{initializers.rb → initializer.rb} +3 -2
  12. data/lib/cheftacular/{parsers.rb → parser.rb} +6 -0
  13. data/lib/cheftacular/stateless_actions/arguments.rb +2 -4
  14. data/lib/cheftacular/stateless_actions/client_list.rb +6 -6
  15. data/lib/cheftacular/stateless_actions/cloud.rb +1 -1
  16. data/lib/cheftacular/stateless_actions/cloud_bootstrap.rb +8 -34
  17. data/lib/cheftacular/stateless_actions/compile_readme.rb +4 -2
  18. data/lib/cheftacular/stateless_actions/get_pg_pass.rb +0 -2
  19. data/lib/cheftacular/stateless_actions/get_shorewall_allowed_connections.rb +65 -0
  20. data/lib/cheftacular/stateless_actions/help.rb +1 -1
  21. data/lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb +6 -0
  22. data/lib/cheftacular/stateless_actions/remove_client.rb +6 -20
  23. data/lib/cheftacular/stateless_actions/replication_status.rb +0 -1
  24. data/lib/cheftacular/stateless_actions/slack.rb +8 -1
  25. data/lib/cheftacular/stateless_actions/update_cloudflare.rb +16 -51
  26. data/lib/cheftacular/stateless_actions/update_tld.rb +22 -19
  27. data/lib/cheftacular/stateless_actions/upload_nodes.rb +3 -1
  28. data/lib/cheftacular/version.rb +1 -1
  29. data/lib/cloud_interactor/domain/create_record.rb +7 -5
  30. data/lib/cloud_interactor/domain/list_records.rb +3 -1
  31. data/lib/cloud_interactor/domain/update_record.rb +4 -2
  32. data/lib/cloudflare/monkeypatches.rb +24 -0
  33. metadata +12 -10
  34. data/lib/cheftacular/remote_helpers.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 10f51fe71394a87e42196c9a3180865a43f652f9
4
- data.tar.gz: 8ab142943a10fd6f16a9b75519fc5f5dcc7a9633
3
+ metadata.gz: 432e618db73dd2f0c3c13dde66a0ba2d48139404
4
+ data.tar.gz: 24eba2f067f13d14f95075101b1eaabdbd2b767d
5
5
  SHA512:
6
- metadata.gz: 1c66d87535954bfc01de4ee4b68b54559fbeb83a206d244fa3e3cf7d80600bf53003c6661b2d3f1f9c5cf7d5a26b38831c0ecd966cab7a0a7607eb674c72be96
7
- data.tar.gz: 26289288c791fd916fe04cbab2d6e40e77d1c5fab4e2a92ff8f542d03f74d7e0d6f46b31d5e4fce4161a2e87183d40240e53c807dd5b09b694c2258edc8904cc
6
+ metadata.gz: 879cda27b14935f3e68ef5570d24c1e60bcfd2e33b3a25fd0126fb25b0f1669b4b5f8f9d55716f7b5e9de50046d7099fbaebc710c6074aca7e0e710630efa874
7
+ data.tar.gz: 745b5247a4393cda8a083a8215230d9e6d1a41c0653e91e8d537c13fd2f7ab7be8b387ac1d11cde2c71cf9e73f5bb52d32a66ade4c3f8b7519714bdb6449a6bb
@@ -1,10 +1,10 @@
1
1
  # Table of Contents for Cheftacular Commands
2
2
 
3
- 1. [Cheftacular Arguments and Flags](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#arguments-and-flags-for-cheftacular))
3
+ 1. [Cheftacular Arguments and Flags](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#arguments-and-flags-for-cheftacular)
4
4
 
5
5
  2. [Application Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-be-run-in-the-application-context)
6
6
 
7
- 3. [DevOps Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-only-be-run-in-the-devops-context))
7
+ 3. [DevOps Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-only-be-run-in-the-devops-context)
8
8
 
9
9
 
10
10
  ## Arguments and flags for cheftacular
@@ -51,14 +51,12 @@
51
51
 
52
52
  1. `-e|--except-role ROLE_NAME` will *prevent* any server with this role from being *deployed to* for the deploy command. Other commands will ignore this argument.
53
53
 
54
- 2. `-z|--unset-revision` will unset a custom revision specified in the arg below and make the codebase utilize the default (staging branch for staging and master for production)
54
+ 2. `-z|--unset-revision` will unset a custom revision specified in the arg below and make the codebase utilize the default.
55
55
 
56
56
  3. `-Z|--revision REVISION` will force the role you're deploying to to utilize the revision specified here. This can be a specific commit or a branch name.
57
57
 
58
58
  1. Note: The system does not check if the revision exists, if you pass a non-existent revision no one will be able to deploy to that role until -Z with a correction revision or -z is passed.
59
59
 
60
- 2. *You will not be able to set a custom revision for beta environments.* The beta environments are tied to split-staging and splita/b/c/d respectively.
61
-
62
60
 
63
61
  ## Commands that can be run in the application context
64
62
 
@@ -82,7 +80,7 @@
82
80
 
83
81
  6. `cft deploy` will do a simple chef-client run on the servers for a role. Logs of the run itself will be sent to the local log directory in the application (or chef-repo) where the run was conducted.
84
82
 
85
- 1. This command also restarts services on the server and updates the code. Changes behavior slightly with the `-z|-Z` args.
83
+ 1. This command also restarts services on the server and updates the code. Changes behavior slightly with the `-z|-Z` args but only if your cookbooks support switching revisions based on tags / branch names.
86
84
 
87
85
  7. `cft disk_report` will fetch useful statistics from every server for every environment and output it into your log directory.
88
86
 
@@ -128,9 +126,7 @@
128
126
 
129
127
  18. `cft reinitialize IP_ADDRESS NODE_NAME` will reconnect a server previously managed by chef to a new chef server. The node name MUST MATCH THE NODE'S ORIGINAL NODE NAME for the roles to be setup correctly.
130
128
 
131
- 19. `cft remove_client -n NODE_NAME` removes a client (and its node data) from the chef-server. It also removes its dns records from the cloud service (if possible). This should not be done lightly as you will have to wipe the server and trigger another chef-client run to get it to register again
132
-
133
- 20. `cft run COMMAND [--all]` will trigger the command on the first server in the role. Can be used to run rake commands or anything else.
129
+ 19. `cft run COMMAND [--all]` will trigger the command on the first server in the role. Can be used to run rake commands or anything else.
134
130
 
135
131
  1. `--all` will make the command run against all servers in a role rather than the first server it comes across. Don't do this if you're modifying the database with the command.
136
132
 
@@ -140,11 +136,11 @@
140
136
 
141
137
  4. IMPORTANT NOTE: You cannot run `cft run rake -T` as is, you have to enclose any command that uses command line dash arguments in quotes like `cft run "rake -T"`
142
138
 
143
- 21. `cft scale up|down [NUM_TO_SCALE]` will add (or remove) NUM_TO_SCALE servers from the server array. This command will not let you scale down below 1 server.
139
+ 20. `cft scale up|down [NUM_TO_SCALE]` will add (or remove) NUM_TO_SCALE servers from the server array. This command will not let you scale down below 1 server.
144
140
 
145
141
  1. In the case of server creation, this command takes a great deal of time to execute. It will output what stage it is currently on to the terminal but <b>you must not kill this command while it is executing</b>.A failed build may require the server to be destroyed / examined by a DevOps engineer.
146
142
 
147
- 22. `cft tail` will tail the logs (return continuous output) of the first node if finds that has an application matching the repository running on it. Currently only supports rails stacks
143
+ 21. `cft tail` will tail the logs (return continuous output) of the first node if finds that has an application matching the repository running on it. Currently only supports rails stacks
148
144
 
149
145
  1. pass `-n NODE_NAME` to grab the output of a node other than the first.
150
146
 
@@ -189,7 +185,7 @@
189
185
 
190
186
  3. This command is aliased to `client-list` with no arguments or cft prefix.
191
187
 
192
- 9. `cft cloud <FIRST_LEVEL_ARG> [<SECOND_LEVEL_ARG>[:<SECOND_LEVEL_ARG_QUERY>]*] ` this command handles talking to various cloud apis. If no args are passed nothing will happen.
188
+ 9. `cft cloud <FIRST_LEVEL_ARG> [<SECOND_LEVEL_ARG>[:<SECOND_LEVEL_ARG_QUERY>]*] ` this command handles talking to various cloud APIs. If no args are passed nothing will happen.
193
189
 
194
190
  1. `domain` 1st level argument for interacting with cloud domains
195
191
 
@@ -307,21 +303,27 @@
307
303
 
308
304
  21. `cft get_pg_pass ['clip']` command will output the current environment's pg_password to your terminal. Optionally you can pass in clip like `cft get_pg_pass clip` to have it also copy the pass to your clipboard.
309
305
 
310
- 22. `cft help COMMAND|MODE` this command returns the documentation for a specific command if COMMAND matches the name of a command. Alternatively, it can be passed `action|arguments|application|current|devops|stateless_action` to fetch the commands for a specific mode.Misspellings of commands will display near hits.
306
+ 22. `cft get_shorewall_allowed_connections` command will query a single server and return all of its ACCEPT connections from shorewall in it's syslog and return the results in a CSV format. Useful for tracking IP activity.
307
+
308
+ 1. This command will attempt to `dig` each ip address to give you the most likely culprit.
309
+
310
+ 23. `cft help COMMAND|MODE` this command returns the documentation for a specific command if COMMAND matches the name of a command. Alternatively, it can be passed `action|arguments|application|current|devops|stateless_action` to fetch the commands for a specific mode.Misspellings of commands will display near hits.
311
+
312
+ 24. `cft initialize_data_bag_contents ENVIRONMENT_NAME` will ensure the data bags always have the correct structure before each run. This command is run every time the gem is started and if called directly, will exit after completion.
311
313
 
312
- 23. `cft initialize_data_bag_contents ENVIRONMENT_NAME` will ensure the data bags always have the correct structure before each run. This command is run every time the gem is started and if called directly, will exit after completion.
314
+ 25. `cft knife_upload` will resync the chef-server with the local chef-repo code. This command is analog for `knife upload /`
313
315
 
314
- 24. `cft knife_upload` will resync the chef-server with the local chef-repo code. This command is analog for `knife upload /`
316
+ 26. `cft pass NODE_NAME` will drop the server's sudo password into your clipboard. Useful for when you need to ssh into the server itself and try advanced linux commands
315
317
 
316
- 25. `cft pass NODE_NAME` will drop the server's sudo password into your clipboard. Useful for when you need to ssh into the server itself and try advanced linux commands
318
+ 27. `cft remove_client -n NODE_NAME` removes a client (and its node data) from the chef-server. It also removes its dns records from the cloud service (if possible). This should not be done lightly as you will have to wipe the server and trigger another chef-client run to get it to register again
317
319
 
318
- 26. `cft replication_status` will check the status of the database master and slaves in every environment. Also lists how far behind the slaves are from the master in milliseconds.
320
+ 28. `cft replication_status` will check the status of the database master and slaves in every environment. Also lists how far behind the slaves are from the master in milliseconds.
319
321
 
320
- 27. `cft restart_swap` will restart the swap on every server that doesn't have swap currently on. Useful if you notice servers with no swap activated from `cft disk_report`
322
+ 29. `cft restart_swap` will restart the swap on every server that doesn't have swap currently on. Useful if you notice servers with no swap activated from `cft disk_report`
321
323
 
322
324
  1. There is no risk in running this command. Sometimes swap doesnt reactivate if the server was rebooted and this command fixes that.
323
325
 
324
- 28. `cft rvm [COMMAND] [ADDITIONAL_COMMANDS]*` will run rvm commands on the remote servers. Output from this command for each server will go into your rvm directory under the log directory. Please refer to [the rvm help page](https://rvm.io/rvm) for more information on rvm commands.
326
+ 30. `cft rvm [COMMAND] [ADDITIONAL_COMMANDS]*` will run rvm commands on the remote servers. Output from this command for each server will go into your rvm directory under the log directory. Please refer to [the rvm help page](https://rvm.io/rvm) for more information on rvm commands.
325
327
 
326
328
  1. When no commands are passed, rvm will just run `rvm list` on each server on all servers in the current environment.
327
329
 
@@ -337,11 +339,11 @@
337
339
 
338
340
  7. `upgrade_rvm` will run `rvm get stable --auth-dotfiles` on all servers for the current environment. It will also check and attempt to upgrade pre 1.25 installations of RVM to 1.26+ (which requires a GPG key).
339
341
 
340
- 29. `cft server_update [restart]` allows you to force update all nodes' packages for a specific environment. This should be done with caution as this *might* break something.
342
+ 31. `cft server_update [restart]` allows you to force update all nodes' packages for a specific environment. This should be done with caution as this *might* break something.
341
343
 
342
344
  1. `hip apt_update restart` will prompt to ask if you also want to restart all servers in a rolling restart. This should be done with extreme caution and only in a worst-case scenario.
343
345
 
344
- 30. `cft service [COMMAND] [SERVICE]` will run service commands on remote servers. This command only runs on the first server it comes across. Specify others with -n NODE_NAME.
346
+ 32. `cft service [COMMAND] [SERVICE]` will run service commands on remote servers. This command only runs on the first server it comes across. Specify others with -n NODE_NAME.
345
347
 
346
348
  1. When no commands are passed, the command will list all the services in the /etc/init directory
347
349
 
@@ -349,9 +351,13 @@
349
351
 
350
352
  3. When `restart|stop|start SERVICE` is passed, the command will attempt to restart|stop|start the service if it has a .conf file on the remote server in the /etc/init directory.
351
353
 
352
- 31. `cft slack "MESSAGE" [CHANNEL]` will attempt to post the message to the webhook set in your cheftacular.yml. Slack posts to your default channel by default but if the CHANNEL argument is supplied the message will post there.
354
+ 33. `cft slack "MESSAGE" [CHANNEL]` will attempt to post the message to the webhook set in your cheftacular.yml. Slack posts to your default channel by default but if the CHANNEL argument is supplied the message will post there.
353
355
 
354
- 32. `cft test_env [TARGET_ENV] boot|destroy` will create (or destroy) the test nodes for a particular environment (defaults to staging, prod split-envs can be set with `-p`). Please read below for how TARGET_ENV works
356
+ 1. NOTE: To prevent confusing spam from many possible sources, the username posted to slack will always be *Cheftacular*. This can be overloaded in the StatelessAction method "slack" but this is not recommended.
357
+
358
+ 2. Remember, if you have auditing turned on in your cheftacular.yml, you can track who sends what to slack.
359
+
360
+ 34. `cft test_env [TARGET_ENV] boot|destroy` will create (or destroy) the test nodes for a particular environment (defaults to staging, prod split-envs can be set with `-p`). Please read below for how TARGET_ENV works
355
361
 
356
362
  1. TARGET_ENV changes functionality depending on the overall (like staging / production) environment
357
363
 
@@ -361,9 +367,15 @@
361
367
 
362
368
  3. The default tld used should change depending on which environment you are booting / destroying. This is set in the environment's config data bag under the tld key
363
369
 
364
- 33. `cft ubuntu_bootstrap ADDRESS ROOT_PASS` This command will bring a fresh server to a state where chef-client can be run on it via `cft chef-bootstrap`. It should be noted that it is in this step where a server's randomized deploy_user sudo password is generated.
370
+ 35. `cft ubuntu_bootstrap ADDRESS ROOT_PASS` This command will bring a fresh server to a state where chef-client can be run on it via `cft chef-bootstrap`. It should be noted that it is in this step where a server's randomized deploy_user sudo password is generated.
371
+
372
+ 36. `cft update_cloudflare_dns_from_cloud` command will force a full dns update for cloudflare.
373
+
374
+ 1. It will ensure all the subdomain entries are correct (based on the contents of the addresses data bag) and update them if they are not. It will also create the local subdomain for the entry as well if it does exist and point it to the correct private address for an environment.
375
+
376
+ 2. This command will also ensure any dns records on your cloud are also migrated over to cloudflare as well. This also includes the reverse in the event you would like to turn off cloudflare.
365
377
 
366
- 34. `cft update_split_branches` will perform a series of git commands that will merge all the split branches for your split_branch enabled repositories with what is currently on master and push them.
378
+ 37. `cft update_split_branches` will perform a series of git commands that will merge all the split branches for your split_branch enabled repositories with what is currently on master and push them.
367
379
 
368
380
  1. Repository must be set with `-R REPOSITORY_NAME` for this command to work.
369
381
 
@@ -373,9 +385,9 @@
373
385
 
374
386
  4. This command will return a helpful error statement if you attempt to run the command with changes to your current working directory. You must commit these changes before running this command.
375
387
 
376
- 35. `cft update_tld TLD` command will force a full dns update for a tld in the preferred cloud. It will ensure all the subdomain entries are correct (based on the contents of the addresses data bag) and update them if they are not. It will also create the local subdomain for the entry as well if it does exist and point it to the correct private address.
388
+ 38. `cft update_tld TLD` command will force a full dns update for a tld in the preferred cloud. It will ensure all the subdomain entries are correct (based on the contents of the addresses data bag) and update them if they are not. It will also create the local subdomain for the entry as well if it does exist and point it to the correct private address.
377
389
 
378
- 36. `cft upload_nodes` This command will resync the chef server's nodes with the data in our chef-repo/node_roles.
390
+ 39. `cft upload_nodes` This command will resync the chef server's nodes with the data in our chef-repo/node_roles.
379
391
 
380
392
  1. This command changes behavior depending on several factors about both your mode and the state of your environment
381
393
 
@@ -387,4 +399,4 @@
387
399
 
388
400
  1. Due to this, only users running this against their chef-repo need to worry about having a nodes_dir, the way it should be.
389
401
 
390
- 37. `cft upload_roles` This command will resync the chef server's roles with the data in the chef-repo/roles.
402
+ 40. `cft upload_roles` This command will resync the chef server's roles with the data in the chef-repo/roles.
File without changes
@@ -6,7 +6,8 @@ class Cheftacular
6
6
  "Logs of the run itself will be sent to the local log directory in the application (or chef-repo) where the run was conducted.",
7
7
 
8
8
  [
9
- " 1. This command also restarts services on the server and updates the code. Changes behavior slightly with the `-z|-Z` args."
9
+ " 1. This command also restarts services on the server and updates the code. Changes behavior slightly with the `-z|-Z` args " +
10
+ "but only if your cookbooks support switching revisions based on tags / branch names."
10
11
  ]
11
12
  ]
12
13
  end
@@ -43,7 +43,9 @@ class Cheftacular
43
43
  end
44
44
 
45
45
  def migrate_wordpress nodes=[]
46
- raise "Not yet implemented"
46
+ puts "Method #{ __migrate_wordpress__ } isb ot yet implemented"
47
+
48
+ exit
47
49
  end
48
50
 
49
51
  def migrate_nodejs nodes=[]
File without changes
@@ -0,0 +1,283 @@
1
+
2
+ class Cheftacular
3
+ class DNS
4
+ def initialize options, config
5
+ @options, @config = options, config
6
+ end
7
+
8
+ def update_cloudflare_from_array_of_domain_hashes target_domain, target_domain_records
9
+ unless @config['helper'].does_cheftacular_config_have?(['cloudflare:api_key', 'cloudflare:user_email'])
10
+ puts "Critical! You tried to run update_cloudflare but have not set a cloudflare_api_key or cloudflare_user_email! Please set these keys and run this method again!"
11
+
12
+ exit
13
+ end
14
+
15
+ if @config[@options['env']]['config_bag_hash'][@options['sub_env']]['cloudflare_activated_domains'].empty?
16
+ puts "Critical! Tere are no entries in the 'cloudflare_activated_domains' array for domain #{ target_domain }! Please open the #{ @options['env'] } data bag item " +
17
+ "\"config\" and add the domains you want to be protected by cloudflare to the array as strings!"
18
+
19
+ exit
20
+ end
21
+
22
+ @config['cloudflare'] = CloudFlare::connection(@config['cheftacular']['cloudflare']['api_key'], @config['cheftacular']['cloudflare']['user_email'])
23
+
24
+ puts("Preparing to update cloudflare for domain #{ target_domain }...") unless @options['quiet']
25
+
26
+ cloudflare_records_hash = fetch_cloudflare_records_as_hash target_domain
27
+
28
+ puts('#'.ljust(4) + 'subdomain'.ljust(50) + 'type'.ljust(6) + 'ttl'.ljust(5) + 'mode'.ljust(20) + 'value') unless @options['quiet']
29
+
30
+ domain_count = 1
31
+
32
+ target_domain_records.each do |record_hash|
33
+ next if record_hash['type'] =~ /NS/
34
+
35
+ if record_hash['type'] =~ /A/
36
+ record_hash['activate_cloudflare'] = @config[@options['env']]['config_bag_hash'][@options['sub_env']]['cloudflare_activated_domains'].include?(record_hash['name'])
37
+ end
38
+
39
+ print(domain_count.to_s.ljust(4, '_') + record_hash['name'].ljust(50, '_') + record_hash['type'].ljust(6, '_') + record_hash['ttl'].to_s.ljust(5, '_'))
40
+
41
+ if cloudflare_records_hash.has_key?("#{ record_hash['name'] }-#{ record_hash['type'] }") && ( !cloudflare_records_hash["#{ record_hash['name'] }-#{ record_hash['type'] }"].empty? ||
42
+ cloudflare_record_does_include_value?(cloudflare_records_hash["#{ record_hash['name'] }-#{ record_hash['type'] }"], record_hash['value']) )
43
+
44
+ edit_cloudflare_record target_domain, record_hash, cloudflare_records_hash
45
+ else
46
+ compile_cloudflare_record_srv_attributes_on_record_hash record_hash, target_domain
47
+
48
+ @config['cloudflare'].rec_new(
49
+ target_domain,
50
+ record_hash['type'],
51
+ record_hash['name'],
52
+ record_hash['value'],
53
+ record_hash['ttl'],
54
+ record_hash['SRV_service'],
55
+ record_hash['SRV_srvname'],
56
+ record_hash['SRV_protocol'],
57
+ record_hash['SRV_weight'],
58
+ record_hash['SRV_port'],
59
+ record_hash['SRV_target'],
60
+ (record_hash['activate_cloudflare'] ? '1' : '0') #service_mode
61
+ )
62
+
63
+ print 'create'.ljust(20, '_')
64
+ end
65
+
66
+ domain_count += 1
67
+
68
+ print record_hash['value'] unless @options['quiet']
69
+
70
+ puts unless @options['quiet']
71
+ end
72
+ end
73
+
74
+ def create_dns_record_for_domain_from_address_hash domain, address_hash, *args
75
+ domain_obj = PublicSuffix.parse domain
76
+
77
+ if args.include?('specific_domain_mode')
78
+ puts("running cloud domain create_record:#{ domain_obj.domain }:#{ domain_obj.trd }:#{ address_hash['public'] }") if @options['verbose']
79
+
80
+ @config['stateless_action'].cloud "domain", "create_record:#{ domain_obj.domain }:#{ domain_obj.trd }:#{ address_hash['public'] }"
81
+
82
+ sleep 5
83
+
84
+ puts("running cloud domain create_record:#{ domain_obj.domain }:local.#{ domain_obj.trd }:#{ address_hash['address'] }") if @options['verbose']
85
+
86
+ @config['stateless_action'].cloud "domain", "create_record:#{ domain_obj.domain }:local.#{ domain_obj.trd }:#{ address_hash['address'] }"
87
+
88
+ #set the wildcard domain for frontend load balancers
89
+ if should_route_wildcard_requests?(address_hash['name'], @options['env'], address_hash['descriptor'])
90
+ puts("running cloud domain create_record:#{ domain_obj.domain }:*:#{ address_hash['public'] }") if @options['verbose']
91
+
92
+ @config['stateless_action'].cloud "domain", "create_record:#{ domain_obj.domain }:*:#{ address_hash['public'] }"
93
+ end
94
+ elsif args.empty?
95
+ puts("running cloud domain create_record:#{ domain }:#{ address_hash['name'] }:#{ address_hash['public'] }") if @options['verbose']
96
+
97
+ @config['stateless_action'].cloud "domain", "create_record:#{ domain }:#{ address_hash['name'] }:#{ address_hash['public'] }"
98
+
99
+ sleep 5
100
+
101
+ puts("running cloud domain create:create_record:#{ domain }:local.#{ address_hash['name'] }:#{ address_hash['address'] }") if @options['verbose']
102
+
103
+ @config['stateless_action'].cloud "domain", "create_record:#{ domain }:local.#{ address_hash['name'] }:#{ address_hash['address'] }"
104
+ end
105
+
106
+ unless @config[@options['env']]['config_bag_hash'][@options['sub_env']]['cloudflare_activated_domains'].empty?
107
+ return true unless @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld'] != domain_obj.tld
108
+
109
+ target_domain_records = []
110
+ target_domain_records << {
111
+ 'name' => "#{ domain_obj.trd }.#{ domain_obj.domain }",
112
+ 'type' => 'A',
113
+ 'value' => address_hash['public'],
114
+ 'ttl' => 300
115
+ }
116
+
117
+ target_domain_records << {
118
+ 'name' => "local.#{ domain_obj.trd }.#{ domain_obj.domain }",
119
+ 'type' => 'A',
120
+ 'value' => address_hash['address'],
121
+ 'ttl' => 300
122
+ }
123
+
124
+ update_cloudflare_from_array_of_domain_hashes domain_obj.tld, target_domain_records
125
+ end
126
+ end
127
+
128
+ def should_route_wildcard_requests? node_name, env, descriptor, should_route_requests=false
129
+ repository_hash = descriptor.blank? ? {} : @config['parser'].parse_repository_hash_from_string(descriptor)
130
+
131
+ if repository_hash.empty?
132
+ puts "Blank repository hash parsed for #{ node_name } in #{ env } with descriptor #{ descriptor }. Setting should route wildcard requests for server to false."
133
+ end
134
+
135
+ #puts "repositories:#{ repository_hash['role'] }:#{ repository_hash['repo_name'] }:route_wildcard_requests_for_tld"
136
+
137
+ if @config['helper'].does_cheftacular_config_have?(["repositories:#{ repository_hash['role'] }:route_wildcard_requests_for_tld"])
138
+ should_route_requests = @config['cheftacular']['repositories'][repository_hash['role']]['route_wildcard_requests_for_tld'] == 'true'
139
+ end
140
+
141
+ should_route_requests
142
+ end
143
+
144
+ def compile_address_hash_for_server_from_options *args
145
+ target_serv_index = nil
146
+ tld = @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld']
147
+
148
+ args.each do |arg|
149
+ if arg.include?('set_specific_domain:')
150
+ full_domain = arg.split(':').last
151
+
152
+ args << 'set_domain_name'
153
+ end
154
+ end
155
+
156
+ full_domain ||= "#{ @options['node_name'] }.#{ tld }"
157
+
158
+ @config[@options['env']]['addresses_bag_hash']['addresses'].each do |serv_hash|
159
+ target_serv_index = @config[@options['env']]['addresses_bag_hash']['addresses'].index(serv_hash) if serv_hash['name'] == @options['node_name']
160
+ end
161
+
162
+ #EX: "name": "api1", "public": "1.2.3.4", "address": "10.208.1.2", "dn":"api1.example.com", "descriptor": "lb:my-backend-codebase"
163
+ @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index] ||= {} unless args.include?('set_hash_to_nil')
164
+ @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['name'] = @options['node_name'] if args.include?('set_node_name') || args.include?('set_all_attributes')
165
+ @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['public'] = @options['address'] if args.include?('set_public_address') || args.include?('set_all_attributes')
166
+ @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['address'] = @options['private_address'] if args.include?('set_private_address') || args.include?('set_all_attributes')
167
+ @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['dn'] = full_domain if args.include?('set_domain_name') || args.include?('set_all_attributes')
168
+ @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['descriptor'] = (@options['descriptor'].nil? ? @options['node_name'] : @options['descriptor']) if args.include?('set_descriptor') || args.include?('set_all_attributes')
169
+
170
+ if !target_serv_index.nil? && target_serv_index.is_a?(Fixnum) && !@options['dont_remove_address_or_server'] && args.include?('set_hash_to_nil')
171
+ puts("Found entry in addresses data bag corresponding to #{ @options['node_name'] } for #{ @options['env'] }, removing...") unless @options['quiet']
172
+
173
+ @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index] = nil
174
+
175
+ @config[@options['env']]['addresses_bag_hash']['addresses'] = @config[@options['env']]['addresses_bag_hash']['addresses'].compact
176
+
177
+ domain_obj = PublicSuffix.parse @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['dn']
178
+
179
+ @config['stateless_action'].cloud "domain", "destroy_record:#{ domain_obj.tld }:#{ domain_obj.trd }" if domain_obj.tld == @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld']
180
+ end
181
+
182
+ @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index] unless args.include?('set_hash_to_nil')
183
+ end
184
+
185
+ private
186
+
187
+ def fetch_cloudflare_records_as_hash target_domain, ret_hash={}
188
+ request = @config['cloudflare'].rec_load_all(target_domain)['response']['recs']
189
+ original_records, count = [], 0
190
+
191
+ while request['has_more']
192
+ original_records << request['objs']
193
+
194
+ count += request['count']
195
+
196
+ request = @config['cloudflare'].rec_load_all(target_domain, count)['response']['recs']
197
+ end
198
+
199
+ original_records << request['objs']
200
+
201
+ original_records.flatten.each do |record_hash|
202
+ ret_hash["#{ record_hash['name'] }-#{ record_hash['type'] }"] ||= []
203
+ ret_hash["#{ record_hash['name'] }-#{ record_hash['type'] }"] << record_hash
204
+ end
205
+
206
+ ret_hash
207
+ end
208
+
209
+ def edit_cloudflare_record target_domain, record_hash, cloudflare_records_hash
210
+ possible_matches = cloudflare_records_hash["#{ record_hash['name'] }-#{ record_hash['type'] }"]
211
+
212
+ raise "Critical! No cloudflare record was found to edit for #{ target_domain }: #{ record_hash['name'] }!" if possible_matches.nil?
213
+
214
+ if possible_matches.count > 1
215
+ possible_matches.each do |match_hash|
216
+ if match_hash.has_key?('matched_already')
217
+ next
218
+ else
219
+ compile_cloudflare_record_srv_attributes_on_record_hash record_hash, target_domain
220
+
221
+ begin
222
+ @config['cloudflare'].rec_edit(
223
+ target_domain,
224
+ record_hash['type'],
225
+ match_hash['rec_id'],
226
+ record_hash['name'],
227
+ record_hash['value'],
228
+ record_hash['ttl'],
229
+ record_hash['activate_cloudflare'],
230
+ record_hash['priority'],
231
+ record_hash['SRV_service'],
232
+ record_hash['SRV_srvname'],
233
+ record_hash['SRV_protocol'],
234
+ record_hash['SRV_weight'],
235
+ record_hash['SRV_port'],
236
+ record_hash['SRV_target']
237
+ )
238
+
239
+ match_hash['matched_already'] = true
240
+
241
+ print 'edit_on_multi_match_'.ljust(19, '_')
242
+ rescue CloudFlare::RequestError => e
243
+ if e.message == 'A record with those settings already exists.'
244
+ print 'edit_fail_match_'
245
+
246
+ next
247
+ else
248
+ @config['helper'].exception_output "There was an issue updating Cloudflare! Please create an issue on the cheftacular repository with this stacktrace!", e
249
+ end
250
+ end
251
+
252
+ break
253
+ end
254
+ end
255
+ else
256
+ print 'edit'.ljust(20, '_')
257
+
258
+ @config['cloudflare'].rec_edit(target_domain, record_hash['type'], possible_matches[0]['rec_id'], record_hash['name'], record_hash['value'], record_hash['ttl'])
259
+ end
260
+ end
261
+
262
+ def cloudflare_record_does_include_value? cloudflare_record, record_hash_value
263
+ cloudflare_record.each do |match_record|
264
+ return true if record_hash_value == match_record['content']
265
+ end
266
+
267
+ false
268
+ end
269
+
270
+ def compile_cloudflare_record_srv_attributes_on_record_hash record_hash, target_domain
271
+ return false unless record_hash['type'].upcase == 'SRV'
272
+
273
+ record_hash['SRV_service'] = record_hash['name'].split('.')[0]
274
+ record_hash['SRV_srvname'] = target_domain
275
+ record_hash['SRV_protocol'] = record_hash['name'].split('.')[1]
276
+ record_hash['SRV_weight'] = record_hash['value'].split(' ')[0].to_i
277
+ record_hash['SRV_port'] = record_hash['value'].split(' ')[1].to_i
278
+ record_hash['SRV_target'] = record_hash['value'].split(' ')[2]
279
+ record_hash['value'] = "#{ record_hash['priority'] } IN SRV #{ record_hash['SRV_weight'] } #{ record_hash['SRV_port'] } #{ record_hash['SRV_target'] }."#10 IN SRV 5 8806 somewhere.com
280
+ #record_hash['name'] = ''
281
+ end
282
+ end
283
+ end