batali 0.3.10 → 0.3.12
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 +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +18 -0
- data/batali.gemspec +2 -0
- data/lib/batali.rb +1 -0
- data/lib/batali/b_file.rb +27 -7
- data/lib/batali/chefspec.rb +5 -0
- data/lib/batali/command.rb +1 -1
- data/lib/batali/command/install.rb +3 -3
- data/lib/batali/command/resolve.rb +6 -5
- data/lib/batali/git.rb +5 -4
- data/lib/batali/manifest.rb +3 -3
- data/lib/batali/monkey.rb +5 -1
- data/lib/batali/origin.rb +1 -0
- data/lib/batali/origin/chef_server.rb +3 -2
- data/lib/batali/origin/git.rb +3 -2
- data/lib/batali/origin/path.rb +6 -4
- data/lib/batali/origin/remote_site.rb +5 -5
- data/lib/batali/requirement_list.rb +8 -1
- data/lib/batali/score_keeper.rb +19 -8
- data/lib/batali/source.rb +15 -11
- data/lib/batali/source/chef_server.rb +2 -4
- data/lib/batali/source/path.rb +1 -1
- data/lib/batali/source/site.rb +1 -3
- data/lib/batali/tag_lines.rb +7 -5
- data/lib/batali/unit.rb +16 -4
- data/lib/batali/unit_loader.rb +15 -9
- data/lib/batali/utility.rb +3 -1
- data/lib/batali/version.rb +2 -1
- data/lib/chef/knife/batali_sync.rb +5 -4
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 011f26a3e8a17db988eb207d7fc79cbdc51e1306
|
4
|
+
data.tar.gz: e0bd881f9cf5be081f73c315e6be9ee50a206ff7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc6e7955b3163d94389ee1b71b61ce63651ea760f39e4061682f8fbb91505642129159252e95d851e3ae6cae6b6600d1bebf9f580adad9613e358ed1ef082abb
|
7
|
+
data.tar.gz: fa4b45f0b1c202a9ada821e6d64456c78316b21b52e969281f7ef6fbc07a9395aec2209dea78b724035430445f9b9498ea0c39ec657a0805d389be7af31811d3
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -240,6 +240,24 @@ $ batali resolve --infrastructure
|
|
240
240
|
|
241
241
|
_NOTE: Depending on constraints defined within the Batali file, this can be a very large manifest_
|
242
242
|
|
243
|
+
#### Single cookbook, multiple sources
|
244
|
+
|
245
|
+
When running in infrastructure mode, Batali supports single cookbooks being loaded from
|
246
|
+
multiple sources. For example, if all the `users` cookbooks greater than version `1.0` should
|
247
|
+
be available _and_ an unreleased development version that lives in a git repository, Batali
|
248
|
+
will properly include all versions:
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
Batali.define do
|
252
|
+
source 'https://supermarket.chef.io'
|
253
|
+
cookbook 'users', '> 1.0'
|
254
|
+
cookbook 'users', git: 'git://example.com/org/users.git', ref: 'development'
|
255
|
+
end
|
256
|
+
```
|
257
|
+
|
258
|
+
The resulting Batali manifest file will include all available versions greater than `1.0`
|
259
|
+
from the supermarket source _and_ the version defined at the specified git end point.
|
260
|
+
|
243
261
|
#### Uploading infrastructure cookbooks
|
244
262
|
|
245
263
|
When the infrastructure cookbooks are installed locally, the cookbook directories will have
|
data/batali.gemspec
CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.add_runtime_dependency 'bogo-ui', '~> 0.1.6'
|
19
19
|
s.add_runtime_dependency 'http', '>= 0.8.2', '< 1.0.0'
|
20
20
|
s.add_runtime_dependency 'git'
|
21
|
+
s.add_development_dependency 'rake'
|
22
|
+
s.add_development_dependency 'rubocop'
|
21
23
|
s.add_development_dependency 'minitest'
|
22
24
|
s.add_development_dependency 'pry'
|
23
25
|
s.add_development_dependency 'chef'
|
data/lib/batali.rb
CHANGED
data/lib/batali/b_file.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'batali'
|
2
2
|
require 'pathname'
|
3
3
|
|
4
|
+
# Batali namespace
|
4
5
|
module Batali
|
5
6
|
|
7
|
+
# Custom struct class for file processing
|
6
8
|
class Struct < AttributeStruct
|
7
9
|
|
8
10
|
def cookbook(*args)
|
@@ -85,8 +87,22 @@ module Batali
|
|
85
87
|
struct
|
86
88
|
end
|
87
89
|
|
90
|
+
# Custom file loading class
|
88
91
|
class BFile < Bogo::Config
|
89
92
|
|
93
|
+
# @return [String] path to cache
|
94
|
+
attr_reader :cache
|
95
|
+
|
96
|
+
# Create a new BFile instance
|
97
|
+
#
|
98
|
+
# @param b_file [String] path to file
|
99
|
+
# @param cache_path [String] path to cache directory
|
100
|
+
# @return [self]
|
101
|
+
def initialize(b_file, cache_path)
|
102
|
+
@cache = cache_path
|
103
|
+
super(b_file)
|
104
|
+
end
|
105
|
+
|
90
106
|
# @return [Proc] cookbook convert
|
91
107
|
def self.cookbook_coerce
|
92
108
|
proc do |v|
|
@@ -107,19 +123,23 @@ module Batali
|
|
107
123
|
end
|
108
124
|
end
|
109
125
|
|
126
|
+
# Cookbook entry
|
110
127
|
class Cookbook < Utility
|
111
128
|
attribute :name, String, :required => true
|
112
129
|
attribute :constraint, String, :multiple => true
|
113
130
|
attribute :git, String
|
114
131
|
attribute :ref, String
|
115
132
|
attribute :path, String
|
133
|
+
attribute :restrict, [TrueClass, FalseClass], :default => false
|
116
134
|
end
|
117
135
|
|
136
|
+
# Restriction entry
|
118
137
|
class Restriction < Utility
|
119
138
|
attribute :cookbook, String, :required => true
|
120
139
|
attribute :source, String, :required => true
|
121
140
|
end
|
122
141
|
|
142
|
+
# Group entry
|
123
143
|
class Group < Utility
|
124
144
|
attribute :name, String, :required => true
|
125
145
|
attribute :cookbook, Cookbook, :multiple => true, :required => true, :coerce => BFile.cookbook_coerce
|
@@ -133,7 +153,7 @@ module Batali
|
|
133
153
|
Restriction.new(:cookbook => v.first, :source => v.last.to_smash[:source])
|
134
154
|
end
|
135
155
|
}
|
136
|
-
attribute :source, Origin::RemoteSite, :multiple => true, :default => [], :coerce => lambda{|v|
|
156
|
+
attribute :source, Origin::RemoteSite, :multiple => true, :default => [], :coerce => lambda{|v, b_file|
|
137
157
|
if(v.is_a?(Hash))
|
138
158
|
args = v
|
139
159
|
else
|
@@ -142,9 +162,9 @@ module Batali
|
|
142
162
|
args.merge!(v.last)
|
143
163
|
end
|
144
164
|
end
|
145
|
-
Origin::RemoteSite.new(args)
|
165
|
+
Origin::RemoteSite.new(args.merge(:cache_path => b_file.cache))
|
146
166
|
}
|
147
|
-
attribute :chef_server, Origin::ChefServer, :multiple => true, :default => [], :coerce => lambda{|v|
|
167
|
+
attribute :chef_server, Origin::ChefServer, :multiple => true, :default => [], :coerce => lambda{|v, b_file|
|
148
168
|
if(v.is_a?(Hash))
|
149
169
|
args = v
|
150
170
|
else
|
@@ -153,7 +173,7 @@ module Batali
|
|
153
173
|
args.merge!(v.last)
|
154
174
|
end
|
155
175
|
end
|
156
|
-
Origin::ChefServer.new(args)
|
176
|
+
Origin::ChefServer.new(args.merge(:cache_path => b_file.cache))
|
157
177
|
}
|
158
178
|
attribute :group, Group, :multiple => true, :coerce => lambda{|v| Group.new(v)}
|
159
179
|
attribute :cookbook, Cookbook, :multiple => true, :coerce => BFile.cookbook_coerce, :default => []
|
@@ -162,7 +182,7 @@ module Batali
|
|
162
182
|
ckbk = Cookbook.new(v)
|
163
183
|
else
|
164
184
|
dir = Pathname.new(File.dirname(b_file.path)).relative_path_from(Pathname.new(Dir.pwd)).to_path
|
165
|
-
m_unit = Origin::Path.new(:name => 'metadata', :path => dir).units.first
|
185
|
+
m_unit = Origin::Path.new(:name => 'metadata', :path => dir, :cache_path => b_file.cache).units.first
|
166
186
|
ckbk = Cookbook.new(:name => m_unit.name, :version => m_unit.version, :path => dir)
|
167
187
|
end
|
168
188
|
unless(b_file.cookbook.map(&:name).include?(ckbk.name))
|
@@ -186,7 +206,7 @@ module Batali
|
|
186
206
|
result[:name] => result[:cookbooks]
|
187
207
|
)
|
188
208
|
end
|
189
|
-
end.compact.inject(Smash.new){|m,n| m.merge(n)}
|
209
|
+
end.compact.inject(Smash.new){|m, n| m.merge(n)}
|
190
210
|
environment_items.each do |e_name, items|
|
191
211
|
next if environment && e_name != environment
|
192
212
|
debug "Discovery processing of environment: #{e_name}"
|
@@ -315,7 +335,7 @@ module Batali
|
|
315
335
|
env.fetch(
|
316
336
|
:cookbook_versions,
|
317
337
|
Smash.new
|
318
|
-
).map{|k,v| [k, v.to_s.split(',')]}
|
338
|
+
).map{|k, v| [k, v.to_s.split(',')]}
|
319
339
|
]
|
320
340
|
)
|
321
341
|
end
|
data/lib/batali/chefspec.rb
CHANGED
@@ -3,7 +3,9 @@ require 'stringio'
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'tmpdir'
|
5
5
|
|
6
|
+
# ChefSpec namespace
|
6
7
|
module ChefSpec
|
8
|
+
# Batali integration class
|
7
9
|
class Batali
|
8
10
|
|
9
11
|
class << self
|
@@ -13,10 +15,12 @@ module ChefSpec
|
|
13
15
|
|
14
16
|
include Singleton
|
15
17
|
|
18
|
+
# Create new instance
|
16
19
|
def initialize
|
17
20
|
@vendor_path = Dir.mktmpdir
|
18
21
|
end
|
19
22
|
|
23
|
+
# Setup the environment (load cookbooks)
|
20
24
|
def setup!
|
21
25
|
output = ''
|
22
26
|
begin
|
@@ -44,6 +48,7 @@ module ChefSpec
|
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
51
|
+
# Clean up after complete
|
47
52
|
def teardown!
|
48
53
|
if(File.directory?(@vendor_path))
|
49
54
|
FileUtils.rm_rf(@vendor_path)
|
data/lib/batali/command.rb
CHANGED
@@ -28,7 +28,7 @@ module Batali
|
|
28
28
|
# TODO: Add directory traverse searching
|
29
29
|
path = config.fetch(:file, File.join(Dir.pwd, 'Batali'))
|
30
30
|
ui.verbose "Loading Batali file from: #{path}"
|
31
|
-
bfile = BFile.new(path)
|
31
|
+
bfile = BFile.new(path, cache_directory)
|
32
32
|
if(bfile.discover)
|
33
33
|
bfile.auto_discover!(config[:environment])
|
34
34
|
end
|
@@ -17,12 +17,12 @@ module Batali
|
|
17
17
|
nil
|
18
18
|
end
|
19
19
|
if(manifest.cookbook.nil? || manifest.cookbook.empty?)
|
20
|
-
ui.error
|
20
|
+
ui.error 'No cookbooks defined within manifest! Try resolving first. (`batali resolve`)'
|
21
21
|
else
|
22
22
|
run_action('Installing cookbooks') do
|
23
23
|
manifest.cookbook.each do |unit|
|
24
|
-
if(unit.source.respond_to?(:
|
25
|
-
unit.source.
|
24
|
+
if(unit.source.respond_to?(:cache_path))
|
25
|
+
unit.source.cache_path = cache_directory(
|
26
26
|
Bogo::Utility.snake(unit.source.class.name.split('::').last)
|
27
27
|
)
|
28
28
|
end
|
@@ -14,7 +14,8 @@ module Batali
|
|
14
14
|
UnitLoader.new(
|
15
15
|
:file => batali_file,
|
16
16
|
:system => system,
|
17
|
-
:cache => cache_directory(:git)
|
17
|
+
:cache => cache_directory(:git),
|
18
|
+
:auto_path_restrict => !infrastructure?
|
18
19
|
).populate!
|
19
20
|
nil
|
20
21
|
end
|
@@ -101,7 +102,7 @@ module Batali
|
|
101
102
|
unless(u_diff.empty?)
|
102
103
|
diff_output = "[#{u_diff.values.map{|v| v.join(' -> ')}.join(' | ')}]"
|
103
104
|
end
|
104
|
-
ui.puts ui.color("#{unit_name} <#{version_output}> #{diff_output}"
|
105
|
+
ui.puts ui.color("#{unit_name} <#{version_output}> #{diff_output}", :yellow)
|
105
106
|
end
|
106
107
|
else
|
107
108
|
ui.puts ui.color("#{unit_name} <#{manifest_units[unit_name].version}>", :red)
|
@@ -169,15 +170,15 @@ module Batali
|
|
169
170
|
uv.last ? ui.color(uv.first.to_s, uv.last) : uv.first.to_s
|
170
171
|
end
|
171
172
|
unless(added.empty? && removed.empty?)
|
172
|
-
ui.puts "#{ui.color(unit_name, :yellow)} #{ui.color('<', :yellow)}#{unit_versions.join(ui.color(', ', :yellow))}#{ui.color('>', :yellow)}"
|
173
|
+
ui.puts "#{ui.color(unit_name, :yellow)} #{ui.color('<', :yellow)}#{unit_versions.join(ui.color(', ', :yellow))}#{ui.color('>', :yellow)}" # rubocop:disable Metrics/LineLength
|
173
174
|
else
|
174
175
|
ui.puts "#{unit_name} <#{unit_versions.join(', ')}>"
|
175
176
|
end
|
176
177
|
else
|
177
|
-
ui.puts ui.color("#{unit_name} <#{manifest_units[unit_name].map(&:version).sort.map(&:to_s).join(', ')}>", :red)
|
178
|
+
ui.puts ui.color("#{unit_name} <#{manifest_units[unit_name].map(&:version).sort.map(&:to_s).join(', ')}>", :red) # rubocop:disable Metrics/LineLength
|
178
179
|
end
|
179
180
|
else
|
180
|
-
ui.puts ui.color("#{unit_name} <#{solution_units[unit_name].map(&:version).sort.map(&:to_s).join(', ')}>", :green)
|
181
|
+
ui.puts ui.color("#{unit_name} <#{solution_units[unit_name].map(&:version).sort.map(&:to_s).join(', ')}>", :green) # rubocop:disable Metrics/LineLength
|
181
182
|
end
|
182
183
|
end
|
183
184
|
end
|
data/lib/batali/git.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'git'
|
2
2
|
require 'batali'
|
3
3
|
|
4
|
+
# Batali namespace
|
4
5
|
module Batali
|
6
|
+
# Helper module for git interactions
|
5
7
|
module Git
|
6
8
|
|
7
9
|
# @return [String] path to repository clone
|
8
10
|
def base_path
|
9
|
-
File.join(
|
11
|
+
File.join(cache_path, Base64.urlsafe_encode64(url))
|
10
12
|
end
|
11
13
|
|
12
14
|
# Clone the repository to the local machine
|
@@ -33,13 +35,13 @@ module Batali
|
|
33
35
|
git.checkout(ref)
|
34
36
|
git.pull('origin', ref)
|
35
37
|
self.ref = git.log.first.sha
|
36
|
-
self.path = File.join(
|
38
|
+
self.path = File.join(cache_path, 'git', ref)
|
37
39
|
unless(File.directory?(path))
|
38
40
|
FileUtils.mkdir_p(path)
|
39
41
|
FileUtils.cp_r(File.join(base_path, '.'), path)
|
40
42
|
FileUtils.rm_rf(File.join(path, '.git'))
|
41
43
|
end
|
42
|
-
|
44
|
+
path
|
43
45
|
end
|
44
46
|
|
45
47
|
# Load attributes into class
|
@@ -47,7 +49,6 @@ module Batali
|
|
47
49
|
klass.class_eval do
|
48
50
|
attribute :url, String, :required => true, :equivalent => true
|
49
51
|
attribute :ref, String, :required => true, :equivalent => true
|
50
|
-
attribute :cache, String, :default => File.join(Dir.home, '.batali', 'cache', 'git')
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
data/lib/batali/manifest.rb
CHANGED
@@ -16,10 +16,10 @@ module Batali
|
|
16
16
|
# @param path [String] path to manifest
|
17
17
|
# @return [Manifest]
|
18
18
|
def self.build(path)
|
19
|
-
if(File.
|
20
|
-
|
19
|
+
if(File.exist?(path))
|
20
|
+
new(Bogo::Config.new(path).data.merge(:path => path))
|
21
21
|
else
|
22
|
-
|
22
|
+
new(:path => path)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
data/lib/batali/monkey.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
require 'batali'
|
2
2
|
require 'bogo/http_proxy'
|
3
3
|
|
4
|
+
# Batali namespace
|
4
5
|
module Batali
|
5
|
-
#
|
6
|
+
# Custom named unit version
|
6
7
|
class UnitVersion < Grimoire::VERSION_CLASS; end
|
8
|
+
# Custom named unit requirement
|
7
9
|
class UnitRequirement < Grimoire::REQUIREMENT_CLASS; end
|
10
|
+
# Custom named unit dependency
|
8
11
|
class UnitDependency < Grimoire::DEPENDENCY_CLASS
|
12
|
+
# Override to properly convert to JSON
|
9
13
|
def to_json(*args)
|
10
14
|
result = [
|
11
15
|
name,
|
data/lib/batali/origin.rb
CHANGED
@@ -20,7 +20,7 @@ module Batali
|
|
20
20
|
init_chef!
|
21
21
|
self.identifier = Digest::SHA256.hexdigest(endpoint)
|
22
22
|
unless(name?)
|
23
|
-
self.name =
|
23
|
+
self.name = identifier
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -48,7 +48,8 @@ module Batali
|
|
48
48
|
:dependencies => c_deps,
|
49
49
|
:endpoint => endpoint,
|
50
50
|
:client_key => client_key,
|
51
|
-
:client_name => client_name
|
51
|
+
:client_name => client_name,
|
52
|
+
:cache_path => cache_path
|
52
53
|
)
|
53
54
|
)
|
54
55
|
end.flatten
|
data/lib/batali/origin/git.rb
CHANGED
@@ -18,7 +18,7 @@ module Batali
|
|
18
18
|
:subdirectory => subdirectory
|
19
19
|
).checksum
|
20
20
|
unless(name?)
|
21
|
-
self.name =
|
21
|
+
self.name = identifier
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -29,7 +29,8 @@ module Batali
|
|
29
29
|
items.first.source = Source::Git.new(
|
30
30
|
:url => url,
|
31
31
|
:ref => ref,
|
32
|
-
:subdirectory => subdirectory
|
32
|
+
:subdirectory => subdirectory,
|
33
|
+
:cache_path => cache_path
|
33
34
|
)
|
34
35
|
items
|
35
36
|
end
|
data/lib/batali/origin/path.rb
CHANGED
@@ -5,6 +5,7 @@ module Batali
|
|
5
5
|
# Fetch unit from local path
|
6
6
|
class Path < Origin
|
7
7
|
|
8
|
+
# Helper class for loading metadata ruby files
|
8
9
|
class Metadata < AttributeStruct
|
9
10
|
|
10
11
|
# Perform constant lookup if required
|
@@ -33,7 +34,7 @@ module Batali
|
|
33
34
|
super
|
34
35
|
self.identifier = Smash.new(:path => path).checksum
|
35
36
|
unless(name?)
|
36
|
-
self.name =
|
37
|
+
self.name = identifier
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
@@ -63,7 +64,8 @@ module Batali
|
|
63
64
|
:type => :path,
|
64
65
|
:version => info[:version],
|
65
66
|
:path => path,
|
66
|
-
:dependencies => info.fetch(:depends, [])
|
67
|
+
:dependencies => info.fetch(:depends, []),
|
68
|
+
:cache_path => cache_path
|
67
69
|
)
|
68
70
|
)
|
69
71
|
]
|
@@ -73,9 +75,9 @@ module Batali
|
|
73
75
|
# @return [Smash] metadata information
|
74
76
|
def load_metadata
|
75
77
|
memoize(:metadata) do
|
76
|
-
if(File.
|
78
|
+
if(File.exist?(json = File.join(path, 'metadata.json')))
|
77
79
|
MultiJson.load(json).to_smash
|
78
|
-
elsif(File.
|
80
|
+
elsif(File.exist?(rb = File.join(path, 'metadata.rb')))
|
79
81
|
struct = Metadata.new
|
80
82
|
struct.set_state!(:value_collapse => true)
|
81
83
|
struct.instance_eval(File.read(rb), rb, 1)
|
@@ -19,21 +19,20 @@ module Batali
|
|
19
19
|
attribute :endpoint, String, :required => true
|
20
20
|
attribute :force_update, [TrueClass, FalseClass], :required => true, :default => false
|
21
21
|
attribute :update_interval, Integer, :required => true, :default => 60
|
22
|
-
attribute :cache, String, :default => File.join(Dir.home, '.batali', 'cache', 'remote_site'), :required => true
|
23
22
|
|
24
23
|
def initialize(*_)
|
25
24
|
super
|
26
25
|
endpoint = URI.join(self.endpoint, COOKBOOK_API_SUFFIX).to_s
|
27
26
|
self.identifier = Digest::SHA256.hexdigest(endpoint)
|
28
27
|
unless(name?)
|
29
|
-
self.name =
|
28
|
+
self.name = identifier
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
33
32
|
# @return [String] cache directory path
|
34
33
|
def cache_directory
|
35
34
|
memoize(:cache_directory) do
|
36
|
-
c_path = File.join(
|
35
|
+
c_path = File.join(cache_path, 'remote_site', identifier)
|
37
36
|
FileUtils.mkdir_p(c_path)
|
38
37
|
c_path
|
39
38
|
end
|
@@ -52,7 +51,8 @@ module Batali
|
|
52
51
|
:type => :site,
|
53
52
|
:url => info[:download_url],
|
54
53
|
:version => version,
|
55
|
-
:dependencies => info[:dependencies]
|
54
|
+
:dependencies => info[:dependencies],
|
55
|
+
:cache_path => cache_path
|
56
56
|
)
|
57
57
|
)
|
58
58
|
end
|
@@ -75,7 +75,7 @@ module Batali
|
|
75
75
|
def fetch
|
76
76
|
do_fetch = true
|
77
77
|
cache_directory # init directory creation
|
78
|
-
if(File.
|
78
|
+
if(File.exist?(universe_path))
|
79
79
|
age = Time.now - File.mtime(universe_path)
|
80
80
|
if(age < update_interval)
|
81
81
|
do_fetch = false
|
@@ -1,8 +1,15 @@
|
|
1
1
|
require 'batali'
|
2
2
|
|
3
|
+
# Batali namespace
|
3
4
|
module Batali
|
4
5
|
# Customized Unit
|
5
6
|
class RequirementList < Grimoire::RequirementList
|
6
|
-
attribute
|
7
|
+
attribute(:requirements, [Batali::UnitDependency, Grimoire::DEPENDENCY_CLASS],
|
8
|
+
:multiple => true,
|
9
|
+
:default => [],
|
10
|
+
:coerce => lambda{ |v|
|
11
|
+
Batali::UnitDependency.new(val.first, *val.last)
|
12
|
+
}
|
13
|
+
)
|
7
14
|
end
|
8
15
|
end
|
data/lib/batali/score_keeper.rb
CHANGED
@@ -4,6 +4,14 @@ module Batali
|
|
4
4
|
# Provide scores for units
|
5
5
|
class ScoreKeeper < Grimoire::UnitScoreKeeper
|
6
6
|
|
7
|
+
# Score multiplier values
|
8
|
+
MULTIPLIERS = {
|
9
|
+
:preferred => 10_000_000,
|
10
|
+
:patch => 1_000_000,
|
11
|
+
:minor => 1_000,
|
12
|
+
:major => 100
|
13
|
+
}
|
14
|
+
|
7
15
|
attribute :manifest, Manifest, :required => true
|
8
16
|
|
9
17
|
# Always prefer higher scoring units
|
@@ -28,25 +36,28 @@ module Batali
|
|
28
36
|
# If the unit version matches the manifest version, this
|
29
37
|
# should be _the_ preferred version
|
30
38
|
if(manifest_unit.version == unit.version)
|
31
|
-
multiplier =
|
39
|
+
multiplier = MULTIPLIERS[:preferred]
|
32
40
|
elsif(opts[:solver] && opts[:solver].new_world)
|
33
41
|
new_world_unit = opts[:solver].new_world.units.detect do |n_unit|
|
34
42
|
n_unit.name == unit.name &&
|
35
43
|
n_unit.version == unit.version
|
36
44
|
end
|
37
|
-
multiplier =
|
45
|
+
multiplier = MULTIPLIERS[:preferred] if new_world_unit
|
38
46
|
else
|
39
47
|
# If the unit version satisfies within the patch segment of
|
40
48
|
# the manifest version score those versions highest for upgrade
|
41
49
|
if(UnitRequirement.new("~> #{manifest_unit.version}").satisfied_by?(unit.version))
|
42
|
-
multiplier =
|
50
|
+
multiplier = MULTIPLIERS[:patch]
|
43
51
|
else
|
44
52
|
# If the unit version satisfies within the minor or major
|
45
53
|
# version segments of the manifest version, bump score
|
46
54
|
# value up (with satisfaction within minor segment being
|
47
55
|
# worth more than satisfaction within major segment)
|
48
|
-
|
49
|
-
|
56
|
+
satisfied = UnitRequirement.new(
|
57
|
+
"~> #{manifest_unit.version.segments.slice(0, 2).join('.')}"
|
58
|
+
).satisfied_by?(unit.version)
|
59
|
+
pos = satisfied ? 1 : 0
|
60
|
+
multi_val = pos == 1 ? MULTIPLIERS[:minor] : MULTIPLIERS[:major]
|
50
61
|
distance = (manifest_unit.version.segments[pos] - unit.version.segments[pos])
|
51
62
|
if(distance > 0)
|
52
63
|
distance = 1.0 / distance
|
@@ -62,17 +73,17 @@ module Batali
|
|
62
73
|
n_unit.name == unit.name &&
|
63
74
|
n_unit.version == unit.version
|
64
75
|
end
|
65
|
-
multiplier =
|
76
|
+
multiplier = MULTIPLIERS[:preferred] if new_world_unit
|
66
77
|
end
|
67
78
|
end
|
68
79
|
score = []
|
69
80
|
# Generate a "value" for each segment of the version with
|
70
81
|
# growing importance (major > minor > patch)
|
71
|
-
unit.version.segments.reverse.each_with_index.map do |val,
|
82
|
+
unit.version.segments.reverse.each_with_index.map do |val, v_pos|
|
72
83
|
if(val == 0)
|
73
84
|
score.push 0
|
74
85
|
else
|
75
|
-
score
|
86
|
+
score << (2 - (1.0 / val)) * ((v_pos + 1)**10)
|
76
87
|
end
|
77
88
|
end
|
78
89
|
# Sum the score for each segment to provide the score for the
|
data/lib/batali/source.rb
CHANGED
@@ -9,7 +9,15 @@ module Batali
|
|
9
9
|
autoload :Git, 'batali/source/git'
|
10
10
|
autoload :ChefServer, 'batali/source/chef_server'
|
11
11
|
|
12
|
-
|
12
|
+
# @return [String] path to local cache
|
13
|
+
attr_accessor :cache_path
|
14
|
+
|
15
|
+
attribute :type, String, :required => true, :default => lambda{ self.name } # rubocop:disable Style/RedundantSelf
|
16
|
+
|
17
|
+
def initialize(args={})
|
18
|
+
@cache_path = args.delete(:cache_path)
|
19
|
+
super
|
20
|
+
end
|
13
21
|
|
14
22
|
# @return [String]
|
15
23
|
def unit_version
|
@@ -28,15 +36,11 @@ module Batali
|
|
28
36
|
|
29
37
|
# @return [TrueClass, FalseClass]
|
30
38
|
def clean_asset(asset_path)
|
31
|
-
if(
|
32
|
-
|
39
|
+
if(cache_path && asset_path.include?(cache_path) && File.exist?(asset_path))
|
40
|
+
FileUtils.rm_rf(asset_path)
|
41
|
+
true
|
33
42
|
else
|
34
|
-
|
35
|
-
FileUtils.rm_rf(asset_path)
|
36
|
-
true
|
37
|
-
else
|
38
|
-
false
|
39
|
-
end
|
43
|
+
false
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
@@ -55,7 +59,7 @@ module Batali
|
|
55
59
|
# @return [Smash]
|
56
60
|
def diff(s)
|
57
61
|
Smash.new.tap do |_diff|
|
58
|
-
self.class.attributes.each do |k,v|
|
62
|
+
self.class.attributes.each do |k, v|
|
59
63
|
if(v[:equivalent])
|
60
64
|
s_attrs = s.respond_to?(:attributes) ? s.attributes : {}
|
61
65
|
unless(attributes[k] == s_attrs[k])
|
@@ -77,7 +81,7 @@ module Batali
|
|
77
81
|
raise ArgumentError.new 'Missing required option `:type`!'
|
78
82
|
end
|
79
83
|
unless(type.to_s.include?('::'))
|
80
|
-
type = [
|
84
|
+
type = [name, Bogo::Utility.camel(type)].join('::')
|
81
85
|
end
|
82
86
|
klass = Bogo::Utility.constantize(type)
|
83
87
|
unless(klass)
|
@@ -48,9 +48,7 @@ module Batali
|
|
48
48
|
# @return [String] path to cache
|
49
49
|
def cache_directory
|
50
50
|
memoize(:cache_directory) do
|
51
|
-
|
52
|
-
@cache = File.join(Dir.home, '.batali', 'cache', 'chef_server', endpoint)
|
53
|
-
end
|
51
|
+
@cache ||= File.join(cache_path, 'chef_server', endpoint)
|
54
52
|
cache
|
55
53
|
end
|
56
54
|
end
|
@@ -63,7 +61,7 @@ module Batali
|
|
63
61
|
cookbook = rest.get_rest("cookbooks/#{name}/#{version}")
|
64
62
|
manifest = cookbook.manifest
|
65
63
|
Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segement|
|
66
|
-
if(manifest.
|
64
|
+
if(manifest.key?(segment))
|
67
65
|
manifest[segement].each do |s_file|
|
68
66
|
new_path = File.join(path, s_file['path'].gsub('/', File::SEPARATOR))
|
69
67
|
FileUtils.mkdir_p(File.dirname(new_path))
|
data/lib/batali/source/path.rb
CHANGED
@@ -23,7 +23,7 @@ module Batali
|
|
23
23
|
dir = Dir.mktmpdir
|
24
24
|
chefignore = IGNORE_FILE.map do |c_name|
|
25
25
|
c_path = File.join(path, c_name)
|
26
|
-
c_path if File.
|
26
|
+
c_path if File.exist?(c_path)
|
27
27
|
end.compact.first
|
28
28
|
chefignore = chefignore ? File.readlines(chefignore) : []
|
29
29
|
chefignore += DEFAULT_IGNORE
|
data/lib/batali/source/site.rb
CHANGED
@@ -43,9 +43,7 @@ module Batali
|
|
43
43
|
# @return [String] path to cache
|
44
44
|
def cache_directory
|
45
45
|
memoize(:cache_directory) do
|
46
|
-
|
47
|
-
@cache = File.join(Dir.home, '.batali', 'cache', 'remote_site')
|
48
|
-
end
|
46
|
+
@cache ||= File.join(cache_path, 'remote_site')
|
49
47
|
cache
|
50
48
|
end
|
51
49
|
end
|
data/lib/batali/tag_lines.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'batali'
|
2
2
|
|
3
|
+
# Batali namespace
|
3
4
|
module Batali
|
4
5
|
|
6
|
+
# Version output taglines
|
5
7
|
TAG_LINES = [
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
'I got 99 problems but a policyfile ain\'t one',
|
9
|
+
'Solve the way you want, not the way you\'re told',
|
10
|
+
'Build environments, not applications',
|
11
|
+
'DRY should be the rule, not the exception',
|
12
|
+
'Solve for the forest, not just a tree'
|
11
13
|
]
|
12
14
|
|
13
15
|
end
|
data/lib/batali/unit.rb
CHANGED
@@ -1,11 +1,23 @@
|
|
1
1
|
require 'batali'
|
2
2
|
|
3
|
+
# Batali namespace
|
3
4
|
module Batali
|
4
5
|
# Customized Unit
|
5
6
|
class Unit < Grimoire::Unit
|
6
7
|
attribute :source, Source, :coerce => lambda{|v| Batali::Source.build(v)}
|
7
|
-
attribute
|
8
|
-
|
8
|
+
attribute(:dependencies, [Batali::UnitDependency, Grimoire::DEPENDENCY_CLASS],
|
9
|
+
:multiple => true,
|
10
|
+
:default => [],
|
11
|
+
:coerce => lambda{ |val|
|
12
|
+
Batali::UnitDependency.new(val.first, *val.last)
|
13
|
+
}
|
14
|
+
)
|
15
|
+
attribute(:version, [Batali::UnitVersion, Grimoire::VERSION_CLASS],
|
16
|
+
:required => true,
|
17
|
+
:coerce => lambda{ |val|
|
18
|
+
Batali::UnitVersion.new(val)
|
19
|
+
}
|
20
|
+
)
|
9
21
|
|
10
22
|
# @return [TrueClass, FalseClass]
|
11
23
|
def diff?(u)
|
@@ -21,8 +33,8 @@ module Batali
|
|
21
33
|
def diff(u)
|
22
34
|
Smash.new.tap do |_diff|
|
23
35
|
[:name, :version].each do |k|
|
24
|
-
unless(
|
25
|
-
_diff[k] = [
|
36
|
+
unless(send(k) == u.send(k))
|
37
|
+
_diff[k] = [send(k), u.send(k)]
|
26
38
|
end
|
27
39
|
end
|
28
40
|
if(source)
|
data/lib/batali/unit_loader.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'batali'
|
2
2
|
|
3
|
+
# Batali namespace
|
3
4
|
module Batali
|
4
5
|
|
6
|
+
# Load cookbook units
|
5
7
|
class UnitLoader < Utility
|
6
8
|
|
7
9
|
include Bogo::Memoization
|
@@ -9,6 +11,7 @@ module Batali
|
|
9
11
|
attribute :file, BFile, :required => true
|
10
12
|
attribute :system, Grimoire::System, :required => true
|
11
13
|
attribute :cache, String, :required => true
|
14
|
+
attribute :auto_path_restrict, [TrueClass, FalseClass], :default => true
|
12
15
|
|
13
16
|
# Populate the system with units
|
14
17
|
#
|
@@ -33,12 +36,13 @@ module Batali
|
|
33
36
|
:url => ckbk.git,
|
34
37
|
:subdirectory => ckbk.path,
|
35
38
|
:ref => ckbk.ref || 'master',
|
36
|
-
:
|
39
|
+
:cache_path => cache
|
37
40
|
)
|
38
41
|
elsif(ckbk.path)
|
39
42
|
source = Origin::Path.new(
|
40
43
|
:name => ckbk.name,
|
41
|
-
:path => ckbk.path
|
44
|
+
:path => ckbk.path,
|
45
|
+
:cache_path => cache
|
42
46
|
)
|
43
47
|
end
|
44
48
|
if(source)
|
@@ -53,13 +57,15 @@ module Batali
|
|
53
57
|
memoize(:restrictions) do
|
54
58
|
rest = (file.restrict || Smash.new).to_smash
|
55
59
|
file.cookbook.each do |ckbk|
|
56
|
-
if(ckbk.
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
if(auto_path_restrict || ckbk.restrict)
|
61
|
+
if(ckbk.path)
|
62
|
+
rest[ckbk.name] = Smash.new(:path => ckbk.path).checksum
|
63
|
+
elsif(ckbk.git)
|
64
|
+
rest[ckbk.name] = Smash.new(
|
65
|
+
:url => ckbk.git,
|
66
|
+
:ref => ckbk.ref
|
67
|
+
).checksum
|
68
|
+
end
|
63
69
|
end
|
64
70
|
end
|
65
71
|
rest
|
data/lib/batali/utility.rb
CHANGED
@@ -32,12 +32,14 @@ module Batali
|
|
32
32
|
:c_name => :node_name,
|
33
33
|
:c_key => :client_key
|
34
34
|
).each do |local_attr, config_key|
|
35
|
-
unless(self.send(local_attr))
|
35
|
+
unless(self.send(local_attr)) # rubocop:disable Style/RedundantSelf
|
36
36
|
memoize(:knife_configure, :global) do
|
37
37
|
require 'chef/knife'
|
38
38
|
::Chef::Knife.new.configure_chef
|
39
39
|
end
|
40
|
+
# rubocop:disable Style/RedundantSelf
|
40
41
|
debug "Settting #{config_key} from knife configuration file for #{self.class} <#{endpoint}>"
|
42
|
+
# rubocop:disable Style/RedundantSelf
|
41
43
|
self.send("#{local_attr}=", ::Chef::Config[config_key])
|
42
44
|
end
|
43
45
|
end
|
data/lib/batali/version.rb
CHANGED
@@ -2,6 +2,7 @@ require 'batali'
|
|
2
2
|
|
3
3
|
class Chef
|
4
4
|
class Knife
|
5
|
+
# Batali manifest to chef server sync
|
5
6
|
class BataliSync < Knife
|
6
7
|
|
7
8
|
banner 'knife batali sync'
|
@@ -63,7 +64,7 @@ class Chef
|
|
63
64
|
)
|
64
65
|
end
|
65
66
|
if(to_add.empty? && to_remove.empty?)
|
66
|
-
ui.info "#{ui.color('[Batali]', :green, :bold)}: Chef Server Batali Manifest Sync - #{ui.color('No Changes Detected!', :green, :bold)}"
|
67
|
+
ui.info "#{ui.color('[Batali]', :green, :bold)}: Chef Server Batali Manifest Sync - #{ui.color('No Changes Detected!', :green, :bold)}" # rubocop:disable Metrics/LineLength
|
67
68
|
else
|
68
69
|
display_sync_info(
|
69
70
|
:additions => to_add,
|
@@ -74,7 +75,7 @@ class Chef
|
|
74
75
|
ui.confirm 'Sync remote cookbooks with Batali manifest'
|
75
76
|
remove_cookbooks(to_remove) unless to_remove.empty?
|
76
77
|
add_cookbooks(to_add) unless to_add.empty?
|
77
|
-
ui.info "#{ui.color('[Batali]', :green, :bold)}: Chef Server Batali Manifest Sync - #{ui.color('Sync Complete!', :green, :bold)}"
|
78
|
+
ui.info "#{ui.color('[Batali]', :green, :bold)}: Chef Server Batali Manifest Sync - #{ui.color('Sync Complete!', :green, :bold)}" # rubocop:disable Metrics/LineLength
|
78
79
|
else
|
79
80
|
ui.warn 'Dry run requested. No action taken.'
|
80
81
|
end
|
@@ -143,7 +144,7 @@ class Chef
|
|
143
144
|
end
|
144
145
|
end
|
145
146
|
if(Chef::Config[:knife][:batali_show_remaining])
|
146
|
-
ui.info "#{ui.color('[Batali]', :green, :bold)}: Final list of cookbooks to be available on the chef server:"
|
147
|
+
ui.info "#{ui.color('[Batali]', :green, :bold)}: Final list of cookbooks to be available on the chef server:" # rubocop:disable Metrics/LineLength
|
147
148
|
opts[:manifest].sort.each do |name, versions|
|
148
149
|
vers = versions.map do |v|
|
149
150
|
Gem::Version.new(v)
|
@@ -178,7 +179,7 @@ class Chef
|
|
178
179
|
|
179
180
|
def generate_manifest_cookbooks
|
180
181
|
path = File.join(Dir.pwd, 'batali.manifest')
|
181
|
-
unless(File.
|
182
|
+
unless(File.exist?(path))
|
182
183
|
raise "Failed to locate batali manifest at: #{path}"
|
183
184
|
end
|
184
185
|
manifest = Batali::Manifest.build(path)
|
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.3.
|
4
|
+
version: 0.3.12
|
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-12-
|
11
|
+
date: 2015-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: attribute_struct
|
@@ -128,6 +128,34 @@ dependencies:
|
|
128
128
|
- - ">="
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: rake
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: rubocop
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
131
159
|
- !ruby/object:Gem::Dependency
|
132
160
|
name: minitest
|
133
161
|
requirement: !ruby/object:Gem::Requirement
|