batali 0.2.12 → 0.2.14

Sign up to get free protection for your applications and to get access to all the features.
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