knife-essentials 0.4 → 0.5

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.
@@ -6,6 +6,8 @@ class Chef
6
6
  class Diff < ChefFS::Knife
7
7
  banner "diff PATTERNS"
8
8
 
9
+ common_options
10
+
9
11
  option :recurse,
10
12
  :long => '--[no-]recurse',
11
13
  :boolean => true,
@@ -22,8 +24,6 @@ class Chef
22
24
  :boolean => true,
23
25
  :description => "Only show names and statuses of modified files: Added, Deleted, Modified, and Type Changed."
24
26
 
25
- common_options
26
-
27
27
  def run
28
28
  if config[:name_only]
29
29
  output_mode = :name_only
@@ -6,6 +6,8 @@ class Chef
6
6
  class Download < ChefFS::Knife
7
7
  banner "download PATTERNS"
8
8
 
9
+ common_options
10
+
9
11
  option :recurse,
10
12
  :long => '--[no-]recurse',
11
13
  :boolean => true,
@@ -18,12 +20,25 @@ class Chef
18
20
  :default => false,
19
21
  :description => "Delete matching local files and directories that do not exist remotely."
20
22
 
23
+ option :force,
24
+ :long => '--[no-]force',
25
+ :boolean => true,
26
+ :default => false,
27
+ :description => "Force upload of files even if they match (quicker and harmless, but doesn't print out what it changed)"
28
+
29
+ option :dry_run,
30
+ :long => '--dry-run',
31
+ :short => '-n',
32
+ :boolean => true,
33
+ :default => false,
34
+ :description => "Don't take action, only print what would happen"
35
+
21
36
  def run
22
37
  patterns = pattern_args_from(name_args.length > 0 ? name_args : [ "" ])
23
38
 
24
39
  # Get the matches (recursively)
25
40
  patterns.each do |pattern|
26
- ChefFS::FileSystem.copy_to(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, config[:purge])
41
+ ChefFS::FileSystem.copy_to(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, config)
27
42
  end
28
43
  end
29
44
  end
@@ -6,6 +6,8 @@ class Chef
6
6
  class List < ChefFS::Knife
7
7
  banner "list [-dR] [PATTERN1 ... PATTERNn]"
8
8
 
9
+ common_options
10
+
9
11
  option :recursive,
10
12
  :short => '-R',
11
13
  :boolean => true,
@@ -6,6 +6,8 @@ class Chef
6
6
  class Show < ChefFS::Knife
7
7
  banner "show [PATTERN1 ... PATTERNn]"
8
8
 
9
+ common_options
10
+
9
11
  def run
10
12
  # Get the matches (recursively)
11
13
  pattern_args.each do |pattern|
@@ -0,0 +1,47 @@
1
+ require 'chef_fs/knife'
2
+ require 'chef_fs/command_line'
3
+
4
+ class Chef
5
+ class Knife
6
+ class Upload < ChefFS::Knife
7
+ banner "upload PATTERNS"
8
+
9
+ common_options
10
+
11
+ option :recurse,
12
+ :long => '--[no-]recurse',
13
+ :boolean => true,
14
+ :default => true,
15
+ :description => "List directories recursively."
16
+
17
+ option :purge,
18
+ :long => '--[no-]purge',
19
+ :boolean => true,
20
+ :default => false,
21
+ :description => "Delete matching local files and directories that do not exist remotely."
22
+
23
+ option :force,
24
+ :long => '--[no-]force',
25
+ :boolean => true,
26
+ :default => false,
27
+ :description => "Force upload of files even if they match (quicker and harmless, but doesn't print out what it changed)"
28
+
29
+ option :dry_run,
30
+ :long => '--dry-run',
31
+ :short => '-n',
32
+ :boolean => true,
33
+ :default => false,
34
+ :description => "Don't take action, only print what would happen"
35
+
36
+ def run
37
+ patterns = pattern_args_from(name_args.length > 0 ? name_args : [ "" ])
38
+
39
+ # Get the matches (recursively)
40
+ patterns.each do |pattern|
41
+ ChefFS::FileSystem.copy_to(pattern, local_fs, chef_fs, config[:recurse] ? nil : 1, config)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -42,7 +42,7 @@ module ChefFS
42
42
  # the entry at the end of the path.
43
43
  #
44
44
  # ==== Attributes
45
- #
45
+ #
46
46
  # * +entry+ - the entry to start looking under. Relative
47
47
  # paths will be resolved from here.
48
48
  # * +path+ - the path to resolve. If it starts with +/+,
@@ -72,26 +72,32 @@ module ChefFS
72
72
  # given pattern will look identical to src.
73
73
  #
74
74
  # ==== Attributes
75
- #
75
+ #
76
76
  # * +pattern+ - ChefFS::FilePattern to match children under
77
77
  # * +src_root+ - the root from which things will be copied
78
78
  # * +dest_root+ - the root to which things will be copied
79
79
  # * +recurse_depth+ - the maximum depth to copy things. +nil+
80
80
  # means infinite depth. 0 means no recursion.
81
- # * +purge+ - if +true+, items in +dest+ that are not in +src+
81
+ # * +options+ - hash of options:
82
+ # - +purge+ - if +true+, items in +dest+ that are not in +src+
82
83
  # will be deleted from +dest+. If +false+, these items will
83
84
  # be left alone.
85
+ # - +force+ - if +true+, matching files are always copied from
86
+ # +src+ to +dest+. If +false+, they will only be copied if
87
+ # actually different (which will take time to determine).
88
+ # - +dry_run+ - if +true+, action will not actually be taken;
89
+ # things will be printed out instead.
84
90
  #
85
91
  # ==== Examples
86
92
  #
87
93
  # ChefFS::FileSystem.copy_to(FilePattern.new('/cookbooks', chef_fs, local_fs, nil, true)
88
94
  #
89
- def self.copy_to(pattern, src_root, dest_root, recurse_depth, purge)
95
+ def self.copy_to(pattern, src_root, dest_root, recurse_depth, options)
90
96
  found_result = false
91
97
  # Find things we might want to copy
92
98
  ChefFS::Diff::diffable_leaves_from_pattern(pattern, src_root, dest_root, recurse_depth) do |src_leaf, dest_leaf, child_recurse_depth|
93
99
  found_result = true
94
- copy_leaves(src_leaf, dest_leaf, child_recurse_depth, purge)
100
+ copy_leaves(src_leaf, dest_leaf, child_recurse_depth, options)
95
101
  end
96
102
  if !found_result && pattern.exact_path
97
103
  yield "#{pattern}: No such file or directory on remote or local"
@@ -101,7 +107,7 @@ module ChefFS
101
107
  private
102
108
 
103
109
  # Copy two known leaves (could be files or dirs)
104
- def self.copy_leaves(src_entry, dest_entry, recurse_depth, purge)
110
+ def self.copy_leaves(src_entry, dest_entry, recurse_depth, options)
105
111
  # A NOTE about this algorithm:
106
112
  # There are cases where this algorithm does too many network requests.
107
113
  # knife upload with a specific filename will first check if the file
@@ -114,11 +120,15 @@ module ChefFS
114
120
  # Will need to decide how that works with checksums, though.
115
121
 
116
122
  if !src_entry.exists?
117
- if purge
123
+ if options[:purge]
118
124
  # If we would not have uploaded it, we will not purge it.
119
125
  if src_entry.parent.can_have_child?(dest_entry.name, dest_entry.dir?)
120
- dest_entry.delete
121
- puts "Delete extra entry #{dest_entry.path_for_printing} (purge is on)"
126
+ if options[:dry_run]
127
+ puts "Would delete #{dest_entry.path_for_printing}"
128
+ else
129
+ dest_entry.delete
130
+ puts "Delete extra entry #{dest_entry.path_for_printing} (purge is on)"
131
+ end
122
132
  else
123
133
  Chef::Log.info("Not deleting extra entry #{dest_entry.path_for_printing} (purge is off)")
124
134
  end
@@ -127,18 +137,27 @@ module ChefFS
127
137
  elsif !dest_entry.exists?
128
138
  if dest_entry.parent.can_have_child?(src_entry.name, src_entry.dir?)
129
139
  if src_entry.dir?
130
- new_dest_dir = dest_entry.parent.create_child(src_entry.name, nil)
131
- puts "Created #{dest_entry.path_for_printing}/"
140
+ if options[:dry_run]
141
+ puts "Would create #{dest_entry.path_for_printing}"
142
+ new_dest_dir = dest_entry.parent.child(src_entry.name)
143
+ else
144
+ new_dest_dir = dest_entry.parent.create_child(src_entry.name, nil)
145
+ puts "Created #{dest_entry.path_for_printing}/"
146
+ end
132
147
  # Directory creation is recursive.
133
148
  if recurse_depth != 0
134
149
  src_entry.children.each do |src_child|
135
150
  new_dest_child = new_dest_dir.child(src_child.name)
136
- copy_leaves(src_child, new_dest_child, recurse_depth ? recurse_depth - 1 : recurse_depth, purge)
151
+ copy_leaves(src_child, new_dest_child, recurse_depth ? recurse_depth - 1 : recurse_depth, options)
137
152
  end
138
153
  end
139
154
  else
140
- dest_entry.parent.create_child(src_entry.name, src_entry.read)
141
- puts "Created #{dest_entry.path_for_printing}"
155
+ if options[:dry_run]
156
+ puts "Would create #{dest_entry.path_for_printing}"
157
+ else
158
+ dest_entry.parent.create_child(src_entry.name, src_entry.read)
159
+ puts "Created #{dest_entry.path_for_printing}"
160
+ end
142
161
  end
143
162
  end
144
163
 
@@ -159,11 +178,24 @@ module ChefFS
159
178
  return
160
179
  else
161
180
  # Both are files! Copy them unless we're sure they are the same.
162
- different, src_value, dest_value = ChefFS::Diff.diff_files_quick(src_entry, dest_entry)
163
- if different || different == nil
181
+ if options[:force]
182
+ should_copy = true
183
+ src_value = src_entry.read
184
+ else
185
+ should_copy, src_value, dest_value = ChefFS::Diff.diff_files(src_entry, dest_entry)
164
186
  src_value = src_entry.read if src_value == :not_retrieved
165
- dest_entry.write(src_value)
166
- puts "Updated #{dest_entry.path_for_printing}"
187
+ if should_copy == nil
188
+ should_copy = true
189
+ end
190
+ end
191
+ if should_copy
192
+ if options[:dry_run]
193
+ puts "Would update #{dest_entry.path_for_printing}"
194
+ else
195
+ src_value = src_entry.read if src_value == :not_retrieved
196
+ dest_entry.write(src_value)
197
+ puts "Updated #{dest_entry.path_for_printing}"
198
+ end
167
199
  end
168
200
  end
169
201
  end
@@ -20,6 +20,17 @@ module ChefFS
20
20
  def can_have_child?(name, is_dir)
21
21
  is_dir
22
22
  end
23
+
24
+ def create_child(name, file_contents)
25
+ begin
26
+ rest.post_rest(api_path, { 'name' => name })
27
+ rescue Net::HTTPServerException
28
+ if $!.response.code != "409"
29
+ raise
30
+ end
31
+ end
32
+ DataBagDir.new(name, self, true)
33
+ end
23
34
  end
24
35
  end
25
36
  end
@@ -33,6 +33,18 @@ module ChefFS
33
33
  end
34
34
  end
35
35
 
36
+ def create_child(name, file_contents)
37
+ json = Chef::JSONCompat.from_json(file_contents).to_hash
38
+ base_name = name[0,name.length-5]
39
+ if json.include?('name') && json['name'] != base_name
40
+ raise "Name in #{path_for_printing}/#{name} must be '#{base_name}' (is '#{json['name']}')"
41
+ elsif json.include?('id') && json['id'] != base_name
42
+ raise "Name in #{path_for_printing}/#{name} must be '#{base_name}' (is '#{json['id']}')"
43
+ end
44
+ rest.post_rest(api_path, json)
45
+ RestListEntry.new(name, self, true)
46
+ end
47
+
36
48
  def environment
37
49
  parent.environment
38
50
  end
@@ -62,8 +62,23 @@ module ChefFS
62
62
  :json
63
63
  end
64
64
 
65
- def write(contents)
66
- rest.put_rest(api_path, contents)
65
+ def write(file_contents)
66
+ json = Chef::JSONCompat.from_json(file_contents).to_hash
67
+ base_name = name[0,name.length-5]
68
+ if json.include?('name') && json['name'] != base_name
69
+ raise "Name in #{path_for_printing}/#{name} must be '#{base_name}' (is '#{json['name']}')"
70
+ elsif json.include?('id') && json['id'] != base_name
71
+ raise "Name in #{path_for_printing}/#{name} must be '#{base_name}' (is '#{json['id']}')"
72
+ end
73
+ begin
74
+ rest.put_rest(api_path, json)
75
+ rescue Net::HTTPServerException
76
+ if $!.response.code == "404"
77
+ raise ChefFS::FileSystem::NotFoundError.new($!), "#{path_for_printing} not found"
78
+ else
79
+ raise
80
+ end
81
+ end
67
82
  end
68
83
  end
69
84
  end
@@ -1,4 +1,4 @@
1
1
  module ChefFS
2
- VERSION = "0.4"
2
+ VERSION = "0.5"
3
3
  end
4
4
 
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: '0.4'
4
+ version: '0.5'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-29 00:00:00.000000000Z
12
+ date: 2012-05-10 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: Universal knife verbs that work with your Chef repository
15
15
  email: jkeiser@opscode.com
@@ -26,6 +26,7 @@ files:
26
26
  - lib/chef/knife/download.rb
27
27
  - lib/chef/knife/list.rb
28
28
  - lib/chef/knife/show.rb
29
+ - lib/chef/knife/upload.rb
29
30
  - lib/chef_fs/command_line.rb
30
31
  - lib/chef_fs/diff.rb
31
32
  - lib/chef_fs/file_pattern.rb