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/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
|