Class: MotherBrain::Plugin

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Comparable, VariaModel
Defined in:
lib/mb/plugin.rb

Defined Under Namespace

Classes: CleanRoom

Constant Summary collapse

NODE_GROUP_ID_REGX =
/^(.+)::(.+)$/.freeze
PLUGIN_FILENAME =
'motherbrain.rb'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(metadata, &block) ⇒ Plugin

Returns a new instance of Plugin.

Parameters:



71
72
73
74
75
76
77
78
79
# File 'lib/mb/plugin.rb', line 71

def initialize(, &block)
  @metadata     = 
  @components   = Set.new
  @commands     = Set.new

  if block_given?
    dsl_eval(&block)
  end
end

Instance Attribute Details

#commandsSet<MB::Command> (readonly)

Returns:



60
61
62
# File 'lib/mb/plugin.rb', line 60

def commands
  @commands
end

#componentsSet<MB::Component> (readonly)

Returns:



58
59
60
# File 'lib/mb/plugin.rb', line 58

def components
  @components
end

#metadataMB::CookbookMetadata (readonly)



56
57
58
# File 'lib/mb/plugin.rb', line 56

def 
  @metadata
end

Class Method Details

.from_path(path) ⇒ MotherBrain::Plugin

Load the contents of a directory into an instance of MB::Plugin

Parameters:

  • path (#to_s)

    a path to a directory containing a motherbrain plugin file and cookbook metadata file

Returns:

Raises:



26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/mb/plugin.rb', line 26

def from_path(path)
  unless Dir.has_mb_plugin?(path)
    raise PluginLoadError, "Expected a motherbrain and metadata file at: #{path}"
  end

  plugin_filename = File.join(path, PLUGIN_FILENAME)
  plugin_contents = File.read(plugin_filename)
          = CookbookMetadata.from_path(path)

  load() { eval(plugin_contents, binding, plugin_filename, 1) }
rescue PluginSyntaxError => ex
  raise PluginSyntaxError, ErrorHandler.new(ex, file_path: plugin_filename).message
end

.key_for(name, version) ⇒ Object



40
41
42
# File 'lib/mb/plugin.rb', line 40

def key_for(name, version)
  "#{name}-#{version}".to_sym
end

.load(metadata, &block) ⇒ Object

Create a new plugin instance from the given content

Parameters:

Yield Returns:

Raises:



11
12
13
14
15
# File 'lib/mb/plugin.rb', line 11

def load(, &block)
  new(, &block).validate!
rescue PluginSyntaxError => ex
  ErrorHandler.wrap(ex)
end

Instance Method Details

#<=>(other) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
# File 'lib/mb/plugin.rb', line 232

def <=>(other)
  unless other.is_a?(self.class)
    return 0
  end

  if self.name == other.name
    self.version <=> other.version
  else
    self.name <=> other.name
  end
end

#add_command(command) ⇒ Object

Parameters:



195
196
197
# File 'lib/mb/plugin.rb', line 195

def add_command(command)
  self.commands.add(command)
end

#add_component(component) ⇒ Object

Parameters:



190
191
192
# File 'lib/mb/plugin.rb', line 190

def add_component(component)
  self.components.add(component)
end

#command(name) ⇒ MB::Command?

Return a command from the plugins list of commands.

Parameters:

  • name (#to_s)

    name of the command to find and return

Returns:



121
122
123
# File 'lib/mb/plugin.rb', line 121

def command(name)
  commands.find { |command| command.name == name.to_s }
end

#command!(name) ⇒ MB::Command

Return a command from the plugin’s list of commands. If a command is not found an exception will be rasied.

Parameters:

  • name (#to_s)

    name of the command to find and return

Returns:

Raises:

  • (CommandNotFound)

    if a command matching the given name is not found on this plugin



133
134
135
136
137
138
139
140
141
# File 'lib/mb/plugin.rb', line 133

def command!(name)
  found = command(name)

  if found.nil?
    raise CommandNotFound.new(name, self)
  end

  found
end

#component(name) ⇒ MB::Component?

Parameters:

Returns:



89
90
91
# File 'lib/mb/plugin.rb', line 89

def component(name)
  components.find { |component| component.name == name.to_s }
end

#component!(name) ⇒ MB::Component

Parameters:

Returns:

Raises:

  • (ComponentNotFound)

    if a component of the given name is not a part of this plugin



98
99
100
101
102
103
104
105
106
# File 'lib/mb/plugin.rb', line 98

def component!(name)
  component = component(name)

  if component.nil?
    raise ComponentNotFound.new(name, self)
  end

  component
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


244
245
246
# File 'lib/mb/plugin.rb', line 244

def eql?(other)
  other.is_a?(self.class) && self == other
end

#has_component?(name) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


111
112
113
# File 'lib/mb/plugin.rb', line 111

def has_component?(name)
  component(name).present?
end

#idSymbol

Returns:

  • (Symbol)


82
83
84
# File 'lib/mb/plugin.rb', line 82

def id
  self.class.key_for(self.name, self.version)
end

#messages_from_errors(errors) ⇒ String

Creates an error message from an error hash, where the keys are attributes and the values are an array of error messages.

Parameters:

  • errors (Hash)

Returns:

  • (String)


222
223
224
225
226
227
228
229
230
# File 'lib/mb/plugin.rb', line 222

def messages_from_errors(errors)
  buffer = []

  errors.each do |attribute, messages|
    buffer |= messages
  end

  buffer.join "\n"
end

#nodes(environment) ⇒ Hash

Finds the nodes for the given environment for each Component of the plugin groups them by Component#name and Group#name into a Hash where the keys are Component#name and values are a hash where the keys are Group#name and the values are a Hash representing a node from Chef.

Examples:


{
  "activemq" => {
    database_masters" => [
      {
        "name" => "db-master1",
        ...
      }
    ],
    "database_slaves" => [
      {
        "name" => "db-slave1",
        ...
      },
      {
        "name" => "db-slave2",
        ...
      }
    ]
  }
}

Parameters:

  • environment (#to_s)

Returns:

  • (Hash)

Raises:



177
178
179
180
181
182
183
184
185
186
187
# File 'lib/mb/plugin.rb', line 177

def nodes(environment)
  unless Application.ridley.environment.find(environment)
    raise EnvironmentNotFound.new(environment)
  end

  {}.tap do |nodes|
    self.components.each do |component|
      nodes[component.name] = component.nodes(environment)
    end
  end
end

#to_hashObject



252
253
254
255
256
257
258
259
260
261
# File 'lib/mb/plugin.rb', line 252

def to_hash
  {
    name: name,
    version: version,
    maintainer: maintainer,
    maintainer_email: maintainer_email,
    description: description,
    long_description: long_description
  }
end

#to_json(options = {}) ⇒ String Also known as: as_json

Parameters:

  • options (Hash) (defaults to: {})

    a set of options to pass to MultiJson.encode

Returns:

  • (String)


267
268
269
# File 'lib/mb/plugin.rb', line 267

def to_json(options = {})
  MultiJson.encode(self.to_hash, options)
end

#to_sObject



248
249
250
# File 'lib/mb/plugin.rb', line 248

def to_s
  "#{self.name} (#{self.version})"
end

#validate!self

Completely validate a loaded plugin and raise an exception of errors

Returns:

  • (self)


202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/mb/plugin.rb', line 202

def validate!
  errors = validate

  if errors.any?
    ErrorHandler.wrap PluginSyntaxError,
      backtrace: [],
      plugin_name: try(:name),
      plugin_version: try(:version),
      text: messages_from_errors(errors)
  end

  self
end