diff options
Diffstat (limited to 'chef/lib/chef/cookbook_version.rb')
-rw-r--r-- | chef/lib/chef/cookbook_version.rb | 301 |
1 files changed, 1 insertions, 300 deletions
diff --git a/chef/lib/chef/cookbook_version.rb b/chef/lib/chef/cookbook_version.rb index a6f95e2c3b..0e11174a07 100644 --- a/chef/lib/chef/cookbook_version.rb +++ b/chef/lib/chef/cookbook_version.rb @@ -24,86 +24,11 @@ require 'chef/node' require 'chef/resource_definition_list' require 'chef/recipe' require 'chef/cookbook/file_vendor' -require 'chef/checksum' require 'chef/cookbook/metadata' require 'chef/version_class' class Chef - #== Chef::MinimalCookbookVersion - # MinimalCookbookVersion is a duck type of CookbookVersion, used - # internally by Chef Server as an optimization when determining the - # optimal cookbook set for a chef-client. - # - # MinimalCookbookVersion objects contain only enough information to - # solve the cookbook collection for a given run list. They *do not* - # contain enough information to generate the response. - # - # See also: Chef::CookbookVersionSelector - class MinimalCookbookVersion - - include Comparable - - ID = "id".freeze - NAME = 'name'.freeze - KEY = 'key'.freeze - VERSION = 'version'.freeze - VALUE = 'value'.freeze - DEPS = 'deps'.freeze - - DEPENDENCIES = 'dependencies'.freeze - - # Loads the full list of cookbooks, using a couchdb view to fetch - # only the id, name, version, and dependency constraints. This is - # enough information to solve for the cookbook collection for a - # given run list. After solving for the cookbook collection, you - # need to call +load_full_versions_of+ to convert - # MinimalCookbookVersion objects to their non-minimal counterparts - def self.load_all(couchdb) - # Example: - # {"id"=>"1a806f1c-b409-4d8e-abab-fa414ff5b96d", "key"=>"activemq", "value"=>{"version"=>"0.3.3", "deps"=>{"java"=>">= 0.0.0", "runit"=>">= 0.0.0"}}} - couchdb ||= Chef::CouchDB.new - couchdb.get_view("cookbooks", "all_with_version_and_deps")["rows"].map {|params| self.new(params) } - end - - # Loads the non-minimal CookbookVersion objects corresponding to - # +minimal_cookbook_versions+ from couchdb using a bulk GET. - def self.load_full_versions_of(minimal_cookbook_versions, couchdb) - database_ids = Array(minimal_cookbook_versions).map {|mcv| mcv.couchdb_id } - couchdb ||= Chef::CouchDB.new - couchdb.bulk_get(*database_ids) - end - - attr_reader :couchdb_id - attr_reader :name - attr_reader :version - attr_reader :deps - - def initialize(params) - @couchdb_id = params[ID] - @name = params[KEY] - @version = params[VALUE][VERSION] - @deps = params[VALUE][DEPS] - end - - # Returns the Cookbook::MinimalMetadata object for this cookbook - # version. - def metadata - @metadata ||= Cookbook::MinimalMetadata.new(@name, DEPENDENCIES => @deps) - end - - def legit_version - @legit_version ||= Chef::Version.new(@version) - end - - def <=>(o) - raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != o.name - raise "Unexpected comparison to #{o}" unless o.respond_to?(:legit_version) - legit_version <=> o.legit_version - end - end - - # == Chef::CookbookVersion # CookbookVersion is a model object encapsulating the data about a Chef # cookbook. Chef supports maintaining multiple versions of a cookbook on a @@ -113,140 +38,10 @@ class Chef # TODO: timh/cw: 5-24-2010: mutators for files (e.g., recipe_filenames=, # recipe_filenames.insert) should dirty the manifest so it gets regenerated. class CookbookVersion - include Chef::IndexQueue::Indexable include Comparable COOKBOOK_SEGMENTS = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ] - DESIGN_DOCUMENT = { - "version" => 8, - "language" => "javascript", - "views" => { - "all" => { - "map" => <<-EOJS - function(doc) { - if (doc.chef_type == "cookbook_version") { - emit(doc.name, doc); - } - } - EOJS - }, - "all_id" => { - "map" => <<-EOJS - function(doc) { - if (doc.chef_type == "cookbook_version") { - emit(doc.name, doc.name); - } - } - EOJS - }, - "all_with_version" => { - "map" => <<-EOJS - function(doc) { - if (doc.chef_type == "cookbook_version") { - emit(doc.cookbook_name, doc.version); - } - } - EOJS - }, - "all_with_version_and_deps" => { - "map" => <<-JS - function(doc) { - if (doc.chef_type == "cookbook_version") { - emit(doc.cookbook_name, {version: doc.version, deps: doc.metadata.dependencies}); - } - } - JS - }, - "all_latest_version" => { - "map" => %q@ - function(doc) { - if (doc.chef_type == "cookbook_version") { - emit(doc.cookbook_name, doc.version); - } - } - @, - "reduce" => %q@ - function(keys, values, rereduce) { - var result = null; - - for (var idx in values) { - var value = values[idx]; - - if (idx == 0) { - result = value; - continue; - } - - var valueParts = value.split('.').map(function(v) { return parseInt(v); }); - var resultParts = result.split('.').map(function(v) { return parseInt(v); }); - - if (valueParts[0] != resultParts[0]) { - if (valueParts[0] > resultParts[0]) { - result = value; - } - } - else if (valueParts[1] != resultParts[1]) { - if (valueParts[1] > resultParts[1]) { - result = value; - } - } - else if (valueParts[2] != resultParts[2]) { - if (valueParts[2] > resultParts[2]) { - result = value; - } - } - } - return result; - } - @ - }, - "all_latest_version_by_id" => { - "map" => %q@ - function(doc) { - if (doc.chef_type == "cookbook_version") { - emit(doc.cookbook_name, {version: doc.version, id:doc._id}); - } - } - @, - "reduce" => %q@ - function(keys, values, rereduce) { - var result = null; - - for (var idx in values) { - var value = values[idx]; - - if (idx == 0) { - result = value; - continue; - } - - var valueParts = value.version.split('.').map(function(v) { return parseInt(v); }); - var resultParts = result.version.split('.').map(function(v) { return parseInt(v); }); - - if (valueParts[0] != resultParts[0]) { - if (valueParts[0] > resultParts[0]) { - result = value; - } - } - else if (valueParts[1] != resultParts[1]) { - if (valueParts[1] > resultParts[1]) { - result = value; - } - } - else if (valueParts[2] != resultParts[2]) { - if (valueParts[2] > resultParts[2]) { - result = value; - } - } - } - return result; - } - @ - }, - } - } - attr_accessor :root_dir attr_accessor :definition_filenames attr_accessor :template_filenames @@ -259,10 +54,6 @@ class Chef attr_accessor :metadata attr_accessor :metadata_filenames attr_accessor :status - attr_accessor :couchdb_rev - attr_accessor :couchdb - - attr_reader :couchdb_id # attribute_filenames also has a setter that has non-default # functionality. @@ -401,7 +192,7 @@ class Chef # # === Returns # object<Chef::CookbookVersion>:: Duh. :) - def initialize(name, couchdb=nil) + def initialize(name) @name = name @frozen = false @attribute_filenames = Array.new @@ -416,9 +207,6 @@ class Chef @metadata_filenames = Array.new @root_dir = nil @root_filenames = Array.new - @couchdb_id = nil - @couchdb = couchdb || Chef::CouchDB.new - @couchdb_rev = nil @status = :ready @manifest = nil @file_vendor = nil @@ -761,7 +549,6 @@ class Chef result = manifest.dup result['frozen?'] = frozen_version? result['chef_type'] = 'cookbook_version' - result["_rev"] = couchdb_rev if couchdb_rev result.to_hash end @@ -773,15 +560,6 @@ class Chef def self.json_create(o) cookbook_version = new(o["cookbook_name"]) - if o.has_key?('_rev') - cookbook_version.couchdb_rev = o["_rev"] if o.has_key?("_rev") - o.delete("_rev") - end - if o.has_key?("_id") - cookbook_version.couchdb_id = o["_id"] if o.has_key?("_id") - cookbook_version.index_id = cookbook_version.couchdb_id - o.delete("_id") - end # We want the Chef::Cookbook::Metadata object to always be inflated cookbook_version.metadata = Chef::Cookbook::Metadata.from_hash(o["metadata"]) cookbook_version.manifest = o @@ -888,83 +666,6 @@ class Chef chef_server_rest.get_rest('cookbooks/_latest') end - ## - # Couchdb - ## - - def self.cdb_by_name(cookbook_name, couchdb=nil) - cdb = (couchdb || Chef::CouchDB.new) - options = { :startkey => cookbook_name, :endkey => cookbook_name } - rs = cdb.get_view("cookbooks", "all_with_version", options) - rs["rows"].inject({}) { |memo, row| memo.has_key?(row["key"]) ? memo[row["key"]] << row["value"] : memo[row["key"]] = [ row["value"] ]; memo } - end - - def self.create_design_document(couchdb=nil) - (couchdb || Chef::CouchDB.new).create_design_document("cookbooks", DESIGN_DOCUMENT) - end - - def self.cdb_list_latest(inflate=false, couchdb=nil) - couchdb ||= Chef::CouchDB.new - if inflate - doc_ids = cdb_list_latest_ids.map {|i|i["id"]} - couchdb.bulk_get(doc_ids) - else - results = couchdb.get_view("cookbooks", "all_latest_version", :group=>true)["rows"] - results.inject({}) { |mapped, row| mapped[row["key"]] = row["value"]; mapped} - end - end - - def self.cdb_list_latest_ids(inflate=false, couchdb=nil) - couchdb ||= Chef::CouchDB.new - results = couchdb.get_view("cookbooks", "all_latest_version_by_id", :group=>true)["rows"] - results.map { |name_and_id| name_and_id["value"]} - end - - def self.cdb_list(inflate=false, couchdb=nil) - couchdb ||= Chef::CouchDB.new - if inflate - couchdb.list("cookbooks", true)["rows"].collect{|r| r["value"]} - else - # If you modify this, please make sure the desc sorted order on the versions doesn't get broken. - couchdb.get_view("cookbooks", "all_with_version")["rows"].inject({}) { |mapped, row| mapped[row["key"]]||=Array.new; mapped[row["key"]].push(Chef::Version.new(row["value"])); mapped[row["key"]].sort!.reverse!; mapped} - end - end - - def self.cdb_load(name, version='latest', couchdb=nil) - cdb = couchdb || Chef::CouchDB.new - if version == "latest" || version == "_latest" - rs = cdb.get_view("cookbooks", "all_latest_version", :key => name, :descending => true, :group => true, :reduce => true)["rows"].first - cdb.load("cookbook_version", "#{rs["key"]}-#{rs["value"]}") - else - cdb.load("cookbook_version", "#{name}-#{version}") - end - end - - def cdb_destroy - (couchdb || Chef::CouchDB.new).delete("cookbook_version", full_name, couchdb_rev) - end - - # Runs on Chef Server (API); deletes the cookbook from couchdb and also destroys associated - # checksum documents - def purge - checksums.keys.each do |checksum| - begin - Chef::Checksum.cdb_load(checksum, couchdb).purge - rescue Chef::Exceptions::CouchDBNotFound - end - end - cdb_destroy - end - - def cdb_save - @couchdb_rev = couchdb.store("cookbook_version", full_name, self)["rev"] - end - - def couchdb_id=(value) - @couchdb_id = value - @index_id = value - end - def <=>(o) raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != o.name # FIXME: can we change the interface to the Metadata class such |