fhcap-cli 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rakeTasks +7 -0
  4. data/.rspec +1 -0
  5. data/CHANGELOG.md +15 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +150 -0
  9. data/Rakefile +2 -0
  10. data/bin/fhcap +6 -0
  11. data/fhcap-cli.gemspec +44 -0
  12. data/lib/cookbooks/provision/libraries/provision.rb +140 -0
  13. data/lib/cookbooks/provision/metadata.rb +7 -0
  14. data/lib/cookbooks/provision/recipes/aws.rb +15 -0
  15. data/lib/cookbooks/provision/recipes/aws_cluster_create.rb +59 -0
  16. data/lib/cookbooks/provision/recipes/aws_cluster_create_elb.rb +61 -0
  17. data/lib/cookbooks/provision/recipes/aws_cluster_destroy.rb +52 -0
  18. data/lib/cookbooks/provision/recipes/cluster_create.rb +2 -0
  19. data/lib/cookbooks/provision/recipes/cluster_destroy.rb +2 -0
  20. data/lib/cookbooks/provision/recipes/cluster_destroy_instances.rb +11 -0
  21. data/lib/cookbooks/provision/recipes/cluster_provision.rb +4 -0
  22. data/lib/cookbooks/provision/recipes/cluster_provision_instances.rb +55 -0
  23. data/lib/cookbooks/provision/recipes/cluster_status.rb +24 -0
  24. data/lib/cookbooks/provision/recipes/common.rb +9 -0
  25. data/lib/cookbooks/provision/recipes/default.rb +5 -0
  26. data/lib/cookbooks/provision/recipes/openstack.rb +11 -0
  27. data/lib/cookbooks/provision/recipes/openstack_cluster_create.rb +11 -0
  28. data/lib/cookbooks/provision/recipes/openstack_cluster_destroy.rb +4 -0
  29. data/lib/cookbooks/provision/recipes/reset_rabbitmq.rb +49 -0
  30. data/lib/cookbooks/provision/recipes/restart_services.rb +24 -0
  31. data/lib/extensions/chef/provisioning.rb +21 -0
  32. data/lib/extensions/chef/provisioning/aws_driver/driver.rb +46 -0
  33. data/lib/extensions/chef/provisioning/chef_run_data.rb +18 -0
  34. data/lib/extensions/cheffish/merged_config.rb +9 -0
  35. data/lib/fhcap.rb +14 -0
  36. data/lib/fhcap/chef-dk/chef_runner.rb +94 -0
  37. data/lib/fhcap/cli.rb +75 -0
  38. data/lib/fhcap/cluster.rb +112 -0
  39. data/lib/fhcap/config.rb +104 -0
  40. data/lib/fhcap/cookbook.rb +75 -0
  41. data/lib/fhcap/dummy_node.rb +80 -0
  42. data/lib/fhcap/fhcap_helper.rb +9 -0
  43. data/lib/fhcap/kitchen.rb +235 -0
  44. data/lib/fhcap/knife.rb +74 -0
  45. data/lib/fhcap/knife_helper.rb +38 -0
  46. data/lib/fhcap/misc.rb +103 -0
  47. data/lib/fhcap/provider.rb +41 -0
  48. data/lib/fhcap/providers_helper.rb +60 -0
  49. data/lib/fhcap/repo.rb +52 -0
  50. data/lib/fhcap/repos_helper.rb +217 -0
  51. data/lib/fhcap/tasks/chef/chef_task_base.rb +82 -0
  52. data/lib/fhcap/tasks/chef/cookbook/list.rb +37 -0
  53. data/lib/fhcap/tasks/chef/cookbook/update_changelog.rb +63 -0
  54. data/lib/fhcap/tasks/chef/cookbook/update_metadata.rb +57 -0
  55. data/lib/fhcap/tasks/chef/cookbook/update_readme.rb +30 -0
  56. data/lib/fhcap/tasks/chef/cookbook/update_version.rb +90 -0
  57. data/lib/fhcap/tasks/chef/environments/create.rb +115 -0
  58. data/lib/fhcap/tasks/chef/environments/destroy.rb +37 -0
  59. data/lib/fhcap/tasks/chef/environments/promote_cookbooks.rb +47 -0
  60. data/lib/fhcap/tasks/chef/provisioning/chef_provisioning_task.rb +27 -0
  61. data/lib/fhcap/tasks/chef/provisioning/chef_provisioning_task_base.rb +38 -0
  62. data/lib/fhcap/tasks/chef/provisioning/create.rb +22 -0
  63. data/lib/fhcap/tasks/chef/provisioning/destroy.rb +21 -0
  64. data/lib/fhcap/tasks/chef/provisioning/provision.rb +19 -0
  65. data/lib/fhcap/tasks/chef/server/bootstrap.rb +165 -0
  66. data/lib/fhcap/tasks/chef/server/create_user.rb +97 -0
  67. data/lib/fhcap/tasks/chef/server/info.rb +82 -0
  68. data/lib/fhcap/tasks/chef/server/provision.rb +45 -0
  69. data/lib/fhcap/tasks/clean.rb +34 -0
  70. data/lib/fhcap/tasks/cluster/cluster_task_base.rb +57 -0
  71. data/lib/fhcap/tasks/cluster/create.rb +243 -0
  72. data/lib/fhcap/tasks/cluster/create_environment.rb +171 -0
  73. data/lib/fhcap/tasks/cluster/destroy.rb +30 -0
  74. data/lib/fhcap/tasks/cluster/destroy_environment.rb +28 -0
  75. data/lib/fhcap/tasks/cluster/info.rb +67 -0
  76. data/lib/fhcap/tasks/cluster/list.rb +40 -0
  77. data/lib/fhcap/tasks/cluster/provision.rb +46 -0
  78. data/lib/fhcap/tasks/cluster/status.rb +17 -0
  79. data/lib/fhcap/tasks/cluster/test.rb +15 -0
  80. data/lib/fhcap/tasks/knife/add.rb +111 -0
  81. data/lib/fhcap/tasks/knife/list.rb +22 -0
  82. data/lib/fhcap/tasks/knife/remove.rb +39 -0
  83. data/lib/fhcap/tasks/misc/create_dns_record.rb +100 -0
  84. data/lib/fhcap/tasks/misc/create_ssl_cert.rb +82 -0
  85. data/lib/fhcap/tasks/provider/add.rb +136 -0
  86. data/lib/fhcap/tasks/provider/list.rb +31 -0
  87. data/lib/fhcap/tasks/provider/remove.rb +28 -0
  88. data/lib/fhcap/tasks/repo/add.rb +57 -0
  89. data/lib/fhcap/tasks/repo/checkout.rb +144 -0
  90. data/lib/fhcap/tasks/repo/list.rb +22 -0
  91. data/lib/fhcap/tasks/repo/remove.rb +34 -0
  92. data/lib/fhcap/tasks/setup.rb +59 -0
  93. data/lib/fhcap/tasks/task_base.rb +89 -0
  94. data/lib/fhcap/thor_base.rb +121 -0
  95. data/lib/fhcap/version.rb +3 -0
  96. data/spec/fhcap/cli_spec.rb +6 -0
  97. data/spec/fhcap/tasks/cluster/create_spec.rb +46 -0
  98. data/spec/fhcap/tasks/knife/add_spec.rb +35 -0
  99. data/spec/fhcap/tasks/knife/remove_spec.rb +25 -0
  100. data/spec/fhcap/tasks/provider/add_spec.rb +61 -0
  101. data/spec/fhcap/tasks/provider/remove_spec.rb +25 -0
  102. data/spec/fhcap/tasks/repo/add_spec.rb +32 -0
  103. data/spec/fhcap/tasks/repo/remove_spec.rb +25 -0
  104. data/spec/fhcap/tasks/task_base_spec.rb +51 -0
  105. data/spec/fhcap/thor_base_spec.rb +9 -0
  106. data/spec/spec_helper.rb +23 -0
  107. data/spec/support/dummy_config.rb +7 -0
  108. data/spec/support/dummy_thor.rb +3 -0
  109. data/templates/chef/cookbook/changelog.md.erb +12 -0
  110. data/templates/chef/cookbook/metadata.erb +45 -0
  111. data/templates/chef/environment_core.json.erb +278 -0
  112. data/templates/chef/environment_empty.json.erb +10 -0
  113. data/templates/chef/environment_mbaas.json.erb +120 -0
  114. data/templates/chef/environment_single.json.erb +300 -0
  115. data/templates/cluster/aws/common.json.erb +43 -0
  116. data/templates/cluster/aws/core-3node.json.erb +106 -0
  117. data/templates/cluster/aws/core-small-9node.json.erb +333 -0
  118. data/templates/cluster/aws/mbaas-3node.json.erb +116 -0
  119. data/templates/cluster/aws/nginx-test.json.erb +93 -0
  120. data/templates/cluster/aws/single-blank.json.erb +41 -0
  121. data/templates/cluster/aws/single.json.erb +88 -0
  122. data/templates/cluster/core-3node.json.erb +8 -0
  123. data/templates/cluster/core-mbaas-6node.json.erb +13 -0
  124. data/templates/cluster/core-small-9node.json.erb +8 -0
  125. data/templates/cluster/mbaas-3node.json.erb +9 -0
  126. data/templates/cluster/nginx-test.json.erb +8 -0
  127. data/templates/cluster/openstack/common.json.erb +7 -0
  128. data/templates/cluster/openstack/core-3node.json.erb +14 -0
  129. data/templates/cluster/openstack/core-small-9node.json.erb +32 -0
  130. data/templates/cluster/openstack/mbaas-3node.json.erb +14 -0
  131. data/templates/cluster/openstack/nginx-test.json.erb +11 -0
  132. data/templates/cluster/openstack/single-blank.json.erb +10 -0
  133. data/templates/cluster/openstack/single.json.erb +10 -0
  134. data/templates/cluster/single-blank.json.erb +8 -0
  135. data/templates/cluster/single.json.erb +8 -0
  136. data/templates/init/knife.rb.erb +13 -0
  137. data/templates/kitchen/Cheffile.erb +11 -0
  138. data/templates/kitchen/kitchen.aws.yml.erb +35 -0
  139. data/templates/kitchen/kitchen.docker.yml.erb +24 -0
  140. data/templates/kitchen/kitchen.generate.yml.erb +2 -0
  141. data/templates/kitchen/kitchen.openstack.yml.erb +31 -0
  142. metadata +506 -0
@@ -0,0 +1,27 @@
1
+ require 'fhcap/tasks/chef/provisioning/chef_provisioning_task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Chef
6
+ module Provisioning
7
+ class ChefProvisioningTask < ChefProvisioningTaskBase
8
+
9
+ attr_reader :run_list
10
+
11
+ def initialize(options)
12
+ super
13
+ @run_list = options[:'run-list']
14
+ end
15
+
16
+ def run
17
+ thor.say "Chef::Provisioning::Task name = #{@name}, run_list = #{@run_list}", :yellow
18
+ do_chef_run(run_list)
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+
@@ -0,0 +1,38 @@
1
+ require 'fhcap/tasks/chef/chef_task_base'
2
+ require 'fhcap/chef-dk/chef_runner'
3
+
4
+ module Fhcap
5
+ module Tasks
6
+ module Chef
7
+ module Provisioning
8
+ class ChefProvisioningTaskBase < ChefTaskBase
9
+
10
+ attr_reader :name, :cluster_config, :cluster_filepath, :chef_server
11
+
12
+ def initialize(options)
13
+ super
14
+ @name = options[:name]
15
+ @cluster_filepath = find_cluster(name)
16
+ if @cluster_filepath
17
+ @cluster_config = JSON.parse(IO.read(@cluster_filepath), {:symbolize_names => true})
18
+ @cluster_config.merge!({
19
+ local_repo_path: repo_dir(@cluster_config[:repo]),
20
+ chef_server_config: chef_server_config_hash_for(@cluster_config[:chef_server]),
21
+ provider_credentials: provider_credentials(@cluster_config[:provider_id])
22
+ })
23
+ @chef_server = @cluster_config[:chef_server]
24
+ else
25
+ exit_with_error("Unknown cluster #{@name}")
26
+ end
27
+ end
28
+
29
+ def do_chef_run(run_list)
30
+ cookbook_path = File.join(Fhcap.source_root, 'lib', 'cookbooks')
31
+ Fhcap::ChefRunner.new(cookbook_path, run_list, @cluster_config).converge
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ require 'fhcap/tasks/chef/provisioning/chef_provisioning_task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Chef
6
+ module Provisioning
7
+ class Create < ChefProvisioningTaskBase
8
+
9
+ def run
10
+ thor.say "Chef::Provisioning::Create #{@name}", :yellow
11
+ do_chef_run("provision::cluster_create")
12
+ do_chef_run("provision::reset_rabbitmq")
13
+ do_chef_run("provision::restart_services")
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+
@@ -0,0 +1,21 @@
1
+ require 'fhcap/tasks/chef/provisioning/chef_provisioning_task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Chef
6
+ module Provisioning
7
+ class Destroy < ChefProvisioningTaskBase
8
+
9
+ def run
10
+ thor.say "Chef::Provisioning::Destroy #{@name}", :yellow
11
+ if thor.yes? "Destroy cluster #{@name}? (y/n)"
12
+ run_list = "provision::cluster_destroy"
13
+ do_chef_run(run_list)
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ require 'fhcap/tasks/chef/provisioning/chef_provisioning_task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Chef
6
+ module Provisioning
7
+ class Provision < ChefProvisioningTaskBase
8
+
9
+ def run
10
+ thor.say "Chef::Provisioning::Provision #{@name}", :yellow
11
+ run_list = "provision::cluster_provision"
12
+ do_chef_run(run_list)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,165 @@
1
+ require 'fhcap/tasks/chef/chef_task_base'
2
+ require 'chef/knife/diff'
3
+
4
+ module Fhcap
5
+ module Tasks
6
+ module Chef
7
+ module Server
8
+ class Bootstrap < ChefTaskBase
9
+
10
+ attr_reader :environments
11
+
12
+ def initialize(options)
13
+ super
14
+ @environments = options[:environments]
15
+ @chef_server = options[:chef_server]
16
+ @diff_strategy = options[:'diff-strategy'] || 'knife'
17
+ @skip_roles = options[:'skip-roles']
18
+ @skip_data_bags = options[:'skip-data-bags']
19
+ @skip_environments = options[:'skip-environments']
20
+ @skip_cookbooks = options[:'skip-cookbooks']
21
+ end
22
+
23
+ def run
24
+ thor.say "Chef::Server::Bootstrap: environments = #{environments}", :yellow
25
+
26
+ chef_server_environments = {}
27
+ environments.each do |environment|
28
+ chef_server = select_chef_server(environment, @chef_server)
29
+ chef_server_environments[chef_server] = chef_server_environments[chef_server] || []
30
+ chef_server_environments[chef_server] << environment
31
+ end
32
+
33
+ chef_server_environments.each do |server, environments|
34
+ sync_roles({:environments => environments, :server => server}) unless @skip_roles
35
+ sync_data_bags({:environments => environments, :server => server}) unless @skip_data_bags
36
+ sync_environments({:environments => environments, :server => server}) unless @skip_environments
37
+ sync_cookbooks({:environments => environments, :server => server}) unless @skip_cookbooks
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def sync_roles(options)
44
+ sync_items('roles', options) do |local_repo, sync_items|
45
+ sync_items.each do |item|
46
+ unless item =~ /roles\/dev*/
47
+ run_knife_cmd("role from file #{File.join(local_repo, item)}", options[:server])
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def sync_data_bags(options, bag_created_cache=[])
54
+ requires_resync = false
55
+ sync_items('data_bags', options) do |local_repo, sync_items|
56
+ sync_items.each do |item|
57
+ if include_data_bag_item?(item, options)
58
+ tmp, bag, bag_item = item.split('/')
59
+ if bag
60
+ unless bag_created_cache.include? bag
61
+ output = run_knife_cmd("data bag create #{bag}", options[:server])
62
+ requires_resync = requires_resync || output =~ /Created/
63
+ bag_created_cache << bag
64
+ end
65
+ if bag_item
66
+ run_knife_cmd("data bag from file #{bag} #{File.join(local_repo, item)}", options[:server])
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ sync_data_bags(options, bag_created_cache) if requires_resync
73
+ end
74
+
75
+ def include_data_bag_item?(item, options)
76
+ include = true
77
+ environments = options[:environments]
78
+ if environments
79
+ if item =~ /nagios_/
80
+ #As usual nagios requires the most work Argghh
81
+ nagios_data_bag_name = item.split('/')[1]
82
+ #Default nagios data bags will only be 2 in length, check everything else
83
+ if nagios_data_bag_name.split('_').length > 2
84
+ allowed = ['fheng', 'production']
85
+ allowed |= environments
86
+ allowed |= environments.collect { |env| env.gsub('-', '_') } # Prod data bags are named incorrectly for some reason
87
+ include = allowed.any? { |val| nagios_data_bag_name =~ /#{val}/ }
88
+ end
89
+ elsif item =~ /environments\//
90
+ include = environments.any? { |val| item =~ /#{val}/ }
91
+ end
92
+ end
93
+ include
94
+ end
95
+
96
+ def sync_environments(options)
97
+ environments = options[:environments]
98
+ if environments
99
+ sync_items('environments', options) do |local_repo, sync_items|
100
+ sync_items.each do |item|
101
+ if environments.any? { |val| item =~ /#{val}/ }
102
+ run_knife_cmd("environment from file #{File.join(local_repo, item)}", options[:server])
103
+ end
104
+ end
105
+ end
106
+ else
107
+ #thor.say "No environments specified!!"
108
+ end
109
+ end
110
+
111
+ def sync_cookbooks(options)
112
+ #sync_items('cookbooks', options) do |local_repo, sync_items|
113
+ # modified_cookbooks = sync_items.collect do |cookbook|
114
+ # cookbook.split('/')[1]
115
+ # end.uniq
116
+ # run_knife_cmd("cookbook upload #{modified_cookbooks.join(' ')} --force", options[:server]) unless modified_cookbooks.empty?
117
+ #end
118
+ run_knife_cmd("cookbook upload -a --force", options[:server], !verbose)
119
+ end
120
+
121
+ def sync_items(item, options)
122
+ repo_paths.each do |local_repo|
123
+ #thor.say "Syncing #{item} in #{local_repo} based on #{@diff_strategy} diff", :yellow
124
+ if @diff_strategy == 'git'
125
+ item = %w{cookbooks site-cookbooks wrapper-cookbooks} if item == 'cookbooks'
126
+ yield local_repo, git_diff(item, local_repo)
127
+ else
128
+ yield local_repo, knife_diff(item, local_repo, options[:server])
129
+ end
130
+ end
131
+ #thor.say "All #{item} synced successfully!"
132
+ end
133
+
134
+ def git_diff(item, local_repo)
135
+ result = ''
136
+ Dir.chdir local_repo do
137
+ paths = item.is_a?(Array) ? item : [item]
138
+ paths.each do |path|
139
+ if Dir.exists? File.join(local_repo, path)
140
+ result += `git diff --name-only origin/master -- #{path}`
141
+ end
142
+ end
143
+ end
144
+ result.split
145
+ end
146
+
147
+ def knife_diff(item, local_repo, server)
148
+ result = ''
149
+ if Dir.exists? File.join(local_repo, item)
150
+ thor.inside local_repo do
151
+ cmd = "knife diff #{item} --chef-repo-path #{local_repo} --repo-mode static --name-only --diff-filter=[AM] --config #{knife_config_file_for(server)}"
152
+ result = thor.run(cmd, :capture => true)
153
+ thor.say result if verbose
154
+ end
155
+ else
156
+ #thor.say "No #{item} in #{local_repo}"
157
+ end
158
+ result.split
159
+ end
160
+
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,97 @@
1
+ require 'fhcap/tasks/chef/chef_task_base'
2
+ require 'chef/config'
3
+ require 'securerandom'
4
+
5
+ module Fhcap
6
+ module Tasks
7
+ module Chef
8
+ module Server
9
+ class CreateUser < ChefTaskBase
10
+
11
+ attr_reader :user_config, :chef_server_version
12
+
13
+ def initialize(options)
14
+ super
15
+ @chef_server_version = options[:'chef-server-version'] || 'osc'
16
+ @user_config = {
17
+ chef_server: options[:'chef-server'],
18
+ username: options[:username],
19
+ display_name: options[:'display-name'] || @username,
20
+ first_name: options[:'first-name'] || @username,
21
+ last_name: options[:'last-name'] || @username,
22
+ email: options[:email],
23
+ password: options[:password] || SecureRandom.urlsafe_base64(6),
24
+ validation_client_name: @validation_client_name,
25
+ }
26
+ end
27
+
28
+ def run
29
+ thor.say "Knife::CreateUser", :yellow
30
+
31
+ ask_config(required_config, user_config)
32
+
33
+ if @chef_server_version == 'osc'
34
+ cmd = "osc_user create #{user_config[:username]} -p #{user_config[:password]} -y -d -a"
35
+ else
36
+ cmd = "user create #{user_config[:username]} #{user_config[:display_name]} #{user_config[:first_name]} #{user_config[:last_name]} #{user_config[:email]} #{user_config[:password]} -y"
37
+ end
38
+
39
+ import_cfg = {}
40
+
41
+ private_key = run_knife_cmd(cmd, user_config[:chef_server])
42
+
43
+ if $?.exitstatus == 0
44
+ knife_config_dir = config[:knife_dir] || File.join(config.default_dir, '.chef')
45
+ knife_config_file = File.join(knife_config_dir, "knife-#{user_config[:chef_server]}.rb")
46
+ ::Chef::Config.from_file(knife_config_file)
47
+ file = File.open(::Chef::Config[:validation_key], "rb")
48
+ validation_key = file.read
49
+
50
+ import_cfg[:chef_server_url] = ::Chef::Config[:chef_server_url]
51
+ import_cfg[:validation_client_name] = ::Chef::Config[:validation_client_name]
52
+ import_cfg[:node_name] = user_config[:username]
53
+ import_cfg[:private_key] = private_key
54
+ import_cfg[:validation_key] = validation_key
55
+
56
+ import_file = File.join(config.tmp_dir,"#{user_config[:username]}-#{user_config[:chef_server]}_import.json")
57
+ thor.create_file(import_file, JSON.pretty_generate(import_cfg), :force => true)
58
+
59
+ table_contents = [table_header('Username', 'Password', 'Chef Server URL')]
60
+ table_contents << table_row(user_config[:username], user_config[:password], ::Chef::Config[:chef_server_url])
61
+ thor.print_table table_contents
62
+
63
+ table_contents = [table_header('Private Key')]
64
+ table_contents << table_row(private_key)
65
+ thor.print_table table_contents
66
+
67
+ table_contents = [table_header('Validation Key')]
68
+ table_contents << table_row(validation_key)
69
+ thor.print_table table_contents
70
+
71
+ thor.say_status 'warning', "The validation key shown above is the validation key used by you for '#{user_config[:chef_server]}'. If you don't normally share this key between users, you should create a new one manually for '#{user_config[:username]}'", :yellow
72
+
73
+ thor.say_status 'Import Command:', "fhcap knife add --name #{user_config[:chef_server]} --import-file #{import_file}", :cyan
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def required_config
80
+ {
81
+ username: {
82
+ },
83
+ chef_server: {
84
+ options: {:limited_to => chef_server_names}
85
+ },
86
+ email: {
87
+ },
88
+ password: {
89
+ }
90
+ }
91
+ end
92
+
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,82 @@
1
+ require 'fhcap/tasks/chef/chef_task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Chef
6
+ module Server
7
+ class Info < ChefTaskBase
8
+
9
+ attr_reader :environments, :node_names, :roles, :chef_server, :urls
10
+
11
+ def initialize(options)
12
+ super
13
+ @environments = options[:environments]
14
+ @node_names = options[:nodes]
15
+ @roles = options[:roles]
16
+ @chef_server = options[:chef_server]
17
+ @urls = {}
18
+ end
19
+
20
+ def run
21
+ thor.say "Chef::Server::Info: environments = #{environments}", :yellow
22
+ environments.each do |env|
23
+ ip_addresses(env) unless options[:only] && options[:only] != 'ips'
24
+ management_dashboards(env) unless options[:only] && options[:only] != 'urls'
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def ip_addresses(env)
31
+ thor.say "[#{env}] IP Addresses", :green
32
+ search_cmd = "search 'chef_environment:#{env}'"
33
+ search_options = '-a cloud.public_ips'
34
+ nodes_for(search_cmd, search_options) do |node|
35
+ thor.say_status "[#{env}] #{node['name']}:", node['cloud.public_ips'].join(','), :cyan
36
+ end
37
+ end
38
+
39
+ def management_dashboards(env)
40
+ thor.say "[#{env}] Monitoring Dashboards", :green
41
+ urls[env] = {} unless urls[env]
42
+ search_cmd = "search 'chef_environment:#{env} AND roles:management_server'"
43
+ search_options = '-a cloud.public_ips -a munin.web_server_port -a nagios.http_port'
44
+ nodes_for(search_cmd, search_options) do |node|
45
+ urls[env][:nagios] = "http://#{node['cloud.public_ips'].first}:#{node['nagios.http_port']}"
46
+ urls[env][:munin] = "http://#{node['cloud.public_ips'].first}:#{node['munin.web_server_port']}/munin"
47
+ thor.say_status "[#{env}] Nagios Dashboard:", "#{urls[env][:nagios]}", :cyan
48
+ thor.say_status "[#{env}] Munin Dashboard:", "#{urls[env][:munin]}", :cyan
49
+ end
50
+
51
+ search_cmd = "search 'chef_environment:#{env} AND roles:rabbitmq_server'"
52
+ search_options = '-a cloud.public_ips -a rabbitmq.web_console_ssl_port'
53
+ node = nodes_for(search_cmd, search_options).first
54
+ if node
55
+ urls[env][:rabbitmq] = "http://#{node['cloud.public_ips'].first}:#{node['rabbitmq.web_console_ssl_port']}"
56
+ thor.say_status "[#{env}] RabbitMQ Dashboard:", "#{urls[env][:rabbitmq]}", :cyan
57
+ end
58
+
59
+ end
60
+
61
+ def nodes_for(search_cmd, search_options)
62
+ cmd = "cd #{File.expand_path("..", knife_config_dir)} && knife #{search_cmd} #{search_options} -c #{knife_config_file_for(chef_server)} -F json"
63
+ raw_nodes = JSON.parse(`#{cmd}`)
64
+ nodes = []
65
+ if raw_nodes['rows'].empty?
66
+ thor.say("No node found for '#{search_cmd}'")
67
+ else
68
+ raw_nodes['rows'].each do |node|
69
+ name, attrs = node.first
70
+ attrs.merge!({'name' => name})
71
+ nodes << attrs
72
+ yield attrs if block_given?
73
+ end
74
+ end
75
+ nodes
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end