fhcap-cli 0.4.5 → 0.4.6
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +6 -0
- data/README.md +1 -1
- data/fhcap-cli.gemspec +2 -1
- data/lib/cookbooks/provision/libraries/provision.rb +26 -11
- data/lib/cookbooks/provision/recipes/aws_cluster_create.rb +7 -0
- data/lib/cookbooks/provision/recipes/aws_cluster_create_elb.rb +6 -1
- data/lib/cookbooks/provision/recipes/aws_cluster_destroy.rb +17 -16
- data/lib/cookbooks/provision/recipes/cluster_bootstrap.rb +4 -0
- data/lib/cookbooks/provision/recipes/cluster_bootstrap_instances.rb +37 -0
- data/lib/cookbooks/provision/recipes/cluster_create_instances.rb +11 -9
- data/lib/cookbooks/provision/recipes/cluster_provision_instances.rb +12 -11
- data/lib/cookbooks/provision/recipes/galera_reset_cluster.rb +40 -36
- data/lib/cookbooks/provision/recipes/mongo_reset_cluster.rb +10 -9
- data/lib/cookbooks/provision/recipes/rabbitmq_reset_cluster.rb +3 -1
- data/lib/extensions/chef/solr/query/regexpable_query.rb +17 -0
- data/lib/fhcap/chef-dk/chef_runner.rb +4 -1
- data/lib/fhcap/cluster.rb +66 -14
- data/lib/fhcap/cookbook.rb +1 -0
- data/lib/fhcap/kitchen.rb +27 -4
- data/lib/fhcap/provider.rb +1 -1
- data/lib/fhcap/repos_helper.rb +1 -1
- data/lib/fhcap/tasks/chef/chef_task_base.rb +3 -1
- data/lib/fhcap/tasks/chef/chef_zero_server.rb +1 -0
- data/lib/fhcap/tasks/chef/cookbook/update_version.rb +1 -2
- data/lib/fhcap/tasks/chef/provisioning/chef_provisioning_task_base.rb +19 -4
- data/lib/fhcap/tasks/chef/provisioning/create.rb +6 -3
- data/lib/fhcap/tasks/cluster/cluster_task_base.rb +1 -0
- data/lib/fhcap/tasks/cluster/create.rb +4 -201
- data/lib/fhcap/tasks/cluster/create_dns_records.rb +108 -0
- data/lib/fhcap/tasks/cluster/create_environment.rb +1 -0
- data/lib/fhcap/tasks/cluster/generate.rb +135 -0
- data/lib/fhcap/tasks/provider/add.rb +11 -0
- data/lib/fhcap/version.rb +1 -1
- data/spec/fhcap/tasks/cluster/create_dns_records_spec.rb +64 -0
- data/spec/fhcap/tasks/cluster/create_spec.rb +34 -13
- data/spec/fhcap/tasks/cluster/generate_spec.rb +44 -0
- data/templates/chef/environment_core.json.erb +8 -3
- data/templates/chef/environment_farm.json.erb +5 -0
- data/templates/chef/environment_mbaas.json.erb +11 -2
- data/templates/chef/environment_single.json.erb +17 -8
- data/templates/cluster/aws/common.json.erb +1 -1
- data/templates/cluster/aws/core-3node.json.erb +14 -2
- data/templates/cluster/aws/core-small-9node.json.erb +13 -1
- data/templates/cluster/aws/mbaas-3node.json.erb +14 -2
- data/templates/cluster/aws/single-blank.json.erb +6 -0
- data/templates/cluster/aws/single.json.erb +13 -1
- data/templates/cluster/openstack/core-3node.json.erb +1 -1
- data/templates/kitchen/kitchen.docker.yml.erb +0 -3
- data/templates/kitchen/kitchen.generate.yml.erb +0 -1
- data/templates/kitchen/kitchen.vagrant.yml.erb +37 -0
- metadata +29 -5
data/lib/fhcap/cluster.rb
CHANGED
@@ -8,34 +8,70 @@ module Fhcap
|
|
8
8
|
add_shared_option :verbose, :aliases => "-v", :desc => "Verbose output", :type => :boolean, :required => false, :default => false
|
9
9
|
add_shared_option :name, :type => :string, :required => true, :desc => "Cluster name"
|
10
10
|
add_shared_option :interactive, :aliases => "-i", :desc => "Interactive mode (Stops for input)", :type => :boolean, :required => false, :default => false
|
11
|
+
add_shared_option :'dry-run', :desc => "Dry Run only, nothing will be modified, but instead will display things that would be changed if this command was executed.", :type => :boolean, :required => false, :default => false
|
12
|
+
add_shared_option :'run-options', :type => :hash, :required => false, :desc => 'Run specific options, will be set as attributes on the node during the chef provisioning run!'
|
13
|
+
|
14
|
+
#Generate options
|
15
|
+
add_shared_option :template, :type => :string, :desc => "Cluster template i.e. [1, 3 , 5 node cluster setup, core or mbaas]", :enum => cluster_template_names
|
16
|
+
add_shared_option :domain, :type => :string, :desc => "host names to register with DNS / base host name"
|
17
|
+
add_shared_option :'ssl-cert', :type => :string, :desc => "ssl cert to use"
|
18
|
+
add_shared_option :'dns-provider-id', :type => :string, :desc => "DNS Provider Id"
|
19
|
+
add_shared_option :'repo', :type => :string, :desc => "Fhcap Repo where all config should be saved", :enum => repo_names
|
20
|
+
add_shared_option :'chef-server', :type => :string, :desc => "Chef Server to use", :enum => chef_server_names
|
21
|
+
add_shared_option :'provider-id', :type => :string, :desc => "Provider Id", :enum => provider_names_for('compute')
|
22
|
+
add_shared_option :'provider-config', :type => :hash, :desc => "Provider specific config"
|
23
|
+
|
24
|
+
desc "generate", "Generate/Update cluster configuration"
|
25
|
+
long_desc <<-LONGDESC
|
26
|
+
Generate/Update cluster configuration.
|
27
|
+
|
28
|
+
This task will generate/update all the configuration and chef files required to create a new cluster using the create task.
|
29
|
+
LONGDESC
|
30
|
+
|
31
|
+
shared_options :verbose, :name, :interactive, :'dry-run', :'run-options',
|
32
|
+
:template, :domain, :'ssl-cert', :'dns-provider-id', :'repo', :'chef-server', :'provider-id', :'provider-config'
|
33
|
+
|
34
|
+
def generate
|
35
|
+
require "fhcap/tasks/cluster/generate"
|
36
|
+
Tasks::Cluster::Generate.new(task_options(options.dup)).run
|
37
|
+
end
|
11
38
|
|
12
39
|
desc "create", "Create a new cluster"
|
13
40
|
|
14
|
-
shared_options :verbose, :name, :interactive
|
41
|
+
shared_options :verbose, :name, :interactive, :'dry-run',
|
42
|
+
:template, :domain, :'ssl-cert', :'dns-provider-id', :'repo', :'chef-server', :'provider-id', :'provider-config'
|
15
43
|
|
16
|
-
method_option
|
17
|
-
method_option 'git-ref', :type => :string, :desc => "fhcap git ref, can be a branch, tag or commit hash"
|
18
|
-
method_option 'git-remote', :type => :string, :desc => "git remote to use, default is the remote for the configured repos url"
|
19
|
-
method_option 'domain', :type => :string, :desc => "host names to register with DNS / base host name"
|
20
|
-
method_option 'ssl-cert', :type => :string, :desc => "ssl cert to use"
|
21
|
-
method_option 'dns-provider-id', :type => :string, :desc => "DNS Provider Id"
|
22
|
-
method_option 'repo', :type => :string, :desc => "Fhcap Repo where all config should be saved", :enum => repo_names
|
23
|
-
method_option 'chef-server', :type => :string, :desc => "Chef Server to use", :enum => chef_server_names
|
24
|
-
method_option 'provider-id', :type => :string, :desc => "Provider Id", :enum => provider_names_for('compute')
|
25
|
-
method_option 'provider-config', :type => :hash, :desc => "Provider specific config"
|
44
|
+
method_option :generate, :type => :boolean, :default => true, :desc => "Run generate task before create"
|
45
|
+
method_option :'git-ref', :type => :string, :desc => "fhcap git ref, can be a branch, tag or commit hash"
|
46
|
+
method_option :'git-remote', :type => :string, :desc => "git remote to use, default is the remote for the configured repos url"
|
26
47
|
create_steps = %w{repo-checkout cookbook-promote server-bootstrap create provision dns-record}
|
27
48
|
create_steps.each do |step|
|
28
49
|
method_option :"skip-#{step}", :type => :boolean, :default => false, :desc => "Skip #{step}"
|
29
50
|
end
|
30
51
|
|
31
52
|
def create
|
53
|
+
require "fhcap/tasks/cluster/generate"
|
32
54
|
require "fhcap/tasks/cluster/create"
|
55
|
+
Tasks::Cluster::Generate.new(task_options(options.dup)).run if options[:generate]
|
33
56
|
Tasks::Cluster::Create.new(task_options(options.dup)).run
|
34
57
|
end
|
35
58
|
|
36
|
-
desc "
|
59
|
+
desc "create_dns_records", "Create/Update a clusters DNS records"
|
60
|
+
long_desc <<-LONGDESC
|
61
|
+
Create/Update a clusters DNS records.
|
62
|
+
LONGDESC
|
37
63
|
|
38
64
|
shared_options :verbose, :name
|
65
|
+
|
66
|
+
def create_dns_records
|
67
|
+
require "fhcap/tasks/cluster/create_dns_records"
|
68
|
+
Tasks::Cluster::CreateDNSRecords.new(task_options(options.dup)).run
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "provision", "Provision a cluster"
|
72
|
+
|
73
|
+
shared_options :verbose, :name, :'dry-run', :'run-options'
|
74
|
+
|
39
75
|
method_option 'git-ref', :type => :string, :desc => "fhcap git ref, can be a branch, tag or commit hash"
|
40
76
|
method_option 'git-remote', :type => :string, :desc => "git remote to use, default is the remote for the configured repos url"
|
41
77
|
method_option 'nodes', :type => :string, :desc => "Query to pass to name"
|
@@ -74,7 +110,7 @@ module Fhcap
|
|
74
110
|
|
75
111
|
desc "destroy", "Destroy a cluster"
|
76
112
|
|
77
|
-
shared_options :verbose
|
113
|
+
shared_options :verbose, :'dry-run'
|
78
114
|
|
79
115
|
method_option 'name', :type => :string, :required => true, :desc => "Cluster name"
|
80
116
|
|
@@ -109,8 +145,24 @@ module Fhcap
|
|
109
145
|
end
|
110
146
|
|
111
147
|
desc "chef_provision", "[ADVANCED USAGE] Run a chef provisioning task against a particular cluster"
|
148
|
+
long_desc <<-LONGDESC
|
149
|
+
Allows the execution of any chef provisioning recipe on the given cluster.
|
150
|
+
Available recipes can be viewed here https://github.com/fheng/fhcap-cli/tree/master/lib/cookbooks/provision/recipes
|
112
151
|
|
113
|
-
|
152
|
+
With --run-options option, allows advanced configuration to be applied during the chef provisioning run.
|
153
|
+
These key:value pairs are added as attributes to the provisioning node and can alter the behaviour of the run.
|
154
|
+
|
155
|
+
env-regexp: Filter environments e.g. --run-options env-regexp:farm - Only environments with farm in the name will be acted upon (qed1-farm)
|
156
|
+
|
157
|
+
node-regexp: Filter nodes e.g. --run-options node-regexp:app - Only nodes with app in the name will be acted upon (qed1-core-app1, qed1-core-app2)
|
158
|
+
|
159
|
+
Examples:
|
160
|
+
|
161
|
+
fhcap cluster chef_provision --name qed1 --run-list provision::cluster_provision_instances
|
162
|
+
|
163
|
+
fhcap cluster chef_provision --name qed1 --run-list provision::cluster_provision_instances --run-options env-regexp:farm node-regexp:linux
|
164
|
+
LONGDESC
|
165
|
+
shared_options :verbose, :'dry-run', :'run-options'
|
114
166
|
|
115
167
|
method_option 'name', :type => :string, :required => true, :desc => 'Cluster name'
|
116
168
|
method_option 'run-list', :type => :array, :required => true, :desc => 'Chef Provisioning Run List i.e provision::cluster_provision'
|
data/lib/fhcap/cookbook.rb
CHANGED
@@ -35,6 +35,7 @@ module Fhcap
|
|
35
35
|
|
36
36
|
method_option 'level', :type => :string, :aliases => "-l", :desc => "Cookbook Bump level", :default => 'minor', :enum => %w{major minor patch}
|
37
37
|
method_option 'version', :type => :string, :aliases => "-v", :desc => "Version to set manually"
|
38
|
+
method_option 'base-branch', :type => :string, :default => 'origin/master', :desc => "Base branch to check modified cookbooks against"
|
38
39
|
|
39
40
|
def update
|
40
41
|
require "fhcap/tasks/chef/cookbook/update_version"
|
data/lib/fhcap/kitchen.rb
CHANGED
@@ -13,14 +13,16 @@ module Fhcap
|
|
13
13
|
|
14
14
|
add_shared_option :cookbooks, :aliases => "-c", :desc => "Apply to these Cookbooks", :type => :array
|
15
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}
|
16
|
+
add_shared_option :driver, :aliases => "-d", :desc => "Kitchen Driver", :type => :string, :default => 'openstack', :enum => %w{aws openstack docker vagrant}
|
17
17
|
add_shared_option :modified, :aliases => "-m", :desc => "Apply only to modified Cookbooks", :type => :boolean, :required => false, :default => false
|
18
18
|
add_shared_option :provisioner, :aliases => "-p", :desc => "Kitchen Provisioner", :type => :string, :default => 'chef_solo', :enum => %w{chef_solo chef_zero}
|
19
|
+
add_shared_option :'base-branch', :type => :string, :default => 'origin/master', :desc => "Base branch to check modified cookbooks against"
|
20
|
+
add_shared_option :'kitchen-options', :type => :hash, :default => {}, :desc => "Options to pass to kitchen command i.e. concurrency:10 = --concurrency=10 "
|
19
21
|
|
20
22
|
|
21
23
|
desc "generate", "Generate"
|
22
24
|
|
23
|
-
shared_options :cookbooks, :roles, :modified, :driver, :provisioner
|
25
|
+
shared_options :cookbooks, :roles, :modified, :driver, :provisioner, :'base-branch', :'kitchen-options'
|
24
26
|
method_option 'only', :type => :array, :default => nil, :desc => "Only include tests for cookbooks matching these names."
|
25
27
|
method_option 'exclude', :type => :array, :default => nil, :desc => "Exclude tests for cookbooks matching these names, takes precedence over 'only' option."
|
26
28
|
method_option 'clean', :type => :boolean, :default => true, :desc => "Clean the current generated kitchen prior to creating the new one"
|
@@ -128,16 +130,24 @@ module Fhcap
|
|
128
130
|
%w{create converge setup verify test list login destroy diagnose}.each do |cmd|
|
129
131
|
|
130
132
|
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
|
133
|
+
shared_options :cookbooks, :roles, :modified, :driver, :provisioner, :'base-branch', :'kitchen-options' if %w{create converge setup verify test list}.include? cmd
|
134
|
+
method_option :'log-level', :aliases => "-l", :desc => "Set the log level", :type => :string, :default => 'info', :enum => %w{debug info warn error fatal}
|
132
135
|
|
133
136
|
define_method(cmd) do |instance='all'|
|
137
|
+
kitchen_options = options[:'kitchen-options'] || {}
|
134
138
|
Fhcap::CLI::Kitchen.new.invoke(:generate, [], options) if options[:cookbooks] || options[:modified] || options[:roles]
|
135
139
|
if is_kitchen_generated?
|
136
140
|
Dir.chdir test_suite_dir do
|
137
141
|
cmd_options = options.dup
|
138
142
|
cmd_options['instance'] = instance
|
139
143
|
cmd_options['kitchen-yaml'] = test_suite_kitchen_yml
|
140
|
-
cmd_options['kitchen-options'] =
|
144
|
+
cmd_options['kitchen-options'] = kitchen_options_for(
|
145
|
+
default_kitchen_options.merge(
|
146
|
+
{:'log-level' => options[:'log-level']}
|
147
|
+
).merge(
|
148
|
+
JSON.parse(kitchen_options.to_json, {:symbolize_names => true})
|
149
|
+
)
|
150
|
+
)
|
141
151
|
run_kitchen_cmd(cmd, cmd_options)
|
142
152
|
end
|
143
153
|
else
|
@@ -149,6 +159,19 @@ module Fhcap
|
|
149
159
|
|
150
160
|
protected
|
151
161
|
|
162
|
+
def kitchen_options_for(opts)
|
163
|
+
opts.collect do |key,val|
|
164
|
+
"--#{key}=#{val}"
|
165
|
+
end.join(' ')
|
166
|
+
end
|
167
|
+
|
168
|
+
def default_kitchen_options
|
169
|
+
{
|
170
|
+
:concurrency => 10,
|
171
|
+
:'log-level' => 'info'
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
152
175
|
def test_suite_dir
|
153
176
|
File.join(config.default_dir, 'tmp', 'kitchen')
|
154
177
|
end
|
data/lib/fhcap/provider.rb
CHANGED
@@ -8,7 +8,7 @@ module Fhcap
|
|
8
8
|
add_shared_option :verbose, :aliases => "-v", :desc => "Verbose output", :type => :boolean, :required => false, :default => false
|
9
9
|
add_shared_option :interactive, :aliases => "-i", :desc => "Interactive mode (Stops for input)", :type => :boolean, :required => false, :default => false
|
10
10
|
add_shared_option :name, :type => :string, :required => true, :desc => "Provider Name"
|
11
|
-
add_shared_option :type, :type => :string, :required => true, :desc => "Provider Type", :enum => %w{aws openstack}
|
11
|
+
add_shared_option :type, :type => :string, :required => true, :desc => "Provider Type", :enum => %w{aws openstack dnsmadeeasy}
|
12
12
|
add_shared_option :credentials, :type => :hash, :desc => "Provider specific credentials"
|
13
13
|
|
14
14
|
desc "add", "Add a provider"
|
data/lib/fhcap/repos_helper.rb
CHANGED
@@ -134,7 +134,7 @@ module Fhcap
|
|
134
134
|
modified = []
|
135
135
|
cookbook_loader(paths).cookbook_names.each do |name|
|
136
136
|
cookbook_dir = cookbook_loader.cookbooks_by_name[name].root_dir
|
137
|
-
modified << name if modified?(cookbook_dir)
|
137
|
+
modified << name if modified?(cookbook_dir, options[:'base-branch'] || 'origin/master')
|
138
138
|
end
|
139
139
|
modified
|
140
140
|
end
|
@@ -21,7 +21,9 @@ module Fhcap
|
|
21
21
|
user = options[:knife_user] || 'hadmin'
|
22
22
|
attr = options[:knife_attr] || 'cloud.public_ipv4'
|
23
23
|
knife_options = options[:knife_options]
|
24
|
-
|
24
|
+
ssh_cmd = ["ssh \"#{query}\" \"#{cmd}\" -x #{user} -a #{attr} #{knife_options}"]
|
25
|
+
ssh_cmd << "--concurrency 1" if options[:series]
|
26
|
+
run_knife_cmd(ssh_cmd.join(' '), server, false)
|
25
27
|
end
|
26
28
|
|
27
29
|
def run_knife_cmd(cmd, server, capture=true)
|
@@ -16,7 +16,6 @@ module Fhcap
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def run
|
19
|
-
thor.say "Chef::Cookbook::UpdateVersion cookbook = #{name}", :yellow
|
20
19
|
cookbook = cookbook_loader.cookbooks_by_name[name]
|
21
20
|
metadata_file = cookbook.metadata_filenames.first
|
22
21
|
|
@@ -51,7 +50,7 @@ module Fhcap
|
|
51
50
|
new_contents = File.read(metadata_file).gsub(/(version\s+['"])[0-9\.]+(['"])/, "\\1#{new_version}\\2")
|
52
51
|
File.open(metadata_file, 'w') { |f| f.write(new_contents) }
|
53
52
|
|
54
|
-
thor.say "
|
53
|
+
thor.say "Updated #{cookbook.name} cookbook version to v#{new_version}!"
|
55
54
|
end
|
56
55
|
|
57
56
|
def bump_type
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'fhcap/tasks/chef/chef_server_task'
|
2
2
|
require 'fhcap/tasks/chef/cookbook/archive'
|
3
3
|
require 'fhcap/chef-dk/chef_runner'
|
4
|
+
require 'deep_merge'
|
4
5
|
|
5
6
|
module Fhcap
|
6
7
|
module Tasks
|
@@ -8,7 +9,7 @@ module Fhcap
|
|
8
9
|
module Provisioning
|
9
10
|
class ChefProvisioningTaskBase < ChefServerTask
|
10
11
|
|
11
|
-
attr_reader :name, :cluster_config, :cluster_filepath
|
12
|
+
attr_reader :name, :cluster_config, :cluster_filepath, :run_options
|
12
13
|
|
13
14
|
def initialize(options)
|
14
15
|
super
|
@@ -20,12 +21,13 @@ module Fhcap
|
|
20
21
|
local_repo_path: repo_dir(@chef_repo),
|
21
22
|
local_repo_clusters_dir: repo_clusters_dir(@chef_repo),
|
22
23
|
chef_server_config: chef_server_config_hash_for(@chef_server),
|
23
|
-
provider_credentials:
|
24
|
+
provider_credentials: provider_credentials(@cluster_config[:provider_id]),
|
24
25
|
max_simultaneous: options[:series] ? 1 : nil
|
25
26
|
})
|
26
27
|
else
|
27
28
|
exit_with_error("Unknown cluster #{@name}")
|
28
29
|
end
|
30
|
+
@run_options = options[:'run-options']
|
29
31
|
end
|
30
32
|
|
31
33
|
def seed_cookbooks
|
@@ -35,10 +37,23 @@ module Fhcap
|
|
35
37
|
do_chef_run("provision::seed_cookbooks")
|
36
38
|
end
|
37
39
|
|
38
|
-
def
|
40
|
+
def default_run_options
|
41
|
+
{
|
42
|
+
max_simultaneous: options[:series] ? 1 : nil,
|
43
|
+
"env-regexp" => '.',
|
44
|
+
"node-regexp" => '.'
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_run_options(opts)
|
49
|
+
default_run_options.deep_merge!(opts)
|
50
|
+
end
|
51
|
+
|
52
|
+
def do_chef_run(run_list, dry_run=options[:'dry-run'])
|
39
53
|
cookbook_path = File.join(Fhcap.source_root, 'lib', 'cookbooks')
|
40
54
|
private_key_paths = [File.join(cluster_config[:local_repo_path], cluster_config[:local_repo_clusters_dir], 'key_pairs')]
|
41
|
-
|
55
|
+
node_attrs = cluster_config.deep_merge(get_run_options(run_options))
|
56
|
+
Fhcap::ChefRunner.new(cookbook_path, run_list, dry_run, node_attrs, private_key_paths).converge
|
42
57
|
end
|
43
58
|
|
44
59
|
end
|
@@ -14,8 +14,13 @@ module Fhcap
|
|
14
14
|
knife_download(repo_dir(chef_repo), chef_server, ['/nodes']) if local_chef_server?
|
15
15
|
|
16
16
|
unless options[:'skip-provision']
|
17
|
+
do_chef_run("provision::cluster_bootstrap")
|
17
18
|
seed_cookbooks if local_chef_server?
|
18
19
|
do_chef_run("provision::post_create_instances")
|
20
|
+
|
21
|
+
#Need to set run list correctly here after post create stuff since provision no longer does it
|
22
|
+
do_chef_run("provision::cluster_bootstrap")
|
23
|
+
|
19
24
|
do_chef_run("provision::cluster_provision")
|
20
25
|
end
|
21
26
|
end
|
@@ -25,6 +30,4 @@ module Fhcap
|
|
25
30
|
end
|
26
31
|
end
|
27
32
|
end
|
28
|
-
end
|
29
|
-
|
30
|
-
|
33
|
+
end
|
@@ -5,7 +5,7 @@ require 'fhcap/tasks/chef/environments/promote_cookbooks'
|
|
5
5
|
require 'fhcap/tasks/chef/environments/create'
|
6
6
|
require 'fhcap/tasks/chef/server/bootstrap'
|
7
7
|
require 'fhcap/tasks/repo/checkout'
|
8
|
-
require "fhcap/tasks/
|
8
|
+
require "fhcap/tasks/cluster/create_dns_records"
|
9
9
|
|
10
10
|
module Fhcap
|
11
11
|
module Tasks
|
@@ -15,35 +15,14 @@ module Fhcap
|
|
15
15
|
attr_reader :name, :cluster_config
|
16
16
|
|
17
17
|
def initialize(options)
|
18
|
-
super(options
|
19
|
-
@template = options[:template]
|
20
|
-
@repo = options[:'repo']
|
21
|
-
@provider_config = options[:'provider-config'] || {}
|
18
|
+
super(options)
|
22
19
|
@gitref = options[:'git-ref']
|
23
|
-
@domain = options[:domain]
|
24
|
-
@ssl_cert = options[:'ssl-cert']
|
25
|
-
@dns_provider_id = options[:'dns-provider-id']
|
26
|
-
@chef_server = options[:'chef-server']
|
27
|
-
@provider_id = options[:'provider-id']
|
28
20
|
@skip_repo_checkout = options[:'skip-repo-checkout']
|
29
21
|
@skip_cookbook_promote = options[:'skip-cookbook-promote']
|
30
22
|
@skip_server_bootstrap = options[:'skip-server-bootstrap']
|
31
23
|
@skip_dns_record = options[:'skip-dns-record']
|
32
24
|
@skip_create = options[:'skip-create']
|
33
25
|
@skip_provision = options[:'skip-provision']
|
34
|
-
|
35
|
-
@cluster_config = {
|
36
|
-
id: @name,
|
37
|
-
template: @template,
|
38
|
-
driver: "",
|
39
|
-
domain: @domain,
|
40
|
-
repo: @repo,
|
41
|
-
chef_server: @chef_server,
|
42
|
-
provider_id: @provider_id
|
43
|
-
}.merge(@cluster_config)
|
44
|
-
|
45
|
-
@cluster_config[:provider_config] = @cluster_config[:provider_config] || {}
|
46
|
-
@cluster_config[:provider_config].merge!(@provider_config)
|
47
26
|
end
|
48
27
|
|
49
28
|
def run
|
@@ -52,16 +31,6 @@ module Fhcap
|
|
52
31
|
#Checkout repos
|
53
32
|
checkout_repos unless @skip_repo_checkout
|
54
33
|
|
55
|
-
#Generate cluster config
|
56
|
-
generate_cluster_config
|
57
|
-
|
58
|
-
#Create environment files
|
59
|
-
create_cluster_environments
|
60
|
-
|
61
|
-
#Write config to disk
|
62
|
-
cluster_file = find_cluster(name) || File.join(repo_dir(cluster_config[:repo]), repo_clusters_dir(cluster_config[:repo]), "#{name}.json")
|
63
|
-
thor.create_file(cluster_file, JSON.pretty_generate(cluster_config))
|
64
|
-
|
65
34
|
#Chef Stuff
|
66
35
|
#Promote cookbooks
|
67
36
|
Chef::Environments::PromoteCookbooks.new(@options.dup.merge({:environments => cluster_environments})).run unless @skip_cookbook_promote
|
@@ -72,176 +41,10 @@ module Fhcap
|
|
72
41
|
#Provisioning create
|
73
42
|
Chef::Provisioning::Create.new(@options.dup.merge(chef_task_options)).run unless @skip_create
|
74
43
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def required_config
|
81
|
-
{
|
82
|
-
repo: {
|
83
|
-
msg: "In which repo should this clusters config and environment files be stored?",
|
84
|
-
options: {:limited_to => repo_names}
|
85
|
-
},
|
86
|
-
domain: {
|
87
|
-
msg: "Base domain/hostname (e.g. foo.skunkhenry.com) for this cluster?",
|
88
|
-
},
|
89
|
-
chef_server: {
|
90
|
-
options: {:limited_to => chef_server_names}
|
91
|
-
},
|
92
|
-
provider_id: {
|
93
|
-
options: {:limited_to => provider_names_for('compute')}
|
94
|
-
},
|
95
|
-
template: {
|
96
|
-
options: {:limited_to => cluster_template_names}
|
97
|
-
}
|
98
|
-
}
|
99
|
-
end
|
100
|
-
|
101
|
-
def aws_required_config
|
102
|
-
aws_regions = provider_config(@cluster_config[:provider_id])[:regions]
|
103
|
-
{
|
104
|
-
region: {
|
105
|
-
options: {:limited_to => aws_regions.keys.collect { |k| k.to_s }}
|
106
|
-
},
|
107
|
-
cidr: {
|
108
|
-
msg: "CIDR block for AWS VPC (e.g. 10.123.0.0/16)?",
|
109
|
-
}
|
110
|
-
}
|
44
|
+
#Create/Update DNS Records
|
45
|
+
Cluster::CreateDNSRecords.new(@options.dup.merge(chef_task_options)).run unless @skip_dns_record
|
111
46
|
end
|
112
47
|
|
113
|
-
def generate_cluster_config
|
114
|
-
ask_config(required_config, cluster_config)
|
115
|
-
cluster_config[:driver] = provider_type(cluster_config[:provider_id])
|
116
|
-
send(:"generate_cluster_config_#{cluster_config[:driver]}")
|
117
|
-
driver_template_file = File.join(Fhcap.source_root, 'templates', 'cluster', cluster_config[:driver], "common.json.erb")
|
118
|
-
driver_template_config = template_as_object(driver_template_file, cluster_config)
|
119
|
-
cluster_config.merge!(driver_template_config)
|
120
|
-
end
|
121
|
-
|
122
|
-
def generate_cluster_config_aws
|
123
|
-
ask_config(aws_required_config, cluster_config[:provider_config])
|
124
|
-
aws_regions = provider_config(cluster_config[:provider_id])[:regions]
|
125
|
-
cluster_config[:default_instance_options] = cluster_config[:default_instance_options] || {}
|
126
|
-
cluster_config[:default_instance_options][:image_id] = aws_regions[cluster_config[:provider_config][:region].to_sym][:base_image]
|
127
|
-
end
|
128
|
-
|
129
|
-
def generate_cluster_config_openstack
|
130
|
-
cluster_config[:default_instance_options] = cluster_config[:default_instance_options] || {}
|
131
|
-
cluster_config[:default_instance_options][:image_ref] = provider_config(@cluster_config[:provider_id])[:image_ref]
|
132
|
-
cluster_config[:default_instance_options][:flavor_ref] = provider_config(@cluster_config[:provider_id])[:flavor_ref]
|
133
|
-
cluster_config[:default_instance_options][:floating_ip_pool] = provider_config(@cluster_config[:provider_id])[:floating_ip_pool]
|
134
|
-
cluster_config[:default_instance_options][:ssh_username] = provider_config(@cluster_config[:provider_id])[:ssh_username]
|
135
|
-
end
|
136
|
-
|
137
|
-
def create_cluster_environments
|
138
|
-
env_template_file = File.join(Fhcap.source_root, 'templates', 'cluster', "#{cluster_config[:template]}.json.erb")
|
139
|
-
template_config = template_as_object(env_template_file, cluster_config)
|
140
|
-
|
141
|
-
template_config[:environments].each do |env|
|
142
|
-
env_template_file = File.join(Fhcap.source_root, 'templates', 'cluster', cluster_config[:driver], "#{env[:template]}.json.erb")
|
143
|
-
template_config = template_as_object(env_template_file, cluster_config)
|
144
|
-
|
145
|
-
env_domain = [env[:'domain-prefix'], cluster_config[:domain]].compact.join('.')
|
146
|
-
env_cfg = {
|
147
|
-
:name => name,
|
148
|
-
:'environment-name' => env[:name],
|
149
|
-
:domain => env_domain,
|
150
|
-
:template => env[:template],
|
151
|
-
:'cluster-config' => cluster_config,
|
152
|
-
:'skip-create-cluster-file' => true
|
153
|
-
}
|
154
|
-
|
155
|
-
CreateEnvironment.new(@options.dup.merge(env_cfg)).run
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def create_dns_record
|
160
|
-
send(:"create_dns_record_#{cluster_config[:driver]}")
|
161
|
-
end
|
162
|
-
|
163
|
-
def create_dns_record_aws
|
164
|
-
cluster_config[:environments].each do |env_name, env_cfg|
|
165
|
-
env_cfg[:load_balancers].each do |lb_name, lb_cfg|
|
166
|
-
if lb_cfg[:scheme] == "internet-facing"
|
167
|
-
begin
|
168
|
-
require 'aws-sdk'
|
169
|
-
|
170
|
-
cfg = provider_config(cluster_config[:provider_id])
|
171
|
-
creds = cfg[:credentials]
|
172
|
-
|
173
|
-
elb = Aws::ElasticLoadBalancing::Client.new(
|
174
|
-
region: cluster_config[:provider_config][:region],
|
175
|
-
access_key_id: creds[:'aws-access-key'],
|
176
|
-
secret_access_key: creds[:'aws-secret-key']
|
177
|
-
)
|
178
|
-
|
179
|
-
lb = load_balancer_name_for(name, env_name, lb_name)
|
180
|
-
resp = elb.describe_load_balancers({
|
181
|
-
load_balancer_names: [lb],
|
182
|
-
page_size: 1,
|
183
|
-
})
|
184
|
-
|
185
|
-
elb = resp.load_balancer_descriptions.first
|
186
|
-
thor.say "Found ELB name: #{elb.load_balancer_name}, dns_name: #{elb.dns_name}, zone_id: #{elb.canonical_hosted_zone_name_id}"
|
187
|
-
|
188
|
-
dns_record_cfg = {
|
189
|
-
domain: "*.#{env_cfg[:domain]}",
|
190
|
-
:"alias-target" => {
|
191
|
-
dns_name: elb.dns_name,
|
192
|
-
hosted_zone_id: elb.canonical_hosted_zone_name_id
|
193
|
-
}
|
194
|
-
}
|
195
|
-
Dns::CreateRecord.new(@options.dup.merge(dns_record_cfg)).run
|
196
|
-
rescue Aws::ElasticLoadBalancing::Errors::LoadBalancerNotFound => e
|
197
|
-
thor.say_status 'error', "LoadBalancer #{lb} not found, unable to create DNS Entry", :red
|
198
|
-
rescue Aws::ElasticLoadBalancing::Errors::ServiceError => e
|
199
|
-
thor.say_status 'error', e.message, :red
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end if env_cfg[:load_balancers]
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def create_dns_record_openstack
|
207
|
-
cluster_config[:environments].each do |env_name, env_cfg|
|
208
|
-
env_name = "#{name}-#{env_name}"
|
209
|
-
knife_config_file = knife_config_file_for(cluster_config[:chef_server])
|
210
|
-
#ToDo [RHMAP-2898] Use knife object
|
211
|
-
nodes = JSON.parse(`knife search "chef_environment:#{env_name} AND recipes:nginx_feedhenry\\:\\:loadbalancer" -c #{knife_config_file} -F json -a name -a cloud.public_ipv4`)
|
212
|
-
|
213
|
-
lb_node = nodes['rows'].collect do |row|
|
214
|
-
name, attrs = row.first
|
215
|
-
attrs
|
216
|
-
end.first
|
217
|
-
|
218
|
-
if lb_node
|
219
|
-
if lb_node['cloud.public_ipv4']
|
220
|
-
dns_record_cfg = {
|
221
|
-
domain: "*.#{env_cfg[:domain]}",
|
222
|
-
ipaddress: lb_node['cloud.public_ipv4']
|
223
|
-
}
|
224
|
-
Dns::CreateRecord.new(@options.dup.merge(dns_record_cfg)).run
|
225
|
-
else
|
226
|
-
thor.say "Found lb node '#{lb_node['name']}', but was unable to retrieve it's IP!!}"
|
227
|
-
end
|
228
|
-
else
|
229
|
-
thor.say "Unable to locate lb node in cluster!!"
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
def load_balancer_name_for(org_name, environment, lb_name)
|
235
|
-
fh_name_for('fh-lb', org_name, environment, lb_name)[0..31] #elb names have a max length of 32
|
236
|
-
end
|
237
|
-
|
238
|
-
def fh_name_for(*args)
|
239
|
-
args.collect do |str|
|
240
|
-
str.to_s.split('-')
|
241
|
-
end.flatten.uniq.join('-')
|
242
|
-
end
|
243
|
-
|
244
|
-
|
245
48
|
end
|
246
49
|
end
|
247
50
|
end
|