knife-essentials 1.4 → 1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,99 @@
1
+ require 'chef_fs/knife'
2
+
3
+ class Chef
4
+ class Knife
5
+ remove_const(:Converge) if const_defined?(:Converge) && Converge.name == 'Chef::Knife::Converge' # override Chef's version
6
+ class Converge < ::ChefFS::Knife
7
+ ChefFS = ::ChefFS
8
+ banner "knife converge [PATTERN1 ... PATTERNn]"
9
+
10
+ deps do
11
+ require 'chef'
12
+ require 'chef/log'
13
+ require 'chef/application/client'
14
+ require 'chef_fs/file_system'
15
+ end
16
+
17
+ option :port,
18
+ :short => '-p',
19
+ :long => '--port=PORT',
20
+ :description => "Port to listen on (default: 8889)"
21
+
22
+ attr_accessor :exit_code
23
+
24
+ def configure_chef
25
+ super
26
+
27
+ self.exit_code = 0
28
+ end
29
+
30
+ def run
31
+ self.exit_code = 0
32
+ # Figure out the run list based on the passed-in objects
33
+ run_list = get_run_list(name_args)
34
+
35
+ if exit_code != 0
36
+ exit exit_code
37
+ end
38
+
39
+ # Configure and run chef client
40
+ if config[:config_file]
41
+ dot_chef = File.dirname(config[:config_file])
42
+ if File.basename(dot_chef) == '.chef'
43
+ # Override default locations to go in the .chef directory, since we are knife.
44
+ Chef::Config[:client_key] = File.join(dot_chef, 'client.pem') if !Chef::Config[:client_key] || Chef::Config[:client_key] == Chef::Config.platform_specific_path("/etc/chef/client.pem")
45
+ Chef::Config[:file_cache_path] = File.join(dot_chef, 'cache') if Chef::Config[:file_cache_path] == Chef::Config.platform_specific_path("/var/chef/cache")
46
+ Chef::Config[:file_backup_path] = File.join(dot_chef, 'backups') if Chef::Config[:file_backup_path] == Chef::Config.platform_specific_path("/var/chef/backup")
47
+ Chef::Config[:file_checksum_path] = File.join(dot_chef, 'checksums') if Chef::Config[:file_checksum_cache] == "/var/chef/checksums"
48
+ end
49
+ end
50
+ client = Chef::Application::Client.new
51
+ if run_list != ''
52
+ client.config[:override_runlist] = run_list
53
+ end
54
+ client.configure_logging # Bypass configure_chef, which we've already done adequately.
55
+ client.setup_application
56
+ client.run_application
57
+ end
58
+
59
+ def get_run_list(args)
60
+ result = []
61
+ args.each do |arg|
62
+ if arg.start_with?('recipe[') || arg.start_with?('role[')
63
+ result += arg.split(',')
64
+
65
+ else
66
+ begin
67
+ ChefFS::FileSystem.list(chef_fs, pattern_arg_from(arg)).each do |entry|
68
+ if entry.parent && entry.parent.path == '/cookbooks'
69
+ result << "recipe[#{entry.name}]"
70
+
71
+ elsif entry.parent && entry.parent.name == 'recipes' &&
72
+ entry.parent.parent && entry.parent.parent.parent && entry.parent.parent.parent.name == 'cookbooks' &&
73
+ entry.name[-3..-1] == '.rb'
74
+ cookbook_name = entry.parent.parent.name
75
+ recipe_name = entry.name[0..-4]
76
+ result << "recipe[#{cookbook_name}::#{recipe_name}]"
77
+
78
+ elsif entry.parent && entry.parent.name == 'roles'
79
+ result << "role[#{entry.name}]"
80
+
81
+ else
82
+ ui.error "arguments must be cookbooks, recipes or roles! #{format_path{e.entry}} is not a cookbook, recipe or role."
83
+ self.exit_code = 1
84
+ end
85
+ end
86
+ rescue ChefFS::FileSystem::OperationFailedError => e
87
+ "#{format_path_with_root(e.entry)} #{e.reason}."
88
+ self.exit_code = 1
89
+ rescue ChefFS::FileSystem::NotFoundError => e
90
+ ui.error "#{format_path(e.entry)}: No such file or directory"
91
+ self.exit_code = 1
92
+ end
93
+ end
94
+ end
95
+ result.join(',')
96
+ end
97
+ end
98
+ end
99
+ end
@@ -52,7 +52,9 @@ module ChefFS
52
52
  child_paths[name].each do |path|
53
53
  Dir.mkdir(path)
54
54
  end
55
- make_child_entry(name)
55
+ child = make_child_entry(name)
56
+ @children << child
57
+ child
56
58
  end
57
59
 
58
60
  def json_class
@@ -67,6 +67,13 @@ module ChefFS
67
67
  @chef_fs_config = ChefFS::Config.new(Chef::Config)
68
68
 
69
69
  ChefFS::Parallelizer.threads = (Chef::Config[:concurrency] || 10) - 1
70
+
71
+ if Chef::Config[:chef_server_url].to_sym == :local
72
+ local_url = start_local_server
73
+ Chef::Config[:chef_server_url] = local_url
74
+ Chef::Config[:client_key] = nil
75
+ Chef::Config[:validation_key] = nil
76
+ end
70
77
  end
71
78
 
72
79
  def chef_fs
@@ -90,17 +97,19 @@ module ChefFS
90
97
  end
91
98
 
92
99
  def pattern_args_from(args)
100
+ args.map { |arg| pattern_arg_from(arg) }
101
+ end
102
+
103
+ def pattern_arg_from(arg)
93
104
  # TODO support absolute file paths and not just patterns? Too much?
94
105
  # Could be super useful in a world with multiple repo paths
95
- args.map do |arg|
96
- if !@chef_fs_config.base_path && !ChefFS::PathUtils.is_absolute?(arg)
97
- # Check if chef repo path is specified to give a better error message
98
- @chef_fs_config.require_chef_repo_path
99
- ui.error("Attempt to use relative path '#{arg}' when current directory is outside the repository path")
100
- exit(1)
101
- end
102
- ChefFS::FilePattern.relative_to(@chef_fs_config.base_path, arg)
106
+ if !@chef_fs_config.base_path && !ChefFS::PathUtils.is_absolute?(arg)
107
+ # Check if chef repo path is specified to give a better error message
108
+ @chef_fs_config.require_chef_repo_path
109
+ ui.error("Attempt to use relative path '#{arg}' when current directory is outside the repository path")
110
+ exit(1)
103
111
  end
112
+ ChefFS::FilePattern.relative_to(@chef_fs_config.base_path, arg)
104
113
  end
105
114
 
106
115
  def format_path(entry)
@@ -110,5 +119,67 @@ module ChefFS
110
119
  def parallelize(inputs, options = {}, &block)
111
120
  ChefFS::Parallelizer.parallelize(inputs, options, &block)
112
121
  end
122
+
123
+ def locate_config_file
124
+ super
125
+ if !config[:config_file]
126
+ # If the config file doesn't already exist, find out where it should be,
127
+ # and create it.
128
+ repo_dir = discover_repo_dir(Dir.pwd)
129
+ if repo_dir
130
+ dot_chef = File.join(repo_dir, ".chef")
131
+ if !File.directory?(dot_chef)
132
+ Dir.mkdir(dot_chef)
133
+ end
134
+ knife_rb = File.join(dot_chef, "knife.rb")
135
+ if !File.exist?(knife_rb)
136
+ ui.warn("No configuration found. Creating .chef/knife.rb in #{repo_dir} ...")
137
+ File.open(knife_rb, "w") do |file|
138
+ file.write <<EOM
139
+ chef_server_url 'local'
140
+ chef_repo_path File.dirname(File.dirname(__FILE__))
141
+ cookbook_path File.join(chef_repo_path, "cookbooks")
142
+ EOM
143
+ end
144
+ end
145
+ config[:config_file] = knife_rb
146
+ end
147
+ end
148
+ end
149
+
150
+ def discover_repo_dir(dir)
151
+ %w(.chef cookbooks data_bags environments roles).each do |subdir|
152
+ return dir if File.directory?(File.join(dir, subdir))
153
+ end
154
+ # If this isn't it, check the parent
155
+ parent = File.dirname(dir)
156
+ if parent && parent != dir
157
+ discover_repo_dir(parent)
158
+ else
159
+ nil
160
+ end
161
+ end
162
+
163
+ def start_local_server
164
+ begin
165
+ require 'chef_zero/server'
166
+ rescue LoadError
167
+ STDERR.puts <<EOM
168
+ ERROR: chef-zero must be installed to use local-server mode! To install:
169
+
170
+ gem install chef-zero
171
+
172
+ EOM
173
+ exit(1)
174
+ end
175
+ require 'chef_fs/chef_fs_data_store'
176
+ server_options = {}
177
+ server_options[:data_store] = ChefFS::ChefFSDataStore.new(local_fs)
178
+ server_options[:log_level] = Chef::Log.level
179
+ server_options[:port] = 8889
180
+ server = ChefZero::Server.new(server_options)
181
+ server.start_background
182
+ server.url
183
+ end
113
184
  end
114
185
  end
@@ -1,3 +1,3 @@
1
1
  module ChefFS
2
- VERSION = "1.4"
2
+ VERSION = "1.5"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-essentials
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.4'
4
+ version: '1.5'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -118,6 +118,7 @@ files:
118
118
  - LICENSE
119
119
  - README.rdoc
120
120
  - Rakefile
121
+ - lib/chef/knife/converge_essentials.rb
121
122
  - lib/chef/knife/delete_essentials.rb
122
123
  - lib/chef/knife/deps_essentials.rb
123
124
  - lib/chef/knife/diff_essentials.rb