Skip to content
This repository has been archived by the owner on Jul 14, 2021. It is now read-only.

chef clean-policy-revisions command #491

Merged
merged 2 commits into from
Aug 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/chef-dk/builtin_commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@

c.builtin "export", :Export, desc: "Export a policy lock as a Chef Zero code repo"

c.builtin "clean-policy-revisions", :CleanPolicyRevisions, desc: "Delete unused policy revisions on the server"

c.builtin "delete-policy-group", :DeletePolicyGroup, desc: "Delete a policy group on the server"

c.builtin "undelete", :Undelete, desc: "Undo a delete command"
Expand Down
114 changes: 114 additions & 0 deletions lib/chef-dk/command/clean_policy_revisions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#
# Copyright:: Copyright (c) 2015 Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'chef-dk/command/base'
require 'chef-dk/ui'
require 'chef-dk/configurable'
require 'chef-dk/policyfile_services/clean_policies'

module ChefDK
module Command


class CleanPolicyRevisions < Base

banner(<<-BANNER)
Usage: chef clean-policy-revisions [options]

`chef clean-policy-revisions` deletes orphaned policyfile revisions from the Chef
Server. Orphaned policyfile revisions are not associated to any group, and
therefore not in active use by any nodes. To list orphaned policyfile revisions
before deleting them, use `chef show-policy --orphans`.

The Policyfile feature is incomplete and beta quality. See our detailed README
for more information.

https://github.com/opscode/chef-dk/blob/master/POLICYFILE_README.md

Options:

BANNER

option :config_file,
short: "-c CONFIG_FILE",
long: "--config CONFIG_FILE",
description: "Path to configuration file"

option :debug,
short: "-D",
long: "--debug",
description: "Enable stacktraces and other debug output",
default: false

include Configurable

attr_accessor :ui

attr_reader :policy_name

attr_reader :policy_group

def initialize(*args)
super
@ui = UI.new
end

def run(params)
return 1 unless apply_params!(params)
clean_policies_service.run
0
rescue PolicyfileServiceError => e
handle_error(e)
1
end

def clean_policies_service
@policy_list_service ||=
PolicyfileServices::CleanPolicies.new(config: chef_config, ui: ui)
end

def debug?
!!config[:debug]
end

def handle_error(error)
ui.err("Error: #{error.message}")
if error.respond_to?(:reason)
ui.err("Reason: #{error.reason}")
ui.err("")
ui.err(error.extended_error_info) if debug?
ui.err(error.cause.backtrace.join("\n")) if debug?
end
end

def apply_params!(params)
remaining_args = parse_options(params)

if !remaining_args.empty?
ui.err("Too many arguments")
ui.err("")
ui.err(opt_parser)
false
else
true
end
end

end
end
end

2 changes: 2 additions & 0 deletions lib/chef-dk/exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class CantUndo < StandardError
class UndoRecordNotFound < StandardError
end

class MultipleErrors < StandardError
end

class BUG < RuntimeError
end
Expand Down
9 changes: 5 additions & 4 deletions lib/chef-dk/policyfile_services/clean_policies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# limitations under the License.
#

require 'chef-dk/exceptions'
require 'chef-dk/service_exceptions'
require 'chef-dk/policyfile/lister'

Expand Down Expand Up @@ -53,7 +54,7 @@ def run

message = "Failed to delete some policy revisions:\n" + details.join("\n") + "\n"

raise PolicyfileCleanError.new(message, nil)
raise PolicyfileCleanError.new(message, MultipleErrors.new("multiple errors"))
end

true
Expand All @@ -74,9 +75,9 @@ def policy_lister
end

def http_client
@http_client ||= ChefDK::AuthenticatedHTTP.new(config.chef_server_url,
signing_key_filename: config.client_key,
client_name: config.node_name)
@http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
signing_key_filename: chef_config.client_key,
client_name: chef_config.node_name)
end

private
Expand Down
181 changes: 181 additions & 0 deletions spec/unit/command/clean_policy_revisions_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#
# Copyright:: Copyright (c) 2015 Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'spec_helper'
require 'shared/command_with_ui_object'
require 'chef-dk/command/clean_policy_revisions'

describe ChefDK::Command::CleanPolicyRevisions do

it_behaves_like "a command with a UI object"

subject(:command) do
described_class.new
end

let(:clean_policies_service) { command.clean_policies_service }

let(:chef_config_loader) { instance_double("Chef::WorkstationConfigLoader") }

let(:chef_config) { double("Chef::Config") }

# nil means the config loader will do the default path lookup
let(:config_arg) { nil }

before do
stub_const("Chef::Config", chef_config)
allow(Chef::WorkstationConfigLoader).to receive(:new).with(config_arg).and_return(chef_config_loader)
end

describe "parsing args and options" do
let(:params) { [] }

before do
command.apply_params!(params)
end

context "when given a path to the config" do

let(:params) { %w[ -c ~/otherstuff/config.rb ] }

let(:config_arg) { "~/otherstuff/config.rb" }

before do
expect(chef_config_loader).to receive(:load)
end

it "reads the chef/knife config" do
expect(Chef::WorkstationConfigLoader).to receive(:new).with(config_arg).and_return(chef_config_loader)
expect(command.chef_config).to eq(chef_config)
expect(clean_policies_service.chef_config).to eq(chef_config)
end

end

describe "settings that require loading chef config" do

before do
allow(chef_config_loader).to receive(:load)
end

context "with no params" do

it "disables debug by default" do
expect(command.debug?).to be(false)
end

end

context "when debug mode is set" do

let(:params) { [ "-D" ] }

it "enables debug" do
expect(command.debug?).to be(true)
end

end

end

end

describe "running the command" do

let(:ui) { TestHelpers::TestUI.new }

before do
allow(chef_config_loader).to receive(:load)
command.ui = ui
end

context "when given too many arguments" do

let(:params) { %w[ wut-is-this ] }

it "shows usage and exits" do
expect(command.run(params)).to eq(1)
end

end

context "when the clean policies service raises an exception" do

let(:backtrace) { caller[0...3] }

let(:cause) do
e = StandardError.new("some operation failed")
e.set_backtrace(backtrace)
e
end

let(:exception) do
ChefDK::PolicyfileCleanError.new("Failed to delete some policy revisions.", cause)
end

before do
allow(clean_policies_service).to receive(:run).and_raise(exception)
end

it "prints a debugging message and exits non-zero" do
expect(command.run([])).to eq(1)

expected_output=<<-E
Error: Failed to delete some policy revisions.
Reason: (StandardError) some operation failed

E

expect(ui.output).to eq(expected_output)
end

context "when debug is enabled" do

it "includes the backtrace in the error" do

command.run(%w[ -D ])

expected_output=<<-E
Error: Failed to delete some policy revisions.
Reason: (StandardError) some operation failed


E
expected_output << backtrace.join("\n") << "\n"

expect(ui.output).to eq(expected_output)
end

end

end

context "when the clean policies service executes successfully" do

before do
expect(clean_policies_service).to receive(:run)
end

it "exits 0" do
expect(command.run([])).to eq(0)
end

end

end
end