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,30 @@
1
+ require 'fhcap/tasks/cluster/cluster_task_base'
2
+ require 'fhcap/tasks/chef/provisioning/destroy'
3
+ require 'fhcap/tasks/chef/environments/destroy'
4
+
5
+ module Fhcap
6
+ module Tasks
7
+ module Cluster
8
+ class Destroy < ClusterTaskBase
9
+
10
+ def initialize(options)
11
+ super(options, false)
12
+ @skip_destroy = options[:'skip-destroy']
13
+ end
14
+
15
+ def run
16
+ thor.say "Cluster::Destroy: name = #{@name}", :yellow
17
+ Chef::Provisioning::Destroy.new(options).run unless @skip_destroy
18
+
19
+ if thor.yes? "Delete all local repo files?"
20
+ cluster_environments.each do |env_name, cfg|
21
+ Chef::Environments::Destroy.new(@options.dup.merge({:name => env_name, :chef_server => @cluster_config[:chef_server], :repo => @cluster_config[:repo]})).run
22
+ end
23
+ thor.remove_file find_cluster(@name)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ require 'fhcap/tasks/cluster/cluster_task_base'
2
+ require 'fhcap/tasks/chef/environments/destroy'
3
+
4
+ module Fhcap
5
+ module Tasks
6
+ module Cluster
7
+ class DestroyEnvironment < ClusterTaskBase
8
+
9
+ attr_reader :environment_name, :domain, :environment_config
10
+
11
+ def initialize(options)
12
+ super(options)
13
+ @environment_name = options[:'environment-name']
14
+ end
15
+
16
+ def run
17
+ thor.say "Cluster::DestroyEnvironment: cluster = #{name}, environment = #{environment_name}", :yellow
18
+
19
+ cluster_config[:environments].delete environment_name.to_sym
20
+ thor.create_file(cluster_file, JSON.pretty_generate(cluster_config), force: true)
21
+
22
+ Chef::Environments::Destroy.new(@options.dup.merge({:name => environment_name, :chef_server => cluster_config[:chef_server]})).run
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,67 @@
1
+ require 'fhcap/tasks/cluster/cluster_task_base'
2
+ require 'fhcap/tasks/chef/server/info'
3
+ require 'launchy'
4
+
5
+ module Fhcap
6
+ module Tasks
7
+ module Cluster
8
+ class Info < ClusterTaskBase
9
+
10
+ attr_reader :launch, :cluster_pwds_file, :cluster_passwords
11
+
12
+ def initialize(options)
13
+ super
14
+ @launch = options[:launch]
15
+ unless @cluster_passwords
16
+ @cluster_passwords = {}
17
+ cluster_environments.each do |env|
18
+ @cluster_passwords[env.to_sym] = {}
19
+ @cluster_pwds_file = find_cluster_pwds(env)
20
+ if @cluster_pwds_file
21
+ @cluster_passwords[env.to_sym] = JSON.parse(IO.read(@cluster_pwds_file), {:symbolize_names => true})
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def run
28
+ thor.say "Cluster::Info: name = #{@name}", :yellow
29
+ info_task = Chef::Server::Info.new(@options.dup.merge({:environments => cluster_environments, :chef_server => cluster_config[:chef_server]}))
30
+ info_task.run
31
+ cluster_environments.each do |env|
32
+ passwords(env) unless options[:only] && options[:only] != 'passwords'
33
+ end
34
+
35
+ if launch
36
+ info_task.urls.each do |env, urls|
37
+ urls.each do |service, url|
38
+ service = service.to_s
39
+ if %w{nagios munin}.include? service
40
+ user = 'team.eng'
41
+ pwd = cluster_passwords[env.to_sym][:'henry_users.teameng']
42
+ if user and pwd
43
+ proto, host = url.split('://')
44
+ url = "#{proto}://#{user}:#{pwd}@#{host}"
45
+ end
46
+ end
47
+ thor.say_status 'launch', url
48
+ Launchy.open(url)
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ private
56
+
57
+ def passwords(env)
58
+ thor.say "[#{env}] Passwords", :green
59
+ cluster_passwords[env.to_sym].each do |user, pwd|
60
+ thor.say_status "[#{env}] #{user}:", "#{pwd}", :cyan
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,40 @@
1
+ require 'fhcap/tasks/task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Cluster
6
+ class List < TaskBase
7
+
8
+ def run
9
+ thor.say "Cluster::List", :yellow
10
+
11
+ table_contents = [table_header('Name', 'Repo', 'Template', 'Driver', 'Chef Server', 'Provider ID', 'Environments', 'Domains', 'No. Instances')]
12
+
13
+ repos_config.each do |repo_name, cfg|
14
+ clusters_dir = File.join(repo_dir(repo_name), repo_clusters_dir(repo_name))
15
+ if Dir.exists?(clusters_dir)
16
+ Dir.glob("#{clusters_dir}/*.json").reject { |f| f =~ /passwords/ }.each do |json_file|
17
+ conf = JSON.parse(IO.read(json_file), {:symbolize_names => true})
18
+ environments = {}
19
+ if conf[:environments]
20
+ conf[:environments].each do |env_name, env_cfg|
21
+ env_name = [conf[:id].to_s, env_name.to_s].uniq.join('-')
22
+ environments[env_name] = {}
23
+ environments[env_name][:domain] = env_cfg[:domain]
24
+ environments[env_name][:instances] = (env_cfg[:instances] || {}).keys.collect { |e| "#{env_name}-#{e}" }
25
+ end
26
+ end
27
+ environment_names = environments.keys.join(',')
28
+ domain_names = environments.values.collect { |env| env[:domain] }.compact.join(',')
29
+ instance_names = environments.values.collect { |env| env[:instances] }.flatten
30
+ table_contents << table_row(conf[:id], conf[:repo], conf[:template], conf[:driver], conf[:chef_server], conf[:provider_id], environment_names, domain_names, instance_names.count)
31
+ end
32
+ end
33
+ end
34
+ thor.print_table table_contents
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ require 'fhcap/tasks/cluster/cluster_task_base'
2
+ require 'fhcap/tasks/chef/server/bootstrap'
3
+ require 'fhcap/tasks/chef/server/provision'
4
+ require 'fhcap/tasks/chef/provisioning/provision'
5
+ require 'fhcap/tasks/chef/environments/promote_cookbooks'
6
+ require 'fhcap/tasks/repo/checkout'
7
+
8
+ module Fhcap
9
+ module Tasks
10
+ module Cluster
11
+ class Provision < ClusterTaskBase
12
+
13
+ attr_reader :gitref, :strategy, :node_names, :roles
14
+
15
+ def initialize(options)
16
+ super
17
+ @gitref = options[:"git-ref"]
18
+ @node_names = options[:nodes]
19
+ @roles = options[:roles]
20
+ @skip_repo_checkout = options[:'skip-repo-checkout']
21
+ @skip_cookbook_promote = options[:'skip-cookbook-promote']
22
+ @skip_server_bootstrap = options[:'skip-server-bootstrap']
23
+ @skip_provision = options[:'skip-provision']
24
+ @strategy = ('knife' unless provider_names.include?(@cluster_config[:provider_id])) || options[:strategy]
25
+ end
26
+
27
+ def run
28
+ thor.say "Cluster::Provision: name = #{name}, strategy = #{strategy}", :yellow
29
+ checkout_repos unless @skip_repo_checkout
30
+ Chef::Environments::PromoteCookbooks.new(@options.dup.merge({:environments => cluster_environments})).run unless @skip_cookbook_promote
31
+ Chef::Server::Bootstrap.new(@options.dup.merge({:environments => cluster_environments, :chef_server => cluster_config[:chef_server]})).run unless @skip_server_bootstrap
32
+ unless @skip_provision
33
+ if strategy == 'chef'
34
+ Chef::Provisioning::Provision.new(@options).run
35
+ elsif strategy == 'knife'
36
+ Chef::Server::Provision.new(@options.dup.merge({:environments => cluster_environments, :chef_server => cluster_config[:chef_server]})).run
37
+ else
38
+ thor.say_status :error, "Unsupported provision strategy #{strategy}"
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ require 'fhcap/tasks/cluster/cluster_task_base'
2
+ require 'fhcap/tasks/chef/provisioning/chef_provisioning_task'
3
+
4
+ module Fhcap
5
+ module Tasks
6
+ module Cluster
7
+ class Status < ClusterTaskBase
8
+
9
+ def run
10
+ thor.say "Cluster::Status: name = #{@name}", :yellow
11
+ Tasks::Chef::Provisioning::ChefProvisioningTask.new(@options.dup.merge({:'run-list' => 'recipe[provision::cluster_status]'})).run
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ require 'fhcap/tasks/cluster/cluster_task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Cluster
6
+ class Test < ClusterTaskBase
7
+
8
+ def run
9
+ thor.say "Cluster::Test: name = #{@name}", :yellow
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,111 @@
1
+ require 'fhcap/tasks/task_base'
2
+ require 'etc'
3
+ require 'chef/config'
4
+
5
+ module Fhcap
6
+ module Tasks
7
+ module Knife
8
+ class Add < TaskBase
9
+
10
+ attr_reader :name, :private_key, :validation_key, :import_file, :knife_config
11
+
12
+ def initialize(options)
13
+ super
14
+ @name = options[:name]
15
+ @chef_server_url = options[:url]
16
+ @node_name = options[:'node-name'] || Etc.getlogin
17
+ @validation_client_name = options[:'validation-client-name'] || 'chef-validator'
18
+ @import_file = options[:'import-file']
19
+ @private_key = nil
20
+ @validation_key = nil
21
+
22
+ if @import_file
23
+ import_cfg = JSON.parse(IO.read(@import_file), {:symbolize_names => true})
24
+ @name = import_cfg[:name] || @name
25
+ @chef_server_url = import_cfg[:chef_server_url]
26
+ @node_name = import_cfg[:node_name]
27
+ @validation_client_name = import_cfg[:validation_client_name]
28
+ @private_key = import_cfg[:private_key]
29
+ @validation_key = import_cfg[:validation_key]
30
+ end
31
+
32
+ @knife_config = config[:knife][@name.to_sym] || {}
33
+ @knife_config = {
34
+ chef_server_url: @chef_server_url,
35
+ node_name: @node_name,
36
+ validation_client_name: @validation_client_name,
37
+ }.merge(@knife_config)
38
+
39
+ end
40
+
41
+ def run
42
+ thor.say "Knife::Add: name = #{name}", :yellow
43
+
44
+ ask_config(required_config, @knife_config)
45
+
46
+ config[:knife][name.to_sym] = @knife_config
47
+
48
+ thor.create_file(config.default_config_file, JSON.pretty_generate(config.data), :force => true)
49
+ config.reload
50
+ create_knife_config
51
+ end
52
+
53
+ private
54
+
55
+ def required_config
56
+ {
57
+ chef_server_url: {
58
+ },
59
+ node_name: {
60
+ },
61
+ validation_client_name: {
62
+ }
63
+ }
64
+ end
65
+
66
+ def create_knife_config
67
+ knife_config_file = File.join(config.knife_dir, "knife-#{name}.rb")
68
+ cookbook_path = repo_cookbook_paths
69
+ cookbook_path << File.join(Fhcap.source_root, 'lib', 'cookbooks')
70
+
71
+ thor.template(File.join("templates", "init", "knife.rb.erb"), knife_config_file,
72
+ :name => name,
73
+ :validation_client_name => knife_config[:validation_client_name],
74
+ :chef_server_url => knife_config[:chef_server_url],
75
+ :node_name => knife_config[:node_name],
76
+ :cookbook_path => cookbook_path
77
+ )
78
+
79
+ thor.empty_directory File.join(knife_config_dir, name)
80
+ thor.empty_directory File.join(knife_config_dir, 'keys')
81
+
82
+ thor.create_file(File.join(knife_config_dir, name, "#{knife_config[:node_name]}.pem"), private_key, :force => true) if private_key
83
+ thor.create_file(File.join(knife_config_dir, name, "#{knife_config[:validation_client_name]}.pem"), private_key, :force => true) if validation_key
84
+
85
+ validate_knife_config(knife_config_file)
86
+
87
+ unless File.exists? File.join(knife_config_dir, "knife.rb")
88
+ thor.create_link File.join(knife_config_dir, "knife.rb"), knife_config_file
89
+ end
90
+
91
+ end
92
+
93
+ def validate_knife_config(knife_config_file)
94
+ if File.exists? knife_config_file
95
+ Chef::Config.from_file(knife_config_file)
96
+ unless File.exists? Chef::Config[:validation_key]
97
+ thor.say_status 'missing', Chef::Config[:validation_key], :red
98
+ end
99
+
100
+ unless File.exists? Chef::Config[:client_key]
101
+ thor.say_status 'missing', Chef::Config[:client_key], :red
102
+ end
103
+ else
104
+ thor.say_status 'missing', knife_config_file, :red
105
+ end
106
+ end
107
+
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,22 @@
1
+ require 'fhcap/tasks/task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Knife
6
+ class List < TaskBase
7
+
8
+ def run
9
+ thor.say "Knife::List", :yellow
10
+
11
+ table_contents = [table_header('ID', 'Chef Server Url', 'Node Name')]
12
+
13
+ knife_config.each do |id, cfg|
14
+ table_contents << table_row(id, cfg[:chef_server_url], cfg[:node_name])
15
+ end
16
+ thor.print_table table_contents
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ require 'fhcap/tasks/task_base'
2
+
3
+ module Fhcap
4
+ module Tasks
5
+ module Knife
6
+ class Remove < TaskBase
7
+
8
+ attr_reader :name
9
+
10
+ def initialize(options)
11
+ super
12
+ @name = options[:name]
13
+ end
14
+
15
+ def run
16
+ thor.say "Knife::Remove: name = #{name}", :yellow
17
+ if thor.yes? "Remove knife #{name}? (y/n)"
18
+ config[:knife].delete(name.to_sym)
19
+ thor.create_file(config.default_config_file, JSON.pretty_generate(config.data), :force => true)
20
+ config.reload
21
+ if thor.yes?("Remove local knife config? (y/n)")
22
+ remove_knife_config
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def remove_knife_config
30
+ knife_config_dir = config[:knife_dir] || File.join(config.default_dir, '.chef')
31
+ knife_config_file = File.join(knife_config_dir, "knife-#{name}.rb")
32
+ thor.remove_file knife_config_file
33
+ thor.remove_file File.join(knife_config_dir, name)
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,100 @@
1
+ require 'fhcap/tasks/task_base'
2
+ require 'aws-sdk'
3
+ require 'public_suffix'
4
+
5
+ # fhcap misc create_dns_record --domain *.test.skunkhenry.com --ipaddress 192.168.33.10
6
+ # fhcap misc create_dns_record --domain *.test2.skunkhenry.com --alias-target dns_name:fh-lb-eng2-core-studio-584044547.eu-central-1.elb.amazonaws.com hosted_zone_id:Z215JYRZR1TBD5
7
+
8
+ module Fhcap
9
+ module Tasks
10
+ module Misc
11
+ class CreateDNSRecord < TaskBase
12
+
13
+ attr_reader :domain, :ipaddress, :alias_target, :ttl
14
+
15
+ def initialize(options)
16
+ super
17
+ @domain = options[:domain]
18
+ @alias_target = options[:'alias-target']
19
+ @ipaddress = options[:ipaddress]
20
+ @ttl = options[:ttl] || 300
21
+ end
22
+
23
+ def run
24
+ thor.say "CreateDNSRecord: name = #{domain}, ipaddress = #{ipaddress}, ttl = #{ttl}", :yellow
25
+
26
+ host_domain = PublicSuffix.parse(domain).domain
27
+ provider = provider_for(host_domain)
28
+
29
+ if provider
30
+ begin
31
+ cfg = provider_config(provider)
32
+ region = provider_regions(provider).keys.first
33
+ creds = cfg[:credentials]
34
+ client = Aws::Route53::Client.new(
35
+ region: region,
36
+ access_key_id: creds[:'aws-access-key'],
37
+ secret_access_key: creds[:'aws-secret-key']
38
+ )
39
+ resp = client.list_hosted_zones
40
+ zone = resp.hosted_zones.reject { |z| !(z.name =~ /#{host_domain}/) }.first
41
+
42
+ if zone
43
+ thor.say "Found zone id: #{zone.id}, name: #{zone.name}"
44
+ resp = client.list_resource_record_sets({
45
+ hosted_zone_id: zone.id,
46
+ start_record_name: domain,
47
+ start_record_type: "A",
48
+ max_items: 1
49
+ })
50
+ record_set = resp.resource_record_sets.reject { |z| !(z.name =~ /^#{domain}/) }.first
51
+ if record_set
52
+ thor.say "Found existing record set, id: name: #{record_set.name}, type: #{record_set.type}, record_set: #{record_set.resource_records || 'None'}, alias_target: #{record_set.alias_target || 'None'}\n"
53
+ else
54
+ change_request = {
55
+ :action => 'CREATE',
56
+ :resource_record_set => {
57
+ :name => domain,
58
+ :type => "A"
59
+ }
60
+ }
61
+
62
+ if @alias_target
63
+ change_request[:resource_record_set].merge!(
64
+ {
65
+ alias_target: {
66
+ evaluate_target_health: false
67
+ }.merge!(@alias_target)
68
+ }
69
+ )
70
+ else
71
+ change_request[:resource_record_set].merge!(
72
+ {
73
+ :ttl => ttl,
74
+ :resource_records => [{:value => ipaddress}]
75
+ }
76
+ )
77
+ end
78
+
79
+ client.change_resource_record_sets({
80
+ :hosted_zone_id => zone.id,
81
+ :change_batch => {
82
+ :changes => [change_request]
83
+ }
84
+ })
85
+ end
86
+ else
87
+ thor.say_status 'error', "Can't get hosted zone for '#{host_domain}'", :red
88
+ end
89
+ rescue Aws::Route53::Errors::ServiceError => e
90
+ thor.say_status 'error', e.message, :red
91
+ end
92
+ else
93
+ thor.say_status 'error', "No DNS provider configured for '#{domain}'", :red
94
+ end
95
+ end
96
+
97
+ end
98
+ end
99
+ end
100
+ end