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,80 @@
1
+ require 'chef/node'
2
+
3
+ module Fhcap
4
+ class DummyNode < Chef::Node
5
+
6
+
7
+ attr_accessor :included_recipe_attributes
8
+
9
+ def initialize
10
+ super
11
+ @included_recipe_attributes = []
12
+ end
13
+
14
+ def include_attribute(recipe)
15
+ @included_recipe_attributes << recipe
16
+ end
17
+
18
+ def from_file(filename)
19
+ if File.exists?(filename) && File.readable?(filename)
20
+ #Convert any references to node['blah'] to a string so instance_eval doesn't try to evaluate it
21
+ text = ""
22
+ ignore_lines = false
23
+ File.open(filename).each_line do |line|
24
+ key, value = line.split(/ = /, 2)
25
+ if key && value
26
+ ignore_lines = false
27
+ if ignore_key? key
28
+ value = "\"Ignored\""
29
+ ignore_lines = true
30
+ else
31
+ value.gsub!(/node(\[['a-zA-Z0-9_-]*\])+/, '"\&"')
32
+ value.gsub!(/node.chef_environment/, '"\&"')
33
+ if value =~ /\.* \| "node\[/
34
+ value.gsub!(/"/, '')
35
+ value = "\"#{value.chomp}\"\n"
36
+ end
37
+ end
38
+ line = "#{key} = #{value}"
39
+ end
40
+ text += line unless ignore_lines
41
+ end
42
+ self.instance_eval(text, filename, 1)
43
+ else
44
+ raise IOError, "Cannot open or read #{filename}!"
45
+ end
46
+ end
47
+
48
+ def ignore_key?(key)
49
+ key =~ /\['cron_jobs'\]/
50
+ end
51
+
52
+ def metadata_attributes
53
+ self.get_attributes(node.default_attrs)
54
+ end
55
+
56
+ def get_attributes(hash, attrs=nil, keys=nil)
57
+ keys ||= []
58
+ attrs ||= {}
59
+ hash.sort.each() do |k, v|
60
+ keys << k.to_s
61
+ if v.is_a? Hash
62
+ self.get_attributes(v, attrs, keys)
63
+ else
64
+ attrs[keys.join("/")] = {:default => parse_value(v)}
65
+ end
66
+ keys.pop
67
+ end
68
+ attrs
69
+ end
70
+
71
+ def parse_value(value)
72
+ if value.is_a? Array
73
+ value
74
+ else
75
+ value.to_s
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,9 @@
1
+ module Fhcap
2
+ module FhcapHelper
3
+
4
+ def cluster_template_names
5
+ Fhcap::TEMPLATE_NAMES
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,235 @@
1
+ require 'thor'
2
+ require 'fhcap/thor_base'
3
+
4
+ require 'pathname'
5
+ require 'yaml'
6
+
7
+ module Fhcap
8
+ module CLI
9
+ class Kitchen < Fhcap::ThorBase
10
+
11
+ TEST_SUITE_NAME='default'
12
+ DEFAULT_INSTANCE='default'
13
+
14
+ add_shared_option :cookbooks, :aliases => "-c", :desc => "Apply to these Cookbooks", :type => :array
15
+ add_shared_option :roles, :aliases => "-r", :desc => "Roles to generate kitchen for", :type => :array
16
+ add_shared_option :driver, :aliases => "-d", :desc => "Kitchen Driver", :type => :string, :default => 'openstack', :enum => %w{aws openstack docker}
17
+ add_shared_option :modified, :aliases => "-m", :desc => "Apply only to modified Cookbooks", :type => :boolean, :required => false, :default => false
18
+ add_shared_option :provisioner, :aliases => "-p", :desc => "Kitchen Provisioner", :type => :string, :default => 'chef_solo', :enum => %w{chef_solo chef_zero}
19
+
20
+
21
+ desc "generate", "Generate"
22
+
23
+ shared_options :cookbooks, :roles, :modified, :driver, :provisioner
24
+ method_option 'only', :type => :array, :default => nil, :desc => "Only include tests for cookbooks matching these names."
25
+ method_option 'exclude', :type => :array, :default => nil, :desc => "Exclude tests for cookbooks matching these names, takes precedence over 'only' option."
26
+ method_option 'clean', :type => :boolean, :default => true, :desc => "Clean the current generated kitchen prior to creating the new one"
27
+
28
+ def generate
29
+ require 'chef'
30
+ cookbooks = get_cookbooks(options, nil, repo_cookbook_paths('-cookbooks'))
31
+ roles = options[:roles] || []
32
+ driver = options[:driver]
33
+ provisioner = options[:provisioner]
34
+ say("Kitchen Generate: Cookbooks = #{cookbooks} : Roles = #{roles}: Driver = #{driver} : Provisioner = #{provisioner}", :yellow)
35
+
36
+ Fhcap::CLI::Kitchen.new.invoke(:clean, [], {}) if is_kitchen_generated? && options[:clean]
37
+ empty_directory test_suite_dir
38
+
39
+ kitchen_config = YAML.load_file(File.join(Fhcap.source_root, "templates", "kitchen", "kitchen.#{driver}.yml.erb"))
40
+ kitchen_config['suites'] = []
41
+ kitchen_config['provisioner']['name'] = provisioner
42
+ kitchen_config['provisioner']['data_bags_path'] = File.join(repo_dir(:fhcap), 'data_bags')
43
+ kitchen_config['provisioner']['environments_path'] = File.join(repo_dir(:fhcap), 'environments')
44
+ kitchen_config['provisioner']['roles_path'] = File.join(repo_dir(:fhcap), 'roles')
45
+
46
+ cookbook_dependencies = {}
47
+
48
+ cookbooks.each do |cookbook|
49
+ meta = cookbook_loader.cookbooks_by_name[cookbook]
50
+ if meta
51
+ cookbook_kitchen_yaml = File.join(meta.root_dir, ".kitchen.yml")
52
+ if File.exists? cookbook_kitchen_yaml
53
+ cookbook_kitchen_config = YAML.load_file(cookbook_kitchen_yaml)
54
+ cookbook_kitchen_config['suites'].each do |suite|
55
+ suite['name'] = "#{suite['name']}_#{cookbook}"
56
+ suite['run_list'].unshift 'recipe[feedhenry_utils::kitchen_docker]' if driver == 'docker'
57
+ suite['run_list'].unshift 'recipe[apt::default]'
58
+ suite['run_list'].unshift 'recipe[chef-solo-search]' if provisioner == 'chef_solo'
59
+ suite['run_list'].unshift 'role[test-kitchen_server]'
60
+ suite['run_list'].uniq!
61
+
62
+ suite_cookbooks = [cookbook] | suite['run_list'].collect do |item|
63
+ recipe_match = /recipe\[(.+?(?=::)|.+?(?=\]))/.match item
64
+ recipe_match ? recipe_match[1] : nil
65
+ end.compact.uniq
66
+
67
+ kitchen_config['suites'] << suite
68
+
69
+ suite_cookbooks.each do |c|
70
+ get_cookbook_deps(c, cookbook_dependencies, {cwd: test_suite_dir})
71
+ end
72
+
73
+ end
74
+ else
75
+ say_status("ERROR", "No test suites found for #{cookbook}", :red)
76
+ end
77
+
78
+ else
79
+ say_status("ERROR", "No cookbook found for #{cookbook}", :red)
80
+ end
81
+ end
82
+
83
+ roles.each do |r|
84
+ role_file = find_role(r)
85
+ if File.exists? role_file
86
+ ::Chef::Config[:role_path] = File.join(repo_dir(:fhcap), 'roles')
87
+ role = ::Chef::Role.from_disk r
88
+ run_list = role.run_list.expand('development')
89
+
90
+ role_cookbooks = run_list.recipes.collect do |recipe|
91
+ recipe.split('::').first
92
+ end.compact.uniq
93
+
94
+ suite = {}
95
+ suite['name'] = "default_#{r}"
96
+ suite['run_list'] = ["role[#{r}]"]
97
+ kitchen_config['suites'] << suite
98
+
99
+ role_cookbooks.each do |c|
100
+ get_cookbook_deps(c, cookbook_dependencies, {cwd: test_suite_dir})
101
+ end
102
+
103
+ link_cookbook_tests(role_cookbooks, options, r)
104
+
105
+ else
106
+ say "Unknown Role #{role_file}"
107
+ end
108
+ end
109
+
110
+ # 1. Create kitchen.yml
111
+ template(File.join("templates", "kitchen", "kitchen.generate.yml.erb"), test_suite_kitchen_yml, :kitchen_yaml => kitchen_config.to_yaml, :force => true)
112
+
113
+ #2. Create Cheffile
114
+ template(File.join("templates", "kitchen", "Cheffile.erb"), File.join(test_suite_dir, "Cheffile"), :cookbooks => cookbook_dependencies.to_h, :name => "Combined Cheffile for #{cookbooks}", :force => true)
115
+
116
+ #3. Configure tests
117
+ link_cookbook_tests(cookbooks, options)
118
+ end
119
+
120
+ desc "clean", "Clean"
121
+
122
+ def clean
123
+ say("Clean Test Suite", :yellow)
124
+ Fhcap::CLI::Kitchen.new.invoke(:destroy, ['all'], {}) if is_kitchen_generated?
125
+ remove_file test_suite_dir
126
+ end
127
+
128
+ %w{create converge setup verify test list login destroy diagnose}.each do |cmd|
129
+
130
+ desc "#{cmd} [INSTANCE|REGEXP|all]", "Run '#{cmd}' command against current kitchen instances."
131
+ shared_options :cookbooks, :roles, :modified, :driver, :provisioner if %w{create converge setup verify test}.include? cmd
132
+
133
+ define_method(cmd) do |instance='all'|
134
+ Fhcap::CLI::Kitchen.new.invoke(:generate, [], options) if options[:cookbooks] || options[:modified] || options[:roles]
135
+ if is_kitchen_generated?
136
+ Dir.chdir test_suite_dir do
137
+ cmd_options = options.dup
138
+ cmd_options['instance'] = instance
139
+ cmd_options['kitchen-yaml'] = test_suite_kitchen_yml
140
+ cmd_options['kitchen-options'] = '--concurrency=10'
141
+ run_kitchen_cmd(cmd, cmd_options)
142
+ end
143
+ else
144
+ say "Please generate a test kitchen first! i.e fhcap kitchen generate -c <cookbooks>", :yellow
145
+ end
146
+ end
147
+
148
+ end
149
+
150
+ protected
151
+
152
+ def test_suite_dir
153
+ File.join(config.default_dir, 'tmp', 'kitchen')
154
+ end
155
+
156
+ def test_suite_kitchen_yml
157
+ File.join(test_suite_dir, 'kitchen.yml')
158
+ end
159
+
160
+ def is_kitchen_generated?
161
+ File.exists? test_suite_kitchen_yml
162
+ end
163
+
164
+ def include_cookbook_tests?(cookbook, options)
165
+ if options['exclude']
166
+ !options['exclude'].include?(cookbook)
167
+ elsif options['only']
168
+ options['only'].include?(cookbook)
169
+ else
170
+ true
171
+ end
172
+ end
173
+
174
+ def link_cookbook_tests(cookbooks, options, role=nil)
175
+ tests_parent_dir = File.join(test_suite_dir, 'test', 'integration')
176
+ test_helpers_dir = File.join(repo_dir(:fhcap), 'test', 'helpers')
177
+
178
+ cookbooks.each do |cookbook|
179
+ if include_cookbook_tests?(cookbook, options)
180
+ meta = cookbook_loader.cookbooks_by_name[cookbook]
181
+ cookbook_dir = File.dirname(meta.root_filenames.first)
182
+ cookbook_test_suite_dir = File.join(cookbook_dir, '/test/integration')
183
+
184
+ if Dir.exists? cookbook_test_suite_dir
185
+ Dir.entries(cookbook_test_suite_dir).select { |f| !File.directory? f }.each() do |test_suite|
186
+
187
+ cookbook_test_dir = File.join(cookbook_test_suite_dir, test_suite)
188
+ Dir.entries(cookbook_test_dir).select { |f| !File.directory? f }.each() do |test_type|
189
+ tests_dir = File.join(tests_parent_dir, "#{test_suite}_#{role || cookbook}")
190
+
191
+ test_type_dir = "#{tests_dir}/#{test_type}"
192
+ empty_directory test_type_dir
193
+
194
+ if Dir.exists? "#{test_helpers_dir}/#{test_type}"
195
+ FileUtils.cp_r(Dir["#{test_helpers_dir}/#{test_type}/*"], test_type_dir)
196
+ end
197
+
198
+ Dir.chdir("#{cookbook_test_dir}/#{test_type}") do
199
+ Dir["*_spec.rb"].each do |test|
200
+ link_src = "#{cookbook_test_dir}/#{test_type}/#{test}"
201
+ link_dest = "#{test_type_dir}/#{cookbook}_#{test}"
202
+ create_link link_dest, link_src
203
+ end
204
+ end
205
+ end
206
+ end
207
+ else
208
+ say_status("warning", "No tests suites found for #{cookbook}", :yellow)
209
+ end
210
+ else
211
+ say_status("exclude", "Excluding tests for #{cookbook}", :yellow)
212
+ end
213
+ end
214
+ end
215
+
216
+ def _get_config(options)
217
+ opts = []
218
+ opts << "KITCHEN_YAML=#{options['kitchen-yaml']}" if options['kitchen-yaml']
219
+ opts.join(' ')
220
+ end
221
+
222
+ def run_kitchen_cmd(cmd, options)
223
+ suite = options['instance'] || DEFAULT_INSTANCE
224
+ kitchen_cmd_options = [options['kitchen-options']] || []
225
+ cmd = ([_get_config(options), 'kitchen', cmd, suite] + kitchen_cmd_options).join(' ')
226
+ run_cmd(cmd, options)
227
+ end
228
+
229
+ def run_cmd(cmd, options)
230
+ run(cmd)
231
+ end
232
+
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,74 @@
1
+ require 'thor'
2
+ require 'fhcap/thor_base'
3
+
4
+ module Fhcap
5
+ module CLI
6
+ class Knife < Fhcap::ThorBase
7
+
8
+ add_shared_option :verbose, :aliases => "-v", :desc => "Verbose output", :type => :boolean, :required => false, :default => false
9
+ add_shared_option :name, :type => :string, :required => true, :desc => "Chef Server name i.e. bob"
10
+ add_shared_option :interactive, :aliases => "-i", :desc => "Interactive mode (Stops for input)", :type => :boolean, :required => false, :default => false
11
+
12
+ desc "add", "Add a chef server"
13
+
14
+ shared_options :verbose, :name, :interactive
15
+ method_option 'url', :type => :string, :required => false, :desc => "Chef Server url i.e. https://bob.feedhenry.net:8443"
16
+ method_option 'node-name', :type => :string, :desc => "Node name, defaults to current users ID i.e. echo $USER"
17
+ method_option 'validation-client-name', :type => :string, :desc => "Validation client name, defaults to 'chef-validator'"
18
+ method_option 'import-file', :type => :string, :desc => "Path to import file"
19
+ long_desc <<-LONGDESC
20
+ Add a chef server to your local fhcap configuration.
21
+
22
+ With --import-file option, if an admin sent you an import-file you can pass this in here and all config, keys etc.. will be created for you
23
+ LONGDESC
24
+
25
+ def add
26
+ require "fhcap/tasks/knife/add"
27
+ Tasks::Knife::Add.new(task_options(options.dup)).run
28
+ end
29
+
30
+ desc "remove", "Remove a chef server"
31
+
32
+ shared_options :verbose, :name
33
+
34
+ def remove
35
+ require "fhcap/tasks/knife/remove"
36
+ Tasks::Knife::Remove.new(task_options(options.dup)).run
37
+ end
38
+
39
+ desc "list", "List configured chef servers"
40
+
41
+ def list
42
+ require "fhcap/tasks/knife/list"
43
+ Tasks::Knife::List.new(task_options(options.dup)).run
44
+ end
45
+
46
+ desc "create_user", "Create a new user on a given chef server."
47
+ long_desc <<-LONGDESC
48
+ Create a new user on a given chef server.
49
+
50
+ To create users on a chef server the user running this command must have the appropriate permissions to do so i.e. admin
51
+
52
+ By default an import-file is generated that can be sent to the new user to make there local setup easier by passing it directly into the add command
53
+
54
+ i.e. fhcap knife add --name <NAME> --import-file <IMPORT_FILE>
55
+ LONGDESC
56
+
57
+ shared_options :verbose, :interactive
58
+ method_option 'chef-server', :type => :string, :desc => "Chef Server", :required => false, :enum => chef_server_names
59
+ method_option :username, :type => :string, :desc => "Username", :required => true
60
+ method_option 'display-name', :type => :string, :desc => "Display Name", :required => false
61
+ method_option 'first-name', :type => :string, :desc => "First Name", :required => false
62
+ method_option 'last-name', :type => :string, :desc => "Last Name", :required => false
63
+ method_option :email, :type => :string, :desc => "Email", :required => false
64
+ method_option :password, :type => :string, :desc => "Password", :required => false
65
+
66
+ def create_user
67
+ require "fhcap/tasks/chef/server/create_user"
68
+ Tasks::Chef::Server::CreateUser.new(task_options(options.dup)).run
69
+
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,38 @@
1
+ require 'chef/config'
2
+
3
+ module Fhcap
4
+ module KnifeHelper
5
+
6
+ def knife_config
7
+ config.exists? && config[:knife] ? config[:knife] : {}
8
+ end
9
+
10
+ def knife_config_dir
11
+ config[:knife_dir] || File.join(config.default_dir, '.chef')
12
+ end
13
+
14
+ def knife_config_file_for(name)
15
+ File.join(knife_config_dir, "knife-#{name}.rb")
16
+ end
17
+
18
+ def chef_server_names
19
+ knife_config.collect do |server_name, cfg|
20
+ server_name.to_s
21
+ end
22
+ end
23
+
24
+ def chef_server_config_for(name)
25
+ Chef::Config.from_file(knife_config_file_for(name))
26
+ end
27
+
28
+ def chef_server_config_hash_for(name)
29
+ chef_server_config_for(name)
30
+ chef_server_config = {
31
+ chef_server_url: Chef::Config[:chef_server_url],
32
+ node_name: Chef::Config[:node_name],
33
+ client_key: Chef::Config[:client_key],
34
+ }
35
+ end
36
+
37
+ end
38
+ end
data/lib/fhcap/misc.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'thor'
2
+ require 'fhcap/thor_base'
3
+
4
+ module Fhcap
5
+ module CLI
6
+ class Misc < Fhcap::ThorBase
7
+
8
+ add_shared_option :verbose, :aliases => "-v", :desc => "Verbose output", :type => :boolean, :required => false, :default => false
9
+
10
+ desc "create_ssl_cert", "Create an SSL Cert"
11
+
12
+ shared_options :verbose
13
+
14
+ method_option 'name', :type => :string, :required => true, :desc => "SSL Cert name"
15
+ method_option 'domain', :type => :string, :required => true, :desc => "SSL Cert Domain i.e. *.feedhenry.me"
16
+ method_option 'directory', :type => :string, :required => true, :desc => "Destination directory"
17
+ method_option 'format', :type => :string, :required => true, :default => 'pem', :desc => "Format to save cert in", :enum => %w{pem json}
18
+
19
+ def create_ssl_cert
20
+ require "fhcap/tasks/misc/create_ssl_cert"
21
+ Tasks::Misc::CreateSslCert.new(task_options(options.dup)).run
22
+ end
23
+
24
+ desc "create_chef_environment", "Create a Chef Environment"
25
+
26
+ shared_options :verbose
27
+
28
+ method_option 'name', :type => :string, :required => true, :desc => 'Environment name'
29
+ method_option 'type', :type => :string, :required => true, :enum => %w{core mbaas}, :desc => 'Environment type'
30
+ method_option 'domain', :type => :string, :required => true, :desc => 'Environment domain'
31
+ method_option 'repo', :type => :string, :required => true, :desc => "Fhcap Repo where environment should be saved", :enum => repo_names
32
+
33
+ def create_chef_environment
34
+ require "fhcap/tasks/chef/environments/create"
35
+ Tasks::Chef::Environments::Create.new(task_options(options.dup)).run
36
+ end
37
+
38
+ desc "destroy_chef_environment", "Create a Chef Environment"
39
+
40
+ shared_options :verbose
41
+
42
+ method_option 'name', :type => :string, :required => true, :desc => 'Environment name'
43
+
44
+ def destroy_chef_environment
45
+ require "fhcap/tasks/chef/environments/destroy"
46
+ Tasks::Chef::Environments::Destroy.new(task_options(options.dup)).run
47
+ end
48
+
49
+ desc "chef_provision", "Run a chef provisioning task against a particular cluster"
50
+
51
+ shared_options :verbose
52
+
53
+ method_option 'name', :type => :string, :required => true, :desc => 'Cluster name'
54
+ method_option 'run-list', :type => :array, :required => true, :desc => 'Chef Provisioning Run List i.e provision::cluster_provision'
55
+
56
+ def chef_provision
57
+ require 'fhcap/tasks/chef/provisioning/chef_provisioning_task'
58
+ Tasks::Chef::Provisioning::ChefProvisioningTask.new(task_options(options.dup)).run
59
+ end
60
+
61
+ desc "create_cluster_environment", "Add an environment to a cluster"
62
+
63
+ shared_options :verbose
64
+
65
+ method_option 'name', :type => :string, :required => true, :desc => 'Cluster name'
66
+ method_option 'environment-name', :type => :string, :required => true, :desc => 'Environment name'
67
+ method_option 'domain', :type => :string, :required => true, :desc => 'Environment domain'
68
+ method_option 'template', :type => :string, :required => true, :desc => 'Environment template'
69
+
70
+ def create_cluster_environment
71
+ require "fhcap/tasks/cluster/create_environment"
72
+ Tasks::Cluster::CreateEnvironment.new(task_options(options.dup)).run
73
+ end
74
+
75
+ desc "destroy_cluster_environment", "Add an environment to a cluster"
76
+
77
+ shared_options :verbose
78
+
79
+ method_option 'name', :type => :string, :required => true, :desc => 'Cluster name'
80
+ method_option 'environment-name', :type => :string, :required => true, :desc => 'Environment name'
81
+
82
+ def destroy_cluster_environment
83
+ require "fhcap/tasks/cluster/destroy_environment"
84
+ Tasks::Cluster::DestroyEnvironment.new(task_options(options.dup)).run
85
+ end
86
+
87
+ desc "create_dns_record", "Create a new DNS Record"
88
+
89
+ shared_options :verbose
90
+
91
+ method_option 'domain', :type => :string, :required => true, :desc => 'Domain'
92
+ method_option 'ipaddress', :type => :string, :desc => 'IP Address'
93
+ method_option 'alias-target', :type => :hash, :desc => 'Alias Target'
94
+ method_option 'ttl', :type => :numeric, :default => 300, :desc => 'Time To Live'
95
+
96
+ def create_dns_record
97
+ require "fhcap/tasks/misc/create_dns_record"
98
+ Tasks::Misc::CreateDNSRecord.new(task_options(options.dup)).run
99
+ end
100
+
101
+ end
102
+ end
103
+ end