batali 0.4.10 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +2 -2
- data/LICENSE +1 -1
- data/README.md +6 -5
- data/batali.gemspec +26 -25
- data/bin/batali +1 -0
- data/lib/batali.rb +23 -26
- data/lib/batali/b_file.rb +116 -98
- data/lib/batali/chefspec.rb +14 -16
- data/lib/batali/command.rb +32 -27
- data/lib/batali/command/cache.rb +9 -11
- data/lib/batali/command/configure.rb +1 -3
- data/lib/batali/command/display.rb +2 -4
- data/lib/batali/command/install.rb +13 -15
- data/lib/batali/command/resolve.rb +49 -51
- data/lib/batali/command/supermarket.rb +42 -45
- data/lib/batali/command/update.rb +2 -5
- data/lib/batali/config.rb +1 -2
- data/lib/batali/git.rb +10 -11
- data/lib/batali/manifest.rb +5 -6
- data/lib/batali/monkey.rb +6 -4
- data/lib/batali/origin.rb +12 -9
- data/lib/batali/origin/chef_server.rb +12 -14
- data/lib/batali/origin/git.rb +7 -9
- data/lib/batali/origin/path.rb +14 -15
- data/lib/batali/origin/remote_site.rb +17 -18
- data/lib/batali/requirement_list.rb +6 -7
- data/lib/batali/score_keeper.rb +12 -13
- data/lib/batali/source.rb +19 -21
- data/lib/batali/source/chef_server.rb +8 -10
- data/lib/batali/source/git.rb +11 -7
- data/lib/batali/source/path.rb +16 -12
- data/lib/batali/source/site.rb +23 -25
- data/lib/batali/tag_lines.rb +4 -5
- data/lib/batali/unit.rb +13 -16
- data/lib/batali/unit_loader.rb +12 -15
- data/lib/batali/utility.rb +42 -14
- data/lib/batali/version.rb +1 -1
- data/lib/chef/knife/batali_sync.rb +66 -72
- metadata +29 -16
data/lib/batali/origin/path.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
module Batali
|
4
4
|
class Origin
|
@@ -13,7 +13,7 @@ module Batali
|
|
13
13
|
# @return [Constant]
|
14
14
|
def self.const_missing(const)
|
15
15
|
[::Object, ::ObjectSpace].map do |root|
|
16
|
-
if
|
16
|
+
if root.const_defined?(const)
|
17
17
|
root.const_get(const)
|
18
18
|
end
|
19
19
|
end.compact.first || super
|
@@ -23,7 +23,6 @@ module Batali
|
|
23
23
|
set!(:depends, args)
|
24
24
|
self
|
25
25
|
end
|
26
|
-
|
27
26
|
end
|
28
27
|
|
29
28
|
include Bogo::Memoization
|
@@ -32,8 +31,9 @@ module Batali
|
|
32
31
|
|
33
32
|
def initialize(*_)
|
34
33
|
super
|
34
|
+
self.path = Utility.clean_path(path)
|
35
35
|
self.identifier = Smash.new(:path => path).checksum
|
36
|
-
unless
|
36
|
+
unless name?
|
37
37
|
self.name = identifier
|
38
38
|
end
|
39
39
|
end
|
@@ -42,16 +42,16 @@ module Batali
|
|
42
42
|
def units
|
43
43
|
memoize(:units) do
|
44
44
|
info = load_metadata
|
45
|
-
if
|
46
|
-
unless
|
45
|
+
if info[:depends]
|
46
|
+
unless info[:depends].first.is_a?(Array)
|
47
47
|
info[:depends] = [info[:depends]]
|
48
48
|
end
|
49
49
|
info[:depends] = info[:depends].map do |dep|
|
50
50
|
case dep
|
51
51
|
when String
|
52
|
-
[dep,
|
52
|
+
[dep, "> 0"]
|
53
53
|
else
|
54
|
-
dep.size == 1 ? dep.push(
|
54
|
+
dep.size == 1 ? dep.push("> 0") : dep
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -65,9 +65,9 @@ module Batali
|
|
65
65
|
:version => info[:version],
|
66
66
|
:path => path,
|
67
67
|
:dependencies => info.fetch(:depends, []),
|
68
|
-
:cache_path => cache_path
|
69
|
-
)
|
70
|
-
)
|
68
|
+
:cache_path => cache_path,
|
69
|
+
),
|
70
|
+
),
|
71
71
|
]
|
72
72
|
end
|
73
73
|
end
|
@@ -75,9 +75,9 @@ module Batali
|
|
75
75
|
# @return [Smash] metadata information
|
76
76
|
def load_metadata
|
77
77
|
memoize(:metadata) do
|
78
|
-
if
|
79
|
-
MultiJson.load(json).to_smash
|
80
|
-
elsif
|
78
|
+
if File.exist?(json = File.join(path, "metadata.json"))
|
79
|
+
MultiJson.load(File.read(json)).to_smash
|
80
|
+
elsif File.exist?(rb = File.join(path, "metadata.rb"))
|
81
81
|
struct = Metadata.new
|
82
82
|
struct.set_state!(:value_collapse => true)
|
83
83
|
struct.instance_eval(File.read(rb), rb, 1)
|
@@ -87,7 +87,6 @@ module Batali
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
90
|
-
|
91
90
|
end
|
92
91
|
end
|
93
92
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require "batali"
|
2
|
+
require "digest/sha2"
|
3
|
+
require "securerandom"
|
4
|
+
require "http"
|
5
|
+
require "fileutils"
|
6
6
|
|
7
7
|
module Batali
|
8
8
|
class Origin
|
@@ -10,7 +10,7 @@ module Batali
|
|
10
10
|
class RemoteSite < Origin
|
11
11
|
|
12
12
|
# Site suffix for API endpoint
|
13
|
-
API_SUFFIX =
|
13
|
+
API_SUFFIX = "api/v1/"
|
14
14
|
|
15
15
|
include Bogo::Memoization
|
16
16
|
|
@@ -25,7 +25,7 @@ module Batali
|
|
25
25
|
# NOTE: We currently don't require API_SUFFIX information
|
26
26
|
# self.endpoint = URI.join(endpoint, API_SUFFIX).to_s
|
27
27
|
self.identifier = Digest::SHA256.hexdigest(endpoint)
|
28
|
-
unless
|
28
|
+
unless name?
|
29
29
|
self.name = identifier
|
30
30
|
end
|
31
31
|
end
|
@@ -33,7 +33,7 @@ module Batali
|
|
33
33
|
# @return [String] cache directory path
|
34
34
|
def cache_directory
|
35
35
|
memoize(:cache_directory) do
|
36
|
-
c_path =
|
36
|
+
c_path = Utility.join_path(cache_path, "remote_site", identifier)
|
37
37
|
FileUtils.mkdir_p(c_path)
|
38
38
|
c_path
|
39
39
|
end
|
@@ -53,8 +53,8 @@ module Batali
|
|
53
53
|
:url => info[:download_url],
|
54
54
|
:version => version,
|
55
55
|
:dependencies => info[:dependencies],
|
56
|
-
:cache_path => cache_path
|
57
|
-
)
|
56
|
+
:cache_path => cache_path,
|
57
|
+
),
|
58
58
|
)
|
59
59
|
end
|
60
60
|
end.flatten
|
@@ -76,17 +76,17 @@ module Batali
|
|
76
76
|
def fetch
|
77
77
|
do_fetch = true
|
78
78
|
cache_directory # init directory creation
|
79
|
-
if
|
79
|
+
if File.exist?(universe_path)
|
80
80
|
age = Time.now - File.mtime(universe_path)
|
81
|
-
if
|
81
|
+
if age < update_interval
|
82
82
|
do_fetch = false
|
83
83
|
end
|
84
84
|
end
|
85
|
-
if
|
85
|
+
if do_fetch
|
86
86
|
t_uni = "#{universe_path}.#{SecureRandom.urlsafe_base64}"
|
87
|
-
result = HTTP.get(URI.join(endpoint,
|
88
|
-
File.open(t_uni,
|
89
|
-
while
|
87
|
+
result = HTTP.get(URI.join(endpoint, "universe"))
|
88
|
+
File.open(t_uni, "w") do |file|
|
89
|
+
while content = result.body.readpartial(2048)
|
90
90
|
file.write content
|
91
91
|
end
|
92
92
|
end
|
@@ -97,9 +97,8 @@ module Batali
|
|
97
97
|
|
98
98
|
# @return [String] path to universe file
|
99
99
|
def universe_path
|
100
|
-
|
100
|
+
Utility.join_path(cache_directory, "universe.json")
|
101
101
|
end
|
102
|
-
|
103
102
|
end
|
104
103
|
end
|
105
104
|
end
|
@@ -1,15 +1,14 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
# Batali namespace
|
4
4
|
module Batali
|
5
5
|
# Customized Unit
|
6
6
|
class RequirementList < Grimoire::RequirementList
|
7
7
|
attribute(:requirements, [Batali::UnitDependency, Grimoire::DEPENDENCY_CLASS],
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
)
|
8
|
+
:multiple => true,
|
9
|
+
:default => [],
|
10
|
+
:coerce => lambda { |v|
|
11
|
+
Batali::UnitDependency.new(val.first, *val.last)
|
12
|
+
})
|
14
13
|
end
|
15
14
|
end
|
data/lib/batali/score_keeper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
module Batali
|
4
4
|
# Provide scores for units
|
@@ -9,7 +9,7 @@ module Batali
|
|
9
9
|
:preferred => 10_000_000,
|
10
10
|
:patch => 1_000_000,
|
11
11
|
:minor => 1_000,
|
12
|
-
:major => 100
|
12
|
+
:major => 100,
|
13
13
|
}
|
14
14
|
|
15
15
|
attribute :manifest, Manifest, :required => true
|
@@ -27,17 +27,17 @@ module Batali
|
|
27
27
|
# @param idx [Integer] current index location
|
28
28
|
# @return [Numeric, NilClass]
|
29
29
|
def score_for(unit, *args)
|
30
|
-
opts = args.detect{|a| a.is_a?(Hash)} || {}
|
30
|
+
opts = args.detect { |a| a.is_a?(Hash) } || {}
|
31
31
|
multiplier = 1
|
32
32
|
manifest_unit = manifest.cookbook.detect do |m_unit|
|
33
33
|
m_unit.name == unit.name
|
34
34
|
end
|
35
|
-
if
|
35
|
+
if manifest_unit
|
36
36
|
# If the unit version matches the manifest version, this
|
37
37
|
# should be _the_ preferred version
|
38
|
-
if
|
38
|
+
if manifest_unit.version == unit.version
|
39
39
|
multiplier = MULTIPLIERS[:preferred]
|
40
|
-
elsif
|
40
|
+
elsif opts[:solver] && opts[:solver].new_world
|
41
41
|
new_world_unit = opts[:solver].new_world.units.detect do |n_unit|
|
42
42
|
n_unit.name == unit.name &&
|
43
43
|
n_unit.version == unit.version
|
@@ -46,7 +46,7 @@ module Batali
|
|
46
46
|
else
|
47
47
|
# If the unit version satisfies within the patch segment of
|
48
48
|
# the manifest version score those versions highest for upgrade
|
49
|
-
if
|
49
|
+
if UnitRequirement.new("~> #{manifest_unit.version}").satisfied_by?(unit.version)
|
50
50
|
multiplier = MULTIPLIERS[:patch]
|
51
51
|
else
|
52
52
|
# If the unit version satisfies within the minor or major
|
@@ -54,12 +54,12 @@ module Batali
|
|
54
54
|
# value up (with satisfaction within minor segment being
|
55
55
|
# worth more than satisfaction within major segment)
|
56
56
|
satisfied = UnitRequirement.new(
|
57
|
-
"~> #{manifest_unit.version.segments.slice(0, 2).join(
|
57
|
+
"~> #{manifest_unit.version.segments.slice(0, 2).join(".")}"
|
58
58
|
).satisfied_by?(unit.version)
|
59
59
|
pos = satisfied ? 1 : 0
|
60
60
|
multi_val = pos == 1 ? MULTIPLIERS[:minor] : MULTIPLIERS[:major]
|
61
61
|
distance = (manifest_unit.version.segments[pos] - unit.version.segments[pos])
|
62
|
-
if
|
62
|
+
if distance > 0
|
63
63
|
distance = 1.0 / distance
|
64
64
|
else
|
65
65
|
distance = 0
|
@@ -68,7 +68,7 @@ module Batali
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
else
|
71
|
-
if
|
71
|
+
if opts[:solver] && opts[:solver].new_world
|
72
72
|
new_world_unit = opts[:solver].new_world.units.detect do |n_unit|
|
73
73
|
n_unit.name == unit.name &&
|
74
74
|
n_unit.version == unit.version
|
@@ -80,10 +80,10 @@ module Batali
|
|
80
80
|
# Generate a "value" for each segment of the version with
|
81
81
|
# growing importance (major > minor > patch)
|
82
82
|
unit.version.segments.reverse.each_with_index.map do |val, v_pos|
|
83
|
-
if
|
83
|
+
if val == 0
|
84
84
|
score.push 0
|
85
85
|
else
|
86
|
-
score << (2 - (1.0 / val)) * ((v_pos + 1)**10)
|
86
|
+
score << (2 - (1.0 / val)) * ((v_pos + 1) ** 10)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
# Sum the score for each segment to provide the score for the
|
@@ -94,6 +94,5 @@ module Batali
|
|
94
94
|
debug "Score <#{unit.name}:#{unit.version}>: #{score}"
|
95
95
|
score
|
96
96
|
end
|
97
|
-
|
98
97
|
end
|
99
98
|
end
|
data/lib/batali/source.rb
CHANGED
@@ -1,42 +1,41 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
module Batali
|
4
4
|
# Source of asset
|
5
5
|
class Source < Utility
|
6
|
-
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
autoload :
|
10
|
-
autoload :ChefServer, 'batali/source/chef_server'
|
6
|
+
autoload :Path, "batali/source/path"
|
7
|
+
autoload :Site, "batali/source/site"
|
8
|
+
autoload :Git, "batali/source/git"
|
9
|
+
autoload :ChefServer, "batali/source/chef_server"
|
11
10
|
|
12
11
|
# @return [String] path to local cache
|
13
12
|
attr_accessor :cache_path
|
14
13
|
|
15
|
-
attribute :type, String, :required => true, :default => lambda{ self.name } # rubocop:disable Style/RedundantSelf
|
14
|
+
attribute :type, String, :required => true, :default => lambda { self.name } # rubocop:disable Style/RedundantSelf
|
16
15
|
|
17
|
-
def initialize(args={})
|
18
|
-
@cache_path = args.delete(:cache_path)
|
16
|
+
def initialize(args = {})
|
17
|
+
@cache_path = Utility.clean_path(args.delete(:cache_path))
|
19
18
|
super
|
20
19
|
end
|
21
20
|
|
22
21
|
# @return [String]
|
23
22
|
def unit_version
|
24
|
-
raise NotImplementedError.new
|
23
|
+
raise NotImplementedError.new "Abstract class"
|
25
24
|
end
|
26
25
|
|
27
26
|
# @return [Array<Array<name, constraints>>]
|
28
27
|
def unit_dependencies
|
29
|
-
raise NotImplementedError.new
|
28
|
+
raise NotImplementedError.new "Abstract class"
|
30
29
|
end
|
31
30
|
|
32
31
|
# @return [String] directory containing contents
|
33
32
|
def asset
|
34
|
-
raise NotImplementedError.new
|
33
|
+
raise NotImplementedError.new "Abstract class"
|
35
34
|
end
|
36
35
|
|
37
36
|
# @return [TrueClass, FalseClass]
|
38
37
|
def clean_asset(asset_path)
|
39
|
-
if
|
38
|
+
if cache_path && asset_path.include?(cache_path) && File.exist?(asset_path)
|
40
39
|
FileUtils.rm_rf(asset_path)
|
41
40
|
true
|
42
41
|
else
|
@@ -60,9 +59,9 @@ module Batali
|
|
60
59
|
def diff(s)
|
61
60
|
Smash.new.tap do |_diff|
|
62
61
|
self.class.attributes.each do |k, v|
|
63
|
-
if
|
62
|
+
if v[:equivalent]
|
64
63
|
s_attrs = s.respond_to?(:attributes) ? s.attributes : {}
|
65
|
-
unless
|
64
|
+
unless attributes[k] == s_attrs[k]
|
66
65
|
_diff[k] = [attributes[k], s_attrs[k]]
|
67
66
|
end
|
68
67
|
end
|
@@ -77,19 +76,18 @@ module Batali
|
|
77
76
|
# @note uses `:type` to build concrete source
|
78
77
|
def self.build(args)
|
79
78
|
type = args.delete(:type)
|
80
|
-
unless
|
81
|
-
raise ArgumentError.new
|
79
|
+
unless type
|
80
|
+
raise ArgumentError.new "Missing required option `:type`!"
|
82
81
|
end
|
83
|
-
unless
|
84
|
-
type = [name, Bogo::Utility.camel(type)].join(
|
82
|
+
unless type.to_s.include?("::")
|
83
|
+
type = [name, Bogo::Utility.camel(type)].join("::")
|
85
84
|
end
|
86
85
|
klass = Bogo::Utility.constantize(type)
|
87
|
-
unless
|
86
|
+
unless klass
|
88
87
|
raise TypeError.new "Unknown source type provided `#{type}`!"
|
89
88
|
else
|
90
89
|
klass.new(args.merge(:type => type))
|
91
90
|
end
|
92
91
|
end
|
93
|
-
|
94
92
|
end
|
95
93
|
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "batali"
|
2
|
+
require "tmpdir"
|
3
3
|
|
4
4
|
module Batali
|
5
5
|
class Source
|
6
6
|
# Chef Server based source
|
7
7
|
class ChefServer < Source
|
8
|
-
|
9
8
|
include Bogo::Memoization
|
10
9
|
include Utility::Chef
|
11
10
|
|
@@ -22,7 +21,7 @@ module Batali
|
|
22
21
|
#
|
23
22
|
# @param args [Hash]
|
24
23
|
# @return [self]
|
25
|
-
def initialize(args={})
|
24
|
+
def initialize(args = {})
|
26
25
|
@deps = args.delete(:dependencies) || {}
|
27
26
|
super
|
28
27
|
init_chef!
|
@@ -48,25 +47,25 @@ module Batali
|
|
48
47
|
# @return [String] path to cache
|
49
48
|
def cache_directory
|
50
49
|
memoize(:cache_directory) do
|
51
|
-
@cache ||=
|
50
|
+
@cache ||= Utility.join_path(cache_path, "chef_server", endpoint)
|
52
51
|
cache
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
55
|
# @return [String] directory
|
57
56
|
def asset
|
58
|
-
path =
|
57
|
+
path = Utility.join_path(cache_directory, name, version)
|
59
58
|
begin
|
60
59
|
FileUtils.mkdir_p(path)
|
61
60
|
cookbook = rest.get_rest("cookbooks/#{name}/#{version}")
|
62
61
|
manifest = cookbook.manifest
|
63
62
|
Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segement|
|
64
|
-
if
|
63
|
+
if manifest.key?(segment)
|
65
64
|
manifest[segement].each do |s_file|
|
66
|
-
new_path =
|
65
|
+
new_path = Utility.join_path(path, s_file["path"].gsub("/", File::SEPARATOR))
|
67
66
|
FileUtils.mkdir_p(File.dirname(new_path))
|
68
67
|
api_service.sign_on_redirect = false
|
69
|
-
t_file = api_service.get_rest(s_file[
|
68
|
+
t_file = api_service.get_rest(s_file["url"], true)
|
70
69
|
FilUtils.mv(t_file.path, new_path)
|
71
70
|
end
|
72
71
|
end
|
@@ -78,7 +77,6 @@ module Batali
|
|
78
77
|
end
|
79
78
|
path
|
80
79
|
end
|
81
|
-
|
82
80
|
end
|
83
81
|
end
|
84
82
|
end
|
data/lib/batali/source/git.rb
CHANGED
@@ -1,24 +1,29 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "batali"
|
2
|
+
require "fileutils"
|
3
|
+
require "tmpdir"
|
4
4
|
|
5
5
|
module Batali
|
6
6
|
# Source of asset
|
7
7
|
class Source
|
8
8
|
# Path based source
|
9
9
|
class Git < Path
|
10
|
-
|
11
10
|
include Bogo::Memoization
|
12
11
|
include Batali::Git
|
13
12
|
|
14
13
|
attribute :subdirectory, String, :equivalent => true
|
15
14
|
attribute :path, String
|
16
15
|
|
16
|
+
def initialize(*_, &block)
|
17
|
+
super
|
18
|
+
self.subdirectory = Utility.clean_path(subdirectory)
|
19
|
+
self.path = Utility.clean_path(path)
|
20
|
+
end
|
21
|
+
|
17
22
|
# @return [String] directory containing contents
|
18
23
|
def asset
|
19
24
|
clone_repository
|
20
25
|
clone_path = ref_dup
|
21
|
-
self.path =
|
26
|
+
self.path = Utility.join_path(*[ref_dup, subdirectory].compact)
|
22
27
|
result = super
|
23
28
|
self.path = clone_path
|
24
29
|
result
|
@@ -31,11 +36,10 @@ module Batali
|
|
31
36
|
:url => url,
|
32
37
|
:ref => ref,
|
33
38
|
:type => self.class.name,
|
34
|
-
:subdirectory => subdirectory
|
39
|
+
:subdirectory => subdirectory,
|
35
40
|
), *args
|
36
41
|
)
|
37
42
|
end
|
38
|
-
|
39
43
|
end
|
40
44
|
end
|
41
45
|
end
|