Class: Vop::Vop

Inherits:
Object
  • Object
show all
Defined in:
lib/vop/vop.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Vop

Returns a new instance of Vop.



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/vop/vop.rb', line 30

def initialize(options = {})
  @options = {
    config_path: "/etc/vop",
    log_level: Logger::INFO
  }.merge(options)
  $logger.level = @options[:log_level]

  @finder = PluginFinder.new
  @loader = PluginLoader.new(self)
  @sorter = DependencyResolver.new(self)

  _reset
end

Instance Attribute Details

#commandsObject (readonly)

Returns the value of attribute commands.



22
23
24
# File 'lib/vop/vop.rb', line 22

def commands
  @commands
end

#entitiesObject (readonly)

Returns the value of attribute entities.



23
24
25
# File 'lib/vop/vop.rb', line 23

def entities
  @entities
end

#filter_chainObject (readonly)

Returns the value of attribute filter_chain.



26
27
28
# File 'lib/vop/vop.rb', line 26

def filter_chain
  @filter_chain
end

#filtersObject (readonly)

Returns the value of attribute filters.



25
26
27
# File 'lib/vop/vop.rb', line 25

def filters
  @filters
end

#finderObject (readonly)

Returns the value of attribute finder.



28
29
30
# File 'lib/vop/vop.rb', line 28

def finder
  @finder
end

#loaderObject (readonly)

Returns the value of attribute loader.



28
29
30
# File 'lib/vop/vop.rb', line 28

def loader
  @loader
end

#pluginsObject (readonly)

Returns the value of attribute plugins.



21
22
23
# File 'lib/vop/vop.rb', line 21

def plugins
  @plugins
end

#sorterObject (readonly)

Returns the value of attribute sorter.



28
29
30
# File 'lib/vop/vop.rb', line 28

def sorter
  @sorter
end

Instance Method Details

#<<(stuff) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/vop/vop.rb', line 142

def <<(stuff)
  if stuff.is_a? Array
    stuff.each do |thing|
      self << thing
    end
  else
    if stuff.is_a? Plugin
      @plugins << stuff
    elsif stuff.is_a? EntityDefinition
      entity = stuff
      @entities[entity.short_name] = stuff
    elsif stuff.is_a? Command
      command = stuff
      unless command.dont_register
        $logger.debug "registering #{command.name}"
        if @commands.keys.include? command.short_name
          $logger.warn "overriding previous declaration of #{command.short_name}"
        end
        @commands[command.short_name] = stuff

        self.class.send(:define_method, command.short_name) do |*args, &block|
          ruby_args = args.length > 0 ? args[0] : {}
          # TODO we might want to do this only if there's a block param defined
          if block
            ruby_args["block"] = block
          end
          self.execute(command.short_name, ruby_args)
        end
      end
    elsif stuff.is_a? Filter
      short_name = stuff.short_name
      @filters[short_name] = stuff
      @filter_chain.unshift short_name
    else
      raise Errors::LoadError.new "unexpected type '#{stuff.class}'"
    end
  end
end

#_resetObject



53
54
55
56
# File 'lib/vop/vop.rb', line 53

def _reset
  clear
  load
end

#call_global_hook(hook_sym, payload = {}) ⇒ Object



185
186
187
188
189
# File 'lib/vop/vop.rb', line 185

def call_global_hook(hook_sym, payload = {})
  @hooks[hook_sym].each do |h|
    h.call(payload)
  end
end

#clearObject



44
45
46
47
48
49
50
51
# File 'lib/vop/vop.rb', line 44

def clear
  @plugins = []
  @commands = {}
  @entities = {}
  @filters = {}
  @filter_chain = []
  @hooks = Hash.new { |h,k| h[k] = [] }
end

#config_pathObject



106
107
108
# File 'lib/vop/vop.rb', line 106

def config_path
  @options[:config_path]
end

#core_locationObject



78
79
80
# File 'lib/vop/vop.rb', line 78

def core_location
  File.join(lib_path, "core")
end

#execute(command_name, param_values = {}, extra = {}) ⇒ Object



207
208
209
210
211
212
# File 'lib/vop/vop.rb', line 207

def execute(command_name, param_values = {}, extra = {})
  request = Request.new(self, command_name, param_values, extra)
  response = execute_request(request)

  response.result
end

#execute_async(request) ⇒ Object



214
215
216
# File 'lib/vop/vop.rb', line 214

def execute_async(request)
  AsyncExecutorWorker.perform_async(request.to_json)
end

#execute_request(request) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/vop/vop.rb', line 191

def execute_request(request)
  call_global_hook(:before_execute, { request: request })
  begin
    response = request.execute()
  rescue => e
    response = ::Vop::Response.new(nil, {})
    response.status = "error"
    raise e
  ensure
    call_global_hook(:after_execute, { request: request, response: response })
  end

  #$logger.debug "executed : #{request.command.name}, response : #{response.pretty_inspect}"
  response
end

#executorObject



114
115
116
# File 'lib/vop/vop.rb', line 114

def executor
  @executor ||= Executor.new(self)
end

#hook(hook_sym, &block) ⇒ Object



181
182
183
# File 'lib/vop/vop.rb', line 181

def hook(hook_sym, &block)
  @hooks[hook_sym] << block
end

#inspectObject



62
63
64
65
66
# File 'lib/vop/vop.rb', line 62

def inspect
  {
    plugins: @plugins.map(&:name)
  }.to_json()
end

#lib_pathObject



74
75
76
# File 'lib/vop/vop.rb', line 74

def lib_path
  Pathname.new(File.join(File.dirname(__FILE__), "..")).realpath
end

#loadObject



132
133
134
135
136
137
138
139
140
# File 'lib/vop/vop.rb', line 132

def load
  load_from(core_location, { core: true })
  load_from(plugin_locations)
  load_from(search_path)

  call_global_hook :loading_finished

  $logger.info "init complete : #{@plugins.size} plugins, #{@commands.size} commands"
end

#load_from(locations, load_options = {}) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/vop/vop.rb', line 118

def load_from(locations, load_options = {})
  found = finder.find(locations)
  plugins = loader.load(found, load_options)
  new_plugins = sorter.sort(plugins.loaded)

  new_plugins.each do |plugin|
    plugin.init
    self << plugin
  end

  $logger.debug "loaded #{new_plugins.size} plugins from #{locations}"
  $logger.debug plugins.loaded.map(&:name)
end

#plugin(name) ⇒ Object



68
69
70
71
72
# File 'lib/vop/vop.rb', line 68

def plugin(name)
  result = @plugins.select { |x| x.name == name }.first
  raise "no such plugin: #{name}" if result.nil?
  result
end

#plugin_config_pathObject



110
111
112
# File 'lib/vop/vop.rb', line 110

def plugin_config_path
  @plugin_config_path ||= File.join(config_path, "plugins.d")
end

#plugin_locationsObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/vop/vop.rb', line 82

def plugin_locations
  result = []

  # during development, we might find checkouts for "plugins" and "services"
  # next to the core
  vop_dir = Pathname.new(File.join(lib_path, "..", "..")).realpath
  unless vop_dir.to_s.start_with? "/usr"
    %w|plugins services|.each do |thing|
      sibling_dir = File.join(vop_dir, thing)
      result << sibling_dir
    end
  end

  # for distribution packages (?)
  result << "/usr/lib/vop-plugins"

  # an extra path might have been passed in the options
  if @options.has_key? :plugin_path
    result << @options[:plugin_path]
  end

  result
end

#to_sObject



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

def to_s
  "Vop (#{@plugins.size} plugins)"
end