batali 0.4.10 → 0.5.0
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 +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/source/path.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
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
|
@@ -9,40 +9,44 @@ module Batali
|
|
9
9
|
class Path < Source
|
10
10
|
|
11
11
|
# @return [Array<String>] default ignore globs
|
12
|
-
DEFAULT_IGNORE = [
|
12
|
+
DEFAULT_IGNORE = [".git*"]
|
13
13
|
# @return [Array<String>] valid ignore file names
|
14
|
-
IGNORE_FILE = [
|
14
|
+
IGNORE_FILE = ["chefignore", ".chefignore"]
|
15
15
|
|
16
16
|
include Bogo::Memoization
|
17
17
|
|
18
18
|
attribute :path, String, :required => true, :equivalent => true
|
19
19
|
|
20
|
+
def initialize(*_, &block)
|
21
|
+
super
|
22
|
+
self.path = Utility.clean_path(path)
|
23
|
+
end
|
24
|
+
|
20
25
|
# @return [String] directory containing contents
|
21
26
|
def asset
|
22
27
|
memoize(:asset) do
|
23
28
|
dir = Dir.mktmpdir
|
24
29
|
chefignore = IGNORE_FILE.map do |c_name|
|
25
|
-
c_path =
|
30
|
+
c_path = Utility.join_path(path, c_name)
|
26
31
|
c_path if File.exist?(c_path)
|
27
32
|
end.compact.first
|
28
33
|
chefignore = chefignore ? File.readlines(chefignore) : []
|
29
34
|
chefignore += DEFAULT_IGNORE
|
30
35
|
chefignore.uniq!
|
31
|
-
files_to_copy = Dir.glob(File.join(path,
|
36
|
+
files_to_copy = Dir.glob(File.join(path, "{.[^.]*,**}", "**", "{*,*.*,.*}"))
|
32
37
|
files_to_copy = files_to_copy.map do |file_path|
|
33
38
|
next unless File.file?(file_path)
|
34
|
-
relative_path = file_path.sub("#{path}#{File::SEPARATOR}",
|
35
|
-
relative_path unless chefignore.detect{|ig| File.fnmatch(ig, relative_path)}
|
39
|
+
relative_path = file_path.sub("#{path}#{File::SEPARATOR}", "")
|
40
|
+
relative_path unless chefignore.detect { |ig| File.fnmatch(ig, relative_path) }
|
36
41
|
end.compact
|
37
42
|
files_to_copy.each do |relative_path|
|
38
|
-
new_path =
|
43
|
+
new_path = Utility.join_path(dir, relative_path)
|
39
44
|
FileUtils.mkdir_p(File.dirname(new_path))
|
40
|
-
FileUtils.cp(
|
45
|
+
FileUtils.cp(Utility.join_path(path, relative_path), new_path)
|
41
46
|
end
|
42
47
|
dir
|
43
48
|
end
|
44
49
|
end
|
45
|
-
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
data/lib/batali/source/site.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require "batali"
|
2
|
+
require "http"
|
3
|
+
require "tmpdir"
|
4
|
+
require "rubygems/package"
|
5
|
+
require "zlib"
|
6
6
|
|
7
7
|
module Batali
|
8
8
|
class Source
|
9
9
|
# Site based source
|
10
10
|
class Site < Source
|
11
|
-
|
12
11
|
include Bogo::Memoization
|
13
12
|
|
14
13
|
# @return [Array<Hash>] dependency strings
|
@@ -25,7 +24,7 @@ module Batali
|
|
25
24
|
#
|
26
25
|
# @param args [Hash]
|
27
26
|
# @return [self]
|
28
|
-
def initialize(args={})
|
27
|
+
def initialize(args = {})
|
29
28
|
@deps = args.delete(:dependencies) || {}
|
30
29
|
super
|
31
30
|
end
|
@@ -43,30 +42,30 @@ module Batali
|
|
43
42
|
# @return [String] path to cache
|
44
43
|
def cache_directory
|
45
44
|
memoize(:cache_directory) do
|
46
|
-
@cache ||=
|
45
|
+
@cache ||= Utility.join_path(cache_path, "remote_site")
|
47
46
|
cache
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
51
50
|
# @return [String] directory
|
52
51
|
def asset
|
53
|
-
path =
|
54
|
-
if
|
55
|
-
discovered_path = Dir.glob(
|
52
|
+
path = Utility.join_path(cache_directory, Base64.urlsafe_encode64(url))
|
53
|
+
if File.directory?(path)
|
54
|
+
discovered_path = Dir.glob(Utility.join_path(path, "*")).reject do |i|
|
56
55
|
i.end_with?("#{File::SEPARATOR}asset")
|
57
56
|
end.first
|
58
57
|
FileUtils.rm_rf(path)
|
59
58
|
end
|
60
|
-
unless
|
59
|
+
unless discovered_path
|
61
60
|
retried = false
|
62
61
|
begin
|
63
62
|
FileUtils.mkdir_p(path)
|
64
|
-
result = HTTP.get(url)
|
65
|
-
while
|
66
|
-
result = HTTP.get(result.headers[
|
63
|
+
result = HTTP.get(url.end_with?("/") ? url : url + "/")
|
64
|
+
while result.code == 302
|
65
|
+
result = HTTP.get(result.headers["Location"])
|
67
66
|
end
|
68
|
-
File.open(a_path =
|
69
|
-
while
|
67
|
+
File.open(a_path = Utility.join_path(path, "asset"), "wb") do |file|
|
68
|
+
while content = result.body.readpartial(2048)
|
70
69
|
file.write content
|
71
70
|
end
|
72
71
|
end
|
@@ -76,10 +75,10 @@ module Batali
|
|
76
75
|
ext.rewind
|
77
76
|
ext.each do |entry|
|
78
77
|
next unless entry.file?
|
79
|
-
n_path =
|
78
|
+
n_path = Utility.join_path(path, entry.full_name)
|
80
79
|
FileUtils.mkdir_p(File.dirname(n_path))
|
81
|
-
File.open(n_path,
|
82
|
-
while
|
80
|
+
File.open(n_path, "wb") do |file|
|
81
|
+
while content = entry.read(2048)
|
83
82
|
file.write(content)
|
84
83
|
end
|
85
84
|
end
|
@@ -91,18 +90,18 @@ module Batali
|
|
91
90
|
end
|
92
91
|
rescue => e
|
93
92
|
FileUtils.rm_rf(path)
|
94
|
-
unless
|
93
|
+
unless retried
|
95
94
|
FileUtils.mkdir_p(path)
|
96
95
|
retried = true
|
97
96
|
retry
|
98
97
|
end
|
99
98
|
raise
|
100
99
|
end
|
101
|
-
discovered_path = Dir.glob(
|
100
|
+
discovered_path = Dir.glob(Utility.join_path(path, "*")).reject do |i|
|
102
101
|
i.end_with?("#{File::SEPARATOR}asset")
|
103
102
|
end.first
|
104
103
|
end
|
105
|
-
unless
|
104
|
+
unless discovered_path
|
106
105
|
raise Errno::ENOENT.new "Failed to locate asset within `#{path}`"
|
107
106
|
end
|
108
107
|
discovered_path
|
@@ -110,13 +109,12 @@ module Batali
|
|
110
109
|
|
111
110
|
# @return [TrueClass, FalseClass]
|
112
111
|
def clean_asset(asset_path)
|
113
|
-
if
|
112
|
+
if asset_path
|
114
113
|
super File.dirname(asset_path)
|
115
114
|
else
|
116
115
|
false
|
117
116
|
end
|
118
117
|
end
|
119
|
-
|
120
118
|
end
|
121
119
|
end
|
122
120
|
end
|
data/lib/batali/tag_lines.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
# Batali namespace
|
4
4
|
module Batali
|
@@ -7,9 +7,8 @@ module Batali
|
|
7
7
|
TAG_LINES = [
|
8
8
|
'I got 99 problems but a policyfile ain\'t one',
|
9
9
|
'Solve the way you want, not the way you\'re told',
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
"Build environments, not applications",
|
11
|
+
"DRY should be the rule, not the exception",
|
12
|
+
"Solve for the forest, not just a tree",
|
13
13
|
]
|
14
|
-
|
15
14
|
end
|
data/lib/batali/unit.rb
CHANGED
@@ -1,23 +1,21 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
# Batali namespace
|
4
4
|
module Batali
|
5
5
|
# Customized Unit
|
6
6
|
class Unit < Grimoire::Unit
|
7
|
-
attribute :source, Source, :coerce => lambda{|v| Batali::Source.build(v)}
|
7
|
+
attribute :source, Source, :coerce => lambda { |v| Batali::Source.build(v) }
|
8
8
|
attribute(:dependencies, [Batali::UnitDependency, Grimoire::DEPENDENCY_CLASS],
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
)
|
9
|
+
:multiple => true,
|
10
|
+
:default => [],
|
11
|
+
:coerce => lambda { |val|
|
12
|
+
Batali::UnitDependency.new(val.first, *val.last)
|
13
|
+
})
|
15
14
|
attribute(:version, [Batali::UnitVersion, Grimoire::VERSION_CLASS],
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
)
|
15
|
+
:required => true,
|
16
|
+
:coerce => lambda { |val|
|
17
|
+
Batali::UnitVersion.new(val)
|
18
|
+
})
|
21
19
|
|
22
20
|
# @return [TrueClass, FalseClass]
|
23
21
|
def diff?(u)
|
@@ -33,15 +31,14 @@ module Batali
|
|
33
31
|
def diff(u)
|
34
32
|
Smash.new.tap do |_diff|
|
35
33
|
[:name, :version].each do |k|
|
36
|
-
unless
|
34
|
+
unless send(k) == u.send(k)
|
37
35
|
_diff[k] = [send(k), u.send(k)]
|
38
36
|
end
|
39
37
|
end
|
40
|
-
if
|
38
|
+
if source
|
41
39
|
_diff.merge!(source.diff(u.source))
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
45
|
-
|
46
43
|
end
|
47
44
|
end
|
data/lib/batali/unit_loader.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
# Batali namespace
|
4
4
|
module Batali
|
5
5
|
|
6
6
|
# Load cookbook units
|
7
7
|
class UnitLoader < Utility
|
8
|
-
|
9
8
|
include Bogo::Memoization
|
10
9
|
|
11
10
|
attribute :file, BFile, :required => true
|
@@ -20,7 +19,7 @@ module Batali
|
|
20
19
|
memoize(:populate) do
|
21
20
|
(file.source + file.chef_server).each do |src|
|
22
21
|
src.units.find_all do |unit|
|
23
|
-
if
|
22
|
+
if restrictions[unit.name]
|
24
23
|
restrictions[unit.name] == src.identifier
|
25
24
|
else
|
26
25
|
true
|
@@ -30,22 +29,22 @@ module Batali
|
|
30
29
|
end
|
31
30
|
end
|
32
31
|
file.cookbook.each do |ckbk|
|
33
|
-
if
|
32
|
+
if ckbk.git
|
34
33
|
source = Origin::Git.new(
|
35
34
|
:name => ckbk.name,
|
36
35
|
:url => ckbk.git,
|
37
36
|
:subdirectory => ckbk.path,
|
38
|
-
:ref => ckbk.ref ||
|
39
|
-
:cache_path => cache
|
37
|
+
:ref => ckbk.ref || "master",
|
38
|
+
:cache_path => cache,
|
40
39
|
)
|
41
|
-
elsif
|
40
|
+
elsif ckbk.path
|
42
41
|
source = Origin::Path.new(
|
43
42
|
:name => ckbk.name,
|
44
43
|
:path => ckbk.path,
|
45
|
-
:cache_path => cache
|
44
|
+
:cache_path => cache,
|
46
45
|
)
|
47
46
|
end
|
48
|
-
if
|
47
|
+
if source
|
49
48
|
system.add_unit(source.units.first)
|
50
49
|
end
|
51
50
|
end
|
@@ -57,13 +56,13 @@ module Batali
|
|
57
56
|
memoize(:restrictions) do
|
58
57
|
rest = (file.restrict || Smash.new).to_smash
|
59
58
|
file.cookbook.each do |ckbk|
|
60
|
-
if
|
61
|
-
if
|
59
|
+
if auto_path_restrict || ckbk.restrict
|
60
|
+
if ckbk.path
|
62
61
|
rest[ckbk.name] = Smash.new(:path => ckbk.path).checksum
|
63
|
-
elsif
|
62
|
+
elsif ckbk.git
|
64
63
|
rest[ckbk.name] = Smash.new(
|
65
64
|
:url => ckbk.git,
|
66
|
-
:ref => ckbk.ref
|
65
|
+
:ref => ckbk.ref,
|
67
66
|
).checksum
|
68
67
|
end
|
69
68
|
end
|
@@ -71,7 +70,5 @@ module Batali
|
|
71
70
|
rest
|
72
71
|
end
|
73
72
|
end
|
74
|
-
|
75
73
|
end
|
76
|
-
|
77
74
|
end
|
data/lib/batali/utility.rb
CHANGED
@@ -1,8 +1,33 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
module Batali
|
4
|
+
# Utility class to provide helper methods
|
4
5
|
class Utility < Grimoire::Utility
|
5
6
|
|
7
|
+
# Prefix for building UNC paths on Windows
|
8
|
+
UNC_PREFIX = "//?/".freeze
|
9
|
+
|
10
|
+
# Properly format and expand path based
|
11
|
+
# on platform in use
|
12
|
+
def self.clean_path(path)
|
13
|
+
path = File.expand_path(path.to_s)
|
14
|
+
if RUBY_PLATFORM =~ /mswin|mingw|windows/ &&
|
15
|
+
path.downcase.match(/^[a-z]:/) &&
|
16
|
+
ENV["BATALI_DISABLE_UNC"].nil?
|
17
|
+
path = UNC_PREFIX + path
|
18
|
+
end
|
19
|
+
path
|
20
|
+
end
|
21
|
+
|
22
|
+
# Join arguments to base path and clean
|
23
|
+
#
|
24
|
+
# @param base [String] base path
|
25
|
+
# @param args [Array<String>]
|
26
|
+
# @return [String]
|
27
|
+
def self.join_path(base, *args)
|
28
|
+
clean_path(File.join(base, *args))
|
29
|
+
end
|
30
|
+
|
6
31
|
# Helper module for enabling chef server support
|
7
32
|
module Chef
|
8
33
|
|
@@ -19,28 +44,33 @@ module Batali
|
|
19
44
|
|
20
45
|
# Load and configure chef
|
21
46
|
def init_chef!
|
22
|
-
debug
|
47
|
+
debug "Loading chef into the runtime"
|
23
48
|
begin
|
24
|
-
require
|
25
|
-
|
26
|
-
|
49
|
+
require "chef"
|
50
|
+
begin
|
51
|
+
require "chef/rest"
|
52
|
+
@_api_klass = ::Chef::REST
|
53
|
+
rescue LoadError
|
54
|
+
# Newer versions of chef do not include REST
|
55
|
+
require "chef/server_api"
|
56
|
+
@_api_klass = ::Chef::ServerAPI
|
57
|
+
end
|
58
|
+
debug "Successfully loaded chef into the runtime"
|
27
59
|
rescue LoadError => e
|
28
60
|
debug "Failed to load the chef gem: #{e.class}: #{e}"
|
29
|
-
raise
|
61
|
+
raise "The `chef` gem was not found. Please `gem install chef` or add `chef` to your bundle."
|
30
62
|
end
|
31
63
|
Smash.new(
|
32
64
|
:endpoint => :chef_server_url,
|
33
65
|
:c_name => :node_name,
|
34
|
-
:c_key => :client_key
|
66
|
+
:c_key => :client_key,
|
35
67
|
).each do |local_attr, config_key|
|
36
|
-
unless
|
68
|
+
unless self.send(local_attr)
|
37
69
|
memoize(:knife_configure, :global) do
|
38
|
-
require
|
70
|
+
require "chef/knife"
|
39
71
|
::Chef::Knife.new.configure_chef
|
40
72
|
end
|
41
|
-
# rubocop:disable Style/RedundantSelf
|
42
73
|
debug "Settting #{config_key} from knife configuration file for #{self.class} <#{endpoint}>"
|
43
|
-
# rubocop:disable Style/RedundantSelf
|
44
74
|
self.send("#{local_attr}=", ::Chef::Config[config_key])
|
45
75
|
end
|
46
76
|
end
|
@@ -54,15 +84,13 @@ module Batali
|
|
54
84
|
# @return [Object] result
|
55
85
|
def api_service
|
56
86
|
memoize(:api_service) do
|
57
|
-
|
87
|
+
@_api_klass.new(
|
58
88
|
endpoint,
|
59
89
|
c_name,
|
60
90
|
c_key
|
61
91
|
)
|
62
92
|
end
|
63
93
|
end
|
64
|
-
|
65
94
|
end
|
66
|
-
|
67
95
|
end
|
68
96
|
end
|
data/lib/batali/version.rb
CHANGED
@@ -1,92 +1,87 @@
|
|
1
|
-
require
|
1
|
+
require "batali"
|
2
2
|
|
3
3
|
class Chef
|
4
4
|
class Knife
|
5
5
|
# Batali manifest to chef server sync
|
6
6
|
class BataliSync < Knife
|
7
|
-
|
8
|
-
banner 'knife batali sync'
|
7
|
+
banner "knife batali sync"
|
9
8
|
|
10
9
|
option(:blacklist,
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
)
|
10
|
+
:short => "-B COOKBOOK_NAME[,COOKBOOK_NAME]",
|
11
|
+
:long => "--blacklist COOKBOOK_NAME[,COOKBOOK_NAME]",
|
12
|
+
:description => "Cookbooks to ignore from sync",
|
13
|
+
:proc => lambda { |val|
|
14
|
+
Chef::Config[:knife][:batali_blacklist] ||= []
|
15
|
+
Chef::Config[:knife][:batali_blacklist] += val.split(",")
|
16
|
+
})
|
19
17
|
|
20
18
|
option(:details,
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
)
|
19
|
+
:long => "--[no-]details",
|
20
|
+
:boolean => true,
|
21
|
+
:default => true,
|
22
|
+
:description => "Show details of cookbooks to be removed / added")
|
26
23
|
|
27
24
|
option(:show_remaining,
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
)
|
25
|
+
:long => "--[no-]show-remaining",
|
26
|
+
:description => "Display cookbook details of expected final server state",
|
27
|
+
:boolean => true,
|
28
|
+
:default => false,
|
29
|
+
:proc => lambda { |val|
|
30
|
+
Chef::Config[:knife][:batali_show_remaining] = val
|
31
|
+
})
|
36
32
|
|
37
33
|
option(:dry_run,
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
)
|
34
|
+
:long => "--[no-]dry-run",
|
35
|
+
:description => "Display information but perform no action",
|
36
|
+
:boolean => true,
|
37
|
+
:default => false)
|
43
38
|
|
44
39
|
def run
|
45
40
|
Chef::Config[:knife][:batali_blacklist] ||= []
|
46
41
|
config[:verbose] = config[:verbosity].to_i > 0
|
47
|
-
ui.info "#{ui.color(
|
48
|
-
valid_cookbooks = run_task(
|
42
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Chef Server Batali Manifest Sync"
|
43
|
+
valid_cookbooks = run_task("Generating valid cookbook versions from manifest") do
|
49
44
|
generate_manifest_cookbooks
|
50
45
|
end
|
51
|
-
remote_cookbooks = run_task(
|
46
|
+
remote_cookbooks = run_task("Generating remote cookbook versions from chef server") do
|
52
47
|
generate_remote_cookbooks
|
53
48
|
end
|
54
|
-
to_remove = run_task(
|
49
|
+
to_remove = run_task("Building cookbook removal list") do
|
55
50
|
locate_removals(
|
56
51
|
:manifest => valid_cookbooks,
|
57
|
-
:server => remote_cookbooks
|
52
|
+
:server => remote_cookbooks,
|
58
53
|
)
|
59
54
|
end
|
60
|
-
to_add = run_task(
|
55
|
+
to_add = run_task("Building cookbook upload list") do
|
61
56
|
locate_additions(
|
62
57
|
:manifest => valid_cookbooks,
|
63
|
-
:server => remote_cookbooks
|
58
|
+
:server => remote_cookbooks,
|
64
59
|
)
|
65
60
|
end
|
66
|
-
if
|
67
|
-
ui.info "#{ui.color(
|
61
|
+
if to_add.empty? && to_remove.empty?
|
62
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Chef Server Batali Manifest Sync - #{ui.color("No Changes Detected!", :green, :bold)}" # rubocop:disable Metrics/LineLength
|
68
63
|
else
|
69
64
|
display_sync_info(
|
70
65
|
:additions => to_add,
|
71
66
|
:removals => to_remove,
|
72
|
-
:manifest => valid_cookbooks
|
67
|
+
:manifest => valid_cookbooks,
|
73
68
|
)
|
74
|
-
unless
|
75
|
-
ui.confirm
|
69
|
+
unless config[:dry_run]
|
70
|
+
ui.confirm "Sync remote cookbooks with Batali manifest"
|
76
71
|
remove_cookbooks(to_remove) unless to_remove.empty?
|
77
72
|
add_cookbooks(to_add) unless to_add.empty?
|
78
|
-
ui.info "#{ui.color(
|
73
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Chef Server Batali Manifest Sync - #{ui.color("Sync Complete!", :green, :bold)}" # rubocop:disable Metrics/LineLength
|
79
74
|
else
|
80
|
-
ui.warn
|
75
|
+
ui.warn "Dry run requested. No action taken."
|
81
76
|
end
|
82
77
|
end
|
83
78
|
end
|
84
79
|
|
85
80
|
def remove_cookbooks(ckbks)
|
86
|
-
run_task(
|
81
|
+
run_task("Removing cookbooks") do
|
87
82
|
ckbks.each do |c_name, vers|
|
88
83
|
vers.each do |version|
|
89
|
-
if
|
84
|
+
if config[:verbose]
|
90
85
|
ui.warn "Deleting cookbook #{c_name} @ #{version}"
|
91
86
|
end
|
92
87
|
rest.delete("/cookbooks/#{c_name}/#{version}")
|
@@ -97,13 +92,13 @@ class Chef
|
|
97
92
|
|
98
93
|
def add_cookbooks(ckbks)
|
99
94
|
Batali::Command::Install.new({}, []).execute!
|
100
|
-
ui.info "#{ui.color(
|
95
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Adding cookbooks to Chef server."
|
101
96
|
Knife::Upload.load_deps
|
102
97
|
ckbks.each do |c_name, vers|
|
103
98
|
vers.each do |version|
|
104
99
|
c_path = [
|
105
|
-
File.join(
|
106
|
-
File.join(
|
100
|
+
File.join("cookbooks", c_name),
|
101
|
+
File.join("cookbooks", "#{c_name}-#{version}"),
|
107
102
|
].detect do |_path|
|
108
103
|
File.directory?(_path)
|
109
104
|
end
|
@@ -111,44 +106,44 @@ class Chef
|
|
111
106
|
uploader.configure_chef
|
112
107
|
uploader.config = config
|
113
108
|
uploader.name_args = [c_path]
|
114
|
-
if
|
109
|
+
if config[:verbose]
|
115
110
|
ui.warn "Unloading cookbook #{c_name} @ #{version} - `#{c_path}`"
|
116
111
|
end
|
117
112
|
uploader.run
|
118
113
|
end
|
119
114
|
end
|
120
|
-
ui.info "#{ui.color(
|
115
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Chef server cookbook additions complete."
|
121
116
|
end
|
122
117
|
|
123
118
|
def display_sync_info(opts)
|
124
119
|
num_remove = ui.color(opts[:removals].size.to_s, :red, :bold)
|
125
120
|
num_add = ui.color(opts[:additions].size.to_s, :green, :bold)
|
126
|
-
ui.info "#{ui.color(
|
127
|
-
if
|
128
|
-
unless
|
129
|
-
ui.info "#{ui.color(
|
121
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Removals - #{num_remove} Additions: #{num_add}"
|
122
|
+
if config[:details]
|
123
|
+
unless opts[:removals].empty?
|
124
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Cookbooks to be #{ui.color("removed", :red, :bold)}:"
|
130
125
|
opts[:removals].sort.each do |name, versions|
|
131
126
|
vers = versions.map do |v|
|
132
127
|
Gem::Version.new(v)
|
133
|
-
end.sort.map(&:to_s).join(
|
128
|
+
end.sort.map(&:to_s).join(", ")
|
134
129
|
ui.info " #{ui.color(name, :red, :bold)}: #{ui.color(vers, :red)}"
|
135
130
|
end
|
136
131
|
end
|
137
|
-
unless
|
138
|
-
ui.info "#{ui.color(
|
132
|
+
unless opts[:additions].empty?
|
133
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Cookbooks to be #{ui.color("added", :green, :bold)}:"
|
139
134
|
opts[:additions].sort.each do |name, versions|
|
140
135
|
vers = versions.map do |v|
|
141
136
|
Gem::Version.new(v)
|
142
|
-
end.sort.map(&:to_s).join(
|
137
|
+
end.sort.map(&:to_s).join(", ")
|
143
138
|
ui.info " #{ui.color(name, :green, :bold)}: #{ui.color(vers, :green)}"
|
144
139
|
end
|
145
140
|
end
|
146
|
-
if
|
147
|
-
ui.info "#{ui.color(
|
141
|
+
if Chef::Config[:knife][:batali_show_remaining]
|
142
|
+
ui.info "#{ui.color("[Batali]", :green, :bold)}: Final list of cookbooks to be available on the chef server:" # rubocop:disable Metrics/LineLength
|
148
143
|
opts[:manifest].sort.each do |name, versions|
|
149
144
|
vers = versions.map do |v|
|
150
145
|
Gem::Version.new(v)
|
151
|
-
end.sort.map(&:to_s).join(
|
146
|
+
end.sort.map(&:to_s).join(", ")
|
152
147
|
ui.info " #{ui.color(name, :bold)}: #{vers}"
|
153
148
|
end
|
154
149
|
end
|
@@ -159,7 +154,7 @@ class Chef
|
|
159
154
|
Smash.new.tap do |rm|
|
160
155
|
opts[:server].each do |c_name, c_versions|
|
161
156
|
kills = c_versions - opts[:manifest].fetch(c_name, [])
|
162
|
-
unless
|
157
|
+
unless kills.empty?
|
163
158
|
rm[c_name] = kills
|
164
159
|
end
|
165
160
|
end
|
@@ -170,7 +165,7 @@ class Chef
|
|
170
165
|
Smash.new.tap do |add|
|
171
166
|
opts[:manifest].each do |c_name, c_versions|
|
172
167
|
adds = c_versions - opts[:server].fetch(c_name, [])
|
173
|
-
unless
|
168
|
+
unless adds.empty?
|
174
169
|
add[c_name] = adds
|
175
170
|
end
|
176
171
|
end
|
@@ -178,8 +173,8 @@ class Chef
|
|
178
173
|
end
|
179
174
|
|
180
175
|
def generate_manifest_cookbooks
|
181
|
-
path = File.join(Dir.pwd,
|
182
|
-
unless
|
176
|
+
path = File.join(Dir.pwd, "batali.manifest")
|
177
|
+
unless File.exist?(path)
|
183
178
|
raise "Failed to locate batali manifest at: #{path}"
|
184
179
|
end
|
185
180
|
manifest = Batali::Manifest.build(path)
|
@@ -194,29 +189,28 @@ class Chef
|
|
194
189
|
|
195
190
|
def generate_remote_cookbooks
|
196
191
|
Smash.new.tap do |ckbks|
|
197
|
-
rest.get(
|
192
|
+
rest.get("cookbooks?num_versions=all").map do |c_name, meta|
|
198
193
|
next if Chef::Config[:knife][:batali_blacklist].include?(c_name)
|
199
194
|
ckbks[c_name] = []
|
200
|
-
meta[
|
201
|
-
ckbks[c_name] << info[
|
195
|
+
meta["versions"].each do |info|
|
196
|
+
ckbks[c_name] << info["version"]
|
202
197
|
end
|
203
198
|
end
|
204
199
|
end
|
205
200
|
end
|
206
201
|
|
207
202
|
def run_task(task)
|
208
|
-
ui.stdout.print "#{ui.color(
|
203
|
+
ui.stdout.print "#{ui.color("[Batali]", :green, :bold)}: #{task}... "
|
209
204
|
begin
|
210
205
|
value = yield if block_given?
|
211
|
-
ui.info ui.color(
|
206
|
+
ui.info ui.color("complete", :green)
|
212
207
|
value
|
213
208
|
rescue => e
|
214
|
-
ui.info ui.color(
|
209
|
+
ui.info ui.color("failed", :red, :bold)
|
215
210
|
puts e.backtrace.join("\n")
|
216
211
|
raise e
|
217
212
|
end
|
218
213
|
end
|
219
|
-
|
220
214
|
end
|
221
215
|
end
|
222
216
|
end
|