forked from thbishop/knife-solo_data_bag
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
179 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
module KnifeSoloDataBag | ||
|
||
class SoloDataBagEdit < Chef::Knife | ||
|
||
require 'chef/knife/helpers' | ||
|
||
include KnifeSoloDataBag::Helpers | ||
|
||
banner 'knife solo data bag edit BAG ITEM (options)' | ||
category 'solo data bag' | ||
|
||
attr_reader :bag_name, :item_name | ||
|
||
option :secret, | ||
:short => '-s SECRET', | ||
:long => '--secret SECRET', | ||
:description => 'The secret key to use to encrypt data bag item values' | ||
|
||
option :secret_file, | ||
:long => '--secret-file SECRET_FILE', | ||
:description => 'A file containing the secret key to use to encrypt data bag item values' | ||
|
||
def edit_content | ||
updated_content = edit_data existing_bag_item_content | ||
item = Chef::DataBagItem.from_hash format_editted_content(updated_content) | ||
item.data_bag bag_name | ||
persist_bag_item item | ||
end | ||
|
||
def existing_bag_item_content | ||
content = Chef::DataBagItem.load(bag_name, item_name) | ||
|
||
return content unless should_be_encrypted? | ||
Chef::EncryptedDataBagItem.new(content, secret_key).to_hash | ||
end | ||
|
||
def format_editted_content(content) | ||
return content unless should_be_encrypted? | ||
Chef::EncryptedDataBagItem.encrypt_data_bag_item content, secret_key | ||
end | ||
|
||
def run | ||
Chef::Config[:solo] = true | ||
@bag_name, @item_name = @name_args | ||
ensure_valid_arguments | ||
edit_content | ||
end | ||
|
||
def ensure_valid_arguments | ||
validate_bag_name_provided | ||
validate_item_name_provided | ||
validate_bags_path_exists | ||
validate_multiple_secrets_were_not_provided | ||
end | ||
|
||
def persist_bag_item(item) | ||
File.open bag_item_path, 'w' do |f| | ||
f.write item.to_json | ||
end | ||
end | ||
|
||
def validate_item_name_provided | ||
unless item_name | ||
show_usage | ||
ui.fatal 'You must supply a name for the item' | ||
exit 1 | ||
end | ||
end | ||
|
||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 3 additions & 2 deletions
5
spec/contexts/secret_string_and_secret_file_are_both_provided.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
require 'spec_helper' | ||
|
||
describe KnifeSoloDataBag::SoloDataBagEdit do | ||
before do | ||
@knife = subject | ||
end | ||
|
||
include_context 'stubbed_out_stdout_and_stderr' | ||
|
||
describe 'run' do | ||
include_context 'bag_name_not_provided' | ||
include_context 'bag_path_is_not_valid', ['foo'] | ||
include_context 'secret_string_and_secret_file_are_both_provided', ['bar'] | ||
|
||
context 'when an item name is not provided' do | ||
before do | ||
@knife.name_args = ['bag_1'] | ||
end | ||
|
||
it 'should exit with an error message' do | ||
lambda { | ||
@knife.run | ||
}.should raise_error SystemExit | ||
@stdout.string.should match /usage/i | ||
@stderr.string.should match /name for the item/ | ||
end | ||
end | ||
|
||
context 'with valid arguments' do | ||
before do | ||
@bags_path = '/var/chef/data_bags' | ||
@bag_path = "#{@bags_path}/bag_1" | ||
@item_path = "#{@bag_path}/foo.json" | ||
@knife.name_args = ['bag_1', 'foo'] | ||
@orig_data = {'id' => 'foo', 'who' => 'bob'} | ||
@updated_data = {'id' => 'foo', 'who' => 'sue'} | ||
@bag_item_foo = Chef::DataBagItem.from_hash @orig_data | ||
@bag_item_foo.data_bag 'bag_1' | ||
@updated_bag_item = Chef::DataBagItem.from_hash @updated_data | ||
@updated_bag_item.data_bag 'bag_1' | ||
|
||
FakeFS.activate! | ||
FileUtils.mkdir_p @bag_path | ||
|
||
Chef::DataBagItem.should_receive(:load).with('bag_1', 'foo'). | ||
and_return(@bag_item_foo) | ||
@knife.stub(:edit_data).and_return(@updated_data) | ||
Chef::Config[:data_bag_path] = @bags_path | ||
end | ||
|
||
after do | ||
FakeFS.deactivate! | ||
FakeFS::FileSystem.clear | ||
end | ||
|
||
it 'should edit the data bag item' do | ||
@knife.run | ||
JSON.parse(File.read(@item_path)).raw_data.should == @updated_data | ||
end | ||
|
||
context 'when encrypting with -s or --secret' do | ||
before do | ||
@knife.config[:secret] = 'secret_key' | ||
Chef::EncryptedDataBagItem.should_receive(:new). | ||
with(@bag_item_foo, 'secret_key'). | ||
and_return(@updated_data) | ||
end | ||
|
||
it 'should edit the encrypted data bag item' do | ||
@knife.run | ||
content = JSON.parse(File.read(@item_path)).raw_data | ||
content['who'].should_not == @orig_data['who'] | ||
content['who'].should_not be_nil | ||
end | ||
end | ||
|
||
context 'when encrypting with --secret-file' do | ||
before do | ||
@secret_path = '/var/chef/secret.txt' | ||
@knife.config[:secret_file] = @secret_path | ||
Chef::EncryptedDataBagItem.stub(:load_secret). | ||
with(@secret_path). | ||
and_return('psst') | ||
Chef::EncryptedDataBagItem.should_receive(:new). | ||
with(@bag_item_foo, 'psst'). | ||
and_return(@updated_data) | ||
end | ||
|
||
it 'should edit the encrypted data bag item' do | ||
@knife.run | ||
content = JSON.parse(File.read(@item_path)).raw_data | ||
content['who'].should_not == @orig_data['who'] | ||
content['who'].should_not be_nil | ||
end | ||
end | ||
|
||
end | ||
|
||
end | ||
|
||
end |