batali 0.2.12 → 0.2.14

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa18c8e69b93424e57b8317616ce7724cb9978ef
4
- data.tar.gz: 7f1399c6617d115a1d80150e955872c90ea7bcce
3
+ metadata.gz: 6a858775a739465f30069ecf5ce22dee5b8e1a24
4
+ data.tar.gz: 59eb2bf5517829257bbdd9d2b9afacca2633fded
5
5
  SHA512:
6
- metadata.gz: ab46ecf666ecb4e50e8a235cfb67eb5b6288d4e0b0292854eb6ca6252b5abc54ca3ed1bcc1091962f9d96d53768bc51812fdef57e10e5ab2996c8803f7d4196b
7
- data.tar.gz: ab32f312eade8efe395430641ae97539fe05e21b255b8a27149a19e946a4b7c00ae04c58615f17f1e8e81b29125aa771e211e88d68fdcb4f808eba66875f51e8
6
+ metadata.gz: ebd131450fdb5ba57f570f89795663f912c44237b04609576ed44890ffbe54623e8b65fcbb3b355ddb98d2c4c95c8bcf82c7c7244b3ca987b56d6741a40671dc
7
+ data.tar.gz: 4e2daaec6765cd360e821978e717e50b45cc98a3badf9b30e66952508da359e16729f927827f777ba9b7f8b7c8bc3c35c887402ffabcf961c612b228f8747742
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ # v0.2.14
2
+ * Add support for using the Chef Server as a source
3
+
1
4
  # v0.2.12
2
5
  * Update home directory path generation to use `Dir.home`
3
6
  * Detect resolution type from manifest files
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ ![Batali](img/batali-logo.png)
2
+
1
3
  # Batali
2
4
 
3
5
  Batali is a light weight cookbook resolver. It is now in
@@ -50,6 +52,7 @@ Currently supported "origins":
50
52
  * RemoteSite
51
53
  * Path
52
54
  * Git
55
+ * ChefServer
53
56
 
54
57
  #### RemoteSite
55
58
 
@@ -67,6 +70,23 @@ source 'https://supermarket.chef.io', :name => 'opscode'
67
70
  source 'https://cookbooks.example.com', :name => 'example'
68
71
  ```
69
72
 
73
+ ##### ChefServer
74
+
75
+ This is a Chef Server endpoint:
76
+
77
+ ```ruby
78
+ chef_server 'https://chef-server.example.com'
79
+ ```
80
+
81
+ It will use the `node_name` and `client_key` defined within the
82
+ `.chef/knife.rb` configuration by default. To use the Chef Server
83
+ URL defined within the configuration, just declare it with no
84
+ arguments:
85
+
86
+ ```ruby
87
+ chef_server
88
+ ```
89
+
70
90
  ##### Path
71
91
 
72
92
  Paths are defined via cookbook entries:
data/batali.gemspec CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
21
21
  s.add_runtime_dependency 'git'
22
22
  s.add_development_dependency 'minitest'
23
23
  s.add_development_dependency 'pry'
24
+ s.add_development_dependency 'chef'
24
25
  s.executables << 'batali'
25
26
  s.files = Dir['{lib,bin}/**/**/*'] + %w(batali.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
26
27
  end
data/lib/batali/b_file.rb CHANGED
@@ -22,6 +22,15 @@ module Batali
22
22
  self
23
23
  end
24
24
 
25
+ def chef_server(*args)
26
+ unless(self[:chef_server])
27
+ set!(:chef_server, ::AttributeStruct::CollapseArray.new.push(args))
28
+ else
29
+ self[:chef_server].push(args)
30
+ end
31
+ self
32
+ end
33
+
25
34
  def restrict(*args)
26
35
  unless(self[:restrict])
27
36
  set!(:restrict, ::AttributeStruct::CollapseArray.new.push(args))
@@ -88,13 +97,20 @@ module Batali
88
97
  attribute :restrict, Restriction, :multiple => true, :coerce => lambda{|v|
89
98
  Restriction.new(:cookbook => v.first, :source => v.last.to_smash[:source])
90
99
  }
91
- attribute :source, Origin::RemoteSite, :multiple => true, :coerce => lambda{|v|
100
+ attribute :source, Origin::RemoteSite, :multiple => true, :default => [], :coerce => lambda{|v|
92
101
  args = Smash.new(:endpoint => v.first)
93
102
  if(v.last.is_a?(Hash))
94
103
  args.merge!(v.last)
95
104
  end
96
105
  Origin::RemoteSite.new(args)
97
106
  }
107
+ attribute :chef_server, Origin::ChefServer, :multiple => true, :default => [], :coerce => lambda{|v|
108
+ args = Smash.new(:endpoint => v.first)
109
+ if(v.last.is_a?(Hash))
110
+ args.merge!(v.last)
111
+ end
112
+ Origin::ChefServer.new(args)
113
+ }
98
114
  attribute :group, Group, :multiple => true, :coerce => lambda{|v| Group.new()}
99
115
  attribute :cookbook, Cookbook, :multiple => true, :coerce => BFile.cookbook_coerce, :default => []
100
116
  attribute :metadata, Cookbook, :coerce => lambda{ |v, b_file|
@@ -0,0 +1,60 @@
1
+ require 'batali'
2
+ require 'digest/sha2'
3
+ require 'securerandom'
4
+ require 'http'
5
+ require 'fileutils'
6
+
7
+ module Batali
8
+ class Origin
9
+ # Fetch unit information from chef server
10
+ class ChefServer < Origin
11
+
12
+ include Bogo::Memoization
13
+ include Utility::Chef
14
+
15
+ attribute :name, String
16
+ attribute :identifier, String
17
+
18
+ def initialize(*_)
19
+ super
20
+ init_chef!
21
+ self.identifier = Digest::SHA256.hexdigest(endpoint)
22
+ unless(name?)
23
+ self.name = self.identifier
24
+ end
25
+ end
26
+
27
+ # @return [Array<Unit>] all units
28
+ def units
29
+ memoize(:units) do
30
+ debug "Fetching units from chef server: #{endpoint}"
31
+ units = api_service.get_rest('cookbooks?num_versions=all').map do |c_name, meta|
32
+ meta['versions'].map do |info|
33
+ "#{c_name}/#{info['version']}"
34
+ end
35
+ end.flatten.map do |ckbk|
36
+ debug "Unit information from #{endpoint}: #{ckbk.inspect}"
37
+ c_name, c_version = ckbk.split('/', 2)
38
+ c_deps = api_service.get_rest(
39
+ "cookbooks/#{c_name}/#{c_version}"
40
+ ).metadata.dependencies.to_a
41
+ Unit.new(
42
+ :name => c_name,
43
+ :version => c_version,
44
+ :dependencies => c_deps,
45
+ :source => Smash.new(
46
+ :type => :chef_server,
47
+ :version => c_version,
48
+ :dependencies => c_deps,
49
+ :endpoint => endpoint,
50
+ :client_key => client_key,
51
+ :client_name => client_name
52
+ )
53
+ )
54
+ end.flatten
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
data/lib/batali/origin.rb CHANGED
@@ -4,6 +4,7 @@ module Batali
4
4
  # Cookbook source origin
5
5
  class Origin < Utility
6
6
 
7
+ autoload :ChefServer, 'batali/origin/chef_server'
7
8
  autoload :RemoteSite, 'batali/origin/remote_site'
8
9
  autoload :Git, 'batali/origin/git'
9
10
  autoload :Path, 'batali/origin/path'
@@ -0,0 +1,86 @@
1
+ require 'batali'
2
+ require 'tmpdir'
3
+
4
+ module Batali
5
+ class Source
6
+ # Chef Server based source
7
+ class ChefServer < Source
8
+
9
+ include Bogo::Memoization
10
+ include Utility::Chef
11
+
12
+ # @return [Array<Hash>] dependency strings
13
+ attr_reader :dependencies
14
+ # @return [String] local cache path
15
+ attr_accessor :cache
16
+ # @return [string] unique identifier
17
+ attr_reader :identifier
18
+
19
+ attribute :version, String, :required => true, :equivalent => true
20
+
21
+ # Extract extra info before allowing super to load data
22
+ #
23
+ # @param args [Hash]
24
+ # @return [self]
25
+ def initialize(args={})
26
+ @deps = args.delete(:dependencies) || {}
27
+ super
28
+ init_chef!
29
+ end
30
+
31
+ # @return [Chef::Rest]
32
+ def api_service
33
+ memoize(:api_service) do
34
+ Chef::Rest.new(endpoint)
35
+ end
36
+ end
37
+
38
+ # @return [String]
39
+ def unit_version
40
+ version
41
+ end
42
+
43
+ # @return [Array<Array<name, constraints>>]
44
+ def unit_dependencies
45
+ deps.to_a
46
+ end
47
+
48
+ # @return [String] path to cache
49
+ def cache_directory
50
+ memoize(:cache_directory) do
51
+ unless(@cache)
52
+ @cache = File.join(Dir.home, '.batali/cache/chef_server', endpoint)
53
+ end
54
+ cache
55
+ end
56
+ end
57
+
58
+ # @return [String] directory
59
+ def asset
60
+ path = File.join(cache_directory, name, version)
61
+ begin
62
+ FileUtils.mkdir_p(path)
63
+ cookbook = rest.get_rest("cookbooks/#{name}/#{version}")
64
+ manifest = cookbook.manifest
65
+ Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segement|
66
+ if(manifest.has_key?(segment))
67
+ manifest[segement].each do |s_file|
68
+ new_path = File.join(path, s_file['path'].gsub('/', File::SEPARATOR))
69
+ FileUtils.mkdir_p(File.dirname(new_path))
70
+ api_service.sign_on_redirect = false
71
+ t_file = api_service.get_rest(s_file['url'], true)
72
+ FilUtils.mv(t_file.path, new_path)
73
+ end
74
+ end
75
+ end
76
+ rescue => e
77
+ debug "Failed to fully download cookbook [#{name}<#{version}>] - #{e.class}: #{e}"
78
+ FileUtils.rm_rf(path)
79
+ raise
80
+ end
81
+ path
82
+ end
83
+
84
+ end
85
+ end
86
+ end
data/lib/batali/source.rb CHANGED
@@ -7,6 +7,7 @@ module Batali
7
7
  autoload :Path, 'batali/source/path'
8
8
  autoload :Site, 'batali/source/site'
9
9
  autoload :Git, 'batali/source/git'
10
+ autoload :ChefServer, 'batali/source/chef_server'
10
11
 
11
12
  attribute :type, String, :required => true, :default => lambda{ self.name }
12
13
 
@@ -15,7 +15,7 @@ module Batali
15
15
  # @return [self]
16
16
  def populate!
17
17
  memoize(:populate) do
18
- file.source.each do |src|
18
+ (file.source + file.chef_server).each do |src|
19
19
  src.units.find_all do |unit|
20
20
  if(restrictions[unit.name])
21
21
  restrictions[unit.name] == src.identifier
@@ -3,5 +3,63 @@ require 'batali'
3
3
  module Batali
4
4
  class Utility < Grimoire::Utility
5
5
 
6
+ # Helper module for enabling chef server support
7
+ module Chef
8
+
9
+ # Provide common required attribute
10
+ def self.included(klass)
11
+ klass.class_eval do
12
+ attribute :client_name, String
13
+ attribute :client_key, String
14
+ attribute :endpoint, String
15
+ attr_accessor :c_name
16
+ attr_accessor :c_key
17
+ end
18
+ end
19
+
20
+ # Load and configure chef
21
+ def init_chef!
22
+ debug 'Loading chef into the runtime'
23
+ begin
24
+ require 'chef'
25
+ debug 'Successfully loaded chef into the runtime'
26
+ rescue LoadError => e
27
+ debug "Failed to load the chef gem: #{e.class}: #{e}"
28
+ raise 'The `chef` gem was not found. Please `gem install chef` or add `chef` to your bundle.'
29
+ end
30
+ Smash.new(
31
+ :endpoint => :chef_server_url,
32
+ :c_name => :node_name,
33
+ :c_key => :client_key
34
+ ).each do |local_attr, config_key|
35
+ unless(self.send(local_attr))
36
+ memoize(:knife_configure, :global) do
37
+ require 'chef/knife'
38
+ ::Chef::Knife.new.configure_chef
39
+ end
40
+ debug "Settting #{config_key} from knife configuration file for #{self.class} <#{endpoint}>"
41
+ self.send("#{local_attr}=", ::Chef::Config[config_key])
42
+ end
43
+ end
44
+ c_name ||= client_name
45
+ c_key ||= client_key
46
+ end
47
+
48
+ # Make request to api service
49
+ #
50
+ # @yieldparam service [Chef::Rest]
51
+ # @return [Object] result
52
+ def api_service
53
+ memoize(:api_service) do
54
+ ::Chef::REST.new(
55
+ endpoint,
56
+ c_name,
57
+ c_key
58
+ )
59
+ end
60
+ end
61
+
62
+ end
63
+
6
64
  end
7
65
  end
@@ -1,4 +1,4 @@
1
1
  module Batali
2
2
  # Current version
3
- VERSION = Gem::Version.new('0.2.12')
3
+ VERSION = Gem::Version.new('0.2.14')
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: batali
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.12
4
+ version: 0.2.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-11 00:00:00.000000000 Z
11
+ date: 2015-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: attribute_struct
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: chef
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
167
181
  description: Magic
168
182
  email: code@chrisroberts.org
169
183
  executables:
@@ -190,12 +204,14 @@ files:
190
204
  - lib/batali/manifest.rb
191
205
  - lib/batali/monkey.rb
192
206
  - lib/batali/origin.rb
207
+ - lib/batali/origin/chef_server.rb
193
208
  - lib/batali/origin/git.rb
194
209
  - lib/batali/origin/path.rb
195
210
  - lib/batali/origin/remote_site.rb
196
211
  - lib/batali/requirement_list.rb
197
212
  - lib/batali/score_keeper.rb
198
213
  - lib/batali/source.rb
214
+ - lib/batali/source/chef_server.rb
199
215
  - lib/batali/source/git.rb
200
216
  - lib/batali/source/path.rb
201
217
  - lib/batali/source/site.rb