class Kriterion::Backend::MongoDB

Attributes

client[R]
database[R]
events_db[R]
hostname[R]
items_db[R]
port[R]
resources_db[R]
sections_db[R]
standard_details_db[R]
standards_db[R]

Public Class Methods

new(opts) click to toggle source
Calls superclass method Kriterion::Backend::new
# File lib/kriterion/backend/mongodb.rb, line 27
def initialize(opts)
  super(opts)
  logger.info 'Initializing MongoDB backend'
  @hostname            = opts[:hostname]
  @port                = opts[:port]
  @database            = opts[:database]
  @client              = Mongo::Client.new(
    ["#{@hostname}:#{@port}"], database: @database
  )
  @client.logger.level = logger.level
  @standards_db        = @client[:standards]
  @sections_db         = @client[:sections]
  @items_db            = @client[:items]
  @resources_db        = @client[:resources]
  @events_db           = @client[:events]
  @standard_details_db = @client[:standard_details]
end

Public Instance Methods

add_unchanged_node(resource, certname) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 64
def add_unchanged_node(resource, certname)
  resources_db.update_one(
    { resource: resource.resource },
    '$addToSet' => {
      unchanged_nodes: certname
    }
  )
end
find(type, query, opts) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 45
def find(type, query, opts)
  database_for(type).find(query).map do |result|
    # Sanitise the data if required
    params = sanitise_data(type, result)

    # Create the object and return in an array
    object = class_for(type).new(params)

    # Find children if required
    find_children!(object) if opts[:recurse]

    object
  end
end
insert(object) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 60
def insert(object)
  insert_into_db(database_for(object), object)
end
purge_events!(certname) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 82
def purge_events!(certname)
  # Delete all events for this certname
  events_db.delete_many(
    certname: certname
  )

  # Delete all instances of this certname under "unchanged_nodes"
  resources_db.update_many(
    {}, # Don't pass a query as we want to purge everything
    '$pull' => { # Remove this node from unchanged nodes
      unchanged_nodes: certname
    }
  )
end
update_compliance!(thing) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 73
def update_compliance!(thing)
  database_for(thing).update_one(
    { uuid: thing.uuid },
    '$set' => {
      compliance: thing.compliance
    }
  )
end

Private Instance Methods

class_for(name) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 121
def class_for(name)
  classes = {
    'standard' => Kriterion::Standard,
    'section'  => Kriterion::Section,
    'item'     => Kriterion::Item,
    'resource' => Kriterion::Resource,
    'event'    => Kriterion::Event
  }
  # If someone has passed in an object, just return the class
  return name.class if classes.value? name.class

  classes[name.to_s]
end
database_for(object) click to toggle source

Returns the database for a given object type

# File lib/kriterion/backend/mongodb.rb, line 109
def database_for(object)
  cls = class_for(object)
  databases = {
    Kriterion::Standard => @standards_db,
    Kriterion::Section  => @sections_db,
    Kriterion::Item     => @items_db,
    Kriterion::Resource => @resources_db,
    Kriterion::Event    => @events_db
  }
  databases[cls]
end
find_child_items(parent) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 196
def find_child_items(parent)
  results = items_db.find(
    parent_type: parent.type,
    parent_uuid: parent.uuid
  )

  results.map do |item|
    Kriterion::Item.new(item)
  end
end
find_child_sections(parent) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 207
def find_child_sections(parent)
  result = sections_db.find(
    parent_type: parent.type,
    parent_uuid: parent.uuid
  )
  result.map do |section|
    Kriterion::Section.new(section)
  end
end
find_children!(object) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 135
def find_children!(object)
  accepted_objects = [
    Kriterion::Standard,
    Kriterion::Section,
    Kriterion::Item,
    Kriterion::Resource,
    Kriterion::Event
  ]

  unless accepted_objects.include?(object.class)
    raise "Unsupported object type #{object.class.name}"
  end

  case object
  when Kriterion::Item
    result = resources_db.find(
      parent_uuid: object.uuid
    )

    result.each do |resource|
      resource = Kriterion::Resource.new(resource)
      find_children! resource
      object.resources << resource
    end
  when Kriterion::Resource
    result = events_db.find(
      resource: object.resource
    )

    result.each do |event|
      event = Kriterion::Event.new(event)
      find_children! event
      object.events << event
    end
  when Kriterion::Event
    nil
  else
    # We can safely assume this is a Kriterion::Standard or
    # Kriterion::Section, which are treated the same

    # Find all child sections and add them to the standard
    find_child_sections(object).each do |section|
      object.sections << section
      # Also recurse and find all children of each child we find
      find_children!(section)
    end

    # Find all direct child items
    find_child_items(object).each do |item|
      object.items << item
      find_children!(item)
    end
  end
end
insert_into_db(database, thing) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 190
def insert_into_db(database, thing)
  result = database.insert_one(thing.to_h)
  raise "Insertion of #{thing} failed" unless result.ok?
  thing
end
sanitise_data(type, data) click to toggle source
# File lib/kriterion/backend/mongodb.rb, line 99
def sanitise_data(type, data)
  if type == :standard
    return nil if data.nil?
    # Compile the regex from a lazy-compiled BSON regex back to a ruby one
    data['item_syntax'] = data['item_syntax'].compile
  end
  data  
end