chef-dk 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/chef-dk/builtin_commands.rb +10 -0
  4. data/lib/chef-dk/command/base.rb +2 -2
  5. data/lib/chef-dk/command/clean_policy_cookbooks.rb +116 -0
  6. data/lib/chef-dk/command/clean_policy_revisions.rb +113 -0
  7. data/lib/chef-dk/command/delete_policy.rb +122 -0
  8. data/lib/chef-dk/command/delete_policy_group.rb +122 -0
  9. data/lib/chef-dk/command/export.rb +3 -3
  10. data/lib/chef-dk/command/generate.rb +8 -0
  11. data/lib/chef-dk/command/generator_commands/app.rb +1 -1
  12. data/lib/chef-dk/command/generator_commands/cookbook.rb +1 -1
  13. data/lib/chef-dk/command/generator_commands/policyfile.rb +1 -1
  14. data/lib/chef-dk/command/generator_commands/repo.rb +1 -1
  15. data/lib/chef-dk/command/install.rb +22 -5
  16. data/lib/chef-dk/command/provision.rb +0 -4
  17. data/lib/chef-dk/command/push.rb +1 -2
  18. data/lib/chef-dk/command/shell_init.rb +65 -6
  19. data/lib/chef-dk/command/show_policy.rb +1 -2
  20. data/lib/chef-dk/command/undelete.rb +155 -0
  21. data/lib/chef-dk/command/update.rb +5 -5
  22. data/lib/chef-dk/command/verify.rb +61 -17
  23. data/lib/chef-dk/completions/bash.sh.erb +5 -0
  24. data/lib/chef-dk/completions/chef.fish.erb +10 -0
  25. data/lib/chef-dk/completions/zsh.zsh.erb +21 -0
  26. data/lib/chef-dk/exceptions.rb +12 -0
  27. data/lib/chef-dk/helpers.rb +17 -0
  28. data/lib/chef-dk/policyfile/community_cookbook_source.rb +0 -3
  29. data/lib/chef-dk/policyfile/lister.rb +3 -1
  30. data/lib/chef-dk/policyfile/undo_record.rb +142 -0
  31. data/lib/chef-dk/policyfile/undo_stack.rb +130 -0
  32. data/lib/chef-dk/policyfile_lock.rb +30 -0
  33. data/lib/chef-dk/policyfile_services/clean_policies.rb +5 -4
  34. data/lib/chef-dk/policyfile_services/clean_policy_cookbooks.rb +125 -0
  35. data/lib/chef-dk/policyfile_services/rm_policy.rb +142 -0
  36. data/lib/chef-dk/policyfile_services/rm_policy_group.rb +86 -0
  37. data/lib/chef-dk/policyfile_services/show_policy.rb +1 -1
  38. data/lib/chef-dk/policyfile_services/undelete.rb +108 -0
  39. data/lib/chef-dk/service_exceptions.rb +11 -0
  40. data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +6 -2
  41. data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +1 -1
  42. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +1 -1
  43. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +1 -1
  44. data/lib/chef-dk/version.rb +1 -1
  45. data/lib/kitchen/provisioner/policyfile_zero.rb +4 -1
  46. data/spec/unit/command/base_spec.rb +26 -1
  47. data/spec/unit/command/clean_policy_cookbooks_spec.rb +181 -0
  48. data/spec/unit/command/clean_policy_revisions_spec.rb +181 -0
  49. data/spec/unit/command/delete_policy_group_spec.rb +207 -0
  50. data/spec/unit/command/delete_policy_spec.rb +207 -0
  51. data/spec/unit/command/generate_spec.rb +41 -1
  52. data/spec/unit/command/generator_commands/cookbook_spec.rb +1 -1
  53. data/spec/unit/command/generator_commands/policyfile_spec.rb +1 -1
  54. data/spec/unit/command/install_spec.rb +24 -0
  55. data/spec/unit/command/shell_init_spec.rb +176 -5
  56. data/spec/unit/command/undelete_spec.rb +246 -0
  57. data/spec/unit/helpers_spec.rb +24 -0
  58. data/spec/unit/policyfile/lister_spec.rb +16 -0
  59. data/spec/unit/policyfile/undo_record_spec.rb +260 -0
  60. data/spec/unit/policyfile/undo_stack_spec.rb +266 -0
  61. data/spec/unit/policyfile_lock_serialization_spec.rb +41 -0
  62. data/spec/unit/policyfile_services/clean_policy_cookbooks_spec.rb +275 -0
  63. data/spec/unit/policyfile_services/rm_policy_group_spec.rb +241 -0
  64. data/spec/unit/policyfile_services/rm_policy_spec.rb +266 -0
  65. data/spec/unit/policyfile_services/show_policy_spec.rb +52 -2
  66. data/spec/unit/policyfile_services/undelete_spec.rb +304 -0
  67. metadata +43 -91
@@ -40,8 +40,7 @@ to the target machine, you can apply the policy to the machine with
40
40
  versioned_cookbooks true
41
41
  policy_document_native_api false
42
42
 
43
- The Policyfile feature is incomplete and beta quality. See our detailed README
44
- for more information.
43
+ See our detailed README for more information:
45
44
 
46
45
  https://github.com/opscode/chef-dk/blob/master/POLICYFILE_README.md
47
46
 
@@ -140,7 +139,8 @@ E
140
139
  when 2
141
140
  @policyfile_relative_path, @export_dir = remaining_args
142
141
  else
143
- ui.err(banner)
142
+ ui.err(opt_parser)
143
+ ui.err("\n")
144
144
  return false
145
145
  end
146
146
  true
@@ -86,6 +86,14 @@ E
86
86
  msg(banner)
87
87
  1
88
88
  end
89
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
90
+ # ChefDK::Command::Base also handles this error in the same way, but it
91
+ # does not have access to the correct option parser, so it cannot print
92
+ # the usage correctly. Therefore, invalid CLI usage needs to be handled
93
+ # here.
94
+ err("ERROR: #{e.message}\n")
95
+ msg(generator.opt_parser)
96
+ 1
89
97
  end
90
98
 
91
99
  def generator_for(arg)
@@ -46,7 +46,7 @@ module ChefDK
46
46
  setup_context
47
47
  chef_runner.converge
48
48
  else
49
- msg(banner)
49
+ err(opt_parser)
50
50
  1
51
51
  end
52
52
  rescue ChefDK::ChefRunnerError => e
@@ -49,7 +49,7 @@ module ChefDK
49
49
  setup_context
50
50
  chef_runner.converge
51
51
  else
52
- msg(banner)
52
+ err(opt_parser)
53
53
  1
54
54
  end
55
55
  rescue ChefDK::ChefRunnerError => e
@@ -52,7 +52,7 @@ module ChefDK
52
52
  chef_runner.converge
53
53
  0
54
54
  else
55
- msg(banner)
55
+ err(opt_parser)
56
56
  1
57
57
  end
58
58
  end
@@ -52,7 +52,7 @@ module ChefDK
52
52
  setup_context
53
53
  chef_runner.converge
54
54
  else
55
- msg(banner)
55
+ err(opt_parser)
56
56
  1
57
57
  end
58
58
  end
@@ -18,12 +18,15 @@
18
18
  require 'chef-dk/command/base'
19
19
  require 'chef-dk/ui'
20
20
  require 'chef-dk/policyfile_services/install'
21
+ require 'chef-dk/configurable'
21
22
 
22
23
  module ChefDK
23
24
  module Command
24
25
 
25
26
  class Install < Base
26
27
 
28
+ include Configurable
29
+
27
30
  banner(<<-E)
28
31
  Usage: chef install [ POLICY_FILE ] [options]
29
32
 
@@ -34,8 +37,7 @@ lockfile to install the locked cookbooks on another machine. You can also push
34
37
  the lockfile to a "policy group" on a Chef Server and apply that exact set of
35
38
  cookbooks to nodes in your infrastructure.
36
39
 
37
- The Policyfile feature is incomplete and beta quality. See our detailed README
38
- for more information.
40
+ See our detailed README for more information:
39
41
 
40
42
  https://github.com/opscode/chef-dk/blob/master/POLICYFILE_README.md
41
43
 
@@ -43,6 +45,11 @@ Options:
43
45
 
44
46
  E
45
47
 
48
+ option :config_file,
49
+ short: "-c CONFIG_FILE",
50
+ long: "--config CONFIG_FILE",
51
+ description: "Path to configuration file"
52
+
46
53
  option :debug,
47
54
  short: "-D",
48
55
  long: "--debug",
@@ -62,7 +69,12 @@ E
62
69
  end
63
70
 
64
71
  def run(params = [])
65
- apply_params!(params)
72
+ return 1 unless apply_params!(params)
73
+ # Force config file to be loaded. We don't use the configuration
74
+ # directly, but the user may have SSL configuration options that they
75
+ # need to talk to a private supermarket (e.g., trusted_certs or
76
+ # ssl_verify_mode)
77
+ chef_config
66
78
  installer.run
67
79
  0
68
80
  rescue PolicyfileServiceError => e
@@ -78,6 +90,10 @@ E
78
90
  !!config[:debug]
79
91
  end
80
92
 
93
+ def config_path
94
+ config[:config_file]
95
+ end
96
+
81
97
  def handle_error(error)
82
98
  ui.err("Error: #{error.message}")
83
99
  if error.respond_to?(:reason)
@@ -91,10 +107,11 @@ E
91
107
  def apply_params!(params)
92
108
  remaining_args = parse_options(params)
93
109
  if remaining_args.size > 1
94
- ui.err(banner)
95
- return 1
110
+ ui.err(opt_parser)
111
+ return false
96
112
  else
97
113
  @policyfile_relative_path = remaining_args.first
114
+ true
98
115
  end
99
116
  end
100
117
 
@@ -130,10 +130,6 @@ before converging the machine(s) defined in the provision cookbook.
130
130
  In the third form of the command, `chef provision` expects to create machines
131
131
  that will not operate in policyfile mode.
132
132
 
133
- Note that this command is considered beta. Behavior, the APIs that pass CLI
134
- data to chef-client, and argument names may change as more experience is gained
135
- from real-world usage.
136
-
137
133
  Chef Provisioning is documented at https://docs.chef.io/provisioning.html
138
134
 
139
135
  Options:
@@ -35,8 +35,7 @@ with all the cookbooks contained in the policy lock. The policy lock is applied
35
35
  to a specific POLICY_GROUP, which is a set of nodes that share the same
36
36
  run_list and cookbooks.
37
37
 
38
- The Policyfile feature is incomplete and beta quality. See our detailed README
39
- for more information.
38
+ See our detailed README for more information:
40
39
 
41
40
  https://github.com/opscode/chef-dk/blob/master/POLICYFILE_README.md
42
41
 
@@ -15,10 +15,29 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
+ require 'erb'
19
+
20
+ require 'chef-dk/commands_map'
21
+ require 'chef-dk/builtin_commands'
18
22
  require 'chef-dk/command/base'
19
23
  require 'mixlib/shellout'
20
24
 
21
25
  module ChefDK
26
+
27
+ class ShellCompletionTemplateContext
28
+
29
+ def commands
30
+ ChefDK.commands_map.command_specs.inject({}) do |cmd_info, (_key, cmd_spec)|
31
+ cmd_info[cmd_spec.name] = cmd_spec.description
32
+ cmd_info
33
+ end
34
+ end
35
+
36
+ def get_binding
37
+ binding
38
+ end
39
+ end
40
+
22
41
  module Command
23
42
  class ShellInit < ChefDK::Command::Base
24
43
 
@@ -56,6 +75,11 @@ HELP
56
75
  :long => "--omnibus-dir OMNIBUS_DIR",
57
76
  :description => "Alternate path to omnibus install (used for testing)"
58
77
 
78
+ def initialize
79
+ super
80
+ @shell_completion_template_context = nil
81
+ end
82
+
59
83
  def omnibus_root
60
84
  config[:omnibus_dir] || super
61
85
  end
@@ -81,9 +105,46 @@ HELP
81
105
  env.each do |var_name, value|
82
106
  export(shell_name, var_name, value)
83
107
  end
108
+
109
+ emit_shell_cmd(completion_for(shell_name))
84
110
  0
85
111
  end
86
112
 
113
+ def emit_shell_cmd(cmd)
114
+ msg(cmd) unless cmd.empty?
115
+ end
116
+
117
+ def completion_for(shell)
118
+ return "" unless (completion_template_basename = completion_template_for(shell))
119
+ completion_template_path = expand_completion_template_path(completion_template_basename)
120
+ erb = ERB.new(File.read(completion_template_path), nil, '-')
121
+ context_binding = shell_completion_template_context.get_binding
122
+ erb.result(context_binding)
123
+ end
124
+
125
+ def completion_template_for(shell)
126
+ case shell
127
+ when "bash"
128
+ "bash.sh.erb"
129
+ when "fish"
130
+ "chef.fish.erb"
131
+ when "zsh"
132
+ "zsh.zsh.erb"
133
+ else
134
+ # Pull requests accepted!
135
+ nil
136
+ end
137
+
138
+ end
139
+
140
+ def expand_completion_template_path(basename)
141
+ File.join(File.expand_path("../../completions", __FILE__), basename)
142
+ end
143
+
144
+ def shell_completion_template_context
145
+ @shell_completion_template_context ||= ShellCompletionTemplateContext.new
146
+ end
147
+
87
148
  def export(shell, var, val)
88
149
  case shell
89
150
  when 'sh', 'bash', 'zsh'
@@ -96,7 +157,7 @@ HELP
96
157
  end
97
158
 
98
159
  def posix_shell_export(var, val)
99
- msg(%Q(export #{var}="#{val}"))
160
+ emit_shell_cmd(%Q(export #{var}="#{val}"))
100
161
  end
101
162
 
102
163
  def fish_shell_export(var, val)
@@ -105,17 +166,15 @@ HELP
105
166
  # /dev/null to avoid Fish's helpful warnings about nonexistent
106
167
  # PATH elements.
107
168
  if var == 'PATH'
108
- msg(%Q(set -gx #{var} "#{val.split(':').join('" "')}" 2>/dev/null;))
169
+ emit_shell_cmd(%Q(set -gx #{var} "#{val.split(':').join('" "')}" 2>/dev/null;))
109
170
  else
110
- msg(%Q(set -gx #{var} "#{val}";))
171
+ emit_shell_cmd(%Q(set -gx #{var} "#{val}";))
111
172
  end
112
173
  end
113
174
 
114
175
  def powershell_export(var, val)
115
- msg(%Q($env:#{var}="#{val}"))
176
+ emit_shell_cmd(%Q($env:#{var}="#{val}"))
116
177
  end
117
178
  end
118
179
  end
119
180
  end
120
-
121
-
@@ -38,8 +38,7 @@ When both POLICY_NAME and POLICY_GROUP are given, the command shows the content
38
38
  of a the active policyfile lock for the given POLICY_GROUP. See also the `diff`
39
39
  command.
40
40
 
41
- The Policyfile feature is incomplete and beta quality. See our detailed README
42
- for more information.
41
+ See our detailed README for more information:
43
42
 
44
43
  https://github.com/opscode/chef-dk/blob/master/POLICYFILE_README.md
45
44
 
@@ -0,0 +1,155 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2015 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef-dk/command/base'
19
+ require 'chef-dk/ui'
20
+ require 'chef-dk/configurable'
21
+ require 'chef-dk/policyfile_services/undelete'
22
+
23
+ module ChefDK
24
+ module Command
25
+
26
+ class Undelete < Base
27
+
28
+ banner(<<-BANNER)
29
+ Usage: chef undelete [--list | --id ID] [options]
30
+
31
+ `chef undelete` helps you recover quickly if you've deleted a policy or policy
32
+ group in error. When run with no arguements, it lists the available undo
33
+ operations. To undo the last delete operation, use `chef undelete --last`.
34
+
35
+ CAVEATS:
36
+ `chef undelete` doesn't detect conflicts. If a deleted item has been recreated,
37
+ running `chef undelete` will overwrite it.
38
+
39
+ Undo information does not include cookbooks that might be referenced by
40
+ policies. If you have cleaned the policy cookbooks after the delete operation
41
+ you want to reverse, `chef undelete` may not be able to fully restore the
42
+ previous state.
43
+
44
+ The delete commands also do not store access control data, so you may have to
45
+ manually reapply any ACL customizations you have made.
46
+
47
+ See our detailed README for more information:
48
+
49
+ https://github.com/opscode/chef-dk/blob/master/POLICYFILE_README.md
50
+
51
+ Options:
52
+
53
+ BANNER
54
+
55
+ option :undo_last,
56
+ short: "-l",
57
+ long: "--last",
58
+ description: "Undo the most recent delete operation"
59
+
60
+ option :undo_record_id,
61
+ short: "-i ID",
62
+ long: "--id ID",
63
+ description: "Undo the delete operation with the given ID"
64
+
65
+ option :config_file,
66
+ short: "-c CONFIG_FILE",
67
+ long: "--config CONFIG_FILE",
68
+ description: "Path to configuration file"
69
+
70
+ option :debug,
71
+ short: "-D",
72
+ long: "--debug",
73
+ description: "Enable stacktraces and other debug output",
74
+ default: false
75
+
76
+ include Configurable
77
+
78
+ attr_accessor :ui
79
+
80
+ attr_reader :undo_record_id
81
+
82
+ def initialize(*args)
83
+ super
84
+ @list_undo_records = false
85
+ @undo_record_id = nil
86
+ @ui = UI.new
87
+ end
88
+
89
+ def run(params)
90
+ return 1 unless apply_params!(params)
91
+ if list_undo_records?
92
+ undelete_service.list
93
+ else
94
+ undelete_service.run
95
+ end
96
+ 0
97
+ rescue PolicyfileServiceError => e
98
+ handle_error(e)
99
+ 1
100
+ end
101
+
102
+ def undelete_service
103
+ @undelete_service ||=
104
+ PolicyfileServices::Undelete.new(config: chef_config,
105
+ ui: ui,
106
+ undo_record_id: undo_record_id)
107
+ end
108
+
109
+ def debug?
110
+ !!config[:debug]
111
+ end
112
+
113
+ def list_undo_records?
114
+ @list_undo_records
115
+ end
116
+
117
+ def handle_error(error)
118
+ ui.err("Error: #{error.message}")
119
+ if error.respond_to?(:reason)
120
+ ui.err("Reason: #{error.reason}")
121
+ ui.err("")
122
+ ui.err(error.extended_error_info) if debug?
123
+ ui.err(error.cause.backtrace.join("\n")) if debug?
124
+ end
125
+ end
126
+
127
+ def apply_params!(params)
128
+ remaining_args = parse_options(params)
129
+
130
+ if !remaining_args.empty?
131
+ ui.err("Too many arguments")
132
+ ui.err("")
133
+ ui.err(opt_parser)
134
+ false
135
+ elsif config[:undo_record_id].nil? && config[:undo_last].nil?
136
+ @list_undo_records = true
137
+ true
138
+ elsif config[:undo_record_id] && config[:undo_last]
139
+ ui.err("Error: options --last and --id cannot both be given.")
140
+ ui.err("")
141
+ ui.err(opt_parser)
142
+ false
143
+ elsif config[:undo_record_id]
144
+ @undo_record_id = config[:undo_record_id]
145
+ true
146
+ elsif config[:undo_last]
147
+ @undo_record_id = nil
148
+ true
149
+ end
150
+ end
151
+
152
+ end
153
+ end
154
+ end
155
+