batali 0.3.10 → 0.3.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc79c37709d9a82123b18ff7f3708d3ab3090747
4
- data.tar.gz: d71675d5533528818ffdafe8a2b7727ae7d20566
3
+ metadata.gz: 011f26a3e8a17db988eb207d7fc79cbdc51e1306
4
+ data.tar.gz: e0bd881f9cf5be081f73c315e6be9ee50a206ff7
5
5
  SHA512:
6
- metadata.gz: e745bf572287f0c86144b03a55493f0de0f8954762664d5165e2cce579bffb80742af7f22c4ac9881fe06519a459b619f922cb7f8c7390cb3d59f62ca7dfc042
7
- data.tar.gz: 6dcb427899adfbc5c7d9e7c9b5b2cb1900a52e98e27511c357f4287b53c94a2698c26ffad5d44efab9cf7df2d66d2f74286ebaac93c0e1d74bc75128de531b96
6
+ metadata.gz: dc6e7955b3163d94389ee1b71b61ce63651ea760f39e4061682f8fbb91505642129159252e95d851e3ae6cae6b6600d1bebf9f580adad9613e358ed1ef082abb
7
+ data.tar.gz: fa4b45f0b1c202a9ada821e6d64456c78316b21b52e969281f7ef6fbc07a9395aec2209dea78b724035430445f9b9498ea0c39ec657a0805d389be7af31811d3
@@ -1,3 +1,7 @@
1
+ # v0.3.12
2
+ * [feature] Support multiple sources for single cookbook in infra-mode
3
+ * [fix] Make cache directory usage consistent in all commands
4
+
1
5
  # v0.3.10
2
6
  * [feature] Chef server manifest sync knife plugin
3
7
 
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
@@ -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'
@@ -2,6 +2,7 @@ require 'bogo-cli'
2
2
  require 'grimoire'
3
3
  require 'batali/monkey'
4
4
 
5
+ # Batali namespace
5
6
  module Batali
6
7
 
7
8
  autoload :BFile, 'batali/b_file'
@@ -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
@@ -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)
@@ -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 "No cookbooks defined within manifest! Try resolving first. (`batali resolve`)"
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?(:cache))
25
- unit.source.cache = cache_directory(
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}" , :yellow)
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
@@ -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(cache, Base64.urlsafe_encode64(url))
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(cache, ref)
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
- self.path
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
 
@@ -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.exists?(path))
20
- self.new(Bogo::Config.new(path).data.merge(:path => path))
19
+ if(File.exist?(path))
20
+ new(Bogo::Config.new(path).data.merge(:path => path))
21
21
  else
22
- self.new(:path => path)
22
+ new(:path => path)
23
23
  end
24
24
  end
25
25
 
@@ -1,11 +1,15 @@
1
1
  require 'batali'
2
2
  require 'bogo/http_proxy'
3
3
 
4
+ # Batali namespace
4
5
  module Batali
5
- # Simple stubs mostly for naming
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,
@@ -10,6 +10,7 @@ module Batali
10
10
  autoload :Path, 'batali/origin/path'
11
11
 
12
12
  attribute :name, String, :required => true
13
+ attribute :cache_path, String, :required => true
13
14
  attribute :identifier, String
14
15
 
15
16
  # @return [Array<Unit>] all units
@@ -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 = self.identifier
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
@@ -18,7 +18,7 @@ module Batali
18
18
  :subdirectory => subdirectory
19
19
  ).checksum
20
20
  unless(name?)
21
- self.name = self.identifier
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
@@ -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 = self.identifier
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.exists?(json = File.join(path, 'metadata.json')))
78
+ if(File.exist?(json = File.join(path, 'metadata.json')))
77
79
  MultiJson.load(json).to_smash
78
- elsif(File.exists?(rb = File.join(path, 'metadata.rb')))
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 = self.identifier
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(cache, identifier)
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.exists?(universe_path))
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 :requirements, [Batali::UnitDependency, Grimoire::DEPENDENCY_CLASS], :multiple => true, :default => [], :coerce => lambda{|v| Batali::UnitDependency.new(val.first, *val.last)}
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
@@ -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 = 10000000
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 = 10000000 if new_world_unit
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 = 1000000
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
- pos = UnitRequirement.new("~> #{manifest_unit.version.segments.slice(0,2).join('.')}").satisfied_by?(unit.version) ? 1 : 0
49
- multi_val = pos == 1 ? 1000 : 100
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 = 10000000 if new_world_unit
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, pos|
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.push (2 - (1.0 / val)) * ((pos + 1)**10)
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
@@ -9,7 +9,15 @@ module Batali
9
9
  autoload :Git, 'batali/source/git'
10
10
  autoload :ChefServer, 'batali/source/chef_server'
11
11
 
12
- attribute :type, String, :required => true, :default => lambda{ self.name }
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(self.respond_to?(:cache))
32
- false
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
- if(File.exists?(asset_path))
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 = [self.name, Bogo::Utility.camel(type)].join('::')
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
- unless(@cache)
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.has_key?(segment))
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))
@@ -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.exists?(c_path)
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
@@ -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
- unless(@cache)
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
@@ -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
- "I got 99 problems but a policyfile ain't one",
7
- "Solve the way you want, not the way you're told",
8
- "Build environments, not applications",
9
- "DRY should be the rule, not the exception",
10
- "Solve for the forest, not just a tree"
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
@@ -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 :dependencies, [Batali::UnitDependency, Grimoire::DEPENDENCY_CLASS], :multiple => true, :default => [], :coerce => lambda{|val| Batali::UnitDependency.new(val.first, *val.last)}
8
- attribute :version, [Batali::UnitVersion, Grimoire::VERSION_CLASS], :required => true, :coerce => lambda{|val| Batali::UnitVersion.new(val)}
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(self.send(k) == u.send(k))
25
- _diff[k] = [self.send(k), u.send(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)
@@ -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
- :cache => cache
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.path)
57
- rest[ckbk.name] = Smash.new(:path => ckbk.path).checksum
58
- elsif(ckbk.git)
59
- rest[ckbk.name] = Smash.new(
60
- :url => ckbk.git,
61
- :ref => ckbk.ref
62
- ).checksum
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
@@ -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
@@ -1,4 +1,5 @@
1
+ # Batali namespace
1
2
  module Batali
2
3
  # Current version
3
- VERSION = Gem::Version.new('0.3.10')
4
+ VERSION = Gem::Version.new('0.3.12')
4
5
  end
@@ -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.exists?(path))
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.10
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-19 00:00:00.000000000 Z
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