summaryrefslogtreecommitdiff
path: root/chef/lib/chef/cookbook_version.rb
diff options
context:
space:
mode:
Diffstat (limited to 'chef/lib/chef/cookbook_version.rb')
-rw-r--r--chef/lib/chef/cookbook_version.rb301
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