Class: Berkshelf::Berksfile
- Inherits:
-
Object
- Object
- Berkshelf::Berksfile
- Extended by:
- Forwardable
- Includes:
- Mixin::Logging
- Defined in:
- lib/berkshelf/berksfile.rb
Overview
Constant Summary collapse
- @@active_group =
nil
Instance Attribute Summary collapse
- #cached_cookbooks ⇒ Array<Berkshelf::CachedCookbook> readonly
- #downloader ⇒ Berkshelf::Downloader readonly
-
#filepath ⇒ String
readonly
The path on disk to the file representing this instance of Berksfile.
Class Method Summary collapse
- .from_file(file) ⇒ Berksfile
-
.vendor(cookbooks, path) ⇒ String
Copy all cached_cookbooks to the given directory.
Instance Method Summary collapse
- #[](name) ⇒ Berkshelf::CookbookSource (also: #get_source)
-
#add_source(name, constraint = nil, options = {}) ⇒ Array<Berkshelf::CookbookSource]
Add a source of the given name and constraint to the array of sources.
-
#chef_api(value, options = {}) ⇒ Hash
Add a ‘Chef API’ default location which will be used to resolve cookbook sources that do not contain an explicit location.
-
#cookbook(*args) ⇒ Object
Add a cookbook source to the Berksfile to be retrieved and have it’s dependencies recursively retrieved and resolved.
- #group(*args) ⇒ Object
-
#groups ⇒ Hash
A hash containing group names as keys and an array of CookbookSources that are a member of that group as values.
- #has_source?(source) ⇒ Boolean
-
#initialize(path) ⇒ Berksfile
constructor
A new instance of Berksfile.
- #install(options = {}) ⇒ Array<Berkshelf::CachedCookbook>
-
#load(content) ⇒ Berksfile
Reload this instance of Berksfile with the given content.
-
#metadata(options = {}) ⇒ Object
Use a Cookbook metadata file to determine additional cookbook sources to retrieve.
-
#outdated(options = {}) ⇒ Hash
Get a list of all the cookbooks which have newer versions found on the community site versus what your current constraints allow.
- #remove_source(source) ⇒ Berkshelf::CookbookSource
-
#resolve(options = {}) ⇒ Array<Berkshelf::CachedCookbooks]
Finds a solution for the Berksfile and returns an array of CachedCookbooks.
-
#site(value) ⇒ Hash
Add a ‘Site’ default location which will be used to resolve cookbook sources that do not contain an explicit location.
- #sources(options = {}) ⇒ Array<Berkshelf::CookbookSource>
- #update(options = {}) ⇒ Object
- #upload(options = {}) ⇒ Object
Methods included from Mixin::Logging
Constructor Details
#initialize(path) ⇒ Berksfile
Returns a new instance of Berksfile.
79 80 81 82 83 84 |
# File 'lib/berkshelf/berksfile.rb', line 79 def initialize(path) @filepath = path @sources = Hash.new @downloader = Downloader.new(Berkshelf.cookbook_store) @cached_cookbooks = nil end |
Instance Attribute Details
#cached_cookbooks ⇒ Array<Berkshelf::CachedCookbook> (readonly)
72 73 74 |
# File 'lib/berkshelf/berksfile.rb', line 72 def cached_cookbooks @cached_cookbooks end |
#downloader ⇒ Berkshelf::Downloader (readonly)
69 70 71 |
# File 'lib/berkshelf/berksfile.rb', line 69 def downloader @downloader end |
#filepath ⇒ String (readonly)
Returns The path on disk to the file representing this instance of Berksfile.
66 67 68 |
# File 'lib/berkshelf/berksfile.rb', line 66 def filepath @filepath end |
Class Method Details
.from_file(file) ⇒ Berksfile
12 13 14 15 16 17 18 |
# File 'lib/berkshelf/berksfile.rb', line 12 def from_file(file) content = File.read(file) object = new(file) object.load(content) rescue Errno::ENOENT => e raise BerksfileNotFound, "No Berksfile or Berksfile.lock found at: #{file}" end |
.vendor(cookbooks, path) ⇒ String
Copy all cached_cookbooks to the given directory. Each cookbook will be contained in a directory named after the name of the cookbook.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/berkshelf/berksfile.rb', line 30 def vendor(cookbooks, path) chefignore = nil path = File.(path) scratch = Berkshelf.mktmpdir FileUtils.mkdir_p(path) unless (ignore_file = Berkshelf::Chef::Cookbook::Chefignore.find_relative_to(Dir.pwd)).nil? chefignore = Berkshelf::Chef::Cookbook::Chefignore.new(ignore_file) end cookbooks.each do |cb| dest = File.join(scratch, cb.cookbook_name, "/") FileUtils.mkdir_p(dest) # Dir.glob does not support backslash as a File separator src = cb.path.to_s.gsub('\\', '/') files = Dir.glob(File.join(src, "*")) # Filter out files using chefignore files = chefignore.remove_ignores_from(files) if chefignore FileUtils.cp_r(files, dest) end FileUtils.remove_dir(path, force: true) FileUtils.mv(scratch, path) path end |
Instance Method Details
#[](name) ⇒ Berkshelf::CookbookSource Also known as: get_source
351 352 353 |
# File 'lib/berkshelf/berksfile.rb', line 351 def [](name) @sources[name] end |
#add_source(name, constraint = nil, options = {}) ⇒ Array<Berkshelf::CookbookSource]
Add a source of the given name and constraint to the array of sources.
255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/berkshelf/berksfile.rb', line 255 def add_source(name, constraint = nil, = {}) if has_source?(name) # Only raise an exception if the source is a true duplicate groups = ([:group].nil? || [:group].empty?) ? [:default] : [:group] if !(@sources[name].groups & groups).empty? raise DuplicateSourceDefined, "Berksfile contains multiple sources named '#{name}'. Use only one, or put them in different groups." end end [:constraint] = constraint @sources[name] = CookbookSource.new(self, name, ) end |
#chef_api(value, options = {}) ⇒ Hash
specifying the symbol :config as the value of the chef_api default location will attempt to use the contents of your Berkshelf configuration to find the Chef API to interact with.
Add a ‘Chef API’ default location which will be used to resolve cookbook sources that do not contain an explicit location.
239 240 241 |
# File 'lib/berkshelf/berksfile.rb', line 239 def chef_api(value, = {}) add_location(:chef_api, value, ) end |
#cookbook(name, version_constraint, options = {}) ⇒ Object #cookbook(name, options = {}) ⇒ Object
Add a cookbook source to the Berksfile to be retrieved and have it’s dependencies recursively retrieved and resolved.
154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/berkshelf/berksfile.rb', line 154 def cookbook(*args) = args.last.is_a?(Hash) ? args.pop : Hash.new name, constraint = args [:group] = Array([:group]) if @@active_group [:group] += @@active_group end add_source(name, constraint, ) end |
#group(*args) ⇒ Object
167 168 169 170 171 |
# File 'lib/berkshelf/berksfile.rb', line 167 def group(*args) @@active_group = args yield @@active_group = nil end |
#groups ⇒ Hash
Returns a hash containing group names as keys and an array of CookbookSources that are a member of that group as values
Example:
{
nautilus: [
#<Berkshelf::CookbookSource @name="nginx">,
#<Berkshelf::CookbookSource @name="mysql">,
],
skarner: [
#<Berkshelf::CookbookSource @name="nginx">
]
}.
336 337 338 339 340 341 342 343 344 345 |
# File 'lib/berkshelf/berksfile.rb', line 336 def groups {}.tap do |groups| sources.each do |source| source.groups.each do |group| groups[group] ||= [] groups[group] << source end end end end |
#has_source?(source) ⇒ Boolean
282 283 284 |
# File 'lib/berkshelf/berksfile.rb', line 282 def has_source?(source) @sources.has_key?(source.to_s) end |
#install(options = {}) ⇒ Array<Berkshelf::CachedCookbook>
367 368 369 370 371 372 373 374 375 376 377 378 |
# File 'lib/berkshelf/berksfile.rb', line 367 def install( = {}) resolver = Resolver.new(self, sources: sources()) @cached_cookbooks = resolver.resolve write_lockfile(resolver.sources) unless lockfile_present? if [:path] self.class.vendor(@cached_cookbooks, [:path]) end self.cached_cookbooks end |
#load(content) ⇒ Berksfile
Reload this instance of Berksfile with the given content. The content is a string that may contain terms from the included DSL.
560 561 562 563 564 565 566 567 |
# File 'lib/berkshelf/berksfile.rb', line 560 def load(content) begin instance_eval(content) rescue => e raise BerksfileReadError.new(e), "An error occurred while reading the Berksfile: #{e.to_s}" end self end |
#metadata(options = {}) ⇒ Object
Use a Cookbook metadata file to determine additional cookbook sources to retrieve. All sources found in the metadata will use the default locations set in the Berksfile (if any are set) or the default locations defined by Berkshelf.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/berkshelf/berksfile.rb', line 181 def ( = {}) path = [:path] || File.dirname(filepath) = Berkshelf.(path) unless raise CookbookNotFound, "No 'metadata.rb' found at #{path}" end = Ridley::Chef::Cookbook::Metadata.from_file(.to_s) name = if .name.empty? || .name.nil? File.basename(File.dirname()) else .name end constraint = "= #{.version}" add_source(name, constraint, path: File.dirname()) end |
#outdated(options = {}) ⇒ Hash
Get a list of all the cookbooks which have newer versions found on the community site versus what your current constraints allow
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/berkshelf/berksfile.rb', line 430 def outdated( = {}) outdated = Hash.new sources().each do |cookbook| location = cookbook.location || Location.init(cookbook.name, cookbook.version_constraint) if location.is_a?(SiteLocation) latest_version = location.latest_version unless cookbook.version_constraint.satisfies?(latest_version) outdated[cookbook] = latest_version end end end outdated end |
#remove_source(source) ⇒ Berkshelf::CookbookSource
274 275 276 |
# File 'lib/berkshelf/berksfile.rb', line 274 def remove_source(source) @sources.delete(source.to_s) end |
#resolve(options = {}) ⇒ Array<Berkshelf::CachedCookbooks]
Finds a solution for the Berksfile and returns an array of CachedCookbooks.
548 549 550 |
# File 'lib/berkshelf/berksfile.rb', line 548 def resolve( = {}) resolver().resolve end |
#site(value) ⇒ Hash
specifying the symbol :opscode as the value of the site default location is an alias for the latest API of the Opscode Community Site.
Add a ‘Site’ default location which will be used to resolve cookbook sources that do not contain an explicit location.
217 218 219 |
# File 'lib/berkshelf/berksfile.rb', line 217 def site(value) add_location(:site, value) end |
#sources(options = {}) ⇒ Array<Berkshelf::CookbookSource>
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/berkshelf/berksfile.rb', line 298 def sources( = {}) l_sources = @sources.collect { |name, source| source }.flatten cookbooks = Array(.fetch(:cookbooks, nil)) except = Array(.fetch(:except, nil)).collect(&:to_sym) only = Array(.fetch(:only, nil)).collect(&:to_sym) case when !except.empty? && !only.empty? raise Berkshelf::ArgumentError, "Cannot specify both :except and :only" when !cookbooks.empty? if !except.empty? && !only.empty? Berkshelf.ui.warn "Cookbooks were specified, ignoring :except and :only" end l_sources.select { |source| [:cookbooks].include?(source.name) } when !except.empty? l_sources.select { |source| (except & source.groups).empty? } when !only.empty? l_sources.select { |source| !(only & source.groups).empty? } else l_sources end end |
#update(options = {}) ⇒ Object
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
# File 'lib/berkshelf/berksfile.rb', line 388 def update( = {}) resolver = Resolver.new(self, sources: sources()) cookbooks = resolver.resolve sources = resolver.sources missing_cookbooks = ([:cookbooks] - cookbooks.map(&:cookbook_name)) unless missing_cookbooks.empty? msg = "Could not find cookbooks #{missing_cookbooks.collect{|cookbook| "'#{cookbook}'"}.join(', ')}" msg << " in any of the sources. #{missing_cookbooks.size == 1 ? 'Is it' : 'Are they' } in your Berksfile?" raise Berkshelf::CookbookNotFound, msg end update_lockfile(sources) if [:path] self.class.vendor(cookbooks, [:path]) end cookbooks end |
#upload(options = {}) ⇒ Object
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
# File 'lib/berkshelf/berksfile.rb', line 475 def upload( = {}) = .reverse_merge( force: false, freeze: true, ssl_verify: Berkshelf::Config.instance.ssl.verify, skip_dependencies: false, halt_on_frozen: false ) = .slice(:ssl) [:server_url] = [:server_url] || Berkshelf::Config.instance.chef.chef_server_url [:client_name] = Berkshelf::Config.instance.chef.node_name [:client_key] = Berkshelf::Config.instance.chef.client_key [:ssl] = { verify: [:ssl_verify] } unless [:server_url].present? raise UploadFailure, "Missing required attribute in your Berkshelf configuration: chef.server_url" end unless [:client_name].present? raise UploadFailure, "Missing required attribute in your Berkshelf configuration: chef.node_name" end unless [:client_key].present? raise UploadFailure, "Missing required attribute in your Berkshelf configuration: chef.client_key" end solution = resolve() upload_opts = .slice(:force, :freeze) conn = Ridley.new() solution.each do |cb| Berkshelf.formatter.upload(cb.cookbook_name, cb.version, conn.server_url) begin conn.cookbook.upload(cb.path, upload_opts.merge(name: cb.cookbook_name)) rescue Ridley::Errors::FrozenCookbook => ex if [:halt_on_frozen] raise Berkshelf::FrozenCookbook, ex end end end if [:skip_dependencies] missing_cookbooks = .fetch(:cookbooks, nil) - solution.map(&:cookbook_name) unless missing_cookbooks.empty? msg = "Unable to upload cookbooks: #{missing_cookbooks.sort.join(', ')}\n" msg << "Specified cookbooks must be defined within the Berkshelf file when using the" msg << " `--skip-dependencies` option" raise ExplicitCookbookNotFound.new(msg) end end rescue Ridley::Errors::RidleyError => ex log_exception(ex) raise UploadFailure, ex ensure conn.terminate if conn && conn.alive? end |