Skip to content

Commit

Permalink
first pass at edit
Browse files Browse the repository at this point in the history
  • Loading branch information
thbishop committed May 16, 2012
1 parent 2393d37 commit 9800d9b
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 3 deletions.
72 changes: 72 additions & 0 deletions lib/chef/knife/solo_data_bag_edit.rb
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
1 change: 1 addition & 0 deletions lib/knife-solo_data_bag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'chef/knife'
require 'chef/knife/helpers'
require 'chef/knife/solo_data_bag_create'
require 'chef/knife/solo_data_bag_edit'
require 'chef/knife/solo_data_bag_show'
require 'knife-solo_data_bag/version'

Expand Down
3 changes: 2 additions & 1 deletion spec/contexts/bag_path_is_not_valid.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
shared_context 'bag_path_is_not_valid' do
shared_context 'bag_path_is_not_valid' do |args|
context 'when the data bag path is not valid' do
before do
File.stub(:directory?).and_return(false)
@knife.name_args = ['foo']
@knife.name_args.concat Array(args)
end

it 'should raise an invalid data bag path exception' do
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
shared_context 'secret_string_and_secret_file_are_both_provided' do
shared_context 'secret_string_and_secret_file_are_both_provided' do |args|
context 'when specifying -s and --secret-file' do
before do
@knife.name_args = 'foo'
@knife.name_args = ['foo']
@knife.name_args.concat Array(args)
@knife.config[:secret] = 'foobar'
@knife.config[:secret_file] = 'secret.txt'
File.stub(:directory?).and_return(true)
Expand Down
101 changes: 101 additions & 0 deletions spec/unit/solo_data_bag_edit_spec.rb
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

0 comments on commit 9800d9b

Please sign in to comment.