berkshelf 0.6.0.beta4 → 1.0.0.rc1

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.
@@ -1,31 +1,46 @@
1
+ require 'chozo/config'
2
+
1
3
  module Berkshelf
2
4
  # @author Justin Campbell <justin@justincampbell.me>
3
- class Config < Hashie::Mash
4
- DEFAULT_PATH = "~/.berkshelf/config.json"
5
-
6
- include ActiveModel::Validations
7
- validates_with ConfigValidator
5
+ # @author Jamie Winsor <jamie@vialstudios.com>
6
+ class Config < Chozo::Config::JSON
7
+ FILENAME = "config.json".freeze
8
8
 
9
9
  class << self
10
- # @return [String, nil]
11
- # the contents of the file
12
- def file
13
- File.read path if File.exists? path
10
+ attr_writer :path
11
+
12
+ # @return [String]
13
+ def path
14
+ File.join(Berkshelf.berkshelf_path, FILENAME)
14
15
  end
15
16
 
16
- # @param [#to_s] json
17
- #
18
- # @return [Config]
19
- def from_json(json)
20
- hash = JSON.parse(json).to_hash
17
+ # @return [String]
18
+ def chef_config_path
19
+ @chef_config_path ||= File.expand_path(ENV["BERKSHELF_CHEF_CONFIG"] || "~/.chef/knife.rb")
20
+ end
21
21
 
22
- new.tap do |config|
23
- hash.each do |key, value|
24
- config[key] = value
25
- end
22
+ # @param [String] value
23
+ def chef_config_path=(value)
24
+ @chef_config = nil
25
+ @chef_config_path = value
26
+ end
27
+
28
+ # @return [Chef::Config]
29
+ def chef_config
30
+ @chef_config ||= begin
31
+ Chef::Config.from_file(File.expand_path(chef_config_path))
32
+ Chef::Config
33
+ rescue
34
+ Chef::Config
26
35
  end
27
36
  end
28
37
 
38
+ # @return [String, nil]
39
+ # the contents of the file
40
+ def file
41
+ File.read(path) if File.exists?(path)
42
+ end
43
+
29
44
  # @return [Config]
30
45
  def instance
31
46
  @instance ||= if file
@@ -34,18 +49,52 @@ module Berkshelf
34
49
  new
35
50
  end
36
51
  end
37
-
38
- # @return [String]
39
- def path
40
- File.expand_path DEFAULT_PATH
41
- end
42
52
  end
43
53
 
44
- # @param [String, Symbol] key
45
- #
46
- # @return [Config, Object]
47
- def [](key)
48
- super or self.class.new
54
+ # @param [String] path
55
+ # @param [Hash] options
56
+ # @see {Chozo::Config::JSON}
57
+ def initialize(path = self.class.path, options = {})
58
+ super(path, options)
49
59
  end
60
+
61
+ attribute 'chef.chef_server_url',
62
+ type: String,
63
+ default: chef_config[:chef_server_url]
64
+ attribute 'chef.validation_client_name',
65
+ type: String,
66
+ default: chef_config[:validation_client_name]
67
+ attribute 'chef.validation_key_path',
68
+ type: String,
69
+ default: chef_config[:validation_key]
70
+ attribute 'chef.client_key',
71
+ type: String,
72
+ default: chef_config[:client_key]
73
+ attribute 'chef.node_name',
74
+ type: String,
75
+ default: chef_config[:node_name]
76
+ attribute 'vagrant.vm.box',
77
+ type: String,
78
+ default: 'Berkshelf-CentOS-6.3-x86_64-minimal',
79
+ required: true
80
+ attribute 'vagrant.vm.box_url',
81
+ type: String,
82
+ default: 'https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box',
83
+ required: true
84
+ attribute 'vagrant.vm.forward_port',
85
+ type: Hash,
86
+ default: Hash.new
87
+ attribute 'vagrant.vm.network.bridged',
88
+ type: Boolean,
89
+ default: true
90
+ attribute 'vagrant.vm.network.hostonly',
91
+ type: String,
92
+ default: '33.33.33.10'
93
+ attribute 'vagrant.vm.provision',
94
+ type: String,
95
+ default: 'chef_solo'
96
+ attribute 'ssl.verify',
97
+ type: Boolean,
98
+ default: true
50
99
  end
51
100
  end
@@ -41,7 +41,7 @@ module Berkshelf
41
41
  class NoSolution < BerkshelfError; status_code(106); end
42
42
  class CookbookSyntaxError < BerkshelfError; status_code(107); end
43
43
  class UploadFailure < BerkshelfError; status_code(108); end
44
- class KnifeConfigNotFound < BerkshelfError; status_code(109); end
44
+ class BerksConfigNotFound < BerkshelfError; status_code(109); end
45
45
 
46
46
  class InvalidGitURI < BerkshelfError
47
47
  status_code(110)
@@ -91,7 +91,7 @@ module Berkshelf
91
91
  def to_s
92
92
  strings = ["Invalid configuration:"]
93
93
 
94
- @errors.messages.each do |key, errors|
94
+ @errors.each do |key, errors|
95
95
  errors.each do |error|
96
96
  strings << " #{key} #{error}"
97
97
  end
@@ -100,4 +100,7 @@ module Berkshelf
100
100
  strings.join "\n"
101
101
  end
102
102
  end
103
+
104
+ class ConfigExists < BerkshelfError; status_code(116); end
105
+ class ConfigurationError < BerkshelfError; status_code(117); end
103
106
  end
@@ -86,9 +86,9 @@ module Berkshelf
86
86
  # @param [Hash] options
87
87
  #
88
88
  # @option options [String, Symbol] :chef_api
89
- # a URL to a Chef API. Alternatively the symbol :knife can be provided
89
+ # a URL to a Chef API. Alternatively the symbol :config can be provided
90
90
  # which will instantiate this location with the values found in your
91
- # knife configuration.
91
+ # Berkshelf configuration.
92
92
  # @option options [String] :node_name
93
93
  # the name of the client to use to communicate with the Chef API.
94
94
  # Default: Chef::Config[:node_name]
@@ -100,17 +100,22 @@ module Berkshelf
100
100
  @version_constraint = version_constraint
101
101
  @downloaded_status = false
102
102
 
103
+ if options[:chef_api] == :knife
104
+ Berkshelf.formatter.deprecation "specifying 'chef_api :knife' is deprecated. Please use 'chef_api :config'."
105
+ options[:chef_api] = :config
106
+ end
107
+
103
108
  validate_options!(options)
104
109
 
105
- if options[:chef_api] == :knife
106
- begin
107
- Berkshelf.load_config
108
- rescue KnifeConfigNotFound => e
109
- raise KnifeConfigNotFound, "A Knife config is required when ':knife' is given for the value of a 'chef_api' location. #{e}"
110
+ if options[:chef_api] == :config
111
+ unless Berkshelf::Config.instance.chef.node_name.present? &&
112
+ Berkshelf::Config.instance.chef.client_key.present? &&
113
+ Berkshelf::Config.instance.chef.chef_server_url.present?
114
+ raise ConfigurationError, "A Berkshelf configuration is required with a 'chef.client_key', 'chef.chef_server_Url', and 'chef.node_name' setting to install or upload cookbooks using 'chef_api :config'."
110
115
  end
111
- @node_name = Chef::Config[:node_name]
112
- @client_key = Chef::Config[:client_key]
113
- @uri = Chef::Config[:chef_server_url]
116
+ @node_name = Berkshelf::Config.instance.chef.node_name
117
+ @client_key = Berkshelf::Config.instance.chef.client_key
118
+ @uri = Berkshelf::Config.instance.chef.chef_server_url
114
119
  else
115
120
  @node_name = options[:node_name]
116
121
  @client_key = options[:client_key]
@@ -250,7 +255,7 @@ module Berkshelf
250
255
  # @raise [InvalidChefAPILocation] if any of the options are missing or their values do not
251
256
  # pass validation
252
257
  def validate_options!(options)
253
- if options[:chef_api] == :knife
258
+ if options[:chef_api] == :config
254
259
  return true
255
260
  end
256
261
 
@@ -4,17 +4,13 @@ module Berkshelf
4
4
  # @author Jamie Winsor <jamie@vialstudios.com>
5
5
  # @author Andrew Garson <andrew.garson@gmail.com>
6
6
  class Install
7
- attr_reader :config
8
7
  attr_reader :shelf
9
8
  attr_reader :berksfile
10
9
 
11
10
  def initialize(app, env)
12
- @app = app
13
- @shelf = Berkshelf::Vagrant.shelf_for(env)
14
- @config = env[:vm].config.berkshelf
15
- Berkshelf.config_path = @config.config_path
16
- Berkshelf.load_config
17
- @berksfile = Berksfile.from_file(@config.berksfile_path)
11
+ @app = app
12
+ @shelf = Berkshelf::Vagrant.shelf_for(env)
13
+ @berksfile = Berksfile.from_file(env[:vm].config.berkshelf.berksfile_path)
18
14
  end
19
15
 
20
16
  def call(env)
@@ -32,7 +28,7 @@ module Berkshelf
32
28
  Berkshelf.formatter.msg "installing cookbooks..."
33
29
  opts = {
34
30
  path: self.shelf
35
- }.merge(self.config.to_hash).symbolize_keys!
31
+ }.merge(env[:vm].config.berkshelf.to_hash).symbolize_keys!
36
32
  berksfile.install(opts)
37
33
  end
38
34
 
@@ -4,16 +4,10 @@ module Berkshelf
4
4
  # @author Jamie Winsor <jamie@vialstudios.com>
5
5
  class Upload
6
6
  attr_reader :berksfile
7
- attr_reader :node_name
8
- attr_reader :client_key
9
- attr_reader :ssl_verify
10
7
 
11
8
  def initialize(app, env)
12
- @app = app
13
- @node_name = env[:vm].config.berkshelf.node_name
14
- @client_key = env[:vm].config.berkshelf.client_key
15
- @ssl_verify = env[:vm].config.berkshelf.ssl_verify
16
- @berksfile = Berksfile.from_file(env[:vm].config.berkshelf.berksfile_path)
9
+ @app = app
10
+ @berksfile = Berksfile.from_file(env[:vm].config.berkshelf.berksfile_path)
17
11
  end
18
12
 
19
13
  def call(env)
@@ -31,10 +25,10 @@ module Berkshelf
31
25
  Berkshelf.formatter.msg "uploading cookbooks to '#{provisioner.config.chef_server_url}'"
32
26
  berksfile.upload(
33
27
  server_url: provisioner.config.chef_server_url,
34
- client_name: self.node_name,
35
- client_key: self.client_key,
28
+ client_name: Berkshelf::Config.instance.chef.node_name,
29
+ client_key: Berkshelf::Config.instance.chef.client_key,
36
30
  ssl: {
37
- verify: self.ssl_verify
31
+ verify: Berkshelf::Config.instance.ssl.verify
38
32
  }
39
33
  )
40
34
  end
@@ -3,24 +3,10 @@ module Berkshelf
3
3
  # @author Jamie Winsor <jamie@vialstudios.com>
4
4
  # @author Andrew Garson <andrew.garson@gmail.com>
5
5
  class Config < ::Vagrant::Config::Base
6
- # @return [String]
7
- # path to a knife configuration file
8
- attr_reader :config_path
9
-
10
6
  # @return [String]
11
7
  # path to the Berksfile to use with Vagrant
12
8
  attr_reader :berksfile_path
13
9
 
14
- # @return [String]
15
- # A path to a client key on disk to use with the Chef Client provisioner to
16
- # upload cookbooks installed by Berkshelf.
17
- attr_reader :client_key
18
-
19
- # @return [String]
20
- # A client name (node_name) to use with the Chef Client provisioner to upload
21
- # cookbooks installed by Berkshelf.
22
- attr_accessor :node_name
23
-
24
10
  # @return [Array<Symbol>]
25
11
  # only cookbooks in these groups will be installed and copied to
26
12
  # Vagrant's shelf
@@ -30,16 +16,11 @@ module Berkshelf
30
16
  # cookbooks in all other groups except for these will be installed
31
17
  # and copied to Vagrant's shelf
32
18
  attr_accessor :except
33
- attr_accessor :ssl_verify
34
19
 
35
20
  def initialize
36
21
  @berksfile_path = File.join(Dir.pwd, Berkshelf::DEFAULT_FILENAME)
37
- @config_path = Berkshelf::DEFAULT_CONFIG
38
- @node_name = nil
39
- @client_key = nil
40
22
  @except = Array.new
41
23
  @only = Array.new
42
- @ssl_verify = true
43
24
  end
44
25
 
45
26
  # @param [String] value
@@ -47,11 +28,6 @@ module Berkshelf
47
28
  @berksfile_path = File.expand_path(value)
48
29
  end
49
30
 
50
- # @param [String] value
51
- def config_path=(value)
52
- @config_path = File.expand_path(value)
53
- end
54
-
55
31
  # @param [String] value
56
32
  def client_key=(value)
57
33
  @client_key = File.expand_path(value)
@@ -63,12 +39,12 @@ module Berkshelf
63
39
  end
64
40
 
65
41
  if Berkshelf::Vagrant.chef_client?(env.config.global)
66
- if node_name.nil?
67
- errors.add("A value for berkshelf.node_name is required when using the chef_client provisioner.")
42
+ if Berkshelf::Config.instance.chef.node_name.nil?
43
+ errors.add("A configuration must be set for chef.node_name when using the chef_client provisioner. Run 'berks configure' or edit your configuration.")
68
44
  end
69
45
 
70
- if client_key.nil?
71
- errors.add("A value for berkshelf.client_key is required when using the chef_client provisioner.")
46
+ if Berkshelf::Config.instance.chef.client_key.nil?
47
+ errors.add("A configuration must be set for chef.client_key when using the chef_client provisioner. Run 'berks configure' or edit your configuration.")
72
48
  end
73
49
  end
74
50
  end
@@ -1,3 +1,3 @@
1
1
  module Berkshelf
2
- VERSION = "0.6.0.beta4"
2
+ VERSION = "1.0.0.rc1"
3
3
  end
@@ -1,91 +1,51 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::Config do
4
- subject { config }
5
-
6
- let(:config) { klass.new }
7
4
  let(:klass) { described_class }
8
5
 
9
- it { should be_valid }
10
-
11
- its(:present?) { should be_false }
12
-
13
- it "set and gets hash keys" do
14
- config[:a] = 1
15
- config[:a].should == 1
16
- end
6
+ describe "ClassMethods" do
7
+ subject { klass }
17
8
 
18
- it "does not raise an error for nested hash keys that have not been set" do
19
- config[:d][:e]
20
- end
9
+ describe "::file" do
10
+ subject { klass.file }
21
11
 
22
- it "has indifferent access" do
23
- config[:a] = 1
24
- config['b'] = 2
12
+ context "when the file does not exist" do
13
+ before :each do
14
+ File.stub exists?: false
15
+ end
25
16
 
26
- config['a'].should == 1
27
- config[:b].should == 2
28
- end
29
-
30
- describe ".file" do
31
- subject { klass.file }
32
-
33
- context "when the file does not exist" do
34
- before :each do
35
- File.stub exists?: false
17
+ it { should be_nil }
36
18
  end
37
-
38
- it { should be_nil }
39
19
  end
40
- end
41
-
42
- describe ".from_json" do
43
- subject(:config) { klass.from_json json }
44
20
 
45
- let(:json) {
46
- <<-JSON
47
- {
48
- "a": 1,
49
- "b": {
50
- "c": 2
51
- }
52
- }
53
- JSON
54
- }
21
+ describe "::instance" do
22
+ subject { klass.instance }
55
23
 
56
- it "has data" do
57
- config[:a].should == 1
24
+ it { should be_a klass }
58
25
  end
59
26
 
60
- it "has nested data" do
61
- config[:b][:c].should == 2
62
- end
63
-
64
- it "does not raise an error for nested hash keys that have not been set" do
65
- config[:d][:e]
66
- end
27
+ describe "::path" do
28
+ subject { klass.path }
67
29
 
68
- it "has indifferent access" do
69
- config['a'].should == 1
70
- config[:a].should == 1
71
- end
30
+ it { should be_a String }
72
31
 
73
- context "with an invalid configuration" do
74
- let(:json) { '{ "wat": 1 }' }
32
+ it "points to a location within ENV['BERKSHELF_PATH']" do
33
+ ENV.stub(:[]).with('BERKSHELF_PATH').and_return('/tmp')
75
34
 
76
- it { should_not be_valid }
35
+ subject.should eql("/tmp/config.json")
36
+ end
77
37
  end
78
- end
79
38
 
80
- describe ".instance" do
81
- subject { klass.instance }
82
-
83
- it { should be_a klass }
84
- end
39
+ describe "::chef_config" do
40
+ it "returns the Chef::Config" do
41
+ subject.chef_config.should eql(Chef::Config)
42
+ end
43
+ end
85
44
 
86
- describe ".path" do
87
- subject { klass.path }
45
+ describe "::chef_config_path" do
46
+ subject { klass.chef_config_path }
88
47
 
89
- it { should be_a String }
48
+ it { should be_a String }
49
+ end
90
50
  end
91
51
  end