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,18 @@
1
+ class Chef
2
+ module Provisioning
3
+ class ChefRunData
4
+
5
+ def connect_to_machine(name, chef_server = nil)
6
+
7
+ if name.is_a?(ManagedEntry)
8
+ machine_spec = name
9
+ else
10
+ machine_spec = Provisioning.chef_managed_entry_store(chef_server).get(:machine, name)
11
+ end
12
+ Chef::Provisioning.connect_to_machine(machine_spec, config, driver_for_url(machine_spec.driver_url))
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module Cheffish
2
+ class MergedConfig
3
+
4
+ def to_h
5
+ to_hash
6
+ end
7
+
8
+ end
9
+ end
data/lib/fhcap.rb ADDED
@@ -0,0 +1,14 @@
1
+ require "fhcap/version"
2
+ require "pathname"
3
+
4
+ module Fhcap
5
+ GEM_DIR = File.expand_path '..', File.dirname(__FILE__)
6
+ TEMPLATE_NAMES = %w{single core-3node mbaas-3node core-mbaas-6node core-small-9node nginx-test single-blank}.sort
7
+
8
+ class << self
9
+ def source_root
10
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,94 @@
1
+ # Modified version of https://github.com/chef/chef-dk/blob/master/lib/chef-dk/chef_runner.rb
2
+
3
+ require 'chef'
4
+ require 'extensions/chef/provisioning'
5
+ require 'extensions/chef/provisioning/chef_run_data'
6
+ require 'extensions/cheffish/merged_config'
7
+
8
+ module Fhcap
9
+ # An adapter to chef's APIs to kick off a chef-client run.
10
+
11
+ class ChefRunnerError < StandardError; end
12
+ class CookbookNotFound < ChefRunnerError; end
13
+ class ChefConvergeError < ChefRunnerError; end
14
+
15
+ class ChefRunner
16
+
17
+ attr_reader :cookbook_path
18
+ attr_reader :run_list
19
+ attr_reader :node_attrs
20
+
21
+ def initialize(cookbook_path, run_list, node_attrs={})
22
+ @cookbook_path = File.expand_path(cookbook_path)
23
+ @run_list = run_list
24
+ @node_attrs = node_attrs
25
+ @formatter = nil
26
+ @ohai = nil
27
+ end
28
+
29
+ def converge
30
+ configure
31
+ Chef::Runner.new(run_context).converge
32
+ rescue Chef::Exceptions::CookbookNotFound => e
33
+ message = "Could not find cookbook(s) to satisfy run list #{run_list.inspect} in #{cookbook_path}"
34
+ raise CookbookNotFound.new(message)
35
+ rescue => e
36
+ test = ChefConvergeError.new("Chef failed to converge: #{e}")
37
+ raise test
38
+ end
39
+
40
+ def run_context
41
+ @run_context ||= policy.setup_run_context
42
+ end
43
+
44
+ def policy
45
+ return @policy_builder if @policy_builder
46
+
47
+ @policy_builder = Chef::PolicyBuilder::ExpandNodeObject.new("fhcap-cli", ohai.data, node_attrs, nil, formatter)
48
+ @policy_builder.load_node
49
+ @policy_builder.build_node
50
+ @policy_builder.node.run_list(*run_list)
51
+ @policy_builder.expand_run_list
52
+ @policy_builder
53
+ end
54
+
55
+ def formatter
56
+ @formatter ||=
57
+ Chef::EventDispatch::Dispatcher.new.tap do |d|
58
+ d.register(Chef::Formatters.new(:doc, stdout, stderr))
59
+ end
60
+ end
61
+
62
+ def configure
63
+ Chef::Config.solo = true
64
+ Chef::Config.log_level = :error
65
+ Chef::Config.ssl_verify_mode = :verify_none
66
+ Chef::Config.cookbook_path = cookbook_path
67
+ Chef::Config.color = true
68
+ Chef::Config.diff_disabled = true
69
+
70
+ # atomic file operations on Windows require Administrator privileges to be able to read the SACL from a file
71
+ # Using file_staging_uses_destdir(true) will get us inherited permissions indirectly on tempfile creation
72
+ Chef::Config.file_atomic_update = false if Chef::Platform.windows?
73
+ Chef::Config.file_staging_uses_destdir = true # Default in Chef 12+
74
+ end
75
+
76
+ def ohai
77
+ return @ohai if @ohai
78
+
79
+ @ohai = Ohai::System.new
80
+ @ohai.all_plugins(["platform", "platform_version"])
81
+ @ohai
82
+ end
83
+
84
+ def stdout
85
+ $stdout
86
+ end
87
+
88
+ def stderr
89
+ $stderr
90
+ end
91
+
92
+ end
93
+ end
94
+
data/lib/fhcap/cli.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'fhcap/thor_base'
2
+ require 'fhcap/cluster'
3
+ require 'fhcap/cookbook'
4
+ require 'fhcap/repo'
5
+ require 'fhcap/knife'
6
+ require 'fhcap/provider'
7
+ require 'fhcap/misc'
8
+ require 'fhcap/kitchen'
9
+ require 'fhcap/version'
10
+
11
+ module Fhcap
12
+ module CLI
13
+ class Cli < Fhcap::ThorBase
14
+ namespace "fhcap"
15
+
16
+ add_shared_option :verbose, :aliases => "-v", :desc => "Verbose Output", :type => :boolean, :required => false, :default => false
17
+ add_shared_option :interactive, :aliases => "-i", :desc => "Interactive mode (Stops for input)", :type => :boolean, :required => false, :default => false
18
+
19
+ method_option 'repos-dir', :type => :string, :desc => "Local directory where configured repos will be checked out"
20
+
21
+ desc "setup", "Setup the FHCAP CLI"
22
+
23
+ shared_options :verbose, :interactive
24
+
25
+ def setup
26
+ require "fhcap/tasks/setup"
27
+ Tasks::Setup.new(task_options(options.dup)).run
28
+ end
29
+
30
+ desc "clean", "Clean up everything created by setup"
31
+
32
+ def clean
33
+ require "fhcap/tasks/clean"
34
+ Tasks::Clean.new(task_options(options.dup)).run
35
+ end
36
+
37
+ desc "info", "Display information about current configuration"
38
+
39
+ def info
40
+ say "Config file: #{config.config_file}", :green
41
+ Fhcap::CLI::Repo.new.invoke(:list)
42
+ Fhcap::CLI::Provider.new.invoke(:list)
43
+ Fhcap::CLI::Knife.new.invoke(:list)
44
+ end
45
+
46
+ desc "cluster COMMANDS", "Cluster commands"
47
+ subcommand "cluster", Fhcap::CLI::Cluster
48
+
49
+ desc "cookbook COMMANDS", "Cookbook commands"
50
+ subcommand "cookbook", Fhcap::CLI::Cookbook
51
+
52
+ desc "repo COMMANDS", "Repo commands"
53
+ subcommand "repo", Fhcap::CLI::Repo
54
+
55
+ desc "knife COMMANDS", "Knife commands"
56
+ subcommand "knife", Fhcap::CLI::Knife
57
+
58
+ desc "provider COMMANDS", "Provider commands"
59
+ subcommand "provider", Fhcap::CLI::Provider
60
+
61
+ desc "misc COMMANDS", "Miscellaneous commands"
62
+ subcommand "misc", Fhcap::CLI::Misc
63
+
64
+ desc "kitchen COMMANDS", "Kitchen commands"
65
+ subcommand "kitchen", Fhcap::CLI::Kitchen
66
+
67
+ desc "version", "Print version information"
68
+ def version
69
+ puts "FHCAP Cli version #{Fhcap::VERSION}"
70
+ end
71
+ map %w[-v --version] => :version
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,112 @@
1
+ require 'thor'
2
+ require 'fhcap/thor_base'
3
+
4
+ module Fhcap
5
+ module CLI
6
+ class Cluster < 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 => "Cluster name"
10
+ add_shared_option :interactive, :aliases => "-i", :desc => "Interactive mode (Stops for input)", :type => :boolean, :required => false, :default => false
11
+
12
+ desc "create", "Create a new cluster"
13
+
14
+ shared_options :verbose, :name, :interactive
15
+
16
+ method_option 'template', :type => :string, :desc => "Cluster template i.e. [1, 3 , 5 node cluster setup, core or mbaas]", :enum => cluster_template_names
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 origin"
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"
26
+ create_steps = %w{repo-checkout cookbook-promote server-bootstrap create dns-record}
27
+ create_steps.each do |step|
28
+ method_option :"skip-#{step}", :type => :boolean, :default => false, :desc => "Skip #{step}"
29
+ end
30
+
31
+ def create
32
+ require "fhcap/tasks/cluster/create"
33
+ Tasks::Cluster::Create.new(task_options(options.dup)).run
34
+ end
35
+
36
+ desc "provision", "Provision a cluster"
37
+
38
+ shared_options :verbose, :name
39
+ method_option 'git-ref', :type => :string, :desc => "fhcap git ref, can be a branch, tag or commit hash"
40
+ method_option 'git-remote', :type => :string, :desc => "git remote to use, default is origin"
41
+ method_option 'nodes', :type => :string, :desc => "Query to pass to name"
42
+ method_option 'roles', :type => :string, :desc => "Query to pass to roles"
43
+ method_option 'series', :type => :boolean, :default => false, :desc => "Run provision in series"
44
+ method_option 'strategy', :type => :string, :default => 'chef', :desc => "Provision strategy to use. Default is chef provisioning, falls back to knife provision.", :enum => %w{chef knife}
45
+
46
+ provision_steps = %w{repo-checkout cookbook-promote server-bootstrap provision}
47
+ provision_steps.each do |step|
48
+ method_option :"skip-#{step}", :type => :boolean, :default => false, :desc => "Skip #{step}"
49
+ end
50
+
51
+ def provision
52
+ require "fhcap/tasks/cluster/provision"
53
+ Tasks::Cluster::Provision.new(task_options(options.dup)).run
54
+ end
55
+
56
+ desc "test", "Test a cluster"
57
+
58
+ shared_options :verbose, :name
59
+
60
+ def test
61
+ require "fhcap/tasks/cluster/test"
62
+ Tasks::Cluster::Test.new(task_options(options.dup)).run
63
+ end
64
+
65
+ desc "status", "Show the Status of a cluster"
66
+
67
+ shared_options :verbose, :name
68
+
69
+ def status
70
+ require "fhcap/tasks/cluster/status"
71
+ Tasks::Cluster::Status.new(task_options(options.dup)).run
72
+ end
73
+
74
+ desc "destroy", "Destroy a cluster"
75
+
76
+ shared_options :verbose
77
+
78
+ method_option 'name', :type => :string, :required => true, :desc => "Cluster name"
79
+
80
+ destroy_steps = %w{destroy}
81
+ destroy_steps.each do |step|
82
+ method_option :"skip-#{step}", :type => :boolean, :default => false, :desc => "Skip #{step}"
83
+ end
84
+
85
+ def destroy
86
+ require "fhcap/tasks/cluster/destroy"
87
+ Tasks::Cluster::Destroy.new(task_options(options.dup)).run
88
+ end
89
+
90
+ desc "info", "Show info about a Cluster"
91
+
92
+ shared_options :verbose
93
+
94
+ method_option 'name', :type => :string, :required => true, :desc => "Cluster name"
95
+ method_option 'launch', :type => :boolean, :default => false, :desc => "Launch all urls in the browser"
96
+ method_option 'only', :type => :string, :desc => "", :enum => %w{ips urls passwords}
97
+
98
+ def info
99
+ require "fhcap/tasks/cluster/info"
100
+ Tasks::Cluster::Info.new(task_options(options.dup)).run
101
+ end
102
+
103
+ desc "list", "List configured clusters"
104
+
105
+ def list
106
+ require "fhcap/tasks/cluster/list"
107
+ Tasks::Cluster::List.new(task_options(options.dup)).run
108
+ end
109
+
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,104 @@
1
+ # config.rb
2
+ require 'json'
3
+ require 'etc'
4
+
5
+ module Fhcap
6
+
7
+ class Config
8
+
9
+ attr_reader :config_file
10
+
11
+ def initialize(options = {})
12
+ @config_file = File.expand_path(options[:config_file] || default_config_file)
13
+ end
14
+
15
+ def exists?
16
+ File.exist?(@config_file)
17
+ end
18
+
19
+ def [](attrib)
20
+ data[attrib]
21
+ end
22
+
23
+ def []=(attr, val)
24
+ data[attr] = val
25
+ end
26
+
27
+ def data
28
+ @data ||= read
29
+ end
30
+
31
+ def reload
32
+ @data = read
33
+ end
34
+
35
+ def read
36
+ unless exists?
37
+ raise "FHCAP Config file #{@config_file} does not exist."
38
+ end
39
+ symbolize_keys_deep(JSON.parse(IO.read(@config_file)))
40
+ end
41
+
42
+ def default_dir
43
+ File.join(Dir.home, 'fhcap')
44
+ end
45
+
46
+ def default_config_file
47
+ File.join(default_dir, 'fhcap.json')
48
+ end
49
+
50
+ def knife_dir
51
+ data[:knife_dir] || File.join(default_dir, '.chef')
52
+ end
53
+
54
+ def repos_dir
55
+ data[:repos_dir] || File.join(default_dir, 'repos')
56
+ end
57
+
58
+ def tmp_dir
59
+ File.join(default_dir, 'tmp')
60
+ end
61
+
62
+ def fhcap_cookbook_archive_url
63
+ 'https://s3-eu-west-1.amazonaws.com/fhcap/fhcap-cookbooks-0fa68747b476f7ee555a94483877969a30133e76.tgz'
64
+ end
65
+
66
+ # Generates the immutable fhcap configuration and reasonable defaults.
67
+ def fhcap_config
68
+ @fhcap_config ||= {
69
+ :repos_dir => File.join(default_dir, 'repos'),
70
+ :repos => {
71
+ :fhcap => {
72
+ :url => 'git@github.com:fheng/fhcap.git',
73
+ :archives => {
74
+ :cookbooks => fhcap_cookbook_archive_url
75
+ }
76
+ },
77
+ :"fhcap-dev" => {
78
+ :clusters_dir => 'organisations',
79
+ :url => 'git@github.com:fheng/fhcap-dev.git'
80
+ }
81
+ },
82
+ :knife_dir => File.join(default_dir, '.chef'),
83
+ :knife => {
84
+ :bob => {
85
+ :chef_server_url => 'https://bob.feedhenry.net:8443',
86
+ :node_name => Etc.getlogin
87
+ }
88
+ }
89
+ }
90
+ end
91
+
92
+ private
93
+
94
+ def symbolize_keys_deep(h)
95
+ h.keys.each do |k|
96
+ ks = k.to_sym
97
+ h[ks] = h.delete k
98
+ symbolize_keys_deep h[ks] if h[ks].kind_of? Hash
99
+ end
100
+ h
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,75 @@
1
+ require 'thor'
2
+ require 'fhcap/thor_base'
3
+
4
+ module Fhcap
5
+ module CLI
6
+ class Cookbook < Fhcap::ThorBase
7
+
8
+ add_shared_option :cookbooks, :aliases => "-c", :desc => "Apply to these Cookbooks", :type => :array
9
+ add_shared_option :modified, :aliases => "-m", :desc => "Apply only to modified Cookbooks", :type => :boolean, :required => false, :default => false
10
+
11
+ desc "update", "Update a cookbook, defaults to all cookbooks."
12
+ long_desc <<-LONGDESC
13
+ Updates a cookbook(s) version, metadata, readme and changelog.
14
+
15
+ With --cookbooks (-c) <cookbook1 cookbook2> option, specifies the cookbook(s) to update, default is all cookbooks.
16
+
17
+ With --modified (-m) option, updates all cookbooks modified between the current HEAD and the last origin commit.
18
+
19
+ With --changelog-entries (-e) <'entry1' 'entry2'> option, changelog entries to be put into the cookbook(s) changelog file for this version change.
20
+
21
+ With --level (-l) [major|minor|patch"] option, sets the bump level to be applied to the given cookbook(s), default is minor.
22
+
23
+ With --version (-v) 1.1.1 option, sets the version to be applied to the given cookbook(s).
24
+
25
+ With --wip option, defaults the level option to 'patch' and skips all metadata updates i.e. cookbook metadata, readme and changelog files are not modified.
26
+
27
+ Examples:
28
+
29
+ fhcap cookbook update -c feedhenry_common -e 'Some awesome new feature'
30
+
31
+ fhcap cookbook update -c feedhenry_common --wip
32
+
33
+ fhcap cookbook update -c feedhenry_common -l major -e 'Some major change'
34
+ LONGDESC
35
+
36
+ shared_options :cookbooks, :modified
37
+
38
+ method_option 'changelog-entries', :type => :array, :aliases => "-e", :default => ["Replace me with a proper changelog entry"], :desc => "Changelog entries"
39
+ method_option 'level', :type => :string, :aliases => "-l", :desc => "Bump level", :enum => %w{major minor patch}
40
+ method_option 'version', :type => :string, :aliases => "-v", :desc => "Version to set manually"
41
+ method_option 'wip', :type => :boolean, :desc => "Work in progress. No meta is generated and level is set to patch level changes."
42
+
43
+ def update
44
+ require "fhcap/tasks/chef/cookbook/update_version"
45
+ require "fhcap/tasks/chef/cookbook/update_metadata"
46
+ require "fhcap/tasks/chef/cookbook/update_readme"
47
+ require "fhcap/tasks/chef/cookbook/update_changelog"
48
+ cookbooks = get_cookbooks(options, nil, repo_cookbook_paths('-cookbooks'))
49
+ say("Cookbook update for #{cookbooks}", :yellow)
50
+
51
+ cookbooks.each do |cookbook|
52
+ Tasks::Chef::Cookbook::UpdateVersion.new(task_options(options.dup.merge({cookbook: cookbook}))).run
53
+ end
54
+
55
+ if options[:wip]
56
+ say("WIP, skipping meta updates.", :yellow)
57
+ else
58
+ cookbooks.each do |cookbook|
59
+ Tasks::Chef::Cookbook::UpdateMetadata.new(task_options(options.dup.merge({cookbook: cookbook}))).run
60
+ Tasks::Chef::Cookbook::UpdateReadme.new(task_options(options.dup.merge({cookbook: cookbook}))).run
61
+ Tasks::Chef::Cookbook::UpdateChangelog.new(task_options(options.dup.merge({cookbook: cookbook}))).run
62
+ end
63
+ end
64
+ end
65
+
66
+ desc "list", "List cookbooks and show artifact versions where applicable."
67
+
68
+ def list
69
+ require "fhcap/tasks/chef/cookbook/list"
70
+ Tasks::Chef::Cookbook::List.new(task_options(options.dup)).run
71
+ end
72
+
73
+ end
74
+ end
75
+ end