class DataMapper::Adapters::ChefAdapter

Public Class Methods

new(name, opts = {}) click to toggle source

@api semipublic

Calls superclass method
# File lib/dm-chef-adapter/adapter.rb, line 116
def initialize(name, opts = {})
  super
  Chef::Config.configuration[:node_name] = opts["node_name"]
        Chef::Config.configuration[:client_key] = opts["client_key"]
        Chef::Config.configuration[:chef_server_url] = opts["chef_server_url"] if !opts["chef_server_url"].nil?
  if opts["memcache"]
    require 'dalli'
    @cache = Dalli::Client.new(opts["memcache_url"])
  else
    @cache = nil
  end
  @uuid = UUIDTools::UUID
end

Public Instance Methods

attributes_as_fields(attributes) click to toggle source

@api semipublic

# File lib/dm-chef-adapter/adapter.rb, line 105
def attributes_as_fields(attributes)
  pairs = attributes.map do |property, value|
    dumped = value.kind_of?(Module) ? value.name : property.dump(value)
    [ property.field, dumped ]
  end
  Hash[pairs]
end
create(resources) click to toggle source

@api semipublic

# File lib/dm-chef-adapter/adapter.rb, line 30
def create(resources)
  resources.collect do |resource|
    if !Chef::DataBag.list.keys.include?(resource.class.storage_name)
      databag = Chef::DataBag.new
      databag.name resource.class.storage_name
      databag.create
    end
    begin
      resource.id = @uuid.sha1_create(
        UUIDTools::UUID_DNS_NAMESPACE, 
        ("%10.6f#{resource.class.storage_name}" % Time.now.to_f)
      )
    rescue
      resource.send :instance_variable_set, :@id, resource.key
    end
    if !Chef::DataBag.load(resource.class.storage_name).keys.include?(resource.key.join('_'))
      databag_item = Chef::DataBagItem.new
      databag_item.data_bag resource.class.storage_name
      data = {"id" => resource.key.join('_')}
      data.merge! Chef::JSONCompat.from_json(resource.to_json)
      databag_item.raw_data = data
      databag_item.create
      if !@cache.nil?
        @cache.delete(resource.class.storage_name)
      end
    else
      raise "DataBagItem #{resource.class.storage_name}/#{resource.key.join('_')} already exists."
    end
  end.count
end
delete(collection) click to toggle source

@api semipublic

# File lib/dm-chef-adapter/adapter.rb, line 94
def delete(collection)
  read(collection.query).each do |doc|
    databag_item = Chef::DataBagItem.load collection.storage_name, doc["id"]
    databag_item.destroy collection.storage_name, doc["id"]
    if !@cache.nil?
      @cache.delete(collection.storage_name)
    end
  end
end
read(query) click to toggle source

@api semipublic

# File lib/dm-chef-adapter/adapter.rb, line 62
def read(query)
  records = records_for(query.model.storage_name)
  ret = []
  query.links.reverse.each do |link|
    children = records_for(link.child_model.storage_name)
    parents = records_for(link.parent_model.storage_name)
    children.each do |child|
      parents.each do |parent|
        if child[link.child_key.first.name.to_s] == parent[link.parent_key.first.name.to_s]
          records.each do |record|
            ret << child.merge(record)
          end
        end
      end
    end
  end
  query.filter_records(ret+records)
end
update(attributes, collection) click to toggle source
# File lib/dm-chef-adapter/adapter.rb, line 81
def update(attributes, collection)
  fields = attributes_as_fields(attributes)
  read(collection.query).each do |doc|
    databag_item = Chef::DataBagItem.load collection.storage_name, doc["id"]
    databag_item.raw_data.merge! Chef::JSONCompat.from_json(fields.to_json)
    databag_item.save
    if !@cache.nil?
      @cache.delete(collection.storage_name)
    end
  end
end

Private Instance Methods

chef_databag(model) click to toggle source

Given a model, gives the databag to be used for record storage

@example

chef_databag(Article) #=> "Chef::DataBag"

@param [#storage_name] model

The model to be used to determine the databag.

@api private

# File lib/dm-chef-adapter/adapter.rb, line 194
def chef_databag(model)
  begin
    Chef::DataBag.load model
  rescue
    nil
  end
end
records_for(model) click to toggle source

Read all records from a databag for a model

@param [#storage_name] model

The model/name to retieve records for

@api private

# File lib/dm-chef-adapter/adapter.rb, line 155
def records_for(model)
  if !@cache.nil?
      return @cache.get(model) if !@cache.get(model).nil?
  end
        records = []
        databag = chef_databag(model)
        if !databag.nil?
    chef_databag(model).keys.each do |key|
      records << Chef::DataBagItem.load(model, key).raw_data
    end
  end
  @cache.set(model, records, 60) if !@cache.nil?
  return records
 end
update_records(model) { |records| ... } click to toggle source

Retrieves all records for a model and yields them to a block.

The block should make any changes to the records in-place. After the block executes all the records are dumped back to the databag.

@param [Model, to_s] model

Used to determine which file to read/write to

@yieldparam [Hash]

A hash of record.key => record pairs retrieved from the databag

@api private

# File lib/dm-chef-adapter/adapter.rb, line 142
def update_records(model)
  records = records_for(model)
  result = yield records
  write_records(model, records)
  result
end
write_records(model, records) click to toggle source

Writes all records to a databag

@param [#storage_name] model

The model/name to write the records for

@param [Hash] records

A hash of record.key => record pairs to be written

@api private

# File lib/dm-chef-adapter/adapter.rb, line 179
def write_records(model, records)
  item = Chef::DataBagItem.load(model. records["id"])
  item.from_hash records
  item.save
end